Implemented driver shutdown registration
[reactos.git] / reactos / ntoskrnl / io / device.c
1 /* $Id: device.c,v 1.21 2000/09/10 13:54:01 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/device.c
6 * PURPOSE: Manage devices
7 * PROGRAMMER: David Welch (welch@cwcom.net)
8 * UPDATE HISTORY:
9 * 15/05/98: Created
10 */
11
12 /* INCLUDES ****************************************************************/
13
14 #include <ddk/ntddk.h>
15
16 #include <internal/io.h>
17 #include <internal/ob.h>
18 #include <internal/ldr.h>
19 #include <internal/id.h>
20 #include <string.h>
21 #include <internal/string.h>
22
23 #define NDEBUG
24 #include <internal/debug.h>
25
26
27 /* FUNCTIONS ***************************************************************/
28
29
30 NTSTATUS STDCALL NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
31 {
32 UNIMPLEMENTED;
33 }
34
35
36 /**********************************************************************
37 * NAME EXPORTED
38 * NtLoadDriver
39 *
40 * DESCRIPTION
41 * Loads a device driver.
42 *
43 * ARGUMENTS
44 * DriverServiceName
45 * Name of the service to load (registry key).
46 *
47 * RETURN VALUE
48 * Status.
49 *
50 * REVISIONS
51 */
52 NTSTATUS
53 STDCALL
54 NtLoadDriver (
55 PUNICODE_STRING DriverServiceName
56 )
57 {
58 /* FIXME: this should lookup the filename from the registry and then call LdrLoadDriver */
59 return LdrLoadDriver (DriverServiceName);
60 }
61
62
63 NTSTATUS
64 STDCALL
65 IoAttachDeviceByPointer (
66 IN PDEVICE_OBJECT SourceDevice,
67 IN PDEVICE_OBJECT TargetDevice
68 )
69 {
70 PDEVICE_OBJECT AttachedDevice;
71
72 DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n",
73 SourceDevice,
74 TargetDevice);
75
76 AttachedDevice = IoAttachDeviceToDeviceStack (SourceDevice,
77 TargetDevice);
78 if (AttachedDevice == NULL)
79 return STATUS_NO_SUCH_DEVICE;
80
81 return STATUS_SUCCESS;
82 }
83
84
85 VOID
86 STDCALL
87 IoDeleteDevice(PDEVICE_OBJECT DeviceObject)
88 {
89 PDEVICE_OBJECT Previous;
90
91 if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED)
92 IoUnregisterShutdownNotification(DeviceObject);
93
94 /* remove the timer if it exists */
95 if (DeviceObject->Timer)
96 {
97 IoStopTimer(DeviceObject);
98 ExFreePool(DeviceObject->Timer);
99 }
100
101 /* free device extension */
102 if (DeviceObject->DeviceObjectExtension)
103 ExFreePool (DeviceObject->DeviceObjectExtension);
104
105 /* remove device from driver device list */
106 Previous = DeviceObject->DriverObject->DeviceObject;
107 if (Previous == DeviceObject)
108 {
109 DeviceObject->DriverObject->DeviceObject = DeviceObject->NextDevice;
110 }
111 else
112 {
113 while (Previous->NextDevice != DeviceObject)
114 Previous = Previous->NextDevice;
115 Previous->NextDevice = DeviceObject->NextDevice;
116 }
117
118 ObDereferenceObject (DeviceObject);
119 }
120
121
122 PDEVICE_OBJECT
123 STDCALL
124 IoGetRelatedDeviceObject (
125 IN PFILE_OBJECT FileObject
126 )
127 {
128 return (FileObject->DeviceObject);
129 }
130
131
132 NTSTATUS
133 STDCALL
134 IoGetDeviceObjectPointer (
135 IN PUNICODE_STRING ObjectName,
136 IN ACCESS_MASK DesiredAccess,
137 OUT PFILE_OBJECT * FileObject,
138 OUT PDEVICE_OBJECT * DeviceObject)
139 {
140 OBJECT_ATTRIBUTES ObjectAttributes;
141 IO_STATUS_BLOCK StatusBlock;
142 PFILE_OBJECT LocalFileObject;
143 HANDLE FileHandle;
144 NTSTATUS Status;
145
146 DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x, FileObject %p DeviceObject %p)\n",
147 ObjectName,
148 DesiredAccess,
149 FileObject,
150 DeviceObject);
151
152 InitializeObjectAttributes (&ObjectAttributes,
153 ObjectName,
154 0,
155 NULL,
156 NULL);
157
158 Status = NtOpenFile (&FileHandle,
159 DesiredAccess,
160 &ObjectAttributes,
161 &StatusBlock,
162 0,
163 FILE_NON_DIRECTORY_FILE);
164 if (!NT_SUCCESS(Status))
165 return Status;
166
167 Status = ObReferenceObjectByHandle (FileHandle,
168 0,
169 IoFileObjectType,
170 KernelMode,
171 (PVOID*)&LocalFileObject,
172 NULL);
173 if (NT_SUCCESS(Status))
174 {
175 *DeviceObject = IoGetRelatedDeviceObject (LocalFileObject);
176 *FileObject = LocalFileObject;
177 }
178 NtClose (FileHandle);
179
180 return Status;
181 }
182
183
184 VOID
185 STDCALL
186 IoDetachDevice(PDEVICE_OBJECT TargetDevice)
187 {
188 UNIMPLEMENTED;
189 }
190
191
192 PDEVICE_OBJECT
193 STDCALL
194 IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
195 {
196 PDEVICE_OBJECT Current = DeviceObject;
197
198 // DPRINT("IoGetAttachedDevice(DeviceObject %x)\n",DeviceObject);
199
200 while (Current->AttachedDevice!=NULL)
201 {
202 Current = Current->AttachedDevice;
203 // DPRINT("Current %x\n",Current);
204 }
205
206 // DPRINT("IoGetAttachedDevice() = %x\n",DeviceObject);
207 return(Current);
208 }
209
210 PDEVICE_OBJECT
211 STDCALL
212 IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice,
213 PDEVICE_OBJECT TargetDevice)
214 {
215 PDEVICE_OBJECT AttachedDevice;
216
217 DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n",
218 SourceDevice,TargetDevice);
219
220 AttachedDevice = IoGetAttachedDevice(TargetDevice);
221 AttachedDevice->AttachedDevice = SourceDevice;
222 SourceDevice->AttachedDevice = NULL;
223 SourceDevice->StackSize = AttachedDevice->StackSize + 1;
224 SourceDevice->Vpb = AttachedDevice->Vpb;
225 return(AttachedDevice);
226 }
227
228 VOID
229 STDCALL
230 IoRegisterDriverReinitialization(PDRIVER_OBJECT DriverObject,
231 PDRIVER_REINITIALIZE ReinitRoutine,
232 PVOID Context)
233 {
234 UNIMPLEMENTED;
235 }
236
237 NTSTATUS IopDefaultDispatchFunction(PDEVICE_OBJECT DeviceObject,
238 PIRP Irp)
239 {
240 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
241 Irp->IoStatus.Information = 0;
242
243 IoCompleteRequest(Irp, IO_NO_INCREMENT);
244 return(STATUS_NOT_IMPLEMENTED);
245 }
246
247 NTSTATUS IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry)
248 /*
249 * FUNCTION: Called to initalize a loaded driver
250 * ARGUMENTS:
251 */
252 {
253 NTSTATUS Status;
254 PDRIVER_OBJECT DriverObject;
255 ULONG i;
256
257 DriverObject = ExAllocatePool(NonPagedPool,sizeof(DRIVER_OBJECT));
258 if (DriverObject == NULL)
259 {
260 return STATUS_INSUFFICIENT_RESOURCES;
261 }
262 memset(DriverObject, 0, sizeof(DRIVER_OBJECT));
263
264 DriverObject->Type = InternalDriverType;
265
266 for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
267 {
268 DriverObject->MajorFunction[i] = IopDefaultDispatchFunction;
269 }
270
271 DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry);
272 Status = DriverEntry(DriverObject, NULL);
273 if (!NT_SUCCESS(Status))
274 {
275 ExFreePool(DriverObject);
276 return(Status);
277 }
278
279 return(Status);
280 }
281
282 NTSTATUS
283 STDCALL
284 IoAttachDevice(PDEVICE_OBJECT SourceDevice,
285 PUNICODE_STRING TargetDevice,
286 PDEVICE_OBJECT* AttachedDevice)
287 /*
288 * FUNCTION: Layers a device over the highest device in a device stack
289 * ARGUMENTS:
290 * SourceDevice = Device to attached
291 * TargetDevice = Name of the target device
292 * AttachedDevice (OUT) = Caller storage for the device attached to
293 */
294 {
295 UNIMPLEMENTED;
296 }
297
298 NTSTATUS IopCreateDevice(PVOID ObjectBody,
299 PVOID Parent,
300 PWSTR RemainingPath,
301 POBJECT_ATTRIBUTES ObjectAttributes)
302 {
303
304 DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n",
305 ObjectBody, Parent, RemainingPath);
306
307 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
308 {
309 return(STATUS_UNSUCCESSFUL);
310 }
311
312 if (Parent != NULL && RemainingPath != NULL)
313 {
314 ObAddEntryDirectory(Parent, ObjectBody, RemainingPath+1);
315 }
316 return(STATUS_SUCCESS);
317 }
318
319
320 NTSTATUS
321 STDCALL
322 IoCreateDevice(PDRIVER_OBJECT DriverObject,
323 ULONG DeviceExtensionSize,
324 PUNICODE_STRING DeviceName,
325 DEVICE_TYPE DeviceType,
326 ULONG DeviceCharacteristics,
327 BOOLEAN Exclusive,
328 PDEVICE_OBJECT* DeviceObject)
329 /*
330 * FUNCTION: Allocates memory for and intializes a device object for use for
331 * a driver
332 * ARGUMENTS:
333 * DriverObject : Driver object passed by iomgr when the driver was
334 * loaded
335 * DeviceExtensionSize : Number of bytes for the device extension
336 * DeviceName : Unicode name of device
337 * DeviceType : Device type
338 * DeviceCharacteristics : Bit mask of device characteristics
339 * Exclusive : True if only one thread can access the device at a
340 * time
341 * RETURNS:
342 * Success or failure
343 * DeviceObject : Contains a pointer to allocated device object
344 * if the call succeeded
345 * NOTES: See the DDK documentation for more information
346 */
347 {
348 PDEVICE_OBJECT CreatedDeviceObject;
349 OBJECT_ATTRIBUTES ObjectAttributes;
350 HANDLE DeviceHandle;
351
352 assert_irql(PASSIVE_LEVEL);
353
354 if (DeviceName != NULL)
355 {
356 DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",DriverObject,
357 DeviceName->Buffer);
358 }
359 else
360 {
361 DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject);
362 }
363
364 if (DeviceName != NULL)
365 {
366 InitializeObjectAttributes(&ObjectAttributes,DeviceName,0,NULL,NULL);
367 CreatedDeviceObject = ObCreateObject(&DeviceHandle,
368 0,
369 &ObjectAttributes,
370 IoDeviceObjectType);
371 }
372 else
373 {
374 CreatedDeviceObject = ObCreateObject(&DeviceHandle,
375 0,
376 NULL,
377 IoDeviceObjectType);
378 }
379
380 *DeviceObject = NULL;
381
382 if (CreatedDeviceObject == NULL)
383 {
384 return(STATUS_INSUFFICIENT_RESOURCES);
385 }
386
387 if (DriverObject->DeviceObject == NULL)
388 {
389 DriverObject->DeviceObject = CreatedDeviceObject;
390 CreatedDeviceObject->NextDevice = NULL;
391 }
392 else
393 {
394 CreatedDeviceObject->NextDevice = DriverObject->DeviceObject;
395 DriverObject->DeviceObject = CreatedDeviceObject;
396 }
397
398 CreatedDeviceObject->Type = DeviceType;
399 CreatedDeviceObject->DriverObject = DriverObject;
400 CreatedDeviceObject->CurrentIrp = NULL;
401 CreatedDeviceObject->Flags = 0;
402
403 CreatedDeviceObject->DeviceExtension = ExAllocatePool(NonPagedPool,
404 DeviceExtensionSize);
405 if (DeviceExtensionSize > 0 && CreatedDeviceObject->DeviceExtension == NULL)
406 {
407 ExFreePool(CreatedDeviceObject);
408 return(STATUS_INSUFFICIENT_RESOURCES);
409 }
410
411 CreatedDeviceObject->AttachedDevice = NULL;
412 CreatedDeviceObject->DeviceType = DeviceType;
413 CreatedDeviceObject->StackSize = 1;
414 CreatedDeviceObject->AlignmentRequirement = 1;
415 KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue);
416
417 if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK)
418 {
419 IoAttachVpb(CreatedDeviceObject);
420 }
421
422 *DeviceObject = CreatedDeviceObject;
423
424 return(STATUS_SUCCESS);
425 }
426
427
428 NTSTATUS
429 STDCALL
430 IoOpenDeviceInstanceKey (
431 DWORD Unknown0,
432 DWORD Unknown1,
433 DWORD Unknown2,
434 DWORD Unknown3,
435 DWORD Unknown4
436 )
437 {
438 UNIMPLEMENTED;
439 return (STATUS_NOT_IMPLEMENTED);
440 }
441
442
443 DWORD
444 STDCALL
445 IoQueryDeviceEnumInfo (
446 DWORD Unknown0,
447 DWORD Unknown1
448 )
449 {
450 UNIMPLEMENTED;
451 return 0;
452 }
453
454
455 VOID
456 STDCALL
457 IoSetDeviceToVerify (
458 DWORD Unknown0,
459 DWORD Unknown1
460 )
461 {
462 UNIMPLEMENTED;
463 }
464
465 /* EOF */