xref: /reactos/ntoskrnl/io/pnpmgr/pnpreport.c (revision 176de8bd)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS Kernel
3c2c66affSColin Finck  * COPYRIGHT:       GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:            ntoskrnl/io/pnpmgr/pnpreport.c
5c2c66affSColin Finck  * PURPOSE:         Device Changes Reporting Functions
6c2c66affSColin Finck  * PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
7c2c66affSColin Finck  *                  Pierre Schweitzer
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10c2c66affSColin Finck /* INCLUDES ******************************************************************/
11c2c66affSColin Finck 
12c2c66affSColin Finck #include <ntoskrnl.h>
13c2c66affSColin Finck #define NDEBUG
14c2c66affSColin Finck #include <debug.h>
15c2c66affSColin Finck 
16c2c66affSColin Finck /* TYPES *******************************************************************/
17c2c66affSColin Finck 
18c2c66affSColin Finck typedef struct _INTERNAL_WORK_QUEUE_ITEM
19c2c66affSColin Finck {
20c2c66affSColin Finck     WORK_QUEUE_ITEM WorkItem;
21c2c66affSColin Finck     PDEVICE_OBJECT PhysicalDeviceObject;
22c2c66affSColin Finck     PDEVICE_CHANGE_COMPLETE_CALLBACK Callback;
23c2c66affSColin Finck     PVOID Context;
24*176de8bdSTimo Kreuzer     TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure;
25c2c66affSColin Finck } INTERNAL_WORK_QUEUE_ITEM, *PINTERNAL_WORK_QUEUE_ITEM;
26c2c66affSColin Finck 
27c2c66affSColin Finck NTSTATUS
28c2c66affSColin Finck IopSetDeviceInstanceData(HANDLE InstanceKey,
29c2c66affSColin Finck                          PDEVICE_NODE DeviceNode);
30c2c66affSColin Finck 
31c2c66affSColin Finck NTSTATUS
32c2c66affSColin Finck PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject,
33c2c66affSColin Finck                        IN OUT PKEVENT SyncEvent OPTIONAL,
34c2c66affSColin Finck                        IN OUT PNTSTATUS SyncStatus OPTIONAL,
35c2c66affSColin Finck                        IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL,
36c2c66affSColin Finck                        IN PVOID Context OPTIONAL,
37c2c66affSColin Finck                        IN PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure);
38c2c66affSColin Finck 
39c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/
40c2c66affSColin Finck 
41c2c66affSColin Finck PWCHAR
IopGetInterfaceTypeString(INTERFACE_TYPE IfType)42c2c66affSColin Finck IopGetInterfaceTypeString(INTERFACE_TYPE IfType)
43c2c66affSColin Finck {
44c2c66affSColin Finck     switch (IfType)
45c2c66affSColin Finck     {
46c2c66affSColin Finck         case Internal:
47c2c66affSColin Finck             return L"Internal";
48c2c66affSColin Finck 
49c2c66affSColin Finck         case Isa:
50c2c66affSColin Finck             return L"Isa";
51c2c66affSColin Finck 
52c2c66affSColin Finck         case Eisa:
53c2c66affSColin Finck             return L"Eisa";
54c2c66affSColin Finck 
55c2c66affSColin Finck         case MicroChannel:
56c2c66affSColin Finck             return L"MicroChannel";
57c2c66affSColin Finck 
58c2c66affSColin Finck         case TurboChannel:
59c2c66affSColin Finck             return L"TurboChannel";
60c2c66affSColin Finck 
61c2c66affSColin Finck         case PCIBus:
62c2c66affSColin Finck             return L"PCIBus";
63c2c66affSColin Finck 
64c2c66affSColin Finck         case VMEBus:
65c2c66affSColin Finck             return L"VMEBus";
66c2c66affSColin Finck 
67c2c66affSColin Finck         case NuBus:
68c2c66affSColin Finck             return L"NuBus";
69c2c66affSColin Finck 
70c2c66affSColin Finck         case PCMCIABus:
71c2c66affSColin Finck             return L"PCMCIABus";
72c2c66affSColin Finck 
73c2c66affSColin Finck         case CBus:
74c2c66affSColin Finck             return L"CBus";
75c2c66affSColin Finck 
76c2c66affSColin Finck         case MPIBus:
77c2c66affSColin Finck             return L"MPIBus";
78c2c66affSColin Finck 
79c2c66affSColin Finck         case MPSABus:
80c2c66affSColin Finck             return L"MPSABus";
81c2c66affSColin Finck 
82c2c66affSColin Finck         case ProcessorInternal:
83c2c66affSColin Finck             return L"ProcessorInternal";
84c2c66affSColin Finck 
85c2c66affSColin Finck         case PNPISABus:
86c2c66affSColin Finck             return L"PNPISABus";
87c2c66affSColin Finck 
88c2c66affSColin Finck         case PNPBus:
89c2c66affSColin Finck             return L"PNPBus";
90c2c66affSColin Finck 
91c2c66affSColin Finck         case Vmcs:
92c2c66affSColin Finck             return L"Vmcs";
93c2c66affSColin Finck 
94c2c66affSColin Finck         default:
95c2c66affSColin Finck             DPRINT1("Invalid bus type: %d\n", IfType);
96c2c66affSColin Finck             return NULL;
97c2c66affSColin Finck     }
98c2c66affSColin Finck }
99c2c66affSColin Finck 
100c2c66affSColin Finck VOID
101c2c66affSColin Finck NTAPI
IopReportTargetDeviceChangeAsyncWorker(PVOID Context)102c2c66affSColin Finck IopReportTargetDeviceChangeAsyncWorker(PVOID Context)
103c2c66affSColin Finck {
104c2c66affSColin Finck     PINTERNAL_WORK_QUEUE_ITEM Item;
105c2c66affSColin Finck 
106c2c66affSColin Finck     Item = (PINTERNAL_WORK_QUEUE_ITEM)Context;
107*176de8bdSTimo Kreuzer     PpSetCustomTargetEvent(Item->PhysicalDeviceObject, NULL, NULL, Item->Callback, Item->Context, &Item->NotificationStructure);
108c2c66affSColin Finck     ObDereferenceObject(Item->PhysicalDeviceObject);
109c2c66affSColin Finck     ExFreePoolWithTag(Context, '  pP');
110c2c66affSColin Finck }
111c2c66affSColin Finck 
112c2c66affSColin Finck NTSTATUS
PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject,IN OUT PKEVENT SyncEvent OPTIONAL,IN OUT PNTSTATUS SyncStatus OPTIONAL,IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL,IN PVOID Context OPTIONAL,IN PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure)113c2c66affSColin Finck PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject,
114c2c66affSColin Finck                        IN OUT PKEVENT SyncEvent OPTIONAL,
115c2c66affSColin Finck                        IN OUT PNTSTATUS SyncStatus OPTIONAL,
116c2c66affSColin Finck                        IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL,
117c2c66affSColin Finck                        IN PVOID Context OPTIONAL,
118c2c66affSColin Finck                        IN PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure)
119c2c66affSColin Finck {
120c2c66affSColin Finck     ASSERT(NotificationStructure != NULL);
121c2c66affSColin Finck     ASSERT(DeviceObject != NULL);
122c2c66affSColin Finck 
123c2c66affSColin Finck     if (SyncEvent)
124c2c66affSColin Finck     {
125c2c66affSColin Finck         ASSERT(SyncStatus);
126c2c66affSColin Finck         *SyncStatus = STATUS_PENDING;
127c2c66affSColin Finck     }
128c2c66affSColin Finck 
129c2c66affSColin Finck     /* That call is totally wrong but notifications handler must be fixed first */
130582ca686SVictor Perevertkin     PiNotifyTargetDeviceChange(&GUID_PNP_CUSTOM_NOTIFICATION, DeviceObject, NotificationStructure);
131c2c66affSColin Finck 
132c2c66affSColin Finck     if (SyncEvent)
133c2c66affSColin Finck     {
134c2c66affSColin Finck         KeSetEvent(SyncEvent, IO_NO_INCREMENT, FALSE);
135c2c66affSColin Finck         *SyncStatus = STATUS_SUCCESS;
136c2c66affSColin Finck     }
137c2c66affSColin Finck 
138c2c66affSColin Finck     return STATUS_SUCCESS;
139c2c66affSColin Finck }
140c2c66affSColin Finck 
141c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/
142c2c66affSColin Finck 
143c2c66affSColin Finck /*
144c2c66affSColin Finck  * @implemented
145c2c66affSColin Finck  */
146c2c66affSColin Finck NTSTATUS
147c2c66affSColin Finck NTAPI
IoReportDetectedDevice(_In_ PDRIVER_OBJECT DriverObject,_In_ INTERFACE_TYPE LegacyBusType,_In_ ULONG BusNumber,_In_ ULONG SlotNumber,_In_opt_ PCM_RESOURCE_LIST ResourceList,_In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements,_In_ BOOLEAN ResourceAssigned,_Inout_ PDEVICE_OBJECT * DeviceObject)148798fc13bSVictor Perevertkin IoReportDetectedDevice(
149798fc13bSVictor Perevertkin     _In_ PDRIVER_OBJECT DriverObject,
150798fc13bSVictor Perevertkin     _In_ INTERFACE_TYPE LegacyBusType,
151798fc13bSVictor Perevertkin     _In_ ULONG BusNumber,
152798fc13bSVictor Perevertkin     _In_ ULONG SlotNumber,
153798fc13bSVictor Perevertkin     _In_opt_ PCM_RESOURCE_LIST ResourceList,
154798fc13bSVictor Perevertkin     _In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements,
155798fc13bSVictor Perevertkin     _In_ BOOLEAN ResourceAssigned,
156798fc13bSVictor Perevertkin     _Inout_ PDEVICE_OBJECT *DeviceObject)
157c2c66affSColin Finck {
158d380e977SHervé Poussineau     UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control");
159d380e977SHervé Poussineau     UNICODE_STRING DeviceReportedName = RTL_CONSTANT_STRING(L"DeviceReported");
160d380e977SHervé Poussineau     OBJECT_ATTRIBUTES ObjectAttributes;
161c2c66affSColin Finck     PDEVICE_NODE DeviceNode;
162c2c66affSColin Finck     PDEVICE_OBJECT Pdo;
163c2c66affSColin Finck     NTSTATUS Status;
164d380e977SHervé Poussineau     HANDLE InstanceKey, ControlKey;
165e616a456SHermès Bélusca-Maïto     UNICODE_STRING ValueName, ServiceLongName, ServiceName;
166c2c66affSColin Finck     WCHAR HardwareId[256];
167c2c66affSColin Finck     PWCHAR IfString;
168c2c66affSColin Finck     ULONG IdLength;
169e616a456SHermès Bélusca-Maïto     ULONG LegacyValue;
170d380e977SHervé Poussineau     ULONG DeviceReported = 1;
171c2c66affSColin Finck 
172c2c66affSColin Finck     DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n",
173c2c66affSColin Finck            DeviceObject, DeviceObject ? *DeviceObject : NULL);
174c2c66affSColin Finck 
175e616a456SHermès Bélusca-Maïto     ServiceLongName = DriverObject->DriverExtension->ServiceKeyName;
176e616a456SHermès Bélusca-Maïto     ServiceName = ServiceLongName;
177c2c66affSColin Finck 
178c2c66affSColin Finck     /* If the interface type is unknown, treat it as internal */
179c2c66affSColin Finck     if (LegacyBusType == InterfaceTypeUndefined)
180c2c66affSColin Finck         LegacyBusType = Internal;
181c2c66affSColin Finck 
182c2c66affSColin Finck     /* Get the string equivalent of the interface type */
183c2c66affSColin Finck     IfString = IopGetInterfaceTypeString(LegacyBusType);
184c2c66affSColin Finck 
185c2c66affSColin Finck     /* If NULL is returned then it's a bad type */
186c2c66affSColin Finck     if (!IfString)
187c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
188c2c66affSColin Finck 
189e616a456SHermès Bélusca-Maïto     /*
190e616a456SHermès Bélusca-Maïto      * Drivers that have been created via a direct IoCreateDriver() call
191e616a456SHermès Bélusca-Maïto      * have their ServiceKeyName set to \Driver\DriverName. We need to
192e616a456SHermès Bélusca-Maïto      * strip everything up to the last path separator and keep what remains.
193e616a456SHermès Bélusca-Maïto      */
194e616a456SHermès Bélusca-Maïto     if (DriverObject->Flags & DRVO_BUILTIN_DRIVER)
195e616a456SHermès Bélusca-Maïto     {
196e616a456SHermès Bélusca-Maïto         /*
197e616a456SHermès Bélusca-Maïto          * Find the last path separator.
198e616a456SHermès Bélusca-Maïto          * NOTE: Since ServiceName is not necessarily NULL-terminated,
199e616a456SHermès Bélusca-Maïto          * we cannot use wcsrchr().
200e616a456SHermès Bélusca-Maïto          */
201e616a456SHermès Bélusca-Maïto         if (ServiceName.Buffer && ServiceName.Length >= sizeof(WCHAR))
202e616a456SHermès Bélusca-Maïto         {
203e616a456SHermès Bélusca-Maïto             ValueName.Length = 1;
204e616a456SHermès Bélusca-Maïto             ValueName.Buffer = ServiceName.Buffer + (ServiceName.Length / sizeof(WCHAR)) - 1;
205e616a456SHermès Bélusca-Maïto 
206e616a456SHermès Bélusca-Maïto             while ((ValueName.Buffer > ServiceName.Buffer) && (*ValueName.Buffer != L'\\'))
207e616a456SHermès Bélusca-Maïto             {
208e616a456SHermès Bélusca-Maïto                 --ValueName.Buffer;
209e616a456SHermès Bélusca-Maïto                 ++ValueName.Length;
210e616a456SHermès Bélusca-Maïto             }
211e616a456SHermès Bélusca-Maïto             if (*ValueName.Buffer == L'\\')
212e616a456SHermès Bélusca-Maïto             {
213e616a456SHermès Bélusca-Maïto                 ++ValueName.Buffer;
214e616a456SHermès Bélusca-Maïto                 --ValueName.Length;
215e616a456SHermès Bélusca-Maïto             }
216e616a456SHermès Bélusca-Maïto             ValueName.Length *= sizeof(WCHAR);
217e616a456SHermès Bélusca-Maïto 
218e616a456SHermès Bélusca-Maïto             /* Shorten the string */
219e616a456SHermès Bélusca-Maïto             ServiceName.MaximumLength -= (ServiceName.Length - ValueName.Length);
220e616a456SHermès Bélusca-Maïto             ServiceName.Length = ValueName.Length;
221e616a456SHermès Bélusca-Maïto             ServiceName.Buffer = ValueName.Buffer;
222e616a456SHermès Bélusca-Maïto         }
223e616a456SHermès Bélusca-Maïto     }
224e616a456SHermès Bélusca-Maïto 
225c2c66affSColin Finck     /* We use the caller's PDO if they supplied one */
2266cac5b8cSVictor Perevertkin     UNICODE_STRING instancePath = {0};
227c2c66affSColin Finck     if (DeviceObject && *DeviceObject)
228c2c66affSColin Finck     {
229c2c66affSColin Finck         Pdo = *DeviceObject;
230c2c66affSColin Finck     }
231c2c66affSColin Finck     else
232c2c66affSColin Finck     {
233c2c66affSColin Finck         /* Create the PDO */
2346cac5b8cSVictor Perevertkin         Status = PnpRootCreateDevice(&ServiceName, &Pdo, &instancePath);
235c2c66affSColin Finck         if (!NT_SUCCESS(Status))
236c2c66affSColin Finck         {
237c2c66affSColin Finck             DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status);
238c2c66affSColin Finck             return Status;
239c2c66affSColin Finck         }
240c2c66affSColin Finck     }
241c2c66affSColin Finck 
242c2c66affSColin Finck     /* Create the device node for the new PDO */
2436f0e37b0SVictor Perevertkin     DeviceNode = PipAllocateDeviceNode(Pdo);
2446f0e37b0SVictor Perevertkin     if (!DeviceNode)
245c2c66affSColin Finck     {
2466f0e37b0SVictor Perevertkin         DPRINT("PipAllocateDeviceNode() failed\n");
2476f0e37b0SVictor Perevertkin         return STATUS_INSUFFICIENT_RESOURCES;
248c2c66affSColin Finck     }
249c2c66affSColin Finck 
2506cac5b8cSVictor Perevertkin     // The string comes from PnpRootCreateDevice, so it can be used right away
2516cac5b8cSVictor Perevertkin     DeviceNode->InstancePath = instancePath;
252c2c66affSColin Finck 
253c2c66affSColin Finck     /* Open a handle to the instance path key */
254e2cb7b50SHermès Bélusca-Maïto     Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
255c2c66affSColin Finck     if (!NT_SUCCESS(Status))
256c2c66affSColin Finck         return Status;
257c2c66affSColin Finck 
258e616a456SHermès Bélusca-Maïto     /* Save the driver name */
259e616a456SHermès Bélusca-Maïto     RtlInitUnicodeString(&ValueName, L"Service");
260e616a456SHermès Bélusca-Maïto     Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_SZ, ServiceLongName.Buffer, ServiceLongName.Length + sizeof(UNICODE_NULL));
261e616a456SHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
262e616a456SHermès Bélusca-Maïto     {
263e616a456SHermès Bélusca-Maïto         DPRINT("Failed to write the Service name value: 0x%x\n", Status);
264e616a456SHermès Bélusca-Maïto     }
265e616a456SHermès Bélusca-Maïto 
266e616a456SHermès Bélusca-Maïto     /* Report as non-legacy driver */
267e616a456SHermès Bélusca-Maïto     RtlInitUnicodeString(&ValueName, L"Legacy");
268e616a456SHermès Bélusca-Maïto     LegacyValue = 0;
269e616a456SHermès Bélusca-Maïto     Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
270e616a456SHermès Bélusca-Maïto     if (!NT_SUCCESS(Status))
271e616a456SHermès Bélusca-Maïto     {
272e616a456SHermès Bélusca-Maïto         DPRINT("Failed to write the Legacy value: 0x%x\n", Status);
273e616a456SHermès Bélusca-Maïto     }
274d380e977SHervé Poussineau     Status = ZwSetValueKey(InstanceKey, &DeviceReportedName, 0, REG_DWORD, &DeviceReported, sizeof(DeviceReported));
275d380e977SHervé Poussineau     if (!NT_SUCCESS(Status))
276d380e977SHervé Poussineau     {
277d380e977SHervé Poussineau         DPRINT("Failed to write the DeviceReported value: 0x%x\n", Status);
278d380e977SHervé Poussineau     }
279d380e977SHervé Poussineau 
280d380e977SHervé Poussineau     /* Set DeviceReported=1 in Control subkey */
281d380e977SHervé Poussineau     InitializeObjectAttributes(&ObjectAttributes,
282d380e977SHervé Poussineau                                &Control,
283d380e977SHervé Poussineau                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
284d380e977SHervé Poussineau                                InstanceKey,
285d380e977SHervé Poussineau                                NULL);
286d380e977SHervé Poussineau     Status = ZwCreateKey(&ControlKey,
287d380e977SHervé Poussineau                          KEY_SET_VALUE,
288d380e977SHervé Poussineau                          &ObjectAttributes,
289d380e977SHervé Poussineau                          0,
290d380e977SHervé Poussineau                          NULL,
291d380e977SHervé Poussineau                          REG_OPTION_VOLATILE,
292d380e977SHervé Poussineau                          NULL);
293d380e977SHervé Poussineau     if (NT_SUCCESS(Status))
294d380e977SHervé Poussineau     {
295d380e977SHervé Poussineau         Status = ZwSetValueKey(ControlKey,
296d380e977SHervé Poussineau                                &DeviceReportedName,
297d380e977SHervé Poussineau                                0,
298d380e977SHervé Poussineau                                REG_DWORD,
299d380e977SHervé Poussineau                                &DeviceReported,
300d380e977SHervé Poussineau                                sizeof(DeviceReported));
301d380e977SHervé Poussineau         ZwClose(ControlKey);
302d380e977SHervé Poussineau     }
303d380e977SHervé Poussineau     if (!NT_SUCCESS(Status))
304d380e977SHervé Poussineau     {
305d380e977SHervé Poussineau         DPRINT1("Failed to set ReportedDevice=1 for device %wZ (status 0x%08lx)\n", &instancePath, Status);
306d380e977SHervé Poussineau     }
307e616a456SHermès Bélusca-Maïto 
308c2c66affSColin Finck     /* Add DETECTEDInterfaceType\DriverName */
309c2c66affSColin Finck     IdLength = 0;
310c2c66affSColin Finck     IdLength += swprintf(&HardwareId[IdLength],
311c2c66affSColin Finck                          L"DETECTED%ls\\%wZ",
312c2c66affSColin Finck                          IfString,
313c2c66affSColin Finck                          &ServiceName);
314c2c66affSColin Finck     IdLength++;
315c2c66affSColin Finck 
316c2c66affSColin Finck     /* Add DETECTED\DriverName */
317c2c66affSColin Finck     IdLength += swprintf(&HardwareId[IdLength],
318c2c66affSColin Finck                          L"DETECTED\\%wZ",
319c2c66affSColin Finck                          &ServiceName);
320c2c66affSColin Finck     IdLength++;
321c2c66affSColin Finck 
322c2c66affSColin Finck     /* Terminate the string with another null */
323c2c66affSColin Finck     HardwareId[IdLength++] = UNICODE_NULL;
324c2c66affSColin Finck 
325c2c66affSColin Finck     /* Store the value for CompatibleIDs */
326c2c66affSColin Finck     RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
327c2c66affSColin Finck     Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, HardwareId, IdLength * sizeof(WCHAR));
328c2c66affSColin Finck     if (!NT_SUCCESS(Status))
329c2c66affSColin Finck     {
330c2c66affSColin Finck         DPRINT("Failed to write the compatible IDs: 0x%x\n", Status);
331c2c66affSColin Finck         ZwClose(InstanceKey);
332c2c66affSColin Finck         return Status;
333c2c66affSColin Finck     }
334c2c66affSColin Finck 
3350fed07b7SVictor Perevertkin     // Set the device's DeviceDesc and LocationInformation fields
3360fed07b7SVictor Perevertkin     PiSetDevNodeText(DeviceNode, InstanceKey);
3370fed07b7SVictor Perevertkin 
338c2c66affSColin Finck     /* Assign the resources to the device node */
339c2c66affSColin Finck     DeviceNode->BootResources = ResourceList;
340c2c66affSColin Finck     DeviceNode->ResourceRequirements = ResourceRequirements;
341c2c66affSColin Finck 
342c2c66affSColin Finck     /* Set appropriate flags */
343c2c66affSColin Finck     if (DeviceNode->BootResources)
344c2c66affSColin Finck         IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG);
345c2c66affSColin Finck 
346c2c66affSColin Finck     if (!DeviceNode->ResourceRequirements && !DeviceNode->BootResources)
347c2c66affSColin Finck         IopDeviceNodeSetFlag(DeviceNode, DNF_NO_RESOURCE_REQUIRED);
348c2c66affSColin Finck 
349c2c66affSColin Finck     /* Write the resource information to the registry */
350c2c66affSColin Finck     IopSetDeviceInstanceData(InstanceKey, DeviceNode);
351c2c66affSColin Finck 
352c2c66affSColin Finck     /* If the caller didn't get the resources assigned for us, do it now */
353c2c66affSColin Finck     if (!ResourceAssigned)
354c2c66affSColin Finck     {
355c2c66affSColin Finck         Status = IopAssignDeviceResources(DeviceNode);
356c2c66affSColin Finck 
357c2c66affSColin Finck         /* See if we failed */
358c2c66affSColin Finck         if (!NT_SUCCESS(Status))
359c2c66affSColin Finck         {
360c2c66affSColin Finck             DPRINT("Assigning resources failed: 0x%x\n", Status);
361c2c66affSColin Finck             ZwClose(InstanceKey);
362c2c66affSColin Finck             return Status;
363c2c66affSColin Finck         }
364c2c66affSColin Finck     }
365c2c66affSColin Finck 
366c2c66affSColin Finck     /* Close the instance key handle */
367c2c66affSColin Finck     ZwClose(InstanceKey);
368c2c66affSColin Finck 
369c2c66affSColin Finck     /* Register the given DO with PnP root if required */
370c2c66affSColin Finck     if (DeviceObject && *DeviceObject)
371c2c66affSColin Finck         PnpRootRegisterDevice(*DeviceObject);
372c2c66affSColin Finck 
373798fc13bSVictor Perevertkin     PiInsertDevNode(DeviceNode, IopRootDeviceNode);
374798fc13bSVictor Perevertkin     DeviceNode->Flags |= DNF_MADEUP | DNF_ENUMERATED;
375c2c66affSColin Finck 
376798fc13bSVictor Perevertkin     // we still need to query IDs, send events and reenumerate this node
377798fc13bSVictor Perevertkin     PiSetDevNodeState(DeviceNode, DeviceNodeStartPostWork);
378c2c66affSColin Finck 
379c2c66affSColin Finck     DPRINT("Reported device: %S (%wZ)\n", HardwareId, &DeviceNode->InstancePath);
380c2c66affSColin Finck 
381162d614cSVictor Perevertkin     PiQueueDeviceAction(Pdo, PiActionEnumDeviceTree, NULL, NULL);
382162d614cSVictor Perevertkin 
383c2c66affSColin Finck     /* Return the PDO */
384c2c66affSColin Finck     if (DeviceObject) *DeviceObject = Pdo;
385c2c66affSColin Finck 
386c2c66affSColin Finck     return STATUS_SUCCESS;
387c2c66affSColin Finck }
388c2c66affSColin Finck 
389c2c66affSColin Finck /*
390c2c66affSColin Finck  * @halfplemented
391c2c66affSColin Finck  */
392c2c66affSColin Finck NTSTATUS
393c2c66affSColin Finck NTAPI
IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject,IN PCM_RESOURCE_LIST DriverList OPTIONAL,IN ULONG DriverListSize OPTIONAL,IN PDEVICE_OBJECT DeviceObject OPTIONAL,IN PCM_RESOURCE_LIST DeviceList OPTIONAL,IN ULONG DeviceListSize OPTIONAL,OUT PBOOLEAN ConflictDetected)394c2c66affSColin Finck IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject,
395c2c66affSColin Finck                              IN PCM_RESOURCE_LIST DriverList OPTIONAL,
396c2c66affSColin Finck                              IN ULONG DriverListSize OPTIONAL,
397c2c66affSColin Finck                              IN PDEVICE_OBJECT DeviceObject OPTIONAL,
398c2c66affSColin Finck                              IN PCM_RESOURCE_LIST DeviceList OPTIONAL,
399c2c66affSColin Finck                              IN ULONG DeviceListSize OPTIONAL,
400c2c66affSColin Finck                              OUT PBOOLEAN ConflictDetected)
401c2c66affSColin Finck {
402c2c66affSColin Finck     PCM_RESOURCE_LIST ResourceList;
403c2c66affSColin Finck     NTSTATUS Status;
404c2c66affSColin Finck 
405c2c66affSColin Finck     *ConflictDetected = FALSE;
406c2c66affSColin Finck 
407c2c66affSColin Finck     if (!DriverList && !DeviceList)
408c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
409c2c66affSColin Finck 
410c2c66affSColin Finck     /* Find the real list */
411c2c66affSColin Finck     if (!DriverList)
412c2c66affSColin Finck         ResourceList = DeviceList;
413c2c66affSColin Finck     else
414c2c66affSColin Finck         ResourceList = DriverList;
415c2c66affSColin Finck 
416c2c66affSColin Finck     /* Look for a resource conflict */
41749358f34SHervé Poussineau     Status = IopDetectResourceConflict(ResourceList, TRUE, NULL);
418c2c66affSColin Finck     if (Status == STATUS_CONFLICTING_ADDRESSES)
419c2c66affSColin Finck     {
420c2c66affSColin Finck         /* Oh noes */
421c2c66affSColin Finck         *ConflictDetected = TRUE;
422c2c66affSColin Finck     }
423c2c66affSColin Finck     else if (NT_SUCCESS(Status))
424c2c66affSColin Finck     {
425c2c66affSColin Finck         /* Looks like we're good to go */
426c2c66affSColin Finck 
427c2c66affSColin Finck         /* TODO: Claim the resources in the ResourceMap */
428c2c66affSColin Finck     }
429c2c66affSColin Finck 
430c2c66affSColin Finck     return Status;
431c2c66affSColin Finck }
432c2c66affSColin Finck 
433c2c66affSColin Finck VOID
434c2c66affSColin Finck NTAPI
IopSetEvent(IN PVOID Context)435c2c66affSColin Finck IopSetEvent(IN PVOID Context)
436c2c66affSColin Finck {
437c2c66affSColin Finck     PKEVENT Event = Context;
438c2c66affSColin Finck 
439c2c66affSColin Finck     /* Set the event */
440c2c66affSColin Finck     KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
441c2c66affSColin Finck }
442c2c66affSColin Finck 
443c2c66affSColin Finck /*
444c2c66affSColin Finck  * @implemented
445c2c66affSColin Finck  */
446c2c66affSColin Finck NTSTATUS
447c2c66affSColin Finck NTAPI
IoReportTargetDeviceChange(IN PDEVICE_OBJECT PhysicalDeviceObject,IN PVOID NotificationStructure)448c2c66affSColin Finck IoReportTargetDeviceChange(IN PDEVICE_OBJECT PhysicalDeviceObject,
449c2c66affSColin Finck                            IN PVOID NotificationStructure)
450c2c66affSColin Finck {
451c2c66affSColin Finck     KEVENT NotifyEvent;
452c2c66affSColin Finck     NTSTATUS Status, NotifyStatus;
453c2c66affSColin Finck     PTARGET_DEVICE_CUSTOM_NOTIFICATION notifyStruct = (PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure;
454c2c66affSColin Finck 
455c2c66affSColin Finck     ASSERT(notifyStruct);
456c2c66affSColin Finck 
457c2c66affSColin Finck     /* Check for valid PDO */
458c2c66affSColin Finck     if (!IopIsValidPhysicalDeviceObject(PhysicalDeviceObject))
459c2c66affSColin Finck     {
460d6792047SIvan Labutin         KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG_PTR)PhysicalDeviceObject, 0, 0);
461c2c66affSColin Finck     }
462c2c66affSColin Finck 
463c2c66affSColin Finck     /* FileObject must be null. PnP will fill in it */
464c2c66affSColin Finck     ASSERT(notifyStruct->FileObject == NULL);
465c2c66affSColin Finck 
466c2c66affSColin Finck     /* Do not handle system PnP events */
46777af2653SAdam Słaboń     if (IsEqualGUID(&(notifyStruct->Event), &GUID_TARGET_DEVICE_QUERY_REMOVE) ||
46877af2653SAdam Słaboń         IsEqualGUID(&(notifyStruct->Event), &GUID_TARGET_DEVICE_REMOVE_CANCELLED) ||
46977af2653SAdam Słaboń         IsEqualGUID(&(notifyStruct->Event), &GUID_TARGET_DEVICE_REMOVE_COMPLETE))
470c2c66affSColin Finck     {
471c2c66affSColin Finck         return STATUS_INVALID_DEVICE_REQUEST;
472c2c66affSColin Finck     }
473c2c66affSColin Finck 
474c2c66affSColin Finck     if (notifyStruct->Version != 1)
475c2c66affSColin Finck     {
476c2c66affSColin Finck         return STATUS_INVALID_DEVICE_REQUEST;
477c2c66affSColin Finck     }
478c2c66affSColin Finck 
479c2c66affSColin Finck     /* Initialize even that will let us know when PnP will have finished notify */
480c2c66affSColin Finck     KeInitializeEvent(&NotifyEvent, NotificationEvent, FALSE);
481c2c66affSColin Finck 
482c2c66affSColin Finck     Status = PpSetCustomTargetEvent(PhysicalDeviceObject, &NotifyEvent, &NotifyStatus, NULL, NULL, notifyStruct);
483c2c66affSColin Finck     /* If no error, wait for the notify to end and return the status of the notify and not of the event */
484c2c66affSColin Finck     if (NT_SUCCESS(Status))
485c2c66affSColin Finck     {
486c2c66affSColin Finck         KeWaitForSingleObject(&NotifyEvent, Executive, KernelMode, FALSE, NULL);
487c2c66affSColin Finck         Status = NotifyStatus;
488c2c66affSColin Finck     }
489c2c66affSColin Finck 
490c2c66affSColin Finck     return Status;
491c2c66affSColin Finck }
492c2c66affSColin Finck 
493c2c66affSColin Finck /*
494c2c66affSColin Finck  * @implemented
495c2c66affSColin Finck  */
496c2c66affSColin Finck NTSTATUS
497c2c66affSColin Finck NTAPI
IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject,IN PVOID NotificationStructure,IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL,IN PVOID Context OPTIONAL)498c2c66affSColin Finck IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject,
499c2c66affSColin Finck                                        IN PVOID NotificationStructure,
500c2c66affSColin Finck                                        IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL,
501c2c66affSColin Finck                                        IN PVOID Context OPTIONAL)
502c2c66affSColin Finck {
503c2c66affSColin Finck     PINTERNAL_WORK_QUEUE_ITEM Item = NULL;
504c2c66affSColin Finck     PTARGET_DEVICE_CUSTOM_NOTIFICATION notifyStruct = (PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure;
505*176de8bdSTimo Kreuzer     SIZE_T WorkItemSize;
506c2c66affSColin Finck 
507c2c66affSColin Finck     ASSERT(notifyStruct);
508c2c66affSColin Finck 
509c2c66affSColin Finck     /* Check for valid PDO */
510c2c66affSColin Finck     if (!IopIsValidPhysicalDeviceObject(PhysicalDeviceObject))
511c2c66affSColin Finck     {
512d6792047SIvan Labutin         KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG_PTR)PhysicalDeviceObject, 0, 0);
513c2c66affSColin Finck     }
514c2c66affSColin Finck 
515c2c66affSColin Finck     /* FileObject must be null. PnP will fill in it */
516c2c66affSColin Finck     ASSERT(notifyStruct->FileObject == NULL);
517c2c66affSColin Finck 
518c2c66affSColin Finck     /* Do not handle system PnP events */
51977af2653SAdam Słaboń     if (IsEqualGUID(&(notifyStruct->Event), &GUID_TARGET_DEVICE_QUERY_REMOVE) ||
52077af2653SAdam Słaboń         IsEqualGUID(&(notifyStruct->Event), &GUID_TARGET_DEVICE_REMOVE_CANCELLED) ||
52177af2653SAdam Słaboń         IsEqualGUID(&(notifyStruct->Event), &GUID_TARGET_DEVICE_REMOVE_COMPLETE))
522c2c66affSColin Finck     {
523c2c66affSColin Finck         return STATUS_INVALID_DEVICE_REQUEST;
524c2c66affSColin Finck     }
525c2c66affSColin Finck 
526c2c66affSColin Finck     if (notifyStruct->Version != 1)
527c2c66affSColin Finck     {
528c2c66affSColin Finck         return STATUS_INVALID_DEVICE_REQUEST;
529c2c66affSColin Finck     }
530c2c66affSColin Finck 
531*176de8bdSTimo Kreuzer     /* Calculate the required size for the work item and notification structure */
532*176de8bdSTimo Kreuzer     WorkItemSize = FIELD_OFFSET(INTERNAL_WORK_QUEUE_ITEM, NotificationStructure)
533*176de8bdSTimo Kreuzer                    + notifyStruct->Size;
534*176de8bdSTimo Kreuzer 
535c2c66affSColin Finck     /* We need to store all the data given by the caller with the WorkItem, so use our own struct */
536*176de8bdSTimo Kreuzer     Item = ExAllocatePoolWithTag(NonPagedPool, WorkItemSize, '  pP');
537c2c66affSColin Finck     if (!Item) return STATUS_INSUFFICIENT_RESOURCES;
538c2c66affSColin Finck 
539c2c66affSColin Finck     /* Initialize all stuff */
540c2c66affSColin Finck     ObReferenceObject(PhysicalDeviceObject);
541c2c66affSColin Finck     Item->PhysicalDeviceObject = PhysicalDeviceObject;
542c2c66affSColin Finck     Item->Callback = Callback;
543c2c66affSColin Finck     Item->Context = Context;
544*176de8bdSTimo Kreuzer     RtlCopyMemory(&Item->NotificationStructure, notifyStruct, notifyStruct->Size);
545c2c66affSColin Finck     ExInitializeWorkItem(&(Item->WorkItem), IopReportTargetDeviceChangeAsyncWorker, Item);
546c2c66affSColin Finck 
547c2c66affSColin Finck     /* Finally, queue the item, our work here is done */
548c2c66affSColin Finck     ExQueueWorkItem(&(Item->WorkItem), DelayedWorkQueue);
549c2c66affSColin Finck 
550c2c66affSColin Finck     return STATUS_PENDING;
551c2c66affSColin Finck }
552