GetLastError after calling DeviceIoControl

Folks,

I have implemented a IOCTL interface in my driver.

All my IOCTLs are METHOD_BUFFERED.

My user application need some info from my driver.
Inside my driver if the buffer length is insufficient, then i return with
error status STATUS_BUFFER_TOO_SMALL which eventually translates to Win32
error code
ERROR_INSUFFICIENT_BUFFER for my user mode app (I do a GetLastError() just
after DeviceIoControl).
After this my user app frees that buffer and increase the buffer size and
again do a DeviceIoControl.
My driver sees that buffer length is enough for I/O to perform.
This time I get SUCCESS return status (.i.e a non zero value which is
success as per docs) from DeviceIoControl but GetLastError() still returns
ERROR_INSUFFICIENT_BUFFER (although I have returned STATUS_SUCCESS from
driver).
Can any body point what I am doing wrong?

Those who are interested in code snippet can see below:-
I am getting the problem for UAL_IOC_LIST ioctl.

*Driver code:–*

NTSTATUS
My_Drv_Ioctl(
IN DEVICE_OBJECT *p_dev_obj,
IN IRP *p_irp )
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION p_io_stack;
ULONG controlcode, n_iocs, n_bytes;
ca_ioc_info_t *p_ca_ioc_info;
child_device_info_t *p_child_dev;

/* Get the stack location. */
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
controlcode = p_io_stack->Parameters.DeviceIoControl.IoControlCode;
p_irp->IoStatus.Information = 0;

switch (controlcode) {
case UAL_IOC_DEVICE_CREATE:
p_child_dev = p_irp->AssociatedIrp.SystemBuffer;

if (sizeof(child_device_info_t) >=
(p_io_stack->Parameters.DeviceIoControl.InputBufferLength)) {
status = STATUS_BUFFER_TOO_SMALL;
} else {
status = create_child_ioc_device(p_child_dev);
}
break;

case UAL_IOC_LIST:
p_ca_ioc_info = p_irp->AssociatedIrp.SystemBuffer;
cl_mutex_acquire(&iou_globals.list_mutex);
n_iocs = cl_qlist_count(&iou_globals.ca_ioc_map_list);

if (n_iocs*sizeof(ca_ioc_info_t) <=
p_io_stack->Parameters.DeviceIoControl.OutputBufferLength) {
n_bytes = build_ca_ioc_list(p_ca_ioc_info);
p_irp->IoStatus.Information = n_bytes;
status = STATUS_SUCCESS;
} else {
status = STATUS_BUFFER_TOO_SMALL;
}

cl_mutex_release(&iou_globals.list_mutex);

break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}

p_irp->IoStatus.Status = status;
IoCompleteRequest(p_irp, IO_NO_INCREMENT);
return status;
}

*Application Snippet:–*

Some_function (arguments) {
…some code
pBuf = NULL;
ioctlcode = UAL_IOC_LIST;
do {
if (pBuf) {
printf(“Before calling free in send_device_ioctl, value
of pBuf %I64X\n”, pBuf);
free(pBuf);
dwMemSize *= 2;
pBuf = NULL;
}

pBuf = malloc(dwMemSize);

if (!pBuf) {
printf(“Insufficient memory\n”);
dwRet = ERROR_NOT_ENOUGH_MEMORY;
break;
}
printf(“Before from DeviceIoControl\n”);
bRet = DeviceIoControl(hDevice, ioctlcode, NULL, 0, pBuf,
dwMemSize, &dwBytesRet, NULL);
dwRet = GetLastError(); *// I am always getting
ERROR_INSUFFICIENT_BUFFER here*

if (bRet) {
printf(“Returned from DeviceIoControl and error code is
%d and bool value is %d\n”, dwRet, bRet);
dwRet = 0;
break;
}

printf(“Returned from DeviceIoControl and error code is %d
and bool value is %d\n”, dwRet, bRet);

}while(dwRet == ERROR_INSUFFICIENT_BUFFER)
…some code
}

Any help/pointers will be appreciated.

Regards
Deepak

When DeviceIoControl returns TRUE (non-zero), value of GetLastError()
is undefined. It is not expected to be 0 on success.
Maybe it’s left unchanged from a previous call.

–pa

Deepak Gupta wrote:

Folks,

I have implemented a IOCTL interface in my driver.

All my IOCTLs are METHOD_BUFFERED.

My user application need some info from my driver.
Inside my driver if the buffer length is insufficient, then i return
with error status STATUS_BUFFER_TOO_SMALL which eventually translates to
Win32 error code
ERROR_INSUFFICIENT_BUFFER for my user mode app (I do a GetLastError()
just after DeviceIoControl).
After this my user app frees that buffer and increase the buffer size
and again do a DeviceIoControl.
My driver sees that buffer length is enough for I/O to perform.
This time I get SUCCESS return status (.i.e a non zero value which is
success as per docs) from DeviceIoControl but GetLastError() still
returns ERROR_INSUFFICIENT_BUFFER (although I have returned
STATUS_SUCCESS from driver).
Can any body point what I am doing wrong?

Those who are interested in code snippet can see below:-
I am getting the problem for UAL_IOC_LIST ioctl.

*Driver code:–*

NTSTATUS
My_Drv_Ioctl(
IN DEVICE_OBJECT *p_dev_obj,
IN IRP *p_irp )
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION p_io_stack;
ULONG controlcode, n_iocs, n_bytes;
ca_ioc_info_t *p_ca_ioc_info;
child_device_info_t *p_child_dev;

/* Get the stack location. */
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
controlcode = p_io_stack->Parameters.DeviceIoControl.IoControlCode;
p_irp->IoStatus.Information = 0;

switch (controlcode) {
case UAL_IOC_DEVICE_CREATE:
p_child_dev = p_irp->AssociatedIrp.SystemBuffer;

if (sizeof(child_device_info_t) >=
(p_io_stack->Parameters.DeviceIoControl.InputBufferLength)) {
status = STATUS_BUFFER_TOO_SMALL;
} else {
status = create_child_ioc_device(p_child_dev);
}
break;

case UAL_IOC_LIST:
p_ca_ioc_info = p_irp->AssociatedIrp.SystemBuffer;
cl_mutex_acquire(&iou_globals.list_mutex);
n_iocs = cl_qlist_count(&iou_globals.ca_ioc_map_list);

if (n_iocs*sizeof(ca_ioc_info_t) <=
p_io_stack->Parameters.DeviceIoControl.OutputBufferLength) {
n_bytes = build_ca_ioc_list(p_ca_ioc_info);
p_irp->IoStatus.Information = n_bytes;
status = STATUS_SUCCESS;
} else {
status = STATUS_BUFFER_TOO_SMALL;
}

cl_mutex_release(&iou_globals.list_mutex);

break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}

p_irp->IoStatus.Status = status;
IoCompleteRequest(p_irp, IO_NO_INCREMENT);
return status;
}

*Application Snippet:–*

Some_function (arguments) {
…some code
pBuf = NULL;
ioctlcode = UAL_IOC_LIST;
do {
if (pBuf) {
printf(“Before calling free in send_device_ioctl,
value of pBuf %I64X\n”, pBuf);
free(pBuf);
dwMemSize *= 2;
pBuf = NULL;
}

pBuf = malloc(dwMemSize);

if (!pBuf) {
printf(“Insufficient memory\n”);
dwRet = ERROR_NOT_ENOUGH_MEMORY;
break;
}
printf(“Before from DeviceIoControl\n”);
bRet = DeviceIoControl(hDevice, ioctlcode, NULL, 0,
pBuf, dwMemSize, &dwBytesRet, NULL);
dwRet = GetLastError(); *// I am always getting
ERROR_INSUFFICIENT_BUFFER here*

if (bRet) {
printf(“Returned from DeviceIoControl and error code
is %d and bool value is %d\n”, dwRet, bRet);
dwRet = 0;
break;
}

printf(“Returned from DeviceIoControl and error code is
%d and bool value is %d\n”, dwRet, bRet);

}while(dwRet == ERROR_INSUFFICIENT_BUFFER)
…some code
}

Any help/pointers will be appreciated.

Regards
Deepak

You should only call GetLastError() when there has been an error.

When DeviceIoControl() succeeds it does not update the internal last
error variable, because this is not an error.

So what gets returned by the 2nd call to GetLastError() is the last
error value placed in the internal variable i.e. the value placed
there by your first failing call to DeviceIoControl().

At 09:24 26/02/2009, Deepak Gupta wrote:

Folks,

I have implemented a IOCTL interface in my driver.

All my IOCTLs are METHOD_BUFFERED.

My user application need some info from my driver.
Inside my driver if the buffer length is insufficient, then i return
with error status STATUS_BUFFER_TOO_SMALL which eventually
translates to Win32 error code
ERROR_INSUFFICIENT_BUFFER for my user mode app (I do a
GetLastError() just after DeviceIoControl).
After this my user app frees that buffer and increase the buffer
size and again do a DeviceIoControl.
My driver sees that buffer length is enough for I/O to perform.
This time I get SUCCESS return status (.i.e a non zero value which
is success as per docs) from DeviceIoControl but GetLastError()
still returns ERROR_INSUFFICIENT_BUFFER (although I have returned
STATUS_SUCCESS from driver).
Can any body point what I am doing wrong?

Those who are interested in code snippet can see below:-
I am getting the problem for UAL_IOC_LIST ioctl.

Driver code:–

NTSTATUS
My_Drv_Ioctl(
IN DEVICE_OBJECT *p_dev_obj,
IN IRP *p_irp )
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION p_io_stack;
ULONG controlcode, n_iocs, n_bytes;
ca_ioc_info_t *p_ca_ioc_info;
child_device_info_t *p_child_dev;

/* Get the stack location. */
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
controlcode = p_io_stack->Parameters.DeviceIoControl.IoControlCode;
p_irp->IoStatus.Information = 0;

switch (controlcode) {
case UAL_IOC_DEVICE_CREATE:
p_child_dev = p_irp->AssociatedIrp.SystemBuffer;

if (sizeof(child_device_info_t) >=
(p_io_stack->Parameters.DeviceIoControl.InputBufferLength)) {
status = STATUS_BUFFER_TOO_SMALL;
} else {
status = create_child_ioc_device(p_child_dev);
}
break;

case UAL_IOC_LIST:
p_ca_ioc_info = p_irp->AssociatedIrp.SystemBuffer;
cl_mutex_acquire(&iou_globals.list_mutex);
n_iocs = cl_qlist_count(&iou_globals.ca_ioc_map_list);

if (n_iocs*sizeof(ca_ioc_info_t) <=
p_io_stack->Parameters.DeviceIoControl.OutputBufferLength) {
n_bytes = build_ca_ioc_list(p_ca_ioc_info);
p_irp->IoStatus.Information = n_bytes;
status = STATUS_SUCCESS;
} else {
status = STATUS_BUFFER_TOO_SMALL;
}

cl_mutex_release(&iou_globals.list_mutex);

break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}

p_irp->IoStatus.Status = status;
IoCompleteRequest(p_irp, IO_NO_INCREMENT);
return status;
}

Application Snippet:–

Some_function (arguments) {
…some code
pBuf = NULL;
ioctlcode = UAL_IOC_LIST;
do {
if (pBuf) {
printf(“Before calling free in
send_device_ioctl, value of pBuf %I64X\n”, pBuf);
free(pBuf);
dwMemSize *= 2;
pBuf = NULL;
}

pBuf = malloc(dwMemSize);

if (!pBuf) {
printf(“Insufficient memory\n”);
dwRet = ERROR_NOT_ENOUGH_MEMORY;
break;
}
printf(“Before from DeviceIoControl\n”);
bRet = DeviceIoControl(hDevice, ioctlcode, NULL, 0,
pBuf, dwMemSize, &dwBytesRet, NULL);
dwRet = GetLastError(); // I am always getting
ERROR_INSUFFICIENT_BUFFER here

if (bRet) {
printf(“Returned from DeviceIoControl and error
code is %d and bool value is %d\n”, dwRet, bRet);
dwRet = 0;
break;
}

printf(“Returned from DeviceIoControl and error
code is %d and bool value is %d\n”, dwRet, bRet);

}while(dwRet == ERROR_INSUFFICIENT_BUFFER)
…some code
}

Any help/pointers will be appreciated.

Regards
Deepak
— 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

Mark, Pavel.

Thanks a lot for your inputs. I was also expecting same thing.
So Last Error only gets updated only if some error happens in any call and
other wise not.

Regards
Deepak

On Thu, Feb 26, 2009 at 3:28 PM, Mark S. Edwards wrote:

> You should only call GetLastError() when there has been an error.
>
> When DeviceIoControl() succeeds it does not update the internal last error
> variable, because this is not an error.
>
> So what gets returned by the 2nd call to GetLastError() is the last error
> value placed in the internal variable i.e. the value placed there by your
> first failing call to DeviceIoControl().
>
>
>
>
> At 09:24 26/02/2009, Deepak Gupta wrote:
>
> Folks,
>
> I have implemented a IOCTL interface in my driver.
>
> All my IOCTLs are METHOD_BUFFERED.
>
> My user application need some info from my driver.
> Inside my driver if the buffer length is insufficient, then i return with
> error status STATUS_BUFFER_TOO_SMALL which eventually translates to Win32
> error code
> ERROR_INSUFFICIENT_BUFFER for my user mode app (I do a GetLastError() just
> after DeviceIoControl).
> After this my user app frees that buffer and increase the buffer size and
> again do a DeviceIoControl.
> My driver sees that buffer length is enough for I/O to perform.
> This time I get SUCCESS return status (.i.e a non zero value which is
> success as per docs) from DeviceIoControl but GetLastError() still returns
> ERROR_INSUFFICIENT_BUFFER (although I have returned STATUS_SUCCESS from
> driver).
> Can any body point what I am doing wrong?
>
> Those who are interested in code snippet can see below:-
> I am getting the problem for UAL_IOC_LIST ioctl.
>
> Driver code:–
>
> NTSTATUS
> My_Drv_Ioctl(
> IN DEVICE_OBJECT *p_dev_obj,
> IN IRP *p_irp )
> {
> NTSTATUS status = STATUS_SUCCESS;
> PIO_STACK_LOCATION p_io_stack;
> ULONG controlcode, n_iocs, n_bytes;
> ca_ioc_info_t *p_ca_ioc_info;
> child_device_info_t p_child_dev;
>
>
> /
Get the stack location. /
> p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
> controlcode = p_io_stack->Parameters.DeviceIoControl.IoControlCode;
> p_irp->IoStatus.Information = 0;
>
> switch (controlcode) {
> case UAL_IOC_DEVICE_CREATE:
> p_child_dev = p_irp->AssociatedIrp.SystemBuffer;
>
> if (sizeof(child_device_info_t) >=
> (p_io_stack->Parameters.DeviceIoControl.InputBufferLength)) {
> status = STATUS_BUFFER_TOO_SMALL;
> } else {
> status = create_child_ioc_device(p_child_dev);
> }
> break;
>
> case UAL_IOC_LIST:
> p_ca_ioc_info = p_irp->AssociatedIrp.SystemBuffer;
> cl_mutex_acquire(&iou_globals.list_mutex);
> n_iocs = cl_qlist_count(&iou_globals.ca_ioc_map_list);
>
> if (n_iocs
sizeof(ca_ioc_info_t) <=
> p_io_stack->Parameters.DeviceIoControl.OutputBufferLength) {
> n_bytes = build_ca_ioc_list(p_ca_ioc_info);
> p_irp->IoStatus.Information = n_bytes;
> status = STATUS_SUCCESS;
> } else {
> status = STATUS_BUFFER_TOO_SMALL;
> }
>
> cl_mutex_release(&iou_globals.list_mutex);
>
> break;
> default:
> status = STATUS_INVALID_DEVICE_REQUEST;
> break;
> }
>
> p_irp->IoStatus.Status = status;
> IoCompleteRequest(p_irp, IO_NO_INCREMENT);
> return status;
> }
>
> Application Snippet:–
>
> Some_function (arguments) {
> …some code
> pBuf = NULL;
> ioctlcode = UAL_IOC_LIST;
> do {
> if (pBuf) {
> printf(“Before calling free in send_device_ioctl, value
> of pBuf %I64X\n”, pBuf);
> free(pBuf);
> dwMemSize *= 2;
> pBuf = NULL;
> }
>
> pBuf = malloc(dwMemSize);
>
> if (!pBuf) {
> printf(“Insufficient memory\n”);
> dwRet = ERROR_NOT_ENOUGH_MEMORY;
> break;
> }
> printf(“Before from DeviceIoControl\n”);
> bRet = DeviceIoControl(hDevice, ioctlcode, NULL, 0, pBuf,
> dwMemSize, &dwBytesRet, NULL);
> dwRet = GetLastError(); // I am always getting
> ERROR_INSUFFICIENT_BUFFER here

>
> if (bRet) {
> printf(“Returned from DeviceIoControl and error code is
> %d and bool value is %d\n”, dwRet, bRet);
> dwRet = 0;
> break;
> }
>
> printf(“Returned from DeviceIoControl and error code is %d
> and bool value is %d\n”, dwRet, bRet);
>
> }while(dwRet == ERROR_INSUFFICIENT_BUFFER)
> …some code
> }
>
> Any help/pointers will be appreciated.
>
> Regards
> Deepak
> — 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
>

To be 100% clear, ther is no definitive rule in windows about when lasterror is set outside of an error condition. Some APIs always clear it on entry, some set it on success. The overall rule you must heed is that you only check it on error, it is undefined for success

d

Sent from my phone with no t9, all spilling mistakes are not intentional.


From: Deepak Gupta
Sent: Thursday, February 26, 2009 2:07 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] GetLastError after calling DeviceIoControl

Mark, Pavel.

Thanks a lot for your inputs. I was also expecting same thing.
So Last Error only gets updated only if some error happens in any call and other wise not.

Regards
Deepak

On Thu, Feb 26, 2009 at 3:28 PM, Mark S. Edwards > wrote:
You should only call GetLastError() when there has been an error.

When DeviceIoControl() succeeds it does not update the internal last error variable, because this is not an error.

So what gets returned by the 2nd call to GetLastError() is the last error value placed in the internal variable i.e. the value placed there by your first failing call to DeviceIoControl().

At 09:24 26/02/2009, Deepak Gupta wrote:
Folks,

I have implemented a IOCTL interface in my driver.

All my IOCTLs are METHOD_BUFFERED.

My user application need some info from my driver.
Inside my driver if the buffer length is insufficient, then i return with error status STATUS_BUFFER_TOO_SMALL which eventually translates to Win32 error code
ERROR_INSUFFICIENT_BUFFER for my user mode app (I do a GetLastError() just after DeviceIoControl).
After this my user app frees that buffer and increase the buffer size and again do a DeviceIoControl.
My driver sees that buffer length is enough for I/O to perform.
This time I get SUCCESS return status (.i.e a non zero value which is success as per docs) from DeviceIoControl but GetLastError() still returns ERROR_INSUFFICIENT_BUFFER (although I have returned STATUS_SUCCESS from driver).
Can any body point what I am doing wrong?

Those who are interested in code snippet can see below:-
I am getting the problem for UAL_IOC_LIST ioctl.

Driver code:–

NTSTATUS
My_Drv_Ioctl(
IN DEVICE_OBJECT *p_dev_obj,
IN IRP *p_irp )
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION p_io_stack;
ULONG controlcode, n_iocs, n_bytes;
ca_ioc_info_t *p_ca_ioc_info;
child_device_info_t p_child_dev;

/
Get the stack location. /
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
controlcode = p_io_stack->Parameters.DeviceIoControl.IoControlCode;
p_irp->IoStatus.Information = 0;

switch (controlcode) {
case UAL_IOC_DEVICE_CREATE:
p_child_dev = p_irp->AssociatedIrp.SystemBuffer;

if (sizeof(child_device_info_t) >= (p_io_stack->Parameters.DeviceIoControl.InputBufferLength)) {
status = STATUS_BUFFER_TOO_SMALL;
} else {
status = create_child_ioc_device(p_child_dev);
}
break;

case UAL_IOC_LIST:
p_ca_ioc_info = p_irp->AssociatedIrp.SystemBuffer;
cl_mutex_acquire(&iou_globals.list_mutex);
n_iocs = cl_qlist_count(&iou_globals.ca_ioc_map_list);

if (n_iocs
sizeof(ca_ioc_info_t) <= p_io_stack->Parameters.DeviceIoControl.OutputBufferLength) {
n_bytes = build_ca_ioc_list(p_ca_ioc_info);
p_irp->IoStatus.Information = n_bytes;
status = STATUS_SUCCESS;
} else {
status = STATUS_BUFFER_TOO_SMALL;
}

cl_mutex_release(&iou_globals.list_mutex);

break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}

p_irp->IoStatus.Status = status;
IoCompleteRequest(p_irp, IO_NO_INCREMENT);
return status;
}

Application Snippet:–

Some_function (arguments) {
…some code
pBuf = NULL;
ioctlcode = UAL_IOC_LIST;
do {
if (pBuf) {
printf(“Before calling free in send_device_ioctl, value of pBuf %I64X\n”, pBuf);
free(pBuf);
dwMemSize *= 2;
pBuf = NULL;
}

pBuf = malloc(dwMemSize);

if (!pBuf) {
printf(“Insufficient memory\n”);
dwRet = ERROR_NOT_ENOUGH_MEMORY;
break;
}
printf(“Before from DeviceIoControl\n”);
bRet = DeviceIoControl(hDevice, ioctlcode, NULL, 0, pBuf, dwMemSize, &dwBytesRet, NULL);
dwRet = GetLastError(); // I am always getting ERROR_INSUFFICIENT_BUFFER here

if (bRet) {
printf(“Returned from DeviceIoControl and error code is %d and bool value is %d\n”, dwRet, bRet);
dwRet = 0;
break;
}

printf(“Returned from DeviceIoControl and error code is %d and bool value is %d\n”, dwRet, bRet);

}while(dwRet == ERROR_INSUFFICIENT_BUFFER)
…some code
}

Any help/pointers will be appreciated.

Regards
Deepak
— 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

> This time I get SUCCESS return status (.i.e a non zero value

which is success as per docs) from DeviceIoControl but
GetLastError() still returns ERROR_INSUFFICIENT_BUFFER
(although I have returned STATUS_SUCCESS from driver).
Doron already said that GLE is meaningful only after an error.
But just out of interest you may want toclear GLE right before
DeviceIoControl:

printf(“Before from DeviceIoControl\n”);
SetLastError(S_OK); // reset it
bRet = DeviceIoControl(hDevice, ioctlcode, NULL, 0, pBuf, dwMemSize, &dwBytesRet, NULL);
dwRet = GetLastError(); // I am always getting ERROR_INSUFFICIENT_BUFFER here

----- Original Message -----
From: Deepak Gupta
To: Windows System Software Devs Interest List
Sent: Thursday, February 26, 2009 4:24 AM
Subject: [ntdev] GetLastError after calling DeviceIoControl

Folks,

I have implemented a IOCTL interface in my driver.

All my IOCTLs are METHOD_BUFFERED.

My user application need some info from my driver.
Inside my driver if the buffer length is insufficient, then i return with error status STATUS_BUFFER_TOO_SMALL which eventually translates to Win32 error code
ERROR_INSUFFICIENT_BUFFER for my user mode app (I do a GetLastError() just after DeviceIoControl).
After this my user app frees that buffer and increase the buffer size and again do a DeviceIoControl.
My driver sees that buffer length is enough for I/O to perform.
This time I get SUCCESS return status (.i.e a non zero value which is success as per docs) from DeviceIoControl but GetLastError() still returns ERROR_INSUFFICIENT_BUFFER (although I have returned STATUS_SUCCESS from driver).
Can any body point what I am doing wrong?

Those who are interested in code snippet can see below:-
I am getting the problem for UAL_IOC_LIST ioctl.

Driver code:–

NTSTATUS
My_Drv_Ioctl(
IN DEVICE_OBJECT *p_dev_obj,
IN IRP *p_irp )
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION p_io_stack;
ULONG controlcode, n_iocs, n_bytes;
ca_ioc_info_t *p_ca_ioc_info;
child_device_info_t *p_child_dev;

/* Get the stack location. */
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
controlcode = p_io_stack->Parameters.DeviceIoControl.IoControlCode;
p_irp->IoStatus.Information = 0;

switch (controlcode) {
case UAL_IOC_DEVICE_CREATE:
p_child_dev = p_irp->AssociatedIrp.SystemBuffer;

if (sizeof(child_device_info_t) >= (p_io_stack->Parameters.DeviceIoControl.InputBufferLength)) {
status = STATUS_BUFFER_TOO_SMALL;
} else {
status = create_child_ioc_device(p_child_dev);
}
break;

case UAL_IOC_LIST:
p_ca_ioc_info = p_irp->AssociatedIrp.SystemBuffer;
cl_mutex_acquire(&iou_globals.list_mutex);
n_iocs = cl_qlist_count(&iou_globals.ca_ioc_map_list);

if (n_iocs*sizeof(ca_ioc_info_t) <= p_io_stack->Parameters.DeviceIoControl.OutputBufferLength) {
n_bytes = build_ca_ioc_list(p_ca_ioc_info);
p_irp->IoStatus.Information = n_bytes;
status = STATUS_SUCCESS;
} else {
status = STATUS_BUFFER_TOO_SMALL;
}

cl_mutex_release(&iou_globals.list_mutex);

break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}

p_irp->IoStatus.Status = status;
IoCompleteRequest(p_irp, IO_NO_INCREMENT);
return status;
}

Application Snippet:–

Some_function (arguments) {
…some code
pBuf = NULL;
ioctlcode = UAL_IOC_LIST;
do {
if (pBuf) {
printf(“Before calling free in send_device_ioctl, value of pBuf %I64X\n”, pBuf);
free(pBuf);
dwMemSize *= 2;
pBuf = NULL;
}

pBuf = malloc(dwMemSize);

if (!pBuf) {
printf(“Insufficient memory\n”);
dwRet = ERROR_NOT_ENOUGH_MEMORY;
break;
}
printf(“Before from DeviceIoControl\n”);
bRet = DeviceIoControl(hDevice, ioctlcode, NULL, 0, pBuf, dwMemSize, &dwBytesRet, NULL);
dwRet = GetLastError(); // I am always getting ERROR_INSUFFICIENT_BUFFER here

if (bRet) {
printf(“Returned from DeviceIoControl and error code is %d and bool value is %d\n”, dwRet, bRet);
dwRet = 0;
break;
}

printf(“Returned from DeviceIoControl and error code is %d and bool value is %d\n”, dwRet, bRet);

}while(dwRet == ERROR_INSUFFICIENT_BUFFER)
…some code
}

Any help/pointers will be appreciated.

Regards
Deepak
— 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