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