ntoskrnl.exe: Implement NtBuildNumber.
[wine.git] / dlls / ntoskrnl.exe / ntoskrnl.c
blobaa569d5eb80bb66c72741aae1f2b09c73ee18ef2
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 "winbase.h"
40 #include "winuser.h"
41 #include "dbt.h"
42 #include "winreg.h"
43 #include "setupapi.h"
44 #include "ddk/csq.h"
45 #include "ddk/ntddk.h"
46 #include "ddk/ntifs.h"
47 #include "ddk/wdm.h"
48 #include "wine/unicode.h"
49 #include "wine/server.h"
50 #include "wine/debug.h"
51 #include "wine/heap.h"
52 #include "wine/rbtree.h"
53 #include "wine/svcctl.h"
55 #include "ntoskrnl_private.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
58 WINE_DECLARE_DEBUG_CHANNEL(relay);
59 WINE_DECLARE_DEBUG_CHANNEL(plugplay);
61 BOOLEAN KdDebuggerEnabled = FALSE;
62 ULONG InitSafeBootMode = 0;
63 USHORT NtBuildNumber = 0;
65 extern LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs );
67 KSYSTEM_TIME KeTickCount = { 0, 0, 0 };
69 typedef struct _KSERVICE_TABLE_DESCRIPTOR
71 PULONG_PTR Base;
72 PULONG Count;
73 ULONG Limit;
74 PUCHAR Number;
75 } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
77 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[4] = { { 0 } };
79 typedef void (WINAPI *PCREATE_PROCESS_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
80 typedef void (WINAPI *PCREATE_PROCESS_NOTIFY_ROUTINE_EX)(PEPROCESS,HANDLE,PPS_CREATE_NOTIFY_INFO);
81 typedef void (WINAPI *PCREATE_THREAD_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
83 static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
84 '\\','M','a','c','h','i','n','e',
85 '\\','S','y','s','t','e','m',
86 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
87 '\\','S','e','r','v','i','c','e','s',
88 '\\',0};
90 #define MAX_SERVICE_NAME 260
92 /* tid of the thread running client request */
93 static DWORD request_thread;
95 /* pid/tid of the client thread */
96 static DWORD client_tid;
97 static DWORD client_pid;
99 struct wine_driver
101 struct wine_rb_entry entry;
103 DRIVER_OBJECT driver_obj;
104 DRIVER_EXTENSION driver_extension;
105 SERVICE_STATUS_HANDLE service_handle;
108 struct device_interface
110 struct wine_rb_entry entry;
112 UNICODE_STRING symbolic_link;
113 DEVICE_OBJECT *device;
114 GUID interface_class;
115 BOOL enabled;
118 static NTSTATUS get_device_id( DEVICE_OBJECT *device, BUS_QUERY_ID_TYPE type, WCHAR **id );
120 static int wine_drivers_rb_compare( const void *key, const struct wine_rb_entry *entry )
122 const struct wine_driver *driver = WINE_RB_ENTRY_VALUE( entry, const struct wine_driver, entry );
123 const UNICODE_STRING *k = key;
125 return RtlCompareUnicodeString( k, &driver->driver_obj.DriverName, FALSE );
128 static struct wine_rb_tree wine_drivers = { wine_drivers_rb_compare };
130 static int interface_rb_compare( const void *key, const struct wine_rb_entry *entry)
132 const struct device_interface *iface = WINE_RB_ENTRY_VALUE( entry, const struct device_interface, entry );
133 const UNICODE_STRING *k = key;
135 return RtlCompareUnicodeString( k, &iface->symbolic_link, FALSE );
138 static struct wine_rb_tree device_interfaces = { interface_rb_compare };
140 static CRITICAL_SECTION drivers_cs;
141 static CRITICAL_SECTION_DEBUG critsect_debug =
143 0, 0, &drivers_cs,
144 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
145 0, 0, { (DWORD_PTR)(__FILE__ ": drivers_cs") }
147 static CRITICAL_SECTION drivers_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
149 static inline LPCSTR debugstr_us( const UNICODE_STRING *us )
151 if (!us) return "<null>";
152 return debugstr_wn( us->Buffer, us->Length / sizeof(WCHAR) );
155 static inline BOOL is_valid_hex(WCHAR c)
157 if (!(((c >= '0') && (c <= '9')) ||
158 ((c >= 'a') && (c <= 'f')) ||
159 ((c >= 'A') && (c <= 'F'))))
160 return FALSE;
161 return TRUE;
164 static const BYTE guid_conv_table[256] =
166 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
169 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
170 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
172 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
175 static BOOL guid_from_string(const WCHAR *s, GUID *id)
177 int i;
179 if (!s || s[0] != '{')
181 memset( id, 0, sizeof (CLSID) );
182 return FALSE;
185 id->Data1 = 0;
186 for (i = 1; i < 9; i++)
188 if (!is_valid_hex(s[i])) return FALSE;
189 id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
191 if (s[9] != '-') return FALSE;
193 id->Data2 = 0;
194 for (i = 10; i < 14; i++)
196 if (!is_valid_hex(s[i])) return FALSE;
197 id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
199 if (s[14] != '-') return FALSE;
201 id->Data3 = 0;
202 for (i = 15; i < 19; i++)
204 if (!is_valid_hex(s[i])) return FALSE;
205 id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
207 if (s[19] != '-') return FALSE;
209 for (i = 20; i < 37; i += 2)
211 if (i == 24)
213 if (s[i] != '-') return FALSE;
214 i++;
216 if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
217 id->Data4[(i-20)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]];
220 if (s[37] == '}')
221 return TRUE;
223 return FALSE;
226 static HANDLE get_device_manager(void)
228 static HANDLE device_manager;
229 HANDLE handle = 0, ret = device_manager;
231 if (!ret)
233 SERVER_START_REQ( create_device_manager )
235 req->access = SYNCHRONIZE;
236 req->attributes = 0;
237 if (!wine_server_call( req )) handle = wine_server_ptr_handle( reply->handle );
239 SERVER_END_REQ;
241 if (!handle)
243 ERR( "failed to create the device manager\n" );
244 return 0;
246 if (!(ret = InterlockedCompareExchangePointer( &device_manager, handle, 0 )))
247 ret = handle;
248 else
249 NtClose( handle ); /* somebody beat us to it */
251 return ret;
254 /* transfer result of IRP back to wineserver */
255 static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp, void *context )
257 FILE_OBJECT *file = irp->Tail.Overlay.OriginalFileObject;
258 HANDLE irp_handle = context;
259 void *out_buff = irp->UserBuffer;
261 if (irp->Flags & IRP_WRITE_OPERATION)
262 out_buff = NULL; /* do not transfer back input buffer */
264 SERVER_START_REQ( set_irp_result )
266 req->handle = wine_server_obj_handle( irp_handle );
267 req->status = irp->IoStatus.u.Status;
268 req->file_ptr = wine_server_client_ptr( file );
269 if (irp->IoStatus.u.Status >= 0)
271 req->size = irp->IoStatus.Information;
272 if (out_buff) wine_server_add_data( req, out_buff, irp->IoStatus.Information );
274 wine_server_call( req );
276 SERVER_END_REQ;
278 if (irp->Flags & IRP_CLOSE_OPERATION)
280 HeapFree( GetProcessHeap(), 0, file );
281 irp->Tail.Overlay.OriginalFileObject = NULL;
284 if (irp->UserBuffer != irp->AssociatedIrp.SystemBuffer)
286 HeapFree( GetProcessHeap(), 0, irp->UserBuffer );
287 irp->UserBuffer = NULL;
289 return STATUS_SUCCESS;
292 static void dispatch_irp( DEVICE_OBJECT *device, IRP *irp, HANDLE irp_handle )
294 LARGE_INTEGER count;
296 IoSetCompletionRoutine( irp, dispatch_irp_completion, irp_handle, TRUE, TRUE, TRUE );
297 KeQueryTickCount( &count ); /* update the global KeTickCount */
299 device->CurrentIrp = irp;
300 IoCallDriver( device, irp );
301 device->CurrentIrp = NULL;
304 /* process a create request for a given file */
305 static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULONG in_size,
306 ULONG out_size, HANDLE irp_handle )
308 IRP *irp;
309 IO_STACK_LOCATION *irpsp;
310 FILE_OBJECT *file;
311 DEVICE_OBJECT *device = wine_server_get_ptr( params->create.device );
313 if (!(file = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*file) ))) return STATUS_NO_MEMORY;
315 TRACE( "device %p -> file %p\n", device, file );
317 file->Type = 5; /* MSDN */
318 file->Size = sizeof(*file);
319 file->DeviceObject = device;
321 if (!(irp = IoAllocateIrp( device->StackSize, FALSE )))
323 HeapFree( GetProcessHeap(), 0, file );
324 return STATUS_NO_MEMORY;
327 irpsp = IoGetNextIrpStackLocation( irp );
328 irpsp->MajorFunction = IRP_MJ_CREATE;
329 irpsp->DeviceObject = device;
330 irpsp->FileObject = file;
331 irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
332 irpsp->Parameters.Create.Options = params->create.options;
333 irpsp->Parameters.Create.ShareAccess = params->create.sharing;
334 irpsp->Parameters.Create.FileAttributes = 0;
335 irpsp->Parameters.Create.EaLength = 0;
337 irp->Tail.Overlay.OriginalFileObject = file;
338 irp->RequestorMode = UserMode;
339 irp->AssociatedIrp.SystemBuffer = NULL;
340 irp->UserBuffer = NULL;
341 irp->UserIosb = NULL;
342 irp->UserEvent = NULL;
344 irp->Flags |= IRP_CREATE_OPERATION;
345 dispatch_irp( device, irp, irp_handle );
347 HeapFree( GetProcessHeap(), 0, in_buff );
348 return STATUS_SUCCESS;
351 /* process a close request for a given file */
352 static NTSTATUS dispatch_close( const irp_params_t *params, void *in_buff, ULONG in_size,
353 ULONG out_size, HANDLE irp_handle )
355 IRP *irp;
356 IO_STACK_LOCATION *irpsp;
357 DEVICE_OBJECT *device;
358 FILE_OBJECT *file = wine_server_get_ptr( params->close.file );
360 if (!file) return STATUS_INVALID_HANDLE;
362 device = file->DeviceObject;
364 TRACE( "device %p file %p\n", device, file );
366 if (!(irp = IoAllocateIrp( device->StackSize, FALSE )))
368 HeapFree( GetProcessHeap(), 0, file );
369 return STATUS_NO_MEMORY;
372 irpsp = IoGetNextIrpStackLocation( irp );
373 irpsp->MajorFunction = IRP_MJ_CLOSE;
374 irpsp->DeviceObject = device;
375 irpsp->FileObject = file;
377 irp->Tail.Overlay.OriginalFileObject = file;
378 irp->RequestorMode = UserMode;
379 irp->AssociatedIrp.SystemBuffer = NULL;
380 irp->UserBuffer = NULL;
381 irp->UserIosb = NULL;
382 irp->UserEvent = NULL;
384 irp->Flags |= IRP_CLOSE_OPERATION;
385 dispatch_irp( device, irp, irp_handle );
387 HeapFree( GetProcessHeap(), 0, in_buff );
388 return STATUS_SUCCESS;
391 /* process a read request for a given device */
392 static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG in_size,
393 ULONG out_size, HANDLE irp_handle )
395 IRP *irp;
396 void *out_buff;
397 LARGE_INTEGER offset;
398 IO_STACK_LOCATION *irpsp;
399 DEVICE_OBJECT *device;
400 FILE_OBJECT *file = wine_server_get_ptr( params->read.file );
402 if (!file) return STATUS_INVALID_HANDLE;
404 device = file->DeviceObject;
406 TRACE( "device %p file %p size %u\n", device, file, out_size );
408 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
410 offset.QuadPart = params->read.pos;
412 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, device, out_buff, out_size,
413 &offset, NULL, NULL )))
415 HeapFree( GetProcessHeap(), 0, out_buff );
416 return STATUS_NO_MEMORY;
419 irp->Tail.Overlay.OriginalFileObject = file;
420 irp->RequestorMode = UserMode;
422 irpsp = IoGetNextIrpStackLocation( irp );
423 irpsp->FileObject = file;
424 irpsp->Parameters.Read.Key = params->read.key;
426 irp->Flags |= IRP_READ_OPERATION;
427 irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate out_buff */
428 dispatch_irp( device, irp, irp_handle );
430 HeapFree( GetProcessHeap(), 0, in_buff );
431 return STATUS_SUCCESS;
434 /* process a write request for a given device */
435 static NTSTATUS dispatch_write( const irp_params_t *params, void *in_buff, ULONG in_size,
436 ULONG out_size, HANDLE irp_handle )
438 IRP *irp;
439 LARGE_INTEGER offset;
440 IO_STACK_LOCATION *irpsp;
441 DEVICE_OBJECT *device;
442 FILE_OBJECT *file = wine_server_get_ptr( params->write.file );
444 if (!file) return STATUS_INVALID_HANDLE;
446 device = file->DeviceObject;
448 TRACE( "device %p file %p size %u\n", device, file, in_size );
450 offset.QuadPart = params->write.pos;
452 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, device, in_buff, in_size,
453 &offset, NULL, NULL )))
454 return STATUS_NO_MEMORY;
456 irp->Tail.Overlay.OriginalFileObject = file;
457 irp->RequestorMode = UserMode;
459 irpsp = IoGetNextIrpStackLocation( irp );
460 irpsp->FileObject = file;
461 irpsp->Parameters.Write.Key = params->write.key;
463 irp->Flags |= IRP_WRITE_OPERATION;
464 irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate in_buff */
465 dispatch_irp( device, irp, irp_handle );
467 return STATUS_SUCCESS;
470 /* process a flush request for a given device */
471 static NTSTATUS dispatch_flush( const irp_params_t *params, void *in_buff, ULONG in_size,
472 ULONG out_size, HANDLE irp_handle )
474 IRP *irp;
475 IO_STACK_LOCATION *irpsp;
476 DEVICE_OBJECT *device;
477 FILE_OBJECT *file = wine_server_get_ptr( params->flush.file );
479 if (!file) return STATUS_INVALID_HANDLE;
481 device = file->DeviceObject;
483 TRACE( "device %p file %p\n", device, file );
485 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_FLUSH_BUFFERS, device, NULL, 0,
486 NULL, NULL, NULL )))
487 return STATUS_NO_MEMORY;
489 irp->Tail.Overlay.OriginalFileObject = file;
490 irp->RequestorMode = UserMode;
492 irpsp = IoGetNextIrpStackLocation( irp );
493 irpsp->FileObject = file;
495 dispatch_irp( device, irp, irp_handle );
497 HeapFree( GetProcessHeap(), 0, in_buff );
498 return STATUS_SUCCESS;
501 /* process an ioctl request for a given device */
502 static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG in_size,
503 ULONG out_size, HANDLE irp_handle )
505 IO_STACK_LOCATION *irpsp;
506 IRP *irp;
507 void *out_buff = NULL;
508 void *to_free = NULL;
509 DEVICE_OBJECT *device;
510 FILE_OBJECT *file = wine_server_get_ptr( params->ioctl.file );
512 if (!file) return STATUS_INVALID_HANDLE;
514 device = file->DeviceObject;
516 TRACE( "ioctl %x device %p file %p in_size %u out_size %u\n",
517 params->ioctl.code, device, file, in_size, out_size );
519 if (out_size)
521 if ((params->ioctl.code & 3) != METHOD_BUFFERED)
523 if (in_size < out_size) return STATUS_INVALID_DEVICE_REQUEST;
524 in_size -= out_size;
525 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
526 memcpy( out_buff, (char *)in_buff + in_size, out_size );
528 else if (out_size > in_size)
530 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
531 memcpy( out_buff, in_buff, in_size );
532 to_free = in_buff;
533 in_buff = out_buff;
535 else
537 out_buff = in_buff;
538 out_size = in_size;
542 irp = IoBuildDeviceIoControlRequest( params->ioctl.code, device, in_buff, in_size, out_buff, out_size,
543 FALSE, NULL, NULL );
544 if (!irp)
546 HeapFree( GetProcessHeap(), 0, out_buff );
547 return STATUS_NO_MEMORY;
550 if (out_size && (params->ioctl.code & 3) != METHOD_BUFFERED)
551 HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, in_buff, in_size );
553 irpsp = IoGetNextIrpStackLocation( irp );
554 irpsp->FileObject = file;
556 irp->Tail.Overlay.OriginalFileObject = file;
557 irp->RequestorMode = UserMode;
558 irp->AssociatedIrp.SystemBuffer = in_buff;
560 irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate in_buff */
561 dispatch_irp( device, irp, irp_handle );
563 HeapFree( GetProcessHeap(), 0, to_free );
564 return STATUS_SUCCESS;
567 typedef NTSTATUS (*dispatch_func)( const irp_params_t *params, void *in_buff, ULONG in_size,
568 ULONG out_size, HANDLE irp_handle );
570 static const dispatch_func dispatch_funcs[IRP_MJ_MAXIMUM_FUNCTION + 1] =
572 dispatch_create, /* IRP_MJ_CREATE */
573 NULL, /* IRP_MJ_CREATE_NAMED_PIPE */
574 dispatch_close, /* IRP_MJ_CLOSE */
575 dispatch_read, /* IRP_MJ_READ */
576 dispatch_write, /* IRP_MJ_WRITE */
577 NULL, /* IRP_MJ_QUERY_INFORMATION */
578 NULL, /* IRP_MJ_SET_INFORMATION */
579 NULL, /* IRP_MJ_QUERY_EA */
580 NULL, /* IRP_MJ_SET_EA */
581 dispatch_flush, /* IRP_MJ_FLUSH_BUFFERS */
582 NULL, /* IRP_MJ_QUERY_VOLUME_INFORMATION */
583 NULL, /* IRP_MJ_SET_VOLUME_INFORMATION */
584 NULL, /* IRP_MJ_DIRECTORY_CONTROL */
585 NULL, /* IRP_MJ_FILE_SYSTEM_CONTROL */
586 dispatch_ioctl, /* IRP_MJ_DEVICE_CONTROL */
587 NULL, /* IRP_MJ_INTERNAL_DEVICE_CONTROL */
588 NULL, /* IRP_MJ_SHUTDOWN */
589 NULL, /* IRP_MJ_LOCK_CONTROL */
590 NULL, /* IRP_MJ_CLEANUP */
591 NULL, /* IRP_MJ_CREATE_MAILSLOT */
592 NULL, /* IRP_MJ_QUERY_SECURITY */
593 NULL, /* IRP_MJ_SET_SECURITY */
594 NULL, /* IRP_MJ_POWER */
595 NULL, /* IRP_MJ_SYSTEM_CONTROL */
596 NULL, /* IRP_MJ_DEVICE_CHANGE */
597 NULL, /* IRP_MJ_QUERY_QUOTA */
598 NULL, /* IRP_MJ_SET_QUOTA */
599 NULL, /* IRP_MJ_PNP */
602 /* helper function to update service status */
603 static void set_service_status( SERVICE_STATUS_HANDLE handle, DWORD state, DWORD accepted )
605 SERVICE_STATUS status;
606 status.dwServiceType = SERVICE_WIN32;
607 status.dwCurrentState = state;
608 status.dwControlsAccepted = accepted;
609 status.dwWin32ExitCode = 0;
610 status.dwServiceSpecificExitCode = 0;
611 status.dwCheckPoint = 0;
612 status.dwWaitHint = (state == SERVICE_START_PENDING) ? 10000 : 0;
613 SetServiceStatus( handle, &status );
616 static void unload_driver( struct wine_rb_entry *entry, void *context )
618 struct wine_driver *driver = WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry );
619 SERVICE_STATUS_HANDLE service_handle = driver->service_handle;
620 LDR_MODULE *ldr;
622 if (!service_handle) return; /* not a service */
624 TRACE("%s\n", debugstr_us(&driver->driver_obj.DriverName));
626 if (!driver->driver_obj.DriverUnload)
628 TRACE( "driver %s does not support unloading\n", debugstr_us(&driver->driver_obj.DriverName) );
629 return;
632 ldr = driver->driver_obj.DriverSection;
634 set_service_status( service_handle, SERVICE_STOP_PENDING, 0 );
636 TRACE_(relay)( "\1Call driver unload %p (obj=%p)\n", driver->driver_obj.DriverUnload, &driver->driver_obj );
638 driver->driver_obj.DriverUnload( &driver->driver_obj );
640 TRACE_(relay)( "\1Ret driver unload %p (obj=%p)\n", driver->driver_obj.DriverUnload, &driver->driver_obj );
642 FreeLibrary( ldr->BaseAddress );
643 IoDeleteDriver( &driver->driver_obj );
645 set_service_status( service_handle, SERVICE_STOPPED, 0 );
646 CloseServiceHandle( (void *)service_handle );
649 /***********************************************************************
650 * wine_ntoskrnl_main_loop (Not a Windows API)
652 NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
654 HANDLE manager = get_device_manager();
655 HANDLE irp = 0;
656 NTSTATUS status = STATUS_SUCCESS;
657 irp_params_t irp_params;
658 ULONG in_size = 4096, out_size = 0;
659 void *in_buff = NULL;
660 HANDLE handles[2];
662 request_thread = GetCurrentThreadId();
664 handles[0] = stop_event;
665 handles[1] = manager;
667 for (;;)
669 if (!in_buff && !(in_buff = HeapAlloc( GetProcessHeap(), 0, in_size )))
671 ERR( "failed to allocate buffer\n" );
672 status = STATUS_NO_MEMORY;
673 goto done;
676 SERVER_START_REQ( get_next_device_request )
678 req->manager = wine_server_obj_handle( manager );
679 req->prev = wine_server_obj_handle( irp );
680 req->status = status;
681 wine_server_set_reply( req, in_buff, in_size );
682 if (!(status = wine_server_call( req )))
684 irp = wine_server_ptr_handle( reply->next );
685 irp_params = reply->params;
686 client_tid = reply->client_tid;
687 client_pid = reply->client_pid;
688 in_size = reply->in_size;
689 out_size = reply->out_size;
691 else
693 irp = 0; /* no previous irp */
694 if (status == STATUS_BUFFER_OVERFLOW)
695 in_size = reply->in_size;
698 SERVER_END_REQ;
700 switch (status)
702 case STATUS_SUCCESS:
703 if (irp_params.major > IRP_MJ_MAXIMUM_FUNCTION || !dispatch_funcs[irp_params.major])
705 WARN( "unsupported request %u\n", irp_params.major );
706 status = STATUS_NOT_SUPPORTED;
707 break;
709 status = dispatch_funcs[irp_params.major]( &irp_params, in_buff, in_size, out_size, irp );
710 if (status == STATUS_SUCCESS)
712 irp = 0; /* status reported by IoCompleteRequest */
713 in_size = 4096;
714 in_buff = NULL;
716 break;
717 case STATUS_BUFFER_OVERFLOW:
718 HeapFree( GetProcessHeap(), 0, in_buff );
719 in_buff = NULL;
720 /* restart with larger buffer */
721 break;
722 case STATUS_PENDING:
723 for (;;)
725 DWORD ret = WaitForMultipleObjectsEx( 2, handles, FALSE, INFINITE, TRUE );
726 if (ret == WAIT_OBJECT_0)
728 HeapFree( GetProcessHeap(), 0, in_buff );
729 status = STATUS_SUCCESS;
730 goto done;
732 if (ret != WAIT_IO_COMPLETION) break;
734 break;
738 done:
739 wine_rb_destroy( &wine_drivers, unload_driver, NULL );
740 return status;
743 /***********************************************************************
744 * IoAllocateDriverObjectExtension (NTOSKRNL.EXE.@)
746 NTSTATUS WINAPI IoAllocateDriverObjectExtension( PDRIVER_OBJECT DriverObject,
747 PVOID ClientIdentificationAddress,
748 ULONG DriverObjectExtensionSize,
749 PVOID *DriverObjectExtension )
751 FIXME( "stub: %p, %p, %u, %p\n", DriverObject, ClientIdentificationAddress,
752 DriverObjectExtensionSize, DriverObjectExtension );
753 return STATUS_NOT_IMPLEMENTED;
757 /***********************************************************************
758 * IoGetDriverObjectExtension (NTOSKRNL.EXE.@)
760 PVOID WINAPI IoGetDriverObjectExtension( PDRIVER_OBJECT DriverObject,
761 PVOID ClientIdentificationAddress )
763 FIXME( "stub: %p, %p\n", DriverObject, ClientIdentificationAddress );
764 return NULL;
768 /***********************************************************************
769 * IoInitializeIrp (NTOSKRNL.EXE.@)
771 void WINAPI IoInitializeIrp( IRP *irp, USHORT size, CCHAR stack_size )
773 TRACE( "%p, %u, %d\n", irp, size, stack_size );
775 RtlZeroMemory( irp, size );
777 irp->Type = IO_TYPE_IRP;
778 irp->Size = size;
779 InitializeListHead( &irp->ThreadListEntry );
780 irp->StackCount = stack_size;
781 irp->CurrentLocation = stack_size + 1;
782 irp->Tail.Overlay.s.u2.CurrentStackLocation =
783 (PIO_STACK_LOCATION)(irp + 1) + stack_size;
787 /***********************************************************************
788 * IoInitializeTimer (NTOSKRNL.EXE.@)
790 NTSTATUS WINAPI IoInitializeTimer(PDEVICE_OBJECT DeviceObject,
791 PIO_TIMER_ROUTINE TimerRoutine,
792 PVOID Context)
794 FIXME( "stub: %p, %p, %p\n", DeviceObject, TimerRoutine, Context );
795 return STATUS_NOT_IMPLEMENTED;
799 /***********************************************************************
800 * IoStartTimer (NTOSKRNL.EXE.@)
802 void WINAPI IoStartTimer(PDEVICE_OBJECT DeviceObject)
804 FIXME( "stub: %p\n", DeviceObject );
808 /***********************************************************************
809 * IoStopTimer (NTOSKRNL.EXE.@)
811 void WINAPI IoStopTimer(PDEVICE_OBJECT DeviceObject)
813 FIXME( "stub: %p\n", DeviceObject );
817 /***********************************************************************
818 * IoAllocateIrp (NTOSKRNL.EXE.@)
820 PIRP WINAPI IoAllocateIrp( CCHAR stack_size, BOOLEAN charge_quota )
822 SIZE_T size;
823 PIRP irp;
824 CCHAR loc_count = stack_size;
826 TRACE( "%d, %d\n", stack_size, charge_quota );
828 if (loc_count < 8 && loc_count != 1)
829 loc_count = 8;
831 size = sizeof(IRP) + loc_count * sizeof(IO_STACK_LOCATION);
832 irp = ExAllocatePool( NonPagedPool, size );
833 if (irp == NULL)
834 return NULL;
835 IoInitializeIrp( irp, size, stack_size );
836 if (stack_size >= 1 && stack_size <= 8)
837 irp->AllocationFlags = IRP_ALLOCATED_FIXED_SIZE;
838 if (charge_quota)
839 irp->AllocationFlags |= IRP_LOOKASIDE_ALLOCATION;
840 return irp;
844 /***********************************************************************
845 * IoFreeIrp (NTOSKRNL.EXE.@)
847 void WINAPI IoFreeIrp( IRP *irp )
849 MDL *mdl;
851 TRACE( "%p\n", irp );
853 mdl = irp->MdlAddress;
854 while (mdl)
856 MDL *next = mdl->Next;
857 IoFreeMdl( mdl );
858 mdl = next;
861 ExFreePool( irp );
865 /***********************************************************************
866 * IoAllocateErrorLogEntry (NTOSKRNL.EXE.@)
868 PVOID WINAPI IoAllocateErrorLogEntry( PVOID IoObject, UCHAR EntrySize )
870 FIXME( "stub: %p, %u\n", IoObject, EntrySize );
871 return NULL;
875 /***********************************************************************
876 * IoAllocateMdl (NTOSKRNL.EXE.@)
878 PMDL WINAPI IoAllocateMdl( PVOID va, ULONG length, BOOLEAN secondary, BOOLEAN charge_quota, IRP *irp )
880 SIZE_T mdl_size;
881 PMDL mdl;
883 TRACE("(%p, %u, %i, %i, %p)\n", va, length, secondary, charge_quota, irp);
885 if (charge_quota)
886 FIXME("Charge quota is not yet supported\n");
888 mdl_size = sizeof(MDL) + sizeof(PFN_NUMBER) * ADDRESS_AND_SIZE_TO_SPAN_PAGES(va, length);
889 mdl = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, mdl_size );
890 if (!mdl)
891 return NULL;
893 MmInitializeMdl( mdl, va, length );
895 if (!irp) return mdl;
897 if (secondary) /* add it at the end */
899 MDL **pmdl = &irp->MdlAddress;
900 while (*pmdl) pmdl = &(*pmdl)->Next;
901 *pmdl = mdl;
903 else
905 mdl->Next = irp->MdlAddress;
906 irp->MdlAddress = mdl;
908 return mdl;
912 /***********************************************************************
913 * IoFreeMdl (NTOSKRNL.EXE.@)
915 void WINAPI IoFreeMdl(PMDL mdl)
917 TRACE("%p\n", mdl);
918 HeapFree(GetProcessHeap(), 0, mdl);
922 /***********************************************************************
923 * IoAllocateWorkItem (NTOSKRNL.EXE.@)
925 PIO_WORKITEM WINAPI IoAllocateWorkItem( PDEVICE_OBJECT DeviceObject )
927 FIXME( "stub: %p\n", DeviceObject );
928 return NULL;
932 /***********************************************************************
933 * IoAttachDeviceToDeviceStack (NTOSKRNL.EXE.@)
935 PDEVICE_OBJECT WINAPI IoAttachDeviceToDeviceStack( DEVICE_OBJECT *source,
936 DEVICE_OBJECT *target )
938 TRACE( "%p, %p\n", source, target );
939 target->AttachedDevice = source;
940 source->StackSize = target->StackSize + 1;
941 return target;
945 /***********************************************************************
946 * IoBuildDeviceIoControlRequest (NTOSKRNL.EXE.@)
948 PIRP WINAPI IoBuildDeviceIoControlRequest( ULONG code, PDEVICE_OBJECT device,
949 PVOID in_buff, ULONG in_len,
950 PVOID out_buff, ULONG out_len,
951 BOOLEAN internal, PKEVENT event,
952 PIO_STATUS_BLOCK iosb )
954 PIRP irp;
955 PIO_STACK_LOCATION irpsp;
956 MDL *mdl;
958 TRACE( "%x, %p, %p, %u, %p, %u, %u, %p, %p\n",
959 code, device, in_buff, in_len, out_buff, out_len, internal, event, iosb );
961 if (device == NULL)
962 return NULL;
964 irp = IoAllocateIrp( device->StackSize, FALSE );
965 if (irp == NULL)
966 return NULL;
968 irpsp = IoGetNextIrpStackLocation( irp );
969 irpsp->MajorFunction = internal ? IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
970 irpsp->Parameters.DeviceIoControl.IoControlCode = code;
971 irpsp->Parameters.DeviceIoControl.InputBufferLength = in_len;
972 irpsp->Parameters.DeviceIoControl.OutputBufferLength = out_len;
973 irpsp->DeviceObject = device;
974 irpsp->CompletionRoutine = NULL;
976 switch (code & 3)
978 case METHOD_BUFFERED:
979 irp->AssociatedIrp.SystemBuffer = in_buff;
980 break;
981 case METHOD_IN_DIRECT:
982 case METHOD_OUT_DIRECT:
983 irp->AssociatedIrp.SystemBuffer = in_buff;
985 mdl = IoAllocateMdl( out_buff, out_len, FALSE, FALSE, irp );
986 if (!mdl)
988 IoFreeIrp( irp );
989 return NULL;
992 mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
993 mdl->MappedSystemVa = out_buff;
994 break;
995 case METHOD_NEITHER:
996 irpsp->Parameters.DeviceIoControl.Type3InputBuffer = in_buff;
997 break;
1000 irp->RequestorMode = KernelMode;
1001 irp->UserBuffer = out_buff;
1002 irp->UserIosb = iosb;
1003 irp->UserEvent = event;
1004 return irp;
1008 /**********************************************************
1009 * IoBuildSynchronousFsdRequest (NTOSKRNL.EXE.@)
1011 PIRP WINAPI IoBuildSynchronousFsdRequest(ULONG majorfunc, PDEVICE_OBJECT device,
1012 PVOID buffer, ULONG length, PLARGE_INTEGER startoffset,
1013 PKEVENT event, PIO_STATUS_BLOCK iosb)
1015 PIRP irp;
1016 PIO_STACK_LOCATION irpsp;
1018 TRACE("(%d %p %p %d %p %p %p)\n", majorfunc, device, buffer, length, startoffset, event, iosb);
1020 if (!(irp = IoAllocateIrp( device->StackSize, FALSE ))) return NULL;
1022 irpsp = IoGetNextIrpStackLocation( irp );
1023 irpsp->MajorFunction = majorfunc;
1024 irpsp->DeviceObject = device;
1025 irpsp->CompletionRoutine = NULL;
1027 irp->AssociatedIrp.SystemBuffer = buffer;
1029 if (device->Flags & DO_DIRECT_IO)
1031 MDL *mdl = IoAllocateMdl( buffer, length, FALSE, FALSE, irp );
1032 if (!mdl)
1034 IoFreeIrp( irp );
1035 return NULL;
1038 mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
1039 mdl->MappedSystemVa = buffer;
1042 switch (majorfunc)
1044 case IRP_MJ_READ:
1045 irpsp->Parameters.Read.Length = length;
1046 irpsp->Parameters.Read.ByteOffset = *startoffset;
1047 break;
1048 case IRP_MJ_WRITE:
1049 irpsp->Parameters.Write.Length = length;
1050 irpsp->Parameters.Write.ByteOffset = *startoffset;
1051 break;
1053 irp->RequestorMode = KernelMode;
1054 irp->UserIosb = iosb;
1055 irp->UserEvent = event;
1056 irp->UserBuffer = buffer;
1057 return irp;
1060 static void build_driver_keypath( const WCHAR *name, UNICODE_STRING *keypath )
1062 static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0};
1063 WCHAR *str;
1065 /* Check what prefix is present */
1066 if (strncmpW( name, servicesW, strlenW(servicesW) ) == 0)
1068 FIXME( "Driver name %s is malformed as the keypath\n", debugstr_w(name) );
1069 RtlCreateUnicodeString( keypath, name );
1070 return;
1072 if (strncmpW( name, driverW, strlenW(driverW) ) == 0)
1073 name += strlenW(driverW);
1074 else
1075 FIXME( "Driver name %s does not properly begin with \\Driver\\\n", debugstr_w(name) );
1077 str = HeapAlloc( GetProcessHeap(), 0, sizeof(servicesW) + strlenW(name)*sizeof(WCHAR));
1078 lstrcpyW( str, servicesW );
1079 lstrcatW( str, name );
1080 RtlInitUnicodeString( keypath, str );
1084 static NTSTATUS WINAPI unhandled_irp( DEVICE_OBJECT *device, IRP *irp )
1086 TRACE( "(%p, %p)\n", device, irp );
1087 irp->IoStatus.u.Status = STATUS_INVALID_DEVICE_REQUEST;
1088 IoCompleteRequest( irp, IO_NO_INCREMENT );
1089 return STATUS_INVALID_DEVICE_REQUEST;
1093 /***********************************************************************
1094 * IoCreateDriver (NTOSKRNL.EXE.@)
1096 NTSTATUS WINAPI IoCreateDriver( UNICODE_STRING *name, PDRIVER_INITIALIZE init )
1098 struct wine_driver *driver;
1099 NTSTATUS status;
1100 unsigned int i;
1102 TRACE("(%s, %p)\n", debugstr_us(name), init);
1104 if (!(driver = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
1105 sizeof(*driver) )))
1106 return STATUS_NO_MEMORY;
1108 if ((status = RtlDuplicateUnicodeString( 1, name, &driver->driver_obj.DriverName )))
1110 RtlFreeHeap( GetProcessHeap(), 0, driver );
1111 return status;
1114 driver->driver_obj.Size = sizeof(driver->driver_obj);
1115 driver->driver_obj.DriverInit = init;
1116 driver->driver_obj.DriverExtension = &driver->driver_extension;
1117 driver->driver_extension.DriverObject = &driver->driver_obj;
1118 build_driver_keypath( driver->driver_obj.DriverName.Buffer, &driver->driver_extension.ServiceKeyName );
1119 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1120 driver->driver_obj.MajorFunction[i] = unhandled_irp;
1122 status = driver->driver_obj.DriverInit( &driver->driver_obj, &driver->driver_extension.ServiceKeyName );
1123 if (status)
1125 RtlFreeUnicodeString( &driver->driver_obj.DriverName );
1126 RtlFreeUnicodeString( &driver->driver_extension.ServiceKeyName );
1127 RtlFreeHeap( GetProcessHeap(), 0, driver );
1128 return status;
1131 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1133 if (driver->driver_obj.MajorFunction[i]) continue;
1134 driver->driver_obj.MajorFunction[i] = unhandled_irp;
1137 EnterCriticalSection( &drivers_cs );
1138 if (wine_rb_put( &wine_drivers, &driver->driver_obj.DriverName, &driver->entry ))
1139 ERR( "failed to insert driver %s in tree\n", debugstr_us(name) );
1140 LeaveCriticalSection( &drivers_cs );
1141 return STATUS_SUCCESS;
1145 /***********************************************************************
1146 * IoDeleteDriver (NTOSKRNL.EXE.@)
1148 void WINAPI IoDeleteDriver( DRIVER_OBJECT *driver_object )
1150 TRACE( "(%p)\n", driver_object );
1152 EnterCriticalSection( &drivers_cs );
1153 wine_rb_remove_key( &wine_drivers, &driver_object->DriverName );
1154 LeaveCriticalSection( &drivers_cs );
1156 RtlFreeUnicodeString( &driver_object->DriverName );
1157 RtlFreeUnicodeString( &driver_object->DriverExtension->ServiceKeyName );
1158 RtlFreeHeap( GetProcessHeap(), 0, CONTAINING_RECORD( driver_object, struct wine_driver, driver_obj ) );
1162 /***********************************************************************
1163 * IoCreateDevice (NTOSKRNL.EXE.@)
1165 NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size,
1166 UNICODE_STRING *name, DEVICE_TYPE type,
1167 ULONG characteristics, BOOLEAN exclusive,
1168 DEVICE_OBJECT **ret_device )
1170 NTSTATUS status;
1171 DEVICE_OBJECT *device;
1172 HANDLE handle = 0;
1173 HANDLE manager = get_device_manager();
1175 TRACE( "(%p, %u, %s, %u, %x, %u, %p)\n",
1176 driver, ext_size, debugstr_us(name), type, characteristics, exclusive, ret_device );
1178 if (!(device = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*device) + ext_size )))
1179 return STATUS_NO_MEMORY;
1181 SERVER_START_REQ( create_device )
1183 req->access = 0;
1184 req->attributes = 0;
1185 req->rootdir = 0;
1186 req->manager = wine_server_obj_handle( manager );
1187 req->user_ptr = wine_server_client_ptr( device );
1188 if (name) wine_server_add_data( req, name->Buffer, name->Length );
1189 if (!(status = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle );
1191 SERVER_END_REQ;
1193 if (status == STATUS_SUCCESS)
1195 device->DriverObject = driver;
1196 device->DeviceExtension = device + 1;
1197 device->DeviceType = type;
1198 device->StackSize = 1;
1199 device->Reserved = handle;
1201 device->NextDevice = driver->DeviceObject;
1202 driver->DeviceObject = device;
1204 *ret_device = device;
1206 else HeapFree( GetProcessHeap(), 0, device );
1208 return status;
1212 /***********************************************************************
1213 * IoDeleteDevice (NTOSKRNL.EXE.@)
1215 void WINAPI IoDeleteDevice( DEVICE_OBJECT *device )
1217 NTSTATUS status;
1219 TRACE( "%p\n", device );
1221 SERVER_START_REQ( delete_device )
1223 req->handle = wine_server_obj_handle( device->Reserved );
1224 status = wine_server_call( req );
1226 SERVER_END_REQ;
1228 if (status == STATUS_SUCCESS)
1230 DEVICE_OBJECT **prev = &device->DriverObject->DeviceObject;
1231 while (*prev && *prev != device) prev = &(*prev)->NextDevice;
1232 if (*prev) *prev = (*prev)->NextDevice;
1233 NtClose( device->Reserved );
1234 HeapFree( GetProcessHeap(), 0, device );
1239 /***********************************************************************
1240 * IoCreateSymbolicLink (NTOSKRNL.EXE.@)
1242 NTSTATUS WINAPI IoCreateSymbolicLink( UNICODE_STRING *name, UNICODE_STRING *target )
1244 HANDLE handle;
1245 OBJECT_ATTRIBUTES attr;
1247 attr.Length = sizeof(attr);
1248 attr.RootDirectory = 0;
1249 attr.ObjectName = name;
1250 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1251 attr.SecurityDescriptor = NULL;
1252 attr.SecurityQualityOfService = NULL;
1254 TRACE( "%s -> %s\n", debugstr_us(name), debugstr_us(target) );
1255 /* FIXME: store handle somewhere */
1256 return NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, target );
1260 /***********************************************************************
1261 * IoDeleteSymbolicLink (NTOSKRNL.EXE.@)
1263 NTSTATUS WINAPI IoDeleteSymbolicLink( UNICODE_STRING *name )
1265 HANDLE handle;
1266 OBJECT_ATTRIBUTES attr;
1267 NTSTATUS status;
1269 attr.Length = sizeof(attr);
1270 attr.RootDirectory = 0;
1271 attr.ObjectName = name;
1272 attr.Attributes = OBJ_CASE_INSENSITIVE;
1273 attr.SecurityDescriptor = NULL;
1274 attr.SecurityQualityOfService = NULL;
1276 if (!(status = NtOpenSymbolicLinkObject( &handle, 0, &attr )))
1278 SERVER_START_REQ( unlink_object )
1280 req->handle = wine_server_obj_handle( handle );
1281 status = wine_server_call( req );
1283 SERVER_END_REQ;
1284 NtClose( handle );
1286 return status;
1289 static NTSTATUS create_device_symlink( DEVICE_OBJECT *device, UNICODE_STRING *symlink_name )
1291 UNICODE_STRING device_nameU;
1292 WCHAR *device_name;
1293 ULONG len = 0;
1294 NTSTATUS ret;
1296 ret = IoGetDeviceProperty( device, DevicePropertyPhysicalDeviceObjectName, 0, NULL, &len );
1297 if (ret != STATUS_BUFFER_TOO_SMALL)
1298 return ret;
1300 device_name = heap_alloc( len );
1301 ret = IoGetDeviceProperty( device, DevicePropertyPhysicalDeviceObjectName, len, device_name, &len );
1302 if (ret)
1304 heap_free( device_name );
1305 return ret;
1308 RtlInitUnicodeString( &device_nameU, device_name );
1309 ret = IoCreateSymbolicLink( symlink_name, &device_nameU );
1310 heap_free( device_name );
1311 return ret;
1314 /***********************************************************************
1315 * IoSetDeviceInterfaceState (NTOSKRNL.EXE.@)
1317 NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable )
1319 static const WCHAR DeviceClassesW[] = {'\\','R','E','G','I','S','T','R','Y','\\',
1320 'M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\',
1321 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1322 'C','o','n','t','r','o','l','\\',
1323 'D','e','v','i','c','e','C','l','a','s','s','e','s','\\',0};
1324 static const WCHAR controlW[] = {'C','o','n','t','r','o','l',0};
1325 static const WCHAR linkedW[] = {'L','i','n','k','e','d',0};
1326 static const WCHAR slashW[] = {'\\',0};
1327 static const WCHAR hashW[] = {'#',0};
1329 size_t namelen = name->Length / sizeof(WCHAR);
1330 DEV_BROADCAST_DEVICEINTERFACE_W *broadcast;
1331 struct device_interface *iface;
1332 HANDLE iface_key, control_key;
1333 OBJECT_ATTRIBUTES attr = {0};
1334 struct wine_rb_entry *entry;
1335 WCHAR *path, *refstr, *p;
1336 UNICODE_STRING string;
1337 DWORD data = enable;
1338 NTSTATUS ret;
1339 GUID class;
1340 ULONG len;
1342 TRACE("(%s, %d)\n", debugstr_us(name), enable);
1344 entry = wine_rb_get( &device_interfaces, name );
1345 if (!entry)
1346 return STATUS_OBJECT_NAME_NOT_FOUND;
1348 iface = WINE_RB_ENTRY_VALUE( entry, struct device_interface, entry );
1350 if (!enable && !iface->enabled)
1351 return STATUS_OBJECT_NAME_NOT_FOUND;
1353 if (enable && iface->enabled)
1354 return STATUS_OBJECT_NAME_EXISTS;
1356 refstr = memrchrW(name->Buffer + 4, '\\', namelen - 4);
1358 if (!guid_from_string( (refstr ? refstr : name->Buffer + namelen) - 38, &class ))
1359 return STATUS_INVALID_PARAMETER;
1361 len = strlenW(DeviceClassesW) + 38 + 1 + namelen + 2 + 1;
1363 if (!(path = heap_alloc( len * sizeof(WCHAR) )))
1364 return STATUS_NO_MEMORY;
1366 strcpyW( path, DeviceClassesW );
1367 lstrcpynW( path + strlenW( path ), (refstr ? refstr : name->Buffer + namelen) - 38, 39 );
1368 strcatW( path, slashW );
1369 p = path + strlenW( path );
1370 lstrcpynW( path + strlenW( path ), name->Buffer, (refstr ? (refstr - name->Buffer) : namelen) + 1 );
1371 p[0] = p[1] = p[3] = '#';
1372 strcatW( path, slashW );
1373 strcatW( path, hashW );
1374 if (refstr)
1375 lstrcpynW( path + strlenW( path ), refstr, name->Buffer + namelen - refstr + 1 );
1377 attr.Length = sizeof(attr);
1378 attr.ObjectName = &string;
1379 RtlInitUnicodeString( &string, path );
1380 ret = NtOpenKey( &iface_key, KEY_CREATE_SUB_KEY, &attr );
1381 heap_free(path);
1382 if (ret)
1383 return ret;
1385 attr.RootDirectory = iface_key;
1386 RtlInitUnicodeString( &string, controlW );
1387 ret = NtCreateKey( &control_key, KEY_SET_VALUE, &attr, 0, NULL, 0, NULL );
1388 NtClose( iface_key );
1389 if (ret)
1390 return ret;
1392 RtlInitUnicodeString( &string, linkedW );
1393 ret = NtSetValueKey( control_key, &string, 0, REG_DWORD, &data, sizeof(data) );
1394 if (ret)
1396 NtClose( control_key );
1397 return ret;
1400 if (enable)
1401 ret = create_device_symlink( iface->device, name );
1402 else
1403 ret = IoDeleteSymbolicLink( name );
1404 if (ret)
1406 NtDeleteValueKey( control_key, &string );
1407 NtClose( control_key );
1408 return ret;
1411 iface->enabled = enable;
1413 len = offsetof(DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name[namelen + 1]);
1415 if ((broadcast = heap_alloc( len )))
1417 broadcast->dbcc_size = len;
1418 broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
1419 broadcast->dbcc_classguid = class;
1420 lstrcpynW( broadcast->dbcc_name, name->Buffer, namelen + 1 );
1421 BroadcastSystemMessageW( BSF_FORCEIFHUNG | BSF_QUERY, NULL, WM_DEVICECHANGE,
1422 enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, (LPARAM)broadcast );
1424 heap_free( broadcast );
1426 return ret;
1430 /***********************************************************************
1431 * IoGetDeviceInterfaces (NTOSKRNL.EXE.@)
1433 NTSTATUS WINAPI IoGetDeviceInterfaces( const GUID *InterfaceClassGuid,
1434 PDEVICE_OBJECT PhysicalDeviceObject,
1435 ULONG Flags, PWSTR *SymbolicLinkList )
1437 FIXME( "stub: %s %p %x %p\n", debugstr_guid(InterfaceClassGuid),
1438 PhysicalDeviceObject, Flags, SymbolicLinkList );
1439 return STATUS_NOT_IMPLEMENTED;
1443 /***********************************************************************
1444 * IoGetDeviceObjectPointer (NTOSKRNL.EXE.@)
1446 NTSTATUS WINAPI IoGetDeviceObjectPointer( UNICODE_STRING *name, ACCESS_MASK access, PFILE_OBJECT *file, PDEVICE_OBJECT *device )
1448 static DEVICE_OBJECT stub_device;
1449 static DRIVER_OBJECT stub_driver;
1451 FIXME( "stub: %s %x %p %p\n", debugstr_us(name), access, file, device );
1453 stub_device.StackSize = 0x80; /* minimum value to appease SecuROM 5.x */
1454 stub_device.DriverObject = &stub_driver;
1456 *file = NULL;
1457 *device = &stub_device;
1459 return STATUS_SUCCESS;
1462 /***********************************************************************
1463 * IoGetAttachedDevice (NTOSKRNL.EXE.@)
1465 DEVICE_OBJECT* WINAPI IoGetAttachedDevice( DEVICE_OBJECT *device )
1467 DEVICE_OBJECT *result = device;
1469 TRACE( "(%p)\n", device );
1471 while (result->AttachedDevice)
1472 result = result->AttachedDevice;
1474 return result;
1478 /***********************************************************************
1479 * IoGetDeviceProperty (NTOSKRNL.EXE.@)
1481 NTSTATUS WINAPI IoGetDeviceProperty( DEVICE_OBJECT *device, DEVICE_REGISTRY_PROPERTY device_property,
1482 ULONG buffer_length, PVOID property_buffer, PULONG result_length )
1484 NTSTATUS status = STATUS_NOT_IMPLEMENTED;
1485 TRACE( "%p %d %u %p %p\n", device, device_property, buffer_length,
1486 property_buffer, result_length );
1487 switch (device_property)
1489 case DevicePropertyEnumeratorName:
1491 WCHAR *id, *ptr;
1493 status = get_device_id( device, BusQueryInstanceID, &id );
1494 if (status != STATUS_SUCCESS)
1496 ERR( "Failed to get device id\n" );
1497 break;
1500 struprW( id );
1501 ptr = strchrW( id, '\\' );
1502 if (ptr) *ptr = 0;
1504 *result_length = sizeof(WCHAR) * (strlenW(id) + 1);
1505 if (buffer_length >= *result_length)
1506 memcpy( property_buffer, id, *result_length );
1507 else
1508 status = STATUS_BUFFER_TOO_SMALL;
1510 HeapFree( GetProcessHeap(), 0, id );
1511 break;
1513 case DevicePropertyPhysicalDeviceObjectName:
1515 ULONG used_len, len = buffer_length + sizeof(OBJECT_NAME_INFORMATION);
1516 OBJECT_NAME_INFORMATION *name = HeapAlloc(GetProcessHeap(), 0, len);
1518 status = NtQueryObject(device->Reserved, ObjectNameInformation, name, len, &used_len);
1519 if (status == STATUS_SUCCESS)
1521 /* Ensure room for NULL termination */
1522 if (buffer_length >= name->Name.MaximumLength)
1523 memcpy(property_buffer, name->Name.Buffer, name->Name.MaximumLength);
1524 else
1525 status = STATUS_BUFFER_TOO_SMALL;
1526 *result_length = name->Name.MaximumLength;
1528 else
1530 if (status == STATUS_INFO_LENGTH_MISMATCH ||
1531 status == STATUS_BUFFER_OVERFLOW)
1533 status = STATUS_BUFFER_TOO_SMALL;
1534 *result_length = used_len - sizeof(OBJECT_NAME_INFORMATION);
1536 else
1537 *result_length = 0;
1539 HeapFree(GetProcessHeap(), 0, name);
1540 break;
1542 default:
1543 FIXME("unhandled property %d\n", device_property);
1545 return status;
1549 /***********************************************************************
1550 * IoCallDriver (NTOSKRNL.EXE.@)
1552 NTSTATUS WINAPI IoCallDriver( DEVICE_OBJECT *device, IRP *irp )
1554 PDRIVER_DISPATCH dispatch;
1555 IO_STACK_LOCATION *irpsp;
1556 NTSTATUS status;
1558 --irp->CurrentLocation;
1559 irpsp = --irp->Tail.Overlay.s.u2.CurrentStackLocation;
1560 dispatch = device->DriverObject->MajorFunction[irpsp->MajorFunction];
1562 TRACE_(relay)( "\1Call driver dispatch %p (device=%p,irp=%p)\n", dispatch, device, irp );
1564 status = dispatch( device, irp );
1566 TRACE_(relay)( "\1Ret driver dispatch %p (device=%p,irp=%p) retval=%08x\n",
1567 dispatch, device, irp, status );
1569 return status;
1573 /***********************************************************************
1574 * IofCallDriver (NTOSKRNL.EXE.@)
1576 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1577 DEFINE_FASTCALL2_ENTRYPOINT( IofCallDriver )
1578 NTSTATUS WINAPI DECLSPEC_HIDDEN __regs_IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
1579 #else
1580 NTSTATUS WINAPI IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
1581 #endif
1583 TRACE( "%p %p\n", device, irp );
1584 return IoCallDriver( device, irp );
1588 /***********************************************************************
1589 * IoGetRelatedDeviceObject (NTOSKRNL.EXE.@)
1591 PDEVICE_OBJECT WINAPI IoGetRelatedDeviceObject( PFILE_OBJECT obj )
1593 FIXME( "stub: %p\n", obj );
1594 return NULL;
1597 static CONFIGURATION_INFORMATION configuration_information;
1599 /***********************************************************************
1600 * IoGetConfigurationInformation (NTOSKRNL.EXE.@)
1602 PCONFIGURATION_INFORMATION WINAPI IoGetConfigurationInformation(void)
1604 FIXME( "partial stub\n" );
1605 /* FIXME: return actual devices on system */
1606 return &configuration_information;
1610 /***********************************************************************
1611 * IoIsWdmVersionAvailable (NTOSKRNL.EXE.@)
1613 NTSTATUS WINAPI IoIsWdmVersionAvailable(UCHAR MajorVersion, UCHAR MinorVersion)
1615 DWORD version;
1616 DWORD major;
1617 DWORD minor;
1619 TRACE( "%d, 0x%X\n", MajorVersion, MinorVersion );
1621 version = GetVersion();
1622 major = LOBYTE(version);
1623 minor = HIBYTE(LOWORD(version));
1625 if (MajorVersion == 6 && MinorVersion == 0)
1627 /* Windows Vista, Windows Server 2008, Windows 7 */
1629 else if (MajorVersion == 1)
1631 if (MinorVersion == 0x30)
1633 /* Windows server 2003 */
1634 MajorVersion = 6;
1635 MinorVersion = 0;
1637 else if (MinorVersion == 0x20)
1639 /* Windows XP */
1640 MajorVersion = 5;
1641 MinorVersion = 1;
1643 else if (MinorVersion == 0x10)
1645 /* Windows 2000 */
1646 MajorVersion = 5;
1647 MinorVersion = 0;
1649 else if (MinorVersion == 0x05)
1651 /* Windows ME */
1652 MajorVersion = 4;
1653 MinorVersion = 0x5a;
1655 else if (MinorVersion == 0x00)
1657 /* Windows 98 */
1658 MajorVersion = 4;
1659 MinorVersion = 0x0a;
1661 else
1663 FIXME( "unknown major %d minor 0x%X\n", MajorVersion, MinorVersion );
1664 return FALSE;
1667 else
1669 FIXME( "unknown major %d minor 0x%X\n", MajorVersion, MinorVersion );
1670 return FALSE;
1672 return major > MajorVersion || (major == MajorVersion && minor >= MinorVersion);
1676 /***********************************************************************
1677 * IoQueryDeviceDescription (NTOSKRNL.EXE.@)
1679 NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE itype, PULONG bus, PCONFIGURATION_TYPE ctype,
1680 PULONG cnum, PCONFIGURATION_TYPE ptype, PULONG pnum,
1681 PIO_QUERY_DEVICE_ROUTINE callout, PVOID context)
1683 FIXME( "(%p %p %p %p %p %p %p %p)\n", itype, bus, ctype, cnum, ptype, pnum, callout, context);
1684 return STATUS_NOT_IMPLEMENTED;
1688 static NTSTATUS get_instance_id(DEVICE_OBJECT *device, WCHAR **instance_id)
1690 WCHAR *id, *ptr;
1691 NTSTATUS status;
1693 status = get_device_id( device, BusQueryInstanceID, &id );
1694 if (status != STATUS_SUCCESS) return status;
1696 struprW( id );
1697 for (ptr = id; *ptr; ptr++)if (*ptr == '\\') *ptr = '#';
1699 *instance_id = id;
1700 return STATUS_SUCCESS;
1704 /*****************************************************
1705 * IoRegisterDeviceInterface(NTOSKRNL.EXE.@)
1707 NTSTATUS WINAPI IoRegisterDeviceInterface(DEVICE_OBJECT *device, const GUID *class_guid, UNICODE_STRING *reference_string, UNICODE_STRING *symbolic_link)
1709 WCHAR *instance_id;
1710 NTSTATUS status = STATUS_SUCCESS;
1711 HDEVINFO infoset;
1712 WCHAR *referenceW = NULL;
1713 SP_DEVINFO_DATA devInfo;
1714 SP_DEVICE_INTERFACE_DATA infoData;
1715 SP_DEVICE_INTERFACE_DETAIL_DATA_W *data;
1716 DWORD required;
1717 BOOL rc;
1718 struct device_interface *iface;
1720 TRACE( "(%p, %s, %s, %p)\n", device, debugstr_guid(class_guid), debugstr_us(reference_string), symbolic_link );
1722 if (reference_string != NULL)
1723 referenceW = reference_string->Buffer;
1725 infoset = SetupDiGetClassDevsW( class_guid, referenceW, NULL, DIGCF_DEVICEINTERFACE );
1726 if (infoset == INVALID_HANDLE_VALUE) return STATUS_UNSUCCESSFUL;
1728 status = get_instance_id( device, &instance_id );
1729 if (status != STATUS_SUCCESS) return status;
1731 devInfo.cbSize = sizeof( devInfo );
1732 rc = SetupDiCreateDeviceInfoW( infoset, instance_id, class_guid, NULL, NULL, 0, &devInfo );
1733 if (rc == 0)
1735 if (GetLastError() == ERROR_DEVINST_ALREADY_EXISTS)
1737 DWORD index = 0;
1738 DWORD size = strlenW(instance_id) + 2;
1739 WCHAR *id = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) );
1742 rc = SetupDiEnumDeviceInfo( infoset, index, &devInfo );
1743 if (rc && IsEqualGUID( &devInfo.ClassGuid, class_guid ))
1745 BOOL check;
1746 check = SetupDiGetDeviceInstanceIdW( infoset, &devInfo, id, size, &required );
1747 if (check && strcmpW( id, instance_id ) == 0)
1748 break;
1750 index++;
1751 } while (rc);
1753 HeapFree( GetProcessHeap(), 0, id );
1754 if (!rc)
1756 HeapFree( GetProcessHeap(), 0, instance_id );
1757 return STATUS_UNSUCCESSFUL;
1760 else
1762 HeapFree( GetProcessHeap(), 0, instance_id );
1763 return STATUS_UNSUCCESSFUL;
1766 HeapFree( GetProcessHeap(), 0, instance_id );
1768 infoData.cbSize = sizeof( infoData );
1769 rc = SetupDiCreateDeviceInterfaceW( infoset, &devInfo, class_guid, NULL, 0, &infoData );
1770 if (!rc) return STATUS_UNSUCCESSFUL;
1772 required = 0;
1773 SetupDiGetDeviceInterfaceDetailW( infoset, &infoData, NULL, 0, &required, NULL );
1774 if (required == 0) return STATUS_UNSUCCESSFUL;
1776 data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY , required );
1777 data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
1779 rc = SetupDiGetDeviceInterfaceDetailW( infoset, &infoData, data, required, NULL, NULL );
1780 if (!rc)
1782 HeapFree( GetProcessHeap(), 0, data );
1783 return STATUS_UNSUCCESSFUL;
1786 data->DevicePath[1] = '?';
1787 TRACE( "Device path %s\n",debugstr_w(data->DevicePath) );
1789 iface = heap_alloc_zero( sizeof(struct device_interface) );
1790 iface->device = device;
1791 iface->interface_class = *class_guid;
1792 RtlCreateUnicodeString(&iface->symbolic_link, data->DevicePath);
1793 if (symbolic_link)
1794 RtlCreateUnicodeString( symbolic_link, data->DevicePath);
1796 if (wine_rb_put( &device_interfaces, &iface->symbolic_link, &iface->entry ))
1797 ERR( "failed to insert interface %s into tree\n", debugstr_us(&iface->symbolic_link) );
1799 HeapFree( GetProcessHeap(), 0, data );
1801 return status;
1805 /***********************************************************************
1806 * IoRegisterDriverReinitialization (NTOSKRNL.EXE.@)
1808 void WINAPI IoRegisterDriverReinitialization( PDRIVER_OBJECT obj, PDRIVER_REINITIALIZE reinit, PVOID context )
1810 FIXME( "stub: %p %p %p\n", obj, reinit, context );
1814 /***********************************************************************
1815 * IoRegisterShutdownNotification (NTOSKRNL.EXE.@)
1817 NTSTATUS WINAPI IoRegisterShutdownNotification( PDEVICE_OBJECT obj )
1819 FIXME( "stub: %p\n", obj );
1820 return STATUS_SUCCESS;
1824 /***********************************************************************
1825 * IoUnregisterShutdownNotification (NTOSKRNL.EXE.@)
1827 VOID WINAPI IoUnregisterShutdownNotification( PDEVICE_OBJECT obj )
1829 FIXME( "stub: %p\n", obj );
1833 /***********************************************************************
1834 * IoReportResourceForDetection (NTOSKRNL.EXE.@)
1836 NTSTATUS WINAPI IoReportResourceForDetection( DRIVER_OBJECT *drv_obj, CM_RESOURCE_LIST *drv_list, ULONG drv_size,
1837 DEVICE_OBJECT *dev_obj, CM_RESOURCE_LIST *dev_list, ULONG dev_size,
1838 BOOLEAN *conflict )
1840 FIXME( "(%p, %p, %u, %p, %p, %u, %p): stub\n", drv_obj, drv_list, drv_size,
1841 dev_obj, dev_list, dev_size, conflict );
1843 return STATUS_NOT_IMPLEMENTED;
1847 /***********************************************************************
1848 * IoReportResourceUsage (NTOSKRNL.EXE.@)
1850 NTSTATUS WINAPI IoReportResourceUsage( UNICODE_STRING *name, DRIVER_OBJECT *drv_obj, CM_RESOURCE_LIST *drv_list,
1851 ULONG drv_size, DRIVER_OBJECT *dev_obj, CM_RESOURCE_LIST *dev_list,
1852 ULONG dev_size, BOOLEAN overwrite, BOOLEAN *conflict )
1854 FIXME( "(%s, %p, %p, %u, %p, %p, %u, %d, %p): stub\n", debugstr_us(name),
1855 drv_obj, drv_list, drv_size, dev_obj, dev_list, dev_size, overwrite, conflict );
1857 return STATUS_NOT_IMPLEMENTED;
1861 /***********************************************************************
1862 * IoCompleteRequest (NTOSKRNL.EXE.@)
1864 VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
1866 IO_STACK_LOCATION *irpsp;
1867 PIO_COMPLETION_ROUTINE routine;
1868 NTSTATUS status, stat;
1869 int call_flag = 0;
1871 TRACE( "%p %u\n", irp, priority_boost );
1873 status = irp->IoStatus.u.Status;
1874 while (irp->CurrentLocation <= irp->StackCount)
1876 irpsp = irp->Tail.Overlay.s.u2.CurrentStackLocation;
1877 routine = irpsp->CompletionRoutine;
1878 call_flag = 0;
1879 /* FIXME: add SL_INVOKE_ON_CANCEL support */
1880 if (routine)
1882 if ((irpsp->Control & SL_INVOKE_ON_SUCCESS) && STATUS_SUCCESS == status)
1883 call_flag = 1;
1884 if ((irpsp->Control & SL_INVOKE_ON_ERROR) && STATUS_SUCCESS != status)
1885 call_flag = 1;
1887 ++irp->CurrentLocation;
1888 ++irp->Tail.Overlay.s.u2.CurrentStackLocation;
1889 if (call_flag)
1891 TRACE( "calling %p( %p, %p, %p )\n", routine,
1892 irpsp->DeviceObject, irp, irpsp->Context );
1893 stat = routine( irpsp->DeviceObject, irp, irpsp->Context );
1894 TRACE( "CompletionRoutine returned %x\n", stat );
1895 if (STATUS_MORE_PROCESSING_REQUIRED == stat)
1896 return;
1900 if (irp->Flags & IRP_DEALLOCATE_BUFFER)
1901 HeapFree( GetProcessHeap(), 0, irp->AssociatedIrp.SystemBuffer );
1903 IoFreeIrp( irp );
1907 /***********************************************************************
1908 * IofCompleteRequest (NTOSKRNL.EXE.@)
1910 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1911 DEFINE_FASTCALL2_ENTRYPOINT( IofCompleteRequest )
1912 void WINAPI DECLSPEC_HIDDEN __regs_IofCompleteRequest( IRP *irp, UCHAR priority_boost )
1913 #else
1914 void WINAPI IofCompleteRequest( IRP *irp, UCHAR priority_boost )
1915 #endif
1917 TRACE( "%p %u\n", irp, priority_boost );
1918 IoCompleteRequest( irp, priority_boost );
1922 /***********************************************************************
1923 * InterlockedCompareExchange (NTOSKRNL.EXE.@)
1925 #ifdef DEFINE_FASTCALL3_ENTRYPOINT
1926 DEFINE_FASTCALL3_ENTRYPOINT( NTOSKRNL_InterlockedCompareExchange )
1927 LONG WINAPI DECLSPEC_HIDDEN __regs_NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
1928 #else
1929 LONG WINAPI NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
1930 #endif
1932 return InterlockedCompareExchange( dest, xchg, compare );
1936 /***********************************************************************
1937 * InterlockedDecrement (NTOSKRNL.EXE.@)
1939 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
1940 DEFINE_FASTCALL1_ENTRYPOINT( NTOSKRNL_InterlockedDecrement )
1941 LONG WINAPI DECLSPEC_HIDDEN __regs_NTOSKRNL_InterlockedDecrement( LONG volatile *dest )
1942 #else
1943 LONG WINAPI NTOSKRNL_InterlockedDecrement( LONG volatile *dest )
1944 #endif
1946 return InterlockedDecrement( dest );
1950 /***********************************************************************
1951 * InterlockedExchange (NTOSKRNL.EXE.@)
1953 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1954 DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedExchange )
1955 LONG WINAPI DECLSPEC_HIDDEN __regs_NTOSKRNL_InterlockedExchange( LONG volatile *dest, LONG val )
1956 #else
1957 LONG WINAPI NTOSKRNL_InterlockedExchange( LONG volatile *dest, LONG val )
1958 #endif
1960 return InterlockedExchange( dest, val );
1964 /***********************************************************************
1965 * InterlockedExchangeAdd (NTOSKRNL.EXE.@)
1967 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
1968 DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedExchangeAdd )
1969 LONG WINAPI DECLSPEC_HIDDEN __regs_NTOSKRNL_InterlockedExchangeAdd( LONG volatile *dest, LONG incr )
1970 #else
1971 LONG WINAPI NTOSKRNL_InterlockedExchangeAdd( LONG volatile *dest, LONG incr )
1972 #endif
1974 return InterlockedExchangeAdd( dest, incr );
1978 /***********************************************************************
1979 * InterlockedIncrement (NTOSKRNL.EXE.@)
1981 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
1982 DEFINE_FASTCALL1_ENTRYPOINT( NTOSKRNL_InterlockedIncrement )
1983 LONG WINAPI DECLSPEC_HIDDEN __regs_NTOSKRNL_InterlockedIncrement( LONG volatile *dest )
1984 #else
1985 LONG WINAPI NTOSKRNL_InterlockedIncrement( LONG volatile *dest )
1986 #endif
1988 return InterlockedIncrement( dest );
1992 /***********************************************************************
1993 * ExAllocatePool (NTOSKRNL.EXE.@)
1995 PVOID WINAPI ExAllocatePool( POOL_TYPE type, SIZE_T size )
1997 return ExAllocatePoolWithTag( type, size, 0 );
2001 /***********************************************************************
2002 * ExAllocatePoolWithQuota (NTOSKRNL.EXE.@)
2004 PVOID WINAPI ExAllocatePoolWithQuota( POOL_TYPE type, SIZE_T size )
2006 return ExAllocatePoolWithTag( type, size, 0 );
2010 /***********************************************************************
2011 * ExAllocatePoolWithTag (NTOSKRNL.EXE.@)
2013 PVOID WINAPI ExAllocatePoolWithTag( POOL_TYPE type, SIZE_T size, ULONG tag )
2015 /* FIXME: handle page alignment constraints */
2016 void *ret = HeapAlloc( GetProcessHeap(), 0, size );
2017 TRACE( "%lu pool %u -> %p\n", size, type, ret );
2018 return ret;
2022 /***********************************************************************
2023 * ExAllocatePoolWithQuotaTag (NTOSKRNL.EXE.@)
2025 PVOID WINAPI ExAllocatePoolWithQuotaTag( POOL_TYPE type, SIZE_T size, ULONG tag )
2027 return ExAllocatePoolWithTag( type, size, tag );
2031 /***********************************************************************
2032 * ExCreateCallback (NTOSKRNL.EXE.@)
2034 NTSTATUS WINAPI ExCreateCallback(PCALLBACK_OBJECT *obj, POBJECT_ATTRIBUTES attr,
2035 BOOLEAN create, BOOLEAN allow_multiple)
2037 FIXME("(%p, %p, %u, %u): stub\n", obj, attr, create, allow_multiple);
2039 return STATUS_NOT_IMPLEMENTED;
2043 /***********************************************************************
2044 * ExDeleteNPagedLookasideList (NTOSKRNL.EXE.@)
2046 void WINAPI ExDeleteNPagedLookasideList( PNPAGED_LOOKASIDE_LIST lookaside )
2048 void *entry;
2050 TRACE("(%p)\n", lookaside);
2052 while ((entry = RtlInterlockedPopEntrySList(&lookaside->L.u.ListHead)))
2053 lookaside->L.u5.FreeEx(entry, (LOOKASIDE_LIST_EX*)lookaside);
2057 /***********************************************************************
2058 * ExDeletePagedLookasideList (NTOSKRNL.EXE.@)
2060 void WINAPI ExDeletePagedLookasideList( PPAGED_LOOKASIDE_LIST lookaside )
2062 FIXME("(%p) stub\n", lookaside);
2066 /***********************************************************************
2067 * ExFreePool (NTOSKRNL.EXE.@)
2069 void WINAPI ExFreePool( void *ptr )
2071 ExFreePoolWithTag( ptr, 0 );
2075 /***********************************************************************
2076 * ExFreePoolWithTag (NTOSKRNL.EXE.@)
2078 void WINAPI ExFreePoolWithTag( void *ptr, ULONG tag )
2080 TRACE( "%p\n", ptr );
2081 HeapFree( GetProcessHeap(), 0, ptr );
2085 /***********************************************************************
2086 * ExInitializeResourceLite (NTOSKRNL.EXE.@)
2088 NTSTATUS WINAPI ExInitializeResourceLite(PERESOURCE Resource)
2090 FIXME( "stub: %p\n", Resource );
2091 return STATUS_NOT_IMPLEMENTED;
2095 /***********************************************************************
2096 * ExInitializeNPagedLookasideList (NTOSKRNL.EXE.@)
2098 void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST lookaside,
2099 PALLOCATE_FUNCTION allocate,
2100 PFREE_FUNCTION free,
2101 ULONG flags,
2102 SIZE_T size,
2103 ULONG tag,
2104 USHORT depth)
2106 TRACE( "%p, %p, %p, %u, %lu, %u, %u\n", lookaside, allocate, free, flags, size, tag, depth );
2108 RtlInitializeSListHead( &lookaside->L.u.ListHead );
2109 lookaside->L.Depth = 4;
2110 lookaside->L.MaximumDepth = 256;
2111 lookaside->L.TotalAllocates = 0;
2112 lookaside->L.u2.AllocateMisses = 0;
2113 lookaside->L.TotalFrees = 0;
2114 lookaside->L.u3.FreeMisses = 0;
2115 lookaside->L.Type = NonPagedPool | flags;
2116 lookaside->L.Tag = tag;
2117 lookaside->L.Size = size;
2118 lookaside->L.u4.Allocate = allocate ? allocate : ExAllocatePoolWithTag;
2119 lookaside->L.u5.Free = free ? free : ExFreePool;
2120 lookaside->L.LastTotalAllocates = 0;
2121 lookaside->L.u6.LastAllocateMisses = 0;
2123 /* FIXME: insert in global list of lookadside lists */
2126 /***********************************************************************
2127 * ExInitializePagedLookasideList (NTOSKRNL.EXE.@)
2129 void WINAPI ExInitializePagedLookasideList(PPAGED_LOOKASIDE_LIST Lookaside,
2130 PALLOCATE_FUNCTION Allocate,
2131 PFREE_FUNCTION Free,
2132 ULONG Flags,
2133 SIZE_T Size,
2134 ULONG Tag,
2135 USHORT Depth)
2137 FIXME( "stub: %p, %p, %p, %u, %lu, %u, %u\n", Lookaside, Allocate, Free, Flags, Size, Tag, Depth );
2140 /***********************************************************************
2141 * ExInitializeZone (NTOSKRNL.EXE.@)
2143 NTSTATUS WINAPI ExInitializeZone(PZONE_HEADER Zone,
2144 ULONG BlockSize,
2145 PVOID InitialSegment,
2146 ULONG InitialSegmentSize)
2148 FIXME( "stub: %p, %u, %p, %u\n", Zone, BlockSize, InitialSegment, InitialSegmentSize );
2149 return STATUS_NOT_IMPLEMENTED;
2152 /***********************************************************************
2153 * FsRtlIsNameInExpression (NTOSKRNL.EXE.@)
2155 BOOLEAN WINAPI FsRtlIsNameInExpression(PUNICODE_STRING expression, PUNICODE_STRING name,
2156 BOOLEAN ignore, PWCH upcase)
2158 FIXME("stub: %p %p %d %p\n", expression, name, ignore, upcase);
2159 return FALSE;
2162 /***********************************************************************
2163 * FsRtlRegisterUncProvider (NTOSKRNL.EXE.@)
2165 NTSTATUS WINAPI FsRtlRegisterUncProvider(PHANDLE MupHandle, PUNICODE_STRING RedirDevName,
2166 BOOLEAN MailslotsSupported)
2168 FIXME("(%p %p %d): stub\n", MupHandle, RedirDevName, MailslotsSupported);
2169 return STATUS_NOT_IMPLEMENTED;
2172 /***********************************************************************
2173 * IoGetCurrentProcess / PsGetCurrentProcess (NTOSKRNL.EXE.@)
2175 PEPROCESS WINAPI IoGetCurrentProcess(void)
2177 FIXME("() stub\n");
2178 return NULL;
2181 /***********************************************************************
2182 * KeGetCurrentThread / PsGetCurrentThread (NTOSKRNL.EXE.@)
2184 PRKTHREAD WINAPI KeGetCurrentThread(void)
2186 FIXME("() stub\n");
2187 return NULL;
2190 /***********************************************************************
2191 * KeInsertQueue (NTOSKRNL.EXE.@)
2193 LONG WINAPI KeInsertQueue(PRKQUEUE Queue, PLIST_ENTRY Entry)
2195 FIXME( "stub: %p %p\n", Queue, Entry );
2196 return 0;
2199 /**********************************************************************
2200 * KeQueryActiveProcessors (NTOSKRNL.EXE.@)
2202 * Return the active Processors as bitmask
2204 * RETURNS
2205 * active Processors as bitmask
2208 KAFFINITY WINAPI KeQueryActiveProcessors( void )
2210 DWORD_PTR AffinityMask;
2212 GetProcessAffinityMask( GetCurrentProcess(), &AffinityMask, NULL);
2213 return AffinityMask;
2217 /**********************************************************************
2218 * KeQueryInterruptTime (NTOSKRNL.EXE.@)
2220 * Return the interrupt time count
2223 ULONGLONG WINAPI KeQueryInterruptTime( void )
2225 LARGE_INTEGER totaltime;
2227 KeQueryTickCount(&totaltime);
2228 return totaltime.QuadPart;
2232 /***********************************************************************
2233 * KeQuerySystemTime (NTOSKRNL.EXE.@)
2235 void WINAPI KeQuerySystemTime( LARGE_INTEGER *time )
2237 NtQuerySystemTime( time );
2241 /***********************************************************************
2242 * KeQueryTickCount (NTOSKRNL.EXE.@)
2244 void WINAPI KeQueryTickCount( LARGE_INTEGER *count )
2246 count->QuadPart = NtGetTickCount();
2247 /* update the global variable too */
2248 KeTickCount.LowPart = count->u.LowPart;
2249 KeTickCount.High1Time = count->u.HighPart;
2250 KeTickCount.High2Time = count->u.HighPart;
2254 /***********************************************************************
2255 * KeQueryTimeIncrement (NTOSKRNL.EXE.@)
2257 ULONG WINAPI KeQueryTimeIncrement(void)
2259 return 10000;
2263 /***********************************************************************
2264 * KeSetPriorityThread (NTOSKRNL.EXE.@)
2266 KPRIORITY WINAPI KeSetPriorityThread( PKTHREAD Thread, KPRIORITY Priority )
2268 FIXME("(%p %d)\n", Thread, Priority);
2269 return Priority;
2272 /***********************************************************************
2273 * KeSetSystemAffinityThread (NTOSKRNL.EXE.@)
2275 VOID WINAPI KeSetSystemAffinityThread(KAFFINITY Affinity)
2277 FIXME("(%lx) stub\n", Affinity);
2281 /***********************************************************************
2282 * KeRevertToUserAffinityThread (NTOSKRNL.EXE.@)
2284 void WINAPI KeRevertToUserAffinityThread(void)
2286 FIXME("() stub\n");
2290 /***********************************************************************
2291 * IoRegisterFileSystem (NTOSKRNL.EXE.@)
2293 VOID WINAPI IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject)
2295 FIXME("(%p): stub\n", DeviceObject);
2298 /***********************************************************************
2299 * KeExpandKernelStackAndCalloutEx (NTOSKRNL.EXE.@)
2301 NTSTATUS WINAPI KeExpandKernelStackAndCalloutEx(PEXPAND_STACK_CALLOUT callout, void *parameter, SIZE_T size,
2302 BOOLEAN wait, void *context)
2304 WARN("(%p %p %lu %x %p) semi-stub: ignoring stack expand\n", callout, parameter, size, wait, context);
2305 callout(parameter);
2306 return STATUS_SUCCESS;
2309 /***********************************************************************
2310 * KeExpandKernelStackAndCallout (NTOSKRNL.EXE.@)
2312 NTSTATUS WINAPI KeExpandKernelStackAndCallout(PEXPAND_STACK_CALLOUT callout, void *parameter, SIZE_T size)
2314 return KeExpandKernelStackAndCalloutEx(callout, parameter, size, TRUE, NULL);
2317 /***********************************************************************
2318 * IoUnregisterFileSystem (NTOSKRNL.EXE.@)
2320 VOID WINAPI IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject)
2322 FIXME("(%p): stub\n", DeviceObject);
2325 /***********************************************************************
2326 * MmAllocateNonCachedMemory (NTOSKRNL.EXE.@)
2328 PVOID WINAPI MmAllocateNonCachedMemory( SIZE_T size )
2330 TRACE( "%lu\n", size );
2331 return VirtualAlloc( NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE|PAGE_NOCACHE );
2334 /***********************************************************************
2335 * MmAllocateContiguousMemory (NTOSKRNL.EXE.@)
2337 PVOID WINAPI MmAllocateContiguousMemory( SIZE_T size, PHYSICAL_ADDRESS highest_valid_address )
2339 FIXME( "%lu, %s stub\n", size, wine_dbgstr_longlong(highest_valid_address.QuadPart) );
2340 return NULL;
2343 /***********************************************************************
2344 * MmAllocateContiguousMemorySpecifyCache (NTOSKRNL.EXE.@)
2346 PVOID WINAPI MmAllocateContiguousMemorySpecifyCache( SIZE_T size,
2347 PHYSICAL_ADDRESS lowest_valid_address,
2348 PHYSICAL_ADDRESS highest_valid_address,
2349 PHYSICAL_ADDRESS BoundaryAddressMultiple,
2350 MEMORY_CACHING_TYPE CacheType )
2352 FIXME(": stub\n");
2353 return NULL;
2356 /***********************************************************************
2357 * MmAllocatePagesForMdl (NTOSKRNL.EXE.@)
2359 PMDL WINAPI MmAllocatePagesForMdl(PHYSICAL_ADDRESS lowaddress, PHYSICAL_ADDRESS highaddress,
2360 PHYSICAL_ADDRESS skipbytes, SIZE_T size)
2362 FIXME("%s %s %s %lu: stub\n", wine_dbgstr_longlong(lowaddress.QuadPart), wine_dbgstr_longlong(highaddress.QuadPart),
2363 wine_dbgstr_longlong(skipbytes.QuadPart), size);
2364 return NULL;
2367 /***********************************************************************
2368 * MmCreateSection (NTOSKRNL.EXE.@)
2370 NTSTATUS WINAPI MmCreateSection( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
2371 LARGE_INTEGER *size, ULONG protect, ULONG alloc_attr,
2372 HANDLE file, FILE_OBJECT *file_obj )
2374 FIXME("%p %#x %p %s %#x %#x %p %p: stub\n", handle, access, attr,
2375 wine_dbgstr_longlong(size->QuadPart), protect, alloc_attr, file, file_obj);
2376 return STATUS_NOT_IMPLEMENTED;
2379 /***********************************************************************
2380 * MmFreeNonCachedMemory (NTOSKRNL.EXE.@)
2382 void WINAPI MmFreeNonCachedMemory( void *addr, SIZE_T size )
2384 TRACE( "%p %lu\n", addr, size );
2385 VirtualFree( addr, 0, MEM_RELEASE );
2388 /***********************************************************************
2389 * MmIsAddressValid (NTOSKRNL.EXE.@)
2391 * Check if the process can access the virtual address without a pagefault
2393 * PARAMS
2394 * VirtualAddress [I] Address to check
2396 * RETURNS
2397 * Failure: FALSE
2398 * Success: TRUE (Accessing the Address works without a Pagefault)
2401 BOOLEAN WINAPI MmIsAddressValid(PVOID VirtualAddress)
2403 TRACE("(%p)\n", VirtualAddress);
2404 return !IsBadReadPtr(VirtualAddress, 1);
2407 /***********************************************************************
2408 * MmMapIoSpace (NTOSKRNL.EXE.@)
2410 PVOID WINAPI MmMapIoSpace( PHYSICAL_ADDRESS PhysicalAddress, DWORD NumberOfBytes, DWORD CacheType )
2412 FIXME( "stub: 0x%08x%08x, %d, %d\n", PhysicalAddress.u.HighPart, PhysicalAddress.u.LowPart, NumberOfBytes, CacheType );
2413 return NULL;
2417 /***********************************************************************
2418 * MmLockPagableSectionByHandle (NTOSKRNL.EXE.@)
2420 VOID WINAPI MmLockPagableSectionByHandle(PVOID ImageSectionHandle)
2422 FIXME("stub %p\n", ImageSectionHandle);
2425 /***********************************************************************
2426 * MmMapLockedPagesSpecifyCache (NTOSKRNL.EXE.@)
2428 PVOID WINAPI MmMapLockedPagesSpecifyCache(PMDLX MemoryDescriptorList, KPROCESSOR_MODE AccessMode, MEMORY_CACHING_TYPE CacheType,
2429 PVOID BaseAddress, ULONG BugCheckOnFailure, MM_PAGE_PRIORITY Priority)
2431 FIXME("(%p, %u, %u, %p, %u, %u): stub\n", MemoryDescriptorList, AccessMode, CacheType, BaseAddress, BugCheckOnFailure, Priority);
2433 return NULL;
2436 /***********************************************************************
2437 * MmUnlockPagableImageSection (NTOSKRNL.EXE.@)
2439 VOID WINAPI MmUnlockPagableImageSection(PVOID ImageSectionHandle)
2441 FIXME("stub %p\n", ImageSectionHandle);
2444 /***********************************************************************
2445 * MmPageEntireDriver (NTOSKRNL.EXE.@)
2447 PVOID WINAPI MmPageEntireDriver(PVOID AddrInSection)
2449 TRACE("%p\n", AddrInSection);
2450 return AddrInSection;
2454 /***********************************************************************
2455 * MmProbeAndLockPages (NTOSKRNL.EXE.@)
2457 void WINAPI MmProbeAndLockPages(PMDLX MemoryDescriptorList, KPROCESSOR_MODE AccessMode, LOCK_OPERATION Operation)
2459 FIXME("(%p, %u, %u): stub\n", MemoryDescriptorList, AccessMode, Operation);
2463 /***********************************************************************
2464 * MmResetDriverPaging (NTOSKRNL.EXE.@)
2466 void WINAPI MmResetDriverPaging(PVOID AddrInSection)
2468 TRACE("%p\n", AddrInSection);
2472 /***********************************************************************
2473 * MmUnlockPages (NTOSKRNL.EXE.@)
2475 void WINAPI MmUnlockPages(PMDLX MemoryDescriptorList)
2477 FIXME("(%p): stub\n", MemoryDescriptorList);
2481 /***********************************************************************
2482 * MmUnmapIoSpace (NTOSKRNL.EXE.@)
2484 VOID WINAPI MmUnmapIoSpace( PVOID BaseAddress, SIZE_T NumberOfBytes )
2486 FIXME( "stub: %p, %lu\n", BaseAddress, NumberOfBytes );
2490 /***********************************************************************
2491 * ObReferenceObjectByHandle (NTOSKRNL.EXE.@)
2493 NTSTATUS WINAPI ObReferenceObjectByHandle( HANDLE obj, ACCESS_MASK access,
2494 POBJECT_TYPE type,
2495 KPROCESSOR_MODE mode, PVOID* ptr,
2496 POBJECT_HANDLE_INFORMATION info)
2498 FIXME( "stub: %p %x %p %d %p %p\n", obj, access, type, mode, ptr, info);
2500 if(ptr)
2501 *ptr = UlongToHandle(0xdeadbeaf);
2503 return STATUS_SUCCESS;
2506 /***********************************************************************
2507 * ObReferenceObjectByName (NTOSKRNL.EXE.@)
2509 NTSTATUS WINAPI ObReferenceObjectByName( UNICODE_STRING *ObjectName,
2510 ULONG Attributes,
2511 ACCESS_STATE *AccessState,
2512 ACCESS_MASK DesiredAccess,
2513 POBJECT_TYPE ObjectType,
2514 KPROCESSOR_MODE AccessMode,
2515 void *ParseContext,
2516 void **Object)
2518 struct wine_driver *driver;
2519 struct wine_rb_entry *entry;
2521 TRACE("mostly-stub:%s %i %p %i %p %i %p %p\n", debugstr_us(ObjectName),
2522 Attributes, AccessState, DesiredAccess, ObjectType, AccessMode,
2523 ParseContext, Object);
2525 if (AccessState) FIXME("Unhandled AccessState\n");
2526 if (DesiredAccess) FIXME("Unhandled DesiredAccess\n");
2527 if (ParseContext) FIXME("Unhandled ParseContext\n");
2528 if (ObjectType) FIXME("Unhandled ObjectType\n");
2530 if (AccessMode != KernelMode)
2532 FIXME("UserMode access not implemented\n");
2533 return STATUS_NOT_IMPLEMENTED;
2536 EnterCriticalSection(&drivers_cs);
2537 entry = wine_rb_get(&wine_drivers, ObjectName);
2538 LeaveCriticalSection(&drivers_cs);
2539 if (!entry)
2541 FIXME("Object (%s) not found, may not be tracked.\n", debugstr_us(ObjectName));
2542 return STATUS_NOT_IMPLEMENTED;
2545 driver = WINE_RB_ENTRY_VALUE(entry, struct wine_driver, entry);
2546 *Object = &driver->driver_obj;
2547 return STATUS_SUCCESS;
2551 static void ObReferenceObject( void *obj )
2553 TRACE( "(%p): stub\n", obj );
2557 /***********************************************************************
2558 * ObReferenceObjectByPointer (NTOSKRNL.EXE.@)
2560 NTSTATUS WINAPI ObReferenceObjectByPointer(void *obj, ACCESS_MASK access,
2561 POBJECT_TYPE type,
2562 KPROCESSOR_MODE mode)
2564 FIXME("(%p, %x, %p, %d): stub\n", obj, access, type, mode);
2566 return STATUS_NOT_IMPLEMENTED;
2570 /***********************************************************************
2571 * ObDereferenceObject (NTOSKRNL.EXE.@)
2573 void WINAPI ObDereferenceObject( void *obj )
2575 TRACE( "(%p): stub\n", obj );
2579 /***********************************************************************
2580 * ObfReferenceObject (NTOSKRNL.EXE.@)
2582 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
2583 DEFINE_FASTCALL1_ENTRYPOINT( ObfReferenceObject )
2584 void WINAPI DECLSPEC_HIDDEN __regs_ObfReferenceObject( void *obj )
2585 #else
2586 void WINAPI ObfReferenceObject( void *obj )
2587 #endif
2589 ObReferenceObject( obj );
2593 /***********************************************************************
2594 * ObfDereferenceObject (NTOSKRNL.EXE.@)
2596 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
2597 DEFINE_FASTCALL1_ENTRYPOINT( ObfDereferenceObject )
2598 void WINAPI DECLSPEC_HIDDEN __regs_ObfDereferenceObject( void *obj )
2599 #else
2600 void WINAPI ObfDereferenceObject( void *obj )
2601 #endif
2603 ObDereferenceObject( obj );
2606 /***********************************************************************
2607 * ObRegisterCallbacks (NTOSKRNL.EXE.@)
2609 NTSTATUS WINAPI ObRegisterCallbacks(POB_CALLBACK_REGISTRATION *callBack, void **handle)
2611 FIXME( "stub: %p %p\n", callBack, handle );
2613 if(handle)
2614 *handle = UlongToHandle(0xdeadbeaf);
2616 return STATUS_SUCCESS;
2619 /***********************************************************************
2620 * ObUnRegisterCallbacks (NTOSKRNL.EXE.@)
2622 void WINAPI ObUnRegisterCallbacks(void *handle)
2624 FIXME( "stub: %p\n", handle );
2627 /***********************************************************************
2628 * ObGetFilterVersion (NTOSKRNL.EXE.@)
2630 USHORT WINAPI ObGetFilterVersion(void)
2632 FIXME( "stub:\n" );
2634 return OB_FLT_REGISTRATION_VERSION;
2637 /***********************************************************************
2638 * ObGetObjectType (NTOSKRNL.EXE.@)
2640 POBJECT_TYPE WINAPI ObGetObjectType(void *object)
2642 FIXME("stub: %p\n", object);
2644 return NULL;
2647 /***********************************************************************
2648 * IoGetAttachedDeviceReference (NTOSKRNL.EXE.@)
2650 DEVICE_OBJECT* WINAPI IoGetAttachedDeviceReference( DEVICE_OBJECT *device )
2652 DEVICE_OBJECT *result = IoGetAttachedDevice( device );
2653 ObReferenceObject( result );
2654 return result;
2658 /***********************************************************************
2659 * PsCreateSystemThread (NTOSKRNL.EXE.@)
2661 NTSTATUS WINAPI PsCreateSystemThread(PHANDLE ThreadHandle, ULONG DesiredAccess,
2662 POBJECT_ATTRIBUTES ObjectAttributes,
2663 HANDLE ProcessHandle, PCLIENT_ID ClientId,
2664 PKSTART_ROUTINE StartRoutine, PVOID StartContext)
2666 if (!ProcessHandle) ProcessHandle = GetCurrentProcess();
2667 return RtlCreateUserThread(ProcessHandle, 0, FALSE, 0, 0,
2668 0, StartRoutine, StartContext,
2669 ThreadHandle, ClientId);
2672 /***********************************************************************
2673 * PsGetCurrentProcessId (NTOSKRNL.EXE.@)
2675 HANDLE WINAPI PsGetCurrentProcessId(void)
2677 if (GetCurrentThreadId() == request_thread)
2678 return UlongToHandle(client_pid);
2679 return UlongToHandle(GetCurrentProcessId());
2683 /***********************************************************************
2684 * PsGetCurrentThreadId (NTOSKRNL.EXE.@)
2686 HANDLE WINAPI PsGetCurrentThreadId(void)
2688 if (GetCurrentThreadId() == request_thread)
2689 return UlongToHandle(client_tid);
2690 return UlongToHandle(GetCurrentThreadId());
2694 /***********************************************************************
2695 * PsGetVersion (NTOSKRNL.EXE.@)
2697 BOOLEAN WINAPI PsGetVersion(ULONG *major, ULONG *minor, ULONG *build, UNICODE_STRING *version )
2699 RTL_OSVERSIONINFOEXW info;
2701 info.dwOSVersionInfoSize = sizeof(info);
2702 RtlGetVersion( &info );
2703 if (major) *major = info.dwMajorVersion;
2704 if (minor) *minor = info.dwMinorVersion;
2705 if (build) *build = info.dwBuildNumber;
2707 if (version)
2709 #if 0 /* FIXME: GameGuard passes an uninitialized pointer in version->Buffer */
2710 size_t len = min( strlenW(info.szCSDVersion)*sizeof(WCHAR), version->MaximumLength );
2711 memcpy( version->Buffer, info.szCSDVersion, len );
2712 if (len < version->MaximumLength) version->Buffer[len / sizeof(WCHAR)] = 0;
2713 version->Length = len;
2714 #endif
2716 return TRUE;
2720 /***********************************************************************
2721 * PsImpersonateClient (NTOSKRNL.EXE.@)
2723 NTSTATUS WINAPI PsImpersonateClient(PETHREAD Thread, PACCESS_TOKEN Token, BOOLEAN CopyOnOpen,
2724 BOOLEAN EffectiveOnly, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
2726 FIXME("(%p, %p, %u, %u, %u): stub\n", Thread, Token, CopyOnOpen, EffectiveOnly, ImpersonationLevel);
2728 return STATUS_NOT_IMPLEMENTED;
2732 /***********************************************************************
2733 * PsRevertToSelf (NTOSKRNL.EXE.@)
2735 void WINAPI PsRevertToSelf(void)
2737 FIXME("\n");
2741 /***********************************************************************
2742 * PsSetCreateProcessNotifyRoutine (NTOSKRNL.EXE.@)
2744 NTSTATUS WINAPI PsSetCreateProcessNotifyRoutine( PCREATE_PROCESS_NOTIFY_ROUTINE callback, BOOLEAN remove )
2746 FIXME( "stub: %p %d\n", callback, remove );
2747 return STATUS_SUCCESS;
2751 /***********************************************************************
2752 * PsSetCreateProcessNotifyRoutineEx (NTOSKRNL.EXE.@)
2754 NTSTATUS WINAPI PsSetCreateProcessNotifyRoutineEx( PCREATE_PROCESS_NOTIFY_ROUTINE_EX callback, BOOLEAN remove )
2756 FIXME( "stub: %p %d\n", callback, remove );
2757 return STATUS_SUCCESS;
2761 /***********************************************************************
2762 * PsSetCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
2764 NTSTATUS WINAPI PsSetCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
2766 FIXME( "stub: %p\n", NotifyRoutine );
2767 return STATUS_SUCCESS;
2771 /***********************************************************************
2772 * PsRemoveCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
2774 NTSTATUS WINAPI PsRemoveCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
2776 FIXME( "stub: %p\n", NotifyRoutine );
2777 return STATUS_SUCCESS;
2781 /***********************************************************************
2782 * PsRemoveLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
2784 NTSTATUS WINAPI PsRemoveLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
2786 FIXME( "stub: %p\n", NotifyRoutine );
2787 return STATUS_SUCCESS;
2791 /***********************************************************************
2792 * PsTerminateSystemThread (NTOSKRNL.EXE.@)
2794 NTSTATUS WINAPI PsTerminateSystemThread(NTSTATUS status)
2796 TRACE("status %#x.\n", status);
2797 ExitThread( status );
2801 /***********************************************************************
2802 * MmGetSystemRoutineAddress (NTOSKRNL.EXE.@)
2804 PVOID WINAPI MmGetSystemRoutineAddress(PUNICODE_STRING SystemRoutineName)
2806 HMODULE hMod;
2807 STRING routineNameA;
2808 PVOID pFunc = NULL;
2810 static const WCHAR ntoskrnlW[] = {'n','t','o','s','k','r','n','l','.','e','x','e',0};
2811 static const WCHAR halW[] = {'h','a','l','.','d','l','l',0};
2813 if (!SystemRoutineName) return NULL;
2815 if (RtlUnicodeStringToAnsiString( &routineNameA, SystemRoutineName, TRUE ) == STATUS_SUCCESS)
2817 /* We only support functions exported from ntoskrnl.exe or hal.dll */
2818 hMod = GetModuleHandleW( ntoskrnlW );
2819 pFunc = GetProcAddress( hMod, routineNameA.Buffer );
2820 if (!pFunc)
2822 hMod = GetModuleHandleW( halW );
2823 if (hMod) pFunc = GetProcAddress( hMod, routineNameA.Buffer );
2825 RtlFreeAnsiString( &routineNameA );
2828 if (pFunc)
2829 TRACE( "%s -> %p\n", debugstr_us(SystemRoutineName), pFunc );
2830 else
2831 FIXME( "%s not found\n", debugstr_us(SystemRoutineName) );
2832 return pFunc;
2836 /***********************************************************************
2837 * MmQuerySystemSize (NTOSKRNL.EXE.@)
2839 MM_SYSTEMSIZE WINAPI MmQuerySystemSize(void)
2841 FIXME("stub\n");
2842 return MmLargeSystem;
2845 /***********************************************************************
2846 * KeInitializeDpc (NTOSKRNL.EXE.@)
2848 VOID WINAPI KeInitializeDpc(PRKDPC Dpc, PKDEFERRED_ROUTINE DeferredRoutine, PVOID DeferredContext)
2850 FIXME("stub\n");
2853 /***********************************************************************
2854 * KeSetTargetProcessorDpc (NTOSKRNL.EXE.@)
2856 VOID WINAPI KeSetTargetProcessorDpc(PRKDPC dpc, CCHAR number)
2858 FIXME("%p, %d stub\n", dpc, number);
2861 /***********************************************************************
2862 * READ_REGISTER_BUFFER_UCHAR (NTOSKRNL.EXE.@)
2864 VOID WINAPI READ_REGISTER_BUFFER_UCHAR(PUCHAR Register, PUCHAR Buffer, ULONG Count)
2866 FIXME("stub\n");
2869 /*****************************************************
2870 * PoSetPowerState (NTOSKRNL.EXE.@)
2872 POWER_STATE WINAPI PoSetPowerState(PDEVICE_OBJECT DeviceObject, POWER_STATE_TYPE Type, POWER_STATE State)
2874 FIXME("(%p %u %u) stub\n", DeviceObject, Type, State.DeviceState);
2875 return State;
2878 /*****************************************************
2879 * IoWMIRegistrationControl (NTOSKRNL.EXE.@)
2881 NTSTATUS WINAPI IoWMIRegistrationControl(PDEVICE_OBJECT DeviceObject, ULONG Action)
2883 FIXME("(%p %u) stub\n", DeviceObject, Action);
2884 return STATUS_SUCCESS;
2887 /*****************************************************
2888 * PsSetLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
2890 NTSTATUS WINAPI PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine)
2892 FIXME("(%p) stub\n", routine);
2893 return STATUS_SUCCESS;
2896 /*****************************************************
2897 * PsLookupProcessByProcessId (NTOSKRNL.EXE.@)
2899 NTSTATUS WINAPI PsLookupProcessByProcessId(HANDLE processid, PEPROCESS *process)
2901 static int once;
2902 if (!once++) FIXME("(%p %p) stub\n", processid, process);
2903 return STATUS_NOT_IMPLEMENTED;
2907 /*****************************************************
2908 * IoSetThreadHardErrorMode (NTOSKRNL.EXE.@)
2910 BOOLEAN WINAPI IoSetThreadHardErrorMode(BOOLEAN EnableHardErrors)
2912 FIXME("stub\n");
2913 return FALSE;
2917 /*****************************************************
2918 * IoInitializeRemoveLockEx (NTOSKRNL.EXE.@)
2920 VOID WINAPI IoInitializeRemoveLockEx(PIO_REMOVE_LOCK lock, ULONG tag,
2921 ULONG maxmin, ULONG high, ULONG size)
2923 FIXME("(%p %u %u %u %u) stub\n", lock, tag, maxmin, high, size);
2927 /*****************************************************
2928 * IoAcquireRemoveLockEx (NTOSKRNL.EXE.@)
2931 NTSTATUS WINAPI IoAcquireRemoveLockEx(PIO_REMOVE_LOCK lock, PVOID tag,
2932 LPCSTR file, ULONG line, ULONG lock_size)
2934 FIXME("(%p, %p, %s, %u, %u): stub\n", lock, tag, debugstr_a(file), line, lock_size);
2936 return STATUS_NOT_IMPLEMENTED;
2940 /*****************************************************
2941 * DllMain
2943 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
2945 static void *handler;
2946 LARGE_INTEGER count;
2948 switch(reason)
2950 case DLL_PROCESS_ATTACH:
2951 DisableThreadLibraryCalls( inst );
2952 #if defined(__i386__) || defined(__x86_64__)
2953 handler = RtlAddVectoredExceptionHandler( TRUE, vectored_handler );
2954 #endif
2955 KeQueryTickCount( &count ); /* initialize the global KeTickCount */
2956 NtBuildNumber = NtCurrentTeb()->Peb->OSBuildNumber;
2957 break;
2958 case DLL_PROCESS_DETACH:
2959 if (reserved) break;
2960 RtlRemoveVectoredExceptionHandler( handler );
2961 break;
2963 return TRUE;
2966 /*****************************************************
2967 * Ke386IoSetAccessProcess (NTOSKRNL.EXE.@)
2969 BOOLEAN WINAPI Ke386IoSetAccessProcess(PEPROCESS *process, ULONG flag)
2971 FIXME("(%p %d) stub\n", process, flag);
2972 return FALSE;
2975 /*****************************************************
2976 * Ke386SetIoAccessMap (NTOSKRNL.EXE.@)
2978 BOOLEAN WINAPI Ke386SetIoAccessMap(ULONG flag, PVOID buffer)
2980 FIXME("(%d %p) stub\n", flag, buffer);
2981 return FALSE;
2984 /*****************************************************
2985 * IoCreateSynchronizationEvent (NTOSKRNL.EXE.@)
2987 PKEVENT WINAPI IoCreateSynchronizationEvent(PUNICODE_STRING name, PHANDLE handle)
2989 FIXME("(%p %p) stub\n", name, handle);
2990 return (KEVENT *)0xdeadbeaf;
2993 /*****************************************************
2994 * IoStartNextPacket (NTOSKRNL.EXE.@)
2996 VOID WINAPI IoStartNextPacket(PDEVICE_OBJECT deviceobject, BOOLEAN cancelable)
2998 FIXME("(%p %d) stub\n", deviceobject, cancelable);
3001 /*****************************************************
3002 * ObQueryNameString (NTOSKRNL.EXE.@)
3004 NTSTATUS WINAPI ObQueryNameString(PVOID object, POBJECT_NAME_INFORMATION name, ULONG maxlength, PULONG returnlength)
3006 FIXME("(%p %p %u %p) stub\n", object, name, maxlength, returnlength);
3007 return STATUS_NOT_IMPLEMENTED;
3010 /*****************************************************
3011 * IoRegisterPlugPlayNotification (NTOSKRNL.EXE.@)
3013 NTSTATUS WINAPI IoRegisterPlugPlayNotification(IO_NOTIFICATION_EVENT_CATEGORY category, ULONG flags, PVOID data,
3014 PDRIVER_OBJECT driver, PDRIVER_NOTIFICATION_CALLBACK_ROUTINE callback,
3015 PVOID context, PVOID *notification)
3017 FIXME("(%u %u %p %p %p %p %p) stub\n", category, flags, data, driver, callback, context, notification);
3018 return STATUS_SUCCESS;
3021 /*****************************************************
3022 * IoUnregisterPlugPlayNotification (NTOSKRNL.EXE.@)
3024 NTSTATUS WINAPI IoUnregisterPlugPlayNotification(PVOID notification)
3026 FIXME("stub: %p\n", notification);
3027 return STATUS_SUCCESS;
3030 /*****************************************************
3031 * IoCsqInitialize (NTOSKRNL.EXE.@)
3033 NTSTATUS WINAPI IoCsqInitialize(PIO_CSQ csq, PIO_CSQ_INSERT_IRP insert_irp, PIO_CSQ_REMOVE_IRP remove_irp,
3034 PIO_CSQ_PEEK_NEXT_IRP peek_irp, PIO_CSQ_ACQUIRE_LOCK acquire_lock,
3035 PIO_CSQ_RELEASE_LOCK release_lock, PIO_CSQ_COMPLETE_CANCELED_IRP complete_irp)
3037 FIXME("(%p %p %p %p %p %p %p) stub\n",
3038 csq, insert_irp, remove_irp, peek_irp, acquire_lock, release_lock, complete_irp);
3039 return STATUS_SUCCESS;
3042 /***********************************************************************
3043 * ExAcquireResourceExclusiveLite (NTOSKRNL.EXE.@)
3045 BOOLEAN WINAPI ExAcquireResourceExclusiveLite( PERESOURCE resource, BOOLEAN wait )
3047 FIXME( ":%p %u stub\n", resource, wait );
3048 return TRUE;
3051 /***********************************************************************
3052 * ExDeleteResourceLite (NTOSKRNL.EXE.@)
3054 NTSTATUS WINAPI ExDeleteResourceLite(PERESOURCE resource)
3056 FIXME("(%p): stub\n", resource);
3057 return STATUS_NOT_IMPLEMENTED;
3060 /***********************************************************************
3061 * ExReleaseResourceForThreadLite (NTOSKRNL.EXE.@)
3063 void WINAPI ExReleaseResourceForThreadLite( PERESOURCE resource, ERESOURCE_THREAD tid )
3065 FIXME( "stub: %p %lu\n", resource, tid );
3068 /***********************************************************************
3069 * KeEnterCriticalRegion (NTOSKRNL.EXE.@)
3071 void WINAPI KeEnterCriticalRegion(void)
3073 FIXME(": stub\n");
3076 /***********************************************************************
3077 * KeLeaveCriticalRegion (NTOSKRNL.EXE.@)
3079 void WINAPI KeLeaveCriticalRegion(void)
3081 FIXME(": stub\n");
3084 /***********************************************************************
3085 * ProbeForRead (NTOSKRNL.EXE.@)
3087 void WINAPI ProbeForRead(void *address, SIZE_T length, ULONG alignment)
3089 FIXME("(%p %lu %u) stub\n", address, length, alignment);
3092 /***********************************************************************
3093 * ProbeForWrite (NTOSKRNL.EXE.@)
3095 void WINAPI ProbeForWrite(void *address, SIZE_T length, ULONG alignment)
3097 FIXME("(%p %lu %u) stub\n", address, length, alignment);
3100 /***********************************************************************
3101 * CmRegisterCallback (NTOSKRNL.EXE.@)
3103 NTSTATUS WINAPI CmRegisterCallback(EX_CALLBACK_FUNCTION *function, void *context, LARGE_INTEGER *cookie)
3105 FIXME("(%p %p %p): stub\n", function, context, cookie);
3106 return STATUS_NOT_IMPLEMENTED;
3109 /***********************************************************************
3110 * CmUnRegisterCallback (NTOSKRNL.EXE.@)
3112 NTSTATUS WINAPI CmUnRegisterCallback(LARGE_INTEGER cookie)
3114 FIXME("(%s): stub\n", wine_dbgstr_longlong(cookie.QuadPart));
3115 return STATUS_NOT_IMPLEMENTED;
3118 /***********************************************************************
3119 * IoAttachDevice (NTOSKRNL.EXE.@)
3121 NTSTATUS WINAPI IoAttachDevice(DEVICE_OBJECT *source, UNICODE_STRING *target, DEVICE_OBJECT *attached)
3123 FIXME("(%p, %s, %p): stub\n", source, debugstr_us(target), attached);
3124 return STATUS_NOT_IMPLEMENTED;
3128 static NTSTATUS open_driver( const UNICODE_STRING *service_name, SC_HANDLE *service )
3130 QUERY_SERVICE_CONFIGW *service_config = NULL;
3131 SC_HANDLE manager_handle;
3132 DWORD config_size = 0;
3133 WCHAR *name;
3135 if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, service_name->Length + sizeof(WCHAR) )))
3136 return STATUS_NO_MEMORY;
3138 memcpy( name, service_name->Buffer, service_name->Length );
3139 name[ service_name->Length / sizeof(WCHAR) ] = 0;
3141 if (strncmpW( name, servicesW, strlenW(servicesW) ))
3143 FIXME( "service name %s is not a keypath\n", debugstr_us(service_name) );
3144 RtlFreeHeap( GetProcessHeap(), 0, name );
3145 return STATUS_NOT_IMPLEMENTED;
3148 if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
3150 WARN( "failed to connect to service manager\n" );
3151 RtlFreeHeap( GetProcessHeap(), 0, name );
3152 return STATUS_NOT_SUPPORTED;
3155 *service = OpenServiceW( manager_handle, name + strlenW(servicesW),
3156 SERVICE_QUERY_CONFIG | SERVICE_SET_STATUS );
3157 RtlFreeHeap( GetProcessHeap(), 0, name );
3158 CloseServiceHandle( manager_handle );
3160 if (!*service)
3162 WARN( "failed to open service %s\n", debugstr_us(service_name) );
3163 return STATUS_UNSUCCESSFUL;
3166 QueryServiceConfigW( *service, NULL, 0, &config_size );
3167 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
3169 WARN( "failed to query service config\n" );
3170 goto error;
3173 if (!(service_config = RtlAllocateHeap( GetProcessHeap(), 0, config_size )))
3174 goto error;
3176 if (!QueryServiceConfigW( *service, service_config, config_size, &config_size ))
3178 WARN( "failed to query service config\n" );
3179 goto error;
3182 if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER &&
3183 service_config->dwServiceType != SERVICE_FILE_SYSTEM_DRIVER)
3185 WARN( "service %s is not a kernel driver\n", debugstr_us(service_name) );
3186 goto error;
3189 TRACE( "opened service for driver %s\n", debugstr_us(service_name) );
3190 RtlFreeHeap( GetProcessHeap(), 0, service_config );
3191 return STATUS_SUCCESS;
3193 error:
3194 CloseServiceHandle( *service );
3195 RtlFreeHeap( GetProcessHeap(), 0, service_config );
3196 return STATUS_UNSUCCESSFUL;
3199 /* find the LDR_MODULE corresponding to the driver module */
3200 static LDR_MODULE *find_ldr_module( HMODULE module )
3202 LDR_MODULE *ldr;
3203 ULONG_PTR magic;
3205 LdrLockLoaderLock( 0, NULL, &magic );
3206 if (LdrFindEntryForAddress( module, &ldr ))
3208 WARN( "module not found for %p\n", module );
3209 ldr = NULL;
3211 LdrUnlockLoaderLock( 0, magic );
3213 return ldr;
3216 /* load the driver module file */
3217 static HMODULE load_driver_module( const WCHAR *name )
3219 IMAGE_NT_HEADERS *nt;
3220 const IMAGE_IMPORT_DESCRIPTOR *imports;
3221 SYSTEM_BASIC_INFORMATION info;
3222 int i;
3223 INT_PTR delta;
3224 ULONG size;
3225 HMODULE module = LoadLibraryW( name );
3227 if (!module) return NULL;
3228 nt = RtlImageNtHeader( module );
3230 if (!(delta = (char *)module - (char *)nt->OptionalHeader.ImageBase)) return module;
3232 /* the loader does not apply relocations to non page-aligned binaries or executables,
3233 * we have to do it ourselves */
3235 NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info), NULL );
3236 if (nt->OptionalHeader.SectionAlignment < info.PageSize ||
3237 !(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
3239 DWORD old;
3240 IMAGE_BASE_RELOCATION *rel, *end;
3242 if ((rel = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size )))
3244 TRACE( "%s: relocating from %p to %p\n", wine_dbgstr_w(name), (char *)module - delta, module );
3245 end = (IMAGE_BASE_RELOCATION *)((char *)rel + size);
3246 while (rel < end && rel->SizeOfBlock)
3248 void *page = (char *)module + rel->VirtualAddress;
3249 VirtualProtect( page, info.PageSize, PAGE_EXECUTE_READWRITE, &old );
3250 rel = LdrProcessRelocationBlock( page, (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
3251 (USHORT *)(rel + 1), delta );
3252 if (old != PAGE_EXECUTE_READWRITE) VirtualProtect( page, info.PageSize, old, &old );
3253 if (!rel) goto error;
3255 /* make sure we don't try again */
3256 size = FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + nt->FileHeader.SizeOfOptionalHeader;
3257 VirtualProtect( nt, size, PAGE_READWRITE, &old );
3258 nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
3259 VirtualProtect( nt, size, old, &old );
3263 /* make sure imports are relocated too */
3265 if ((imports = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
3267 for (i = 0; imports[i].Name && imports[i].FirstThunk; i++)
3269 char *name = (char *)module + imports[i].Name;
3270 WCHAR buffer[32], *p = buffer;
3272 while (p < buffer + 32) if (!(*p++ = *name++)) break;
3273 if (p <= buffer + 32) FreeLibrary( load_driver_module( buffer ) );
3277 return module;
3279 error:
3280 FreeLibrary( module );
3281 return NULL;
3284 /* load the .sys module for a device driver */
3285 static HMODULE load_driver( const WCHAR *driver_name, const UNICODE_STRING *keyname )
3287 static const WCHAR driversW[] = {'\\','d','r','i','v','e','r','s','\\',0};
3288 static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t','\\',0};
3289 static const WCHAR postfixW[] = {'.','s','y','s',0};
3290 static const WCHAR ntprefixW[] = {'\\','?','?','\\',0};
3291 static const WCHAR ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
3292 HKEY driver_hkey;
3293 HMODULE module;
3294 LPWSTR path = NULL, str;
3295 DWORD type, size;
3297 if (RegOpenKeyW( HKEY_LOCAL_MACHINE, keyname->Buffer + 18 /* skip \registry\machine */, &driver_hkey ))
3299 ERR( "cannot open key %s, err=%u\n", wine_dbgstr_w(keyname->Buffer), GetLastError() );
3300 return NULL;
3303 /* read the executable path from memory */
3304 size = 0;
3305 if (!RegQueryValueExW( driver_hkey, ImagePathW, NULL, &type, NULL, &size ))
3307 str = HeapAlloc( GetProcessHeap(), 0, size );
3308 if (!RegQueryValueExW( driver_hkey, ImagePathW, NULL, &type, (LPBYTE)str, &size ))
3310 size = ExpandEnvironmentStringsW(str,NULL,0);
3311 path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
3312 ExpandEnvironmentStringsW(str,path,size);
3314 HeapFree( GetProcessHeap(), 0, str );
3315 if (!path)
3317 RegCloseKey( driver_hkey );
3318 return NULL;
3321 if (!strncmpiW( path, systemrootW, 12 ))
3323 WCHAR buffer[MAX_PATH];
3325 GetWindowsDirectoryW(buffer, MAX_PATH);
3327 str = HeapAlloc(GetProcessHeap(), 0, (size -11 + strlenW(buffer))
3328 * sizeof(WCHAR));
3329 lstrcpyW(str, buffer);
3330 lstrcatW(str, path + 11);
3331 HeapFree( GetProcessHeap(), 0, path );
3332 path = str;
3334 else if (!strncmpW( path, ntprefixW, 4 ))
3335 str = path + 4;
3336 else
3337 str = path;
3339 else
3341 /* default is to use the driver name + ".sys" */
3342 WCHAR buffer[MAX_PATH];
3343 GetSystemDirectoryW(buffer, MAX_PATH);
3344 path = HeapAlloc(GetProcessHeap(),0,
3345 (strlenW(buffer) + strlenW(driversW) + strlenW(driver_name) + strlenW(postfixW) + 1)
3346 *sizeof(WCHAR));
3347 lstrcpyW(path, buffer);
3348 lstrcatW(path, driversW);
3349 lstrcatW(path, driver_name);
3350 lstrcatW(path, postfixW);
3351 str = path;
3353 RegCloseKey( driver_hkey );
3355 TRACE( "loading driver %s\n", wine_dbgstr_w(str) );
3357 module = load_driver_module( str );
3358 HeapFree( GetProcessHeap(), 0, path );
3359 return module;
3362 /* call the driver init entry point */
3363 static NTSTATUS WINAPI init_driver( DRIVER_OBJECT *driver_object, UNICODE_STRING *keyname )
3365 unsigned int i;
3366 NTSTATUS status;
3367 const IMAGE_NT_HEADERS *nt;
3368 const WCHAR *driver_name;
3369 HMODULE module;
3371 /* Retrieve driver name from the keyname */
3372 driver_name = strrchrW( keyname->Buffer, '\\' );
3373 driver_name++;
3375 module = load_driver( driver_name, keyname );
3376 if (!module)
3377 return STATUS_DLL_INIT_FAILED;
3379 driver_object->DriverSection = find_ldr_module( module );
3381 nt = RtlImageNtHeader( module );
3382 if (!nt->OptionalHeader.AddressOfEntryPoint) return STATUS_SUCCESS;
3383 driver_object->DriverInit = (PDRIVER_INITIALIZE)((char *)module + nt->OptionalHeader.AddressOfEntryPoint);
3385 TRACE_(relay)( "\1Call driver init %p (obj=%p,str=%s)\n",
3386 driver_object->DriverInit, driver_object, wine_dbgstr_w(keyname->Buffer) );
3388 status = driver_object->DriverInit( driver_object, keyname );
3390 TRACE_(relay)( "\1Ret driver init %p (obj=%p,str=%s) retval=%08x\n",
3391 driver_object->DriverInit, driver_object, wine_dbgstr_w(keyname->Buffer), status );
3393 TRACE( "init done for %s obj %p\n", wine_dbgstr_w(driver_name), driver_object );
3394 TRACE( "- DriverInit = %p\n", driver_object->DriverInit );
3395 TRACE( "- DriverStartIo = %p\n", driver_object->DriverStartIo );
3396 TRACE( "- DriverUnload = %p\n", driver_object->DriverUnload );
3397 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
3398 TRACE( "- MajorFunction[%d] = %p\n", i, driver_object->MajorFunction[i] );
3400 return status;
3403 static BOOLEAN get_drv_name( UNICODE_STRING *drv_name, const UNICODE_STRING *service_name )
3405 static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0};
3406 WCHAR *str;
3408 if (!(str = heap_alloc( sizeof(driverW) + service_name->Length - strlenW(servicesW)*sizeof(WCHAR) )))
3409 return FALSE;
3411 lstrcpyW( str, driverW );
3412 lstrcpynW( str + strlenW(driverW), service_name->Buffer + strlenW(servicesW),
3413 service_name->Length/sizeof(WCHAR) - strlenW(servicesW) + 1 );
3414 RtlInitUnicodeString( drv_name, str );
3415 return TRUE;
3418 /***********************************************************************
3419 * ZwLoadDriver (NTOSKRNL.EXE.@)
3421 NTSTATUS WINAPI ZwLoadDriver( const UNICODE_STRING *service_name )
3423 SERVICE_STATUS_HANDLE service_handle;
3424 struct wine_rb_entry *entry;
3425 struct wine_driver *driver;
3426 UNICODE_STRING drv_name;
3427 NTSTATUS status;
3429 TRACE( "(%s)\n", debugstr_us(service_name) );
3431 if ((status = open_driver( service_name, (SC_HANDLE *)&service_handle )) != STATUS_SUCCESS)
3432 return status;
3434 if (!get_drv_name( &drv_name, service_name ))
3436 CloseServiceHandle( (void *)service_handle );
3437 return STATUS_NO_MEMORY;
3440 if (wine_rb_get( &wine_drivers, &drv_name ))
3442 TRACE( "driver %s already loaded\n", debugstr_us(&drv_name) );
3443 RtlFreeUnicodeString( &drv_name );
3444 CloseServiceHandle( (void *)service_handle );
3445 return STATUS_IMAGE_ALREADY_LOADED;
3448 set_service_status( service_handle, SERVICE_START_PENDING, 0 );
3450 status = IoCreateDriver( &drv_name, init_driver );
3451 entry = wine_rb_get( &wine_drivers, &drv_name );
3452 RtlFreeUnicodeString( &drv_name );
3453 if (status != STATUS_SUCCESS)
3455 ERR( "failed to create driver %s: %08x\n", debugstr_us(service_name), status );
3456 goto error;
3459 driver = WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry );
3460 driver->service_handle = service_handle;
3462 set_service_status( service_handle, SERVICE_RUNNING,
3463 SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN );
3464 return STATUS_SUCCESS;
3466 error:
3467 set_service_status( service_handle, SERVICE_STOPPED, 0 );
3468 CloseServiceHandle( (void *)service_handle );
3469 return status;
3472 /***********************************************************************
3473 * ZwUnloadDriver (NTOSKRNL.EXE.@)
3475 NTSTATUS WINAPI ZwUnloadDriver( const UNICODE_STRING *service_name )
3477 struct wine_rb_entry *entry;
3478 UNICODE_STRING drv_name;
3480 TRACE( "(%s)\n", debugstr_us(service_name) );
3482 if (!get_drv_name( &drv_name, service_name ))
3483 return STATUS_NO_MEMORY;
3485 entry = wine_rb_get( &wine_drivers, &drv_name );
3486 RtlFreeUnicodeString( &drv_name );
3487 if (!entry)
3489 ERR( "failed to locate driver %s\n", debugstr_us(service_name) );
3490 return STATUS_OBJECT_NAME_NOT_FOUND;
3493 unload_driver( entry, NULL );
3495 return STATUS_SUCCESS;
3499 static NTSTATUS WINAPI internal_complete( DEVICE_OBJECT *device, IRP *irp, void *context )
3501 HANDLE event = context;
3502 SetEvent( event );
3503 return STATUS_MORE_PROCESSING_REQUIRED;
3507 static NTSTATUS send_device_irp( DEVICE_OBJECT *device, IRP *irp, ULONG_PTR *info )
3509 NTSTATUS status;
3510 HANDLE event = CreateEventA( NULL, FALSE, FALSE, NULL );
3511 DEVICE_OBJECT *toplevel_device;
3513 irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED;
3514 IoSetCompletionRoutine( irp, internal_complete, event, TRUE, TRUE, TRUE );
3516 toplevel_device = IoGetAttachedDeviceReference( device );
3517 status = IoCallDriver( toplevel_device, irp );
3519 if (status == STATUS_PENDING)
3520 WaitForSingleObject( event, INFINITE );
3522 status = irp->IoStatus.u.Status;
3523 if (info)
3524 *info = irp->IoStatus.Information;
3525 IoCompleteRequest( irp, IO_NO_INCREMENT );
3526 ObDereferenceObject( toplevel_device );
3527 CloseHandle( event );
3528 return status;
3532 static NTSTATUS get_device_id( DEVICE_OBJECT *device, BUS_QUERY_ID_TYPE type, WCHAR **id )
3534 IO_STACK_LOCATION *irpsp;
3535 IO_STATUS_BLOCK irp_status;
3536 IRP *irp;
3538 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, device, NULL, 0, NULL, NULL, &irp_status )))
3539 return STATUS_NO_MEMORY;
3541 irpsp = IoGetNextIrpStackLocation( irp );
3542 irpsp->MinorFunction = IRP_MN_QUERY_ID;
3543 irpsp->Parameters.QueryId.IdType = type;
3545 return send_device_irp( device, irp, (ULONG_PTR *)id );
3549 static BOOL get_driver_for_id( const WCHAR *id, WCHAR *driver )
3551 static const WCHAR serviceW[] = {'S','e','r','v','i','c','e',0};
3552 static const UNICODE_STRING service_str = { sizeof(serviceW) - sizeof(WCHAR), sizeof(serviceW), (WCHAR *)serviceW };
3553 static const WCHAR critical_fmtW[] =
3554 {'\\','R','e','g','i','s','t','r','y',
3555 '\\','M','a','c','h','i','n','e',
3556 '\\','S','y','s','t','e','m',
3557 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
3558 '\\','C','o','n','t','r','o','l',
3559 '\\','C','r','i','t','i','c','a','l','D','e','v','i','c','e','D','a','t','a','b','a','s','e',
3560 '\\','%','s',0};
3561 WCHAR buffer[FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data[MAX_SERVICE_NAME * sizeof(WCHAR)] )];
3562 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
3563 OBJECT_ATTRIBUTES attr;
3564 UNICODE_STRING key;
3565 NTSTATUS status;
3566 HANDLE hkey;
3567 WCHAR *keyW;
3568 DWORD len;
3570 if (!(keyW = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(critical_fmtW) + strlenW(id) * sizeof(WCHAR) )))
3571 return STATUS_NO_MEMORY;
3573 sprintfW( keyW, critical_fmtW, id );
3574 RtlInitUnicodeString( &key, keyW );
3575 InitializeObjectAttributes( &attr, &key, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL );
3577 status = NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr );
3578 RtlFreeUnicodeString( &key );
3579 if (status != STATUS_SUCCESS)
3581 TRACE_(plugplay)( "no driver found for %s\n", debugstr_w(id) );
3582 return FALSE;
3585 status = NtQueryValueKey( hkey, &service_str, KeyValuePartialInformation,
3586 info, sizeof(buffer) - sizeof(WCHAR), &len );
3587 NtClose( hkey );
3588 if (status != STATUS_SUCCESS || info->Type != REG_SZ)
3590 TRACE_(plugplay)( "no driver found for %s\n", debugstr_w(id) );
3591 return FALSE;
3594 memcpy( driver, info->Data, info->DataLength );
3595 driver[ info->DataLength / sizeof(WCHAR) ] = 0;
3596 TRACE_(plugplay)( "found driver %s for %s\n", debugstr_w(driver), debugstr_w(id) );
3597 return TRUE;
3601 static NTSTATUS send_pnp_irp( DEVICE_OBJECT *device, UCHAR minor )
3603 IO_STACK_LOCATION *irpsp;
3604 IO_STATUS_BLOCK irp_status;
3605 IRP *irp;
3607 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, device, NULL, 0, NULL, NULL, &irp_status )))
3608 return STATUS_NO_MEMORY;
3610 irpsp = IoGetNextIrpStackLocation( irp );
3611 irpsp->MinorFunction = minor;
3613 irpsp->Parameters.StartDevice.AllocatedResources = NULL;
3614 irpsp->Parameters.StartDevice.AllocatedResourcesTranslated = NULL;
3616 return send_device_irp( device, irp, NULL );
3620 static NTSTATUS send_power_irp( DEVICE_OBJECT *device, DEVICE_POWER_STATE power )
3622 IO_STATUS_BLOCK irp_status;
3623 IO_STACK_LOCATION *irpsp;
3624 IRP *irp;
3626 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_POWER, device, NULL, 0, NULL, NULL, &irp_status )))
3627 return STATUS_NO_MEMORY;
3629 irpsp = IoGetNextIrpStackLocation( irp );
3630 irpsp->MinorFunction = IRP_MN_SET_POWER;
3632 irpsp->Parameters.Power.Type = DevicePowerState;
3633 irpsp->Parameters.Power.State.DeviceState = power;
3635 return send_device_irp( device, irp, NULL );
3639 static void handle_bus_relations( DEVICE_OBJECT *device )
3641 static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0};
3642 WCHAR buffer[MAX_SERVICE_NAME + ARRAY_SIZE(servicesW)];
3643 WCHAR driver[MAX_SERVICE_NAME] = {0};
3644 DRIVER_OBJECT *driver_obj;
3645 UNICODE_STRING string;
3646 WCHAR *ids, *ptr;
3647 NTSTATUS status;
3649 TRACE_(plugplay)( "(%p)\n", device );
3651 /* We could (should?) do a full IRP_MN_QUERY_DEVICE_RELATIONS query,
3652 * but we don't have to, we have the DEVICE_OBJECT of the new device
3653 * so we can simply handle the process here */
3655 status = get_device_id( device, BusQueryCompatibleIDs, &ids );
3656 if (status != STATUS_SUCCESS || !ids)
3658 ERR_(plugplay)( "Failed to get device IDs\n" );
3659 return;
3662 for (ptr = ids; *ptr; ptr += strlenW(ptr) + 1)
3664 if (get_driver_for_id( ptr, driver ))
3665 break;
3667 RtlFreeHeap( GetProcessHeap(), 0, ids );
3669 if (!driver[0])
3671 ERR_(plugplay)( "No matching driver found for device\n" );
3672 return;
3675 strcpyW( buffer, servicesW );
3676 strcatW( buffer, driver );
3677 RtlInitUnicodeString( &string, buffer );
3678 status = ZwLoadDriver( &string );
3679 if (status != STATUS_SUCCESS && status != STATUS_IMAGE_ALREADY_LOADED)
3681 ERR_(plugplay)( "Failed to load driver %s\n", debugstr_w(driver) );
3682 return;
3685 strcpyW( buffer, driverW );
3686 strcatW( buffer, driver );
3687 RtlInitUnicodeString( &string, buffer );
3688 if (ObReferenceObjectByName( &string, OBJ_CASE_INSENSITIVE, NULL,
3689 0, NULL, KernelMode, NULL, (void **)&driver_obj ) != STATUS_SUCCESS)
3691 ERR_(plugplay)( "Failed to locate loaded driver %s\n", debugstr_w(driver) );
3692 return;
3695 if (driver_obj->DriverExtension->AddDevice)
3696 status = driver_obj->DriverExtension->AddDevice( driver_obj, device );
3697 else
3698 status = STATUS_NOT_IMPLEMENTED;
3700 ObDereferenceObject( driver_obj );
3702 if (status != STATUS_SUCCESS)
3704 ERR_(plugplay)( "AddDevice failed for driver %s\n", debugstr_w(driver) );
3705 return;
3708 send_pnp_irp( device, IRP_MN_START_DEVICE );
3709 send_power_irp( device, PowerDeviceD0 );
3713 static void handle_removal_relations( DEVICE_OBJECT *device )
3715 TRACE_(plugplay)( "(%p)\n", device );
3717 send_power_irp( device, PowerDeviceD3 );
3718 send_pnp_irp( device, IRP_MN_SURPRISE_REMOVAL );
3719 send_pnp_irp( device, IRP_MN_REMOVE_DEVICE );
3723 /***********************************************************************
3724 * IoInvalidateDeviceRelations (NTOSKRNL.EXE.@)
3726 void WINAPI IoInvalidateDeviceRelations( DEVICE_OBJECT *device_object, DEVICE_RELATION_TYPE type )
3728 TRACE( "(%p, %i)\n", device_object, type );
3730 switch (type)
3732 case BusRelations:
3733 handle_bus_relations( device_object );
3734 break;
3735 case RemovalRelations:
3736 handle_removal_relations( device_object );
3737 break;
3738 default:
3739 FIXME( "unhandled relation %i\n", type );
3740 break;
3744 /***********************************************************************
3745 * IoCreateFile (NTOSKRNL.EXE.@)
3747 NTSTATUS WINAPI IoCreateFile(HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
3748 IO_STATUS_BLOCK *io, LARGE_INTEGER *alloc_size, ULONG attributes, ULONG sharing,
3749 ULONG disposition, ULONG create_options, VOID *ea_buffer, ULONG ea_length,
3750 CREATE_FILE_TYPE file_type, VOID *parameters, ULONG options )
3752 FIXME(": stub\n");
3753 return STATUS_NOT_IMPLEMENTED;
3756 /***********************************************************************
3757 * IoCreateNotificationEvent (NTOSKRNL.EXE.@)
3759 PKEVENT WINAPI IoCreateNotificationEvent(UNICODE_STRING *name, HANDLE *handle)
3761 FIXME( "stub: %s %p\n", debugstr_us(name), handle );
3762 return NULL;
3766 /*********************************************************************
3767 * memcpy (NTOSKRNL.@)
3769 * NOTES
3770 * Behaves like memmove.
3772 void * __cdecl NTOSKRNL_memcpy( void *dst, const void *src, size_t n )
3774 return memmove( dst, src, n );
3777 /*********************************************************************
3778 * memset (NTOSKRNL.@)
3780 void * __cdecl NTOSKRNL_memset( void *dst, int c, size_t n )
3782 return memset( dst, c, n );
3785 /*********************************************************************
3786 * _stricmp (NTOSKRNL.@)
3788 int __cdecl NTOSKRNL__stricmp( LPCSTR str1, LPCSTR str2 )
3790 return strcasecmp( str1, str2 );
3793 /*********************************************************************
3794 * _strnicmp (NTOSKRNL.@)
3796 int __cdecl NTOSKRNL__strnicmp( LPCSTR str1, LPCSTR str2, size_t n )
3798 return strncasecmp( str1, str2, n );
3801 /*********************************************************************
3802 * _wcsnicmp (NTOSKRNL.@)
3804 INT __cdecl NTOSKRNL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
3806 return strncmpiW( str1, str2, n );
3809 /*********************************************************************
3810 * wcsncmp (NTOSKRNL.@)
3812 INT __cdecl NTOSKRNL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
3814 return strncmpW( str1, str2, n );
3818 #ifdef __x86_64__
3819 /**************************************************************************
3820 * __chkstk (NTOSKRNL.@)
3822 * Supposed to touch all the stack pages, but we shouldn't need that.
3824 __ASM_GLOBAL_FUNC( __chkstk, "ret" );
3826 #elif defined(__i386__)
3827 /**************************************************************************
3828 * _chkstk (NTOSKRNL.@)
3830 __ASM_STDCALL_FUNC( _chkstk, 0,
3831 "negl %eax\n\t"
3832 "addl %esp,%eax\n\t"
3833 "xchgl %esp,%eax\n\t"
3834 "movl 0(%eax),%eax\n\t" /* copy return address from old location */
3835 "movl %eax,0(%esp)\n\t"
3836 "ret" )
3837 #elif defined(__arm__)
3838 /**************************************************************************
3839 * __chkstk (NTDLL.@)
3841 * Incoming r4 contains words to allocate, converting to bytes then return
3843 __ASM_GLOBAL_FUNC( __chkstk, "lsl r4, r4, #2\n\t"
3844 "bx lr" )
3845 #endif
3847 /*********************************************************************
3848 * PsAcquireProcessExitSynchronization (NTOSKRNL.@)
3850 NTSTATUS WINAPI PsAcquireProcessExitSynchronization(PEPROCESS process)
3852 FIXME("stub: %p\n", process);
3854 return STATUS_NOT_IMPLEMENTED;
3857 /*********************************************************************
3858 * PsReleaseProcessExitSynchronization (NTOSKRNL.@)
3860 void WINAPI PsReleaseProcessExitSynchronization(PEPROCESS process)
3862 FIXME("stub: %p\n", process);
3865 typedef struct _EX_PUSH_LOCK_WAIT_BLOCK *PEX_PUSH_LOCK_WAIT_BLOCK;
3866 /*********************************************************************
3867 * ExfUnblockPushLock (NTOSKRNL.@)
3869 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
3870 DEFINE_FASTCALL2_ENTRYPOINT( ExfUnblockPushLock )
3871 void WINAPI DECLSPEC_HIDDEN __regs_ExfUnblockPushLock( EX_PUSH_LOCK *lock,
3872 PEX_PUSH_LOCK_WAIT_BLOCK block)
3873 #else
3874 void WINAPI ExfUnblockPushLock( EX_PUSH_LOCK *lock, PEX_PUSH_LOCK_WAIT_BLOCK block )
3875 #endif
3877 FIXME( "stub: %p, %p\n", lock, block );
3880 /*********************************************************************
3881 * PsGetProcessId (NTOSKRNL.@)
3883 HANDLE WINAPI PsGetProcessId(PEPROCESS process)
3885 FIXME("stub: %p\n", process);
3887 return 0;
3890 /*********************************************************************
3891 * FsRtlRegisterFileSystemFilterCallbacks (NTOSKRNL.@)
3893 NTSTATUS WINAPI FsRtlRegisterFileSystemFilterCallbacks( DRIVER_OBJECT *object, PFS_FILTER_CALLBACKS callbacks)
3895 FIXME("stub: %p %p\n", object, callbacks);
3896 return STATUS_NOT_IMPLEMENTED;
3899 /*********************************************************************
3900 * SeSinglePrivilegeCheck (NTOSKRNL.@)
3902 BOOLEAN WINAPI SeSinglePrivilegeCheck(LUID privilege, KPROCESSOR_MODE mode)
3904 FIXME("stub: %08x%08x %u\n", privilege.HighPart, privilege.LowPart, mode);
3905 return TRUE;
3908 /*********************************************************************
3909 * KeFlushQueuedDpcs (NTOSKRNL.@)
3911 void WINAPI KeFlushQueuedDpcs(void)
3913 FIXME("stub!\n");
3916 /*********************************************************************
3917 * IoReleaseRemoveLockAndWaitEx (NTOSKRNL.@)
3919 void WINAPI IoReleaseRemoveLockAndWaitEx(PIO_REMOVE_LOCK lock, PVOID tag, ULONG size)
3921 FIXME("stub: %p %p %u\n", lock, tag, size);
3924 /*********************************************************************
3925 * DbgQueryDebugFilterState (NTOSKRNL.@)
3927 NTSTATUS WINAPI DbgQueryDebugFilterState(ULONG component, ULONG level)
3929 FIXME("stub: %d %d\n", component, level);
3930 return STATUS_NOT_IMPLEMENTED;
3933 /*********************************************************************
3934 * ExReleaseResourceLite (NTOSKRNL.@)
3936 void WINAPI ExReleaseResourceLite(PERESOURCE resource)
3938 FIXME("stub: %p\n", resource);
3941 /*********************************************************************
3942 * PsGetProcessWow64Process (NTOSKRNL.@)
3944 PVOID WINAPI PsGetProcessWow64Process(PEPROCESS process)
3946 FIXME("stub: %p\n", process);
3947 return NULL;
3950 /*********************************************************************
3951 * MmCopyVirtualMemory (NTOSKRNL.@)
3953 NTSTATUS WINAPI MmCopyVirtualMemory(PEPROCESS fromprocess, PVOID fromaddress, PEPROCESS toprocess,
3954 PVOID toaddress, SIZE_T bufsize, KPROCESSOR_MODE mode,
3955 PSIZE_T copied)
3957 FIXME("stub: %p %p %p %p %lu %d %p\n", fromprocess, fromaddress, toprocess, toaddress, bufsize, mode, copied);
3958 return STATUS_NOT_IMPLEMENTED;
3961 /*********************************************************************
3962 * KeEnterGuardedRegion (NTOSKRNL.@)
3964 void WINAPI KeEnterGuardedRegion(void)
3966 FIXME("\n");
3969 /*********************************************************************
3970 * KeLeaveGuardedRegion (NTOSKRNL.@)
3972 void WINAPI KeLeaveGuardedRegion(void)
3974 FIXME("\n");