Why actual data is not coming in driver

Hi All, I am facing problem in passing data from user mode application to driver using ctl code.

I have define the the ctl code as follows

#define IOCTL_READ_WRITE_DEVICE_DATA \ CTL_CODE(0x8000, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS )

handling that IOCTl as follows

NTSTATUS SdHostDispatchIoctl(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{ PIO_STACK_LOCATION pIrpStack; NTSTATUS ntStatus= STATUS_SUCCESS; PSD_HOST_FDO_DATA pSdHostFdoData; ULONG ulInformation; PREAD_WRITE_DEVICE_DATA_INPARAMS pReadWriteDeviceDataInputBuffer; ULONG ulInputData; PVOID pOutputBuffer;
PAGED_CODE();

pSdHostFdoData = (PSD_HOST_FDO_DATA) DeviceObject->DeviceExtension; ulInformation = 0;
pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_READ_WRITE_DEVICE_DATA: pReadWriteDeviceDataInputBuffer = (PREAD_WRITE_DEVICE_DATA_INPARAMS)pIrp->AssociatedIrp.SystemBuffer; pOutputBuffer = (PVOID)pIrp->AssociatedIrp.SystemBuffer;
if( pOutputBuffer== NULL ||pReadWriteDeviceDataInputBuffer == NULL|| pIrpStack->Parameters.DeviceIoControl.InputBufferLength != sizeof(READ_WRITE_DEVICE_DATA_INPARAMS) ) { ntStatus = STATUS_INVALID_USER_BUFFER; goto EXIT; }
if(pIrpStack->Parameters.DeviceIoControl.OutputBufferLength != (pReadWriteDeviceDataInputBuffer->ulItemSize*pReadWriteDeviceDataInputBuffer->ulItemCount)) { ntStatus = STATUS_BUFFER_TOO_SMALL; goto EXIT; }
RtlZeroMemory(&ulInputData,sizeof(ULONG)); RtlCopyMemory(&ulInputData ,pOutputBuffer,pIrpStack->Parameters.DeviceIoControl.OutputBufferLength); DbgPrint(“Data To Be Written To Device :0x%08X\n”,ulInputData);
break; default:
// ASSERTMSG(FALSE, “Invalid IOCTL request\n”);
ntStatus = STATUS_INVALID_DEVICE_REQUEST; }

EXIT:
pIrp->IoStatus.Status = ntStatus; pIrp->IoStatus.Information = ulInformation;
IoCompleteRequest (pIrp, IO_NO_INCREMENT);

return ntStatus;}
Following is the user mode app code for passing the data through ctl code
BOOL WriteRegister8(HANDLE hdr, DWORD dwBarIndex, DWORD dwOffset, PVOID pBuffer, DWORD dwItemSize, DWORD dwItemCount){ BOOL bReturn = FALSE; DWORD dwError = 0; DWORD dwBytesWritten = 0; OVERLAPPED oOverlap ; PREAD_WRITE_DEVICE_DATA_INPARAMS pWriteInParams = NULL;
DWORD dwBytesToWrite = dwItemSize * dwItemCount; DWORD dwTotalParamBytes = sizeof(WRITE_DEVICE_DATA_INPARAMS) + dwBytesToWrite; ::memset(&oOverlap,0,sizeof(OVERLAPPED)); oOverlap.hEvent = hOverlappedIo;
pWriteInParams = (PREAD_WRITE_DEVICE_DATA_INPARAMS)new char[sizeof(READ_WRITE_DEVICE_DATA_INPARAMS)];
if(!pWriteInParams) { return FALSE; } ::memset(pWriteInParams,0,sizeof(READ_WRITE_DEVICE_DATA_INPARAMS));
pWriteInParams->ulItemSize = dwItemSize; pWriteInParams->ulItemCount = dwItemCount; pWriteInParams->ucMemorySpace = 1; pWriteInParams->ucReadOrWrite = 1; pWriteInParams->ulPhysicalAddress = (ULONG)(dwBarIndex + dwOffset); DeviceIoControl( hdr, IOCTL_READ_WRITE_DEVICE_DATA, pWriteInParams, sizeof(READ_WRITE_DEVICE_DATA_INPARAMS), pBuffer, dwBytesToWrite, &dwBytesWritten, (LPOVERLAPPED)&oOverlap );
if ((dwError = GetLastError()) != ERROR_IO_PENDING) { DWORD dNumberOfBytesTransferred = 0; if(GetOverlappedResult(hdr,(LPOVERLAPPED)&oOverlap,&dNumberOfBytesTransferred,FALSE)) { dNumberOfBytesTransferred = dNumberOfBytesTransferred; bReturn = TRUE; } }
if ((dwError = GetLastError()) == ERROR_IO_PENDING) { bReturn = FALSE; } } catch(…) { if(pWriteInParams) { delete pWriteInParams; pWriteInParams = NULL; } return FALSE; }
if(pWriteInParams) { delete pWriteInParams; pWriteInParams = NULL; }
return bReturn;}

In any case i am getting default value that is 0x01 regardless of any value that i am passing through pBuffer 5th parameter of DeviceIoControl .

whats wrong i am doing because of which i am not getting actual value that i am passing from user mode app.

Any kind of help will be very helpgful.

Regards


Get the new Windows Live Messenger!
http://get.live.com/messenger/overview

nayan kumar wrote:

Hi All,
I am facing problem in passing data from user mode
application to driver using ctl code.

I have define the the ctl code as follows

#define IOCTL_READ_WRITE_DEVICE_DATA \
CTL_CODE(0x8000, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS )

handling that IOCTl as follows

NTSTATUS SdHostDispatchIoctl(IN PDEVICE_OBJECT DeviceObject,IN
PIRP pIrp)
{
PIO_STACK_LOCATION pIrpStack;
NTSTATUS ntStatus= STATUS_SUCCESS;
PSD_HOST_FDO_DATA pSdHostFdoData;
ULONG ulInformation;
PREAD_WRITE_DEVICE_DATA_INPARAMS pReadWriteDeviceDataInputBuffer;
ULONG ulInputData;
PVOID pOutputBuffer;
PAGED_CODE();

pSdHostFdoData = (PSD_HOST_FDO_DATA) DeviceObject->DeviceExtension;
ulInformation = 0;
pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_READ_WRITE_DEVICE_DATA:
pReadWriteDeviceDataInputBuffer =
(PREAD_WRITE_DEVICE_DATA_INPARAMS)pIrp->AssociatedIrp.SystemBuffer;
pOutputBuffer = (PVOID)pIrp->AssociatedIrp.SystemBuffer;
if( pOutputBuffer== NULL ||pReadWriteDeviceDataInputBuffer == NULL||
pIrpStack->Parameters.DeviceIoControl.InputBufferLength !=
sizeof(READ_WRITE_DEVICE_DATA_INPARAMS)
)
{

ntStatus = STATUS_INVALID_USER_BUFFER;
goto EXIT;
}
if(pIrpStack->Parameters.DeviceIoControl.OutputBufferLength !=
(pReadWriteDeviceDataInputBuffer->ulItemSize*pReadWriteDeviceDataInputBuffer->ulItemCount))
{
ntStatus = STATUS_BUFFER_TOO_SMALL;
goto EXIT;
}
RtlZeroMemory(&ulInputData,sizeof(ULONG));
RtlCopyMemory(&ulInputData
,pOutputBuffer,pIrpStack->Parameters.DeviceIoControl.OutputBufferLength);
DbgPrint(“Data To Be Written To Device :0x%08X\n”,ulInputData);
break;
default:
// ASSERTMSG(FALSE, “Invalid IOCTL request\n”);
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
}

EXIT:
pIrp->IoStatus.Status = ntStatus;
pIrp->IoStatus.Information = ulInformation;
IoCompleteRequest (pIrp, IO_NO_INCREMENT);

return ntStatus;
}
Following is the user mode app code for passing the data through ctl code
BOOL WriteRegister8(HANDLE hdr, DWORD dwBarIndex, DWORD dwOffset, PVOID
pBuffer, DWORD dwItemSize, DWORD dwItemCount)
{
BOOL bReturn = FALSE;
DWORD dwError = 0;
DWORD dwBytesWritten = 0;
OVERLAPPED oOverlap ;

PREAD_WRITE_DEVICE_DATA_INPARAMS pWriteInParams = NULL;

DWORD dwBytesToWrite = dwItemSize * dwItemCount;
DWORD dwTotalParamBytes = sizeof(WRITE_DEVICE_DATA_INPARAMS) +
dwBytesToWrite;
::memset(&oOverlap,0,sizeof(OVERLAPPED));
oOverlap.hEvent = hOverlappedIo;

pWriteInParams = (PREAD_WRITE_DEVICE_DATA_INPARAMS)new
char[sizeof(READ_WRITE_DEVICE_DATA_INPARAMS)];
if(!pWriteInParams)
{
return FALSE;
}

::memset(pWriteInParams,0,sizeof(READ_WRITE_DEVICE_DATA_INPARAMS));
pWriteInParams->ulItemSize = dwItemSize;
pWriteInParams->ulItemCount = dwItemCount;
pWriteInParams->ucMemorySpace = 1;
pWriteInParams->ucReadOrWrite = 1;
pWriteInParams->ulPhysicalAddress = (ULONG)(dwBarIndex + dwOffset);

DeviceIoControl(
hdr,
IOCTL_READ_WRITE_DEVICE_DATA,
pWriteInParams,
sizeof(READ_WRITE_DEVICE_DATA_INPARAMS),
pBuffer,
dwBytesToWrite,
&dwBytesWritten,
(LPOVERLAPPED)&oOverlap
);
if ((dwError = GetLastError()) != ERROR_IO_PENDING)
{
DWORD dNumberOfBytesTransferred = 0;

if(GetOverlappedResult(hdr,(LPOVERLAPPED)&oOverlap,&dNumberOfBytesTransferred,FALSE))
{
dNumberOfBytesTransferred = dNumberOfBytesTransferred;
bReturn = TRUE;

}

}
if ((dwError = GetLastError()) == ERROR_IO_PENDING)
{
bReturn = FALSE;
}
}
catch(…)
{
if(pWriteInParams)
{
delete pWriteInParams;
pWriteInParams = NULL;
}
return FALSE;
}
if(pWriteInParams)
{
delete pWriteInParams;
pWriteInParams = NULL;
}
return bReturn;
}

In any case i am getting default value that is 0x01 regardless of any
value that i am passing through pBuffer 5th parameter of DeviceIoControl .

whats wrong i am doing because of which i am not getting actual value
that i am passing from user mode app.

Any kind of help will be very helpgful.

Regards


Get the new Windows Live Messenger! Try it!
http:

Nayan:

I’m confused. It looks like you’re crossing the input and output
buffers somewhere, if I understand the situation correctly. pBuffer is
output, so what you pass wouldn’t matter. You’re also copying from the
output buffer in your device io control routine, which doesn’t make a
lot of sense semantically.

RtlCopyMemory(&ulInputData
&pOutputBuffer,pIrpStack->Parameters.DeviceIoControl.OutputBufferLength);

I’m not really clear on what it is you’re trying to do. I don’t know
what READ_WRITE_DEVICE_DATA_INPARAM looks like, but my guess would be
that you are getting the first member of it, which happens to be ‘1.’

mm</http:>

Martin O’Brien wrote:

I’m confused. It looks like you’re crossing the input and output
buffers somewhere, if I understand the situation correctly. pBuffer
is output, so what you pass wouldn’t matter. You’re also copying from
the output buffer in your device io control routine, which doesn’t
make a lot of sense semantically.

It’s a METHOD_BUFFERED ioctl, so SystemBuffer *IS* both the input and
the output buffer.

RtlCopyMemory(&ulInputData
&pOutputBuffer,pIrpStack->Parameters.DeviceIoControl.OutputBufferLength);

I’m not really clear on what it is you’re trying to do. I don’t know
what READ_WRITE_DEVICE_DATA_INPARAM looks like, but my guess would be
that you are getting the first member of it, which happens to be ‘1.’

Right.

One very serious problem here is that ulInputData is only 4 bytes long.
If the application passes in more than 4 bytes, he has a very excellent
mechanism for producing a blue screen.


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

nayan kumar wrote:

I am facing problem in passing data from user mode
application to driver using ctl code.

I have define the the ctl code as follows

#define IOCTL_READ_WRITE_DEVICE_DATA \
CTL_CODE(0x8000, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS )

::memset(pWriteInParams,0,sizeof(READ_WRITE_DEVICE_DATA_INPARAMS));
pWriteInParams->ulItemSize = dwItemSize;
pWriteInParams->ulItemCount = dwItemCount;
pWriteInParams->ucMemorySpace = 1;
pWriteInParams->ucReadOrWrite = 1;
pWriteInParams->ulPhysicalAddress = (ULONG)(dwBarIndex + dwOffset);

DeviceIoControl(
hdr,
IOCTL_READ_WRITE_DEVICE_DATA,
pWriteInParams,
sizeof(READ_WRITE_DEVICE_DATA_INPARAMS),
pBuffer,
dwBytesToWrite,
&dwBytesWritten,
(LPOVERLAPPED)&oOverlap
);

In any case i am getting default value that is 0x01 regardless of any
value that i am passing through pBuffer 5th parameter of DeviceIoControl .

Of course you are. This is a METHOD_BUFFERED ioctl, so the 5th
parameter of DeviceIoControl is an OUTPUT buffer. What you are getting
in SystemBuffer is the READ_WRITE_DEVICE_DATA_INPARAMS structure, from
the 3rd parameter. Whatever you copy into SystemBuffer in the ioctl
will be copied back to the buffer in the 5th parameter.

If you want to have both buffers in the DeviceIoControl call be sent to
the driver, which is a perfectly valid thing to want, then you need to
change the ioctl code to METHOD_IN_DIRECT. The second buffer will then
be handed to you in Irp->MdlAddress.

Because of this, it is a bad idea to have read and write operations
share a single ioctl. You probably want read operations to be a
METHOD_OUT_DIRECT ioctl, and write operations to be a METHOD_IN_DIRECT
ioctl.


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

Tim Roberts wrote:

Martin O’Brien wrote:
> I’m confused. It looks like you’re crossing the input and output
> buffers somewhere, if I understand the situation correctly. pBuffer
> is output, so what you pass wouldn’t matter. You’re also copying from
> the output buffer in your device io control routine, which doesn’t
> make a lot of sense semantically.

It’s a METHOD_BUFFERED ioctl, so SystemBuffer *IS* both the input and
the output buffer.

> RtlCopyMemory(&ulInputData
> &pOutputBuffer,pIrpStack->Parameters.DeviceIoControl.OutputBufferLength);
>
> I’m not really clear on what it is you’re trying to do. I don’t know
> what READ_WRITE_DEVICE_DATA_INPARAM looks like, but my guess would be
> that you are getting the first member of it, which happens to be ‘1.’

Right.

One very serious problem here is that ulInputData is only 4 bytes long.
If the application passes in more than 4 bytes, he has a very excellent
mechanism for producing a blue screen.

Agreed. The only reason I mentioned that made no sense semantically
(copying from the output buffer) was because he was talking about
passing things via the 5th (output) parameter of DeviceIoControl in user
mode, and thought he might have the whole thing backwards, that it
happens to be the same memory in the kernel notwithstanding.

mm