ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

usbd.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:     ReactOS Universal Serial Bus Driver/Helper Library
00003  * LICENSE:     GPL - See COPYING in the top level directory
00004  * FILE:        drivers/usb/usbd/usbd.c
00005  * PURPOSE:     Helper Library for USB
00006  * PROGRAMMERS:
00007  *              Filip Navara <xnavara@volny.cz>
00008  *              Michael Martin <michael.martin@reactos.org>
00009  *
00010  */
00011 
00012 /*
00013  * Universal Serial Bus Driver/Helper Library
00014  *
00015  * Written by Filip Navara <xnavara@volny.cz>
00016  *
00017  * Notes:
00018  *    This driver was obsoleted in Windows XP and most functions
00019  *    became pure stubs. But some of them were retained for backward
00020  *    compatibilty with existing drivers.
00021  *
00022  *    Preserved functions:
00023  *
00024  *    USBD_Debug_GetHeap (implemented)
00025  *    USBD_Debug_RetHeap (implemented)
00026  *    USBD_CalculateUsbBandwidth (implemented, tested)
00027  *    USBD_CreateConfigurationRequestEx (implemented)
00028  *    USBD_CreateConfigurationRequest
00029  *    USBD_GetInterfaceLength (implemented)
00030  *    USBD_ParseConfigurationDescriptorEx (implemented)
00031  *    USBD_ParseDescriptors (implemented)
00032  *    USBD_GetPdoRegistryParameters (implemented)
00033  */
00034 
00035 #define _USBD_
00036 #define NDEBUG
00037 #include <ntddk.h>
00038 #include <usbdi.h>
00039 #include <usbdlib.h>
00040 #include <debug.h>
00041 #ifndef PLUGPLAY_REGKEY_DRIVER
00042 #define PLUGPLAY_REGKEY_DRIVER              2
00043 #endif
00044 
00045 NTSTATUS NTAPI
00046 DriverEntry(PDRIVER_OBJECT DriverObject,
00047             PUNICODE_STRING RegistryPath)
00048 {
00049     return STATUS_SUCCESS;
00050 }
00051 
00052 /*
00053  * @implemented
00054  */
00055 ULONG NTAPI
00056 DllInitialize(ULONG Unknown)
00057 {
00058     return 0;
00059 }
00060 
00061 /*
00062  * @implemented
00063  */
00064 ULONG NTAPI
00065 DllUnload(VOID)
00066 {
00067     return 0;
00068 }
00069 
00070 /*
00071  * @implemented
00072  */
00073 PVOID NTAPI
00074 USBD_Debug_GetHeap(ULONG Unknown1, POOL_TYPE PoolType, ULONG NumberOfBytes,
00075                    ULONG Tag)
00076 {
00077     return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
00078 }
00079 
00080 /*
00081  * @implemented
00082  */
00083 VOID NTAPI
00084 USBD_Debug_RetHeap(PVOID Heap, ULONG Unknown2, ULONG Unknown3)
00085 {
00086     ExFreePool(Heap);
00087 }
00088 
00089 /*
00090  * @implemented
00091  */
00092 VOID NTAPI
00093 USBD_Debug_LogEntry(PCHAR Name, ULONG_PTR Info1, ULONG_PTR Info2,
00094     ULONG_PTR Info3)
00095 {
00096 }
00097 
00098 /*
00099  * @implemented
00100  */
00101 PVOID NTAPI
00102 USBD_AllocateDeviceName(ULONG Unknown)
00103 {
00104     UNIMPLEMENTED
00105     return NULL;
00106 }
00107 
00108 /*
00109  * @implemented
00110  */
00111 ULONG NTAPI
00112 USBD_CalculateUsbBandwidth(
00113     ULONG MaxPacketSize,
00114     UCHAR EndpointType,
00115     BOOLEAN LowSpeed
00116     )
00117 {
00118     ULONG OverheadTable[] = {
00119             0x00, /* UsbdPipeTypeControl */
00120             0x09, /* UsbdPipeTypeIsochronous */
00121             0x00, /* UsbdPipeTypeBulk */
00122             0x0d  /* UsbdPipeTypeInterrupt */
00123         };
00124     ULONG Result;
00125 
00126     if (OverheadTable[EndpointType] != 0)
00127     {
00128         Result = ((MaxPacketSize + OverheadTable[EndpointType]) * 8 * 7) / 6;
00129         if (LowSpeed)
00130            return Result << 3;
00131         return Result;
00132     }
00133     return 0;
00134 }
00135 
00136 /*
00137  * @implemented
00138  */
00139 ULONG NTAPI
00140 USBD_Dispatch(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, ULONG Unknown4)
00141 {
00142     UNIMPLEMENTED
00143     return 1;
00144 }
00145 
00146 /*
00147  * @implemented
00148  */
00149 VOID NTAPI
00150 USBD_FreeDeviceMutex(PVOID Unknown)
00151 {
00152     UNIMPLEMENTED
00153 }
00154 
00155 /*
00156  * @implemented
00157  */
00158 VOID NTAPI
00159 USBD_FreeDeviceName(PVOID Unknown)
00160 {
00161     UNIMPLEMENTED
00162 }
00163 
00164 /*
00165  * @implemented
00166  */
00167 VOID NTAPI
00168 USBD_WaitDeviceMutex(PVOID Unknown)
00169 {
00170     UNIMPLEMENTED
00171 }
00172 
00173 /*
00174  * @implemented
00175  */
00176 ULONG NTAPI
00177 USBD_GetSuspendPowerState(ULONG Unknown1)
00178 {
00179     UNIMPLEMENTED
00180     return 0;
00181 }
00182 
00183 /*
00184  * @implemented
00185  */
00186 NTSTATUS NTAPI
00187 USBD_InitializeDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3,
00188     ULONG Unknown4, ULONG Unknown5, ULONG Unknown6)
00189 {
00190     UNIMPLEMENTED
00191     return STATUS_NOT_SUPPORTED;
00192 }
00193 
00194 /*
00195  * @implemented
00196  */
00197 NTSTATUS NTAPI
00198 USBD_RegisterHostController(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3,
00199     ULONG Unknown4, ULONG Unknown5, ULONG Unknown6, ULONG Unknown7,
00200     ULONG Unknown8, ULONG Unknown9, ULONG Unknown10)
00201 {
00202     UNIMPLEMENTED
00203     return STATUS_NOT_SUPPORTED;
00204 }
00205 
00206 /*
00207  * @implemented
00208  */
00209 NTSTATUS NTAPI
00210 USBD_GetDeviceInformation(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3)
00211 {
00212     UNIMPLEMENTED
00213     return STATUS_NOT_SUPPORTED;
00214 }
00215 
00216 /*
00217  * @implemented
00218  */
00219 NTSTATUS NTAPI
00220 USBD_CreateDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3,
00221     ULONG Unknown4, ULONG Unknown5)
00222 {
00223     UNIMPLEMENTED
00224     return STATUS_NOT_SUPPORTED;
00225 }
00226 
00227 /*
00228  * @implemented
00229  */
00230 NTSTATUS NTAPI
00231 USBD_RemoveDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3)
00232 {
00233     UNIMPLEMENTED
00234     return STATUS_NOT_SUPPORTED;
00235 }
00236 
00237 /*
00238  * @implemented
00239  */
00240 VOID NTAPI
00241 USBD_CompleteRequest(ULONG Unknown1, ULONG Unknown2)
00242 {
00243     UNIMPLEMENTED
00244 }
00245 
00246 /*
00247  * @implemented
00248  */
00249 VOID NTAPI
00250 USBD_RegisterHcFilter(
00251     PDEVICE_OBJECT DeviceObject,
00252     PDEVICE_OBJECT FilterDeviceObject
00253     )
00254 {
00255     UNIMPLEMENTED
00256 }
00257 
00258 /*
00259  * @implemented
00260  */
00261 VOID NTAPI
00262 USBD_SetSuspendPowerState(ULONG Unknown1, ULONG Unknown2)
00263 {
00264     UNIMPLEMENTED
00265 }
00266 
00267 /*
00268  * @implemented
00269  */
00270 NTSTATUS NTAPI
00271 USBD_MakePdoName(ULONG Unknown1, ULONG Unknown2)
00272 {
00273     UNIMPLEMENTED
00274     return STATUS_NOT_SUPPORTED;
00275 }
00276 
00277 /*
00278  * @implemented
00279  */
00280 NTSTATUS NTAPI
00281 USBD_QueryBusTime(
00282     PDEVICE_OBJECT RootHubPdo,
00283     PULONG CurrentFrame
00284     )
00285 {
00286     UNIMPLEMENTED
00287     return STATUS_NOT_SUPPORTED;
00288 }
00289 
00290 /*
00291  * @implemented
00292  */
00293 VOID NTAPI
00294 USBD_GetUSBDIVersion(
00295     PUSBD_VERSION_INFORMATION Version
00296     )
00297 {
00298     if (Version != NULL)
00299     {
00300         Version->USBDI_Version = USBDI_VERSION;
00301         Version->Supported_USB_Version = 0x200;
00302     }
00303 }
00304 
00305 /*
00306  * @implemented
00307  */
00308 NTSTATUS NTAPI
00309 USBD_RestoreDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3)
00310 {
00311     UNIMPLEMENTED
00312     return STATUS_NOT_SUPPORTED;
00313 }
00314 
00315 /*
00316  * @implemented
00317  */
00318 VOID NTAPI
00319 USBD_RegisterHcDeviceCapabilities(ULONG Unknown1, ULONG Unknown2,
00320     ULONG Unknown3)
00321 {
00322     UNIMPLEMENTED
00323 }
00324 
00325 /*
00326  * @implemented
00327  */
00328 PURB NTAPI
00329 USBD_CreateConfigurationRequestEx(
00330     PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
00331     PUSBD_INTERFACE_LIST_ENTRY InterfaceList
00332     )
00333 {
00334     PURB Urb;
00335     ULONG UrbSize = 0;
00336     ULONG InterfaceCount = 0, PipeCount = 0;
00337     ULONG InterfaceNumber, EndPointNumber;
00338     PUSBD_INTERFACE_INFORMATION InterfaceInfo;
00339 
00340     while(InterfaceList[InterfaceCount].InterfaceDescriptor)
00341     {
00342         // pipe count
00343         PipeCount += InterfaceList[InterfaceCount].InterfaceDescriptor->bNumEndpoints;
00344 
00345         // interface count
00346         InterfaceCount++;
00347     }
00348 
00349     // size of urb
00350     UrbSize = GET_SELECT_CONFIGURATION_REQUEST_SIZE(InterfaceCount, PipeCount);
00351 
00352     // allocate urb
00353     Urb = ExAllocatePool(NonPagedPool, UrbSize);
00354     if (!Urb)
00355     {
00356         // no memory
00357         return NULL;
00358     }
00359 
00360     // zero urb
00361     RtlZeroMemory(Urb, UrbSize);
00362 
00363     // init urb header
00364     Urb->UrbSelectConfiguration.Hdr.Function =  URB_FUNCTION_SELECT_CONFIGURATION;
00365     Urb->UrbSelectConfiguration.Hdr.Length = UrbSize;
00366     Urb->UrbSelectConfiguration.ConfigurationDescriptor = ConfigurationDescriptor;
00367 
00368     // init interface information
00369     InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
00370     for (InterfaceNumber = 0; InterfaceNumber < InterfaceCount; InterfaceNumber++)
00371     {
00372         // init interface info
00373         InterfaceList[InterfaceNumber].Interface = InterfaceInfo;
00374         InterfaceInfo->InterfaceNumber = InterfaceList[InterfaceNumber].InterfaceDescriptor->bInterfaceNumber;
00375         InterfaceInfo->AlternateSetting = InterfaceList[InterfaceNumber].InterfaceDescriptor->bAlternateSetting;
00376         InterfaceInfo->NumberOfPipes = InterfaceList[InterfaceNumber].InterfaceDescriptor->bNumEndpoints;
00377 
00378         // store length
00379         InterfaceInfo->Length = GET_USBD_INTERFACE_SIZE(InterfaceList[InterfaceNumber].InterfaceDescriptor->bNumEndpoints);
00380 
00381         // sanity check
00382         //C_ASSERT(FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) == 16);
00383 
00384         for (EndPointNumber = 0; EndPointNumber < InterfaceInfo->NumberOfPipes; EndPointNumber++)
00385         {
00386             // init max transfer size
00387             InterfaceInfo->Pipes[EndPointNumber].MaximumTransferSize = PAGE_SIZE;
00388         }
00389 
00390         // next interface info
00391         InterfaceInfo = (PUSBD_INTERFACE_INFORMATION) ((ULONG_PTR)InterfaceInfo + InterfaceInfo->Length);
00392     }
00393 
00394     return Urb;
00395 }
00396 
00397 /*
00398  * @implemented
00399  */
00400 PURB NTAPI
00401 USBD_CreateConfigurationRequest(
00402     PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
00403     PUSHORT Size
00404     )
00405 {
00406     /* WindowsXP returns NULL */
00407     return NULL;
00408 }
00409 
00410 /*
00411  * @implemented
00412  */
00413 ULONG NTAPI
00414 USBD_GetInterfaceLength(
00415     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
00416     PUCHAR BufferEnd
00417     )
00418 {
00419     ULONG_PTR Current;
00420     PUSB_INTERFACE_DESCRIPTOR CurrentDescriptor = InterfaceDescriptor;
00421     ULONG Length = 0;
00422     BOOLEAN InterfaceFound = FALSE;
00423 
00424     for (Current = (ULONG_PTR)CurrentDescriptor;
00425          Current < (ULONG_PTR)BufferEnd;
00426          Current += CurrentDescriptor->bLength)
00427     {
00428         CurrentDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Current;
00429 
00430         if ((CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) && (InterfaceFound))
00431             break;
00432         else if (CurrentDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
00433             InterfaceFound = TRUE;
00434 
00435         Length += CurrentDescriptor->bLength;
00436     }
00437 
00438     return Length;
00439 }
00440 
00441 /*
00442  * @implemented
00443  */
00444 PUSB_COMMON_DESCRIPTOR NTAPI
00445 USBD_ParseDescriptors(
00446     PVOID  DescriptorBuffer,
00447     ULONG  TotalLength,
00448     PVOID  StartPosition,
00449     LONG  DescriptorType
00450     )
00451 {
00452     PUSB_COMMON_DESCRIPTOR CommonDescriptor;
00453 
00454     /* use start position */
00455     CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)StartPosition;
00456 
00457 
00458     /* find next available descriptor */
00459     while(CommonDescriptor)
00460     {
00461        if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)DescriptorBuffer + TotalLength))
00462        {
00463            /* end reached */
00464            DPRINT("End reached %p\n", CommonDescriptor);
00465            return NULL;
00466        }
00467 
00468        DPRINT("CommonDescriptor Type %x Length %x\n", CommonDescriptor->bDescriptorType, CommonDescriptor->bLength);
00469 
00470        /* is the requested one */
00471        if (CommonDescriptor->bDescriptorType == DescriptorType)
00472        {
00473            /* it is */
00474            return CommonDescriptor;
00475        }
00476 
00477        /* sanity check */
00478        ASSERT(CommonDescriptor->bLength);
00479 
00480        /* move to next descriptor */
00481        CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
00482     }
00483 
00484     /* no descriptor found */
00485     return NULL;
00486 }
00487 
00488 
00489 /*
00490  * @implemented
00491  */
00492 PUSB_INTERFACE_DESCRIPTOR NTAPI
00493 USBD_ParseConfigurationDescriptorEx(
00494     PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
00495     PVOID StartPosition,
00496     LONG InterfaceNumber,
00497     LONG AlternateSetting,
00498     LONG InterfaceClass,
00499     LONG InterfaceSubClass,
00500     LONG InterfaceProtocol
00501     )
00502 {
00503     BOOLEAN Found;
00504     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
00505 
00506     /* set to start position */
00507     InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)StartPosition;
00508 
00509     DPRINT("USBD_ParseConfigurationDescriptorEx\n");
00510     DPRINT("ConfigurationDescriptor %p Length %lu\n", ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength);
00511     DPRINT("CurrentOffset %p Offset %lu\n", StartPosition, ((ULONG_PTR)StartPosition - (ULONG_PTR)ConfigurationDescriptor));
00512 
00513     while(InterfaceDescriptor)
00514     {
00515        /* get interface descriptor */
00516        InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, InterfaceDescriptor, USB_INTERFACE_DESCRIPTOR_TYPE);
00517        if (!InterfaceDescriptor)
00518        {
00519            /* no more descriptors available */
00520            break;
00521        }
00522 
00523        DPRINT("InterfaceDescriptor %p InterfaceNumber %x AlternateSetting %x Length %lu\n", InterfaceDescriptor, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, InterfaceDescriptor->bLength);
00524 
00525        /* set found */
00526        Found = TRUE;
00527 
00528        /* is there an interface number provided */
00529        if(InterfaceNumber != -1)
00530        {
00531           if(InterfaceNumber != InterfaceDescriptor->bInterfaceNumber)
00532           {
00533               /* interface number does not match */
00534               Found = FALSE;
00535           }
00536        }
00537 
00538        /* is there an alternate setting provided */
00539        if(AlternateSetting != -1)
00540        {
00541           if(AlternateSetting != InterfaceDescriptor->bAlternateSetting)
00542           {
00543               /* alternate setting does not match */
00544               Found = FALSE;
00545           }
00546        }
00547 
00548        /* match on interface class */
00549        if(InterfaceClass != -1)
00550        {
00551           if(InterfaceClass != InterfaceDescriptor->bInterfaceClass)
00552           {
00553               /* no match with interface class criteria */
00554               Found = FALSE;
00555           }
00556        }
00557 
00558        /* match on interface sub class */
00559        if(InterfaceSubClass != -1)
00560        {
00561           if(InterfaceSubClass != InterfaceDescriptor->bInterfaceSubClass)
00562           {
00563               /* no interface sub class match */
00564               Found = FALSE;
00565           }
00566        }
00567 
00568        /* interface protocol criteria */
00569        if(InterfaceProtocol != -1)
00570        {
00571           if(InterfaceProtocol != InterfaceDescriptor->bInterfaceProtocol)
00572           {
00573               /* no interface protocol match */
00574               Found = FALSE;
00575           }
00576        }
00577 
00578        if (Found)
00579        {
00580            /* the choosen one */
00581            return InterfaceDescriptor;
00582        }
00583 
00584        /* sanity check */
00585        ASSERT(InterfaceDescriptor->bLength);
00586 
00587        /* move to next descriptor */
00588        InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
00589     }
00590 
00591     DPRINT("No Descriptor With InterfaceNumber %ld AlternateSetting %ld InterfaceClass %ld InterfaceSubClass %ld InterfaceProtocol %ld found\n", InterfaceNumber,
00592             AlternateSetting, InterfaceClass, InterfaceSubClass, InterfaceProtocol);
00593 
00594     return NULL;
00595 }
00596 
00597 /*
00598  * @implemented
00599  */
00600 PUSB_INTERFACE_DESCRIPTOR NTAPI
00601 USBD_ParseConfigurationDescriptor(
00602     PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
00603     UCHAR InterfaceNumber,
00604     UCHAR AlternateSetting
00605     )
00606 {
00607     return USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,
00608         (PVOID)ConfigurationDescriptor, InterfaceNumber, AlternateSetting,
00609         -1, -1, -1);
00610 }
00611 
00612 
00613 /*
00614  * @implemented
00615  */
00616 ULONG NTAPI
00617 USBD_GetPdoRegistryParameter(
00618     PDEVICE_OBJECT PhysicalDeviceObject,
00619     PVOID Parameter,
00620     ULONG ParameterLength,
00621     PWCHAR KeyName,
00622     ULONG KeyNameLength
00623     )
00624 {
00625     NTSTATUS Status;
00626     HANDLE DevInstRegKey;
00627 
00628     /* Open the device key */
00629     Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
00630         PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_ALL, &DevInstRegKey);
00631     if (NT_SUCCESS(Status))
00632     {
00633         PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
00634         UNICODE_STRING ValueName;
00635         ULONG Length;
00636 
00637         /* Initialize the unicode string based on caller data */
00638         ValueName.Buffer = KeyName;
00639         ValueName.Length = ValueName.MaximumLength = KeyNameLength;
00640 
00641         Length = ParameterLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION);
00642         PartialInfo = ExAllocatePool(PagedPool, Length);
00643         if (PartialInfo)
00644         {
00645             Status = ZwQueryValueKey(DevInstRegKey, &ValueName,
00646                 KeyValuePartialInformation, PartialInfo, Length, &Length);
00647             if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
00648             {
00649                 /* The caller doesn't want all the data */
00650                 ExFreePool(PartialInfo);
00651                 PartialInfo = ExAllocatePool(PagedPool, Length);
00652                 if (PartialInfo)
00653                 {
00654                     Status = ZwQueryValueKey(DevInstRegKey, &ValueName,
00655                        KeyValuePartialInformation, PartialInfo, Length, &Length);
00656                 }
00657                 else
00658                 {
00659                     Status = STATUS_NO_MEMORY;
00660                 }
00661             }
00662 
00663             if (NT_SUCCESS(Status))
00664             {
00665                 /* Compute the length to copy back */
00666                 if (ParameterLength < PartialInfo->DataLength)
00667                     Length = ParameterLength;
00668                 else
00669                     Length = PartialInfo->DataLength;
00670 
00671                 RtlCopyMemory(Parameter,
00672                               PartialInfo->Data,
00673                               Length);
00674             }
00675 
00676             if (PartialInfo)
00677             {
00678                 ExFreePool(PartialInfo);
00679             }
00680         } else
00681             Status = STATUS_NO_MEMORY;
00682         ZwClose(DevInstRegKey);
00683     }
00684     return Status;
00685 }

Generated on Sun May 27 2012 04:28:30 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.