ntoskrnl.exe: Implement ZwLoadDriver and ZwUnloadDriver based on services API.
[wine.git] / dlls / ntoskrnl.exe / ntoskrnl.c
blob7c35d14c7b0343e3511df50a44f1d689d8292a14
1 /*
2 * ntoskrnl.exe implementation
4 * Copyright (C) 2007 Alexandre Julliard
5 * Copyright (C) 2010 Damjan Jovanovic
6 * Copyright (C) 2016 Sebastian Lackner
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #include "windef.h"
34 #include "winsvc.h"
35 #include "winternl.h"
36 #include "excpt.h"
37 #include "winioctl.h"
38 #include "ddk/csq.h"
39 #include "ddk/ntddk.h"
40 #include "ddk/ntifs.h"
41 #include "ddk/wdm.h"
42 #include "wine/unicode.h"
43 #include "wine/server.h"
44 #include "wine/debug.h"
46 #include "wine/rbtree.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
49 WINE_DECLARE_DEBUG_CHANNEL(relay);
51 BOOLEAN KdDebuggerEnabled = FALSE;
52 ULONG InitSafeBootMode = 0;
54 extern LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs );
56 KSYSTEM_TIME KeTickCount = { 0, 0, 0 };
58 typedef struct _KSERVICE_TABLE_DESCRIPTOR
60 PULONG_PTR Base;
61 PULONG Count;
62 ULONG Limit;
63 PUCHAR Number;
64 } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
66 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[4] = { { 0 } };
68 typedef void (WINAPI *PCREATE_PROCESS_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
69 typedef void (WINAPI *PCREATE_THREAD_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
71 static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
72 '\\','M','a','c','h','i','n','e',
73 '\\','S','y','s','t','e','m',
74 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
75 '\\','S','e','r','v','i','c','e','s',
76 '\\',0};
78 /* tid of the thread running client request */
79 static DWORD request_thread;
81 /* pid/tid of the client thread */
82 static DWORD client_tid;
83 static DWORD client_pid;
85 struct wine_driver
87 struct wine_rb_entry entry;
89 DRIVER_OBJECT driver_obj;
90 DRIVER_EXTENSION driver_extension;
93 static struct wine_rb_tree wine_drivers;
95 static CRITICAL_SECTION drivers_cs;
96 static CRITICAL_SECTION_DEBUG critsect_debug =
98 0, 0, &drivers_cs,
99 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
100 0, 0, { (DWORD_PTR)(__FILE__ ": drivers_cs") }
102 static CRITICAL_SECTION drivers_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
104 static void *wine_drivers_rb_alloc( size_t size )
106 return HeapAlloc( GetProcessHeap(), 0, size );
109 static void *wine_drivers_rb_realloc( void *ptr, size_t size )
111 return HeapReAlloc( GetProcessHeap(), 0, ptr, size );
114 static void wine_drivers_rb_free( void *ptr )
116 HeapFree( GetProcessHeap(), 0, ptr );
119 static int wine_drivers_rb_compare( const void *key, const struct wine_rb_entry *entry )
121 const struct wine_driver *driver = WINE_RB_ENTRY_VALUE( entry, const struct wine_driver, entry );
122 const UNICODE_STRING *k = key;
124 return RtlCompareUnicodeString( k, &driver->driver_obj.DriverName, FALSE );
127 static const struct wine_rb_functions wine_drivers_rb_functions =
129 wine_drivers_rb_alloc,
130 wine_drivers_rb_realloc,
131 wine_drivers_rb_free,
132 wine_drivers_rb_compare,
135 #ifdef __i386__
136 #define DEFINE_FASTCALL1_ENTRYPOINT( name ) \
137 __ASM_STDCALL_FUNC( name, 4, \
138 "popl %eax\n\t" \
139 "pushl %ecx\n\t" \
140 "pushl %eax\n\t" \
141 "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(4))
142 #define DEFINE_FASTCALL2_ENTRYPOINT( name ) \
143 __ASM_STDCALL_FUNC( name, 8, \
144 "popl %eax\n\t" \
145 "pushl %edx\n\t" \
146 "pushl %ecx\n\t" \
147 "pushl %eax\n\t" \
148 "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(8))
149 #define DEFINE_FASTCALL3_ENTRYPOINT( name ) \
150 __ASM_STDCALL_FUNC( name, 12, \
151 "popl %eax\n\t" \
152 "pushl %edx\n\t" \
153 "pushl %ecx\n\t" \
154 "pushl %eax\n\t" \
155 "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(12))
156 #endif
158 static inline LPCSTR debugstr_us( const UNICODE_STRING *us )
160 if (!us) return "<null>";
161 return debugstr_wn( us->Buffer, us->Length / sizeof(WCHAR) );
164 static HANDLE get_device_manager(void)
166 static HANDLE device_manager;
167 HANDLE handle = 0, ret = device_manager;
169 if (!ret)
171 SERVER_START_REQ( create_device_manager )
173 req->access = SYNCHRONIZE;
174 req->attributes = 0;
175 if (!wine_server_call( req )) handle = wine_server_ptr_handle( reply->handle );
177 SERVER_END_REQ;
179 if (!handle)
181 ERR( "failed to create the device manager\n" );
182 return 0;
184 if (!(ret = InterlockedCompareExchangePointer( &device_manager, handle, 0 )))
185 ret = handle;
186 else
187 NtClose( handle ); /* somebody beat us to it */
189 return ret;
192 static NTSTATUS dispatch_irp( DEVICE_OBJECT *device, IRP *irp )
194 LARGE_INTEGER count;
196 KeQueryTickCount( &count ); /* update the global KeTickCount */
198 device->CurrentIrp = irp;
200 IoCallDriver( device, irp );
202 device->CurrentIrp = NULL;
204 return STATUS_SUCCESS;
207 /* process a create request for a given file */
208 static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULONG in_size,
209 ULONG out_size, HANDLE irp_handle )
211 IRP *irp;
212 IO_STACK_LOCATION *irpsp;
213 FILE_OBJECT *file;
214 DEVICE_OBJECT *device = wine_server_get_ptr( params->create.device );
216 if (!(file = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*file) ))) return STATUS_NO_MEMORY;
218 TRACE( "device %p -> file %p\n", device, file );
220 file->Type = 5; /* MSDN */
221 file->Size = sizeof(*file);
222 file->DeviceObject = device;
224 if (!(irp = IoAllocateIrp( device->StackSize, FALSE )))
226 HeapFree( GetProcessHeap(), 0, file );
227 return STATUS_NO_MEMORY;
230 irpsp = IoGetNextIrpStackLocation( irp );
231 irpsp->MajorFunction = IRP_MJ_CREATE;
232 irpsp->DeviceObject = device;
233 irpsp->CompletionRoutine = NULL;
234 irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
235 irpsp->Parameters.Create.Options = params->create.options;
236 irpsp->Parameters.Create.ShareAccess = params->create.sharing;
237 irpsp->Parameters.Create.FileAttributes = 0;
238 irpsp->Parameters.Create.EaLength = 0;
240 irp->Tail.Overlay.OriginalFileObject = file;
241 irp->RequestorMode = UserMode;
242 irp->AssociatedIrp.SystemBuffer = NULL;
243 irp->UserBuffer = NULL;
244 irp->UserIosb = irp_handle; /* note: we abuse UserIosb to store the server irp handle */
245 irp->UserEvent = NULL;
247 if (device->DriverObject->MajorFunction[IRP_MJ_CREATE]) return dispatch_irp( device, irp );
249 irp->IoStatus.u.Status = STATUS_SUCCESS;
250 IoCompleteRequest( irp, IO_NO_INCREMENT );
251 return STATUS_SUCCESS;
254 /* process a close request for a given file */
255 static NTSTATUS dispatch_close( const irp_params_t *params, void *in_buff, ULONG in_size,
256 ULONG out_size, HANDLE irp_handle )
258 IRP *irp;
259 IO_STACK_LOCATION *irpsp;
260 DEVICE_OBJECT *device;
261 FILE_OBJECT *file = wine_server_get_ptr( params->close.file );
263 if (!file) return STATUS_INVALID_HANDLE;
265 device = file->DeviceObject;
267 TRACE( "device %p file %p\n", device, file );
269 if (!(irp = IoAllocateIrp( device->StackSize, FALSE )))
271 HeapFree( GetProcessHeap(), 0, file );
272 return STATUS_NO_MEMORY;
275 irpsp = IoGetNextIrpStackLocation( irp );
276 irpsp->MajorFunction = IRP_MJ_CLOSE;
277 irpsp->DeviceObject = device;
278 irpsp->CompletionRoutine = NULL;
279 irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
280 irpsp->Parameters.Create.Options = params->create.options;
281 irpsp->Parameters.Create.ShareAccess = params->create.sharing;
282 irpsp->Parameters.Create.FileAttributes = 0;
283 irpsp->Parameters.Create.EaLength = 0;
285 irp->Tail.Overlay.OriginalFileObject = file;
286 irp->RequestorMode = UserMode;
287 irp->AssociatedIrp.SystemBuffer = NULL;
288 irp->UserBuffer = NULL;
289 irp->UserIosb = irp_handle; /* note: we abuse UserIosb to store the server irp handle */
290 irp->UserEvent = NULL;
292 if (!device->DriverObject->MajorFunction[IRP_MJ_CLOSE])
294 irp->IoStatus.u.Status = STATUS_SUCCESS;
295 IoCompleteRequest( irp, IO_NO_INCREMENT );
297 else dispatch_irp( device, irp );
299 HeapFree( GetProcessHeap(), 0, file ); /* FIXME: async close processing not supported */
300 return STATUS_SUCCESS;
303 /* process a read request for a given device */
304 static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG in_size,
305 ULONG out_size, HANDLE irp_handle )
307 IRP *irp;
308 void *out_buff;
309 LARGE_INTEGER offset;
310 IO_STACK_LOCATION *irpsp;
311 DEVICE_OBJECT *device;
312 FILE_OBJECT *file = wine_server_get_ptr( params->read.file );
314 if (!file) return STATUS_INVALID_HANDLE;
316 device = file->DeviceObject;
317 if (!device->DriverObject->MajorFunction[IRP_MJ_READ]) return STATUS_NOT_SUPPORTED;
319 TRACE( "device %p file %p size %u\n", device, file, out_size );
321 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
323 offset.QuadPart = params->read.pos;
325 /* note: we abuse UserIosb to store the server irp handle */
326 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, device, out_buff, out_size,
327 &offset, NULL, irp_handle )))
329 HeapFree( GetProcessHeap(), 0, out_buff );
330 return STATUS_NO_MEMORY;
333 irp->Tail.Overlay.OriginalFileObject = file;
334 irp->RequestorMode = UserMode;
336 irpsp = IoGetNextIrpStackLocation( irp );
337 irpsp->Parameters.Read.Key = params->read.key;
339 return dispatch_irp( device, irp );
342 /* process a write request for a given device */
343 static NTSTATUS dispatch_write( const irp_params_t *params, void *in_buff, ULONG in_size,
344 ULONG out_size, HANDLE irp_handle )
346 IRP *irp;
347 LARGE_INTEGER offset;
348 IO_STACK_LOCATION *irpsp;
349 DEVICE_OBJECT *device;
350 FILE_OBJECT *file = wine_server_get_ptr( params->write.file );
352 if (!file) return STATUS_INVALID_HANDLE;
354 device = file->DeviceObject;
355 if (!device->DriverObject->MajorFunction[IRP_MJ_WRITE]) return STATUS_NOT_SUPPORTED;
357 TRACE( "device %p file %p size %u\n", device, file, in_size );
359 offset.QuadPart = params->write.pos;
361 /* note: we abuse UserIosb to store the server irp handle */
362 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, device, in_buff, in_size,
363 &offset, NULL, irp_handle )))
364 return STATUS_NO_MEMORY;
366 irp->Tail.Overlay.OriginalFileObject = file;
367 irp->RequestorMode = UserMode;
369 irpsp = IoGetNextIrpStackLocation( irp );
370 irpsp->Parameters.Write.Key = params->write.key;
372 return dispatch_irp( device, irp );
375 /* process a flush request for a given device */
376 static NTSTATUS dispatch_flush( const irp_params_t *params, void *in_buff, ULONG in_size,
377 ULONG out_size, HANDLE irp_handle )
379 IRP *irp;
380 DEVICE_OBJECT *device;
381 FILE_OBJECT *file = wine_server_get_ptr( params->flush.file );
383 if (!file) return STATUS_INVALID_HANDLE;
385 device = file->DeviceObject;
386 if (!device->DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS]) return STATUS_NOT_SUPPORTED;
388 TRACE( "device %p file %p\n", device, file );
390 /* note: we abuse UserIosb to store the server irp handle */
391 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_FLUSH_BUFFERS, device, in_buff, in_size,
392 NULL, NULL, irp_handle )))
393 return STATUS_NO_MEMORY;
395 irp->Tail.Overlay.OriginalFileObject = file;
396 irp->RequestorMode = UserMode;
398 return dispatch_irp( device, irp );
401 /* process an ioctl request for a given device */
402 static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG in_size,
403 ULONG out_size, HANDLE irp_handle )
405 IRP *irp;
406 void *out_buff = NULL;
407 DEVICE_OBJECT *device;
408 FILE_OBJECT *file = wine_server_get_ptr( params->ioctl.file );
410 if (!file) return STATUS_INVALID_HANDLE;
412 device = file->DeviceObject;
413 if (!device->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]) return STATUS_NOT_SUPPORTED;
415 TRACE( "ioctl %x device %p file %p in_size %u out_size %u\n",
416 params->ioctl.code, device, file, in_size, out_size );
418 if ((params->ioctl.code & 3) == METHOD_BUFFERED) out_size = max( in_size, out_size );
420 if (out_size)
422 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
423 if ((params->ioctl.code & 3) == METHOD_BUFFERED)
425 memcpy( out_buff, in_buff, in_size );
426 in_buff = out_buff;
430 /* note: we abuse UserIosb to store the server handle to the ioctl */
431 irp = IoBuildDeviceIoControlRequest( params->ioctl.code, device, in_buff, in_size, out_buff, out_size,
432 FALSE, NULL, irp_handle );
433 if (!irp)
435 HeapFree( GetProcessHeap(), 0, out_buff );
436 return STATUS_NO_MEMORY;
439 irp->Tail.Overlay.OriginalFileObject = file;
440 irp->RequestorMode = UserMode;
442 return dispatch_irp( device, irp );
445 typedef NTSTATUS (*dispatch_func)( const irp_params_t *params, void *in_buff, ULONG in_size,
446 ULONG out_size, HANDLE irp_handle );
448 static const dispatch_func dispatch_funcs[IRP_MJ_MAXIMUM_FUNCTION + 1] =
450 dispatch_create, /* IRP_MJ_CREATE */
451 NULL, /* IRP_MJ_CREATE_NAMED_PIPE */
452 dispatch_close, /* IRP_MJ_CLOSE */
453 dispatch_read, /* IRP_MJ_READ */
454 dispatch_write, /* IRP_MJ_WRITE */
455 NULL, /* IRP_MJ_QUERY_INFORMATION */
456 NULL, /* IRP_MJ_SET_INFORMATION */
457 NULL, /* IRP_MJ_QUERY_EA */
458 NULL, /* IRP_MJ_SET_EA */
459 dispatch_flush, /* IRP_MJ_FLUSH_BUFFERS */
460 NULL, /* IRP_MJ_QUERY_VOLUME_INFORMATION */
461 NULL, /* IRP_MJ_SET_VOLUME_INFORMATION */
462 NULL, /* IRP_MJ_DIRECTORY_CONTROL */
463 NULL, /* IRP_MJ_FILE_SYSTEM_CONTROL */
464 dispatch_ioctl, /* IRP_MJ_DEVICE_CONTROL */
465 NULL, /* IRP_MJ_INTERNAL_DEVICE_CONTROL */
466 NULL, /* IRP_MJ_SHUTDOWN */
467 NULL, /* IRP_MJ_LOCK_CONTROL */
468 NULL, /* IRP_MJ_CLEANUP */
469 NULL, /* IRP_MJ_CREATE_MAILSLOT */
470 NULL, /* IRP_MJ_QUERY_SECURITY */
471 NULL, /* IRP_MJ_SET_SECURITY */
472 NULL, /* IRP_MJ_POWER */
473 NULL, /* IRP_MJ_SYSTEM_CONTROL */
474 NULL, /* IRP_MJ_DEVICE_CHANGE */
475 NULL, /* IRP_MJ_QUERY_QUOTA */
476 NULL, /* IRP_MJ_SET_QUOTA */
477 NULL, /* IRP_MJ_PNP */
481 /***********************************************************************
482 * wine_ntoskrnl_main_loop (Not a Windows API)
484 NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
486 HANDLE manager = get_device_manager();
487 HANDLE irp = 0;
488 NTSTATUS status = STATUS_SUCCESS;
489 irp_params_t irp_params;
490 void *in_buff;
491 ULONG in_size = 4096, out_size = 0;
492 HANDLE handles[2];
494 request_thread = GetCurrentThreadId();
496 if (!(in_buff = HeapAlloc( GetProcessHeap(), 0, in_size )))
498 ERR( "failed to allocate buffer\n" );
499 return STATUS_NO_MEMORY;
502 handles[0] = stop_event;
503 handles[1] = manager;
505 for (;;)
507 SERVER_START_REQ( get_next_device_request )
509 req->manager = wine_server_obj_handle( manager );
510 req->prev = wine_server_obj_handle( irp );
511 req->status = status;
512 wine_server_set_reply( req, in_buff, in_size );
513 if (!(status = wine_server_call( req )))
515 irp = wine_server_ptr_handle( reply->next );
516 irp_params = reply->params;
517 client_tid = reply->client_tid;
518 client_pid = reply->client_pid;
519 in_size = reply->in_size;
520 out_size = reply->out_size;
522 else
524 irp = 0; /* no previous irp */
525 out_size = 0;
526 in_size = reply->in_size;
529 SERVER_END_REQ;
531 switch(status)
533 case STATUS_SUCCESS:
534 if (irp_params.major > IRP_MJ_MAXIMUM_FUNCTION || !dispatch_funcs[irp_params.major])
536 WARN( "unsupported request %u\n", irp_params.major );
537 status = STATUS_NOT_SUPPORTED;
538 break;
540 status = dispatch_funcs[irp_params.major]( &irp_params, in_buff, in_size, out_size, irp );
541 if (status == STATUS_SUCCESS) irp = 0; /* status reported by IoCompleteRequest */
542 break;
543 case STATUS_BUFFER_OVERFLOW:
544 HeapFree( GetProcessHeap(), 0, in_buff );
545 in_buff = HeapAlloc( GetProcessHeap(), 0, in_size );
546 /* restart with larger buffer */
547 break;
548 case STATUS_PENDING:
549 for (;;)
551 DWORD ret = WaitForMultipleObjectsEx( 2, handles, FALSE, INFINITE, TRUE );
552 if (ret == WAIT_OBJECT_0)
554 HeapFree( GetProcessHeap(), 0, in_buff );
555 return STATUS_SUCCESS;
557 if (ret != WAIT_IO_COMPLETION) break;
559 break;
565 /***********************************************************************
566 * IoAcquireCancelSpinLock (NTOSKRNL.EXE.@)
568 void WINAPI IoAcquireCancelSpinLock(PKIRQL irql)
570 FIXME("(%p): stub\n", irql);
574 /***********************************************************************
575 * IoReleaseCancelSpinLock (NTOSKRNL.EXE.@)
577 void WINAPI IoReleaseCancelSpinLock(PKIRQL irql)
579 FIXME("(%p): stub\n", irql);
583 /***********************************************************************
584 * IoAllocateDriverObjectExtension (NTOSKRNL.EXE.@)
586 NTSTATUS WINAPI IoAllocateDriverObjectExtension( PDRIVER_OBJECT DriverObject,
587 PVOID ClientIdentificationAddress,
588 ULONG DriverObjectExtensionSize,
589 PVOID *DriverObjectExtension )
591 FIXME( "stub: %p, %p, %u, %p\n", DriverObject, ClientIdentificationAddress,
592 DriverObjectExtensionSize, DriverObjectExtension );
593 return STATUS_NOT_IMPLEMENTED;
597 /***********************************************************************
598 * IoGetDriverObjectExtension (NTOSKRNL.EXE.@)
600 PVOID WINAPI IoGetDriverObjectExtension( PDRIVER_OBJECT DriverObject,
601 PVOID ClientIdentificationAddress )
603 FIXME( "stub: %p, %p\n", DriverObject, ClientIdentificationAddress );
604 return NULL;
608 /***********************************************************************
609 * IoInitializeIrp (NTOSKRNL.EXE.@)
611 void WINAPI IoInitializeIrp( IRP *irp, USHORT size, CCHAR stack_size )
613 TRACE( "%p, %u, %d\n", irp, size, stack_size );
615 RtlZeroMemory( irp, size );
617 irp->Type = IO_TYPE_IRP;
618 irp->Size = size;
619 InitializeListHead( &irp->ThreadListEntry );
620 irp->StackCount = stack_size;
621 irp->CurrentLocation = stack_size + 1;
622 irp->Tail.Overlay.s.u2.CurrentStackLocation =
623 (PIO_STACK_LOCATION)(irp + 1) + stack_size;
627 /***********************************************************************
628 * IoInitializeTimer (NTOSKRNL.EXE.@)
630 NTSTATUS WINAPI IoInitializeTimer(PDEVICE_OBJECT DeviceObject,
631 PIO_TIMER_ROUTINE TimerRoutine,
632 PVOID Context)
634 FIXME( "stub: %p, %p, %p\n", DeviceObject, TimerRoutine, Context );
635 return STATUS_NOT_IMPLEMENTED;
639 /***********************************************************************
640 * IoStartTimer (NTOSKRNL.EXE.@)
642 void WINAPI IoStartTimer(PDEVICE_OBJECT DeviceObject)
644 FIXME( "stub: %p\n", DeviceObject );
648 /***********************************************************************
649 * IoAllocateIrp (NTOSKRNL.EXE.@)
651 PIRP WINAPI IoAllocateIrp( CCHAR stack_size, BOOLEAN charge_quota )
653 SIZE_T size;
654 PIRP irp;
655 CCHAR loc_count = stack_size;
657 TRACE( "%d, %d\n", stack_size, charge_quota );
659 if (loc_count < 8 && loc_count != 1)
660 loc_count = 8;
662 size = sizeof(IRP) + loc_count * sizeof(IO_STACK_LOCATION);
663 irp = ExAllocatePool( NonPagedPool, size );
664 if (irp == NULL)
665 return NULL;
666 IoInitializeIrp( irp, size, stack_size );
667 if (stack_size >= 1 && stack_size <= 8)
668 irp->AllocationFlags = IRP_ALLOCATED_FIXED_SIZE;
669 if (charge_quota)
670 irp->AllocationFlags |= IRP_LOOKASIDE_ALLOCATION;
671 return irp;
675 /***********************************************************************
676 * IoFreeIrp (NTOSKRNL.EXE.@)
678 void WINAPI IoFreeIrp( IRP *irp )
680 MDL *mdl;
682 TRACE( "%p\n", irp );
684 mdl = irp->MdlAddress;
685 while (mdl)
687 MDL *next = mdl->Next;
688 IoFreeMdl( mdl );
689 mdl = next;
692 ExFreePool( irp );
696 /***********************************************************************
697 * IoAllocateErrorLogEntry (NTOSKRNL.EXE.@)
699 PVOID WINAPI IoAllocateErrorLogEntry( PVOID IoObject, UCHAR EntrySize )
701 FIXME( "stub: %p, %u\n", IoObject, EntrySize );
702 return NULL;
706 /***********************************************************************
707 * IoAllocateMdl (NTOSKRNL.EXE.@)
709 PMDL WINAPI IoAllocateMdl( PVOID va, ULONG length, BOOLEAN secondary, BOOLEAN charge_quota, IRP *irp )
711 PMDL mdl;
712 ULONG_PTR address = (ULONG_PTR)va;
713 ULONG_PTR page_address;
714 SIZE_T nb_pages, mdl_size;
716 TRACE("(%p, %u, %i, %i, %p)\n", va, length, secondary, charge_quota, irp);
718 if (charge_quota)
719 FIXME("Charge quota is not yet supported\n");
721 /* FIXME: We suppose that page size is 4096 */
722 page_address = address & ~(4096 - 1);
723 nb_pages = (((address + length - 1) & ~(4096 - 1)) - page_address) / 4096 + 1;
725 mdl_size = sizeof(MDL) + nb_pages * sizeof(PVOID);
727 mdl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mdl_size);
728 if (!mdl)
729 return NULL;
731 mdl->Size = mdl_size;
732 mdl->Process = NULL; /* FIXME: IoGetCurrentProcess */
733 mdl->StartVa = (PVOID)page_address;
734 mdl->ByteCount = length;
735 mdl->ByteOffset = address - page_address;
737 if (!irp) return mdl;
739 if (secondary) /* add it at the end */
741 MDL **pmdl = &irp->MdlAddress;
742 while (*pmdl) pmdl = &(*pmdl)->Next;
743 *pmdl = mdl;
745 else
747 mdl->Next = irp->MdlAddress;
748 irp->MdlAddress = mdl;
750 return mdl;
754 /***********************************************************************
755 * IoFreeMdl (NTOSKRNL.EXE.@)
757 void WINAPI IoFreeMdl(PMDL mdl)
759 TRACE("%p\n", mdl);
760 HeapFree(GetProcessHeap(), 0, mdl);
764 /***********************************************************************
765 * IoAllocateWorkItem (NTOSKRNL.EXE.@)
767 PIO_WORKITEM WINAPI IoAllocateWorkItem( PDEVICE_OBJECT DeviceObject )
769 FIXME( "stub: %p\n", DeviceObject );
770 return NULL;
774 /***********************************************************************
775 * IoAttachDeviceToDeviceStack (NTOSKRNL.EXE.@)
777 PDEVICE_OBJECT WINAPI IoAttachDeviceToDeviceStack( DEVICE_OBJECT *source,
778 DEVICE_OBJECT *target )
780 TRACE( "%p, %p\n", source, target );
781 target->AttachedDevice = source;
782 source->StackSize = target->StackSize + 1;
783 return target;
787 /***********************************************************************
788 * IoBuildDeviceIoControlRequest (NTOSKRNL.EXE.@)
790 PIRP WINAPI IoBuildDeviceIoControlRequest( ULONG code, PDEVICE_OBJECT device,
791 PVOID in_buff, ULONG in_len,
792 PVOID out_buff, ULONG out_len,
793 BOOLEAN internal, PKEVENT event,
794 PIO_STATUS_BLOCK iosb )
796 PIRP irp;
797 PIO_STACK_LOCATION irpsp;
799 TRACE( "%x, %p, %p, %u, %p, %u, %u, %p, %p\n",
800 code, device, in_buff, in_len, out_buff, out_len, internal, event, iosb );
802 if (device == NULL)
803 return NULL;
805 irp = IoAllocateIrp( device->StackSize, FALSE );
806 if (irp == NULL)
807 return NULL;
809 irpsp = IoGetNextIrpStackLocation( irp );
810 irpsp->MajorFunction = internal ? IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
811 irpsp->Parameters.DeviceIoControl.IoControlCode = code;
812 irpsp->Parameters.DeviceIoControl.InputBufferLength = in_len;
813 irpsp->Parameters.DeviceIoControl.OutputBufferLength = out_len;
814 irpsp->DeviceObject = device;
815 irpsp->CompletionRoutine = NULL;
817 switch (code & 3)
819 case METHOD_BUFFERED:
820 irp->AssociatedIrp.SystemBuffer = in_buff;
821 break;
822 case METHOD_IN_DIRECT:
823 case METHOD_OUT_DIRECT:
824 irp->AssociatedIrp.SystemBuffer = in_buff;
825 IoAllocateMdl( out_buff, out_len, FALSE, FALSE, irp );
826 break;
827 case METHOD_NEITHER:
828 irpsp->Parameters.DeviceIoControl.Type3InputBuffer = in_buff;
829 break;
832 irp->RequestorMode = KernelMode;
833 irp->UserBuffer = out_buff;
834 irp->UserIosb = iosb;
835 irp->UserEvent = event;
836 return irp;
840 /**********************************************************
841 * IoBuildSynchronousFsdRequest (NTOSKRNL.EXE.@)
843 PIRP WINAPI IoBuildSynchronousFsdRequest(ULONG majorfunc, PDEVICE_OBJECT device,
844 PVOID buffer, ULONG length, PLARGE_INTEGER startoffset,
845 PKEVENT event, PIO_STATUS_BLOCK iosb)
847 PIRP irp;
848 PIO_STACK_LOCATION irpsp;
850 TRACE("(%d %p %p %d %p %p %p)\n", majorfunc, device, buffer, length, startoffset, event, iosb);
852 if (!(irp = IoAllocateIrp( device->StackSize, FALSE ))) return NULL;
854 irpsp = IoGetNextIrpStackLocation( irp );
855 irpsp->MajorFunction = majorfunc;
856 irpsp->DeviceObject = device;
857 irpsp->CompletionRoutine = NULL;
859 irp->AssociatedIrp.SystemBuffer = buffer;
860 if (device->Flags & DO_DIRECT_IO) IoAllocateMdl( buffer, length, FALSE, FALSE, irp );
862 switch (majorfunc)
864 case IRP_MJ_READ:
865 irpsp->Parameters.Read.Length = length;
866 irpsp->Parameters.Read.ByteOffset = *startoffset;
867 break;
868 case IRP_MJ_WRITE:
869 irpsp->Parameters.Write.Length = length;
870 irpsp->Parameters.Write.ByteOffset = *startoffset;
871 break;
873 irp->RequestorMode = KernelMode;
874 irp->UserIosb = iosb;
875 irp->UserEvent = event;
876 irp->UserBuffer = buffer;
877 return irp;
880 static void build_driver_keypath( const WCHAR *name, UNICODE_STRING *keypath )
882 static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0};
883 WCHAR *str;
885 /* Check what prefix is present */
886 if (strncmpW( name, servicesW, strlenW(servicesW) ) == 0)
888 FIXME( "Driver name %s is malformed as the keypath\n", debugstr_w(name) );
889 RtlCreateUnicodeString( keypath, name );
890 return;
892 if (strncmpW( name, driverW, strlenW(driverW) ) == 0)
893 name += strlenW(driverW);
894 else
895 FIXME( "Driver name %s does not properly begin with \\Driver\\\n", debugstr_w(name) );
897 str = HeapAlloc( GetProcessHeap(), 0, sizeof(servicesW) + strlenW(name)*sizeof(WCHAR));
898 lstrcpyW( str, servicesW );
899 lstrcatW( str, name );
900 RtlInitUnicodeString( keypath, str );
904 /***********************************************************************
905 * IoCreateDriver (NTOSKRNL.EXE.@)
907 NTSTATUS WINAPI IoCreateDriver( UNICODE_STRING *name, PDRIVER_INITIALIZE init )
909 struct wine_driver *driver;
910 NTSTATUS status;
912 TRACE("(%s, %p)\n", debugstr_us(name), init);
914 if (!(driver = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
915 sizeof(*driver) )))
916 return STATUS_NO_MEMORY;
918 if ((status = RtlDuplicateUnicodeString( 1, name, &driver->driver_obj.DriverName )))
920 RtlFreeHeap( GetProcessHeap(), 0, driver );
921 return status;
924 driver->driver_obj.Size = sizeof(driver->driver_obj);
925 driver->driver_obj.DriverInit = init;
926 driver->driver_obj.DriverExtension = &driver->driver_extension;
927 driver->driver_extension.DriverObject = &driver->driver_obj;
928 build_driver_keypath( driver->driver_obj.DriverName.Buffer, &driver->driver_extension.ServiceKeyName );
930 status = driver->driver_obj.DriverInit( &driver->driver_obj, &driver->driver_extension.ServiceKeyName );
932 if (status)
934 RtlFreeUnicodeString( &driver->driver_obj.DriverName );
935 RtlFreeUnicodeString( &driver->driver_extension.ServiceKeyName );
936 RtlFreeHeap( GetProcessHeap(), 0, driver );
938 else
940 EnterCriticalSection( &drivers_cs );
941 if (wine_rb_put( &wine_drivers, &driver->driver_obj.DriverName, &driver->entry ))
942 ERR( "failed to insert driver %s in tree\n", debugstr_us(name) );
943 LeaveCriticalSection( &drivers_cs );
946 return status;
950 /***********************************************************************
951 * IoDeleteDriver (NTOSKRNL.EXE.@)
953 void WINAPI IoDeleteDriver( DRIVER_OBJECT *driver_object )
955 TRACE( "(%p)\n", driver_object );
957 EnterCriticalSection( &drivers_cs );
958 wine_rb_remove( &wine_drivers, &driver_object->DriverName );
959 LeaveCriticalSection( &drivers_cs );
961 RtlFreeUnicodeString( &driver_object->DriverName );
962 RtlFreeUnicodeString( &driver_object->DriverExtension->ServiceKeyName );
963 RtlFreeHeap( GetProcessHeap(), 0, CONTAINING_RECORD( driver_object, struct wine_driver, driver_obj ) );
967 /***********************************************************************
968 * IoCreateDevice (NTOSKRNL.EXE.@)
970 NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size,
971 UNICODE_STRING *name, DEVICE_TYPE type,
972 ULONG characteristics, BOOLEAN exclusive,
973 DEVICE_OBJECT **ret_device )
975 NTSTATUS status;
976 DEVICE_OBJECT *device;
977 HANDLE handle = 0;
978 HANDLE manager = get_device_manager();
980 TRACE( "(%p, %u, %s, %u, %x, %u, %p)\n",
981 driver, ext_size, debugstr_us(name), type, characteristics, exclusive, ret_device );
983 if (!(device = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*device) + ext_size )))
984 return STATUS_NO_MEMORY;
986 SERVER_START_REQ( create_device )
988 req->access = 0;
989 req->attributes = 0;
990 req->rootdir = 0;
991 req->manager = wine_server_obj_handle( manager );
992 req->user_ptr = wine_server_client_ptr( device );
993 if (name) wine_server_add_data( req, name->Buffer, name->Length );
994 if (!(status = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle );
996 SERVER_END_REQ;
998 if (status == STATUS_SUCCESS)
1000 device->DriverObject = driver;
1001 device->DeviceExtension = device + 1;
1002 device->DeviceType = type;
1003 device->StackSize = 1;
1004 device->Reserved = handle;
1006 device->NextDevice = driver->DeviceObject;
1007 driver->DeviceObject = device;
1009 *ret_device = device;
1011 else HeapFree( GetProcessHeap(), 0, device );
1013 return status;
1017 /***********************************************************************
1018 * IoDeleteDevice (NTOSKRNL.EXE.@)
1020 void WINAPI IoDeleteDevice( DEVICE_OBJECT *device )
1022 NTSTATUS status;
1024 TRACE( "%p\n", device );
1026 SERVER_START_REQ( delete_device )
1028 req->handle = wine_server_obj_handle( device->Reserved );
1029 status = wine_server_call( req );
1031 SERVER_END_REQ;
1033 if (status == STATUS_SUCCESS)
1035 DEVICE_OBJECT **prev = &device->DriverObject->DeviceObject;
1036 while (*prev && *prev != device) prev = &(*prev)->NextDevice;
1037 if (*prev) *prev = (*prev)->NextDevice;
1038 NtClose( device->Reserved );
1039 HeapFree( GetProcessHeap(), 0, device );
1044 /***********************************************************************
1045 * IoCreateSymbolicLink (NTOSKRNL.EXE.@)
1047 NTSTATUS WINAPI IoCreateSymbolicLink( UNICODE_STRING *name, UNICODE_STRING *target )
1049 HANDLE handle;
1050 OBJECT_ATTRIBUTES attr;
1052 attr.Length = sizeof(attr);
1053 attr.RootDirectory = 0;
1054 attr.ObjectName = name;
1055 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1056 attr.SecurityDescriptor = NULL;
1057 attr.SecurityQualityOfService = NULL;
1059 TRACE( "%s -> %s\n", debugstr_us(name), debugstr_us(target) );
1060 /* FIXME: store handle somewhere */
1061 return NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, target );
1065 /***********************************************************************
1066 * IoDeleteSymbolicLink (NTOSKRNL.EXE.@)
1068 NTSTATUS WINAPI IoDeleteSymbolicLink( UNICODE_STRING *name )
1070 HANDLE handle;
1071 OBJECT_ATTRIBUTES attr;
1072 NTSTATUS status;
1074 attr.Length = sizeof(attr);
1075 attr.RootDirectory = 0;
1076 attr.ObjectName = name;
1077 attr.Attributes = OBJ_CASE_INSENSITIVE;
1078 attr.SecurityDescriptor = NULL;
1079 attr.SecurityQualityOfService = NULL;
1081 if (!(status = NtOpenSymbolicLinkObject( &handle, 0, &attr )))
1083 SERVER_START_REQ( unlink_object )
1085 req->handle = wine_server_obj_handle( handle );
1086 status = wine_server_call( req );
1088 SERVER_END_REQ;
1089 NtClose( handle );
1091 return status;
1095 /***********************************************************************
1096 * IoGetDeviceInterfaces (NTOSKRNL.EXE.@)
1098 NTSTATUS WINAPI IoGetDeviceInterfaces( const GUID *InterfaceClassGuid,
1099 PDEVICE_OBJECT PhysicalDeviceObject,
1100 ULONG Flags, PWSTR *SymbolicLinkList )
1102 FIXME( "stub: %s %p %x %p\n", debugstr_guid(InterfaceClassGuid),
1103 PhysicalDeviceObject, Flags, SymbolicLinkList );
1104 return STATUS_NOT_IMPLEMENTED;
1108 /***********************************************************************
1109 * IoGetDeviceObjectPointer (NTOSKRNL.EXE.@)
1111 NTSTATUS WINAPI IoGetDeviceObjectPointer( UNICODE_STRING *name, ACCESS_MASK access, PFILE_OBJECT *file, PDEVICE_OBJECT *device )
1113 static DEVICE_OBJECT stub_device;
1114 static DRIVER_OBJECT stub_driver;
1116 FIXME( "stub: %s %x %p %p\n", debugstr_us(name), access, file, device );
1118 stub_device.StackSize = 0x80; /* minimum value to appease SecuROM 5.x */
1119 stub_device.DriverObject = &stub_driver;
1121 *file = NULL;
1122 *device = &stub_device;
1124 return STATUS_SUCCESS;
1127 /***********************************************************************
1128 * IoGetAttachedDevice (NTOSKRNL.EXE.@)
1130 PDEVICE_OBJECT WINAPI IoGetAttachedDevice( PDEVICE_OBJECT device )
1132 FIXME( "stub: %p\n", device );
1134 return device;
1137 /***********************************************************************
1138 * IoGetDeviceProperty (NTOSKRNL.EXE.@)
1140 NTSTATUS WINAPI IoGetDeviceProperty( DEVICE_OBJECT *device, DEVICE_REGISTRY_PROPERTY device_property,
1141 ULONG buffer_length, PVOID property_buffer, PULONG result_length )
1143 NTSTATUS status = STATUS_NOT_IMPLEMENTED;
1144 TRACE( "%p %d %u %p %p\n", device, device_property, buffer_length,
1145 property_buffer, result_length );
1146 switch (device_property)
1148 case DevicePropertyPhysicalDeviceObjectName:
1150 ULONG used_len, len = buffer_length + sizeof(OBJECT_NAME_INFORMATION);
1151 OBJECT_NAME_INFORMATION *name = HeapAlloc(GetProcessHeap(), 0, len);
1153 status = NtQueryObject(device->Reserved, ObjectNameInformation, name, len, &used_len);
1154 if (status == STATUS_SUCCESS)
1156 /* Ensure room for NULL termination */
1157 if (buffer_length >= name->Name.MaximumLength)
1158 memcpy(property_buffer, name->Name.Buffer, name->Name.MaximumLength);
1159 else
1160 status = STATUS_BUFFER_TOO_SMALL;
1161 *result_length = name->Name.MaximumLength;
1163 else
1165 if (status == STATUS_INFO_LENGTH_MISMATCH ||
1166 status == STATUS_BUFFER_OVERFLOW)
1168 status = STATUS_BUFFER_TOO_SMALL;
1169 *result_length = used_len - sizeof(OBJECT_NAME_INFORMATION);
1171 else
1172 *result_length = 0;
1174 HeapFree(GetProcessHeap(), 0, name);
1175 break;
1177 default:
1178 FIXME("unhandled property %d\n", device_property);
1180 return status;
1184 /***********************************************************************
1185 * IoCallDriver (NTOSKRNL.EXE.@)
1187 NTSTATUS WINAPI IoCallDriver( DEVICE_OBJECT *device, IRP *irp )
1189 PDRIVER_DISPATCH dispatch;
1190 IO_STACK_LOCATION *irpsp;
1191 NTSTATUS status;
1193 --irp->CurrentLocation;
1194 irpsp = --irp->Tail.Overlay.s.u2.CurrentStackLocation;
1195 dispatch = device->DriverObject->MajorFunction[irpsp->MajorFunction];
1197 if (TRACE_ON(relay))
1198 DPRINTF( "%04x:Call driver dispatch %p (device=%p,irp=%p)\n",
1199 GetCurrentThreadId(), dispatch, device, irp );
1201 status = dispatch( device, irp );
1203 if (TRACE_ON(relay))
1204 DPRINTF( "%04x:Ret driver dispatch %p (device=%p,irp=%p) retval=%08x\n",
1205 GetCurrentThreadId(), dispatch, device, irp, status );
1207 return status;
1211 /***********************************************************************
1212 * IofCallDriver (NTOSKRNL.EXE.@)
1214 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1215 DEFINE_FASTCALL2_ENTRYPOINT( IofCallDriver )
1216 NTSTATUS WINAPI __regs_IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
1217 #else
1218 NTSTATUS WINAPI IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
1219 #endif
1221 TRACE( "%p %p\n", device, irp );
1222 return IoCallDriver( device, irp );
1226 /***********************************************************************
1227 * IoGetRelatedDeviceObject (NTOSKRNL.EXE.@)
1229 PDEVICE_OBJECT WINAPI IoGetRelatedDeviceObject( PFILE_OBJECT obj )
1231 FIXME( "stub: %p\n", obj );
1232 return NULL;
1235 static CONFIGURATION_INFORMATION configuration_information;
1237 /***********************************************************************
1238 * IoGetConfigurationInformation (NTOSKRNL.EXE.@)
1240 PCONFIGURATION_INFORMATION WINAPI IoGetConfigurationInformation(void)
1242 FIXME( "partial stub\n" );
1243 /* FIXME: return actual devices on system */
1244 return &configuration_information;
1248 /***********************************************************************
1249 * IoIsWdmVersionAvailable (NTOSKRNL.EXE.@)
1251 NTSTATUS WINAPI IoIsWdmVersionAvailable(UCHAR MajorVersion, UCHAR MinorVersion)
1253 DWORD version;
1254 DWORD major;
1255 DWORD minor;
1257 TRACE( "%d, 0x%X\n", MajorVersion, MinorVersion );
1259 version = GetVersion();
1260 major = LOBYTE(version);
1261 minor = HIBYTE(LOWORD(version));
1263 if (MajorVersion == 6 && MinorVersion == 0)
1265 /* Windows Vista, Windows Server 2008, Windows 7 */
1267 else if (MajorVersion == 1)
1269 if (MinorVersion == 0x30)
1271 /* Windows server 2003 */
1272 MajorVersion = 6;
1273 MinorVersion = 0;
1275 else if (MinorVersion == 0x20)
1277 /* Windows XP */
1278 MajorVersion = 5;
1279 MinorVersion = 1;
1281 else if (MinorVersion == 0x10)
1283 /* Windows 2000 */
1284 MajorVersion = 5;
1285 MinorVersion = 0;
1287 else if (MinorVersion == 0x05)
1289 /* Windows ME */
1290 MajorVersion = 4;
1291 MinorVersion = 0x5a;
1293 else if (MinorVersion == 0x00)
1295 /* Windows 98 */
1296 MajorVersion = 4;
1297 MinorVersion = 0x0a;
1299 else
1301 FIXME( "unknown major %d minor 0x%X\n", MajorVersion, MinorVersion );
1302 return FALSE;
1305 else
1307 FIXME( "unknown major %d minor 0x%X\n", MajorVersion, MinorVersion );
1308 return FALSE;
1310 return major > MajorVersion || (major == MajorVersion && minor >= MinorVersion);
1314 /***********************************************************************
1315 * IoQueryDeviceDescription (NTOSKRNL.EXE.@)
1317 NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE itype, PULONG bus, PCONFIGURATION_TYPE ctype,
1318 PULONG cnum, PCONFIGURATION_TYPE ptype, PULONG pnum,
1319 PIO_QUERY_DEVICE_ROUTINE callout, PVOID context)
1321 FIXME( "(%p %p %p %p %p %p %p %p)\n", itype, bus, ctype, cnum, ptype, pnum, callout, context);
1322 return STATUS_NOT_IMPLEMENTED;
1326 /***********************************************************************
1327 * IoRegisterDriverReinitialization (NTOSKRNL.EXE.@)
1329 void WINAPI IoRegisterDriverReinitialization( PDRIVER_OBJECT obj, PDRIVER_REINITIALIZE reinit, PVOID context )
1331 FIXME( "stub: %p %p %p\n", obj, reinit, context );
1335 /***********************************************************************
1336 * IoRegisterShutdownNotification (NTOSKRNL.EXE.@)
1338 NTSTATUS WINAPI IoRegisterShutdownNotification( PDEVICE_OBJECT obj )
1340 FIXME( "stub: %p\n", obj );
1341 return STATUS_SUCCESS;
1345 /***********************************************************************
1346 * IoUnregisterShutdownNotification (NTOSKRNL.EXE.@)
1348 VOID WINAPI IoUnregisterShutdownNotification( PDEVICE_OBJECT obj )
1350 FIXME( "stub: %p\n", obj );
1354 /***********************************************************************
1355 * IoReportResourceUsage (NTOSKRNL.EXE.@)
1357 NTSTATUS WINAPI IoReportResourceUsage(PUNICODE_STRING name, PDRIVER_OBJECT drv_obj, PCM_RESOURCE_LIST drv_list,
1358 ULONG drv_size, PDRIVER_OBJECT dev_obj, PCM_RESOURCE_LIST dev_list,
1359 ULONG dev_size, BOOLEAN overwrite, PBOOLEAN detected)
1361 FIXME( "(%s, %p, %p, %u, %p, %p, %u, %d, %p): stub\n", debugstr_us(name),
1362 drv_obj, drv_list, drv_size, dev_obj, dev_list, dev_size, overwrite, detected );
1363 return STATUS_NOT_IMPLEMENTED;
1367 /***********************************************************************
1368 * IoCompleteRequest (NTOSKRNL.EXE.@)
1370 VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
1372 IO_STACK_LOCATION *irpsp;
1373 PIO_COMPLETION_ROUTINE routine;
1374 NTSTATUS status, stat;
1375 HANDLE handle;
1376 int call_flag = 0;
1378 TRACE( "%p %u\n", irp, priority_boost );
1380 status = irp->IoStatus.u.Status;
1381 while (irp->CurrentLocation <= irp->StackCount)
1383 irpsp = irp->Tail.Overlay.s.u2.CurrentStackLocation;
1384 routine = irpsp->CompletionRoutine;
1385 call_flag = 0;
1386 /* FIXME: add SL_INVOKE_ON_CANCEL support */
1387 if (routine)
1389 if ((irpsp->Control & SL_INVOKE_ON_SUCCESS) && STATUS_SUCCESS == status)
1390 call_flag = 1;
1391 if ((irpsp->Control & SL_INVOKE_ON_ERROR) && STATUS_SUCCESS != status)
1392 call_flag = 1;
1394 ++irp->CurrentLocation;
1395 ++irp->Tail.Overlay.s.u2.CurrentStackLocation;
1396 if (call_flag)
1398 TRACE( "calling %p( %p, %p, %p )\n", routine,
1399 irpsp->DeviceObject, irp, irpsp->Context );
1400 stat = routine( irpsp->DeviceObject, irp, irpsp->Context );
1401 TRACE( "CompletionRoutine returned %x\n", stat );
1402 if (STATUS_MORE_PROCESSING_REQUIRED == stat)
1403 return;
1407 handle = (HANDLE)irp->UserIosb;
1408 if (handle)
1410 void *out_buff = irp->UserBuffer;
1411 FILE_OBJECT *file = irp->Tail.Overlay.OriginalFileObject;
1413 SERVER_START_REQ( set_irp_result )
1415 req->handle = wine_server_obj_handle( handle );
1416 req->status = irp->IoStatus.u.Status;
1417 req->file_ptr = wine_server_client_ptr( file );
1418 if (irp->IoStatus.u.Status >= 0)
1420 req->size = irp->IoStatus.Information;
1421 if (out_buff) wine_server_add_data( req, out_buff, irp->IoStatus.Information );
1423 wine_server_call( req );
1425 SERVER_END_REQ;
1426 HeapFree( GetProcessHeap(), 0, out_buff );
1429 IoFreeIrp( irp );
1433 /***********************************************************************
1434 * IofCompleteRequest (NTOSKRNL.EXE.@)
1436 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1437 DEFINE_FASTCALL2_ENTRYPOINT( IofCompleteRequest )
1438 void WINAPI __regs_IofCompleteRequest( IRP *irp, UCHAR priority_boost )
1439 #else
1440 void WINAPI IofCompleteRequest( IRP *irp, UCHAR priority_boost )
1441 #endif
1443 TRACE( "%p %u\n", irp, priority_boost );
1444 IoCompleteRequest( irp, priority_boost );
1448 /***********************************************************************
1449 * InterlockedCompareExchange (NTOSKRNL.EXE.@)
1451 #ifdef DEFINE_FASTCALL3_ENTRYPOINT
1452 DEFINE_FASTCALL3_ENTRYPOINT( NTOSKRNL_InterlockedCompareExchange )
1453 LONG WINAPI __regs_NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
1454 #else
1455 LONG WINAPI NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
1456 #endif
1458 return InterlockedCompareExchange( dest, xchg, compare );
1462 /***********************************************************************
1463 * InterlockedDecrement (NTOSKRNL.EXE.@)
1465 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
1466 DEFINE_FASTCALL1_ENTRYPOINT( NTOSKRNL_InterlockedDecrement )
1467 LONG WINAPI __regs_NTOSKRNL_InterlockedDecrement( LONG volatile *dest )
1468 #else
1469 LONG WINAPI NTOSKRNL_InterlockedDecrement( LONG volatile *dest )
1470 #endif
1472 return InterlockedDecrement( dest );
1476 /***********************************************************************
1477 * InterlockedExchange (NTOSKRNL.EXE.@)
1479 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1480 DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedExchange )
1481 LONG WINAPI __regs_NTOSKRNL_InterlockedExchange( LONG volatile *dest, LONG val )
1482 #else
1483 LONG WINAPI NTOSKRNL_InterlockedExchange( LONG volatile *dest, LONG val )
1484 #endif
1486 return InterlockedExchange( dest, val );
1490 /***********************************************************************
1491 * InterlockedExchangeAdd (NTOSKRNL.EXE.@)
1493 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1494 DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedExchangeAdd )
1495 LONG WINAPI __regs_NTOSKRNL_InterlockedExchangeAdd( LONG volatile *dest, LONG incr )
1496 #else
1497 LONG WINAPI NTOSKRNL_InterlockedExchangeAdd( LONG volatile *dest, LONG incr )
1498 #endif
1500 return InterlockedExchangeAdd( dest, incr );
1504 /***********************************************************************
1505 * InterlockedIncrement (NTOSKRNL.EXE.@)
1507 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
1508 DEFINE_FASTCALL1_ENTRYPOINT( NTOSKRNL_InterlockedIncrement )
1509 LONG WINAPI __regs_NTOSKRNL_InterlockedIncrement( LONG volatile *dest )
1510 #else
1511 LONG WINAPI NTOSKRNL_InterlockedIncrement( LONG volatile *dest )
1512 #endif
1514 return InterlockedIncrement( dest );
1518 /***********************************************************************
1519 * InterlockedPopEntrySList (NTOSKRNL.EXE.@)
1521 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
1522 DEFINE_FASTCALL1_ENTRYPOINT( NTOSKRNL_InterlockedPopEntrySList )
1523 PSLIST_ENTRY WINAPI __regs_NTOSKRNL_InterlockedPopEntrySList( PSLIST_HEADER list )
1524 #else
1525 PSLIST_ENTRY WINAPI NTOSKRNL_InterlockedPopEntrySList( PSLIST_HEADER list )
1526 #endif
1528 return InterlockedPopEntrySList( list );
1532 /***********************************************************************
1533 * InterlockedPushEntrySList (NTOSKRNL.EXE.@)
1535 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1536 DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedPushEntrySList )
1537 PSLIST_ENTRY WINAPI __regs_NTOSKRNL_InterlockedPushEntrySList( PSLIST_HEADER list, PSLIST_ENTRY entry )
1538 #else
1539 PSLIST_ENTRY WINAPI NTOSKRNL_InterlockedPushEntrySList( PSLIST_HEADER list, PSLIST_ENTRY entry )
1540 #endif
1542 return InterlockedPushEntrySList( list, entry );
1546 /***********************************************************************
1547 * ExAllocatePool (NTOSKRNL.EXE.@)
1549 PVOID WINAPI ExAllocatePool( POOL_TYPE type, SIZE_T size )
1551 return ExAllocatePoolWithTag( type, size, 0 );
1555 /***********************************************************************
1556 * ExAllocatePoolWithQuota (NTOSKRNL.EXE.@)
1558 PVOID WINAPI ExAllocatePoolWithQuota( POOL_TYPE type, SIZE_T size )
1560 return ExAllocatePoolWithTag( type, size, 0 );
1564 /***********************************************************************
1565 * ExAllocatePoolWithTag (NTOSKRNL.EXE.@)
1567 PVOID WINAPI ExAllocatePoolWithTag( POOL_TYPE type, SIZE_T size, ULONG tag )
1569 /* FIXME: handle page alignment constraints */
1570 void *ret = HeapAlloc( GetProcessHeap(), 0, size );
1571 TRACE( "%lu pool %u -> %p\n", size, type, ret );
1572 return ret;
1576 /***********************************************************************
1577 * ExAllocatePoolWithQuotaTag (NTOSKRNL.EXE.@)
1579 PVOID WINAPI ExAllocatePoolWithQuotaTag( POOL_TYPE type, SIZE_T size, ULONG tag )
1581 return ExAllocatePoolWithTag( type, size, tag );
1585 /***********************************************************************
1586 * ExCreateCallback (NTOSKRNL.EXE.@)
1588 NTSTATUS WINAPI ExCreateCallback(PCALLBACK_OBJECT *obj, POBJECT_ATTRIBUTES attr,
1589 BOOLEAN create, BOOLEAN allow_multiple)
1591 FIXME("(%p, %p, %u, %u): stub\n", obj, attr, create, allow_multiple);
1593 return STATUS_NOT_IMPLEMENTED;
1597 /***********************************************************************
1598 * ExDeleteNPagedLookasideList (NTOSKRNL.EXE.@)
1600 void WINAPI ExDeleteNPagedLookasideList( PNPAGED_LOOKASIDE_LIST lookaside )
1602 FIXME("(%p) stub\n", lookaside);
1606 /***********************************************************************
1607 * ExDeletePagedLookasideList (NTOSKRNL.EXE.@)
1609 void WINAPI ExDeletePagedLookasideList( PPAGED_LOOKASIDE_LIST lookaside )
1611 FIXME("(%p) stub\n", lookaside);
1615 /***********************************************************************
1616 * ExFreePool (NTOSKRNL.EXE.@)
1618 void WINAPI ExFreePool( void *ptr )
1620 ExFreePoolWithTag( ptr, 0 );
1624 /***********************************************************************
1625 * ExFreePoolWithTag (NTOSKRNL.EXE.@)
1627 void WINAPI ExFreePoolWithTag( void *ptr, ULONG tag )
1629 TRACE( "%p\n", ptr );
1630 HeapFree( GetProcessHeap(), 0, ptr );
1634 /***********************************************************************
1635 * ExInitializeResourceLite (NTOSKRNL.EXE.@)
1637 NTSTATUS WINAPI ExInitializeResourceLite(PERESOURCE Resource)
1639 FIXME( "stub: %p\n", Resource );
1640 return STATUS_NOT_IMPLEMENTED;
1644 /***********************************************************************
1645 * ExInitializeNPagedLookasideList (NTOSKRNL.EXE.@)
1647 void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside,
1648 PALLOCATE_FUNCTION Allocate,
1649 PFREE_FUNCTION Free,
1650 ULONG Flags,
1651 SIZE_T Size,
1652 ULONG Tag,
1653 USHORT Depth)
1655 FIXME( "stub: %p, %p, %p, %u, %lu, %u, %u\n", Lookaside, Allocate, Free, Flags, Size, Tag, Depth );
1658 /***********************************************************************
1659 * ExInitializePagedLookasideList (NTOSKRNL.EXE.@)
1661 void WINAPI ExInitializePagedLookasideList(PPAGED_LOOKASIDE_LIST Lookaside,
1662 PALLOCATE_FUNCTION Allocate,
1663 PFREE_FUNCTION Free,
1664 ULONG Flags,
1665 SIZE_T Size,
1666 ULONG Tag,
1667 USHORT Depth)
1669 FIXME( "stub: %p, %p, %p, %u, %lu, %u, %u\n", Lookaside, Allocate, Free, Flags, Size, Tag, Depth );
1672 /***********************************************************************
1673 * ExInitializeZone (NTOSKRNL.EXE.@)
1675 NTSTATUS WINAPI ExInitializeZone(PZONE_HEADER Zone,
1676 ULONG BlockSize,
1677 PVOID InitialSegment,
1678 ULONG InitialSegmentSize)
1680 FIXME( "stub: %p, %u, %p, %u\n", Zone, BlockSize, InitialSegment, InitialSegmentSize );
1681 return STATUS_NOT_IMPLEMENTED;
1684 /***********************************************************************
1685 * FsRtlRegisterUncProvider (NTOSKRNL.EXE.@)
1687 NTSTATUS WINAPI FsRtlRegisterUncProvider(PHANDLE MupHandle, PUNICODE_STRING RedirDevName,
1688 BOOLEAN MailslotsSupported)
1690 FIXME("(%p %p %d): stub\n", MupHandle, RedirDevName, MailslotsSupported);
1691 return STATUS_NOT_IMPLEMENTED;
1694 /***********************************************************************
1695 * IoGetCurrentProcess / PsGetCurrentProcess (NTOSKRNL.EXE.@)
1697 PEPROCESS WINAPI IoGetCurrentProcess(void)
1699 FIXME("() stub\n");
1700 return NULL;
1703 /***********************************************************************
1704 * KeGetCurrentThread / PsGetCurrentThread (NTOSKRNL.EXE.@)
1706 PRKTHREAD WINAPI KeGetCurrentThread(void)
1708 FIXME("() stub\n");
1709 return NULL;
1712 /***********************************************************************
1713 * KeInitializeEvent (NTOSKRNL.EXE.@)
1715 void WINAPI KeInitializeEvent( PRKEVENT Event, EVENT_TYPE Type, BOOLEAN State )
1717 FIXME( "stub: %p %d %d\n", Event, Type, State );
1721 /***********************************************************************
1722 * KeInitializeMutex (NTOSKRNL.EXE.@)
1724 void WINAPI KeInitializeMutex(PRKMUTEX Mutex, ULONG Level)
1726 FIXME( "stub: %p, %u\n", Mutex, Level );
1730 /***********************************************************************
1731 * KeWaitForMutexObject (NTOSKRNL.EXE.@)
1733 NTSTATUS WINAPI KeWaitForMutexObject(PRKMUTEX Mutex, KWAIT_REASON WaitReason, KPROCESSOR_MODE WaitMode,
1734 BOOLEAN Alertable, PLARGE_INTEGER Timeout)
1736 FIXME( "stub: %p, %d, %d, %d, %p\n", Mutex, WaitReason, WaitMode, Alertable, Timeout );
1737 return STATUS_NOT_IMPLEMENTED;
1741 /***********************************************************************
1742 * KeReleaseMutex (NTOSKRNL.EXE.@)
1744 LONG WINAPI KeReleaseMutex(PRKMUTEX Mutex, BOOLEAN Wait)
1746 FIXME( "stub: %p, %d\n", Mutex, Wait );
1747 return STATUS_NOT_IMPLEMENTED;
1751 /***********************************************************************
1752 * KeInitializeSemaphore (NTOSKRNL.EXE.@)
1754 void WINAPI KeInitializeSemaphore( PRKSEMAPHORE Semaphore, LONG Count, LONG Limit )
1756 FIXME( "(%p %d %d) stub\n", Semaphore , Count, Limit );
1760 /***********************************************************************
1761 * KeInitializeSpinLock (NTOSKRNL.EXE.@)
1763 void WINAPI KeInitializeSpinLock( PKSPIN_LOCK SpinLock )
1765 FIXME( "stub: %p\n", SpinLock );
1769 /***********************************************************************
1770 * KeInitializeTimerEx (NTOSKRNL.EXE.@)
1772 void WINAPI KeInitializeTimerEx( PKTIMER Timer, TIMER_TYPE Type )
1774 FIXME( "stub: %p %d\n", Timer, Type );
1778 /***********************************************************************
1779 * KeInitializeTimer (NTOSKRNL.EXE.@)
1781 void WINAPI KeInitializeTimer( PKTIMER Timer )
1783 KeInitializeTimerEx(Timer, NotificationTimer);
1786 /***********************************************************************
1787 * KeInsertQueue (NTOSKRNL.EXE.@)
1789 LONG WINAPI KeInsertQueue(PRKQUEUE Queue, PLIST_ENTRY Entry)
1791 FIXME( "stub: %p %p\n", Queue, Entry );
1792 return 0;
1795 /**********************************************************************
1796 * KeQueryActiveProcessors (NTOSKRNL.EXE.@)
1798 * Return the active Processors as bitmask
1800 * RETURNS
1801 * active Processors as bitmask
1804 KAFFINITY WINAPI KeQueryActiveProcessors( void )
1806 DWORD_PTR AffinityMask;
1808 GetProcessAffinityMask( GetCurrentProcess(), &AffinityMask, NULL);
1809 return AffinityMask;
1813 /**********************************************************************
1814 * KeQueryInterruptTime (NTOSKRNL.EXE.@)
1816 * Return the interrupt time count
1819 ULONGLONG WINAPI KeQueryInterruptTime( void )
1821 LARGE_INTEGER totaltime;
1823 KeQueryTickCount(&totaltime);
1824 return totaltime.QuadPart;
1828 /***********************************************************************
1829 * KeQuerySystemTime (NTOSKRNL.EXE.@)
1831 void WINAPI KeQuerySystemTime( LARGE_INTEGER *time )
1833 NtQuerySystemTime( time );
1837 /***********************************************************************
1838 * KeQueryTickCount (NTOSKRNL.EXE.@)
1840 void WINAPI KeQueryTickCount( LARGE_INTEGER *count )
1842 count->QuadPart = NtGetTickCount();
1843 /* update the global variable too */
1844 KeTickCount.LowPart = count->u.LowPart;
1845 KeTickCount.High1Time = count->u.HighPart;
1846 KeTickCount.High2Time = count->u.HighPart;
1850 /***********************************************************************
1851 * KeReleaseSemaphore (NTOSKRNL.EXE.@)
1853 LONG WINAPI KeReleaseSemaphore( PRKSEMAPHORE Semaphore, KPRIORITY Increment,
1854 LONG Adjustment, BOOLEAN Wait )
1856 FIXME("(%p %d %d %d) stub\n", Semaphore, Increment, Adjustment, Wait );
1857 return 0;
1861 /***********************************************************************
1862 * KeQueryTimeIncrement (NTOSKRNL.EXE.@)
1864 ULONG WINAPI KeQueryTimeIncrement(void)
1866 return 10000;
1870 /***********************************************************************
1871 * KeResetEvent (NTOSKRNL.EXE.@)
1873 LONG WINAPI KeResetEvent( PRKEVENT Event )
1875 FIXME("(%p): stub\n", Event);
1876 return 0;
1880 /***********************************************************************
1881 * KeSetEvent (NTOSKRNL.EXE.@)
1883 LONG WINAPI KeSetEvent( PRKEVENT Event, KPRIORITY Increment, BOOLEAN Wait )
1885 FIXME("(%p, %d, %d): stub\n", Event, Increment, Wait);
1886 return 0;
1890 /***********************************************************************
1891 * KeSetPriorityThread (NTOSKRNL.EXE.@)
1893 KPRIORITY WINAPI KeSetPriorityThread( PKTHREAD Thread, KPRIORITY Priority )
1895 FIXME("(%p %d)\n", Thread, Priority);
1896 return Priority;
1899 /***********************************************************************
1900 * KeSetSystemAffinityThread (NTOSKRNL.EXE.@)
1902 VOID WINAPI KeSetSystemAffinityThread(KAFFINITY Affinity)
1904 FIXME("(%lx) stub\n", Affinity);
1907 /***********************************************************************
1908 * KeWaitForSingleObject (NTOSKRNL.EXE.@)
1910 NTSTATUS WINAPI KeWaitForSingleObject(PVOID Object,
1911 KWAIT_REASON WaitReason,
1912 KPROCESSOR_MODE WaitMode,
1913 BOOLEAN Alertable,
1914 PLARGE_INTEGER Timeout)
1916 FIXME( "stub: %p, %d, %d, %d, %p\n", Object, WaitReason, WaitMode, Alertable, Timeout );
1917 return STATUS_NOT_IMPLEMENTED;
1920 /***********************************************************************
1921 * IoRegisterFileSystem (NTOSKRNL.EXE.@)
1923 VOID WINAPI IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject)
1925 FIXME("(%p): stub\n", DeviceObject);
1928 /***********************************************************************
1929 * IoUnregisterFileSystem (NTOSKRNL.EXE.@)
1931 VOID WINAPI IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject)
1933 FIXME("(%p): stub\n", DeviceObject);
1936 /***********************************************************************
1937 * MmAllocateNonCachedMemory (NTOSKRNL.EXE.@)
1939 PVOID WINAPI MmAllocateNonCachedMemory( SIZE_T size )
1941 TRACE( "%lu\n", size );
1942 return VirtualAlloc( NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE|PAGE_NOCACHE );
1945 /***********************************************************************
1946 * MmAllocateContiguousMemory (NTOSKRNL.EXE.@)
1948 PVOID WINAPI MmAllocateContiguousMemory( SIZE_T size, PHYSICAL_ADDRESS highest_valid_address )
1950 FIXME( "%lu, %s stub\n", size, wine_dbgstr_longlong(highest_valid_address.QuadPart) );
1951 return NULL;
1954 /***********************************************************************
1955 * MmAllocateContiguousMemorySpecifyCache (NTOSKRNL.EXE.@)
1957 PVOID WINAPI MmAllocateContiguousMemorySpecifyCache( SIZE_T size,
1958 PHYSICAL_ADDRESS lowest_valid_address,
1959 PHYSICAL_ADDRESS highest_valid_address,
1960 PHYSICAL_ADDRESS BoundaryAddressMultiple,
1961 MEMORY_CACHING_TYPE CacheType )
1963 FIXME(": stub\n");
1964 return NULL;
1967 /***********************************************************************
1968 * MmAllocatePagesForMdl (NTOSKRNL.EXE.@)
1970 PMDL WINAPI MmAllocatePagesForMdl(PHYSICAL_ADDRESS lowaddress, PHYSICAL_ADDRESS highaddress,
1971 PHYSICAL_ADDRESS skipbytes, SIZE_T size)
1973 FIXME("%s %s %s %lu: stub\n", wine_dbgstr_longlong(lowaddress.QuadPart), wine_dbgstr_longlong(highaddress.QuadPart),
1974 wine_dbgstr_longlong(skipbytes.QuadPart), size);
1975 return NULL;
1978 /***********************************************************************
1979 * MmFreeNonCachedMemory (NTOSKRNL.EXE.@)
1981 void WINAPI MmFreeNonCachedMemory( void *addr, SIZE_T size )
1983 TRACE( "%p %lu\n", addr, size );
1984 VirtualFree( addr, 0, MEM_RELEASE );
1987 /***********************************************************************
1988 * MmIsAddressValid (NTOSKRNL.EXE.@)
1990 * Check if the process can access the virtual address without a pagefault
1992 * PARAMS
1993 * VirtualAddress [I] Address to check
1995 * RETURNS
1996 * Failure: FALSE
1997 * Success: TRUE (Accessing the Address works without a Pagefault)
2000 BOOLEAN WINAPI MmIsAddressValid(PVOID VirtualAddress)
2002 TRACE("(%p)\n", VirtualAddress);
2003 return !IsBadWritePtr(VirtualAddress, 1);
2006 /***********************************************************************
2007 * MmMapIoSpace (NTOSKRNL.EXE.@)
2009 PVOID WINAPI MmMapIoSpace( PHYSICAL_ADDRESS PhysicalAddress, DWORD NumberOfBytes, DWORD CacheType )
2011 FIXME( "stub: 0x%08x%08x, %d, %d\n", PhysicalAddress.u.HighPart, PhysicalAddress.u.LowPart, NumberOfBytes, CacheType );
2012 return NULL;
2016 /***********************************************************************
2017 * MmLockPagableSectionByHandle (NTOSKRNL.EXE.@)
2019 VOID WINAPI MmLockPagableSectionByHandle(PVOID ImageSectionHandle)
2021 FIXME("stub %p\n", ImageSectionHandle);
2024 /***********************************************************************
2025 * MmMapLockedPagesSpecifyCache (NTOSKRNL.EXE.@)
2027 PVOID WINAPI MmMapLockedPagesSpecifyCache(PMDLX MemoryDescriptorList, KPROCESSOR_MODE AccessMode, MEMORY_CACHING_TYPE CacheType,
2028 PVOID BaseAddress, ULONG BugCheckOnFailure, MM_PAGE_PRIORITY Priority)
2030 FIXME("(%p, %u, %u, %p, %u, %u): stub\n", MemoryDescriptorList, AccessMode, CacheType, BaseAddress, BugCheckOnFailure, Priority);
2032 return NULL;
2035 /***********************************************************************
2036 * MmUnlockPagableImageSection (NTOSKRNL.EXE.@)
2038 VOID WINAPI MmUnlockPagableImageSection(PVOID ImageSectionHandle)
2040 FIXME("stub %p\n", ImageSectionHandle);
2043 /***********************************************************************
2044 * MmPageEntireDriver (NTOSKRNL.EXE.@)
2046 PVOID WINAPI MmPageEntireDriver(PVOID AddrInSection)
2048 TRACE("%p\n", AddrInSection);
2049 return AddrInSection;
2053 /***********************************************************************
2054 * MmProbeAndLockPages (NTOSKRNL.EXE.@)
2056 void WINAPI MmProbeAndLockPages(PMDLX MemoryDescriptorList, KPROCESSOR_MODE AccessMode, LOCK_OPERATION Operation)
2058 FIXME("(%p, %u, %u): stub\n", MemoryDescriptorList, AccessMode, Operation);
2062 /***********************************************************************
2063 * MmResetDriverPaging (NTOSKRNL.EXE.@)
2065 void WINAPI MmResetDriverPaging(PVOID AddrInSection)
2067 TRACE("%p\n", AddrInSection);
2071 /***********************************************************************
2072 * MmUnlockPages (NTOSKRNL.EXE.@)
2074 void WINAPI MmUnlockPages(PMDLX MemoryDescriptorList)
2076 FIXME("(%p): stub\n", MemoryDescriptorList);
2080 /***********************************************************************
2081 * MmUnmapIoSpace (NTOSKRNL.EXE.@)
2083 VOID WINAPI MmUnmapIoSpace( PVOID BaseAddress, SIZE_T NumberOfBytes )
2085 FIXME( "stub: %p, %lu\n", BaseAddress, NumberOfBytes );
2089 /***********************************************************************
2090 * ObReferenceObjectByHandle (NTOSKRNL.EXE.@)
2092 NTSTATUS WINAPI ObReferenceObjectByHandle( HANDLE obj, ACCESS_MASK access,
2093 POBJECT_TYPE type,
2094 KPROCESSOR_MODE mode, PVOID* ptr,
2095 POBJECT_HANDLE_INFORMATION info)
2097 FIXME( "stub: %p %x %p %d %p %p\n", obj, access, type, mode, ptr, info);
2098 return STATUS_NOT_IMPLEMENTED;
2101 /***********************************************************************
2102 * ObReferenceObjectByName (NTOSKRNL.EXE.@)
2104 NTSTATUS WINAPI ObReferenceObjectByName( UNICODE_STRING *ObjectName,
2105 ULONG Attributes,
2106 ACCESS_STATE *AccessState,
2107 ACCESS_MASK DesiredAccess,
2108 POBJECT_TYPE ObjectType,
2109 KPROCESSOR_MODE AccessMode,
2110 void *ParseContext,
2111 void **Object)
2113 struct wine_driver *driver;
2114 struct wine_rb_entry *entry;
2116 TRACE("mostly-stub:%s %i %p %i %p %i %p %p\n", debugstr_us(ObjectName),
2117 Attributes, AccessState, DesiredAccess, ObjectType, AccessMode,
2118 ParseContext, Object);
2120 if (AccessState) FIXME("Unhandled AccessState\n");
2121 if (DesiredAccess) FIXME("Unhandled DesiredAccess\n");
2122 if (ParseContext) FIXME("Unhandled ParseContext\n");
2123 if (ObjectType) FIXME("Unhandled ObjectType\n");
2125 if (AccessMode != KernelMode)
2127 FIXME("UserMode access not implemented\n");
2128 return STATUS_NOT_IMPLEMENTED;
2131 EnterCriticalSection(&drivers_cs);
2132 entry = wine_rb_get(&wine_drivers, ObjectName);
2133 LeaveCriticalSection(&drivers_cs);
2134 if (!entry)
2136 FIXME("Object (%s) not found, may not be tracked.\n", debugstr_us(ObjectName));
2137 return STATUS_NOT_IMPLEMENTED;
2140 driver = WINE_RB_ENTRY_VALUE(entry, struct wine_driver, entry);
2141 *Object = &driver->driver_obj;
2142 return STATUS_SUCCESS;
2146 /***********************************************************************
2147 * ObDereferenceObject (NTOSKRNL.EXE.@)
2149 void WINAPI ObDereferenceObject( void *obj )
2151 TRACE( "(%p): stub\n", obj );
2155 /***********************************************************************
2156 * ObfReferenceObject (NTOSKRNL.EXE.@)
2158 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
2159 DEFINE_FASTCALL1_ENTRYPOINT( ObfReferenceObject )
2160 void WINAPI __regs_ObfReferenceObject( void *obj )
2161 #else
2162 void WINAPI ObfReferenceObject( void *obj )
2163 #endif
2165 FIXME( "(%p): stub\n", obj );
2169 /***********************************************************************
2170 * ObfDereferenceObject (NTOSKRNL.EXE.@)
2172 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
2173 DEFINE_FASTCALL1_ENTRYPOINT( ObfDereferenceObject )
2174 void WINAPI __regs_ObfDereferenceObject( void *obj )
2175 #else
2176 void WINAPI ObfDereferenceObject( void *obj )
2177 #endif
2179 ObDereferenceObject( obj );
2183 /***********************************************************************
2184 * PsCreateSystemThread (NTOSKRNL.EXE.@)
2186 NTSTATUS WINAPI PsCreateSystemThread(PHANDLE ThreadHandle, ULONG DesiredAccess,
2187 POBJECT_ATTRIBUTES ObjectAttributes,
2188 HANDLE ProcessHandle, PCLIENT_ID ClientId,
2189 PKSTART_ROUTINE StartRoutine, PVOID StartContext)
2191 if (!ProcessHandle) ProcessHandle = GetCurrentProcess();
2192 return RtlCreateUserThread(ProcessHandle, 0, FALSE, 0, 0,
2193 0, StartRoutine, StartContext,
2194 ThreadHandle, ClientId);
2197 /***********************************************************************
2198 * PsGetCurrentProcessId (NTOSKRNL.EXE.@)
2200 HANDLE WINAPI PsGetCurrentProcessId(void)
2202 if (GetCurrentThreadId() == request_thread)
2203 return UlongToHandle(client_pid);
2204 return UlongToHandle(GetCurrentProcessId());
2208 /***********************************************************************
2209 * PsGetCurrentThreadId (NTOSKRNL.EXE.@)
2211 HANDLE WINAPI PsGetCurrentThreadId(void)
2213 if (GetCurrentThreadId() == request_thread)
2214 return UlongToHandle(client_tid);
2215 return UlongToHandle(GetCurrentThreadId());
2219 /***********************************************************************
2220 * PsGetVersion (NTOSKRNL.EXE.@)
2222 BOOLEAN WINAPI PsGetVersion(ULONG *major, ULONG *minor, ULONG *build, UNICODE_STRING *version )
2224 RTL_OSVERSIONINFOEXW info;
2226 info.dwOSVersionInfoSize = sizeof(info);
2227 RtlGetVersion( &info );
2228 if (major) *major = info.dwMajorVersion;
2229 if (minor) *minor = info.dwMinorVersion;
2230 if (build) *build = info.dwBuildNumber;
2232 if (version)
2234 #if 0 /* FIXME: GameGuard passes an uninitialized pointer in version->Buffer */
2235 size_t len = min( strlenW(info.szCSDVersion)*sizeof(WCHAR), version->MaximumLength );
2236 memcpy( version->Buffer, info.szCSDVersion, len );
2237 if (len < version->MaximumLength) version->Buffer[len / sizeof(WCHAR)] = 0;
2238 version->Length = len;
2239 #endif
2241 return TRUE;
2245 /***********************************************************************
2246 * PsImpersonateClient (NTOSKRNL.EXE.@)
2248 NTSTATUS WINAPI PsImpersonateClient(PETHREAD Thread, PACCESS_TOKEN Token, BOOLEAN CopyOnOpen,
2249 BOOLEAN EffectiveOnly, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2251 FIXME("(%p, %p, %u, %u, %u): stub\n", Thread, Token, CopyOnOpen, EffectiveOnly, ImpersonationLevel);
2253 return STATUS_NOT_IMPLEMENTED;
2257 /***********************************************************************
2258 * PsSetCreateProcessNotifyRoutine (NTOSKRNL.EXE.@)
2260 NTSTATUS WINAPI PsSetCreateProcessNotifyRoutine( PCREATE_PROCESS_NOTIFY_ROUTINE callback, BOOLEAN remove )
2262 FIXME( "stub: %p %d\n", callback, remove );
2263 return STATUS_SUCCESS;
2267 /***********************************************************************
2268 * PsSetCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
2270 NTSTATUS WINAPI PsSetCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
2272 FIXME( "stub: %p\n", NotifyRoutine );
2273 return STATUS_SUCCESS;
2277 /***********************************************************************
2278 * PsRemoveCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
2280 NTSTATUS WINAPI PsRemoveCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
2282 FIXME( "stub: %p\n", NotifyRoutine );
2283 return STATUS_SUCCESS;
2287 /***********************************************************************
2288 * PsRemoveLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
2290 NTSTATUS WINAPI PsRemoveLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
2292 FIXME( "stub: %p\n", NotifyRoutine );
2293 return STATUS_SUCCESS;
2297 /***********************************************************************
2298 * PsTerminateSystemThread (NTOSKRNL.EXE.@)
2300 NTSTATUS WINAPI PsTerminateSystemThread(NTSTATUS ExitStatus)
2302 FIXME( "stub: %u\n", ExitStatus );
2303 return STATUS_NOT_IMPLEMENTED;
2307 /***********************************************************************
2308 * MmGetSystemRoutineAddress (NTOSKRNL.EXE.@)
2310 PVOID WINAPI MmGetSystemRoutineAddress(PUNICODE_STRING SystemRoutineName)
2312 HMODULE hMod;
2313 STRING routineNameA;
2314 PVOID pFunc = NULL;
2316 static const WCHAR ntoskrnlW[] = {'n','t','o','s','k','r','n','l','.','e','x','e',0};
2317 static const WCHAR halW[] = {'h','a','l','.','d','l','l',0};
2319 if (!SystemRoutineName) return NULL;
2321 if (RtlUnicodeStringToAnsiString( &routineNameA, SystemRoutineName, TRUE ) == STATUS_SUCCESS)
2323 /* We only support functions exported from ntoskrnl.exe or hal.dll */
2324 hMod = GetModuleHandleW( ntoskrnlW );
2325 pFunc = GetProcAddress( hMod, routineNameA.Buffer );
2326 if (!pFunc)
2328 hMod = GetModuleHandleW( halW );
2329 if (hMod) pFunc = GetProcAddress( hMod, routineNameA.Buffer );
2331 RtlFreeAnsiString( &routineNameA );
2334 if (pFunc)
2335 TRACE( "%s -> %p\n", debugstr_us(SystemRoutineName), pFunc );
2336 else
2337 FIXME( "%s not found\n", debugstr_us(SystemRoutineName) );
2338 return pFunc;
2342 /***********************************************************************
2343 * MmQuerySystemSize (NTOSKRNL.EXE.@)
2345 MM_SYSTEMSIZE WINAPI MmQuerySystemSize(void)
2347 FIXME("stub\n");
2348 return MmLargeSystem;
2351 /***********************************************************************
2352 * KeInitializeDpc (NTOSKRNL.EXE.@)
2354 VOID WINAPI KeInitializeDpc(PRKDPC Dpc, PKDEFERRED_ROUTINE DeferredRoutine, PVOID DeferredContext)
2356 FIXME("stub\n");
2359 /***********************************************************************
2360 * READ_REGISTER_BUFFER_UCHAR (NTOSKRNL.EXE.@)
2362 VOID WINAPI READ_REGISTER_BUFFER_UCHAR(PUCHAR Register, PUCHAR Buffer, ULONG Count)
2364 FIXME("stub\n");
2367 /*****************************************************
2368 * PoSetPowerState (NTOSKRNL.EXE.@)
2370 POWER_STATE WINAPI PoSetPowerState(PDEVICE_OBJECT DeviceObject, POWER_STATE_TYPE Type, POWER_STATE State)
2372 FIXME("(%p %u %u) stub\n", DeviceObject, Type, State.DeviceState);
2373 return State;
2376 /*****************************************************
2377 * IoWMIRegistrationControl (NTOSKRNL.EXE.@)
2379 NTSTATUS WINAPI IoWMIRegistrationControl(PDEVICE_OBJECT DeviceObject, ULONG Action)
2381 FIXME("(%p %u) stub\n", DeviceObject, Action);
2382 return STATUS_SUCCESS;
2385 /*****************************************************
2386 * PsSetLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
2388 NTSTATUS WINAPI PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine)
2390 FIXME("(%p) stub\n", routine);
2391 return STATUS_SUCCESS;
2394 /*****************************************************
2395 * PsLookupProcessByProcessId (NTOSKRNL.EXE.@)
2397 NTSTATUS WINAPI PsLookupProcessByProcessId(HANDLE processid, PEPROCESS *process)
2399 static int once;
2400 if (!once++) FIXME("(%p %p) stub\n", processid, process);
2401 return STATUS_NOT_IMPLEMENTED;
2405 /*****************************************************
2406 * IoSetThreadHardErrorMode (NTOSKRNL.EXE.@)
2408 BOOLEAN WINAPI IoSetThreadHardErrorMode(BOOLEAN EnableHardErrors)
2410 FIXME("stub\n");
2411 return FALSE;
2415 /*****************************************************
2416 * IoInitializeRemoveLockEx (NTOSKRNL.EXE.@)
2418 VOID WINAPI IoInitializeRemoveLockEx(PIO_REMOVE_LOCK lock, ULONG tag,
2419 ULONG maxmin, ULONG high, ULONG size)
2421 FIXME("(%p %u %u %u %u) stub\n", lock, tag, maxmin, high, size);
2425 /*****************************************************
2426 * IoAcquireRemoveLockEx (NTOSKRNL.EXE.@)
2429 NTSTATUS WINAPI IoAcquireRemoveLockEx(PIO_REMOVE_LOCK lock, PVOID tag,
2430 LPCSTR file, ULONG line, ULONG lock_size)
2432 FIXME("(%p, %p, %s, %u, %u): stub\n", lock, tag, debugstr_a(file), line, lock_size);
2434 return STATUS_NOT_IMPLEMENTED;
2438 /*****************************************************
2439 * DllMain
2441 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
2443 static void *handler;
2444 LARGE_INTEGER count;
2446 switch(reason)
2448 case DLL_PROCESS_ATTACH:
2449 DisableThreadLibraryCalls( inst );
2450 if (wine_rb_init( &wine_drivers, &wine_drivers_rb_functions )) return FALSE;
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 NTSTATUS status;
2728 DWORD bytes;
2729 int i;
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 for (i = 0; i < 100; i++) /* 10 sec timeout */
2740 if (StartServiceW( service_handle, 0, NULL )) break;
2741 if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) break;
2742 if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED) goto error;
2743 Sleep(100);
2745 if (i == 100) goto error;
2747 for (i = 0; i < 100; i++) /* 10 sec timeout */
2749 if (!QueryServiceStatusEx( service_handle, SC_STATUS_PROCESS_INFO,
2750 (BYTE *)&service_status, sizeof(service_status), &bytes )) goto error;
2751 if (service_status.dwCurrentState != SERVICE_START_PENDING) break;
2752 Sleep(100);
2755 if (service_status.dwCurrentState == SERVICE_RUNNING)
2757 if (service_status.dwProcessId != GetCurrentProcessId())
2758 FIXME( "driver %s was loaded into a different process\n", debugstr_us(service_name) );
2760 status = STATUS_SUCCESS;
2761 goto done;
2764 error:
2765 WARN( "failed to start service %s\n", debugstr_us(service_name) );
2766 status = STATUS_UNSUCCESSFUL;
2768 done:
2769 TRACE( "returning status %08x\n", status );
2770 CloseServiceHandle( service_handle );
2771 return status;
2775 /***********************************************************************
2776 * ZwUnloadDriver (NTOSKRNL.EXE.@)
2778 NTSTATUS WINAPI ZwUnloadDriver( const UNICODE_STRING *service_name )
2780 SERVICE_STATUS service_status;
2781 SC_HANDLE service_handle;
2782 NTSTATUS status;
2783 int i;
2785 TRACE( "(%s)\n", debugstr_us(service_name) );
2787 if ((status = open_driver( service_name, &service_handle )) != STATUS_SUCCESS)
2788 return status;
2790 if (!ControlService( service_handle, SERVICE_CONTROL_STOP, &service_status ))
2791 goto error;
2793 for (i = 0; i < 100; i++) /* 10 sec timeout */
2795 if (!QueryServiceStatus( service_handle, &service_status )) goto error;
2796 if (service_status.dwCurrentState != SERVICE_STOP_PENDING) break;
2797 Sleep(100);
2800 if (service_status.dwCurrentState == SERVICE_STOPPED)
2802 status = STATUS_SUCCESS;
2803 goto done;
2806 error:
2807 WARN( "failed to stop service %s\n", debugstr_us(service_name) );
2808 status = STATUS_UNSUCCESSFUL;
2810 done:
2811 TRACE( "returning status %08x\n", status );
2812 CloseServiceHandle( service_handle );
2813 return status;