Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenplugplay.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
1.7.6.1
|