WdfRequestSend completion routine gives status=0xC000000D urb USBD_STATUS=0x80000600

Hi.

I am trying to write to a usb iso out pipe and am getting error status=0xC000000D urb USBD_STATUS=0x80000600.

0x80000600 supposedly means USBD_STATUS_INVALID_PIPE_HANDLE, but my urb has the pipe handle set correctly. In fact I have checked the whole structure and everything seems OK. It’s a highspeed device with bInterval set to 4 (only 1 micro frame per 1ms frame). Yet, I am sending 8 packets. The packets take up the entire buffer, are in order etc.

Everything looks OK. My pipe handle is certainly a valid pipe handle as returned from WDF, so are there any other reasons why I might get error 0x80000600?

Another question: If bInterval=4, do I still need to supply at least 8 packets in the urb? Will wdf simply take the first packet and ignore the remaining 7 micro frame packets. If bInterval=3 (2 micro frames per frame), will WDF only use the 1st and 4th packet in my urb structure? From reading the docs this is not very clear to me…

Thanks
Philip

Are you putting the WDFUSBPIPE or the USBPIPEHANDLE handle value in the URB? The latter is the correct one, but your description is not clear to know for sure which one you are using

d

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

-----Original Message-----
From: xxxxx@cox.net
Sent: Monday, September 07, 2009 11:49 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] WdfRequestSend completion routine gives status=0xC000000D urb USBD_STATUS=0x80000600

Hi.

I am trying to write to a usb iso out pipe and am getting error status=0xC000000D urb USBD_STATUS=0x80000600.

0x80000600 supposedly means USBD_STATUS_INVALID_PIPE_HANDLE, but my urb has the pipe handle set correctly. In fact I have checked the whole structure and everything seems OK. It’s a highspeed device with bInterval set to 4 (only 1 micro frame per 1ms frame). Yet, I am sending 8 packets. The packets take up the entire buffer, are in order etc.

Everything looks OK. My pipe handle is certainly a valid pipe handle as returned from WDF, so are there any other reasons why I might get error 0x80000600?

Another question: If bInterval=4, do I still need to supply at least 8 packets in the urb? Will wdf simply take the first packet and ignore the remaining 7 micro frame packets. If bInterval=3 (2 micro frames per frame), will WDF only use the 1st and 4th packet in my urb structure? From reading the docs this is not very clear to me…

Thanks
Philip


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 Doron, that was exactly the problem. Sorry but I have more questions :slight_smile:

Now I have another problem. I get noerrors, but the completion routine gets zero in urbBuffer->UrbIsochronousTransfer.TransferBufferLength. I looked at the USB bus and no packets are being sent. One thing of interest is that I see periodic reset events on the USB bus, and wonder if that could have something to do with it. In the driver I simply select the interface and alt setting, get the pipe, and then keep that information until it is actually time to send packets. If I don’t get any error shouldn’t TransferBufferLength>0?

I tried playing around with size and number of packets and this makes no difference. This particular pipe has bInterval=4 so only one high speed micro frame per 1ms frame. NumberOfPackets=1 and NumberOfPackets=8 makes no difference.

Regarding my secondary question from before, I am still not clear how to queue packets if bInterval=3 or bInterval=4. Does the USB stack simply skip the packets that are not supposed to be sent or should I not include the packets in the URB? Also, if bInterval=3, does it send packet#0 and packet#4 in that order?

Thanks

Philip

xxxxx@cox.net wrote:

Now I have another problem. I get noerrors, but the completion routine gets zero in urbBuffer->UrbIsochronousTransfer.TransferBufferLength. I looked at the USB bus and no packets are being sent. One thing of interest is that I see periodic reset events on the USB bus, and wonder if that could have something to do with it. In the driver I simply select the interface and alt setting, get the pipe, and then keep that information until it is actually time to send packets. If I don’t get any error shouldn’t TransferBufferLength>0?

Theoretically, yes, but you should check the lengths and the error codes
in the IsoPacket array for more information. The individual packets in
an isochronous transfer are rather independent of one another.

I tried playing around with size and number of packets and this makes no difference. This particular pipe has bInterval=4 so only one high speed micro frame per 1ms frame. NumberOfPackets=1 and NumberOfPackets=8 makes no difference.

Right. The number of packets needs to be a multiple of the number of
transfers per frame. Since bInterval=4 means you have 1 transfer per
frame, there is no restriction on the number of packets per URB. If you
set bInterval=3, then your packet count must be even. bInterval=2 means
you must have a multiple of 4. bInterval=1 means you must have a
multiple of 8.

(Somewhat related side note: the number of transactions per microframe
isn’t involved with this. If you have a maximum bandwidth pipe, with 3
transactions per microframe and an interval of 1 with a packet size of
1024, you must have a multiple of 8 packets in each URB, and the packets
must each be 3072 bytes.)

Regarding my secondary question from before, I am still not clear how to queue packets if bInterval=3 or bInterval=4. Does the USB stack simply skip the packets that are not supposed to be sent or should I not include the packets in the URB? Also, if bInterval=3, does it send packet#0 and packet#4 in that order?

The IsoPacket array maps 1-to-1 to your assigned transfer
opportunities. So, if you have bInterval=4, and you send 8 packets,
that maps to 8ms of real time. If you send 8 packets with bInterval=3,
that maps to 4ms of real time. You do not need to worry about the
microframes where you are not involved.

The packets are sent in order. With isochronous, there is no guarantee
that each packet will succeed; if the 1st packet fails for some reason,
you’ll get an error code in IsoPacket[0], and it will continue with the
second packet.


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

Thanks Tim.

So I think I understand generally how things are supposed to be done.

However I am still getting no errors and TransferBufferLength==0 in the
completion routine. To keep things simple I now only send a single frame.
The completion routine sees packet.Status==0 and packet.Length==176 (the
original length that I set).

I assume if there were something wrong with my frame numbers I would get a
frame related error.

Any ideas why no error but no data sent?

Philip

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Tuesday, September 08, 2009 2:03 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] WdfRequestSend completion routine gives
status=0xC000000D urb USBD_STATUS=0x80000600

xxxxx@cox.net wrote:

Now I have another problem. I get noerrors, but the completion routine
gets zero in urbBuffer->UrbIsochronousTransfer.TransferBufferLength. I
looked at the USB bus and no packets are being sent. One thing of interest
is that I see periodic reset events on the USB bus, and wonder if that could
have something to do with it. In the driver I simply select the interface
and alt setting, get the pipe, and then keep that information until it is
actually time to send packets. If I don’t get any error shouldn’t
TransferBufferLength>0?

Theoretically, yes, but you should check the lengths and the error codes
in the IsoPacket array for more information. The individual packets in
an isochronous transfer are rather independent of one another.

I tried playing around with size and number of packets and this makes no
difference. This particular pipe has bInterval=4 so only one high speed
micro frame per 1ms frame. NumberOfPackets=1 and NumberOfPackets=8 makes no
difference.

Right. The number of packets needs to be a multiple of the number of
transfers per frame. Since bInterval=4 means you have 1 transfer per
frame, there is no restriction on the number of packets per URB. If you
set bInterval=3, then your packet count must be even. bInterval=2 means
you must have a multiple of 4. bInterval=1 means you must have a
multiple of 8.

(Somewhat related side note: the number of transactions per microframe
isn’t involved with this. If you have a maximum bandwidth pipe, with 3
transactions per microframe and an interval of 1 with a packet size of
1024, you must have a multiple of 8 packets in each URB, and the packets
must each be 3072 bytes.)

Regarding my secondary question from before, I am still not clear how to
queue packets if bInterval=3 or bInterval=4. Does the USB stack simply skip
the packets that are not supposed to be sent or should I not include the
packets in the URB? Also, if bInterval=3, does it send packet#0 and
packet#4 in that order?

The IsoPacket array maps 1-to-1 to your assigned transfer
opportunities. So, if you have bInterval=4, and you send 8 packets,
that maps to 8ms of real time. If you send 8 packets with bInterval=3,
that maps to 4ms of real time. You do not need to worry about the
microframes where you are not involved.

The packets are sent in order. With isochronous, there is no guarantee
that each packet will succeed; if the 1st packet fails for some reason,
you’ll get an error code in IsoPacket[0], and it will continue with the
second packet.


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

pgruebele wrote:

So I think I understand generally how things are supposed to be done.

However I am still getting no errors and TransferBufferLength==0 in the
completion routine. To keep things simple I now only send a single frame.
The completion routine sees packet.Status==0 and packet.Length==176 (the
original length that I set).

I assume if there were something wrong with my frame numbers I would get a
frame related error.

Any ideas why no error but no data sent?

This is an output request, right? For an input request, the packet
sizes must all equal the max packet size for the pipe. Are you
specifying USBD_SHORT_REQUEST_OK? Are you giving a frame number, or
specifying ASAP? Are you setting TransferBufferLength=176 when you
build the request?


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

Yes, this is an out request. I am not specifying USBD_SHORT_REQUEST_OK
since this is an out request (actually I cannot find anything on that flag).
TransferBufferLength and the packet length are set to 176.

I tried several frame number related permutations with the same results (all
requests fail the same way, including first one):

********1.

ntStatus =
WdfUsbTargetDeviceRetrieveCurrentFrameNumber(context->WdfUsbTargetDevice,
&frameNumber);
frameNumber += 5;
if (!NT_SUCCESS(ntStatus))
{
}
urb->TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
urb->StartFrame = frameNumber;

********2.

ntStatus =
WdfUsbTargetDeviceRetrieveCurrentFrameNumber(context->WdfUsbTargetDevice,
&frameNumber);
frameNumber += 5;
urb->TransferFlags = USBD_TRANSFER_DIRECTION_OUT |
USBD_START_ISO_TRANSFER_ASAP;
urb->StartFrame = frameNumber;

********3.

urb->TransferFlags = USBD_TRANSFER_DIRECTION_OUT |
USBD_START_ISO_TRANSFER_ASAP;
urb->StartFrame = 0;

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Tuesday, September 08, 2009 2:27 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] WdfRequestSend completion routine gives
status=0xC000000D urb USBD_STATUS=0x80000600

pgruebele wrote:

So I think I understand generally how things are supposed to be done.

However I am still getting no errors and TransferBufferLength==0 in the
completion routine. To keep things simple I now only send a single frame.
The completion routine sees packet.Status==0 and packet.Length==176 (the
original length that I set).

I assume if there were something wrong with my frame numbers I would get a
frame related error.

Any ideas why no error but no data sent?

This is an output request, right? For an input request, the packet
sizes must all equal the max packet size for the pipe. Are you
specifying USBD_SHORT_REQUEST_OK? Are you giving a frame number, or
specifying ASAP? Are you setting TransferBufferLength=176 when you
build the request?


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

In case it helps, here is the basic code:

ULONG frameNumber;
ntStatus =
WdfUsbTargetDeviceRetrieveCurrentFrameNumber(context->WdfUsbTargetDevice,
&frameNumber);
frameNumber += 5;
if (!NT_SUCCESS(ntStatus))
{

}

struct _URB_ISOCH_TRANSFER *urb =
&request->urbBuffer->UrbIsochronousTransfer;
urb->Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
urb->Hdr.Length = GET_ISO_URB_SIZE(1);
urb->Hdr.Status = 0;
urb->PipeHandle =
WdfUsbTargetPipeWdmGetPipeHandle(context->writePipe);
urb->TransferFlags = USBD_TRANSFER_DIRECTION_OUT |
USBD_START_ISO_TRANSFER_ASAP;
urb->TransferBufferMDL = 0;
urb->ErrorCount = 0;
urb->StartFrame = frameNumber;
urb->NumberOfPackets = 1;
urb->TransferBuffer = pBuffer;
urb->TransferBufferLength = 176;
urb->UrbLink = NULL;

urb->IsoPacket[0].Offset = 0;
urb->IsoPacket[0].Length = 176;
urb->IsoPacket[0].Status = 0;

ntStatus =
WdfUsbTargetPipeFormatRequestForUrb(context->writePipe, Request,
request->urbMemory, NULL);
if (!NT_SUCCESS(ntStatus))
{

}

USBRequestSetCompletionRoutine(Request);

if (WdfRequestSend(Request, context->ioTarget,
WDF_NO_SEND_OPTIONS) == FALSE)
{

}

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Tuesday, September 08, 2009 2:27 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] WdfRequestSend completion routine gives
status=0xC000000D urb USBD_STATUS=0x80000600

pgruebele wrote:

So I think I understand generally how things are supposed to be done.

However I am still getting no errors and TransferBufferLength==0 in the
completion routine. To keep things simple I now only send a single frame.
The completion routine sees packet.Status==0 and packet.Length==176 (the
original length that I set).

I assume if there were something wrong with my frame numbers I would get a
frame related error.

Any ideas why no error but no data sent?

This is an output request, right? For an input request, the packet
sizes must all equal the max packet size for the pipe. Are you
specifying USBD_SHORT_REQUEST_OK? Are you giving a frame number, or
specifying ASAP? Are you setting TransferBufferLength=176 when you
build the request?


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

Does anyone have any ideas as to why my completion routine gets
TransferBufferLength=0 packet[0].Length=176 packet[0].status=0x0 but no
errors? I would expect there to be some sort of error code if zero bytes
are being transferred.

There is no activity on the usb bus, so I know that no bytes are being
transferred.

I’ve examined all the samples and can’t find what I am doing wrong. The
only unusual thing is that I am seeing Device Reset events on the USB bus.
I don’t see these when using my device with the generic usb audio driver.
Why would WDF be resetting my device? I am not sending an reset requests.

Thanks

Philip

pgruebele wrote:

Does anyone have any ideas as to why my completion routine gets
TransferBufferLength=0 packet[0].Length=176 packet[0].status=0x0 but no
errors? I would expect there to be some sort of error code if zero bytes
are being transferred.

Can you post the code that creates the URB and IRP?


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

Urb/request creation. I took out error detection to keep it shorter (but of
course I check all error return codes and none of them return any errors):

for (int i = 0; i < 1; i++)
{
// create request
WDF_OBJECT_ATTRIBUTES objectAttribs;
WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&objectAttribs,
USB_ISO_REQUEST);
WdfRequestCreate(&objectAttribs,
WdfUsbTargetDeviceGetIoTarget(context->WdfUsbTargetDevice),
&context->writeResources.WriteRequestArray[i].request);

// alloc urb
WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
objectAttribs.ParentObject =
context->writeResources.WriteRequestArray[i].request;
WdfMemoryCreate(&objectAttribs, NonPagedPool, POOL_TAG,
GET_ISO_URB_SIZE(1),
&context->writeResources.WriteRequestArray[i].urbMemory,
(PVOID*)&context->writeResources.WriteRequestArray[i].urbBuffer);
memset(context->writeResources.WriteRequestArray[i].urbBuffer, 0,
GET_ISO_URB_SIZE(1));

}

Urb sending:

WDFREQUEST Request;
PUSB_ISO_REQUEST request = GetWriteRequest(&Request);
ASSERT(request != 0 && Request != 0);

ULONG frameNumber;

WdfUsbTargetDeviceRetrieveCurrentFrameNumber(context->WdfUsbTargetDevice,
&frameNumber);
frameNumber += 10;

struct _URB_ISOCH_TRANSFER *urb =
&request->urbBuffer->UrbIsochronousTransfer;
urb->Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
urb->Hdr.Length = GET_ISO_URB_SIZE(1);
urb->Hdr.Status = 0;
urb->PipeHandle =
WdfUsbTargetPipeWdmGetPipeHandle(context->writePipe);
urb->TransferFlags = USBD_TRANSFER_DIRECTION_OUT;// |
USBD_START_ISO_TRANSFER_ASAP;
urb->TransferBufferMDL = 0;
urb->ErrorCount = 0;
urb->StartFrame = frameNumber;
urb->NumberOfPackets = 1;
urb->TransferBuffer = context->writeResources.pAudioBuffer;
urb->TransferBufferLength = 176;
urb->UrbLink = NULL;

urb->IsoPacket[0].Offset = 0;
urb->IsoPacket[0].Length = 176;
urb->IsoPacket[0].Status = 0;

WdfUsbTargetPipeFormatRequestForUrb(context->writePipe, Request,
request->urbMemory, NULL);

WdfRequestSetCompletionRoutine(Request, WriteCompletionRoutine,
this);

if (WdfRequestSend(Request,
WdfUsbTargetPipeGetIoTarget(context->writePipe, WDF_NO_SEND_OPTIONS) ==
FALSE)
{
ntStatus = WdfRequestGetStatus(Request);
usbtDebugPrint((DBGERROR, “WdfRequestSend failed with
status code 0x%x\n”, ntStatus));
}

pgruebele wrote:

Urb/request creation. I took out error detection to keep it shorter (but of
course I check all error return codes and none of them return any errors):

Urb sending:

I don’t see anything wrong with the code.

So, you have an analyzer hooked up, and you don’t ever see an OUT token
at all? With the code you have, there should be a 10 millisecond delay
between your submission and the bus activity, but there should be something.


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

There is no bus activity as a result of this code. The only thing on the
bus I see are device resets events.

The completion routine sees
urbBuffer->UrbIsochronousTransfer.TransferBufferLength==0 so it is not lying
since nothing is being sent to the bus.

Other communication with the device (configuring and selecting interfaces
etc) works fine and is of course visible on the bus. I am able to select
the correct interface and alt setting, and I am able to get the pipe handle
and see that this is the correct pipe information (endpoint 5 ISO out).
WdfIoTargetStart() also works.

Only sending these ISO packets does not appear to work. I just don’t
understand why I’m not getting any error. Also, the packet length seems to
remain untouched and the packet also has no error.

I welcome any suggestions because I’ve run out of things to try. The only
thing left is that I will use a tool like UBLyzer and see if this will shed
any light…

Thanks

Philip

Is this on Win7? If so, you can take an ETW log, which I’d like to see
(will send instructions).

The resets sound suspicious. Are they regular? How often?

pgruebele wrote:

There is no bus activity as a result of this code. The only thing on the
bus I see are device resets events.

The completion routine sees
urbBuffer->UrbIsochronousTransfer.TransferBufferLength==0 so it is not lying
since nothing is being sent to the bus.

Other communication with the device (configuring and selecting interfaces
etc) works fine and is of course visible on the bus. I am able to select
the correct interface and alt setting, and I am able to get the pipe handle
and see that this is the correct pipe information (endpoint 5 ISO out).
WdfIoTargetStart() also works.

Only sending these ISO packets does not appear to work. I just don’t
understand why I’m not getting any error. Also, the packet length seems to
remain untouched and the packet also has no error.

I welcome any suggestions because I’ve run out of things to try. The only
thing left is that I will use a tool like UBLyzer and see if this will shed
any light…

Thanks

Philip

Ok, I inadvertently solved the problem. I accidentally booted the target
without debug mode, and it worked. It turns out that my DbgPrintEx
statements were slowing the computer down enough to cause USB ISO to no
longer work. I have removed some of these and now things work even when
booting into debug mode.

I’m still surprised that I did not get any error messages, for example for
the specified frame time having passed etc… WDF/USB should have given
some kind of error. Would have saved me 10 hours of grief :slight_smile:

Thanks Doron, Tim, and Philip for helping me on this. As usual it turned
out to be a simple solution!

On another note, I am surprised at how slow DbgPrintEx is considering I am
using a 1394 debug cable. The host/target must not make full use of 1394
bandwidth.

pgruebele wrote:

On another note, I am surprised at how slow DbgPrintEx is considering I am
using a 1394 debug cable. The host/target must not make full use of 1394
bandwidth.

The kernel debug interface is optimized for reliability, not speed.
Remember it’s not using the “real” 1394 device stack; it’s using a
limited bare-bones stack that is launched at boot time. Plus, the
interface is fully synchronous; the thread blocks until the message is sent.


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

Is there any way to modify the data rate used via 1394? Would a USB
connection be faster? USB might not be a good idea in my case since I’m
debugging a USB device.

My estimation is that the 1394 data rate is roughly equivalent to a 200KBaud
serial connection, which is pretty darn slow for such a high speed
interface.

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

> Is there any way to modify the data rate used via 1394?

Reduce your amount of DbgPrints instead, make them more controllable, or print to a ring buffer inside your driver (instrumented build) and then view it from WinDbg using a trivial extension DLL.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

I don’t know the answer to this question, but I kind of doubt it, and everything that I’ve heard about using USB with windbg hasn’t been good, and that’s out of only a handful of cases, so I don’t think that I would try it (expensive, hard to find cable as well) without some better information that I can offer.

It’s been a while, but I definitely recall that at least during the Vista beta cycle, a lot of people had this slow 1394 problem. Unfortunately, I don’t recall what was doing it. It’s true that DbgPrint can be quite slow, but what you’re describing sounds REALLY slow.

What’s your target OS?

I’d be curious to see how creating a crashdump over your connection would go. At the speed your describing, it would take forever. I not all that uncommonly create a full memory dump of an 8GB target, and that takes a while, but many times less what it would at that rate, if my mental math is correct (know to be dubious).

.dump /f

mm

I agree that under heavy logging loads, a ring buffer would be appropriate,
but for the limited amount of outputting I am doing, this should really not
be necessary when a high speed interface like 1394 is available. I believe
the 1394 stack on the target should be able to transfer at higher speeds,
well above RS232 speeds.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Wednesday, September 09, 2009 5:20 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] WdfRequestSend completion routine gives
status=0xC000000D urb USBD_STATUS=0x80000600

Is there any way to modify the data rate used via 1394?

Reduce your amount of DbgPrints instead, make them more controllable, or
print to a ring buffer inside your driver (instrumented build) and then view
it from WinDbg using a trivial extension DLL.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com


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