Ioctl request question.

Hi,

I am testing my porting KMDF driver on a XP system. It seems everything
ok so far. There is one wired thing. I am running a simple application
test program to open the driver and send couple Ioctl calls. In the WDM,
all DeviceIoControl calls return TRUE if no error. Now I keep receive
FALSE from DeviceIoControl calls. The GetLastError returns random
value. In the driver, everything is fine . It calls complete with
STATUS_SUCCESS. One of the IO control read some hardware data back. All
the data is correct. I wonder if Microsoft changed the application
interface or I still have some bug in our driver.

Thanks for help.

Bob Bao

KMDF will mark all incoming io as pending. If you are opening the handle as overlapped and in your previous wdm driver processed io asynchronously, you will be seeing this type of mismatch. I am betting GLE is not returning a random value, rather it is returning ERROR_IO_PENDING. Perhaps you are making a subsequent API call that is setting GLE to something else.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Bob Bao
Sent: Friday, October 24, 2008 2:03 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Ioctl request question.

Hi,

I am testing my porting KMDF driver on a XP system. It seems everything
ok so far. There is one wired thing. I am running a simple application
test program to open the driver and send couple Ioctl calls. In the WDM,
all DeviceIoControl calls return TRUE if no error. Now I keep receive
FALSE from DeviceIoControl calls. The GetLastError returns random
value. In the driver, everything is fine . It calls complete with
STATUS_SUCCESS. One of the IO control read some hardware data back. All
the data is correct. I wonder if Microsoft changed the application
interface or I still have some bug in our driver.

Thanks for help.

Bob Bao


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Thanks for reply. I am not sure what is the problem. I open the driver
with FILE_ATRIBUTE_NOMAL. In driver, I configure the IoCtrol queue with
WdfIoQueueDispatchParallel. But all the ioctl calls did not pending.
They are all completed in the driver with no error.( WdfRequestComplete
called). Could you please explain more detail about the problem.

Bob Bao

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Friday, October 24, 2008 4:12 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Ioctl request question.

KMDF will mark all incoming io as pending. If you are opening the
handle as overlapped and in your previous wdm driver processed io
asynchronously, you will be seeing this type of mismatch. I am betting
GLE is not returning a random value, rather it is returning
ERROR_IO_PENDING. Perhaps you are making a subsequent API call that is
setting GLE to something else.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Bob Bao
Sent: Friday, October 24, 2008 2:03 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Ioctl request question.

Hi,

I am testing my porting KMDF driver on a XP system. It seems everything
ok so far. There is one wired thing. I am running a simple application
test program to open the driver and send couple Ioctl calls. In the WDM,
all DeviceIoControl calls return TRUE if no error. Now I keep receive
FALSE from DeviceIoControl calls. The GetLastError returns random
value. In the driver, everything is fine . It calls complete with
STATUS_SUCCESS. One of the IO control read some hardware data back. All
the data is correct. I wonder if Microsoft changed the application
interface or I still have some bug in our driver.

Thanks for help.

Bob Bao


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

File attribute normal is not the same as file_flag_overlapped. If you are opening the handle as non overlapped, how KMDF pends io is a non issue with respect to your current problem. My guess is if you are seeing random GLE values, I think that you are completing the WDFREQUESTs with an uninitialized NTSTATUS value in your driver

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Bob Bao
Sent: Friday, October 24, 2008 2:33 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Ioctl request question.

Thanks for reply. I am not sure what is the problem. I open the driver
with FILE_ATRIBUTE_NOMAL. In driver, I configure the IoCtrol queue with
WdfIoQueueDispatchParallel. But all the ioctl calls did not pending.
They are all completed in the driver with no error.( WdfRequestComplete
called). Could you please explain more detail about the problem.

Bob Bao

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Friday, October 24, 2008 4:12 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Ioctl request question.

KMDF will mark all incoming io as pending. If you are opening the
handle as overlapped and in your previous wdm driver processed io
asynchronously, you will be seeing this type of mismatch. I am betting
GLE is not returning a random value, rather it is returning
ERROR_IO_PENDING. Perhaps you are making a subsequent API call that is
setting GLE to something else.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Bob Bao
Sent: Friday, October 24, 2008 2:03 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Ioctl request question.

Hi,

I am testing my porting KMDF driver on a XP system. It seems everything
ok so far. There is one wired thing. I am running a simple application
test program to open the driver and send couple Ioctl calls. In the WDM,
all DeviceIoControl calls return TRUE if no error. Now I keep receive
FALSE from DeviceIoControl calls. The GetLastError returns random
value. In the driver, everything is fine . It calls complete with
STATUS_SUCCESS. One of the IO control read some hardware data back. All
the data is correct. I wonder if Microsoft changed the application
interface or I still have some bug in our driver.

Thanks for help.

Bob Bao


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Bob Bao wrote:

Thanks for reply. I am not sure what is the problem. I open the driver
with FILE_ATRIBUTE_NOMAL. In driver, I configure the IoCtrol queue with
WdfIoQueueDispatchParallel. But all the ioctl calls did not pending.
They are all completed in the driver with no error.( WdfRequestComplete
called). Could you please explain more detail about the problem.

That last sentence is really what we should be asking YOU.

Why don’t you show us the code that (a) calls CreateFile, (b) calls
DeviceIoControl and GetLastError, and (c) handles and completes an ioctl
in the driver?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi, Tim.

I copy the code below:

(a) open the driver

HANDLE GetDeviceViaInterface(GUID* pGuid, DWORD instance)
{
SP_INTERFACE_DEVICE_DATA ifdata;
DWORD ReqLen;
PSP_INTERFACE_DEVICE_DETAIL_DATA ifDetail;
HANDLE rv;

// Get handle to relevant device information set
HDEVINFO info = SetupDiGetClassDevs(pGuid, NULL, NULL,
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);

if (info == INVALID_HANDLE_VALUE)
{
printf(“info error %d 0x%x\n”, info, GetLastError());
return NULL;
}

// Get interface data for the requested instance
ifdata.cbSize = sizeof(ifdata);

if (!SetupDiEnumDeviceInterfaces(info, NULL, pGuid, instance,
&ifdata))
{
SetupDiDestroyDeviceInfoList(info);
printf(" SetupDiEnumDeviceInterfaces error 0x%x \n",
GetLastError());
return NULL;
}

SetupDiGetDeviceInterfaceDetail(info, &ifdata, NULL, 0, &ReqLen,
NULL);
ifDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(ReqLen);

if (ifDetail==NULL)
{

printf(" ifDetail = NULL\n");
SetupDiDestroyDeviceInfoList(info);
return NULL;
}

// Get symbolic link name
ifDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

if (!SetupDiGetDeviceInterfaceDetail(info, &ifdata, ifDetail,
ReqLen, NULL, NULL))
{
SetupDiDestroyDeviceInfoList(info);
printf(“SetupDiGetDeviceInterfaceDetail error\n”);
free(ifDetail);
return NULL;
}

// Open handle
rv = CreateFile(ifDetail->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (rv == INVALID_HANDLE_VALUE)
{
printf(“create error %d 0x%x\n”, rv, GetLastError());
rv = NULL;
}

free (ifDetail);
SetupDiDestroyDeviceInfoList(info);

return rv;
}

(b) calls DeviceIoControl and GetLastError,
The subroutine accesses the Dpram on the hardware to
find the board ID.
The board ID it bring back is correct even the
DeviceIoControl return’s FALTE

static BOOL GetBoardId(char board_number, PUCHAR buffer)
{
BOOL bOK; // boolean
return code
ULONG datalength = 0;
XDS_DPRAM DrvBoard_ram; // pointer to xds driver message
structure

DrvBoard_ram.board_number = board_number;
DrvBoard_ram.offset = 0x1F00;
DrvBoard_ram.size = 4; // size of ID string to read
DrvBoard_ram.buffer = buffer;

// call low level driver
bOK = DeviceIoControl(
gl_hdriver,
(DWORD)READ_DPRAM,
&DrvBoard_ram,
sizeof(XDS_DPRAM),
NULL,
0,
&datalength,
NULL);

if (!bOK)
{
printf(" read dpram error 0x%x \n", GetLastError());
return 1;
}

// terminate string
buffer[DrvBoard_ram.size] = 0;

return 0;
}

(c) handles and completes an ioctl in the driver?
The return status initialize to STATUS_SUCCCESS at
declare area. The driver handle go through without error. It calls
completes with status = 0.

case READ_DPRAM:

DbgPrint (“get in read dpram\n”);
pRAM = (PXDS_DPRAM)inBuffer;
//pOutRam = (PXDS_DPRAM)outBuffer;
// Check buffer space.
if (InputBufferLength < sizeof(XDS_DPRAM))
{
Status = STATUS_BUFFER_TOO_SMALL;
DbgPrint(“error 1\n”);
break;
}

else if ((pRAM->buffer == 0) || (pRAM->size <=
0))
{
Status = STATUS_BUFFER_TOO_SMALL;
DbgPrint(“error 3\n”);
break;
}

else
{
// translate to low-level board number
from user-level board number
if (!GetBoardNumByUserNum(pExt,
pRAM->board_number, &board_number))
{
Status = STATUS_DATA_ERROR;
DbgPrint(“error 4\n”);
break;
}

if
(!pExt->BoardMessage[board_number].PciBoardActive)
{
Status = STATUS_DATA_ERROR;
DbgPrint(“error 5\n”);
break;
}

else if ((pRAM->offset + pRAM->size) >

pExt->BoardMessage[board_number].XdsBaseMemAddressSize)
{
Status = STATUS_DATA_ERROR;
DbgPrint(“error 6\n”);
break;
}

// If everything ok, read buffer.

memcpy((PVOID)pRAM->buffer,

(PVOID)((PUCHAR)(pExt->BoardMessage[board_number].XdsVirtualMemAddress
+
pRAM->offset)),
pRAM->size);

// return the number of bytes in
the output buffer.
//bytesReturned =
sizeof(XDS_DPRAM);

}
DbgPrint(“read dprm done\n”);
break;

/* - default case - */
default:
Status = STATUS_UNSUCCESSFUL;
break;
}

if(bytesReturned > 0)
WdfRequestCompleteWithInformation(Request, Status,
bytesReturned );
else
{
WdfRequestComplete( Request, Status);
DbgPrint(“ioctl comlete with status = 0x%X\n” ,status);
}

Thank you very much for help.

Bob Bao
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Friday, October 24, 2008 4:59 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Ioctl request question.

Bob Bao wrote:

Thanks for reply. I am not sure what is the problem. I open the
driver
with FILE_ATRIBUTE_NOMAL. In driver, I configure the IoCtrol queue
with
WdfIoQueueDispatchParallel. But all the ioctl calls did not pending.
They are all completed in the driver with no error.(
WdfRequestComplete
called). Could you please explain more detail about the problem.

That last sentence is really what we should be asking YOU.

Why don’t you show us the code that (a) calls CreateFile, (b) calls
DeviceIoControl and GetLastError, and (c) handles and completes an ioctl
in the driver?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Bob Bao wrote:

Hi, Tim.

I copy the code below:
(b) calls DeviceIoControl and GetLastError,
The subroutine accesses the Dpram on the hardware to
find the board ID.
The board ID it bring back is correct even the
DeviceIoControl return’s FALTE

static BOOL GetBoardId(char board_number, PUCHAR buffer)
{
BOOL bOK; // boolean
return code
ULONG datalength = 0;
XDS_DPRAM DrvBoard_ram; // pointer to xds driver message
structure

DrvBoard_ram.board_number = board_number;
DrvBoard_ram.offset = 0x1F00;
DrvBoard_ram.size = 4; // size of ID string to read
DrvBoard_ram.buffer = buffer;

// call low level driver
bOK = DeviceIoControl(
gl_hdriver,
(DWORD)READ_DPRAM,
&DrvBoard_ram,
sizeof(XDS_DPRAM),
NULL,
0,
&datalength,
NULL);

You should not have to cast READ_DPRAM to DWORD here. How is READ_DPRAM
defined? The buffering is important here. You are passing READ_DPRAM
as an input buffer, but your driver code is also WRITING to it.
Depending on the buffering, this might not work at all.

Also, there is another problem here. You are passing a POINTER in one
of the elements. By the time that gets to your driver, it will STILL be
a user-mode pointer, but your driver code does not convert it to kernel
mode. I’m frankly surprised this worked at all, especially in KMDF,
where the ioctl can easily run in a different context.

The RIGHT way to do this is to pass board_number, offset, and size as
the input buffer, but pass the “buffer” as the output buffer. That way,
your driver doesn’t have to worry about working directly with user-mode
pointers, or with validating that the buffer is large enough (which you
are not doing right now).

// If everything ok, read buffer.

memcpy((PVOID)pRAM->buffer,

(PVOID)((PUCHAR)(pExt->BoardMessage[board_number].XdsVirtualMemAddress
+
pRAM->offset)),
pRAM->size);

// return the number of bytes in
the output buffer.
//bytesReturned =
sizeof(XDS_DPRAM);

Again, you shouldn’t need all of those casts. Are you compiling as C or
C++?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Thanks, Tim.

I agree “passing a POINTER in one of the elements. By the time that
gets to your driver, it will STILL be a user-mode pointer, but your
driver code does not convert it to kernel mode.” We switch the user-mode
pointer to kernel mode pointer in the Linux driver. Since It works in
WDM, we never think about it(We use buffered IO). I will fix it. BTW,
how to switch the user-mode pointer to kernel mode pointer in KMDF?

But, I think this is not the case causing the IOCTL return FALSE. In my
test program, I call couple ioctl calls. Some of these just pass a
command to the board. In the driver they are completed without error.
But they all return FALSE.

I first test it on a XP os system. When I tried it on a 2000 os system,
they got same problem. But I saw three line error messages in kernel
when the ioctl is back.

RTL: RtlNTStatusToDosError(0x804b7256):No Valid Win32 Error Mapping
RTL: Edit ntos\rtl\generr.c to correct the problem
RTL: ERROR_MB_MID_NOT_FOUND is being returned

The GLE always return 0x013D.

Bob Bao

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, October 27, 2008 12:19 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Ioctl request question.

Bob Bao wrote:

Hi, Tim.

I copy the code below:
(b) calls DeviceIoControl and GetLastError,
The subroutine accesses the Dpram on the hardware to
find the board ID.
The board ID it bring back is correct even the
DeviceIoControl return’s FALTE

static BOOL GetBoardId(char board_number, PUCHAR buffer)
{
BOOL bOK; // boolean
return code
ULONG datalength = 0;
XDS_DPRAM DrvBoard_ram; // pointer to xds driver message
structure

DrvBoard_ram.board_number = board_number;
DrvBoard_ram.offset = 0x1F00;
DrvBoard_ram.size = 4; // size of ID string to read
DrvBoard_ram.buffer = buffer;

// call low level driver
bOK = DeviceIoControl(
gl_hdriver,
(DWORD)READ_DPRAM,
&DrvBoard_ram,
sizeof(XDS_DPRAM),
NULL,
0,
&datalength,
NULL);

You should not have to cast READ_DPRAM to DWORD here. How is READ_DPRAM
defined? The buffering is important here. You are passing READ_DPRAM
as an input buffer, but your driver code is also WRITING to it.
Depending on the buffering, this might not work at all.

Also, there is another problem here. You are passing a POINTER in one
of the elements. By the time that gets to your driver, it will STILL be
a user-mode pointer, but your driver code does not convert it to kernel
mode. I’m frankly surprised this worked at all, especially in KMDF,
where the ioctl can easily run in a different context.

The RIGHT way to do this is to pass board_number, offset, and size as
the input buffer, but pass the “buffer” as the output buffer. That way,
your driver doesn’t have to worry about working directly with user-mode
pointers, or with validating that the buffer is large enough (which you
are not doing right now).

// If everything ok, read buffer.

memcpy((PVOID)pRAM->buffer,

(PVOID)((PUCHAR)(pExt->BoardMessage[board_number].XdsVirtualMemAddress
+
pRAM->offset)),
pRAM->size);

// return the number of bytes in
the output buffer.
//bytesReturned =
sizeof(XDS_DPRAM);

Again, you shouldn’t need all of those casts. Are you compiling as C or
C++?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Bob Bao wrote:

I agree “passing a POINTER in one of the elements. By the time that
gets to your driver, it will STILL be a user-mode pointer, but your
driver code does not convert it to kernel mode.” We switch the user-mode
pointer to kernel mode pointer in the Linux driver. Since It works in
WDM, we never think about it(We use buffered IO). I will fix it. BTW,
how to switch the user-mode pointer to kernel mode pointer in KMDF?

As I said, the right way is to use a METHOD_OUT_DIRECT ioctl and let the
I/O manager do this for you. The input buffer will still be buffered.

To do this properly, you would need to handle this in a
EvtIoInCallerContext event callback. That’s the only place where you
are guaranteed that you are still executing in the context of the
calling process. You’d use WDM calls to probe and lock the buffer, and
save the kernel address away in a safe place (like a new context on the
WDFREQUEST) to use in the real handler.

I first test it on a XP os system. When I tried it on a 2000 os system,
they got same problem. But I saw three line error messages in kernel
when the ioctl is back.

RTL: RtlNTStatusToDosError(0x804b7256):No Valid Win32 Error Mapping
RTL: Edit ntos\rtl\generr.c to correct the problem
RTL: ERROR_MB_MID_NOT_FOUND is being returned

The GLE always return 0x013D.

Aha! That clearly implies that you are returning a pointer as your
status value, not 0. Are you SURE you are initializing Status in your code?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Woops. My mistake. I declare two status variables (Status and status) in
the DrvEvtIoDeviceControl. I initialize the status but use Status to
call complete.
I am so sorry.

Thank you very much Tim. I will fix the buffer problem too.

Bob Bao

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, October 27, 2008 1:48 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Ioctl request question.

Bob Bao wrote:

I agree “passing a POINTER in one of the elements. By the time that
gets to your driver, it will STILL be a user-mode pointer, but your
driver code does not convert it to kernel mode.” We switch the
user-mode
pointer to kernel mode pointer in the Linux driver. Since It works in
WDM, we never think about it(We use buffered IO). I will fix it. BTW,
how to switch the user-mode pointer to kernel mode pointer in KMDF?

As I said, the right way is to use a METHOD_OUT_DIRECT ioctl and let the
I/O manager do this for you. The input buffer will still be buffered.

To do this properly, you would need to handle this in a
EvtIoInCallerContext event callback. That’s the only place where you
are guaranteed that you are still executing in the context of the
calling process. You’d use WDM calls to probe and lock the buffer, and
save the kernel address away in a safe place (like a new context on the
WDFREQUEST) to use in the real handler.

I first test it on a XP os system. When I tried it on a 2000 os
system,
they got same problem. But I saw three line error messages in kernel
when the ioctl is back.

RTL: RtlNTStatusToDosError(0x804b7256):No Valid Win32 Error Mapping
RTL: Edit ntos\rtl\generr.c to correct the problem
RTL: ERROR_MB_MID_NOT_FOUND is being returned

The GLE always return 0x013D.

Aha! That clearly implies that you are returning a pointer as your
status value, not 0. Are you SURE you are initializing Status in your
code?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Bob Bao wrote:

Woops. My mistake. I declare two status variables (Status and status) in
the DrvEvtIoDeviceControl. I initialize the status but use Status to
call complete.
I am so sorry.

Well, I can’t say that I have never made that same mistake. I was just
fortunate enough to catch it before I went world-wide with it…


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

For KMDF to capture the um pointer and convert it into a KM pointer, you need to do 2 things

  1. Register an EvtIoInCallerContext callback via WdfDeviceInitSetIoInCallerContextCallback
  2. in the callback, call WdfRequestProbeAndLockUserBufferForWrite/Read and it will map it to KM. you can then get the KM pointer from the returned WDFMEMORY by calling WdfMemoryGetBuffer

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Bob Bao
Sent: Monday, October 27, 2008 11:24 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Ioctl request question.

Thanks, Tim.

I agree “passing a POINTER in one of the elements. By the time that
gets to your driver, it will STILL be a user-mode pointer, but your
driver code does not convert it to kernel mode.” We switch the user-mode
pointer to kernel mode pointer in the Linux driver. Since It works in
WDM, we never think about it(We use buffered IO). I will fix it. BTW,
how to switch the user-mode pointer to kernel mode pointer in KMDF?

But, I think this is not the case causing the IOCTL return FALSE. In my
test program, I call couple ioctl calls. Some of these just pass a
command to the board. In the driver they are completed without error.
But they all return FALSE.

I first test it on a XP os system. When I tried it on a 2000 os system,
they got same problem. But I saw three line error messages in kernel
when the ioctl is back.

RTL: RtlNTStatusToDosError(0x804b7256):No Valid Win32 Error Mapping
RTL: Edit ntos\rtl\generr.c to correct the problem
RTL: ERROR_MB_MID_NOT_FOUND is being returned

The GLE always return 0x013D.

Bob Bao

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, October 27, 2008 12:19 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Ioctl request question.

Bob Bao wrote:

Hi, Tim.

I copy the code below:
(b) calls DeviceIoControl and GetLastError,
The subroutine accesses the Dpram on the hardware to
find the board ID.
The board ID it bring back is correct even the
DeviceIoControl return’s FALTE

static BOOL GetBoardId(char board_number, PUCHAR buffer)
{
BOOL bOK; // boolean
return code
ULONG datalength = 0;
XDS_DPRAM DrvBoard_ram; // pointer to xds driver message
structure

DrvBoard_ram.board_number = board_number;
DrvBoard_ram.offset = 0x1F00;
DrvBoard_ram.size = 4; // size of ID string to read
DrvBoard_ram.buffer = buffer;

// call low level driver
bOK = DeviceIoControl(
gl_hdriver,
(DWORD)READ_DPRAM,
&DrvBoard_ram,
sizeof(XDS_DPRAM),
NULL,
0,
&datalength,
NULL);

You should not have to cast READ_DPRAM to DWORD here. How is READ_DPRAM
defined? The buffering is important here. You are passing READ_DPRAM
as an input buffer, but your driver code is also WRITING to it.
Depending on the buffering, this might not work at all.

Also, there is another problem here. You are passing a POINTER in one
of the elements. By the time that gets to your driver, it will STILL be
a user-mode pointer, but your driver code does not convert it to kernel
mode. I’m frankly surprised this worked at all, especially in KMDF,
where the ioctl can easily run in a different context.

The RIGHT way to do this is to pass board_number, offset, and size as
the input buffer, but pass the “buffer” as the output buffer. That way,
your driver doesn’t have to worry about working directly with user-mode
pointers, or with validating that the buffer is large enough (which you
are not doing right now).

// If everything ok, read buffer.

memcpy((PVOID)pRAM->buffer,

(PVOID)((PUCHAR)(pExt->BoardMessage[board_number].XdsVirtualMemAddress
+
pRAM->offset)),
pRAM->size);

// return the number of bytes in
the output buffer.
//bytesReturned =
sizeof(XDS_DPRAM);

Again, you shouldn’t need all of those casts. Are you compiling as C or
C++?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer