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

plugplay.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * COPYRIGHT:       GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/io/pnpmgr/plugplay.c
00005  * PURPOSE:         Plug-and-play interface routines
00006  * PROGRAMMERS:     Eric Kohl <eric.kohl@t-online.de>
00007  */
00008 
00009 /* INCLUDES *****************************************************************/
00010 
00011 #include <ntoskrnl.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 #if defined (ALLOC_PRAGMA)
00016 #pragma alloc_text(INIT, IopInitPlugPlayEvents)
00017 #endif
00018 
00019 typedef struct _PNP_EVENT_ENTRY
00020 {
00021     LIST_ENTRY ListEntry;
00022     PLUGPLAY_EVENT_BLOCK Event;
00023 } PNP_EVENT_ENTRY, *PPNP_EVENT_ENTRY;
00024 
00025 
00026 /* GLOBALS *******************************************************************/
00027 
00028 static LIST_ENTRY IopPnpEventQueueHead;
00029 static KEVENT IopPnpNotifyEvent;
00030 
00031 /* FUNCTIONS *****************************************************************/
00032 
00033 NTSTATUS INIT_FUNCTION
00034 IopInitPlugPlayEvents(VOID)
00035 {
00036     InitializeListHead(&IopPnpEventQueueHead);
00037 
00038     KeInitializeEvent(&IopPnpNotifyEvent,
00039                       SynchronizationEvent,
00040                       FALSE);
00041 
00042     return STATUS_SUCCESS;
00043 }
00044 
00045 NTSTATUS
00046 IopQueueTargetDeviceEvent(const GUID *Guid,
00047                           PUNICODE_STRING DeviceIds)
00048 {
00049     PPNP_EVENT_ENTRY EventEntry;
00050     UNICODE_STRING Copy;
00051     ULONG TotalSize;
00052     NTSTATUS Status;
00053 
00054     ASSERT(DeviceIds);
00055 
00056     /* Allocate a big enough buffer */
00057     Copy.Length = 0;
00058     Copy.MaximumLength = DeviceIds->Length + sizeof(UNICODE_NULL);
00059     TotalSize =
00060         FIELD_OFFSET(PLUGPLAY_EVENT_BLOCK, TargetDevice.DeviceIds) +
00061         Copy.MaximumLength;
00062 
00063     EventEntry = ExAllocatePool(NonPagedPool,
00064                                 TotalSize + FIELD_OFFSET(PNP_EVENT_ENTRY, Event));
00065     if (!EventEntry)
00066         return STATUS_INSUFFICIENT_RESOURCES;
00067 
00068     /* Fill the buffer with the event GUID */
00069     RtlCopyMemory(&EventEntry->Event.EventGuid,
00070                   Guid,
00071                   sizeof(GUID));
00072     EventEntry->Event.EventCategory = TargetDeviceChangeEvent;
00073     EventEntry->Event.TotalSize = TotalSize;
00074 
00075     /* Fill the device id */
00076     Copy.Buffer = EventEntry->Event.TargetDevice.DeviceIds;
00077     Status = RtlAppendUnicodeStringToString(&Copy, DeviceIds);
00078     if (!NT_SUCCESS(Status))
00079         return Status;
00080 
00081     InsertHeadList(&IopPnpEventQueueHead,
00082                    &EventEntry->ListEntry);
00083     KeSetEvent(&IopPnpNotifyEvent,
00084                0,
00085                FALSE);
00086 
00087     return STATUS_SUCCESS;
00088 }
00089 
00090 
00091 /*
00092  * Remove the current PnP event from the tail of the event queue
00093  * and signal IopPnpNotifyEvent if there is yet another event in the queue.
00094  */
00095 static NTSTATUS
00096 IopRemovePlugPlayEvent(VOID)
00097 {
00098     /* Remove a pnp event entry from the tail of the queue */
00099     if (!IsListEmpty(&IopPnpEventQueueHead))
00100     {
00101         ExFreePool(CONTAINING_RECORD(RemoveTailList(&IopPnpEventQueueHead), PNP_EVENT_ENTRY, ListEntry));
00102     }
00103 
00104     /* Signal the next pnp event in the queue */
00105     if (!IsListEmpty(&IopPnpEventQueueHead))
00106     {
00107         KeSetEvent(&IopPnpNotifyEvent,
00108                    0,
00109                    FALSE);
00110     }
00111 
00112     return STATUS_SUCCESS;
00113 }
00114 
00115 static PDEVICE_OBJECT
00116 IopTraverseDeviceNode(PDEVICE_NODE Node, PUNICODE_STRING DeviceInstance)
00117 {
00118     PDEVICE_OBJECT DeviceObject;
00119     PDEVICE_NODE ChildNode;
00120 
00121     if (RtlEqualUnicodeString(&Node->InstancePath,
00122                               DeviceInstance, TRUE))
00123     {
00124         ObReferenceObject(Node->PhysicalDeviceObject);
00125         return Node->PhysicalDeviceObject;
00126     }
00127 
00128     /* Traversal of all children nodes */
00129     for (ChildNode = Node->Child;
00130          ChildNode != NULL;
00131          ChildNode = ChildNode->Sibling)
00132     {
00133         DeviceObject = IopTraverseDeviceNode(ChildNode, DeviceInstance);
00134         if (DeviceObject != NULL)
00135         {
00136             return DeviceObject;
00137         }
00138     }
00139 
00140     return NULL;
00141 }
00142 
00143 
00144 PDEVICE_OBJECT
00145 IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
00146 {
00147     if (IopRootDeviceNode == NULL)
00148         return NULL;
00149 
00150     if (DeviceInstance == NULL ||
00151         DeviceInstance->Length == 0)
00152     {
00153         if (IopRootDeviceNode->PhysicalDeviceObject)
00154         {
00155             ObReferenceObject(IopRootDeviceNode->PhysicalDeviceObject);
00156             return IopRootDeviceNode->PhysicalDeviceObject;
00157         }
00158         else
00159             return NULL;
00160     }
00161 
00162     return IopTraverseDeviceNode(IopRootDeviceNode, DeviceInstance);
00163 
00164 }
00165 
00166 static NTSTATUS
00167 IopCaptureUnicodeString(PUNICODE_STRING DstName, PUNICODE_STRING SrcName)
00168 {
00169     NTSTATUS Status = STATUS_SUCCESS;
00170     UNICODE_STRING Name;
00171 
00172     Name.Buffer = NULL;
00173     _SEH2_TRY
00174     {
00175         Name.Length = SrcName->Length;
00176         Name.MaximumLength = SrcName->MaximumLength;
00177         if (Name.Length > Name.MaximumLength)
00178         {
00179             Status = STATUS_INVALID_PARAMETER;
00180             _SEH2_LEAVE;
00181         }
00182 
00183         if (Name.MaximumLength)
00184         {
00185             ProbeForRead(SrcName->Buffer,
00186                          Name.MaximumLength,
00187                          sizeof(WCHAR));
00188             Name.Buffer = ExAllocatePool(NonPagedPool, Name.MaximumLength);
00189             if (Name.Buffer == NULL)
00190             {
00191                 Status = STATUS_INSUFFICIENT_RESOURCES;
00192                 _SEH2_LEAVE;
00193             }
00194 
00195             memcpy(Name.Buffer, SrcName->Buffer, Name.MaximumLength);
00196         }
00197 
00198         *DstName = Name;
00199     }
00200     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00201     {
00202         if (Name.Buffer)
00203             ExFreePool(Name.Buffer);
00204         Status = _SEH2_GetExceptionCode();
00205     }
00206     _SEH2_END;
00207 
00208     return Status;
00209 }
00210 
00211 static NTSTATUS
00212 IopGetDeviceProperty(PPLUGPLAY_CONTROL_PROPERTY_DATA PropertyData)
00213 {
00214     PDEVICE_OBJECT DeviceObject = NULL;
00215     NTSTATUS Status;
00216     UNICODE_STRING DeviceInstance;
00217     ULONG BufferSize;
00218     ULONG Property = 0;
00219     PVOID Buffer;
00220 
00221     DPRINT("IopGetDeviceProperty() called\n");
00222     DPRINT("Device name: %wZ\n", &PropertyData->DeviceInstance);
00223 
00224     Status = IopCaptureUnicodeString(&DeviceInstance, &PropertyData->DeviceInstance);
00225     if (!NT_SUCCESS(Status))
00226     {
00227         return Status;
00228     }
00229 
00230     _SEH2_TRY
00231     {
00232         Property = PropertyData->Property;
00233         BufferSize = PropertyData->BufferSize;
00234         ProbeForWrite(PropertyData->Buffer,
00235                       BufferSize,
00236                       sizeof(UCHAR));
00237     }
00238     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00239     {
00240         ExFreePool(DeviceInstance.Buffer);
00241         _SEH2_YIELD(return _SEH2_GetExceptionCode());
00242     }
00243     _SEH2_END;
00244 
00245     /* Get the device object */
00246     DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
00247     ExFreePool(DeviceInstance.Buffer);
00248     if (DeviceObject == NULL)
00249     {
00250         return STATUS_NO_SUCH_DEVICE;
00251     }
00252 
00253     Buffer = ExAllocatePool(NonPagedPool, BufferSize);
00254     if (Buffer == NULL)
00255     {
00256         return STATUS_INSUFFICIENT_RESOURCES;
00257     }
00258 
00259     Status = IoGetDeviceProperty(DeviceObject,
00260                                  Property,
00261                                  BufferSize,
00262                                  Buffer,
00263                                  &BufferSize);
00264 
00265     ObDereferenceObject(DeviceObject);
00266 
00267     if (NT_SUCCESS(Status))
00268     {
00269         _SEH2_TRY
00270         {
00271             memcpy(PropertyData->Buffer, Buffer, BufferSize);
00272             PropertyData->BufferSize = BufferSize;
00273         }
00274         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00275         {
00276             Status = _SEH2_GetExceptionCode();
00277         }
00278         _SEH2_END;
00279     }
00280 
00281     ExFreePool(Buffer);
00282     return Status;
00283 }
00284 
00285 
00286 static NTSTATUS
00287 IopGetRelatedDevice(PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA RelatedDeviceData)
00288 {
00289     UNICODE_STRING RootDeviceName;
00290     PDEVICE_OBJECT DeviceObject = NULL;
00291     PDEVICE_NODE DeviceNode = NULL;
00292     PDEVICE_NODE RelatedDeviceNode;
00293     UNICODE_STRING TargetDeviceInstance;
00294     NTSTATUS Status = STATUS_SUCCESS;
00295     ULONG Relation = 0;
00296     ULONG MaximumLength = 0;
00297 
00298     DPRINT("IopGetRelatedDevice() called\n");
00299     DPRINT("Device name: %wZ\n", &RelatedDeviceData->TargetDeviceInstance);
00300 
00301     Status = IopCaptureUnicodeString(&TargetDeviceInstance, &RelatedDeviceData->TargetDeviceInstance);
00302     if (!NT_SUCCESS(Status))
00303     {
00304         return Status;
00305     }
00306 
00307     _SEH2_TRY
00308     {
00309         Relation = RelatedDeviceData->Relation;
00310         MaximumLength = RelatedDeviceData->RelatedDeviceInstanceLength;
00311         ProbeForWrite(RelatedDeviceData->RelatedDeviceInstance,
00312                       MaximumLength,
00313                       sizeof(WCHAR));
00314     }
00315     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00316     {
00317         ExFreePool(TargetDeviceInstance.Buffer);
00318         _SEH2_YIELD(return _SEH2_GetExceptionCode());
00319     }
00320     _SEH2_END;
00321 
00322     RtlInitUnicodeString(&RootDeviceName,
00323                          L"HTREE\\ROOT\\0");
00324     if (RtlEqualUnicodeString(&TargetDeviceInstance,
00325                               &RootDeviceName,
00326                               TRUE))
00327     {
00328         DeviceNode = IopRootDeviceNode;
00329         ExFreePool(TargetDeviceInstance.Buffer);
00330     }
00331     else
00332     {
00333         /* Get the device object */
00334         DeviceObject = IopGetDeviceObjectFromDeviceInstance(&TargetDeviceInstance);
00335         ExFreePool(TargetDeviceInstance.Buffer);
00336         if (DeviceObject == NULL)
00337             return STATUS_NO_SUCH_DEVICE;
00338 
00339         DeviceNode = ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode;
00340     }
00341 
00342     switch (Relation)
00343     {
00344         case PNP_GET_PARENT_DEVICE:
00345             RelatedDeviceNode = DeviceNode->Parent;
00346             break;
00347 
00348         case PNP_GET_CHILD_DEVICE:
00349             RelatedDeviceNode = DeviceNode->Child;
00350             break;
00351 
00352         case PNP_GET_SIBLING_DEVICE:
00353             RelatedDeviceNode = DeviceNode->Sibling;
00354             break;
00355 
00356         default:
00357             if (DeviceObject != NULL)
00358             {
00359                 ObDereferenceObject(DeviceObject);
00360             }
00361 
00362             return STATUS_INVALID_PARAMETER;
00363     }
00364 
00365     if (RelatedDeviceNode == NULL)
00366     {
00367         if (DeviceObject)
00368         {
00369             ObDereferenceObject(DeviceObject);
00370         }
00371 
00372         return STATUS_NO_SUCH_DEVICE;
00373     }
00374 
00375     if (RelatedDeviceNode->InstancePath.Length > MaximumLength)
00376     {
00377         if (DeviceObject)
00378         {
00379             ObDereferenceObject(DeviceObject);
00380         }
00381 
00382         return STATUS_BUFFER_TOO_SMALL;
00383     }
00384 
00385     /* Copy related device instance name */
00386     _SEH2_TRY
00387     {
00388         RtlCopyMemory(RelatedDeviceData->RelatedDeviceInstance,
00389                       RelatedDeviceNode->InstancePath.Buffer,
00390                       RelatedDeviceNode->InstancePath.Length);
00391         RelatedDeviceData->RelatedDeviceInstanceLength = RelatedDeviceNode->InstancePath.Length;
00392     }
00393     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00394     {
00395         Status = _SEH2_GetExceptionCode();
00396     }
00397     _SEH2_END;
00398 
00399     if (DeviceObject != NULL)
00400     {
00401         ObDereferenceObject(DeviceObject);
00402     }
00403 
00404     DPRINT("IopGetRelatedDevice() done\n");
00405 
00406     return Status;
00407 }
00408 
00409 static ULONG
00410 IopGetDeviceNodeStatus(PDEVICE_NODE DeviceNode)
00411 {
00412     ULONG Output = 0;
00413 
00414     if (DeviceNode->Parent == IopRootDeviceNode)
00415         Output |= DN_ROOT_ENUMERATED;
00416 
00417     if (DeviceNode->Flags & DNF_ADDED)
00418         Output |= DN_DRIVER_LOADED;
00419 
00420     /* FIXME: DN_ENUM_LOADED */
00421 
00422     if (DeviceNode->Flags & DNF_STARTED)
00423         Output |= DN_STARTED;
00424 
00425     /* FIXME: Manual */
00426 
00427     if (!(DeviceNode->Flags & DNF_PROCESSED))
00428         Output |= DN_NEED_TO_ENUM;
00429 
00430     /* DN_NOT_FIRST_TIME is 9x only */
00431 
00432     /* FIXME: DN_HARDWARE_ENUM */
00433 
00434     /* DN_LIAR and DN_HAS_MARK are 9x only */
00435 
00436     if (DeviceNode->Problem != 0)
00437         Output |= DN_HAS_PROBLEM;
00438 
00439     /* FIXME: DN_FILTERED */
00440 
00441     if (DeviceNode->Flags & DNF_LEGACY_DRIVER)
00442         Output |= DN_LEGACY_DRIVER;
00443 
00444     if (DeviceNode->UserFlags & DNUF_DONT_SHOW_IN_UI)
00445         Output |= DN_NO_SHOW_IN_DM;
00446 
00447     if (!(DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE))
00448         Output |= DN_DISABLEABLE;
00449 
00450     /* FIXME: Implement the rest */
00451 
00452     Output |= DN_NT_ENUMERATOR | DN_NT_DRIVER;
00453 
00454     return Output;
00455 }
00456 
00457 static NTSTATUS
00458 IopDeviceStatus(PPLUGPLAY_CONTROL_STATUS_DATA StatusData)
00459 {
00460     PDEVICE_OBJECT DeviceObject;
00461     PDEVICE_NODE DeviceNode;
00462     ULONG Operation = 0;
00463     ULONG DeviceStatus = 0;
00464     ULONG DeviceProblem = 0;
00465     UNICODE_STRING DeviceInstance;
00466     NTSTATUS Status;
00467 
00468     DPRINT("IopDeviceStatus() called\n");
00469 
00470     Status = IopCaptureUnicodeString(&DeviceInstance, &StatusData->DeviceInstance);
00471     if (!NT_SUCCESS(Status))
00472         return Status;
00473     DPRINT("Device name: '%wZ'\n", &DeviceInstance);
00474 
00475     _SEH2_TRY
00476     {
00477         Operation = StatusData->Operation;
00478         if (Operation == PNP_SET_DEVICE_STATUS)
00479         {
00480             DeviceStatus = StatusData->DeviceStatus;
00481             DeviceProblem = StatusData->DeviceProblem;
00482         }
00483     }
00484     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00485     {
00486         if (DeviceInstance.Buffer) ExFreePool(DeviceInstance.Buffer);
00487         _SEH2_YIELD(return _SEH2_GetExceptionCode());
00488     }
00489     _SEH2_END;
00490 
00491     /* Get the device object */
00492     DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
00493     ExFreePool(DeviceInstance.Buffer);
00494     if (DeviceObject == NULL)
00495         return STATUS_NO_SUCH_DEVICE;
00496 
00497     DeviceNode = IopGetDeviceNode(DeviceObject);
00498 
00499     switch (Operation)
00500     {
00501         case PNP_GET_DEVICE_STATUS:
00502             DPRINT("Get status data\n");
00503             DeviceStatus = IopGetDeviceNodeStatus(DeviceNode);
00504             DeviceProblem = DeviceNode->Problem;
00505             break;
00506 
00507         case PNP_SET_DEVICE_STATUS:
00508             DPRINT1("Set status data is NOT SUPPORTED\n");
00509             break;
00510 
00511         case PNP_CLEAR_DEVICE_STATUS:
00512             DPRINT1("FIXME: Clear status data!\n");
00513             break;
00514     }
00515 
00516     ObDereferenceObject(DeviceObject);
00517 
00518     if (Operation == PNP_GET_DEVICE_STATUS)
00519     {
00520         _SEH2_TRY
00521         {
00522             StatusData->DeviceStatus = DeviceStatus;
00523             StatusData->DeviceProblem = DeviceProblem;
00524         }
00525         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00526         {
00527             Status = _SEH2_GetExceptionCode();
00528         }
00529         _SEH2_END;
00530     }
00531 
00532     return Status;
00533 }
00534 
00535 
00536 static NTSTATUS
00537 IopGetDeviceDepth(PPLUGPLAY_CONTROL_DEPTH_DATA DepthData)
00538 {
00539     PDEVICE_OBJECT DeviceObject;
00540     PDEVICE_NODE DeviceNode;
00541     UNICODE_STRING DeviceInstance;
00542     NTSTATUS Status = STATUS_SUCCESS;
00543 
00544     DPRINT("IopGetDeviceDepth() called\n");
00545     DPRINT("Device name: %wZ\n", &DepthData->DeviceInstance);
00546 
00547     Status = IopCaptureUnicodeString(&DeviceInstance, &DepthData->DeviceInstance);
00548     if (!NT_SUCCESS(Status))
00549     {
00550         return Status;
00551     }
00552 
00553     /* Get the device object */
00554     DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
00555     ExFreePool(DeviceInstance.Buffer);
00556     if (DeviceObject == NULL)
00557         return STATUS_NO_SUCH_DEVICE;
00558 
00559     DeviceNode = IopGetDeviceNode(DeviceObject);
00560 
00561     _SEH2_TRY
00562     {
00563         DepthData->Depth = DeviceNode->Level;
00564     }
00565     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00566     {
00567         Status = _SEH2_GetExceptionCode();
00568     }
00569     _SEH2_END;
00570 
00571     ObDereferenceObject(DeviceObject);
00572 
00573     return Status;
00574 }
00575 
00576 
00577 static NTSTATUS
00578 IopResetDevice(PPLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData)
00579 {
00580     PDEVICE_OBJECT DeviceObject;
00581     PDEVICE_NODE DeviceNode;
00582     NTSTATUS Status = STATUS_SUCCESS;
00583     UNICODE_STRING DeviceInstance;
00584 
00585     Status = IopCaptureUnicodeString(&DeviceInstance, &ResetDeviceData->DeviceInstance);
00586     if (!NT_SUCCESS(Status))
00587         return Status;
00588 
00589     DPRINT("IopResetDevice(%wZ)\n", &DeviceInstance);
00590 
00591     /* Get the device object */
00592     DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance);
00593     ExFreePool(DeviceInstance.Buffer);
00594     if (DeviceObject == NULL)
00595         return STATUS_NO_SUCH_DEVICE;
00596 
00597     /* Get the device node */
00598     DeviceNode = IopGetDeviceNode(DeviceObject);
00599 
00600     ASSERT(DeviceNode->Flags & DNF_ENUMERATED);
00601     ASSERT(DeviceNode->Flags & DNF_PROCESSED);
00602 
00603     /* Check if there's already a driver loaded for this device */
00604     if (DeviceNode->Flags & DNF_ADDED)
00605     {
00606 #if 0
00607         /* Remove the device node */
00608         Status = IopRemoveDevice(DeviceNode);
00609         if (NT_SUCCESS(Status))
00610         {
00611             /* Invalidate device relations for the parent to reenumerate the device */
00612             DPRINT1("A new driver will be loaded for '%wZ' (FDO above removed)\n", &DeviceNode->InstancePath);
00613             Status = IoSynchronousInvalidateDeviceRelations(DeviceNode->Parent->PhysicalDeviceObject, BusRelations);
00614         }
00615         else
00616 #endif
00617         {
00618             /* A driver has already been loaded for this device */
00619             DPRINT1("A reboot is required for the current driver for '%wZ' to be replaced\n", &DeviceNode->InstancePath);
00620             DeviceNode->Problem = CM_PROB_NEED_RESTART;
00621         }
00622     }
00623     else
00624     {
00625         /* FIXME: What if the device really is disabled? */
00626         DeviceNode->Flags &= ~DNF_DISABLED;
00627         DeviceNode->Problem = 0;
00628 
00629         /* Load service data from the registry */
00630         Status = IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
00631 
00632         if (NT_SUCCESS(Status))
00633         {
00634             /* Start the service and begin PnP initialization of the device again */
00635             DPRINT1("A new driver will be loaded for '%wZ' (no FDO above)\n", &DeviceNode->InstancePath);
00636             Status = IopActionInitChildServices(DeviceNode, DeviceNode->Parent);
00637         }
00638     }
00639 
00640     ObDereferenceObject(DeviceObject);
00641 
00642     return Status;
00643 }
00644 
00645 /* PUBLIC FUNCTIONS **********************************************************/
00646 
00647 /*
00648  * Plug and Play event structure used by NtGetPlugPlayEvent.
00649  *
00650  * EventGuid
00651  *    Can be one of the following values:
00652  *       GUID_HWPROFILE_QUERY_CHANGE
00653  *       GUID_HWPROFILE_CHANGE_CANCELLED
00654  *       GUID_HWPROFILE_CHANGE_COMPLETE
00655  *       GUID_TARGET_DEVICE_QUERY_REMOVE
00656  *       GUID_TARGET_DEVICE_REMOVE_CANCELLED
00657  *       GUID_TARGET_DEVICE_REMOVE_COMPLETE
00658  *       GUID_PNP_CUSTOM_NOTIFICATION
00659  *       GUID_PNP_POWER_NOTIFICATION
00660  *       GUID_DEVICE_* (see above)
00661  *
00662  * EventCategory
00663  *    Type of the event that happened.
00664  *
00665  * Result
00666  *    ?
00667  *
00668  * Flags
00669  *    ?
00670  *
00671  * TotalSize
00672  *    Size of the event block including the device IDs and other
00673  *    per category specific fields.
00674  */
00675 
00676 /*
00677  * NtGetPlugPlayEvent
00678  *
00679  * Returns one Plug & Play event from a global queue.
00680  *
00681  * Parameters
00682  *    Reserved1
00683  *    Reserved2
00684  *       Always set to zero.
00685  *
00686  *    Buffer
00687  *       The buffer that will be filled with the event information on
00688  *       successful return from the function.
00689  *
00690  *    BufferSize
00691  *       Size of the buffer pointed by the Buffer parameter. If the
00692  *       buffer size is not large enough to hold the whole event
00693  *       information, error STATUS_BUFFER_TOO_SMALL is returned and
00694  *       the buffer remains untouched.
00695  *
00696  * Return Values
00697  *    STATUS_PRIVILEGE_NOT_HELD
00698  *    STATUS_BUFFER_TOO_SMALL
00699  *    STATUS_SUCCESS
00700  *
00701  * Remarks
00702  *    This function isn't multi-thread safe!
00703  *
00704  * @implemented
00705  */
00706 NTSTATUS
00707 NTAPI
00708 NtGetPlugPlayEvent(IN ULONG Reserved1,
00709                    IN ULONG Reserved2,
00710                    OUT PPLUGPLAY_EVENT_BLOCK Buffer,
00711                    IN ULONG BufferSize)
00712 {
00713     PPNP_EVENT_ENTRY Entry;
00714     NTSTATUS Status;
00715 
00716     DPRINT("NtGetPlugPlayEvent() called\n");
00717 
00718     /* Function can only be called from user-mode */
00719     if (KeGetPreviousMode() == KernelMode)
00720     {
00721         DPRINT1("NtGetPlugPlayEvent cannot be called from kernel mode!\n");
00722         return STATUS_ACCESS_DENIED;
00723     }
00724 
00725     /* Check for Tcb privilege */
00726     if (!SeSinglePrivilegeCheck(SeTcbPrivilege,
00727                                 UserMode))
00728     {
00729         DPRINT1("NtGetPlugPlayEvent: Caller does not hold the SeTcbPrivilege privilege!\n");
00730         return STATUS_PRIVILEGE_NOT_HELD;
00731     }
00732 
00733     /* Wait for a PnP event */
00734     DPRINT("Waiting for pnp notification event\n");
00735     Status = KeWaitForSingleObject(&IopPnpNotifyEvent,
00736                                    UserRequest,
00737                                    KernelMode,
00738                                    FALSE,
00739                                    NULL);
00740     if (!NT_SUCCESS(Status))
00741     {
00742         DPRINT1("KeWaitForSingleObject() failed (Status %lx)\n", Status);
00743         return Status;
00744     }
00745 
00746     /* Get entry from the tail of the queue */
00747     Entry = CONTAINING_RECORD(IopPnpEventQueueHead.Blink,
00748                               PNP_EVENT_ENTRY,
00749                               ListEntry);
00750 
00751     /* Check the buffer size */
00752     if (BufferSize < Entry->Event.TotalSize)
00753     {
00754         DPRINT1("Buffer is too small for the pnp-event\n");
00755         return STATUS_BUFFER_TOO_SMALL;
00756     }
00757 
00758     /* Copy event data to the user buffer */
00759     memcpy(Buffer,
00760            &Entry->Event,
00761            Entry->Event.TotalSize);
00762 
00763     DPRINT("NtGetPlugPlayEvent() done\n");
00764 
00765     return STATUS_SUCCESS;
00766 }
00767 
00768 /*
00769  * NtPlugPlayControl
00770  *
00771  * A function for doing various Plug & Play operations from user mode.
00772  *
00773  * Parameters
00774  *    PlugPlayControlClass
00775  *       0x00   Reenumerate device tree
00776  *
00777  *              Buffer points to UNICODE_STRING decribing the instance
00778  *              path (like "HTREE\ROOT\0" or "Root\ACPI_HAL\0000"). For
00779  *              more information about instance paths see !devnode command
00780  *              in kernel debugger or look at "Inside Windows 2000" book,
00781  *              chapter "Driver Loading, Initialization, and Installation".
00782  *
00783  *       0x01   Register new device
00784  *       0x02   Deregister device
00785  *       0x03   Initialize device
00786  *       0x04   Start device
00787  *       0x06   Query and remove device
00788  *       0x07   User response
00789  *
00790  *              Called after processing the message from NtGetPlugPlayEvent.
00791  *
00792  *       0x08   Generate legacy device
00793  *       0x09   Get interface device list
00794  *       0x0A   Get property data
00795  *       0x0B   Device class association (Registration)
00796  *       0x0C   Get related device
00797  *       0x0D   Get device interface alias
00798  *       0x0E   Get/set/clear device status
00799  *       0x0F   Get device depth
00800  *       0x10   Query device relations
00801  *       0x11   Query target device relation
00802  *       0x12   Query conflict list
00803  *       0x13   Retrieve dock data
00804  *       0x14   Reset device
00805  *       0x15   Halt device
00806  *       0x16   Get blocked driver data
00807  *
00808  *    Buffer
00809  *       The buffer contains information that is specific to each control
00810  *       code. The buffer is read-only.
00811  *
00812  *    BufferSize
00813  *       Size of the buffer pointed by the Buffer parameter. If the
00814  *       buffer size specifies incorrect value for specified control
00815  *       code, error ??? is returned.
00816  *
00817  * Return Values
00818  *    STATUS_PRIVILEGE_NOT_HELD
00819  *    STATUS_SUCCESS
00820  *    ...
00821  *
00822  * @unimplemented
00823  */
00824 NTSTATUS
00825 NTAPI
00826 NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass,
00827                   IN OUT PVOID Buffer,
00828                   IN ULONG BufferLength)
00829 {
00830     DPRINT("NtPlugPlayControl(%lu %p %lu) called\n",
00831            PlugPlayControlClass, Buffer, BufferLength);
00832 
00833     /* Function can only be called from user-mode */
00834     if (KeGetPreviousMode() == KernelMode)
00835     {
00836         DPRINT1("NtGetPlugPlayEvent cannot be called from kernel mode!\n");
00837         return STATUS_ACCESS_DENIED;
00838     }
00839 
00840     /* Check for Tcb privilege */
00841     if (!SeSinglePrivilegeCheck(SeTcbPrivilege,
00842                                 UserMode))
00843     {
00844         DPRINT1("NtGetPlugPlayEvent: Caller does not hold the SeTcbPrivilege privilege!\n");
00845         return STATUS_PRIVILEGE_NOT_HELD;
00846     }
00847 
00848     /* Probe the buffer */
00849     _SEH2_TRY
00850     {
00851         ProbeForWrite(Buffer,
00852                       BufferLength,
00853                       sizeof(ULONG));
00854     }
00855     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00856     {
00857         _SEH2_YIELD(return _SEH2_GetExceptionCode());
00858     }
00859     _SEH2_END;
00860 
00861     switch (PlugPlayControlClass)
00862     {
00863         case PlugPlayControlUserResponse:
00864             if (Buffer || BufferLength != 0)
00865                 return STATUS_INVALID_PARAMETER;
00866             return IopRemovePlugPlayEvent();
00867 
00868         case PlugPlayControlProperty:
00869             if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA))
00870                 return STATUS_INVALID_PARAMETER;
00871             return IopGetDeviceProperty((PPLUGPLAY_CONTROL_PROPERTY_DATA)Buffer);
00872 
00873         case PlugPlayControlGetRelatedDevice:
00874             if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA))
00875                 return STATUS_INVALID_PARAMETER;
00876             return IopGetRelatedDevice((PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA)Buffer);
00877 
00878         case PlugPlayControlDeviceStatus:
00879             if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_STATUS_DATA))
00880                 return STATUS_INVALID_PARAMETER;
00881             return IopDeviceStatus((PPLUGPLAY_CONTROL_STATUS_DATA)Buffer);
00882 
00883         case PlugPlayControlGetDeviceDepth:
00884             if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_DEPTH_DATA))
00885                 return STATUS_INVALID_PARAMETER;
00886             return IopGetDeviceDepth((PPLUGPLAY_CONTROL_DEPTH_DATA)Buffer);
00887 
00888         case PlugPlayControlResetDevice:
00889             if (!Buffer || BufferLength < sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA))
00890                 return STATUS_INVALID_PARAMETER;
00891             return IopResetDevice((PPLUGPLAY_CONTROL_RESET_DEVICE_DATA)Buffer);
00892 
00893         default:
00894             return STATUS_NOT_IMPLEMENTED;
00895     }
00896 
00897     return STATUS_NOT_IMPLEMENTED;
00898 }

Generated on Thu May 24 2012 04:37:43 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.