ntoskrnl.exe: Implement IoGetAttachedDevice and IoGetAttachedDeviceReference.
[wine.git] / dlls / ntoskrnl.exe / ntoskrnl.c
blob91e08d923cda94db4ba2b5c5e018e26ae0e6b93f
1 /*
2 * ntoskrnl.exe implementation
4 * Copyright (C) 2007 Alexandre Julliard
5 * Copyright (C) 2010 Damjan Jovanovic
6 * Copyright (C) 2016 Sebastian Lackner
7 * Copyright (C) 2016 CodeWeavers, Aric Stewart
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
25 #include "wine/port.h"
27 #include <stdarg.h>
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "windef.h"
35 #include "winsvc.h"
36 #include "winternl.h"
37 #include "excpt.h"
38 #include "winioctl.h"
39 #include "ddk/csq.h"
40 #include "ddk/ntddk.h"
41 #include "ddk/ntifs.h"
42 #include "ddk/wdm.h"
43 #include "wine/unicode.h"
44 #include "wine/server.h"
45 #include "wine/debug.h"
47 #include "wine/rbtree.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
50 WINE_DECLARE_DEBUG_CHANNEL(relay);
52 BOOLEAN KdDebuggerEnabled = FALSE;
53 ULONG InitSafeBootMode = 0;
55 extern LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs );
57 KSYSTEM_TIME KeTickCount = { 0, 0, 0 };
59 typedef struct _KSERVICE_TABLE_DESCRIPTOR
61 PULONG_PTR Base;
62 PULONG Count;
63 ULONG Limit;
64 PUCHAR Number;
65 } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
67 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[4] = { { 0 } };
69 typedef void (WINAPI *PCREATE_PROCESS_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
70 typedef void (WINAPI *PCREATE_THREAD_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
72 static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
73 '\\','M','a','c','h','i','n','e',
74 '\\','S','y','s','t','e','m',
75 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
76 '\\','S','e','r','v','i','c','e','s',
77 '\\',0};
79 /* tid of the thread running client request */
80 static DWORD request_thread;
82 /* pid/tid of the client thread */
83 static DWORD client_tid;
84 static DWORD client_pid;
86 struct wine_driver
88 struct wine_rb_entry entry;
90 DRIVER_OBJECT driver_obj;
91 DRIVER_EXTENSION driver_extension;
94 static int wine_drivers_rb_compare( const void *key, const struct wine_rb_entry *entry )
96 const struct wine_driver *driver = WINE_RB_ENTRY_VALUE( entry, const struct wine_driver, entry );
97 const UNICODE_STRING *k = key;
99 return RtlCompareUnicodeString( k, &driver->driver_obj.DriverName, FALSE );
102 static struct wine_rb_tree wine_drivers = { wine_drivers_rb_compare };
104 static CRITICAL_SECTION drivers_cs;
105 static CRITICAL_SECTION_DEBUG critsect_debug =
107 0, 0, &drivers_cs,
108 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
109 0, 0, { (DWORD_PTR)(__FILE__ ": drivers_cs") }
111 static CRITICAL_SECTION drivers_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
113 #ifdef __i386__
114 #define DEFINE_FASTCALL1_ENTRYPOINT( name ) \
115 __ASM_STDCALL_FUNC( name, 4, \
116 "popl %eax\n\t" \
117 "pushl %ecx\n\t" \
118 "pushl %eax\n\t" \
119 "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(4))
120 #define DEFINE_FASTCALL2_ENTRYPOINT( name ) \
121 __ASM_STDCALL_FUNC( name, 8, \
122 "popl %eax\n\t" \
123 "pushl %edx\n\t" \
124 "pushl %ecx\n\t" \
125 "pushl %eax\n\t" \
126 "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(8))
127 #define DEFINE_FASTCALL3_ENTRYPOINT( name ) \
128 __ASM_STDCALL_FUNC( name, 12, \
129 "popl %eax\n\t" \
130 "pushl %edx\n\t" \
131 "pushl %ecx\n\t" \
132 "pushl %eax\n\t" \
133 "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(12))
134 #endif
136 static inline LPCSTR debugstr_us( const UNICODE_STRING *us )
138 if (!us) return "<null>";
139 return debugstr_wn( us->Buffer, us->Length / sizeof(WCHAR) );
142 static HANDLE get_device_manager(void)
144 static HANDLE device_manager;
145 HANDLE handle = 0, ret = device_manager;
147 if (!ret)
149 SERVER_START_REQ( create_device_manager )
151 req->access = SYNCHRONIZE;
152 req->attributes = 0;
153 if (!wine_server_call( req )) handle = wine_server_ptr_handle( reply->handle );
155 SERVER_END_REQ;
157 if (!handle)
159 ERR( "failed to create the device manager\n" );
160 return 0;
162 if (!(ret = InterlockedCompareExchangePointer( &device_manager, handle, 0 )))
163 ret = handle;
164 else
165 NtClose( handle ); /* somebody beat us to it */
167 return ret;
170 static NTSTATUS dispatch_irp( DEVICE_OBJECT *device, IRP *irp )
172 LARGE_INTEGER count;
174 KeQueryTickCount( &count ); /* update the global KeTickCount */
176 device->CurrentIrp = irp;
178 IoCallDriver( device, irp );
180 device->CurrentIrp = NULL;
182 return STATUS_SUCCESS;
185 /* process a create request for a given file */
186 static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULONG in_size,
187 ULONG out_size, HANDLE irp_handle )
189 IRP *irp;
190 IO_STACK_LOCATION *irpsp;
191 FILE_OBJECT *file;
192 DEVICE_OBJECT *device = wine_server_get_ptr( params->create.device );
194 if (!(file = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*file) ))) return STATUS_NO_MEMORY;
196 TRACE( "device %p -> file %p\n", device, file );
198 file->Type = 5; /* MSDN */
199 file->Size = sizeof(*file);
200 file->DeviceObject = device;
202 if (!(irp = IoAllocateIrp( device->StackSize, FALSE )))
204 HeapFree( GetProcessHeap(), 0, file );
205 return STATUS_NO_MEMORY;
208 irpsp = IoGetNextIrpStackLocation( irp );
209 irpsp->MajorFunction = IRP_MJ_CREATE;
210 irpsp->DeviceObject = device;
211 irpsp->CompletionRoutine = NULL;
212 irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
213 irpsp->Parameters.Create.Options = params->create.options;
214 irpsp->Parameters.Create.ShareAccess = params->create.sharing;
215 irpsp->Parameters.Create.FileAttributes = 0;
216 irpsp->Parameters.Create.EaLength = 0;
218 irp->Tail.Overlay.OriginalFileObject = file;
219 irp->RequestorMode = UserMode;
220 irp->AssociatedIrp.SystemBuffer = NULL;
221 irp->UserBuffer = NULL;
222 irp->UserIosb = irp_handle; /* note: we abuse UserIosb to store the server irp handle */
223 irp->UserEvent = NULL;
225 if (device->DriverObject->MajorFunction[IRP_MJ_CREATE]) return dispatch_irp( device, irp );
227 irp->IoStatus.u.Status = STATUS_SUCCESS;
228 IoCompleteRequest( irp, IO_NO_INCREMENT );
229 return STATUS_SUCCESS;
232 /* process a close request for a given file */
233 static NTSTATUS dispatch_close( const irp_params_t *params, void *in_buff, ULONG in_size,
234 ULONG out_size, HANDLE irp_handle )
236 IRP *irp;
237 IO_STACK_LOCATION *irpsp;
238 DEVICE_OBJECT *device;
239 FILE_OBJECT *file = wine_server_get_ptr( params->close.file );
241 if (!file) return STATUS_INVALID_HANDLE;
243 device = file->DeviceObject;
245 TRACE( "device %p file %p\n", device, file );
247 if (!(irp = IoAllocateIrp( device->StackSize, FALSE )))
249 HeapFree( GetProcessHeap(), 0, file );
250 return STATUS_NO_MEMORY;
253 irpsp = IoGetNextIrpStackLocation( irp );
254 irpsp->MajorFunction = IRP_MJ_CLOSE;
255 irpsp->DeviceObject = device;
256 irpsp->CompletionRoutine = NULL;
257 irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
258 irpsp->Parameters.Create.Options = params->create.options;
259 irpsp->Parameters.Create.ShareAccess = params->create.sharing;
260 irpsp->Parameters.Create.FileAttributes = 0;
261 irpsp->Parameters.Create.EaLength = 0;
263 irp->Tail.Overlay.OriginalFileObject = file;
264 irp->RequestorMode = UserMode;
265 irp->AssociatedIrp.SystemBuffer = NULL;
266 irp->UserBuffer = NULL;
267 irp->UserIosb = irp_handle; /* note: we abuse UserIosb to store the server irp handle */
268 irp->UserEvent = NULL;
270 if (!device->DriverObject->MajorFunction[IRP_MJ_CLOSE])
272 irp->IoStatus.u.Status = STATUS_SUCCESS;
273 IoCompleteRequest( irp, IO_NO_INCREMENT );
275 else dispatch_irp( device, irp );
277 HeapFree( GetProcessHeap(), 0, file ); /* FIXME: async close processing not supported */
278 return STATUS_SUCCESS;
281 /* process a read request for a given device */
282 static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG in_size,
283 ULONG out_size, HANDLE irp_handle )
285 IRP *irp;
286 void *out_buff;
287 LARGE_INTEGER offset;
288 IO_STACK_LOCATION *irpsp;
289 DEVICE_OBJECT *device;
290 FILE_OBJECT *file = wine_server_get_ptr( params->read.file );
292 if (!file) return STATUS_INVALID_HANDLE;
294 device = file->DeviceObject;
295 if (!device->DriverObject->MajorFunction[IRP_MJ_READ]) return STATUS_NOT_SUPPORTED;
297 TRACE( "device %p file %p size %u\n", device, file, out_size );
299 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
301 offset.QuadPart = params->read.pos;
303 /* note: we abuse UserIosb to store the server irp handle */
304 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, device, out_buff, out_size,
305 &offset, NULL, irp_handle )))
307 HeapFree( GetProcessHeap(), 0, out_buff );
308 return STATUS_NO_MEMORY;
311 irp->Tail.Overlay.OriginalFileObject = file;
312 irp->RequestorMode = UserMode;
314 irpsp = IoGetNextIrpStackLocation( irp );
315 irpsp->Parameters.Read.Key = params->read.key;
317 return dispatch_irp( device, irp );
320 /* process a write request for a given device */
321 static NTSTATUS dispatch_write( const irp_params_t *params, void *in_buff, ULONG in_size,
322 ULONG out_size, HANDLE irp_handle )
324 IRP *irp;
325 LARGE_INTEGER offset;
326 IO_STACK_LOCATION *irpsp;
327 DEVICE_OBJECT *device;
328 FILE_OBJECT *file = wine_server_get_ptr( params->write.file );
330 if (!file) return STATUS_INVALID_HANDLE;
332 device = file->DeviceObject;
333 if (!device->DriverObject->MajorFunction[IRP_MJ_WRITE]) return STATUS_NOT_SUPPORTED;
335 TRACE( "device %p file %p size %u\n", device, file, in_size );
337 offset.QuadPart = params->write.pos;
339 /* note: we abuse UserIosb to store the server irp handle */
340 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, device, in_buff, in_size,
341 &offset, NULL, irp_handle )))
342 return STATUS_NO_MEMORY;
344 irp->Tail.Overlay.OriginalFileObject = file;
345 irp->RequestorMode = UserMode;
347 irpsp = IoGetNextIrpStackLocation( irp );
348 irpsp->Parameters.Write.Key = params->write.key;
350 return dispatch_irp( device, irp );
353 /* process a flush request for a given device */
354 static NTSTATUS dispatch_flush( const irp_params_t *params, void *in_buff, ULONG in_size,
355 ULONG out_size, HANDLE irp_handle )
357 IRP *irp;
358 DEVICE_OBJECT *device;
359 FILE_OBJECT *file = wine_server_get_ptr( params->flush.file );
361 if (!file) return STATUS_INVALID_HANDLE;
363 device = file->DeviceObject;
364 if (!device->DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS]) return STATUS_NOT_SUPPORTED;
366 TRACE( "device %p file %p\n", device, file );
368 /* note: we abuse UserIosb to store the server irp handle */
369 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_FLUSH_BUFFERS, device, in_buff, in_size,
370 NULL, NULL, irp_handle )))
371 return STATUS_NO_MEMORY;
373 irp->Tail.Overlay.OriginalFileObject = file;
374 irp->RequestorMode = UserMode;
376 return dispatch_irp( device, irp );
379 /* process an ioctl request for a given device */
380 static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG in_size,
381 ULONG out_size, HANDLE irp_handle )
383 IRP *irp;
384 void *out_buff = NULL;
385 DEVICE_OBJECT *device;
386 FILE_OBJECT *file = wine_server_get_ptr( params->ioctl.file );
388 if (!file) return STATUS_INVALID_HANDLE;
390 device = file->DeviceObject;
391 if (!device->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]) return STATUS_NOT_SUPPORTED;
393 TRACE( "ioctl %x device %p file %p in_size %u out_size %u\n",
394 params->ioctl.code, device, file, in_size, out_size );
396 if ((params->ioctl.code & 3) == METHOD_BUFFERED) out_size = max( in_size, out_size );
398 if (out_size)
400 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
401 if ((params->ioctl.code & 3) == METHOD_BUFFERED)
403 memcpy( out_buff, in_buff, in_size );
404 in_buff = out_buff;
408 /* note: we abuse UserIosb to store the server handle to the ioctl */
409 irp = IoBuildDeviceIoControlRequest( params->ioctl.code, device, in_buff, in_size, out_buff, out_size,
410 FALSE, NULL, irp_handle );
411 if (!irp)
413 HeapFree( GetProcessHeap(), 0, out_buff );
414 return STATUS_NO_MEMORY;
417 irp->Tail.Overlay.OriginalFileObject = file;
418 irp->RequestorMode = UserMode;
420 return dispatch_irp( device, irp );
423 typedef NTSTATUS (*dispatch_func)( const irp_params_t *params, void *in_buff, ULONG in_size,
424 ULONG out_size, HANDLE irp_handle );
426 static const dispatch_func dispatch_funcs[IRP_MJ_MAXIMUM_FUNCTION + 1] =
428 dispatch_create, /* IRP_MJ_CREATE */
429 NULL, /* IRP_MJ_CREATE_NAMED_PIPE */
430 dispatch_close, /* IRP_MJ_CLOSE */
431 dispatch_read, /* IRP_MJ_READ */
432 dispatch_write, /* IRP_MJ_WRITE */
433 NULL, /* IRP_MJ_QUERY_INFORMATION */
434 NULL, /* IRP_MJ_SET_INFORMATION */
435 NULL, /* IRP_MJ_QUERY_EA */
436 NULL, /* IRP_MJ_SET_EA */
437 dispatch_flush, /* IRP_MJ_FLUSH_BUFFERS */
438 NULL, /* IRP_MJ_QUERY_VOLUME_INFORMATION */
439 NULL, /* IRP_MJ_SET_VOLUME_INFORMATION */
440 NULL, /* IRP_MJ_DIRECTORY_CONTROL */
441 NULL, /* IRP_MJ_FILE_SYSTEM_CONTROL */
442 dispatch_ioctl, /* IRP_MJ_DEVICE_CONTROL */
443 NULL, /* IRP_MJ_INTERNAL_DEVICE_CONTROL */
444 NULL, /* IRP_MJ_SHUTDOWN */
445 NULL, /* IRP_MJ_LOCK_CONTROL */
446 NULL, /* IRP_MJ_CLEANUP */
447 NULL, /* IRP_MJ_CREATE_MAILSLOT */
448 NULL, /* IRP_MJ_QUERY_SECURITY */
449 NULL, /* IRP_MJ_SET_SECURITY */
450 NULL, /* IRP_MJ_POWER */
451 NULL, /* IRP_MJ_SYSTEM_CONTROL */
452 NULL, /* IRP_MJ_DEVICE_CHANGE */
453 NULL, /* IRP_MJ_QUERY_QUOTA */
454 NULL, /* IRP_MJ_SET_QUOTA */
455 NULL, /* IRP_MJ_PNP */
459 /***********************************************************************
460 * wine_ntoskrnl_main_loop (Not a Windows API)
462 NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
464 HANDLE manager = get_device_manager();
465 HANDLE irp = 0;
466 NTSTATUS status = STATUS_SUCCESS;
467 irp_params_t irp_params;
468 void *in_buff;
469 ULONG in_size = 4096, out_size = 0;
470 HANDLE handles[2];
472 request_thread = GetCurrentThreadId();
474 if (!(in_buff = HeapAlloc( GetProcessHeap(), 0, in_size )))
476 ERR( "failed to allocate buffer\n" );
477 return STATUS_NO_MEMORY;
480 handles[0] = stop_event;
481 handles[1] = manager;
483 for (;;)
485 SERVER_START_REQ( get_next_device_request )
487 req->manager = wine_server_obj_handle( manager );
488 req->prev = wine_server_obj_handle( irp );
489 req->status = status;
490 wine_server_set_reply( req, in_buff, in_size );
491 if (!(status = wine_server_call( req )))
493 irp = wine_server_ptr_handle( reply->next );
494 irp_params = reply->params;
495 client_tid = reply->client_tid;
496 client_pid = reply->client_pid;
497 in_size = reply->in_size;
498 out_size = reply->out_size;
500 else
502 irp = 0; /* no previous irp */
503 out_size = 0;
504 in_size = reply->in_size;
507 SERVER_END_REQ;
509 switch(status)
511 case STATUS_SUCCESS:
512 if (irp_params.major > IRP_MJ_MAXIMUM_FUNCTION || !dispatch_funcs[irp_params.major])
514 WARN( "unsupported request %u\n", irp_params.major );
515 status = STATUS_NOT_SUPPORTED;
516 break;
518 status = dispatch_funcs[irp_params.major]( &irp_params, in_buff, in_size, out_size, irp );
519 if (status == STATUS_SUCCESS) irp = 0; /* status reported by IoCompleteRequest */
520 break;
521 case STATUS_BUFFER_OVERFLOW:
522 HeapFree( GetProcessHeap(), 0, in_buff );
523 in_buff = HeapAlloc( GetProcessHeap(), 0, in_size );
524 /* restart with larger buffer */
525 break;
526 case STATUS_PENDING:
527 for (;;)
529 DWORD ret = WaitForMultipleObjectsEx( 2, handles, FALSE, INFINITE, TRUE );
530 if (ret == WAIT_OBJECT_0)
532 HeapFree( GetProcessHeap(), 0, in_buff );
533 return STATUS_SUCCESS;
535 if (ret != WAIT_IO_COMPLETION) break;
537 break;
543 /***********************************************************************
544 * IoAcquireCancelSpinLock (NTOSKRNL.EXE.@)
546 void WINAPI IoAcquireCancelSpinLock(PKIRQL irql)
548 FIXME("(%p): stub\n", irql);
552 /***********************************************************************
553 * IoReleaseCancelSpinLock (NTOSKRNL.EXE.@)
555 void WINAPI IoReleaseCancelSpinLock(PKIRQL irql)
557 FIXME("(%p): stub\n", irql);
561 /***********************************************************************
562 * IoAllocateDriverObjectExtension (NTOSKRNL.EXE.@)
564 NTSTATUS WINAPI IoAllocateDriverObjectExtension( PDRIVER_OBJECT DriverObject,
565 PVOID ClientIdentificationAddress,
566 ULONG DriverObjectExtensionSize,
567 PVOID *DriverObjectExtension )
569 FIXME( "stub: %p, %p, %u, %p\n", DriverObject, ClientIdentificationAddress,
570 DriverObjectExtensionSize, DriverObjectExtension );
571 return STATUS_NOT_IMPLEMENTED;
575 /***********************************************************************
576 * IoGetDriverObjectExtension (NTOSKRNL.EXE.@)
578 PVOID WINAPI IoGetDriverObjectExtension( PDRIVER_OBJECT DriverObject,
579 PVOID ClientIdentificationAddress )
581 FIXME( "stub: %p, %p\n", DriverObject, ClientIdentificationAddress );
582 return NULL;
586 /***********************************************************************
587 * IoInitializeIrp (NTOSKRNL.EXE.@)
589 void WINAPI IoInitializeIrp( IRP *irp, USHORT size, CCHAR stack_size )
591 TRACE( "%p, %u, %d\n", irp, size, stack_size );
593 RtlZeroMemory( irp, size );
595 irp->Type = IO_TYPE_IRP;
596 irp->Size = size;
597 InitializeListHead( &irp->ThreadListEntry );
598 irp->StackCount = stack_size;
599 irp->CurrentLocation = stack_size + 1;
600 irp->Tail.Overlay.s.u2.CurrentStackLocation =
601 (PIO_STACK_LOCATION)(irp + 1) + stack_size;
605 /***********************************************************************
606 * IoInitializeTimer (NTOSKRNL.EXE.@)
608 NTSTATUS WINAPI IoInitializeTimer(PDEVICE_OBJECT DeviceObject,
609 PIO_TIMER_ROUTINE TimerRoutine,
610 PVOID Context)
612 FIXME( "stub: %p, %p, %p\n", DeviceObject, TimerRoutine, Context );
613 return STATUS_NOT_IMPLEMENTED;
617 /***********************************************************************
618 * IoStartTimer (NTOSKRNL.EXE.@)
620 void WINAPI IoStartTimer(PDEVICE_OBJECT DeviceObject)
622 FIXME( "stub: %p\n", DeviceObject );
626 /***********************************************************************
627 * IoAllocateIrp (NTOSKRNL.EXE.@)
629 PIRP WINAPI IoAllocateIrp( CCHAR stack_size, BOOLEAN charge_quota )
631 SIZE_T size;
632 PIRP irp;
633 CCHAR loc_count = stack_size;
635 TRACE( "%d, %d\n", stack_size, charge_quota );
637 if (loc_count < 8 && loc_count != 1)
638 loc_count = 8;
640 size = sizeof(IRP) + loc_count * sizeof(IO_STACK_LOCATION);
641 irp = ExAllocatePool( NonPagedPool, size );
642 if (irp == NULL)
643 return NULL;
644 IoInitializeIrp( irp, size, stack_size );
645 if (stack_size >= 1 && stack_size <= 8)
646 irp->AllocationFlags = IRP_ALLOCATED_FIXED_SIZE;
647 if (charge_quota)
648 irp->AllocationFlags |= IRP_LOOKASIDE_ALLOCATION;
649 return irp;
653 /***********************************************************************
654 * IoFreeIrp (NTOSKRNL.EXE.@)
656 void WINAPI IoFreeIrp( IRP *irp )
658 MDL *mdl;
660 TRACE( "%p\n", irp );
662 mdl = irp->MdlAddress;
663 while (mdl)
665 MDL *next = mdl->Next;
666 IoFreeMdl( mdl );
667 mdl = next;
670 ExFreePool( irp );
674 /***********************************************************************
675 * IoAllocateErrorLogEntry (NTOSKRNL.EXE.@)
677 PVOID WINAPI IoAllocateErrorLogEntry( PVOID IoObject, UCHAR EntrySize )
679 FIXME( "stub: %p, %u\n", IoObject, EntrySize );
680 return NULL;
684 /***********************************************************************
685 * IoAllocateMdl (NTOSKRNL.EXE.@)
687 PMDL WINAPI IoAllocateMdl( PVOID va, ULONG length, BOOLEAN secondary, BOOLEAN charge_quota, IRP *irp )
689 PMDL mdl;
690 ULONG_PTR address = (ULONG_PTR)va;
691 ULONG_PTR page_address;
692 SIZE_T nb_pages, mdl_size;
694 TRACE("(%p, %u, %i, %i, %p)\n", va, length, secondary, charge_quota, irp);
696 if (charge_quota)
697 FIXME("Charge quota is not yet supported\n");
699 /* FIXME: We suppose that page size is 4096 */
700 page_address = address & ~(4096 - 1);
701 nb_pages = (((address + length - 1) & ~(4096 - 1)) - page_address) / 4096 + 1;
703 mdl_size = sizeof(MDL) + nb_pages * sizeof(PVOID);
705 mdl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mdl_size);
706 if (!mdl)
707 return NULL;
709 mdl->Size = mdl_size;
710 mdl->Process = NULL; /* FIXME: IoGetCurrentProcess */
711 mdl->StartVa = (PVOID)page_address;
712 mdl->ByteCount = length;
713 mdl->ByteOffset = address - page_address;
715 if (!irp) return mdl;
717 if (secondary) /* add it at the end */
719 MDL **pmdl = &irp->MdlAddress;
720 while (*pmdl) pmdl = &(*pmdl)->Next;
721 *pmdl = mdl;
723 else
725 mdl->Next = irp->MdlAddress;
726 irp->MdlAddress = mdl;
728 return mdl;
732 /***********************************************************************
733 * IoFreeMdl (NTOSKRNL.EXE.@)
735 void WINAPI IoFreeMdl(PMDL mdl)
737 TRACE("%p\n", mdl);
738 HeapFree(GetProcessHeap(), 0, mdl);
742 /***********************************************************************
743 * IoAllocateWorkItem (NTOSKRNL.EXE.@)
745 PIO_WORKITEM WINAPI IoAllocateWorkItem( PDEVICE_OBJECT DeviceObject )
747 FIXME( "stub: %p\n", DeviceObject );
748 return NULL;
752 /***********************************************************************
753 * IoAttachDeviceToDeviceStack (NTOSKRNL.EXE.@)
755 PDEVICE_OBJECT WINAPI IoAttachDeviceToDeviceStack( DEVICE_OBJECT *source,
756 DEVICE_OBJECT *target )
758 TRACE( "%p, %p\n", source, target );
759 target->AttachedDevice = source;
760 source->StackSize = target->StackSize + 1;
761 return target;
765 /***********************************************************************
766 * IoBuildDeviceIoControlRequest (NTOSKRNL.EXE.@)
768 PIRP WINAPI IoBuildDeviceIoControlRequest( ULONG code, PDEVICE_OBJECT device,
769 PVOID in_buff, ULONG in_len,
770 PVOID out_buff, ULONG out_len,
771 BOOLEAN internal, PKEVENT event,
772 PIO_STATUS_BLOCK iosb )
774 PIRP irp;
775 PIO_STACK_LOCATION irpsp;
777 TRACE( "%x, %p, %p, %u, %p, %u, %u, %p, %p\n",
778 code, device, in_buff, in_len, out_buff, out_len, internal, event, iosb );
780 if (device == NULL)
781 return NULL;
783 irp = IoAllocateIrp( device->StackSize, FALSE );
784 if (irp == NULL)
785 return NULL;
787 irpsp = IoGetNextIrpStackLocation( irp );
788 irpsp->MajorFunction = internal ? IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
789 irpsp->Parameters.DeviceIoControl.IoControlCode = code;
790 irpsp->Parameters.DeviceIoControl.InputBufferLength = in_len;
791 irpsp->Parameters.DeviceIoControl.OutputBufferLength = out_len;
792 irpsp->DeviceObject = device;
793 irpsp->CompletionRoutine = NULL;
795 switch (code & 3)
797 case METHOD_BUFFERED:
798 irp->AssociatedIrp.SystemBuffer = in_buff;
799 break;
800 case METHOD_IN_DIRECT:
801 case METHOD_OUT_DIRECT:
802 irp->AssociatedIrp.SystemBuffer = in_buff;
803 IoAllocateMdl( out_buff, out_len, FALSE, FALSE, irp );
804 break;
805 case METHOD_NEITHER:
806 irpsp->Parameters.DeviceIoControl.Type3InputBuffer = in_buff;
807 break;
810 irp->RequestorMode = KernelMode;
811 irp->UserBuffer = out_buff;
812 irp->UserIosb = iosb;
813 irp->UserEvent = event;
814 return irp;
818 /**********************************************************
819 * IoBuildSynchronousFsdRequest (NTOSKRNL.EXE.@)
821 PIRP WINAPI IoBuildSynchronousFsdRequest(ULONG majorfunc, PDEVICE_OBJECT device,
822 PVOID buffer, ULONG length, PLARGE_INTEGER startoffset,
823 PKEVENT event, PIO_STATUS_BLOCK iosb)
825 PIRP irp;
826 PIO_STACK_LOCATION irpsp;
828 TRACE("(%d %p %p %d %p %p %p)\n", majorfunc, device, buffer, length, startoffset, event, iosb);
830 if (!(irp = IoAllocateIrp( device->StackSize, FALSE ))) return NULL;
832 irpsp = IoGetNextIrpStackLocation( irp );
833 irpsp->MajorFunction = majorfunc;
834 irpsp->DeviceObject = device;
835 irpsp->CompletionRoutine = NULL;
837 irp->AssociatedIrp.SystemBuffer = buffer;
838 if (device->Flags & DO_DIRECT_IO) IoAllocateMdl( buffer, length, FALSE, FALSE, irp );
840 switch (majorfunc)
842 case IRP_MJ_READ:
843 irpsp->Parameters.Read.Length = length;
844 irpsp->Parameters.Read.ByteOffset = *startoffset;
845 break;
846 case IRP_MJ_WRITE:
847 irpsp->Parameters.Write.Length = length;
848 irpsp->Parameters.Write.ByteOffset = *startoffset;
849 break;
851 irp->RequestorMode = KernelMode;
852 irp->UserIosb = iosb;
853 irp->UserEvent = event;
854 irp->UserBuffer = buffer;
855 return irp;
858 static void build_driver_keypath( const WCHAR *name, UNICODE_STRING *keypath )
860 static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0};
861 WCHAR *str;
863 /* Check what prefix is present */
864 if (strncmpW( name, servicesW, strlenW(servicesW) ) == 0)
866 FIXME( "Driver name %s is malformed as the keypath\n", debugstr_w(name) );
867 RtlCreateUnicodeString( keypath, name );
868 return;
870 if (strncmpW( name, driverW, strlenW(driverW) ) == 0)
871 name += strlenW(driverW);
872 else
873 FIXME( "Driver name %s does not properly begin with \\Driver\\\n", debugstr_w(name) );
875 str = HeapAlloc( GetProcessHeap(), 0, sizeof(servicesW) + strlenW(name)*sizeof(WCHAR));
876 lstrcpyW( str, servicesW );
877 lstrcatW( str, name );
878 RtlInitUnicodeString( keypath, str );
882 /***********************************************************************
883 * IoCreateDriver (NTOSKRNL.EXE.@)
885 NTSTATUS WINAPI IoCreateDriver( UNICODE_STRING *name, PDRIVER_INITIALIZE init )
887 struct wine_driver *driver;
888 NTSTATUS status;
890 TRACE("(%s, %p)\n", debugstr_us(name), init);
892 if (!(driver = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
893 sizeof(*driver) )))
894 return STATUS_NO_MEMORY;
896 if ((status = RtlDuplicateUnicodeString( 1, name, &driver->driver_obj.DriverName )))
898 RtlFreeHeap( GetProcessHeap(), 0, driver );
899 return status;
902 driver->driver_obj.Size = sizeof(driver->driver_obj);
903 driver->driver_obj.DriverInit = init;
904 driver->driver_obj.DriverExtension = &driver->driver_extension;
905 driver->driver_extension.DriverObject = &driver->driver_obj;
906 build_driver_keypath( driver->driver_obj.DriverName.Buffer, &driver->driver_extension.ServiceKeyName );
908 status = driver->driver_obj.DriverInit( &driver->driver_obj, &driver->driver_extension.ServiceKeyName );
910 if (status)
912 RtlFreeUnicodeString( &driver->driver_obj.DriverName );
913 RtlFreeUnicodeString( &driver->driver_extension.ServiceKeyName );
914 RtlFreeHeap( GetProcessHeap(), 0, driver );
916 else
918 EnterCriticalSection( &drivers_cs );
919 if (wine_rb_put( &wine_drivers, &driver->driver_obj.DriverName, &driver->entry ))
920 ERR( "failed to insert driver %s in tree\n", debugstr_us(name) );
921 LeaveCriticalSection( &drivers_cs );
924 return status;
928 /***********************************************************************
929 * IoDeleteDriver (NTOSKRNL.EXE.@)
931 void WINAPI IoDeleteDriver( DRIVER_OBJECT *driver_object )
933 TRACE( "(%p)\n", driver_object );
935 EnterCriticalSection( &drivers_cs );
936 wine_rb_remove( &wine_drivers, &driver_object->DriverName );
937 LeaveCriticalSection( &drivers_cs );
939 RtlFreeUnicodeString( &driver_object->DriverName );
940 RtlFreeUnicodeString( &driver_object->DriverExtension->ServiceKeyName );
941 RtlFreeHeap( GetProcessHeap(), 0, CONTAINING_RECORD( driver_object, struct wine_driver, driver_obj ) );
945 /***********************************************************************
946 * IoCreateDevice (NTOSKRNL.EXE.@)
948 NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size,
949 UNICODE_STRING *name, DEVICE_TYPE type,
950 ULONG characteristics, BOOLEAN exclusive,
951 DEVICE_OBJECT **ret_device )
953 NTSTATUS status;
954 DEVICE_OBJECT *device;
955 HANDLE handle = 0;
956 HANDLE manager = get_device_manager();
958 TRACE( "(%p, %u, %s, %u, %x, %u, %p)\n",
959 driver, ext_size, debugstr_us(name), type, characteristics, exclusive, ret_device );
961 if (!(device = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*device) + ext_size )))
962 return STATUS_NO_MEMORY;
964 SERVER_START_REQ( create_device )
966 req->access = 0;
967 req->attributes = 0;
968 req->rootdir = 0;
969 req->manager = wine_server_obj_handle( manager );
970 req->user_ptr = wine_server_client_ptr( device );
971 if (name) wine_server_add_data( req, name->Buffer, name->Length );
972 if (!(status = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle );
974 SERVER_END_REQ;
976 if (status == STATUS_SUCCESS)
978 device->DriverObject = driver;
979 device->DeviceExtension = device + 1;
980 device->DeviceType = type;
981 device->StackSize = 1;
982 device->Reserved = handle;
984 device->NextDevice = driver->DeviceObject;
985 driver->DeviceObject = device;
987 *ret_device = device;
989 else HeapFree( GetProcessHeap(), 0, device );
991 return status;
995 /***********************************************************************
996 * IoDeleteDevice (NTOSKRNL.EXE.@)
998 void WINAPI IoDeleteDevice( DEVICE_OBJECT *device )
1000 NTSTATUS status;
1002 TRACE( "%p\n", device );
1004 SERVER_START_REQ( delete_device )
1006 req->handle = wine_server_obj_handle( device->Reserved );
1007 status = wine_server_call( req );
1009 SERVER_END_REQ;
1011 if (status == STATUS_SUCCESS)
1013 DEVICE_OBJECT **prev = &device->DriverObject->DeviceObject;
1014 while (*prev && *prev != device) prev = &(*prev)->NextDevice;
1015 if (*prev) *prev = (*prev)->NextDevice;
1016 NtClose( device->Reserved );
1017 HeapFree( GetProcessHeap(), 0, device );
1022 /***********************************************************************
1023 * IoCreateSymbolicLink (NTOSKRNL.EXE.@)
1025 NTSTATUS WINAPI IoCreateSymbolicLink( UNICODE_STRING *name, UNICODE_STRING *target )
1027 HANDLE handle;
1028 OBJECT_ATTRIBUTES attr;
1030 attr.Length = sizeof(attr);
1031 attr.RootDirectory = 0;
1032 attr.ObjectName = name;
1033 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1034 attr.SecurityDescriptor = NULL;
1035 attr.SecurityQualityOfService = NULL;
1037 TRACE( "%s -> %s\n", debugstr_us(name), debugstr_us(target) );
1038 /* FIXME: store handle somewhere */
1039 return NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, target );
1043 /***********************************************************************
1044 * IoDeleteSymbolicLink (NTOSKRNL.EXE.@)
1046 NTSTATUS WINAPI IoDeleteSymbolicLink( UNICODE_STRING *name )
1048 HANDLE handle;
1049 OBJECT_ATTRIBUTES attr;
1050 NTSTATUS status;
1052 attr.Length = sizeof(attr);
1053 attr.RootDirectory = 0;
1054 attr.ObjectName = name;
1055 attr.Attributes = OBJ_CASE_INSENSITIVE;
1056 attr.SecurityDescriptor = NULL;
1057 attr.SecurityQualityOfService = NULL;
1059 if (!(status = NtOpenSymbolicLinkObject( &handle, 0, &attr )))
1061 SERVER_START_REQ( unlink_object )
1063 req->handle = wine_server_obj_handle( handle );
1064 status = wine_server_call( req );
1066 SERVER_END_REQ;
1067 NtClose( handle );
1069 return status;
1073 /***********************************************************************
1074 * IoGetDeviceInterfaces (NTOSKRNL.EXE.@)
1076 NTSTATUS WINAPI IoGetDeviceInterfaces( const GUID *InterfaceClassGuid,
1077 PDEVICE_OBJECT PhysicalDeviceObject,
1078 ULONG Flags, PWSTR *SymbolicLinkList )
1080 FIXME( "stub: %s %p %x %p\n", debugstr_guid(InterfaceClassGuid),
1081 PhysicalDeviceObject, Flags, SymbolicLinkList );
1082 return STATUS_NOT_IMPLEMENTED;
1086 /***********************************************************************
1087 * IoGetDeviceObjectPointer (NTOSKRNL.EXE.@)
1089 NTSTATUS WINAPI IoGetDeviceObjectPointer( UNICODE_STRING *name, ACCESS_MASK access, PFILE_OBJECT *file, PDEVICE_OBJECT *device )
1091 static DEVICE_OBJECT stub_device;
1092 static DRIVER_OBJECT stub_driver;
1094 FIXME( "stub: %s %x %p %p\n", debugstr_us(name), access, file, device );
1096 stub_device.StackSize = 0x80; /* minimum value to appease SecuROM 5.x */
1097 stub_device.DriverObject = &stub_driver;
1099 *file = NULL;
1100 *device = &stub_device;
1102 return STATUS_SUCCESS;
1105 /***********************************************************************
1106 * IoGetAttachedDevice (NTOSKRNL.EXE.@)
1108 DEVICE_OBJECT* WINAPI IoGetAttachedDevice( DEVICE_OBJECT *device )
1110 DEVICE_OBJECT *result = device;
1112 TRACE( "(%p)\n", device );
1114 while (result->AttachedDevice)
1115 result = result->AttachedDevice;
1117 return result;
1121 /***********************************************************************
1122 * IoGetDeviceProperty (NTOSKRNL.EXE.@)
1124 NTSTATUS WINAPI IoGetDeviceProperty( DEVICE_OBJECT *device, DEVICE_REGISTRY_PROPERTY device_property,
1125 ULONG buffer_length, PVOID property_buffer, PULONG result_length )
1127 NTSTATUS status = STATUS_NOT_IMPLEMENTED;
1128 TRACE( "%p %d %u %p %p\n", device, device_property, buffer_length,
1129 property_buffer, result_length );
1130 switch (device_property)
1132 case DevicePropertyPhysicalDeviceObjectName:
1134 ULONG used_len, len = buffer_length + sizeof(OBJECT_NAME_INFORMATION);
1135 OBJECT_NAME_INFORMATION *name = HeapAlloc(GetProcessHeap(), 0, len);
1137 status = NtQueryObject(device->Reserved, ObjectNameInformation, name, len, &used_len);
1138 if (status == STATUS_SUCCESS)
1140 /* Ensure room for NULL termination */
1141 if (buffer_length >= name->Name.MaximumLength)
1142 memcpy(property_buffer, name->Name.Buffer, name->Name.MaximumLength);
1143 else
1144 status = STATUS_BUFFER_TOO_SMALL;
1145 *result_length = name->Name.MaximumLength;
1147 else
1149 if (status == STATUS_INFO_LENGTH_MISMATCH ||
1150 status == STATUS_BUFFER_OVERFLOW)
1152 status = STATUS_BUFFER_TOO_SMALL;
1153 *result_length = used_len - sizeof(OBJECT_NAME_INFORMATION);
1155 else
1156 *result_length = 0;
1158 HeapFree(GetProcessHeap(), 0, name);
1159 break;
1161 default:
1162 FIXME("unhandled property %d\n", device_property);
1164 return status;
1168 /***********************************************************************
1169 * IoCallDriver (NTOSKRNL.EXE.@)
1171 NTSTATUS WINAPI IoCallDriver( DEVICE_OBJECT *device, IRP *irp )
1173 PDRIVER_DISPATCH dispatch;
1174 IO_STACK_LOCATION *irpsp;
1175 NTSTATUS status;
1177 --irp->CurrentLocation;
1178 irpsp = --irp->Tail.Overlay.s.u2.CurrentStackLocation;
1179 dispatch = device->DriverObject->MajorFunction[irpsp->MajorFunction];
1181 if (TRACE_ON(relay))
1182 DPRINTF( "%04x:Call driver dispatch %p (device=%p,irp=%p)\n",
1183 GetCurrentThreadId(), dispatch, device, irp );
1185 status = dispatch( device, irp );
1187 if (TRACE_ON(relay))
1188 DPRINTF( "%04x:Ret driver dispatch %p (device=%p,irp=%p) retval=%08x\n",
1189 GetCurrentThreadId(), dispatch, device, irp, status );
1191 return status;
1195 /***********************************************************************
1196 * IofCallDriver (NTOSKRNL.EXE.@)
1198 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1199 DEFINE_FASTCALL2_ENTRYPOINT( IofCallDriver )
1200 NTSTATUS WINAPI __regs_IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
1201 #else
1202 NTSTATUS WINAPI IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
1203 #endif
1205 TRACE( "%p %p\n", device, irp );
1206 return IoCallDriver( device, irp );
1210 /***********************************************************************
1211 * IoGetRelatedDeviceObject (NTOSKRNL.EXE.@)
1213 PDEVICE_OBJECT WINAPI IoGetRelatedDeviceObject( PFILE_OBJECT obj )
1215 FIXME( "stub: %p\n", obj );
1216 return NULL;
1219 static CONFIGURATION_INFORMATION configuration_information;
1221 /***********************************************************************
1222 * IoGetConfigurationInformation (NTOSKRNL.EXE.@)
1224 PCONFIGURATION_INFORMATION WINAPI IoGetConfigurationInformation(void)
1226 FIXME( "partial stub\n" );
1227 /* FIXME: return actual devices on system */
1228 return &configuration_information;
1232 /***********************************************************************
1233 * IoIsWdmVersionAvailable (NTOSKRNL.EXE.@)
1235 NTSTATUS WINAPI IoIsWdmVersionAvailable(UCHAR MajorVersion, UCHAR MinorVersion)
1237 DWORD version;
1238 DWORD major;
1239 DWORD minor;
1241 TRACE( "%d, 0x%X\n", MajorVersion, MinorVersion );
1243 version = GetVersion();
1244 major = LOBYTE(version);
1245 minor = HIBYTE(LOWORD(version));
1247 if (MajorVersion == 6 && MinorVersion == 0)
1249 /* Windows Vista, Windows Server 2008, Windows 7 */
1251 else if (MajorVersion == 1)
1253 if (MinorVersion == 0x30)
1255 /* Windows server 2003 */
1256 MajorVersion = 6;
1257 MinorVersion = 0;
1259 else if (MinorVersion == 0x20)
1261 /* Windows XP */
1262 MajorVersion = 5;
1263 MinorVersion = 1;
1265 else if (MinorVersion == 0x10)
1267 /* Windows 2000 */
1268 MajorVersion = 5;
1269 MinorVersion = 0;
1271 else if (MinorVersion == 0x05)
1273 /* Windows ME */
1274 MajorVersion = 4;
1275 MinorVersion = 0x5a;
1277 else if (MinorVersion == 0x00)
1279 /* Windows 98 */
1280 MajorVersion = 4;
1281 MinorVersion = 0x0a;
1283 else
1285 FIXME( "unknown major %d minor 0x%X\n", MajorVersion, MinorVersion );
1286 return FALSE;
1289 else
1291 FIXME( "unknown major %d minor 0x%X\n", MajorVersion, MinorVersion );
1292 return FALSE;
1294 return major > MajorVersion || (major == MajorVersion && minor >= MinorVersion);
1298 /***********************************************************************
1299 * IoQueryDeviceDescription (NTOSKRNL.EXE.@)
1301 NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE itype, PULONG bus, PCONFIGURATION_TYPE ctype,
1302 PULONG cnum, PCONFIGURATION_TYPE ptype, PULONG pnum,
1303 PIO_QUERY_DEVICE_ROUTINE callout, PVOID context)
1305 FIXME( "(%p %p %p %p %p %p %p %p)\n", itype, bus, ctype, cnum, ptype, pnum, callout, context);
1306 return STATUS_NOT_IMPLEMENTED;
1310 /***********************************************************************
1311 * IoRegisterDriverReinitialization (NTOSKRNL.EXE.@)
1313 void WINAPI IoRegisterDriverReinitialization( PDRIVER_OBJECT obj, PDRIVER_REINITIALIZE reinit, PVOID context )
1315 FIXME( "stub: %p %p %p\n", obj, reinit, context );
1319 /***********************************************************************
1320 * IoRegisterShutdownNotification (NTOSKRNL.EXE.@)
1322 NTSTATUS WINAPI IoRegisterShutdownNotification( PDEVICE_OBJECT obj )
1324 FIXME( "stub: %p\n", obj );
1325 return STATUS_SUCCESS;
1329 /***********************************************************************
1330 * IoUnregisterShutdownNotification (NTOSKRNL.EXE.@)
1332 VOID WINAPI IoUnregisterShutdownNotification( PDEVICE_OBJECT obj )
1334 FIXME( "stub: %p\n", obj );
1338 /***********************************************************************
1339 * IoReportResourceUsage (NTOSKRNL.EXE.@)
1341 NTSTATUS WINAPI IoReportResourceUsage(PUNICODE_STRING name, PDRIVER_OBJECT drv_obj, PCM_RESOURCE_LIST drv_list,
1342 ULONG drv_size, PDRIVER_OBJECT dev_obj, PCM_RESOURCE_LIST dev_list,
1343 ULONG dev_size, BOOLEAN overwrite, PBOOLEAN detected)
1345 FIXME( "(%s, %p, %p, %u, %p, %p, %u, %d, %p): stub\n", debugstr_us(name),
1346 drv_obj, drv_list, drv_size, dev_obj, dev_list, dev_size, overwrite, detected );
1347 return STATUS_NOT_IMPLEMENTED;
1351 /***********************************************************************
1352 * IoCompleteRequest (NTOSKRNL.EXE.@)
1354 VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
1356 IO_STACK_LOCATION *irpsp;
1357 PIO_COMPLETION_ROUTINE routine;
1358 NTSTATUS status, stat;
1359 HANDLE handle;
1360 int call_flag = 0;
1362 TRACE( "%p %u\n", irp, priority_boost );
1364 status = irp->IoStatus.u.Status;
1365 while (irp->CurrentLocation <= irp->StackCount)
1367 irpsp = irp->Tail.Overlay.s.u2.CurrentStackLocation;
1368 routine = irpsp->CompletionRoutine;
1369 call_flag = 0;
1370 /* FIXME: add SL_INVOKE_ON_CANCEL support */
1371 if (routine)
1373 if ((irpsp->Control & SL_INVOKE_ON_SUCCESS) && STATUS_SUCCESS == status)
1374 call_flag = 1;
1375 if ((irpsp->Control & SL_INVOKE_ON_ERROR) && STATUS_SUCCESS != status)
1376 call_flag = 1;
1378 ++irp->CurrentLocation;
1379 ++irp->Tail.Overlay.s.u2.CurrentStackLocation;
1380 if (call_flag)
1382 TRACE( "calling %p( %p, %p, %p )\n", routine,
1383 irpsp->DeviceObject, irp, irpsp->Context );
1384 stat = routine( irpsp->DeviceObject, irp, irpsp->Context );
1385 TRACE( "CompletionRoutine returned %x\n", stat );
1386 if (STATUS_MORE_PROCESSING_REQUIRED == stat)
1387 return;
1391 handle = (HANDLE)irp->UserIosb;
1392 if (handle)
1394 void *out_buff = irp->UserBuffer;
1395 FILE_OBJECT *file = irp->Tail.Overlay.OriginalFileObject;
1397 SERVER_START_REQ( set_irp_result )
1399 req->handle = wine_server_obj_handle( handle );
1400 req->status = irp->IoStatus.u.Status;
1401 req->file_ptr = wine_server_client_ptr( file );
1402 if (irp->IoStatus.u.Status >= 0)
1404 req->size = irp->IoStatus.Information;
1405 if (out_buff) wine_server_add_data( req, out_buff, irp->IoStatus.Information );
1407 wine_server_call( req );
1409 SERVER_END_REQ;
1410 HeapFree( GetProcessHeap(), 0, out_buff );
1413 IoFreeIrp( irp );
1417 /***********************************************************************
1418 * IofCompleteRequest (NTOSKRNL.EXE.@)
1420 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1421 DEFINE_FASTCALL2_ENTRYPOINT( IofCompleteRequest )
1422 void WINAPI __regs_IofCompleteRequest( IRP *irp, UCHAR priority_boost )
1423 #else
1424 void WINAPI IofCompleteRequest( IRP *irp, UCHAR priority_boost )
1425 #endif
1427 TRACE( "%p %u\n", irp, priority_boost );
1428 IoCompleteRequest( irp, priority_boost );
1432 /***********************************************************************
1433 * InterlockedCompareExchange (NTOSKRNL.EXE.@)
1435 #ifdef DEFINE_FASTCALL3_ENTRYPOINT
1436 DEFINE_FASTCALL3_ENTRYPOINT( NTOSKRNL_InterlockedCompareExchange )
1437 LONG WINAPI __regs_NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
1438 #else
1439 LONG WINAPI NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
1440 #endif
1442 return InterlockedCompareExchange( dest, xchg, compare );
1446 /***********************************************************************
1447 * InterlockedDecrement (NTOSKRNL.EXE.@)
1449 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
1450 DEFINE_FASTCALL1_ENTRYPOINT( NTOSKRNL_InterlockedDecrement )
1451 LONG WINAPI __regs_NTOSKRNL_InterlockedDecrement( LONG volatile *dest )
1452 #else
1453 LONG WINAPI NTOSKRNL_InterlockedDecrement( LONG volatile *dest )
1454 #endif
1456 return InterlockedDecrement( dest );
1460 /***********************************************************************
1461 * InterlockedExchange (NTOSKRNL.EXE.@)
1463 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1464 DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedExchange )
1465 LONG WINAPI __regs_NTOSKRNL_InterlockedExchange( LONG volatile *dest, LONG val )
1466 #else
1467 LONG WINAPI NTOSKRNL_InterlockedExchange( LONG volatile *dest, LONG val )
1468 #endif
1470 return InterlockedExchange( dest, val );
1474 /***********************************************************************
1475 * InterlockedExchangeAdd (NTOSKRNL.EXE.@)
1477 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1478 DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedExchangeAdd )
1479 LONG WINAPI __regs_NTOSKRNL_InterlockedExchangeAdd( LONG volatile *dest, LONG incr )
1480 #else
1481 LONG WINAPI NTOSKRNL_InterlockedExchangeAdd( LONG volatile *dest, LONG incr )
1482 #endif
1484 return InterlockedExchangeAdd( dest, incr );
1488 /***********************************************************************
1489 * InterlockedIncrement (NTOSKRNL.EXE.@)
1491 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
1492 DEFINE_FASTCALL1_ENTRYPOINT( NTOSKRNL_InterlockedIncrement )
1493 LONG WINAPI __regs_NTOSKRNL_InterlockedIncrement( LONG volatile *dest )
1494 #else
1495 LONG WINAPI NTOSKRNL_InterlockedIncrement( LONG volatile *dest )
1496 #endif
1498 return InterlockedIncrement( dest );
1502 /***********************************************************************
1503 * InterlockedPopEntrySList (NTOSKRNL.EXE.@)
1505 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
1506 DEFINE_FASTCALL1_ENTRYPOINT( NTOSKRNL_InterlockedPopEntrySList )
1507 PSLIST_ENTRY WINAPI __regs_NTOSKRNL_InterlockedPopEntrySList( PSLIST_HEADER list )
1508 #else
1509 PSLIST_ENTRY WINAPI NTOSKRNL_InterlockedPopEntrySList( PSLIST_HEADER list )
1510 #endif
1512 return InterlockedPopEntrySList( list );
1516 /***********************************************************************
1517 * InterlockedPushEntrySList (NTOSKRNL.EXE.@)
1519 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1520 DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedPushEntrySList )
1521 PSLIST_ENTRY WINAPI __regs_NTOSKRNL_InterlockedPushEntrySList( PSLIST_HEADER list, PSLIST_ENTRY entry )
1522 #else
1523 PSLIST_ENTRY WINAPI NTOSKRNL_InterlockedPushEntrySList( PSLIST_HEADER list, PSLIST_ENTRY entry )
1524 #endif
1526 return InterlockedPushEntrySList( list, entry );
1530 /***********************************************************************
1531 * ExAllocatePool (NTOSKRNL.EXE.@)
1533 PVOID WINAPI ExAllocatePool( POOL_TYPE type, SIZE_T size )
1535 return ExAllocatePoolWithTag( type, size, 0 );
1539 /***********************************************************************
1540 * ExAllocatePoolWithQuota (NTOSKRNL.EXE.@)
1542 PVOID WINAPI ExAllocatePoolWithQuota( POOL_TYPE type, SIZE_T size )
1544 return ExAllocatePoolWithTag( type, size, 0 );
1548 /***********************************************************************
1549 * ExAllocatePoolWithTag (NTOSKRNL.EXE.@)
1551 PVOID WINAPI ExAllocatePoolWithTag( POOL_TYPE type, SIZE_T size, ULONG tag )
1553 /* FIXME: handle page alignment constraints */
1554 void *ret = HeapAlloc( GetProcessHeap(), 0, size );
1555 TRACE( "%lu pool %u -> %p\n", size, type, ret );
1556 return ret;
1560 /***********************************************************************
1561 * ExAllocatePoolWithQuotaTag (NTOSKRNL.EXE.@)
1563 PVOID WINAPI ExAllocatePoolWithQuotaTag( POOL_TYPE type, SIZE_T size, ULONG tag )
1565 return ExAllocatePoolWithTag( type, size, tag );
1569 /***********************************************************************
1570 * ExCreateCallback (NTOSKRNL.EXE.@)
1572 NTSTATUS WINAPI ExCreateCallback(PCALLBACK_OBJECT *obj, POBJECT_ATTRIBUTES attr,
1573 BOOLEAN create, BOOLEAN allow_multiple)
1575 FIXME("(%p, %p, %u, %u): stub\n", obj, attr, create, allow_multiple);
1577 return STATUS_NOT_IMPLEMENTED;
1581 /***********************************************************************
1582 * ExDeleteNPagedLookasideList (NTOSKRNL.EXE.@)
1584 void WINAPI ExDeleteNPagedLookasideList( PNPAGED_LOOKASIDE_LIST lookaside )
1586 FIXME("(%p) stub\n", lookaside);
1590 /***********************************************************************
1591 * ExDeletePagedLookasideList (NTOSKRNL.EXE.@)
1593 void WINAPI ExDeletePagedLookasideList( PPAGED_LOOKASIDE_LIST lookaside )
1595 FIXME("(%p) stub\n", lookaside);
1599 /***********************************************************************
1600 * ExFreePool (NTOSKRNL.EXE.@)
1602 void WINAPI ExFreePool( void *ptr )
1604 ExFreePoolWithTag( ptr, 0 );
1608 /***********************************************************************
1609 * ExFreePoolWithTag (NTOSKRNL.EXE.@)
1611 void WINAPI ExFreePoolWithTag( void *ptr, ULONG tag )
1613 TRACE( "%p\n", ptr );
1614 HeapFree( GetProcessHeap(), 0, ptr );
1618 /***********************************************************************
1619 * ExInitializeResourceLite (NTOSKRNL.EXE.@)
1621 NTSTATUS WINAPI ExInitializeResourceLite(PERESOURCE Resource)
1623 FIXME( "stub: %p\n", Resource );
1624 return STATUS_NOT_IMPLEMENTED;
1628 /***********************************************************************
1629 * ExInitializeNPagedLookasideList (NTOSKRNL.EXE.@)
1631 void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside,
1632 PALLOCATE_FUNCTION Allocate,
1633 PFREE_FUNCTION Free,
1634 ULONG Flags,
1635 SIZE_T Size,
1636 ULONG Tag,
1637 USHORT Depth)
1639 FIXME( "stub: %p, %p, %p, %u, %lu, %u, %u\n", Lookaside, Allocate, Free, Flags, Size, Tag, Depth );
1642 /***********************************************************************
1643 * ExInitializePagedLookasideList (NTOSKRNL.EXE.@)
1645 void WINAPI ExInitializePagedLookasideList(PPAGED_LOOKASIDE_LIST Lookaside,
1646 PALLOCATE_FUNCTION Allocate,
1647 PFREE_FUNCTION Free,
1648 ULONG Flags,
1649 SIZE_T Size,
1650 ULONG Tag,
1651 USHORT Depth)
1653 FIXME( "stub: %p, %p, %p, %u, %lu, %u, %u\n", Lookaside, Allocate, Free, Flags, Size, Tag, Depth );
1656 /***********************************************************************
1657 * ExInitializeZone (NTOSKRNL.EXE.@)
1659 NTSTATUS WINAPI ExInitializeZone(PZONE_HEADER Zone,
1660 ULONG BlockSize,
1661 PVOID InitialSegment,
1662 ULONG InitialSegmentSize)
1664 FIXME( "stub: %p, %u, %p, %u\n", Zone, BlockSize, InitialSegment, InitialSegmentSize );
1665 return STATUS_NOT_IMPLEMENTED;
1668 /***********************************************************************
1669 * FsRtlRegisterUncProvider (NTOSKRNL.EXE.@)
1671 NTSTATUS WINAPI FsRtlRegisterUncProvider(PHANDLE MupHandle, PUNICODE_STRING RedirDevName,
1672 BOOLEAN MailslotsSupported)
1674 FIXME("(%p %p %d): stub\n", MupHandle, RedirDevName, MailslotsSupported);
1675 return STATUS_NOT_IMPLEMENTED;
1678 /***********************************************************************
1679 * IoGetCurrentProcess / PsGetCurrentProcess (NTOSKRNL.EXE.@)
1681 PEPROCESS WINAPI IoGetCurrentProcess(void)
1683 FIXME("() stub\n");
1684 return NULL;
1687 /***********************************************************************
1688 * KeGetCurrentThread / PsGetCurrentThread (NTOSKRNL.EXE.@)
1690 PRKTHREAD WINAPI KeGetCurrentThread(void)
1692 FIXME("() stub\n");
1693 return NULL;
1696 /***********************************************************************
1697 * KeInitializeEvent (NTOSKRNL.EXE.@)
1699 void WINAPI KeInitializeEvent( PRKEVENT Event, EVENT_TYPE Type, BOOLEAN State )
1701 FIXME( "stub: %p %d %d\n", Event, Type, State );
1705 /***********************************************************************
1706 * KeInitializeMutex (NTOSKRNL.EXE.@)
1708 void WINAPI KeInitializeMutex(PRKMUTEX Mutex, ULONG Level)
1710 FIXME( "stub: %p, %u\n", Mutex, Level );
1714 /***********************************************************************
1715 * KeWaitForMutexObject (NTOSKRNL.EXE.@)
1717 NTSTATUS WINAPI KeWaitForMutexObject(PRKMUTEX Mutex, KWAIT_REASON WaitReason, KPROCESSOR_MODE WaitMode,
1718 BOOLEAN Alertable, PLARGE_INTEGER Timeout)
1720 FIXME( "stub: %p, %d, %d, %d, %p\n", Mutex, WaitReason, WaitMode, Alertable, Timeout );
1721 return STATUS_NOT_IMPLEMENTED;
1725 /***********************************************************************
1726 * KeReleaseMutex (NTOSKRNL.EXE.@)
1728 LONG WINAPI KeReleaseMutex(PRKMUTEX Mutex, BOOLEAN Wait)
1730 FIXME( "stub: %p, %d\n", Mutex, Wait );
1731 return STATUS_NOT_IMPLEMENTED;
1735 /***********************************************************************
1736 * KeInitializeSemaphore (NTOSKRNL.EXE.@)
1738 void WINAPI KeInitializeSemaphore( PRKSEMAPHORE Semaphore, LONG Count, LONG Limit )
1740 FIXME( "(%p %d %d) stub\n", Semaphore , Count, Limit );
1744 /***********************************************************************
1745 * KeInitializeSpinLock (NTOSKRNL.EXE.@)
1747 void WINAPI KeInitializeSpinLock( PKSPIN_LOCK SpinLock )
1749 FIXME( "stub: %p\n", SpinLock );
1753 /***********************************************************************
1754 * KeInitializeTimerEx (NTOSKRNL.EXE.@)
1756 void WINAPI KeInitializeTimerEx( PKTIMER Timer, TIMER_TYPE Type )
1758 FIXME( "stub: %p %d\n", Timer, Type );
1762 /***********************************************************************
1763 * KeInitializeTimer (NTOSKRNL.EXE.@)
1765 void WINAPI KeInitializeTimer( PKTIMER Timer )
1767 KeInitializeTimerEx(Timer, NotificationTimer);
1770 /***********************************************************************
1771 * KeInsertQueue (NTOSKRNL.EXE.@)
1773 LONG WINAPI KeInsertQueue(PRKQUEUE Queue, PLIST_ENTRY Entry)
1775 FIXME( "stub: %p %p\n", Queue, Entry );
1776 return 0;
1779 /**********************************************************************
1780 * KeQueryActiveProcessors (NTOSKRNL.EXE.@)
1782 * Return the active Processors as bitmask
1784 * RETURNS
1785 * active Processors as bitmask
1788 KAFFINITY WINAPI KeQueryActiveProcessors( void )
1790 DWORD_PTR AffinityMask;
1792 GetProcessAffinityMask( GetCurrentProcess(), &AffinityMask, NULL);
1793 return AffinityMask;
1797 /**********************************************************************
1798 * KeQueryInterruptTime (NTOSKRNL.EXE.@)
1800 * Return the interrupt time count
1803 ULONGLONG WINAPI KeQueryInterruptTime( void )
1805 LARGE_INTEGER totaltime;
1807 KeQueryTickCount(&totaltime);
1808 return totaltime.QuadPart;
1812 /***********************************************************************
1813 * KeQuerySystemTime (NTOSKRNL.EXE.@)
1815 void WINAPI KeQuerySystemTime( LARGE_INTEGER *time )
1817 NtQuerySystemTime( time );
1821 /***********************************************************************
1822 * KeQueryTickCount (NTOSKRNL.EXE.@)
1824 void WINAPI KeQueryTickCount( LARGE_INTEGER *count )
1826 count->QuadPart = NtGetTickCount();
1827 /* update the global variable too */
1828 KeTickCount.LowPart = count->u.LowPart;
1829 KeTickCount.High1Time = count->u.HighPart;
1830 KeTickCount.High2Time = count->u.HighPart;
1834 /***********************************************************************
1835 * KeReleaseSemaphore (NTOSKRNL.EXE.@)
1837 LONG WINAPI KeReleaseSemaphore( PRKSEMAPHORE Semaphore, KPRIORITY Increment,
1838 LONG Adjustment, BOOLEAN Wait )
1840 FIXME("(%p %d %d %d) stub\n", Semaphore, Increment, Adjustment, Wait );
1841 return 0;
1845 /***********************************************************************
1846 * KeQueryTimeIncrement (NTOSKRNL.EXE.@)
1848 ULONG WINAPI KeQueryTimeIncrement(void)
1850 return 10000;
1854 /***********************************************************************
1855 * KeResetEvent (NTOSKRNL.EXE.@)
1857 LONG WINAPI KeResetEvent( PRKEVENT Event )
1859 FIXME("(%p): stub\n", Event);
1860 return 0;
1864 /***********************************************************************
1865 * KeSetEvent (NTOSKRNL.EXE.@)
1867 LONG WINAPI KeSetEvent( PRKEVENT Event, KPRIORITY Increment, BOOLEAN Wait )
1869 FIXME("(%p, %d, %d): stub\n", Event, Increment, Wait);
1870 return 0;
1874 /***********************************************************************
1875 * KeSetPriorityThread (NTOSKRNL.EXE.@)
1877 KPRIORITY WINAPI KeSetPriorityThread( PKTHREAD Thread, KPRIORITY Priority )
1879 FIXME("(%p %d)\n", Thread, Priority);
1880 return Priority;
1883 /***********************************************************************
1884 * KeSetSystemAffinityThread (NTOSKRNL.EXE.@)
1886 VOID WINAPI KeSetSystemAffinityThread(KAFFINITY Affinity)
1888 FIXME("(%lx) stub\n", Affinity);
1891 /***********************************************************************
1892 * KeWaitForSingleObject (NTOSKRNL.EXE.@)
1894 NTSTATUS WINAPI KeWaitForSingleObject(PVOID Object,
1895 KWAIT_REASON WaitReason,
1896 KPROCESSOR_MODE WaitMode,
1897 BOOLEAN Alertable,
1898 PLARGE_INTEGER Timeout)
1900 FIXME( "stub: %p, %d, %d, %d, %p\n", Object, WaitReason, WaitMode, Alertable, Timeout );
1901 return STATUS_NOT_IMPLEMENTED;
1904 /***********************************************************************
1905 * IoRegisterFileSystem (NTOSKRNL.EXE.@)
1907 VOID WINAPI IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject)
1909 FIXME("(%p): stub\n", DeviceObject);
1912 /***********************************************************************
1913 * IoUnregisterFileSystem (NTOSKRNL.EXE.@)
1915 VOID WINAPI IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject)
1917 FIXME("(%p): stub\n", DeviceObject);
1920 /***********************************************************************
1921 * MmAllocateNonCachedMemory (NTOSKRNL.EXE.@)
1923 PVOID WINAPI MmAllocateNonCachedMemory( SIZE_T size )
1925 TRACE( "%lu\n", size );
1926 return VirtualAlloc( NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE|PAGE_NOCACHE );
1929 /***********************************************************************
1930 * MmAllocateContiguousMemory (NTOSKRNL.EXE.@)
1932 PVOID WINAPI MmAllocateContiguousMemory( SIZE_T size, PHYSICAL_ADDRESS highest_valid_address )
1934 FIXME( "%lu, %s stub\n", size, wine_dbgstr_longlong(highest_valid_address.QuadPart) );
1935 return NULL;
1938 /***********************************************************************
1939 * MmAllocateContiguousMemorySpecifyCache (NTOSKRNL.EXE.@)
1941 PVOID WINAPI MmAllocateContiguousMemorySpecifyCache( SIZE_T size,
1942 PHYSICAL_ADDRESS lowest_valid_address,
1943 PHYSICAL_ADDRESS highest_valid_address,
1944 PHYSICAL_ADDRESS BoundaryAddressMultiple,
1945 MEMORY_CACHING_TYPE CacheType )
1947 FIXME(": stub\n");
1948 return NULL;
1951 /***********************************************************************
1952 * MmAllocatePagesForMdl (NTOSKRNL.EXE.@)
1954 PMDL WINAPI MmAllocatePagesForMdl(PHYSICAL_ADDRESS lowaddress, PHYSICAL_ADDRESS highaddress,
1955 PHYSICAL_ADDRESS skipbytes, SIZE_T size)
1957 FIXME("%s %s %s %lu: stub\n", wine_dbgstr_longlong(lowaddress.QuadPart), wine_dbgstr_longlong(highaddress.QuadPart),
1958 wine_dbgstr_longlong(skipbytes.QuadPart), size);
1959 return NULL;
1962 /***********************************************************************
1963 * MmFreeNonCachedMemory (NTOSKRNL.EXE.@)
1965 void WINAPI MmFreeNonCachedMemory( void *addr, SIZE_T size )
1967 TRACE( "%p %lu\n", addr, size );
1968 VirtualFree( addr, 0, MEM_RELEASE );
1971 /***********************************************************************
1972 * MmIsAddressValid (NTOSKRNL.EXE.@)
1974 * Check if the process can access the virtual address without a pagefault
1976 * PARAMS
1977 * VirtualAddress [I] Address to check
1979 * RETURNS
1980 * Failure: FALSE
1981 * Success: TRUE (Accessing the Address works without a Pagefault)
1984 BOOLEAN WINAPI MmIsAddressValid(PVOID VirtualAddress)
1986 TRACE("(%p)\n", VirtualAddress);
1987 return !IsBadWritePtr(VirtualAddress, 1);
1990 /***********************************************************************
1991 * MmMapIoSpace (NTOSKRNL.EXE.@)
1993 PVOID WINAPI MmMapIoSpace( PHYSICAL_ADDRESS PhysicalAddress, DWORD NumberOfBytes, DWORD CacheType )
1995 FIXME( "stub: 0x%08x%08x, %d, %d\n", PhysicalAddress.u.HighPart, PhysicalAddress.u.LowPart, NumberOfBytes, CacheType );
1996 return NULL;
2000 /***********************************************************************
2001 * MmLockPagableSectionByHandle (NTOSKRNL.EXE.@)
2003 VOID WINAPI MmLockPagableSectionByHandle(PVOID ImageSectionHandle)
2005 FIXME("stub %p\n", ImageSectionHandle);
2008 /***********************************************************************
2009 * MmMapLockedPagesSpecifyCache (NTOSKRNL.EXE.@)
2011 PVOID WINAPI MmMapLockedPagesSpecifyCache(PMDLX MemoryDescriptorList, KPROCESSOR_MODE AccessMode, MEMORY_CACHING_TYPE CacheType,
2012 PVOID BaseAddress, ULONG BugCheckOnFailure, MM_PAGE_PRIORITY Priority)
2014 FIXME("(%p, %u, %u, %p, %u, %u): stub\n", MemoryDescriptorList, AccessMode, CacheType, BaseAddress, BugCheckOnFailure, Priority);
2016 return NULL;
2019 /***********************************************************************
2020 * MmUnlockPagableImageSection (NTOSKRNL.EXE.@)
2022 VOID WINAPI MmUnlockPagableImageSection(PVOID ImageSectionHandle)
2024 FIXME("stub %p\n", ImageSectionHandle);
2027 /***********************************************************************
2028 * MmPageEntireDriver (NTOSKRNL.EXE.@)
2030 PVOID WINAPI MmPageEntireDriver(PVOID AddrInSection)
2032 TRACE("%p\n", AddrInSection);
2033 return AddrInSection;
2037 /***********************************************************************
2038 * MmProbeAndLockPages (NTOSKRNL.EXE.@)
2040 void WINAPI MmProbeAndLockPages(PMDLX MemoryDescriptorList, KPROCESSOR_MODE AccessMode, LOCK_OPERATION Operation)
2042 FIXME("(%p, %u, %u): stub\n", MemoryDescriptorList, AccessMode, Operation);
2046 /***********************************************************************
2047 * MmResetDriverPaging (NTOSKRNL.EXE.@)
2049 void WINAPI MmResetDriverPaging(PVOID AddrInSection)
2051 TRACE("%p\n", AddrInSection);
2055 /***********************************************************************
2056 * MmUnlockPages (NTOSKRNL.EXE.@)
2058 void WINAPI MmUnlockPages(PMDLX MemoryDescriptorList)
2060 FIXME("(%p): stub\n", MemoryDescriptorList);
2064 /***********************************************************************
2065 * MmUnmapIoSpace (NTOSKRNL.EXE.@)
2067 VOID WINAPI MmUnmapIoSpace( PVOID BaseAddress, SIZE_T NumberOfBytes )
2069 FIXME( "stub: %p, %lu\n", BaseAddress, NumberOfBytes );
2073 /***********************************************************************
2074 * ObReferenceObjectByHandle (NTOSKRNL.EXE.@)
2076 NTSTATUS WINAPI ObReferenceObjectByHandle( HANDLE obj, ACCESS_MASK access,
2077 POBJECT_TYPE type,
2078 KPROCESSOR_MODE mode, PVOID* ptr,
2079 POBJECT_HANDLE_INFORMATION info)
2081 FIXME( "stub: %p %x %p %d %p %p\n", obj, access, type, mode, ptr, info);
2082 return STATUS_NOT_IMPLEMENTED;
2085 /***********************************************************************
2086 * ObReferenceObjectByName (NTOSKRNL.EXE.@)
2088 NTSTATUS WINAPI ObReferenceObjectByName( UNICODE_STRING *ObjectName,
2089 ULONG Attributes,
2090 ACCESS_STATE *AccessState,
2091 ACCESS_MASK DesiredAccess,
2092 POBJECT_TYPE ObjectType,
2093 KPROCESSOR_MODE AccessMode,
2094 void *ParseContext,
2095 void **Object)
2097 struct wine_driver *driver;
2098 struct wine_rb_entry *entry;
2100 TRACE("mostly-stub:%s %i %p %i %p %i %p %p\n", debugstr_us(ObjectName),
2101 Attributes, AccessState, DesiredAccess, ObjectType, AccessMode,
2102 ParseContext, Object);
2104 if (AccessState) FIXME("Unhandled AccessState\n");
2105 if (DesiredAccess) FIXME("Unhandled DesiredAccess\n");
2106 if (ParseContext) FIXME("Unhandled ParseContext\n");
2107 if (ObjectType) FIXME("Unhandled ObjectType\n");
2109 if (AccessMode != KernelMode)
2111 FIXME("UserMode access not implemented\n");
2112 return STATUS_NOT_IMPLEMENTED;
2115 EnterCriticalSection(&drivers_cs);
2116 entry = wine_rb_get(&wine_drivers, ObjectName);
2117 LeaveCriticalSection(&drivers_cs);
2118 if (!entry)
2120 FIXME("Object (%s) not found, may not be tracked.\n", debugstr_us(ObjectName));
2121 return STATUS_NOT_IMPLEMENTED;
2124 driver = WINE_RB_ENTRY_VALUE(entry, struct wine_driver, entry);
2125 *Object = &driver->driver_obj;
2126 return STATUS_SUCCESS;
2130 static void ObReferenceObject( void *obj )
2132 TRACE( "(%p): stub\n", obj );
2136 /***********************************************************************
2137 * ObDereferenceObject (NTOSKRNL.EXE.@)
2139 void WINAPI ObDereferenceObject( void *obj )
2141 TRACE( "(%p): stub\n", obj );
2145 /***********************************************************************
2146 * ObfReferenceObject (NTOSKRNL.EXE.@)
2148 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
2149 DEFINE_FASTCALL1_ENTRYPOINT( ObfReferenceObject )
2150 void WINAPI __regs_ObfReferenceObject( void *obj )
2151 #else
2152 void WINAPI ObfReferenceObject( void *obj )
2153 #endif
2155 ObReferenceObject( obj );
2159 /***********************************************************************
2160 * ObfDereferenceObject (NTOSKRNL.EXE.@)
2162 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
2163 DEFINE_FASTCALL1_ENTRYPOINT( ObfDereferenceObject )
2164 void WINAPI __regs_ObfDereferenceObject( void *obj )
2165 #else
2166 void WINAPI ObfDereferenceObject( void *obj )
2167 #endif
2169 ObDereferenceObject( obj );
2173 /***********************************************************************
2174 * IoGetAttachedDeviceReference (NTOSKRNL.EXE.@)
2176 DEVICE_OBJECT* WINAPI IoGetAttachedDeviceReference( DEVICE_OBJECT *device )
2178 DEVICE_OBJECT *result = IoGetAttachedDevice( device );
2179 ObReferenceObject( result );
2180 return result;
2184 /***********************************************************************
2185 * PsCreateSystemThread (NTOSKRNL.EXE.@)
2187 NTSTATUS WINAPI PsCreateSystemThread(PHANDLE ThreadHandle, ULONG DesiredAccess,
2188 POBJECT_ATTRIBUTES ObjectAttributes,
2189 HANDLE ProcessHandle, PCLIENT_ID ClientId,
2190 PKSTART_ROUTINE StartRoutine, PVOID StartContext)
2192 if (!ProcessHandle) ProcessHandle = GetCurrentProcess();
2193 return RtlCreateUserThread(ProcessHandle, 0, FALSE, 0, 0,
2194 0, StartRoutine, StartContext,
2195 ThreadHandle, ClientId);
2198 /***********************************************************************
2199 * PsGetCurrentProcessId (NTOSKRNL.EXE.@)
2201 HANDLE WINAPI PsGetCurrentProcessId(void)
2203 if (GetCurrentThreadId() == request_thread)
2204 return UlongToHandle(client_pid);
2205 return UlongToHandle(GetCurrentProcessId());
2209 /***********************************************************************
2210 * PsGetCurrentThreadId (NTOSKRNL.EXE.@)
2212 HANDLE WINAPI PsGetCurrentThreadId(void)
2214 if (GetCurrentThreadId() == request_thread)
2215 return UlongToHandle(client_tid);
2216 return UlongToHandle(GetCurrentThreadId());
2220 /***********************************************************************
2221 * PsGetVersion (NTOSKRNL.EXE.@)
2223 BOOLEAN WINAPI PsGetVersion(ULONG *major, ULONG *minor, ULONG *build, UNICODE_STRING *version )
2225 RTL_OSVERSIONINFOEXW info;
2227 info.dwOSVersionInfoSize = sizeof(info);
2228 RtlGetVersion( &info );
2229 if (major) *major = info.dwMajorVersion;
2230 if (minor) *minor = info.dwMinorVersion;
2231 if (build) *build = info.dwBuildNumber;
2233 if (version)
2235 #if 0 /* FIXME: GameGuard passes an uninitialized pointer in version->Buffer */
2236 size_t len = min( strlenW(info.szCSDVersion)*sizeof(WCHAR), version->MaximumLength );
2237 memcpy( version->Buffer, info.szCSDVersion, len );
2238 if (len < version->MaximumLength) version->Buffer[len / sizeof(WCHAR)] = 0;
2239 version->Length = len;
2240 #endif
2242 return TRUE;
2246 /***********************************************************************
2247 * PsImpersonateClient (NTOSKRNL.EXE.@)
2249 NTSTATUS WINAPI PsImpersonateClient(PETHREAD Thread, PACCESS_TOKEN Token, BOOLEAN CopyOnOpen,
2250 BOOLEAN EffectiveOnly, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2252 FIXME("(%p, %p, %u, %u, %u): stub\n", Thread, Token, CopyOnOpen, EffectiveOnly, ImpersonationLevel);
2254 return STATUS_NOT_IMPLEMENTED;
2258 /***********************************************************************
2259 * PsSetCreateProcessNotifyRoutine (NTOSKRNL.EXE.@)
2261 NTSTATUS WINAPI PsSetCreateProcessNotifyRoutine( PCREATE_PROCESS_NOTIFY_ROUTINE callback, BOOLEAN remove )
2263 FIXME( "stub: %p %d\n", callback, remove );
2264 return STATUS_SUCCESS;
2268 /***********************************************************************
2269 * PsSetCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
2271 NTSTATUS WINAPI PsSetCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
2273 FIXME( "stub: %p\n", NotifyRoutine );
2274 return STATUS_SUCCESS;
2278 /***********************************************************************
2279 * PsRemoveCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
2281 NTSTATUS WINAPI PsRemoveCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
2283 FIXME( "stub: %p\n", NotifyRoutine );
2284 return STATUS_SUCCESS;
2288 /***********************************************************************
2289 * PsRemoveLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
2291 NTSTATUS WINAPI PsRemoveLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
2293 FIXME( "stub: %p\n", NotifyRoutine );
2294 return STATUS_SUCCESS;
2298 /***********************************************************************
2299 * PsTerminateSystemThread (NTOSKRNL.EXE.@)
2301 NTSTATUS WINAPI PsTerminateSystemThread(NTSTATUS ExitStatus)
2303 FIXME( "stub: %u\n", ExitStatus );
2304 return STATUS_NOT_IMPLEMENTED;
2308 /***********************************************************************
2309 * MmGetSystemRoutineAddress (NTOSKRNL.EXE.@)
2311 PVOID WINAPI MmGetSystemRoutineAddress(PUNICODE_STRING SystemRoutineName)
2313 HMODULE hMod;
2314 STRING routineNameA;
2315 PVOID pFunc = NULL;
2317 static const WCHAR ntoskrnlW[] = {'n','t','o','s','k','r','n','l','.','e','x','e',0};
2318 static const WCHAR halW[] = {'h','a','l','.','d','l','l',0};
2320 if (!SystemRoutineName) return NULL;
2322 if (RtlUnicodeStringToAnsiString( &routineNameA, SystemRoutineName, TRUE ) == STATUS_SUCCESS)
2324 /* We only support functions exported from ntoskrnl.exe or hal.dll */
2325 hMod = GetModuleHandleW( ntoskrnlW );
2326 pFunc = GetProcAddress( hMod, routineNameA.Buffer );
2327 if (!pFunc)
2329 hMod = GetModuleHandleW( halW );
2330 if (hMod) pFunc = GetProcAddress( hMod, routineNameA.Buffer );
2332 RtlFreeAnsiString( &routineNameA );
2335 if (pFunc)
2336 TRACE( "%s -> %p\n", debugstr_us(SystemRoutineName), pFunc );
2337 else
2338 FIXME( "%s not found\n", debugstr_us(SystemRoutineName) );
2339 return pFunc;
2343 /***********************************************************************
2344 * MmQuerySystemSize (NTOSKRNL.EXE.@)
2346 MM_SYSTEMSIZE WINAPI MmQuerySystemSize(void)
2348 FIXME("stub\n");
2349 return MmLargeSystem;
2352 /***********************************************************************
2353 * KeInitializeDpc (NTOSKRNL.EXE.@)
2355 VOID WINAPI KeInitializeDpc(PRKDPC Dpc, PKDEFERRED_ROUTINE DeferredRoutine, PVOID DeferredContext)
2357 FIXME("stub\n");
2360 /***********************************************************************
2361 * READ_REGISTER_BUFFER_UCHAR (NTOSKRNL.EXE.@)
2363 VOID WINAPI READ_REGISTER_BUFFER_UCHAR(PUCHAR Register, PUCHAR Buffer, ULONG Count)
2365 FIXME("stub\n");
2368 /*****************************************************
2369 * PoSetPowerState (NTOSKRNL.EXE.@)
2371 POWER_STATE WINAPI PoSetPowerState(PDEVICE_OBJECT DeviceObject, POWER_STATE_TYPE Type, POWER_STATE State)
2373 FIXME("(%p %u %u) stub\n", DeviceObject, Type, State.DeviceState);
2374 return State;
2377 /*****************************************************
2378 * IoWMIRegistrationControl (NTOSKRNL.EXE.@)
2380 NTSTATUS WINAPI IoWMIRegistrationControl(PDEVICE_OBJECT DeviceObject, ULONG Action)
2382 FIXME("(%p %u) stub\n", DeviceObject, Action);
2383 return STATUS_SUCCESS;
2386 /*****************************************************
2387 * PsSetLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
2389 NTSTATUS WINAPI PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine)
2391 FIXME("(%p) stub\n", routine);
2392 return STATUS_SUCCESS;
2395 /*****************************************************
2396 * PsLookupProcessByProcessId (NTOSKRNL.EXE.@)
2398 NTSTATUS WINAPI PsLookupProcessByProcessId(HANDLE processid, PEPROCESS *process)
2400 static int once;
2401 if (!once++) FIXME("(%p %p) stub\n", processid, process);
2402 return STATUS_NOT_IMPLEMENTED;
2406 /*****************************************************
2407 * IoSetThreadHardErrorMode (NTOSKRNL.EXE.@)
2409 BOOLEAN WINAPI IoSetThreadHardErrorMode(BOOLEAN EnableHardErrors)
2411 FIXME("stub\n");
2412 return FALSE;
2416 /*****************************************************
2417 * IoInitializeRemoveLockEx (NTOSKRNL.EXE.@)
2419 VOID WINAPI IoInitializeRemoveLockEx(PIO_REMOVE_LOCK lock, ULONG tag,
2420 ULONG maxmin, ULONG high, ULONG size)
2422 FIXME("(%p %u %u %u %u) stub\n", lock, tag, maxmin, high, size);
2426 /*****************************************************
2427 * IoAcquireRemoveLockEx (NTOSKRNL.EXE.@)
2430 NTSTATUS WINAPI IoAcquireRemoveLockEx(PIO_REMOVE_LOCK lock, PVOID tag,
2431 LPCSTR file, ULONG line, ULONG lock_size)
2433 FIXME("(%p, %p, %s, %u, %u): stub\n", lock, tag, debugstr_a(file), line, lock_size);
2435 return STATUS_NOT_IMPLEMENTED;
2439 /*****************************************************
2440 * DllMain
2442 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
2444 static void *handler;
2445 LARGE_INTEGER count;
2447 switch(reason)
2449 case DLL_PROCESS_ATTACH:
2450 DisableThreadLibraryCalls( inst );
2451 #if defined(__i386__) || defined(__x86_64__)
2452 handler = RtlAddVectoredExceptionHandler( TRUE, vectored_handler );
2453 #endif
2454 KeQueryTickCount( &count ); /* initialize the global KeTickCount */
2455 break;
2456 case DLL_PROCESS_DETACH:
2457 if (reserved) break;
2458 RtlRemoveVectoredExceptionHandler( handler );
2459 break;
2461 return TRUE;
2464 /*****************************************************
2465 * Ke386IoSetAccessProcess (NTOSKRNL.EXE.@)
2467 BOOLEAN WINAPI Ke386IoSetAccessProcess(PEPROCESS *process, ULONG flag)
2469 FIXME("(%p %d) stub\n", process, flag);
2470 return FALSE;
2473 /*****************************************************
2474 * Ke386SetIoAccessMap (NTOSKRNL.EXE.@)
2476 BOOLEAN WINAPI Ke386SetIoAccessMap(ULONG flag, PVOID buffer)
2478 FIXME("(%d %p) stub\n", flag, buffer);
2479 return FALSE;
2482 /*****************************************************
2483 * IoCreateSynchronizationEvent (NTOSKRNL.EXE.@)
2485 PKEVENT WINAPI IoCreateSynchronizationEvent(PUNICODE_STRING name, PHANDLE handle)
2487 FIXME("(%p %p) stub\n", name, handle);
2488 return NULL;
2491 /*****************************************************
2492 * IoStartNextPacket (NTOSKRNL.EXE.@)
2494 VOID WINAPI IoStartNextPacket(PDEVICE_OBJECT deviceobject, BOOLEAN cancelable)
2496 FIXME("(%p %d) stub\n", deviceobject, cancelable);
2499 /*****************************************************
2500 * ObQueryNameString (NTOSKRNL.EXE.@)
2502 NTSTATUS WINAPI ObQueryNameString(PVOID object, POBJECT_NAME_INFORMATION name, ULONG maxlength, PULONG returnlength)
2504 FIXME("(%p %p %u %p) stub\n", object, name, maxlength, returnlength);
2505 return STATUS_NOT_IMPLEMENTED;
2508 /*****************************************************
2509 * IoRegisterPlugPlayNotification (NTOSKRNL.EXE.@)
2511 NTSTATUS WINAPI IoRegisterPlugPlayNotification(IO_NOTIFICATION_EVENT_CATEGORY category, ULONG flags, PVOID data,
2512 PDRIVER_OBJECT driver, PDRIVER_NOTIFICATION_CALLBACK_ROUTINE callback,
2513 PVOID context, PVOID *notification)
2515 FIXME("(%u %u %p %p %p %p %p) stub\n", category, flags, data, driver, callback, context, notification);
2516 return STATUS_SUCCESS;
2519 /*****************************************************
2520 * IoCsqInitialize (NTOSKRNL.EXE.@)
2522 NTSTATUS WINAPI IoCsqInitialize(PIO_CSQ csq, PIO_CSQ_INSERT_IRP insert_irp, PIO_CSQ_REMOVE_IRP remove_irp,
2523 PIO_CSQ_PEEK_NEXT_IRP peek_irp, PIO_CSQ_ACQUIRE_LOCK acquire_lock,
2524 PIO_CSQ_RELEASE_LOCK release_lock, PIO_CSQ_COMPLETE_CANCELED_IRP complete_irp)
2526 FIXME("(%p %p %p %p %p %p %p) stub\n",
2527 csq, insert_irp, remove_irp, peek_irp, acquire_lock, release_lock, complete_irp);
2528 return STATUS_SUCCESS;
2531 /***********************************************************************
2532 * ExAcquireResourceExclusiveLite (NTOSKRNL.EXE.@)
2534 BOOLEAN WINAPI ExAcquireResourceExclusiveLite( PERESOURCE resource, BOOLEAN wait )
2536 FIXME( ":%p %u stub\n", resource, wait );
2537 return TRUE;
2540 /***********************************************************************
2541 * ExDeleteResourceLite (NTOSKRNL.EXE.@)
2543 NTSTATUS WINAPI ExDeleteResourceLite(PERESOURCE resource)
2545 FIXME("(%p): stub\n", resource);
2546 return STATUS_NOT_IMPLEMENTED;
2549 /*****************************************************
2550 * ExInterlockedRemoveHeadList (NTOSKRNL.EXE.@)
2552 PLIST_ENTRY WINAPI ExInterlockedRemoveHeadList(PLIST_ENTRY head, PKSPIN_LOCK lock)
2554 FIXME("(%p %p) stub\n", head, lock);
2555 return NULL;
2558 /***********************************************************************
2559 * ExfInterlockedRemoveHeadList (NTOSKRNL.EXE.@)
2561 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
2562 DEFINE_FASTCALL2_ENTRYPOINT( ExfInterlockedRemoveHeadList )
2563 PLIST_ENTRY WINAPI __regs_ExfInterlockedRemoveHeadList(PLIST_ENTRY head, PKSPIN_LOCK lock)
2564 #else
2565 PLIST_ENTRY WINAPI ExfInterlockedRemoveHeadList(PLIST_ENTRY head, PKSPIN_LOCK lock)
2566 #endif
2568 FIXME("(%p %p) stub\n", head, lock);
2569 return ExInterlockedRemoveHeadList( head, lock );
2572 /***********************************************************************
2573 * ExReleaseResourceForThreadLite (NTOSKRNL.EXE.@)
2575 void WINAPI ExReleaseResourceForThreadLite( PERESOURCE resource, ERESOURCE_THREAD tid )
2577 FIXME( "stub: %p %lu\n", resource, tid );
2580 /***********************************************************************
2581 * KeEnterCriticalRegion (NTOSKRNL.EXE.@)
2583 void WINAPI KeEnterCriticalRegion(void)
2585 FIXME(": stub\n");
2588 /***********************************************************************
2589 * KeLeaveCriticalRegion (NTOSKRNL.EXE.@)
2591 void WINAPI KeLeaveCriticalRegion(void)
2593 FIXME(": stub\n");
2596 /***********************************************************************
2597 * ProbeForRead (NTOSKRNL.EXE.@)
2599 void WINAPI ProbeForRead(void *address, SIZE_T length, ULONG alignment)
2601 FIXME("(%p %lu %u) stub\n", address, length, alignment);
2604 /***********************************************************************
2605 * ProbeForWrite (NTOSKRNL.EXE.@)
2607 void WINAPI ProbeForWrite(void *address, SIZE_T length, ULONG alignment)
2609 FIXME("(%p %lu %u) stub\n", address, length, alignment);
2612 /***********************************************************************
2613 * CmRegisterCallback (NTOSKRNL.EXE.@)
2615 NTSTATUS WINAPI CmRegisterCallback(EX_CALLBACK_FUNCTION *function, void *context, LARGE_INTEGER *cookie)
2617 FIXME("(%p %p %p): stub\n", function, context, cookie);
2618 return STATUS_NOT_IMPLEMENTED;
2621 /***********************************************************************
2622 * CmUnRegisterCallback (NTOSKRNL.EXE.@)
2624 NTSTATUS WINAPI CmUnRegisterCallback(LARGE_INTEGER cookie)
2626 FIXME("(%s): stub\n", wine_dbgstr_longlong(cookie.QuadPart));
2627 return STATUS_NOT_IMPLEMENTED;
2630 /***********************************************************************
2631 * KeDelayExecutionThread (NTOSKRNL.EXE.@)
2633 NTSTATUS WINAPI KeDelayExecutionThread(KPROCESSOR_MODE waitmode, BOOLEAN alertable, PLARGE_INTEGER interval)
2635 FIXME("(%u, %u, %p): stub\n", waitmode, alertable, interval);
2636 return STATUS_NOT_IMPLEMENTED;
2639 /***********************************************************************
2640 * IoAttachDevice (NTOSKRNL.EXE.@)
2642 NTSTATUS WINAPI IoAttachDevice(DEVICE_OBJECT *source, UNICODE_STRING *target, DEVICE_OBJECT *attached)
2644 FIXME("(%p, %s, %p): stub\n", source, debugstr_us(target), attached);
2645 return STATUS_NOT_IMPLEMENTED;
2649 static NTSTATUS open_driver( const UNICODE_STRING *service_name, SC_HANDLE *service )
2651 QUERY_SERVICE_CONFIGW *service_config = NULL;
2652 SC_HANDLE manager_handle;
2653 DWORD config_size = 0;
2654 WCHAR *name;
2656 if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, service_name->Length + sizeof(WCHAR) )))
2657 return STATUS_NO_MEMORY;
2659 memcpy( name, service_name->Buffer, service_name->Length );
2660 name[ service_name->Length / sizeof(WCHAR) ] = 0;
2662 if (strncmpW( name, servicesW, strlenW(servicesW) ))
2664 FIXME( "service name %s is not a keypath\n", debugstr_us(service_name) );
2665 RtlFreeHeap( GetProcessHeap(), 0, name );
2666 return STATUS_NOT_IMPLEMENTED;
2669 if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
2671 WARN( "failed to connect to service manager\n" );
2672 RtlFreeHeap( GetProcessHeap(), 0, name );
2673 return STATUS_NOT_SUPPORTED;
2676 *service = OpenServiceW( manager_handle, name + strlenW(servicesW), SERVICE_ALL_ACCESS );
2677 RtlFreeHeap( GetProcessHeap(), 0, name );
2678 CloseServiceHandle( manager_handle );
2680 if (!*service)
2682 WARN( "failed to open service %s\n", debugstr_us(service_name) );
2683 return STATUS_UNSUCCESSFUL;
2686 QueryServiceConfigW( *service, NULL, 0, &config_size );
2687 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2689 WARN( "failed to query service config\n" );
2690 goto error;
2693 if (!(service_config = RtlAllocateHeap( GetProcessHeap(), 0, config_size )))
2694 goto error;
2696 if (!QueryServiceConfigW( *service, service_config, config_size, &config_size ))
2698 WARN( "failed to query service config\n" );
2699 goto error;
2702 if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER &&
2703 service_config->dwServiceType != SERVICE_FILE_SYSTEM_DRIVER)
2705 WARN( "service %s is not a kernel driver\n", debugstr_us(service_name) );
2706 goto error;
2709 TRACE( "opened service for driver %s\n", debugstr_us(service_name) );
2710 RtlFreeHeap( GetProcessHeap(), 0, service_config );
2711 return STATUS_SUCCESS;
2713 error:
2714 CloseServiceHandle( *service );
2715 RtlFreeHeap( GetProcessHeap(), 0, service_config );
2716 return STATUS_UNSUCCESSFUL;
2720 /***********************************************************************
2721 * ZwLoadDriver (NTOSKRNL.EXE.@)
2723 NTSTATUS WINAPI ZwLoadDriver( const UNICODE_STRING *service_name )
2725 SERVICE_STATUS_PROCESS service_status;
2726 SC_HANDLE service_handle;
2727 ULONGLONG start_time;
2728 NTSTATUS status;
2729 DWORD bytes;
2731 TRACE( "(%s)\n", debugstr_us(service_name) );
2733 if ((status = open_driver( service_name, &service_handle )) != STATUS_SUCCESS)
2734 return status;
2736 TRACE( "trying to start %s\n", debugstr_us(service_name) );
2738 start_time = GetTickCount64();
2739 for (;;)
2741 if (StartServiceW( service_handle, 0, NULL )) break;
2742 if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) break;
2743 if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED) goto error;
2744 if (GetTickCount64() - start_time > 30000) goto error;
2745 Sleep( 100 );
2748 start_time = GetTickCount64();
2749 for (;;)
2751 if (!QueryServiceStatusEx( service_handle, SC_STATUS_PROCESS_INFO,
2752 (BYTE *)&service_status, sizeof(service_status), &bytes )) goto error;
2753 if (service_status.dwCurrentState != SERVICE_START_PENDING) break;
2754 if (GetTickCount64() - start_time > 30000) goto error;
2755 Sleep( 100 );
2758 if (service_status.dwCurrentState == SERVICE_RUNNING)
2760 if (service_status.dwProcessId != GetCurrentProcessId())
2761 FIXME( "driver %s was loaded into a different process\n", debugstr_us(service_name) );
2763 status = STATUS_SUCCESS;
2764 goto done;
2767 error:
2768 WARN( "failed to start service %s\n", debugstr_us(service_name) );
2769 status = STATUS_UNSUCCESSFUL;
2771 done:
2772 TRACE( "returning status %08x\n", status );
2773 CloseServiceHandle( service_handle );
2774 return status;
2778 /***********************************************************************
2779 * ZwUnloadDriver (NTOSKRNL.EXE.@)
2781 NTSTATUS WINAPI ZwUnloadDriver( const UNICODE_STRING *service_name )
2783 SERVICE_STATUS service_status;
2784 SC_HANDLE service_handle;
2785 ULONGLONG start_time;
2786 NTSTATUS status;
2788 TRACE( "(%s)\n", debugstr_us(service_name) );
2790 if ((status = open_driver( service_name, &service_handle )) != STATUS_SUCCESS)
2791 return status;
2793 if (!ControlService( service_handle, SERVICE_CONTROL_STOP, &service_status ))
2794 goto error;
2796 start_time = GetTickCount64();
2797 for (;;)
2799 if (!QueryServiceStatus( service_handle, &service_status )) goto error;
2800 if (service_status.dwCurrentState != SERVICE_STOP_PENDING) break;
2801 if (GetTickCount64() - start_time > 30000) goto error;
2802 Sleep( 100 );
2805 if (service_status.dwCurrentState == SERVICE_STOPPED)
2807 status = STATUS_SUCCESS;
2808 goto done;
2811 error:
2812 WARN( "failed to stop service %s\n", debugstr_us(service_name) );
2813 status = STATUS_UNSUCCESSFUL;
2815 done:
2816 TRACE( "returning status %08x\n", status );
2817 CloseServiceHandle( service_handle );
2818 return status;
2822 /***********************************************************************
2823 * IoInvalidateDeviceRelations (NTOSKRNL.EXE.@)
2825 void WINAPI IoInvalidateDeviceRelations( DEVICE_OBJECT *device_object, DEVICE_RELATION_TYPE type )
2827 FIXME( "(%p, %i): stub\n", device_object, type );