maintainers: Update the Direct3D section.
[wine.git] / dlls / ntoskrnl.exe / ntoskrnl.c
blobf8e1c24bb49ff7d8fd92ee5a97692d4c7cae01ab
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 <assert.h>
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
29 #include "ntoskrnl_private.h"
30 #include "excpt.h"
31 #include "winreg.h"
32 #include "ntsecapi.h"
33 #include "ddk/csq.h"
34 #include "wine/server.h"
35 #include "wine/heap.h"
36 #include "wine/svcctl.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
39 WINE_DECLARE_DEBUG_CHANNEL(relay);
41 BOOLEAN KdDebuggerEnabled = FALSE;
42 ULONG InitSafeBootMode = 0;
43 USHORT NtBuildNumber = 0;
45 extern LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs );
47 KSYSTEM_TIME KeTickCount = { 0, 0, 0 };
49 typedef struct _KSERVICE_TABLE_DESCRIPTOR
51 PULONG_PTR Base;
52 PULONG Count;
53 ULONG Limit;
54 PUCHAR Number;
55 } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
57 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[4] = { { 0 } };
59 #define MAX_SERVICE_NAME 260
61 static TP_POOL *dpc_call_tp;
62 static TP_CALLBACK_ENVIRON dpc_call_tpe;
63 DECLARE_CRITICAL_SECTION(dpc_call_cs);
64 static DWORD dpc_call_tls_index;
66 /* tid of the thread running client request */
67 static DWORD request_thread;
69 /* tid of the client thread */
70 static DWORD client_tid;
72 static HANDLE ntoskrnl_heap;
74 static void *ldr_notify_cookie;
76 static PLOAD_IMAGE_NOTIFY_ROUTINE load_image_notify_routines[8];
77 static unsigned int load_image_notify_routine_count;
79 struct irp_data
81 HANDLE handle;
82 IRP *irp;
83 BOOL async;
84 BOOL complete;
87 static int wine_drivers_rb_compare( const void *key, const struct wine_rb_entry *entry )
89 const struct wine_driver *driver = WINE_RB_ENTRY_VALUE( entry, const struct wine_driver, entry );
90 const UNICODE_STRING *k = key;
92 return RtlCompareUnicodeString( k, &driver->driver_obj.DriverName, TRUE );
95 static struct wine_rb_tree wine_drivers = { wine_drivers_rb_compare };
97 DECLARE_CRITICAL_SECTION(drivers_cs);
99 struct wine_driver *get_driver( const WCHAR *name )
101 static const WCHAR driverW[] = L"\\Driver\\";
102 struct wine_rb_entry *entry;
103 UNICODE_STRING drv_name;
105 drv_name.Length = (wcslen( driverW ) + wcslen( name )) * sizeof(WCHAR);
106 if (!(drv_name.Buffer = malloc( drv_name.Length + sizeof(WCHAR) )))
107 return NULL;
108 wcscpy( drv_name.Buffer, driverW );
109 wcscat( drv_name.Buffer, name );
110 entry = wine_rb_get( &wine_drivers, &drv_name );
111 free( drv_name.Buffer );
113 if (entry) return WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry );
114 return NULL;
117 static HANDLE get_device_manager(void)
119 static HANDLE device_manager;
120 HANDLE handle = 0, ret = device_manager;
122 if (!ret)
124 SERVER_START_REQ( create_device_manager )
126 req->access = SYNCHRONIZE;
127 req->attributes = 0;
128 if (!wine_server_call( req )) handle = wine_server_ptr_handle( reply->handle );
130 SERVER_END_REQ;
132 if (!handle)
134 ERR( "failed to create the device manager\n" );
135 return 0;
137 if (!(ret = InterlockedCompareExchangePointer( &device_manager, handle, 0 )))
138 ret = handle;
139 else
140 NtClose( handle ); /* somebody beat us to it */
142 return ret;
146 struct object_header
148 LONG ref;
149 POBJECT_TYPE type;
152 static void free_kernel_object( void *obj )
154 struct object_header *header = (struct object_header *)obj - 1;
155 HeapFree( GetProcessHeap(), 0, header );
158 void *alloc_kernel_object( POBJECT_TYPE type, HANDLE handle, SIZE_T size, LONG ref )
160 struct object_header *header;
162 if (!(header = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*header) + size)) )
163 return NULL;
165 if (handle)
167 NTSTATUS status;
168 SERVER_START_REQ( set_kernel_object_ptr )
170 req->manager = wine_server_obj_handle( get_device_manager() );
171 req->handle = wine_server_obj_handle( handle );
172 req->user_ptr = wine_server_client_ptr( header + 1 );
173 status = wine_server_call( req );
175 SERVER_END_REQ;
176 if (status) FIXME( "set_object_reference failed: %#lx\n", status );
179 header->ref = ref;
180 header->type = type;
181 return header + 1;
184 DECLARE_CRITICAL_SECTION(obref_cs);
186 /***********************************************************************
187 * ObDereferenceObject (NTOSKRNL.EXE.@)
189 void WINAPI ObDereferenceObject( void *obj )
191 struct object_header *header = (struct object_header*)obj - 1;
192 LONG ref;
194 if (!obj)
196 FIXME("NULL obj\n");
197 return;
200 EnterCriticalSection( &obref_cs );
202 ref = --header->ref;
203 TRACE( "(%p) ref=%lu\n", obj, ref );
204 if (!ref)
206 if (header->type->release)
208 header->type->release( obj );
210 else
212 SERVER_START_REQ( release_kernel_object )
214 req->manager = wine_server_obj_handle( get_device_manager() );
215 req->user_ptr = wine_server_client_ptr( obj );
216 if (wine_server_call( req )) FIXME( "failed to release %p\n", obj );
218 SERVER_END_REQ;
222 LeaveCriticalSection( &obref_cs );
225 void ObReferenceObject( void *obj )
227 struct object_header *header = (struct object_header*)obj - 1;
228 LONG ref;
230 if (!obj)
232 FIXME("NULL obj\n");
233 return;
236 EnterCriticalSection( &obref_cs );
238 ref = ++header->ref;
239 TRACE( "(%p) ref=%lu\n", obj, ref );
240 if (ref == 1)
242 SERVER_START_REQ( grab_kernel_object )
244 req->manager = wine_server_obj_handle( get_device_manager() );
245 req->user_ptr = wine_server_client_ptr( obj );
246 if (wine_server_call( req )) FIXME( "failed to grab %p reference\n", obj );
248 SERVER_END_REQ;
251 LeaveCriticalSection( &obref_cs );
254 /***********************************************************************
255 * ObGetObjectType (NTOSKRNL.EXE.@)
257 POBJECT_TYPE WINAPI ObGetObjectType( void *object )
259 struct object_header *header = (struct object_header *)object - 1;
260 return header->type;
263 static const POBJECT_TYPE *known_types[] =
265 &ExEventObjectType,
266 &ExSemaphoreObjectType,
267 &IoDeviceObjectType,
268 &IoDriverObjectType,
269 &IoFileObjectType,
270 &PsProcessType,
271 &PsThreadType,
272 &SeTokenObjectType
275 DECLARE_CRITICAL_SECTION(handle_map_cs);
277 NTSTATUS kernel_object_from_handle( HANDLE handle, POBJECT_TYPE type, void **ret )
279 void *obj;
280 NTSTATUS status;
282 EnterCriticalSection( &handle_map_cs );
284 SERVER_START_REQ( get_kernel_object_ptr )
286 req->manager = wine_server_obj_handle( get_device_manager() );
287 req->handle = wine_server_obj_handle( handle );
288 status = wine_server_call( req );
289 obj = wine_server_get_ptr( reply->user_ptr );
291 SERVER_END_REQ;
292 if (status)
294 LeaveCriticalSection( &handle_map_cs );
295 return status;
298 if (!obj)
300 char buf[256];
301 OBJECT_TYPE_INFORMATION *type_info = (OBJECT_TYPE_INFORMATION *)buf;
302 ULONG size;
304 status = NtQueryObject( handle, ObjectTypeInformation, buf, sizeof(buf), &size );
305 if (status)
307 LeaveCriticalSection( &handle_map_cs );
308 return status;
310 if (!type)
312 size_t i;
313 for (i = 0; i < ARRAY_SIZE(known_types); i++)
315 type = *known_types[i];
316 if (!RtlCompareUnicodeStrings( type->name, lstrlenW(type->name), type_info->TypeName.Buffer,
317 type_info->TypeName.Length / sizeof(WCHAR), FALSE ))
318 break;
320 if (i == ARRAY_SIZE(known_types))
322 FIXME("Unsupported type %s\n", debugstr_us(&type_info->TypeName));
323 LeaveCriticalSection( &handle_map_cs );
324 return STATUS_INVALID_HANDLE;
327 else if (RtlCompareUnicodeStrings( type->name, lstrlenW(type->name), type_info->TypeName.Buffer,
328 type_info->TypeName.Length / sizeof(WCHAR), FALSE) )
330 LeaveCriticalSection( &handle_map_cs );
331 return STATUS_OBJECT_TYPE_MISMATCH;
334 if (type->constructor)
335 obj = type->constructor( handle );
336 else
338 FIXME( "No constructor for type %s\n", debugstr_w(type->name) );
339 obj = alloc_kernel_object( type, handle, 0, 0 );
341 if (!obj) status = STATUS_NO_MEMORY;
343 else if (type && ObGetObjectType( obj ) != type) status = STATUS_OBJECT_TYPE_MISMATCH;
345 LeaveCriticalSection( &handle_map_cs );
346 if (!status) *ret = obj;
347 return status;
350 /***********************************************************************
351 * ObReferenceObjectByHandle (NTOSKRNL.EXE.@)
353 NTSTATUS WINAPI ObReferenceObjectByHandle( HANDLE handle, ACCESS_MASK access,
354 POBJECT_TYPE type,
355 KPROCESSOR_MODE mode, void **ptr,
356 POBJECT_HANDLE_INFORMATION info )
358 NTSTATUS status;
360 TRACE( "%p %lx %p %d %p %p\n", handle, access, type, mode, ptr, info );
362 if (mode != KernelMode)
364 FIXME("UserMode access not implemented\n");
365 return STATUS_NOT_IMPLEMENTED;
368 status = kernel_object_from_handle( handle, type, ptr );
369 if (!status) ObReferenceObject( *ptr );
370 return status;
373 /***********************************************************************
374 * ObOpenObjectByPointer (NTOSKRNL.EXE.@)
376 NTSTATUS WINAPI ObOpenObjectByPointer( void *obj, ULONG attr, ACCESS_STATE *access_state,
377 ACCESS_MASK access, POBJECT_TYPE type,
378 KPROCESSOR_MODE mode, HANDLE *handle )
380 NTSTATUS status;
382 TRACE( "%p %lx %p %lx %p %d %p\n", obj, attr, access_state, access, type, mode, handle );
384 if (mode != KernelMode)
386 FIXME( "UserMode access not implemented\n" );
387 return STATUS_NOT_IMPLEMENTED;
390 if (attr & ~OBJ_KERNEL_HANDLE) FIXME( "attr %#lx not supported\n", attr );
391 if (access_state) FIXME( "access_state not implemented\n" );
393 if (type && ObGetObjectType( obj ) != type) return STATUS_OBJECT_TYPE_MISMATCH;
395 SERVER_START_REQ( get_kernel_object_handle )
397 req->manager = wine_server_obj_handle( get_device_manager() );
398 req->user_ptr = wine_server_client_ptr( obj );
399 req->access = access;
400 if (!(status = wine_server_call( req )))
401 *handle = wine_server_ptr_handle( reply->handle );
403 SERVER_END_REQ;
404 return status;
408 static void *create_file_object( HANDLE handle );
410 static const WCHAR file_type_name[] = {'F','i','l','e',0};
412 static struct _OBJECT_TYPE file_type = {
413 file_type_name,
414 create_file_object
417 POBJECT_TYPE IoFileObjectType = &file_type;
419 static void *create_file_object( HANDLE handle )
421 FILE_OBJECT *file;
422 if (!(file = alloc_kernel_object( IoFileObjectType, handle, sizeof(*file), 0 ))) return NULL;
423 file->Type = 5; /* MSDN */
424 file->Size = sizeof(*file);
425 return file;
428 DECLARE_CRITICAL_SECTION(irp_completion_cs);
430 static void free_dispatch_irp( struct irp_data *irp_data )
432 IRP *irp = irp_data->irp;
434 if (irp->UserBuffer != irp->AssociatedIrp.SystemBuffer)
436 HeapFree( GetProcessHeap(), 0, irp->UserBuffer );
437 irp->UserBuffer = NULL;
440 free( irp_data );
443 static ULONG get_irp_output_size( IRP *irp )
445 IO_STACK_LOCATION *stack = IoGetNextIrpStackLocation( irp );
447 if (!irp->UserBuffer || (irp->Flags & IRP_WRITE_OPERATION))
448 return 0;
450 /* For IRPs not using buffered I/O, the driver is supposed to have direct
451 * access to the user's output buffer, either via an MDL (direct I/O) or
452 * with the raw user VA (neither). We can't fully support this, but we
453 * should at least copy the entire buffer back to the caller. */
454 switch (stack->MajorFunction)
456 case IRP_MJ_FILE_SYSTEM_CONTROL:
457 case IRP_MJ_DEVICE_CONTROL:
458 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
459 if ((stack->Parameters.DeviceIoControl.IoControlCode & 3) != METHOD_BUFFERED)
460 return stack->Parameters.DeviceIoControl.OutputBufferLength;
461 break;
463 case IRP_MJ_READ:
464 /* FIXME: Handle non-buffered reads. */
465 default:
466 break;
469 if (NT_ERROR(irp->IoStatus.u.Status))
470 return 0;
471 return irp->IoStatus.Information;
474 /* transfer result of IRP back to wineserver */
475 static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp, void *context )
477 struct irp_data *irp_data = context;
478 NTSTATUS status;
479 ULONG out_size;
481 EnterCriticalSection( &irp_completion_cs );
483 irp_data->complete = TRUE;
484 if (!irp_data->async)
486 /* main loop will report completion via get_next_device_request */
487 LeaveCriticalSection( &irp_completion_cs );
488 return STATUS_MORE_PROCESSING_REQUIRED;
491 out_size = get_irp_output_size( irp );
493 SERVER_START_REQ( set_irp_result )
495 req->handle = wine_server_obj_handle( irp_data->handle );
496 req->status = irp->IoStatus.u.Status;
497 req->size = irp->IoStatus.Information;
498 if (out_size) wine_server_add_data( req, irp->UserBuffer, out_size );
499 status = wine_server_call( req );
501 SERVER_END_REQ;
503 free_dispatch_irp( irp_data );
505 LeaveCriticalSection( &irp_completion_cs );
506 return status;
509 struct dispatch_context
511 irp_params_t params;
512 HANDLE handle;
513 struct irp_data *irp_data;
514 ULONG in_size;
515 void *in_buff;
518 static NTSTATUS dispatch_irp( DEVICE_OBJECT *device, IRP *irp, struct dispatch_context *context )
520 struct irp_data *irp_data;
521 LARGE_INTEGER count;
522 NTSTATUS status;
524 if (!(irp_data = malloc( sizeof(*irp_data) )))
525 return STATUS_NO_MEMORY;
526 irp_data->handle = context->handle;
527 irp_data->irp = irp;
528 irp_data->async = FALSE;
529 irp_data->complete = FALSE;
531 IoSetCompletionRoutine( irp, dispatch_irp_completion, irp_data, TRUE, TRUE, TRUE );
532 context->irp_data = irp_data;
533 context->handle = 0;
535 KeQueryTickCount( &count ); /* update the global KeTickCount */
537 device->CurrentIrp = irp;
538 KeEnterCriticalRegion();
539 status = IoCallDriver( device, irp );
540 KeLeaveCriticalRegion();
541 device->CurrentIrp = NULL;
543 if (status != STATUS_PENDING && !irp_data->complete)
544 ERR( "dispatch routine returned %#lx but didn't complete the IRP\n", status );
546 return status;
549 /* process a create request for a given file */
550 static NTSTATUS dispatch_create( struct dispatch_context *context )
552 IRP *irp;
553 IO_STACK_LOCATION *irpsp;
554 FILE_OBJECT *file;
555 DEVICE_OBJECT *device = wine_server_get_ptr( context->params.create.device );
556 HANDLE handle = wine_server_ptr_handle( context->params.create.file );
558 if (!(file = alloc_kernel_object( IoFileObjectType, handle, sizeof(*file), 0 )))
559 return STATUS_NO_MEMORY;
561 TRACE( "device %p -> file %p\n", device, file );
563 file->Type = 5; /* MSDN */
564 file->Size = sizeof(*file);
565 file->DeviceObject = device;
567 device = IoGetAttachedDevice( device );
569 if (!(irp = IoAllocateIrp( device->StackSize, FALSE ))) return STATUS_NO_MEMORY;
571 irpsp = IoGetNextIrpStackLocation( irp );
572 irpsp->MajorFunction = IRP_MJ_CREATE;
573 irpsp->FileObject = file;
574 irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
575 irpsp->Parameters.Create.Options = context->params.create.options;
576 irpsp->Parameters.Create.ShareAccess = context->params.create.sharing;
577 irpsp->Parameters.Create.FileAttributes = 0;
578 irpsp->Parameters.Create.EaLength = 0;
580 irp->Tail.Overlay.OriginalFileObject = file;
581 irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
582 irp->RequestorMode = UserMode;
583 irp->AssociatedIrp.SystemBuffer = NULL;
584 irp->UserBuffer = NULL;
585 irp->UserIosb = NULL;
586 irp->UserEvent = NULL;
588 irp->Flags |= IRP_CREATE_OPERATION;
589 return dispatch_irp( device, irp, context );
592 /* process a close request for a given file */
593 static NTSTATUS dispatch_close( struct dispatch_context *context )
595 IRP *irp;
596 IO_STACK_LOCATION *irpsp;
597 DEVICE_OBJECT *device;
598 FILE_OBJECT *file = wine_server_get_ptr( context->params.close.file );
600 if (!file) return STATUS_INVALID_HANDLE;
602 device = IoGetAttachedDevice( file->DeviceObject );
604 TRACE( "device %p file %p\n", device, file );
606 if (!(irp = IoAllocateIrp( device->StackSize, FALSE )))
608 ObDereferenceObject( file );
609 return STATUS_NO_MEMORY;
612 irpsp = IoGetNextIrpStackLocation( irp );
613 irpsp->MajorFunction = IRP_MJ_CLOSE;
614 irpsp->FileObject = file;
616 irp->Tail.Overlay.OriginalFileObject = file;
617 irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
618 irp->RequestorMode = UserMode;
619 irp->AssociatedIrp.SystemBuffer = NULL;
620 irp->UserBuffer = NULL;
621 irp->UserIosb = NULL;
622 irp->UserEvent = NULL;
624 irp->Flags |= IRP_CLOSE_OPERATION;
625 return dispatch_irp( device, irp, context );
628 /* process a read request for a given device */
629 static NTSTATUS dispatch_read( struct dispatch_context *context )
631 IRP *irp;
632 void *out_buff;
633 LARGE_INTEGER offset;
634 IO_STACK_LOCATION *irpsp;
635 DEVICE_OBJECT *device;
636 FILE_OBJECT *file = wine_server_get_ptr( context->params.read.file );
637 ULONG out_size = context->params.read.out_size;
639 if (!file) return STATUS_INVALID_HANDLE;
641 device = IoGetAttachedDevice( file->DeviceObject );
643 TRACE( "device %p file %p size %lu\n", device, file, out_size );
645 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
647 offset.QuadPart = context->params.read.pos;
649 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, device, out_buff, out_size,
650 &offset, NULL, NULL )))
652 HeapFree( GetProcessHeap(), 0, out_buff );
653 return STATUS_NO_MEMORY;
656 irp->Tail.Overlay.OriginalFileObject = file;
657 irp->RequestorMode = UserMode;
659 irpsp = IoGetNextIrpStackLocation( irp );
660 irpsp->FileObject = file;
661 irpsp->Parameters.Read.Key = context->params.read.key;
663 irp->Flags |= IRP_READ_OPERATION;
664 irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate out_buff */
665 return dispatch_irp( device, irp, context );
668 /* process a write request for a given device */
669 static NTSTATUS dispatch_write( struct dispatch_context *context )
671 IRP *irp;
672 LARGE_INTEGER offset;
673 IO_STACK_LOCATION *irpsp;
674 DEVICE_OBJECT *device;
675 FILE_OBJECT *file = wine_server_get_ptr( context->params.write.file );
677 if (!file) return STATUS_INVALID_HANDLE;
679 device = IoGetAttachedDevice( file->DeviceObject );
681 TRACE( "device %p file %p size %lu\n", device, file, context->in_size );
683 offset.QuadPart = context->params.write.pos;
685 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, device, context->in_buff, context->in_size,
686 &offset, NULL, NULL )))
687 return STATUS_NO_MEMORY;
688 context->in_buff = NULL;
690 irp->Tail.Overlay.OriginalFileObject = file;
691 irp->RequestorMode = UserMode;
693 irpsp = IoGetNextIrpStackLocation( irp );
694 irpsp->FileObject = file;
695 irpsp->Parameters.Write.Key = context->params.write.key;
697 irp->Flags |= IRP_WRITE_OPERATION;
698 irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate in_buff */
699 return dispatch_irp( device, irp, context );
702 /* process a flush request for a given device */
703 static NTSTATUS dispatch_flush( struct dispatch_context *context )
705 IRP *irp;
706 IO_STACK_LOCATION *irpsp;
707 DEVICE_OBJECT *device;
708 FILE_OBJECT *file = wine_server_get_ptr( context->params.flush.file );
710 if (!file) return STATUS_INVALID_HANDLE;
712 device = IoGetAttachedDevice( file->DeviceObject );
714 TRACE( "device %p file %p\n", device, file );
716 if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_FLUSH_BUFFERS, device, NULL, 0,
717 NULL, NULL, NULL )))
718 return STATUS_NO_MEMORY;
720 irp->Tail.Overlay.OriginalFileObject = file;
721 irp->RequestorMode = UserMode;
723 irpsp = IoGetNextIrpStackLocation( irp );
724 irpsp->FileObject = file;
726 return dispatch_irp( device, irp, context );
729 /* process an ioctl request for a given device */
730 static NTSTATUS dispatch_ioctl( struct dispatch_context *context )
732 IO_STACK_LOCATION *irpsp;
733 IRP *irp;
734 void *out_buff = NULL;
735 void *to_free = NULL;
736 DEVICE_OBJECT *device;
737 FILE_OBJECT *file = wine_server_get_ptr( context->params.ioctl.file );
738 ULONG out_size = context->params.ioctl.out_size;
739 NTSTATUS status;
741 if (!file) return STATUS_INVALID_HANDLE;
743 device = IoGetAttachedDevice( file->DeviceObject );
745 TRACE( "ioctl %x device %p file %p in_size %lu out_size %lu\n",
746 context->params.ioctl.code, device, file, context->in_size, out_size );
748 if (out_size)
750 if ((context->params.ioctl.code & 3) != METHOD_BUFFERED)
752 if (context->in_size < out_size) return STATUS_INVALID_DEVICE_REQUEST;
753 context->in_size -= out_size;
754 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
755 memcpy( out_buff, (char *)context->in_buff + context->in_size, out_size );
757 else if (out_size > context->in_size)
759 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
760 memcpy( out_buff, context->in_buff, context->in_size );
761 to_free = context->in_buff;
762 context->in_buff = out_buff;
764 else
765 out_buff = context->in_buff;
768 irp = IoBuildDeviceIoControlRequest( context->params.ioctl.code, device, context->in_buff,
769 context->in_size, out_buff, out_size, FALSE, NULL, NULL );
770 if (!irp)
772 HeapFree( GetProcessHeap(), 0, out_buff );
773 return STATUS_NO_MEMORY;
776 if (out_size && (context->params.ioctl.code & 3) != METHOD_BUFFERED)
777 HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, context->in_buff, context->in_size );
779 irpsp = IoGetNextIrpStackLocation( irp );
780 irpsp->FileObject = file;
782 irp->Tail.Overlay.OriginalFileObject = file;
783 irp->RequestorMode = UserMode;
784 irp->AssociatedIrp.SystemBuffer = context->in_buff;
785 context->in_buff = NULL;
787 irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate in_buff */
788 status = dispatch_irp( device, irp, context );
790 HeapFree( GetProcessHeap(), 0, to_free );
791 return status;
794 /* process a volume information request for a given device */
795 static NTSTATUS dispatch_volume( struct dispatch_context *context )
797 IO_STACK_LOCATION *irpsp;
798 IRP *irp;
799 void *out_buff = NULL;
800 DEVICE_OBJECT *device;
801 FILE_OBJECT *file = wine_server_get_ptr( context->params.volume.file );
802 ULONG out_size = context->params.volume.out_size;
804 if (!file) return STATUS_INVALID_HANDLE;
806 device = IoGetAttachedDevice( file->DeviceObject );
808 TRACE( "class 0x%x device %p file %p in_size %lu out_size %lu\n",
809 context->params.volume.info_class, device, file, context->in_size, out_size );
811 if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
813 irp = IoAllocateIrp( device->StackSize, FALSE );
814 if (!irp)
816 HeapFree( GetProcessHeap(), 0, out_buff );
817 return STATUS_NO_MEMORY;
820 irpsp = IoGetNextIrpStackLocation( irp );
821 irpsp->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
822 irpsp->Parameters.QueryVolume.FsInformationClass = context->params.volume.info_class;
823 irpsp->Parameters.QueryVolume.Length = out_size;
824 irpsp->DeviceObject = NULL;
825 irpsp->CompletionRoutine = NULL;
826 irpsp->FileObject = file;
827 irp->AssociatedIrp.SystemBuffer = out_buff;
828 irp->RequestorMode = KernelMode;
829 irp->UserBuffer = out_buff;
830 irp->UserIosb = NULL;
831 irp->UserEvent = NULL;
832 irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
833 irp->Tail.Overlay.OriginalFileObject = file;
834 irp->RequestorMode = UserMode;
835 context->in_buff = NULL;
837 irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate out_buff */
838 return dispatch_irp( device, irp, context );
841 static NTSTATUS dispatch_free( struct dispatch_context *context )
843 void *obj = wine_server_get_ptr( context->params.free.obj );
844 TRACE( "freeing %p object\n", obj );
845 free_kernel_object( obj );
846 return STATUS_SUCCESS;
849 static NTSTATUS dispatch_cancel( struct dispatch_context *context )
851 IRP *irp = wine_server_get_ptr( context->params.cancel.irp );
853 TRACE( "%p\n", irp );
855 EnterCriticalSection( &irp_completion_cs );
856 IoCancelIrp( irp );
857 LeaveCriticalSection( &irp_completion_cs );
858 return STATUS_SUCCESS;
861 typedef NTSTATUS (*dispatch_func)( struct dispatch_context *context );
863 static const dispatch_func dispatch_funcs[] =
865 NULL, /* IRP_CALL_NONE */
866 dispatch_create, /* IRP_CALL_CREATE */
867 dispatch_close, /* IRP_CALL_CLOSE */
868 dispatch_read, /* IRP_CALL_READ */
869 dispatch_write, /* IRP_CALL_WRITE */
870 dispatch_flush, /* IRP_CALL_FLUSH */
871 dispatch_ioctl, /* IRP_CALL_IOCTL */
872 dispatch_volume, /* IRP_CALL_VOLUME */
873 dispatch_free, /* IRP_CALL_FREE */
874 dispatch_cancel /* IRP_CALL_CANCEL */
877 /* helper function to update service status */
878 static void set_service_status( SERVICE_STATUS_HANDLE handle, DWORD state, DWORD accepted )
880 SERVICE_STATUS status;
881 status.dwServiceType = SERVICE_WIN32;
882 status.dwCurrentState = state;
883 status.dwControlsAccepted = accepted;
884 status.dwWin32ExitCode = 0;
885 status.dwServiceSpecificExitCode = 0;
886 status.dwCheckPoint = 0;
887 status.dwWaitHint = (state == SERVICE_START_PENDING) ? 10000 : 0;
888 SetServiceStatus( handle, &status );
891 static void unload_driver( struct wine_rb_entry *entry, void *context )
893 struct wine_driver *driver = WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry );
894 SERVICE_STATUS_HANDLE service_handle = driver->service_handle;
895 LDR_DATA_TABLE_ENTRY *ldr;
897 if (!service_handle) return; /* not a service */
899 TRACE("%s\n", debugstr_us(&driver->driver_obj.DriverName));
901 if (!driver->driver_obj.DriverUnload)
903 TRACE( "driver %s does not support unloading\n", debugstr_us(&driver->driver_obj.DriverName) );
904 return;
907 ldr = driver->driver_obj.DriverSection;
909 set_service_status( service_handle, SERVICE_STOP_PENDING, 0 );
911 TRACE_(relay)( "\1Call driver unload %p (obj=%p)\n", driver->driver_obj.DriverUnload, &driver->driver_obj );
913 driver->driver_obj.DriverUnload( &driver->driver_obj );
915 TRACE_(relay)( "\1Ret driver unload %p (obj=%p)\n", driver->driver_obj.DriverUnload, &driver->driver_obj );
917 FreeLibrary( ldr->DllBase );
918 IoDeleteDriver( &driver->driver_obj );
920 set_service_status( service_handle, SERVICE_STOPPED, 0 );
921 CloseServiceHandle( (void *)service_handle );
924 PEPROCESS PsInitialSystemProcess = NULL;
926 /***********************************************************************
927 * wine_ntoskrnl_main_loop (Not a Windows API)
929 NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
931 HANDLE manager = get_device_manager();
932 struct dispatch_context context = {.in_size = 4096};
933 NTSTATUS status = STATUS_SUCCESS;
934 struct wine_driver *driver;
935 HANDLE handles[2];
937 /* Set the system process global before setting up the request thread trickery */
938 PsInitialSystemProcess = IoGetCurrentProcess();
939 request_thread = GetCurrentThreadId();
941 pnp_manager_start();
943 handles[0] = stop_event;
944 handles[1] = manager;
946 for (;;)
948 NtCurrentTeb()->Reserved5[1] = NULL;
949 if (!context.in_buff && !(context.in_buff = HeapAlloc( GetProcessHeap(), 0, context.in_size )))
951 ERR( "failed to allocate buffer\n" );
952 status = STATUS_NO_MEMORY;
953 goto done;
956 EnterCriticalSection( &irp_completion_cs );
958 SERVER_START_REQ( get_next_device_request )
960 req->manager = wine_server_obj_handle( manager );
961 req->prev = wine_server_obj_handle( context.handle );
963 if (context.irp_data)
965 IRP *irp = context.irp_data->irp;
967 req->user_ptr = wine_server_client_ptr( irp );
968 req->status = status;
970 if (context.irp_data->complete)
972 /* IRP completed even before we got here; we can report completion now */
973 unsigned int out_size = get_irp_output_size( irp );
975 req->prev = wine_server_obj_handle( context.irp_data->handle );
976 req->pending = irp->PendingReturned;
977 req->iosb_status = irp->IoStatus.u.Status;
978 req->result = irp->IoStatus.Information;
979 if (out_size) wine_server_add_data( req, irp->UserBuffer, out_size );
981 else
983 req->pending = 1;
986 else
988 req->user_ptr = 0;
989 req->status = status;
992 wine_server_set_reply( req, context.in_buff, context.in_size );
993 if (!(status = wine_server_call( req )))
995 context.handle = wine_server_ptr_handle( reply->next );
996 context.params = reply->params;
997 context.in_size = reply->in_size;
998 client_tid = reply->client_tid;
999 NtCurrentTeb()->Reserved5[1] = wine_server_get_ptr( reply->client_thread );
1001 else
1003 context.handle = 0; /* no previous irp */
1004 if (status == STATUS_BUFFER_OVERFLOW)
1005 context.in_size = reply->in_size;
1008 SERVER_END_REQ;
1010 if (context.irp_data)
1012 if (context.irp_data->complete)
1014 IRP *irp = context.irp_data->irp;
1015 free_dispatch_irp( context.irp_data );
1016 IoCompleteRequest( irp, IO_NO_INCREMENT );
1018 else
1020 context.irp_data->async = TRUE;
1024 LeaveCriticalSection( &irp_completion_cs );
1026 context.irp_data = NULL;
1028 switch (status)
1030 case STATUS_SUCCESS:
1031 assert( context.params.type != IRP_CALL_NONE && context.params.type < ARRAY_SIZE(dispatch_funcs) );
1032 status = dispatch_funcs[context.params.type]( &context );
1033 if (!context.in_buff) context.in_size = 4096;
1034 break;
1035 case STATUS_BUFFER_OVERFLOW:
1036 HeapFree( GetProcessHeap(), 0, context.in_buff );
1037 context.in_buff = NULL;
1038 /* restart with larger buffer */
1039 break;
1040 case STATUS_PENDING:
1041 for (;;)
1043 DWORD ret = WaitForMultipleObjectsEx( 2, handles, FALSE, INFINITE, TRUE );
1044 if (ret == WAIT_OBJECT_0)
1046 HeapFree( GetProcessHeap(), 0, context.in_buff );
1047 status = STATUS_SUCCESS;
1048 goto done;
1050 if (ret != WAIT_IO_COMPLETION) break;
1052 break;
1056 done:
1057 /* Native PnP drivers expect that all of their devices will be removed when
1058 * their unload routine is called. Moreover, we cannot unload a module
1059 * until we have removed devices for all lower drivers, so we have to stop
1060 * all devices first, and then unload all drivers. */
1061 WINE_RB_FOR_EACH_ENTRY( driver, &wine_drivers, struct wine_driver, entry )
1062 pnp_manager_stop_driver( driver );
1063 wine_rb_destroy( &wine_drivers, unload_driver, NULL );
1064 pnp_manager_stop();
1065 return status;
1068 /***********************************************************************
1069 * IoAllocateDriverObjectExtension (NTOSKRNL.EXE.@)
1071 NTSTATUS WINAPI IoAllocateDriverObjectExtension( PDRIVER_OBJECT DriverObject,
1072 PVOID ClientIdentificationAddress,
1073 ULONG DriverObjectExtensionSize,
1074 PVOID *DriverObjectExtension )
1076 FIXME( "stub: %p, %p, %lu, %p\n", DriverObject, ClientIdentificationAddress,
1077 DriverObjectExtensionSize, DriverObjectExtension );
1078 return STATUS_NOT_IMPLEMENTED;
1082 /***********************************************************************
1083 * IoGetDriverObjectExtension (NTOSKRNL.EXE.@)
1085 PVOID WINAPI IoGetDriverObjectExtension( PDRIVER_OBJECT DriverObject,
1086 PVOID ClientIdentificationAddress )
1088 FIXME( "stub: %p, %p\n", DriverObject, ClientIdentificationAddress );
1089 return NULL;
1093 /***********************************************************************
1094 * IoInitializeIrp (NTOSKRNL.EXE.@)
1096 void WINAPI IoInitializeIrp( IRP *irp, USHORT size, CCHAR stack_size )
1098 TRACE( "%p, %u, %d\n", irp, size, stack_size );
1100 RtlZeroMemory( irp, size );
1102 irp->Type = IO_TYPE_IRP;
1103 irp->Size = size;
1104 InitializeListHead( &irp->ThreadListEntry );
1105 irp->StackCount = stack_size;
1106 irp->CurrentLocation = stack_size + 1;
1107 irp->Tail.Overlay.s.u2.CurrentStackLocation =
1108 (PIO_STACK_LOCATION)(irp + 1) + stack_size;
1111 void WINAPI IoReuseIrp(IRP *irp, NTSTATUS iostatus)
1113 UCHAR AllocationFlags;
1115 TRACE("irp %p, iostatus %#lx.\n", irp, iostatus);
1117 AllocationFlags = irp->AllocationFlags;
1118 IoInitializeIrp(irp, irp->Size, irp->StackCount);
1119 irp->AllocationFlags = AllocationFlags;
1120 irp->IoStatus.u.Status = iostatus;
1123 /***********************************************************************
1124 * IoInitializeTimer (NTOSKRNL.EXE.@)
1126 NTSTATUS WINAPI IoInitializeTimer(PDEVICE_OBJECT DeviceObject,
1127 PIO_TIMER_ROUTINE TimerRoutine,
1128 PVOID Context)
1130 FIXME( "stub: %p, %p, %p\n", DeviceObject, TimerRoutine, Context );
1131 return STATUS_NOT_IMPLEMENTED;
1135 /***********************************************************************
1136 * IoStartTimer (NTOSKRNL.EXE.@)
1138 void WINAPI IoStartTimer(PDEVICE_OBJECT DeviceObject)
1140 FIXME( "stub: %p\n", DeviceObject );
1144 /***********************************************************************
1145 * IoStopTimer (NTOSKRNL.EXE.@)
1147 void WINAPI IoStopTimer(PDEVICE_OBJECT DeviceObject)
1149 FIXME( "stub: %p\n", DeviceObject );
1153 /***********************************************************************
1154 * IoAllocateIrp (NTOSKRNL.EXE.@)
1156 PIRP WINAPI IoAllocateIrp( CCHAR stack_size, BOOLEAN charge_quota )
1158 SIZE_T size;
1159 PIRP irp;
1160 CCHAR loc_count = stack_size;
1162 TRACE( "%d, %d\n", stack_size, charge_quota );
1164 if (loc_count < 8 && loc_count != 1)
1165 loc_count = 8;
1167 size = sizeof(IRP) + loc_count * sizeof(IO_STACK_LOCATION);
1168 irp = ExAllocatePool( NonPagedPool, size );
1169 if (irp == NULL)
1170 return NULL;
1171 IoInitializeIrp( irp, size, stack_size );
1172 if (stack_size >= 1 && stack_size <= 8)
1173 irp->AllocationFlags = IRP_ALLOCATED_FIXED_SIZE;
1174 if (charge_quota)
1175 irp->AllocationFlags |= IRP_LOOKASIDE_ALLOCATION;
1176 return irp;
1180 /***********************************************************************
1181 * IoFreeIrp (NTOSKRNL.EXE.@)
1183 void WINAPI IoFreeIrp( IRP *irp )
1185 MDL *mdl;
1187 TRACE( "%p\n", irp );
1189 mdl = irp->MdlAddress;
1190 while (mdl)
1192 MDL *next = mdl->Next;
1193 IoFreeMdl( mdl );
1194 mdl = next;
1197 ExFreePool( irp );
1201 /***********************************************************************
1202 * IoAllocateErrorLogEntry (NTOSKRNL.EXE.@)
1204 PVOID WINAPI IoAllocateErrorLogEntry( PVOID IoObject, UCHAR EntrySize )
1206 FIXME( "stub: %p, %u\n", IoObject, EntrySize );
1207 return NULL;
1211 /***********************************************************************
1212 * IoAllocateMdl (NTOSKRNL.EXE.@)
1214 PMDL WINAPI IoAllocateMdl( PVOID va, ULONG length, BOOLEAN secondary, BOOLEAN charge_quota, IRP *irp )
1216 SIZE_T mdl_size;
1217 PMDL mdl;
1219 TRACE("(%p, %lu, %i, %i, %p)\n", va, length, secondary, charge_quota, irp);
1221 if (charge_quota)
1222 FIXME("Charge quota is not yet supported\n");
1224 mdl_size = sizeof(MDL) + sizeof(PFN_NUMBER) * ADDRESS_AND_SIZE_TO_SPAN_PAGES(va, length);
1225 mdl = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, mdl_size );
1226 if (!mdl)
1227 return NULL;
1229 MmInitializeMdl( mdl, va, length );
1231 if (!irp) return mdl;
1233 if (secondary) /* add it at the end */
1235 MDL **pmdl = &irp->MdlAddress;
1236 while (*pmdl) pmdl = &(*pmdl)->Next;
1237 *pmdl = mdl;
1239 else
1241 mdl->Next = irp->MdlAddress;
1242 irp->MdlAddress = mdl;
1244 return mdl;
1248 /***********************************************************************
1249 * IoFreeMdl (NTOSKRNL.EXE.@)
1251 void WINAPI IoFreeMdl(PMDL mdl)
1253 TRACE("%p\n", mdl);
1254 HeapFree(GetProcessHeap(), 0, mdl);
1258 struct _IO_WORKITEM
1260 DEVICE_OBJECT *device;
1261 PIO_WORKITEM_ROUTINE worker;
1262 void *context;
1265 /***********************************************************************
1266 * IoAllocateWorkItem (NTOSKRNL.EXE.@)
1268 PIO_WORKITEM WINAPI IoAllocateWorkItem( PDEVICE_OBJECT device )
1270 PIO_WORKITEM work_item;
1272 TRACE( "%p\n", device );
1274 if (!(work_item = ExAllocatePool( PagedPool, sizeof(*work_item) ))) return NULL;
1275 work_item->device = device;
1276 return work_item;
1280 /***********************************************************************
1281 * IoFreeWorkItem (NTOSKRNL.EXE.@)
1283 void WINAPI IoFreeWorkItem( PIO_WORKITEM work_item )
1285 TRACE( "%p\n", work_item );
1286 ExFreePool( work_item );
1290 static void WINAPI run_work_item_worker(TP_CALLBACK_INSTANCE *instance, void *context)
1292 PIO_WORKITEM work_item = context;
1293 DEVICE_OBJECT *device = work_item->device;
1295 TRACE( "%p: calling %p(%p %p)\n", work_item, work_item->worker, device, work_item->context );
1296 work_item->worker( device, work_item->context );
1297 TRACE( "done\n" );
1299 ObDereferenceObject( device );
1302 /***********************************************************************
1303 * IoQueueWorkItem (NTOSKRNL.EXE.@)
1305 void WINAPI IoQueueWorkItem( PIO_WORKITEM work_item, PIO_WORKITEM_ROUTINE worker,
1306 WORK_QUEUE_TYPE type, void *context )
1308 TRACE( "%p %p %u %p\n", work_item, worker, type, context );
1310 ObReferenceObject( work_item->device );
1311 work_item->worker = worker;
1312 work_item->context = context;
1313 TrySubmitThreadpoolCallback( run_work_item_worker, work_item, NULL );
1316 /***********************************************************************
1317 * IoGetAttachedDevice (NTOSKRNL.EXE.@)
1319 DEVICE_OBJECT* WINAPI IoGetAttachedDevice( DEVICE_OBJECT *device )
1321 DEVICE_OBJECT *result = device;
1323 TRACE( "(%p)\n", device );
1325 while (result->AttachedDevice)
1326 result = result->AttachedDevice;
1328 return result;
1331 void WINAPI IoDetachDevice( DEVICE_OBJECT *device )
1333 device->AttachedDevice = NULL;
1336 /***********************************************************************
1337 * IoAttachDeviceToDeviceStack (NTOSKRNL.EXE.@)
1339 PDEVICE_OBJECT WINAPI IoAttachDeviceToDeviceStack( DEVICE_OBJECT *source,
1340 DEVICE_OBJECT *target )
1342 TRACE( "%p, %p\n", source, target );
1343 target = IoGetAttachedDevice( target );
1344 target->AttachedDevice = source;
1345 source->StackSize = target->StackSize + 1;
1346 return target;
1349 /***********************************************************************
1350 * IoBuildDeviceIoControlRequest (NTOSKRNL.EXE.@)
1352 PIRP WINAPI IoBuildDeviceIoControlRequest( ULONG code, PDEVICE_OBJECT device,
1353 PVOID in_buff, ULONG in_len,
1354 PVOID out_buff, ULONG out_len,
1355 BOOLEAN internal, PKEVENT event,
1356 PIO_STATUS_BLOCK iosb )
1358 PIRP irp;
1359 PIO_STACK_LOCATION irpsp;
1360 MDL *mdl;
1362 TRACE( "%lx, %p, %p, %lu, %p, %lu, %u, %p, %p\n",
1363 code, device, in_buff, in_len, out_buff, out_len, internal, event, iosb );
1365 if (device == NULL)
1366 return NULL;
1368 irp = IoAllocateIrp( device->StackSize, FALSE );
1369 if (irp == NULL)
1370 return NULL;
1372 irpsp = IoGetNextIrpStackLocation( irp );
1373 irpsp->MajorFunction = internal ? IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
1374 irpsp->Parameters.DeviceIoControl.IoControlCode = code;
1375 irpsp->Parameters.DeviceIoControl.InputBufferLength = in_len;
1376 irpsp->Parameters.DeviceIoControl.OutputBufferLength = out_len;
1377 irpsp->DeviceObject = NULL;
1378 irpsp->CompletionRoutine = NULL;
1380 switch (code & 3)
1382 case METHOD_BUFFERED:
1383 irp->AssociatedIrp.SystemBuffer = in_buff;
1384 break;
1385 case METHOD_IN_DIRECT:
1386 case METHOD_OUT_DIRECT:
1387 irp->AssociatedIrp.SystemBuffer = in_buff;
1389 mdl = IoAllocateMdl( out_buff, out_len, FALSE, FALSE, irp );
1390 if (!mdl)
1392 IoFreeIrp( irp );
1393 return NULL;
1396 mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
1397 mdl->MappedSystemVa = out_buff;
1398 break;
1399 case METHOD_NEITHER:
1400 irpsp->Parameters.DeviceIoControl.Type3InputBuffer = in_buff;
1401 break;
1404 irp->RequestorMode = KernelMode;
1405 irp->UserBuffer = out_buff;
1406 irp->UserIosb = iosb;
1407 irp->UserEvent = event;
1408 irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
1409 return irp;
1412 /***********************************************************************
1413 * IoBuildAsynchronousFsdRequest (NTOSKRNL.EXE.@)
1415 PIRP WINAPI IoBuildAsynchronousFsdRequest(ULONG majorfunc, DEVICE_OBJECT *device,
1416 void *buffer, ULONG length, LARGE_INTEGER *startoffset,
1417 IO_STATUS_BLOCK *iosb)
1419 PIRP irp;
1420 PIO_STACK_LOCATION irpsp;
1422 TRACE( "(%ld %p %p %ld %p %p)\n", majorfunc, device, buffer, length, startoffset, iosb );
1424 if (!(irp = IoAllocateIrp( device->StackSize, FALSE ))) return NULL;
1426 irpsp = IoGetNextIrpStackLocation( irp );
1427 irpsp->MajorFunction = majorfunc;
1428 irpsp->DeviceObject = NULL;
1429 irpsp->CompletionRoutine = NULL;
1431 irp->AssociatedIrp.SystemBuffer = buffer;
1433 if (device->Flags & DO_DIRECT_IO)
1435 MDL *mdl = IoAllocateMdl( buffer, length, FALSE, FALSE, irp );
1436 if (!mdl)
1438 IoFreeIrp( irp );
1439 return NULL;
1442 mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
1443 mdl->MappedSystemVa = buffer;
1446 switch (majorfunc)
1448 case IRP_MJ_READ:
1449 irpsp->Parameters.Read.Length = length;
1450 irpsp->Parameters.Read.ByteOffset.QuadPart = startoffset ? startoffset->QuadPart : 0;
1451 break;
1452 case IRP_MJ_WRITE:
1453 irpsp->Parameters.Write.Length = length;
1454 irpsp->Parameters.Write.ByteOffset.QuadPart = startoffset ? startoffset->QuadPart : 0;
1455 break;
1457 irp->RequestorMode = KernelMode;
1458 irp->UserIosb = iosb;
1459 irp->UserEvent = NULL;
1460 irp->UserBuffer = buffer;
1461 irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
1462 return irp;
1467 /***********************************************************************
1468 * IoBuildSynchronousFsdRequest (NTOSKRNL.EXE.@)
1470 PIRP WINAPI IoBuildSynchronousFsdRequest(ULONG majorfunc, PDEVICE_OBJECT device,
1471 PVOID buffer, ULONG length, PLARGE_INTEGER startoffset,
1472 PKEVENT event, PIO_STATUS_BLOCK iosb)
1474 IRP *irp;
1476 TRACE("(%ld %p %p %ld %p %p)\n", majorfunc, device, buffer, length, startoffset, iosb);
1478 irp = IoBuildAsynchronousFsdRequest( majorfunc, device, buffer, length, startoffset, iosb );
1479 if (!irp) return NULL;
1481 irp->UserEvent = event;
1482 return irp;
1485 static void build_driver_keypath( const WCHAR *name, UNICODE_STRING *keypath )
1487 static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0};
1488 WCHAR *str;
1490 /* Check what prefix is present */
1491 if (wcsncmp( name, servicesW, lstrlenW(servicesW) ) == 0)
1493 FIXME( "Driver name %s is malformed as the keypath\n", debugstr_w(name) );
1494 RtlCreateUnicodeString( keypath, name );
1495 return;
1497 if (wcsncmp( name, driverW, lstrlenW(driverW) ) == 0)
1498 name += lstrlenW(driverW);
1499 else
1500 FIXME( "Driver name %s does not properly begin with \\Driver\\\n", debugstr_w(name) );
1502 str = HeapAlloc( GetProcessHeap(), 0, sizeof(servicesW) + lstrlenW(name)*sizeof(WCHAR));
1503 lstrcpyW( str, servicesW );
1504 lstrcatW( str, name );
1505 RtlInitUnicodeString( keypath, str );
1509 static NTSTATUS WINAPI unhandled_irp( DEVICE_OBJECT *device, IRP *irp )
1511 TRACE( "(%p, %p)\n", device, irp );
1512 irp->IoStatus.u.Status = STATUS_INVALID_DEVICE_REQUEST;
1513 IoCompleteRequest( irp, IO_NO_INCREMENT );
1514 return STATUS_INVALID_DEVICE_REQUEST;
1518 static void free_driver_object( void *obj )
1520 struct wine_driver *driver = obj;
1521 RtlFreeUnicodeString( &driver->driver_obj.DriverName );
1522 RtlFreeUnicodeString( &driver->driver_obj.DriverExtension->ServiceKeyName );
1523 free_kernel_object( driver );
1526 static const WCHAR driver_type_name[] = {'D','r','i','v','e','r',0};
1528 static struct _OBJECT_TYPE driver_type =
1530 driver_type_name,
1531 NULL,
1532 free_driver_object
1535 POBJECT_TYPE IoDriverObjectType = &driver_type;
1538 /***********************************************************************
1539 * IoCreateDriver (NTOSKRNL.EXE.@)
1541 NTSTATUS WINAPI IoCreateDriver( UNICODE_STRING *name, PDRIVER_INITIALIZE init )
1543 struct wine_driver *driver;
1544 NTSTATUS status;
1545 unsigned int i;
1547 TRACE("(%s, %p)\n", debugstr_us(name), init);
1549 if (!(driver = alloc_kernel_object( IoDriverObjectType, NULL, sizeof(*driver), 1 )))
1550 return STATUS_NO_MEMORY;
1552 if ((status = RtlDuplicateUnicodeString( 1, name, &driver->driver_obj.DriverName )))
1554 free_kernel_object( driver );
1555 return status;
1558 driver->driver_obj.Size = sizeof(driver->driver_obj);
1559 driver->driver_obj.DriverInit = init;
1560 driver->driver_obj.DriverExtension = &driver->driver_extension;
1561 driver->driver_extension.DriverObject = &driver->driver_obj;
1562 build_driver_keypath( driver->driver_obj.DriverName.Buffer, &driver->driver_extension.ServiceKeyName );
1563 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1564 driver->driver_obj.MajorFunction[i] = unhandled_irp;
1565 list_init( &driver->root_pnp_devices );
1567 EnterCriticalSection( &drivers_cs );
1568 if (wine_rb_put( &wine_drivers, &driver->driver_obj.DriverName, &driver->entry ))
1569 ERR( "failed to insert driver %s in tree\n", debugstr_us(name) );
1570 LeaveCriticalSection( &drivers_cs );
1572 status = driver->driver_obj.DriverInit( &driver->driver_obj, &driver->driver_extension.ServiceKeyName );
1573 if (status)
1575 IoDeleteDriver( &driver->driver_obj );
1576 return status;
1579 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1581 if (driver->driver_obj.MajorFunction[i]) continue;
1582 driver->driver_obj.MajorFunction[i] = unhandled_irp;
1585 return STATUS_SUCCESS;
1589 /***********************************************************************
1590 * IoDeleteDriver (NTOSKRNL.EXE.@)
1592 void WINAPI IoDeleteDriver( DRIVER_OBJECT *driver_object )
1594 TRACE( "(%p)\n", driver_object );
1596 EnterCriticalSection( &drivers_cs );
1597 wine_rb_remove_key( &wine_drivers, &driver_object->DriverName );
1598 LeaveCriticalSection( &drivers_cs );
1600 ObDereferenceObject( driver_object );
1604 static const WCHAR device_type_name[] = {'D','e','v','i','c','e',0};
1606 static struct _OBJECT_TYPE device_type =
1608 device_type_name,
1611 POBJECT_TYPE IoDeviceObjectType = &device_type;
1613 /***********************************************************************
1614 * IoCreateDeviceSecure (NTOSKRNL.EXE.@)
1616 NTSTATUS WINAPI IoCreateDeviceSecure( DRIVER_OBJECT *driver, ULONG ext_size,
1617 UNICODE_STRING *name, DEVICE_TYPE type,
1618 ULONG characteristics, BOOLEAN exclusive,
1619 PCUNICODE_STRING sddl, LPCGUID guid,
1620 DEVICE_OBJECT **ret_device )
1622 FIXME( "(%p, %lu, %s, %lu, %lx, %u, %s, %s, %p): semi-stub\n",
1623 driver, ext_size, debugstr_us(name), type, characteristics, exclusive,
1624 debugstr_us(sddl), wine_dbgstr_guid(guid), ret_device );
1626 return IoCreateDevice( driver, ext_size, name, type, characteristics, exclusive, ret_device );
1629 /***********************************************************************
1630 * IoCreateDevice (NTOSKRNL.EXE.@)
1632 NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size,
1633 UNICODE_STRING *name, DEVICE_TYPE type,
1634 ULONG characteristics, BOOLEAN exclusive,
1635 DEVICE_OBJECT **ret_device )
1637 static const WCHAR auto_format[] = {'\\','D','e','v','i','c','e','\\','%','0','8','x',0};
1638 NTSTATUS status;
1639 struct wine_device *wine_device;
1640 DEVICE_OBJECT *device;
1641 HANDLE manager = get_device_manager();
1642 static unsigned int auto_idx = 0;
1643 WCHAR autoW[17];
1645 TRACE( "(%p, %lu, %s, %lu, %lx, %u, %p)\n",
1646 driver, ext_size, debugstr_us(name), type, characteristics, exclusive, ret_device );
1648 if (!(wine_device = alloc_kernel_object( IoDeviceObjectType, NULL, sizeof(struct wine_device) + ext_size, 1 )))
1649 return STATUS_NO_MEMORY;
1650 device = &wine_device->device_obj;
1652 device->DriverObject = driver;
1653 device->DeviceExtension = wine_device + 1;
1654 device->DeviceType = type;
1655 device->StackSize = 1;
1657 if (characteristics & FILE_AUTOGENERATED_DEVICE_NAME)
1661 swprintf( autoW, ARRAY_SIZE(autoW), auto_format, auto_idx++ );
1662 SERVER_START_REQ( create_device )
1664 req->rootdir = 0;
1665 req->manager = wine_server_obj_handle( manager );
1666 req->user_ptr = wine_server_client_ptr( device );
1667 wine_server_add_data( req, autoW, lstrlenW(autoW) * sizeof(WCHAR) );
1668 status = wine_server_call( req );
1670 SERVER_END_REQ;
1671 } while (status == STATUS_OBJECT_NAME_COLLISION);
1673 else
1675 SERVER_START_REQ( create_device )
1677 req->rootdir = 0;
1678 req->manager = wine_server_obj_handle( manager );
1679 req->user_ptr = wine_server_client_ptr( device );
1680 if (name) wine_server_add_data( req, name->Buffer, name->Length );
1681 status = wine_server_call( req );
1683 SERVER_END_REQ;
1686 if (status)
1688 free_kernel_object( device );
1689 return status;
1692 device->NextDevice = driver->DeviceObject;
1693 driver->DeviceObject = device;
1695 *ret_device = device;
1696 return STATUS_SUCCESS;
1700 /***********************************************************************
1701 * IoDeleteDevice (NTOSKRNL.EXE.@)
1703 void WINAPI IoDeleteDevice( DEVICE_OBJECT *device )
1705 NTSTATUS status;
1707 TRACE( "%p\n", device );
1709 SERVER_START_REQ( delete_device )
1711 req->manager = wine_server_obj_handle( get_device_manager() );
1712 req->device = wine_server_client_ptr( device );
1713 status = wine_server_call( req );
1715 SERVER_END_REQ;
1717 if (status == STATUS_SUCCESS)
1719 struct wine_device *wine_device = CONTAINING_RECORD(device, struct wine_device, device_obj);
1720 DEVICE_OBJECT **prev = &device->DriverObject->DeviceObject;
1721 DEVICE_RELATIONS *children;
1722 unsigned int i;
1724 while (*prev && *prev != device) prev = &(*prev)->NextDevice;
1725 if (*prev) *prev = (*prev)->NextDevice;
1726 if ((children = wine_device->children))
1728 for (i = 0; i < children->Count; ++i)
1729 ObDereferenceObject( children->Objects[i] );
1730 ExFreePool( children );
1732 ObDereferenceObject( device );
1737 /***********************************************************************
1738 * IoCreateSymbolicLink (NTOSKRNL.EXE.@)
1740 NTSTATUS WINAPI IoCreateSymbolicLink( UNICODE_STRING *name, UNICODE_STRING *target )
1742 HANDLE handle;
1743 OBJECT_ATTRIBUTES attr;
1744 NTSTATUS ret;
1746 attr.Length = sizeof(attr);
1747 attr.RootDirectory = 0;
1748 attr.ObjectName = name;
1749 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_PERMANENT;
1750 attr.SecurityDescriptor = NULL;
1751 attr.SecurityQualityOfService = NULL;
1753 TRACE( "%s -> %s\n", debugstr_us(name), debugstr_us(target) );
1754 if (!(ret = NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, target )))
1755 NtClose( handle );
1756 return ret;
1760 /***********************************************************************
1761 * IoCreateUnprotectedSymbolicLink (NTOSKRNL.EXE.@)
1763 NTSTATUS WINAPI IoCreateUnprotectedSymbolicLink( UNICODE_STRING *name, UNICODE_STRING *target )
1765 HANDLE handle;
1766 OBJECT_ATTRIBUTES attr;
1767 NTSTATUS ret;
1769 attr.Length = sizeof(attr);
1770 attr.RootDirectory = 0;
1771 attr.ObjectName = name;
1772 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_PERMANENT;
1773 attr.SecurityDescriptor = NULL;
1774 attr.SecurityQualityOfService = NULL;
1776 TRACE( "%s -> %s\n", debugstr_us(name), debugstr_us(target) );
1777 if (!(ret = NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, target )))
1778 NtClose( handle );
1779 return ret;
1783 /***********************************************************************
1784 * IoDeleteSymbolicLink (NTOSKRNL.EXE.@)
1786 NTSTATUS WINAPI IoDeleteSymbolicLink( UNICODE_STRING *name )
1788 HANDLE handle;
1789 OBJECT_ATTRIBUTES attr;
1790 NTSTATUS status;
1792 attr.Length = sizeof(attr);
1793 attr.RootDirectory = 0;
1794 attr.ObjectName = name;
1795 attr.Attributes = OBJ_CASE_INSENSITIVE;
1796 attr.SecurityDescriptor = NULL;
1797 attr.SecurityQualityOfService = NULL;
1799 if (!(status = NtOpenSymbolicLinkObject( &handle, 0, &attr )))
1801 NtMakeTemporaryObject( handle );
1802 NtClose( handle );
1804 return status;
1807 /***********************************************************************
1808 * IoGetDeviceInterfaces (NTOSKRNL.EXE.@)
1810 NTSTATUS WINAPI IoGetDeviceInterfaces( const GUID *InterfaceClassGuid,
1811 PDEVICE_OBJECT PhysicalDeviceObject,
1812 ULONG Flags, PWSTR *SymbolicLinkList )
1814 FIXME( "stub: %s %p %lx %p\n", debugstr_guid(InterfaceClassGuid),
1815 PhysicalDeviceObject, Flags, SymbolicLinkList );
1816 return STATUS_NOT_IMPLEMENTED;
1820 /***********************************************************************
1821 * IoGetDeviceObjectPointer (NTOSKRNL.EXE.@)
1823 NTSTATUS WINAPI IoGetDeviceObjectPointer( UNICODE_STRING *name, ACCESS_MASK access, PFILE_OBJECT *file, PDEVICE_OBJECT *device )
1825 static DEVICE_OBJECT stub_device;
1826 static DRIVER_OBJECT stub_driver;
1828 FIXME( "stub: %s %lx %p %p\n", debugstr_us(name), access, file, device );
1830 stub_device.StackSize = 0x80; /* minimum value to appease SecuROM 5.x */
1831 stub_device.DriverObject = &stub_driver;
1833 *file = NULL;
1834 *device = &stub_device;
1836 return STATUS_SUCCESS;
1839 /***********************************************************************
1840 * IoCallDriver (NTOSKRNL.EXE.@)
1842 NTSTATUS WINAPI IoCallDriver( DEVICE_OBJECT *device, IRP *irp )
1844 PDRIVER_DISPATCH dispatch;
1845 IO_STACK_LOCATION *irpsp;
1846 NTSTATUS status;
1848 --irp->CurrentLocation;
1849 irpsp = --irp->Tail.Overlay.s.u2.CurrentStackLocation;
1850 irpsp->DeviceObject = device;
1851 dispatch = device->DriverObject->MajorFunction[irpsp->MajorFunction];
1853 TRACE_(relay)( "\1Call driver dispatch %p (device=%p,irp=%p)\n", dispatch, device, irp );
1855 status = dispatch( device, irp );
1857 TRACE_(relay)( "\1Ret driver dispatch %p (device=%p,irp=%p) retval=%08lx\n",
1858 dispatch, device, irp, status );
1860 return status;
1864 /***********************************************************************
1865 * IofCallDriver (NTOSKRNL.EXE.@)
1867 DEFINE_FASTCALL_WRAPPER( IofCallDriver, 8 )
1868 NTSTATUS FASTCALL IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
1870 TRACE( "%p %p\n", device, irp );
1871 return IoCallDriver( device, irp );
1875 /***********************************************************************
1876 * IoGetRelatedDeviceObject (NTOSKRNL.EXE.@)
1878 PDEVICE_OBJECT WINAPI IoGetRelatedDeviceObject( PFILE_OBJECT obj )
1880 FIXME( "stub: %p\n", obj );
1881 return NULL;
1884 static CONFIGURATION_INFORMATION configuration_information;
1886 /***********************************************************************
1887 * IoGetConfigurationInformation (NTOSKRNL.EXE.@)
1889 PCONFIGURATION_INFORMATION WINAPI IoGetConfigurationInformation(void)
1891 FIXME( "partial stub\n" );
1892 /* FIXME: return actual devices on system */
1893 return &configuration_information;
1896 /***********************************************************************
1897 * IoGetStackLimits (NTOSKRNL.EXE.@)
1899 void WINAPI IoGetStackLimits(ULONG_PTR *low, ULONG_PTR *high)
1901 TEB *teb = NtCurrentTeb();
1903 TRACE( "%p %p\n", low, high );
1905 *low = (DWORD_PTR)teb->Tib.StackLimit;
1906 *high = (DWORD_PTR)teb->Tib.StackBase;
1909 /***********************************************************************
1910 * IoIsWdmVersionAvailable (NTOSKRNL.EXE.@)
1912 NTSTATUS WINAPI IoIsWdmVersionAvailable(UCHAR MajorVersion, UCHAR MinorVersion)
1914 DWORD version;
1915 DWORD major;
1916 DWORD minor;
1918 TRACE( "%d, 0x%X\n", MajorVersion, MinorVersion );
1920 version = GetVersion();
1921 major = LOBYTE(version);
1922 minor = HIBYTE(LOWORD(version));
1924 if (MajorVersion == 6 && MinorVersion == 0)
1926 /* Windows Vista, Windows Server 2008, Windows 7 */
1928 else if (MajorVersion == 1)
1930 if (MinorVersion == 0x30)
1932 /* Windows server 2003 */
1933 MajorVersion = 6;
1934 MinorVersion = 0;
1936 else if (MinorVersion == 0x20)
1938 /* Windows XP */
1939 MajorVersion = 5;
1940 MinorVersion = 1;
1942 else if (MinorVersion == 0x10)
1944 /* Windows 2000 */
1945 MajorVersion = 5;
1946 MinorVersion = 0;
1948 else if (MinorVersion == 0x05)
1950 /* Windows ME */
1951 MajorVersion = 4;
1952 MinorVersion = 0x5a;
1954 else if (MinorVersion == 0x00)
1956 /* Windows 98 */
1957 MajorVersion = 4;
1958 MinorVersion = 0x0a;
1960 else
1962 FIXME( "unknown major %d minor 0x%X\n", MajorVersion, MinorVersion );
1963 return FALSE;
1966 else
1968 FIXME( "unknown major %d minor 0x%X\n", MajorVersion, MinorVersion );
1969 return FALSE;
1971 return major > MajorVersion || (major == MajorVersion && minor >= MinorVersion);
1974 /***********************************************************************
1975 * IoQueryDeviceDescription (NTOSKRNL.EXE.@)
1977 NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE itype, PULONG bus, PCONFIGURATION_TYPE ctype,
1978 PULONG cnum, PCONFIGURATION_TYPE ptype, PULONG pnum,
1979 PIO_QUERY_DEVICE_ROUTINE callout, PVOID context)
1981 FIXME( "(%p %p %p %p %p %p %p %p)\n", itype, bus, ctype, cnum, ptype, pnum, callout, context);
1982 return STATUS_NOT_IMPLEMENTED;
1985 /***********************************************************************
1986 * IoRegisterDriverReinitialization (NTOSKRNL.EXE.@)
1988 void WINAPI IoRegisterDriverReinitialization( PDRIVER_OBJECT obj, PDRIVER_REINITIALIZE reinit, PVOID context )
1990 FIXME( "stub: %p %p %p\n", obj, reinit, context );
1993 /***********************************************************************
1994 * IoRegisterBootDriverReinitialization (NTOSKRNL.EXE.@)
1996 void WINAPI IoRegisterBootDriverReinitialization(DRIVER_OBJECT *driver, PDRIVER_REINITIALIZE proc, void *ctx)
1998 FIXME("driver %p, proc %p, ctx %p, stub!\n", driver, proc, ctx);
2001 /***********************************************************************
2002 * IoRegisterShutdownNotification (NTOSKRNL.EXE.@)
2004 NTSTATUS WINAPI IoRegisterShutdownNotification( PDEVICE_OBJECT obj )
2006 FIXME( "stub: %p\n", obj );
2007 return STATUS_SUCCESS;
2011 /***********************************************************************
2012 * IoUnregisterShutdownNotification (NTOSKRNL.EXE.@)
2014 VOID WINAPI IoUnregisterShutdownNotification( PDEVICE_OBJECT obj )
2016 FIXME( "stub: %p\n", obj );
2020 /***********************************************************************
2021 * IoReportResourceForDetection (NTOSKRNL.EXE.@)
2023 NTSTATUS WINAPI IoReportResourceForDetection( DRIVER_OBJECT *drv_obj, CM_RESOURCE_LIST *drv_list, ULONG drv_size,
2024 DEVICE_OBJECT *dev_obj, CM_RESOURCE_LIST *dev_list, ULONG dev_size,
2025 BOOLEAN *conflict )
2027 FIXME( "(%p, %p, %lu, %p, %p, %lu, %p): stub\n", drv_obj, drv_list, drv_size,
2028 dev_obj, dev_list, dev_size, conflict );
2030 return STATUS_NOT_IMPLEMENTED;
2034 /***********************************************************************
2035 * IoReportResourceUsage (NTOSKRNL.EXE.@)
2037 NTSTATUS WINAPI IoReportResourceUsage( UNICODE_STRING *name, DRIVER_OBJECT *drv_obj, CM_RESOURCE_LIST *drv_list,
2038 ULONG drv_size, DRIVER_OBJECT *dev_obj, CM_RESOURCE_LIST *dev_list,
2039 ULONG dev_size, BOOLEAN overwrite, BOOLEAN *conflict )
2041 FIXME( "(%s, %p, %p, %lu, %p, %p, %lu, %d, %p): stub\n", debugstr_us(name),
2042 drv_obj, drv_list, drv_size, dev_obj, dev_list, dev_size, overwrite, conflict );
2044 return STATUS_NOT_IMPLEMENTED;
2048 /***********************************************************************
2049 * IoCompleteRequest (NTOSKRNL.EXE.@)
2051 VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
2053 IO_STACK_LOCATION *irpsp;
2054 PIO_COMPLETION_ROUTINE routine;
2055 NTSTATUS status, stat;
2056 DEVICE_OBJECT *device;
2057 int call_flag = 0;
2059 TRACE( "%p %u\n", irp, priority_boost );
2061 status = irp->IoStatus.u.Status;
2062 while (irp->CurrentLocation <= irp->StackCount)
2064 irpsp = irp->Tail.Overlay.s.u2.CurrentStackLocation;
2065 routine = irpsp->CompletionRoutine;
2066 call_flag = 0;
2067 if (routine)
2069 if ((irpsp->Control & SL_INVOKE_ON_SUCCESS) && STATUS_SUCCESS == status)
2070 call_flag = 1;
2071 if ((irpsp->Control & SL_INVOKE_ON_ERROR) && STATUS_SUCCESS != status)
2072 call_flag = 1;
2073 if ((irpsp->Control & SL_INVOKE_ON_CANCEL) && irp->Cancel)
2074 call_flag = 1;
2076 ++irp->CurrentLocation;
2077 ++irp->Tail.Overlay.s.u2.CurrentStackLocation;
2078 if (irp->CurrentLocation <= irp->StackCount)
2079 device = IoGetCurrentIrpStackLocation(irp)->DeviceObject;
2080 else
2081 device = NULL;
2082 irp->PendingReturned = !!(irpsp->Control & SL_PENDING_RETURNED);
2083 irpsp->Control = 0;
2084 if (call_flag)
2086 TRACE( "calling %p( %p, %p, %p )\n", routine, device, irp, irpsp->Context );
2087 stat = routine( device, irp, irpsp->Context );
2088 TRACE( "CompletionRoutine returned %lx\n", stat );
2089 if (STATUS_MORE_PROCESSING_REQUIRED == stat)
2090 return;
2094 if (irp->Flags & IRP_DEALLOCATE_BUFFER)
2095 HeapFree( GetProcessHeap(), 0, irp->AssociatedIrp.SystemBuffer );
2096 if (irp->UserIosb) *irp->UserIosb = irp->IoStatus;
2097 if (irp->UserEvent) KeSetEvent( irp->UserEvent, IO_NO_INCREMENT, FALSE );
2099 IoFreeIrp( irp );
2103 /***********************************************************************
2104 * IofCompleteRequest (NTOSKRNL.EXE.@)
2106 DEFINE_FASTCALL_WRAPPER( IofCompleteRequest, 8 )
2107 void FASTCALL IofCompleteRequest( IRP *irp, UCHAR priority_boost )
2109 TRACE( "%p %u\n", irp, priority_boost );
2110 IoCompleteRequest( irp, priority_boost );
2114 /***********************************************************************
2115 * IoCancelIrp (NTOSKRNL.EXE.@)
2117 BOOLEAN WINAPI IoCancelIrp( IRP *irp )
2119 PDRIVER_CANCEL cancel_routine;
2120 KIRQL irql;
2122 TRACE( "(%p)\n", irp );
2124 IoAcquireCancelSpinLock( &irql );
2125 irp->Cancel = TRUE;
2126 if (!(cancel_routine = IoSetCancelRoutine( irp, NULL )))
2128 IoReleaseCancelSpinLock( irp->CancelIrql );
2129 return FALSE;
2132 /* CancelRoutine is responsible for calling IoReleaseCancelSpinLock */
2133 irp->CancelIrql = irql;
2134 cancel_routine( IoGetCurrentIrpStackLocation(irp)->DeviceObject, irp );
2135 return TRUE;
2139 /***********************************************************************
2140 * InterlockedCompareExchange (NTOSKRNL.EXE.@)
2142 DEFINE_FASTCALL_WRAPPER( NTOSKRNL_InterlockedCompareExchange, 12 )
2143 LONG FASTCALL NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
2145 return InterlockedCompareExchange( dest, xchg, compare );
2149 /***********************************************************************
2150 * InterlockedDecrement (NTOSKRNL.EXE.@)
2152 DEFINE_FASTCALL1_WRAPPER( NTOSKRNL_InterlockedDecrement )
2153 LONG FASTCALL NTOSKRNL_InterlockedDecrement( LONG volatile *dest )
2155 return InterlockedDecrement( dest );
2159 /***********************************************************************
2160 * InterlockedExchange (NTOSKRNL.EXE.@)
2162 DEFINE_FASTCALL_WRAPPER( NTOSKRNL_InterlockedExchange, 8 )
2163 LONG FASTCALL NTOSKRNL_InterlockedExchange( LONG volatile *dest, LONG val )
2165 return InterlockedExchange( dest, val );
2169 /***********************************************************************
2170 * InterlockedExchangeAdd (NTOSKRNL.EXE.@)
2172 DEFINE_FASTCALL_WRAPPER( NTOSKRNL_InterlockedExchangeAdd, 8 )
2173 LONG FASTCALL NTOSKRNL_InterlockedExchangeAdd( LONG volatile *dest, LONG incr )
2175 return InterlockedExchangeAdd( dest, incr );
2179 /***********************************************************************
2180 * InterlockedIncrement (NTOSKRNL.EXE.@)
2182 DEFINE_FASTCALL1_WRAPPER( NTOSKRNL_InterlockedIncrement )
2183 LONG FASTCALL NTOSKRNL_InterlockedIncrement( LONG volatile *dest )
2185 return InterlockedIncrement( dest );
2189 /***********************************************************************
2190 * ExAllocatePool (NTOSKRNL.EXE.@)
2192 PVOID WINAPI ExAllocatePool( POOL_TYPE type, SIZE_T size )
2194 return ExAllocatePoolWithTag( type, size, 0 );
2198 /***********************************************************************
2199 * ExAllocatePoolWithQuota (NTOSKRNL.EXE.@)
2201 PVOID WINAPI ExAllocatePoolWithQuota( POOL_TYPE type, SIZE_T size )
2203 return ExAllocatePoolWithTag( type, size, 0 );
2207 /***********************************************************************
2208 * ExAllocatePoolWithTag (NTOSKRNL.EXE.@)
2210 PVOID WINAPI ExAllocatePoolWithTag( POOL_TYPE type, SIZE_T size, ULONG tag )
2212 /* FIXME: handle page alignment constraints */
2213 void *ret = HeapAlloc( ntoskrnl_heap, 0, size );
2214 TRACE( "%Iu pool %u -> %p\n", size, type, ret );
2215 return ret;
2219 /***********************************************************************
2220 * ExAllocatePoolWithQuotaTag (NTOSKRNL.EXE.@)
2222 PVOID WINAPI ExAllocatePoolWithQuotaTag( POOL_TYPE type, SIZE_T size, ULONG tag )
2224 return ExAllocatePoolWithTag( type, size, tag );
2228 /***********************************************************************
2229 * ExCreateCallback (NTOSKRNL.EXE.@)
2231 NTSTATUS WINAPI ExCreateCallback(PCALLBACK_OBJECT *obj, POBJECT_ATTRIBUTES attr,
2232 BOOLEAN create, BOOLEAN allow_multiple)
2234 FIXME("(%p, %p, %u, %u): stub\n", obj, attr, create, allow_multiple);
2236 return STATUS_SUCCESS;
2239 void * WINAPI ExRegisterCallback(PCALLBACK_OBJECT callback_object,
2240 PCALLBACK_FUNCTION callback_function, void *callback_context)
2242 FIXME("callback_object %p, callback_function %p, callback_context %p stub.\n",
2243 callback_object, callback_function, callback_context);
2245 return (void *)0xdeadbeef;
2248 void WINAPI ExUnregisterCallback(void *callback_registration)
2250 FIXME("callback_registration %p stub.\n", callback_registration);
2253 /***********************************************************************
2254 * ExFreePool (NTOSKRNL.EXE.@)
2256 void WINAPI ExFreePool( void *ptr )
2258 ExFreePoolWithTag( ptr, 0 );
2262 /***********************************************************************
2263 * ExFreePoolWithTag (NTOSKRNL.EXE.@)
2265 void WINAPI ExFreePoolWithTag( void *ptr, ULONG tag )
2267 TRACE( "%p\n", ptr );
2268 HeapFree( ntoskrnl_heap, 0, ptr );
2271 static void initialize_lookaside_list( GENERAL_LOOKASIDE *lookaside, PALLOCATE_FUNCTION allocate, PFREE_FUNCTION free,
2272 ULONG type, SIZE_T size, ULONG tag )
2275 RtlInitializeSListHead( &lookaside->u.ListHead );
2276 lookaside->Depth = 4;
2277 lookaside->MaximumDepth = 256;
2278 lookaside->TotalAllocates = 0;
2279 lookaside->u2.AllocateMisses = 0;
2280 lookaside->TotalFrees = 0;
2281 lookaside->u3.FreeMisses = 0;
2282 lookaside->Type = type;
2283 lookaside->Tag = tag;
2284 lookaside->Size = size;
2285 lookaside->u4.Allocate = allocate ? allocate : ExAllocatePoolWithTag;
2286 lookaside->u5.Free = free ? free : ExFreePool;
2287 lookaside->LastTotalAllocates = 0;
2288 lookaside->u6.LastAllocateMisses = 0;
2290 /* FIXME: insert in global list of lookadside lists */
2293 /***********************************************************************
2294 * ExInitializeNPagedLookasideList (NTOSKRNL.EXE.@)
2296 void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST lookaside,
2297 PALLOCATE_FUNCTION allocate,
2298 PFREE_FUNCTION free,
2299 ULONG flags,
2300 SIZE_T size,
2301 ULONG tag,
2302 USHORT depth)
2304 TRACE( "%p, %p, %p, %lu, %Iu, %lu, %u\n", lookaside, allocate, free, flags, size, tag, depth );
2305 initialize_lookaside_list( &lookaside->L, allocate, free, NonPagedPool | flags, size, tag );
2308 /***********************************************************************
2309 * ExInitializePagedLookasideList (NTOSKRNL.EXE.@)
2311 void WINAPI ExInitializePagedLookasideList(PPAGED_LOOKASIDE_LIST lookaside,
2312 PALLOCATE_FUNCTION allocate,
2313 PFREE_FUNCTION free,
2314 ULONG flags,
2315 SIZE_T size,
2316 ULONG tag,
2317 USHORT depth)
2319 TRACE( "%p, %p, %p, %lu, %Iu, %lu, %u\n", lookaside, allocate, free, flags, size, tag, depth );
2320 initialize_lookaside_list( &lookaside->L, allocate, free, PagedPool | flags, size, tag );
2323 static void delete_lookaside_list( GENERAL_LOOKASIDE *lookaside )
2325 void *entry;
2326 while ((entry = RtlInterlockedPopEntrySList(&lookaside->u.ListHead)))
2327 lookaside->u5.FreeEx(entry, (LOOKASIDE_LIST_EX*)lookaside);
2330 /***********************************************************************
2331 * ExDeleteNPagedLookasideList (NTOSKRNL.EXE.@)
2333 void WINAPI ExDeleteNPagedLookasideList( PNPAGED_LOOKASIDE_LIST lookaside )
2335 TRACE( "%p\n", lookaside );
2336 delete_lookaside_list( &lookaside->L );
2340 /***********************************************************************
2341 * ExDeletePagedLookasideList (NTOSKRNL.EXE.@)
2343 void WINAPI ExDeletePagedLookasideList( PPAGED_LOOKASIDE_LIST lookaside )
2345 TRACE( "%p\n", lookaside );
2346 delete_lookaside_list( &lookaside->L );
2349 /***********************************************************************
2350 * ExInitializeZone (NTOSKRNL.EXE.@)
2352 NTSTATUS WINAPI ExInitializeZone(PZONE_HEADER Zone,
2353 ULONG BlockSize,
2354 PVOID InitialSegment,
2355 ULONG InitialSegmentSize)
2357 FIXME( "stub: %p, %lu, %p, %lu\n", Zone, BlockSize, InitialSegment, InitialSegmentSize );
2358 return STATUS_NOT_IMPLEMENTED;
2361 /***********************************************************************
2362 * FsRtlIsNameInExpression (NTOSKRNL.EXE.@)
2364 BOOLEAN WINAPI FsRtlIsNameInExpression(PUNICODE_STRING expression, PUNICODE_STRING name,
2365 BOOLEAN ignore, PWCH upcase)
2367 FIXME("stub: %p %p %d %p\n", expression, name, ignore, upcase);
2368 return FALSE;
2371 /***********************************************************************
2372 * FsRtlRegisterUncProvider (NTOSKRNL.EXE.@)
2374 NTSTATUS WINAPI FsRtlRegisterUncProvider(PHANDLE MupHandle, PUNICODE_STRING RedirDevName,
2375 BOOLEAN MailslotsSupported)
2377 FIXME("(%p %p %d): stub\n", MupHandle, RedirDevName, MailslotsSupported);
2378 return STATUS_NOT_IMPLEMENTED;
2382 static void *create_process_object( HANDLE handle )
2384 PEPROCESS process;
2386 if (!(process = alloc_kernel_object( PsProcessType, handle, sizeof(*process), 0 ))) return NULL;
2388 process->header.Type = 3;
2389 process->header.WaitListHead.Blink = INVALID_HANDLE_VALUE; /* mark as kernel object */
2390 NtQueryInformationProcess( handle, ProcessBasicInformation, &process->info, sizeof(process->info), NULL );
2391 IsWow64Process( handle, &process->wow64 );
2392 return process;
2395 static const WCHAR process_type_name[] = {'P','r','o','c','e','s','s',0};
2397 static struct _OBJECT_TYPE process_type =
2399 process_type_name,
2400 create_process_object
2403 POBJECT_TYPE PsProcessType = &process_type;
2406 /***********************************************************************
2407 * IoGetCurrentProcess / PsGetCurrentProcess (NTOSKRNL.EXE.@)
2409 PEPROCESS WINAPI IoGetCurrentProcess(void)
2411 return KeGetCurrentThread()->process;
2414 /***********************************************************************
2415 * PsLookupProcessByProcessId (NTOSKRNL.EXE.@)
2417 NTSTATUS WINAPI PsLookupProcessByProcessId( HANDLE processid, PEPROCESS *process )
2419 NTSTATUS status;
2420 HANDLE handle;
2422 TRACE( "(%p %p)\n", processid, process );
2424 if (!(handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, HandleToUlong(processid) )))
2425 return STATUS_INVALID_PARAMETER;
2427 status = ObReferenceObjectByHandle( handle, PROCESS_ALL_ACCESS, PsProcessType, KernelMode, (void**)process, NULL );
2429 NtClose( handle );
2430 return status;
2433 /*********************************************************************
2434 * PsGetProcessId (NTOSKRNL.@)
2436 HANDLE WINAPI PsGetProcessId(PEPROCESS process)
2438 TRACE( "%p -> %Ix\n", process, process->info.UniqueProcessId );
2439 return (HANDLE)process->info.UniqueProcessId;
2442 /*********************************************************************
2443 * PsGetProcessInheritedFromUniqueProcessId (NTOSKRNL.@)
2445 HANDLE WINAPI PsGetProcessInheritedFromUniqueProcessId( PEPROCESS process )
2447 HANDLE id = (HANDLE)process->info.InheritedFromUniqueProcessId;
2448 TRACE( "%p -> %p\n", process, id );
2449 return id;
2452 static void *create_thread_object( HANDLE handle )
2454 THREAD_BASIC_INFORMATION info;
2455 struct _KTHREAD *thread;
2456 HANDLE process;
2458 if (!(thread = alloc_kernel_object( PsThreadType, handle, sizeof(*thread), 0 ))) return NULL;
2460 thread->header.Type = 6;
2461 thread->header.WaitListHead.Blink = INVALID_HANDLE_VALUE; /* mark as kernel object */
2462 thread->user_affinity = 0;
2464 if (!NtQueryInformationThread( handle, ThreadBasicInformation, &info, sizeof(info), NULL ))
2466 thread->id = info.ClientId;
2467 if ((process = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, HandleToUlong(thread->id.UniqueProcess) )))
2469 kernel_object_from_handle( process, PsProcessType, (void**)&thread->process );
2470 NtClose( process );
2475 return thread;
2478 static const WCHAR thread_type_name[] = {'T','h','r','e','a','d',0};
2480 static struct _OBJECT_TYPE thread_type =
2482 thread_type_name,
2483 create_thread_object
2486 POBJECT_TYPE PsThreadType = &thread_type;
2489 /***********************************************************************
2490 * KeGetCurrentThread / PsGetCurrentThread (NTOSKRNL.EXE.@)
2492 PRKTHREAD WINAPI KeGetCurrentThread(void)
2494 struct _KTHREAD *thread = NtCurrentTeb()->Reserved5[1];
2496 if (!thread)
2498 HANDLE handle = GetCurrentThread();
2500 /* FIXME: we shouldn't need it, GetCurrentThread() should be client thread already */
2501 if (GetCurrentThreadId() == request_thread)
2502 handle = OpenThread( THREAD_QUERY_INFORMATION, FALSE, client_tid );
2504 kernel_object_from_handle( handle, PsThreadType, (void**)&thread );
2505 if (handle != GetCurrentThread()) NtClose( handle );
2507 NtCurrentTeb()->Reserved5[1] = thread;
2510 return thread;
2513 /*****************************************************
2514 * PsLookupThreadByThreadId (NTOSKRNL.EXE.@)
2516 NTSTATUS WINAPI PsLookupThreadByThreadId( HANDLE threadid, PETHREAD *thread )
2518 OBJECT_ATTRIBUTES attr;
2519 CLIENT_ID cid;
2520 NTSTATUS status;
2521 HANDLE handle;
2523 TRACE( "(%p %p)\n", threadid, thread );
2525 cid.UniqueProcess = 0;
2526 cid.UniqueThread = threadid;
2527 InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL );
2528 status = NtOpenThread( &handle, THREAD_QUERY_INFORMATION, &attr, &cid );
2529 if (status) return status;
2531 status = ObReferenceObjectByHandle( handle, THREAD_ALL_ACCESS, PsThreadType, KernelMode, (void**)thread, NULL );
2533 NtClose( handle );
2534 return status;
2537 /*********************************************************************
2538 * PsGetThreadId (NTOSKRNL.@)
2540 HANDLE WINAPI PsGetThreadId(PETHREAD thread)
2542 TRACE( "%p -> %p\n", thread, thread->kthread.id.UniqueThread );
2543 return thread->kthread.id.UniqueThread;
2546 /*********************************************************************
2547 * PsGetThreadProcessId (NTOSKRNL.@)
2549 HANDLE WINAPI PsGetThreadProcessId( PETHREAD thread )
2551 TRACE( "%p -> %p\n", thread, thread->kthread.id.UniqueProcess );
2552 return thread->kthread.id.UniqueProcess;
2555 /***********************************************************************
2556 * KeInsertQueue (NTOSKRNL.EXE.@)
2558 LONG WINAPI KeInsertQueue(PRKQUEUE Queue, PLIST_ENTRY Entry)
2560 FIXME( "stub: %p %p\n", Queue, Entry );
2561 return 0;
2564 /**********************************************************************
2565 * KeQueryActiveProcessors (NTOSKRNL.EXE.@)
2567 * Return the active Processors as bitmask
2569 * RETURNS
2570 * active Processors as bitmask
2573 KAFFINITY WINAPI KeQueryActiveProcessors( void )
2575 DWORD_PTR affinity_mask;
2577 GetProcessAffinityMask( GetCurrentProcess(), NULL, &affinity_mask);
2578 return affinity_mask;
2581 ULONG WINAPI KeQueryActiveProcessorCountEx(USHORT group_number)
2583 TRACE("group_number %u.\n", group_number);
2585 return GetActiveProcessorCount(group_number);
2588 /**********************************************************************
2589 * KeQueryInterruptTime (NTOSKRNL.EXE.@)
2591 * Return the interrupt time count
2594 ULONGLONG WINAPI KeQueryInterruptTime( void )
2596 LARGE_INTEGER totaltime;
2598 KeQueryTickCount(&totaltime);
2599 return totaltime.QuadPart;
2603 /***********************************************************************
2604 * KeQuerySystemTime (NTOSKRNL.EXE.@)
2606 void WINAPI KeQuerySystemTime( LARGE_INTEGER *time )
2608 NtQuerySystemTime( time );
2612 /***********************************************************************
2613 * KeQueryTickCount (NTOSKRNL.EXE.@)
2615 void WINAPI KeQueryTickCount( LARGE_INTEGER *count )
2617 count->QuadPart = NtGetTickCount();
2618 /* update the global variable too */
2619 KeTickCount.LowPart = count->u.LowPart;
2620 KeTickCount.High1Time = count->u.HighPart;
2621 KeTickCount.High2Time = count->u.HighPart;
2625 /***********************************************************************
2626 * KeQueryTimeIncrement (NTOSKRNL.EXE.@)
2628 ULONG WINAPI KeQueryTimeIncrement(void)
2630 return 10000;
2634 /***********************************************************************
2635 * KeSetPriorityThread (NTOSKRNL.EXE.@)
2637 KPRIORITY WINAPI KeSetPriorityThread( PKTHREAD Thread, KPRIORITY Priority )
2639 FIXME("(%p %ld)\n", Thread, Priority);
2640 return Priority;
2643 /***********************************************************************
2644 * KeSetSystemAffinityThread (NTOSKRNL.EXE.@)
2646 VOID WINAPI KeSetSystemAffinityThread(KAFFINITY affinity)
2648 KeSetSystemAffinityThreadEx(affinity);
2651 KAFFINITY WINAPI KeSetSystemAffinityThreadEx(KAFFINITY affinity)
2653 DWORD_PTR system_affinity = KeQueryActiveProcessors();
2654 PKTHREAD thread = KeGetCurrentThread();
2655 GROUP_AFFINITY old, new;
2657 TRACE("affinity %#Ix.\n", affinity);
2659 affinity &= system_affinity;
2661 NtQueryInformationThread(GetCurrentThread(), ThreadGroupInformation,
2662 &old, sizeof(old), NULL);
2664 if (old.Mask != system_affinity)
2665 thread->user_affinity = old.Mask;
2667 memset(&new, 0, sizeof(new));
2668 new.Mask = affinity;
2670 return NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation, &new, sizeof(new))
2671 ? 0 : thread->user_affinity;
2675 /***********************************************************************
2676 * KeRevertToUserAffinityThread (NTOSKRNL.EXE.@)
2678 void WINAPI KeRevertToUserAffinityThread(void)
2680 KeRevertToUserAffinityThreadEx(0);
2683 void WINAPI KeRevertToUserAffinityThreadEx(KAFFINITY affinity)
2685 DWORD_PTR system_affinity = KeQueryActiveProcessors();
2686 PRKTHREAD thread = KeGetCurrentThread();
2687 GROUP_AFFINITY new;
2689 TRACE("affinity %#Ix.\n", affinity);
2691 affinity &= system_affinity;
2693 memset(&new, 0, sizeof(new));
2694 new.Mask = affinity ? affinity
2695 : (thread->user_affinity ? thread->user_affinity : system_affinity);
2697 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation, &new, sizeof(new));
2698 thread->user_affinity = affinity;
2701 /***********************************************************************
2702 * IoRegisterFileSystem (NTOSKRNL.EXE.@)
2704 VOID WINAPI IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject)
2706 FIXME("(%p): stub\n", DeviceObject);
2709 /***********************************************************************
2710 * KeExpandKernelStackAndCalloutEx (NTOSKRNL.EXE.@)
2712 NTSTATUS WINAPI KeExpandKernelStackAndCalloutEx(PEXPAND_STACK_CALLOUT callout, void *parameter, SIZE_T size,
2713 BOOLEAN wait, void *context)
2715 WARN("(%p %p %Iu %x %p) semi-stub: ignoring stack expand\n", callout, parameter, size, wait, context);
2716 callout(parameter);
2717 return STATUS_SUCCESS;
2720 /***********************************************************************
2721 * KeExpandKernelStackAndCallout (NTOSKRNL.EXE.@)
2723 NTSTATUS WINAPI KeExpandKernelStackAndCallout(PEXPAND_STACK_CALLOUT callout, void *parameter, SIZE_T size)
2725 return KeExpandKernelStackAndCalloutEx(callout, parameter, size, TRUE, NULL);
2728 /***********************************************************************
2729 * IoUnregisterFileSystem (NTOSKRNL.EXE.@)
2731 VOID WINAPI IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject)
2733 FIXME("(%p): stub\n", DeviceObject);
2736 /***********************************************************************
2737 * MmAllocateNonCachedMemory (NTOSKRNL.EXE.@)
2739 PVOID WINAPI MmAllocateNonCachedMemory( SIZE_T size )
2741 TRACE( "%Iu\n", size );
2742 return VirtualAlloc( NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE|PAGE_NOCACHE );
2745 /***********************************************************************
2746 * MmAllocateContiguousMemory (NTOSKRNL.EXE.@)
2748 PVOID WINAPI MmAllocateContiguousMemory( SIZE_T size, PHYSICAL_ADDRESS highest_valid_address )
2750 FIXME( "%Iu, %s stub\n", size, wine_dbgstr_longlong(highest_valid_address.QuadPart) );
2751 return NULL;
2754 /***********************************************************************
2755 * MmAllocateContiguousMemorySpecifyCache (NTOSKRNL.EXE.@)
2757 PVOID WINAPI MmAllocateContiguousMemorySpecifyCache( SIZE_T size,
2758 PHYSICAL_ADDRESS lowest_valid_address,
2759 PHYSICAL_ADDRESS highest_valid_address,
2760 PHYSICAL_ADDRESS BoundaryAddressMultiple,
2761 MEMORY_CACHING_TYPE CacheType )
2763 FIXME(": stub\n");
2764 return NULL;
2767 /***********************************************************************
2768 * MmAllocatePagesForMdl (NTOSKRNL.EXE.@)
2770 PMDL WINAPI MmAllocatePagesForMdl(PHYSICAL_ADDRESS lowaddress, PHYSICAL_ADDRESS highaddress,
2771 PHYSICAL_ADDRESS skipbytes, SIZE_T size)
2773 FIXME("%s %s %s %Iu: stub\n", wine_dbgstr_longlong(lowaddress.QuadPart), wine_dbgstr_longlong(highaddress.QuadPart),
2774 wine_dbgstr_longlong(skipbytes.QuadPart), size);
2775 return NULL;
2778 /***********************************************************************
2779 * MmBuildMdlForNonPagedPool (NTOSKRNL.EXE.@)
2781 void WINAPI MmBuildMdlForNonPagedPool(MDL *mdl)
2783 FIXME("stub: %p\n", mdl);
2786 /***********************************************************************
2787 * MmCreateSection (NTOSKRNL.EXE.@)
2789 NTSTATUS WINAPI MmCreateSection( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
2790 LARGE_INTEGER *size, ULONG protect, ULONG alloc_attr,
2791 HANDLE file, FILE_OBJECT *file_obj )
2793 FIXME("%p %#lx %p %s %#lx %#lx %p %p: stub\n", handle, access, attr,
2794 wine_dbgstr_longlong(size->QuadPart), protect, alloc_attr, file, file_obj);
2795 return STATUS_NOT_IMPLEMENTED;
2798 /***********************************************************************
2799 * MmFreeNonCachedMemory (NTOSKRNL.EXE.@)
2801 void WINAPI MmFreeNonCachedMemory( void *addr, SIZE_T size )
2803 TRACE( "%p %Iu\n", addr, size );
2804 VirtualFree( addr, 0, MEM_RELEASE );
2807 /***********************************************************************
2808 * MmIsAddressValid (NTOSKRNL.EXE.@)
2810 * Check if the process can access the virtual address without a pagefault
2812 * PARAMS
2813 * VirtualAddress [I] Address to check
2815 * RETURNS
2816 * Failure: FALSE
2817 * Success: TRUE (Accessing the Address works without a Pagefault)
2820 BOOLEAN WINAPI MmIsAddressValid(PVOID VirtualAddress)
2822 TRACE("(%p)\n", VirtualAddress);
2823 return !IsBadReadPtr(VirtualAddress, 1);
2826 /***********************************************************************
2827 * MmGetPhysicalAddress (NTOSKRNL.EXE.@)
2829 PHYSICAL_ADDRESS WINAPI MmGetPhysicalAddress(void *virtual_address)
2831 PHYSICAL_ADDRESS ret;
2832 FIXME("(%p): semi-stub\n", virtual_address);
2833 ret.QuadPart = (ULONG_PTR)virtual_address;
2834 return ret;
2837 /***********************************************************************
2838 * MmMapIoSpace (NTOSKRNL.EXE.@)
2840 PVOID WINAPI MmMapIoSpace( PHYSICAL_ADDRESS PhysicalAddress, DWORD NumberOfBytes, DWORD CacheType )
2842 FIXME( "stub: 0x%08lx%08lx, %ld, %ld\n", PhysicalAddress.u.HighPart, PhysicalAddress.u.LowPart, NumberOfBytes, CacheType );
2843 return NULL;
2847 /***********************************************************************
2848 * MmLockPagableSectionByHandle (NTOSKRNL.EXE.@)
2850 VOID WINAPI MmLockPagableSectionByHandle(PVOID ImageSectionHandle)
2852 FIXME("stub %p\n", ImageSectionHandle);
2855 /***********************************************************************
2856 * MmMapLockedPagesSpecifyCache (NTOSKRNL.EXE.@)
2858 PVOID WINAPI MmMapLockedPagesSpecifyCache(PMDLX MemoryDescriptorList, KPROCESSOR_MODE AccessMode, MEMORY_CACHING_TYPE CacheType,
2859 PVOID BaseAddress, ULONG BugCheckOnFailure, MM_PAGE_PRIORITY Priority)
2861 FIXME("(%p, %u, %u, %p, %lu, %u): stub\n", MemoryDescriptorList, AccessMode, CacheType, BaseAddress, BugCheckOnFailure, Priority);
2863 return NULL;
2866 /***********************************************************************
2867 * MmUnmapLockedPages (NTOSKRNL.EXE.@)
2869 void WINAPI MmUnmapLockedPages( void *base, MDL *mdl )
2871 FIXME( "(%p %p_\n", base, mdl );
2874 /***********************************************************************
2875 * MmUnlockPagableImageSection (NTOSKRNL.EXE.@)
2877 VOID WINAPI MmUnlockPagableImageSection(PVOID ImageSectionHandle)
2879 FIXME("stub %p\n", ImageSectionHandle);
2882 /***********************************************************************
2883 * MmPageEntireDriver (NTOSKRNL.EXE.@)
2885 PVOID WINAPI MmPageEntireDriver(PVOID AddrInSection)
2887 TRACE("%p\n", AddrInSection);
2888 return AddrInSection;
2892 /***********************************************************************
2893 * MmProbeAndLockPages (NTOSKRNL.EXE.@)
2895 void WINAPI MmProbeAndLockPages(PMDLX MemoryDescriptorList, KPROCESSOR_MODE AccessMode, LOCK_OPERATION Operation)
2897 FIXME("(%p, %u, %u): stub\n", MemoryDescriptorList, AccessMode, Operation);
2901 /***********************************************************************
2902 * MmResetDriverPaging (NTOSKRNL.EXE.@)
2904 void WINAPI MmResetDriverPaging(PVOID AddrInSection)
2906 TRACE("%p\n", AddrInSection);
2910 /***********************************************************************
2911 * MmUnlockPages (NTOSKRNL.EXE.@)
2913 void WINAPI MmUnlockPages(PMDLX MemoryDescriptorList)
2915 FIXME("(%p): stub\n", MemoryDescriptorList);
2919 /***********************************************************************
2920 * MmUnmapIoSpace (NTOSKRNL.EXE.@)
2922 VOID WINAPI MmUnmapIoSpace( PVOID BaseAddress, SIZE_T NumberOfBytes )
2924 FIXME( "stub: %p, %Iu\n", BaseAddress, NumberOfBytes );
2928 /***********************************************************************
2929 * ObReferenceObjectByName (NTOSKRNL.EXE.@)
2931 NTSTATUS WINAPI ObReferenceObjectByName( UNICODE_STRING *ObjectName,
2932 ULONG Attributes,
2933 ACCESS_STATE *AccessState,
2934 ACCESS_MASK DesiredAccess,
2935 POBJECT_TYPE ObjectType,
2936 KPROCESSOR_MODE AccessMode,
2937 void *ParseContext,
2938 void **Object)
2940 struct wine_driver *driver;
2941 struct wine_rb_entry *entry;
2943 TRACE("mostly-stub:%s %li %p %li %p %i %p %p\n", debugstr_us(ObjectName),
2944 Attributes, AccessState, DesiredAccess, ObjectType, AccessMode,
2945 ParseContext, Object);
2947 if (AccessState) FIXME("Unhandled AccessState\n");
2948 if (DesiredAccess) FIXME("Unhandled DesiredAccess\n");
2949 if (ParseContext) FIXME("Unhandled ParseContext\n");
2950 if (ObjectType) FIXME("Unhandled ObjectType\n");
2952 if (AccessMode != KernelMode)
2954 FIXME("UserMode access not implemented\n");
2955 return STATUS_NOT_IMPLEMENTED;
2958 EnterCriticalSection(&drivers_cs);
2959 entry = wine_rb_get(&wine_drivers, ObjectName);
2960 LeaveCriticalSection(&drivers_cs);
2961 if (!entry)
2963 FIXME("Object (%s) not found, may not be tracked.\n", debugstr_us(ObjectName));
2964 return STATUS_NOT_IMPLEMENTED;
2967 driver = WINE_RB_ENTRY_VALUE(entry, struct wine_driver, entry);
2968 ObReferenceObject( *Object = &driver->driver_obj );
2969 return STATUS_SUCCESS;
2973 /********************************************************************
2974 * ObOpenObjectByName (NTOSKRNL.EXE.@)
2976 NTSTATUS WINAPI ObOpenObjectByName(POBJECT_ATTRIBUTES attr, POBJECT_TYPE type,
2977 KPROCESSOR_MODE mode, ACCESS_STATE *access_state,
2978 ACCESS_MASK access, PVOID ctx, HANDLE *handle)
2980 NTSTATUS status;
2981 void *object;
2983 TRACE( "attr(%p %s %lx) %p %u %p %lu %p %p\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
2984 attr->Attributes, type, mode, access_state, access, ctx, handle );
2986 if (mode != KernelMode)
2988 FIXME( "UserMode access not implemented\n" );
2989 return STATUS_NOT_IMPLEMENTED;
2992 if (attr->RootDirectory) FIXME( "RootDirectory unhandled\n" );
2994 status = ObReferenceObjectByName(attr->ObjectName, attr->Attributes, access_state, access, type, mode, ctx, &object );
2995 if (status != STATUS_SUCCESS)
2996 return status;
2998 status = ObOpenObjectByPointer(object, attr->Attributes, access_state, access, type, mode, handle);
3000 ObDereferenceObject(object);
3001 return status;
3005 /***********************************************************************
3006 * ObReferenceObjectByPointer (NTOSKRNL.EXE.@)
3008 NTSTATUS WINAPI ObReferenceObjectByPointer(void *obj, ACCESS_MASK access,
3009 POBJECT_TYPE type,
3010 KPROCESSOR_MODE mode)
3012 FIXME("(%p, %lx, %p, %d): stub\n", obj, access, type, mode);
3014 return STATUS_NOT_IMPLEMENTED;
3018 /***********************************************************************
3019 * ObfReferenceObject (NTOSKRNL.EXE.@)
3021 DEFINE_FASTCALL1_WRAPPER( ObfReferenceObject )
3022 void FASTCALL ObfReferenceObject( void *obj )
3024 ObReferenceObject( obj );
3028 /***********************************************************************
3029 * ObfDereferenceObject (NTOSKRNL.EXE.@)
3031 DEFINE_FASTCALL1_WRAPPER( ObfDereferenceObject )
3032 void FASTCALL ObfDereferenceObject( void *obj )
3034 ObDereferenceObject( obj );
3037 /***********************************************************************
3038 * ObRegisterCallbacks (NTOSKRNL.EXE.@)
3040 NTSTATUS WINAPI ObRegisterCallbacks(POB_CALLBACK_REGISTRATION callback, void **handle)
3042 FIXME( "callback %p, handle %p.\n", callback, handle );
3044 if(handle)
3045 *handle = UlongToHandle(0xdeadbeaf);
3047 return STATUS_SUCCESS;
3050 /***********************************************************************
3051 * ObUnRegisterCallbacks (NTOSKRNL.EXE.@)
3053 void WINAPI ObUnRegisterCallbacks(void *handle)
3055 FIXME( "stub: %p\n", handle );
3058 /***********************************************************************
3059 * ObGetFilterVersion (NTOSKRNL.EXE.@)
3061 USHORT WINAPI ObGetFilterVersion(void)
3063 FIXME( "stub:\n" );
3065 return OB_FLT_REGISTRATION_VERSION;
3068 /***********************************************************************
3069 * IoGetAttachedDeviceReference (NTOSKRNL.EXE.@)
3071 DEVICE_OBJECT* WINAPI IoGetAttachedDeviceReference( DEVICE_OBJECT *device )
3073 DEVICE_OBJECT *result = IoGetAttachedDevice( device );
3074 ObReferenceObject( result );
3075 return result;
3079 /***********************************************************************
3080 * PsCreateSystemThread (NTOSKRNL.EXE.@)
3082 NTSTATUS WINAPI PsCreateSystemThread(PHANDLE ThreadHandle, ULONG DesiredAccess,
3083 POBJECT_ATTRIBUTES ObjectAttributes,
3084 HANDLE ProcessHandle, PCLIENT_ID ClientId,
3085 PKSTART_ROUTINE StartRoutine, PVOID StartContext)
3087 if (!ProcessHandle) ProcessHandle = GetCurrentProcess();
3088 return RtlCreateUserThread(ProcessHandle, 0, FALSE, 0, 0,
3089 0, StartRoutine, StartContext,
3090 ThreadHandle, ClientId);
3093 /***********************************************************************
3094 * PsGetCurrentProcessId (NTOSKRNL.EXE.@)
3096 HANDLE WINAPI PsGetCurrentProcessId(void)
3098 return KeGetCurrentThread()->id.UniqueProcess;
3101 /***********************************************************************
3102 * PsGetCurrentProcessSessionId (NTOSKRNL.EXE.@)
3104 ULONG WINAPI PsGetCurrentProcessSessionId(void)
3106 return PsGetCurrentProcess()->info.PebBaseAddress->SessionId;
3109 /***********************************************************************
3110 * PsGetCurrentThreadId (NTOSKRNL.EXE.@)
3112 HANDLE WINAPI PsGetCurrentThreadId(void)
3114 return KeGetCurrentThread()->id.UniqueThread;
3118 /***********************************************************************
3119 * PsIsSystemThread (NTOSKRNL.EXE.@)
3121 BOOLEAN WINAPI PsIsSystemThread(PETHREAD thread)
3123 return thread->kthread.process == PsInitialSystemProcess;
3127 /***********************************************************************
3128 * PsGetVersion (NTOSKRNL.EXE.@)
3130 BOOLEAN WINAPI PsGetVersion(ULONG *major, ULONG *minor, ULONG *build, UNICODE_STRING *version )
3132 RTL_OSVERSIONINFOEXW info;
3134 info.dwOSVersionInfoSize = sizeof(info);
3135 RtlGetVersion( &info );
3136 if (major) *major = info.dwMajorVersion;
3137 if (minor) *minor = info.dwMinorVersion;
3138 if (build) *build = info.dwBuildNumber;
3140 if (version)
3142 #if 0 /* FIXME: GameGuard passes an uninitialized pointer in version->Buffer */
3143 size_t len = min( lstrlenW(info.szCSDVersion)*sizeof(WCHAR), version->MaximumLength );
3144 memcpy( version->Buffer, info.szCSDVersion, len );
3145 if (len < version->MaximumLength) version->Buffer[len / sizeof(WCHAR)] = 0;
3146 version->Length = len;
3147 #endif
3149 return TRUE;
3153 /***********************************************************************
3154 * PsImpersonateClient (NTOSKRNL.EXE.@)
3156 NTSTATUS WINAPI PsImpersonateClient(PETHREAD Thread, PACCESS_TOKEN Token, BOOLEAN CopyOnOpen,
3157 BOOLEAN EffectiveOnly, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
3159 FIXME("(%p, %p, %u, %u, %u): stub\n", Thread, Token, CopyOnOpen, EffectiveOnly, ImpersonationLevel);
3161 return STATUS_NOT_IMPLEMENTED;
3165 /***********************************************************************
3166 * PsRevertToSelf (NTOSKRNL.EXE.@)
3168 void WINAPI PsRevertToSelf(void)
3170 FIXME("\n");
3174 /***********************************************************************
3175 * PsSetCreateProcessNotifyRoutine (NTOSKRNL.EXE.@)
3177 NTSTATUS WINAPI PsSetCreateProcessNotifyRoutine( PCREATE_PROCESS_NOTIFY_ROUTINE callback, BOOLEAN remove )
3179 FIXME( "stub: %p %d\n", callback, remove );
3180 return STATUS_SUCCESS;
3184 /***********************************************************************
3185 * PsSetCreateProcessNotifyRoutineEx (NTOSKRNL.EXE.@)
3187 NTSTATUS WINAPI PsSetCreateProcessNotifyRoutineEx( PCREATE_PROCESS_NOTIFY_ROUTINE_EX callback, BOOLEAN remove )
3189 FIXME( "stub: %p %d\n", callback, remove );
3190 return STATUS_SUCCESS;
3194 /***********************************************************************
3195 * PsSetCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
3197 NTSTATUS WINAPI PsSetCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
3199 FIXME( "stub: %p\n", NotifyRoutine );
3200 return STATUS_SUCCESS;
3204 /***********************************************************************
3205 * PsRemoveCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
3207 NTSTATUS WINAPI PsRemoveCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
3209 FIXME( "stub: %p\n", NotifyRoutine );
3210 return STATUS_SUCCESS;
3214 /***********************************************************************
3215 * PsRemoveLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
3217 NTSTATUS WINAPI PsRemoveLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine)
3219 unsigned int i;
3221 TRACE("routine %p.\n", routine);
3223 for (i = 0; i < load_image_notify_routine_count; ++i)
3224 if (load_image_notify_routines[i] == routine)
3226 --load_image_notify_routine_count;
3227 memmove(&load_image_notify_routines[i], &load_image_notify_routines[i + 1],
3228 sizeof(*load_image_notify_routines) * (load_image_notify_routine_count - i));
3229 return STATUS_SUCCESS;
3231 return STATUS_PROCEDURE_NOT_FOUND;
3235 /***********************************************************************
3236 * PsReferenceProcessFilePointer (NTOSKRNL.EXE.@)
3238 NTSTATUS WINAPI PsReferenceProcessFilePointer(PEPROCESS process, FILE_OBJECT **file)
3240 FIXME("%p %p\n", process, file);
3241 return STATUS_NOT_IMPLEMENTED;
3245 /***********************************************************************
3246 * PsTerminateSystemThread (NTOSKRNL.EXE.@)
3248 NTSTATUS WINAPI PsTerminateSystemThread(NTSTATUS status)
3250 TRACE("status %#lx.\n", status);
3251 ExitThread( status );
3255 /***********************************************************************
3256 * PsSuspendProcess (NTOSKRNL.EXE.@)
3258 NTSTATUS WINAPI PsSuspendProcess(PEPROCESS process)
3260 FIXME("stub: %p\n", process);
3261 return STATUS_NOT_IMPLEMENTED;
3265 /***********************************************************************
3266 * PsResumeProcess (NTOSKRNL.EXE.@)
3268 NTSTATUS WINAPI PsResumeProcess(PEPROCESS process)
3270 FIXME("stub: %p\n", process);
3271 return STATUS_NOT_IMPLEMENTED;
3275 /***********************************************************************
3276 * MmGetSystemRoutineAddress (NTOSKRNL.EXE.@)
3278 PVOID WINAPI MmGetSystemRoutineAddress(PUNICODE_STRING SystemRoutineName)
3280 HMODULE hMod;
3281 STRING routineNameA;
3282 PVOID pFunc = NULL;
3284 static const WCHAR ntoskrnlW[] = {'n','t','o','s','k','r','n','l','.','e','x','e',0};
3285 static const WCHAR halW[] = {'h','a','l','.','d','l','l',0};
3287 if (!SystemRoutineName) return NULL;
3289 if (RtlUnicodeStringToAnsiString( &routineNameA, SystemRoutineName, TRUE ) == STATUS_SUCCESS)
3291 /* We only support functions exported from ntoskrnl.exe or hal.dll */
3292 hMod = GetModuleHandleW( ntoskrnlW );
3293 pFunc = GetProcAddress( hMod, routineNameA.Buffer );
3294 if (!pFunc)
3296 hMod = GetModuleHandleW( halW );
3298 if (hMod) pFunc = GetProcAddress( hMod, routineNameA.Buffer );
3300 RtlFreeAnsiString( &routineNameA );
3303 if (pFunc)
3304 TRACE( "%s -> %p\n", debugstr_us(SystemRoutineName), pFunc );
3305 else
3306 FIXME( "%s not found\n", debugstr_us(SystemRoutineName) );
3307 return pFunc;
3310 /***********************************************************************
3311 * MmIsThisAnNtAsSystem (NTOSKRNL.EXE.@)
3313 BOOLEAN WINAPI MmIsThisAnNtAsSystem(void)
3315 TRACE("\n");
3316 return FALSE;
3319 /***********************************************************************
3320 * MmProtectMdlSystemAddress (NTOSKRNL.EXE.@)
3322 NTSTATUS WINAPI MmProtectMdlSystemAddress(PMDL MemoryDescriptorList, ULONG NewProtect)
3324 FIXME("(%p, %lu) stub\n", MemoryDescriptorList, NewProtect);
3325 return STATUS_SUCCESS;
3328 /***********************************************************************
3329 * MmQuerySystemSize (NTOSKRNL.EXE.@)
3331 MM_SYSTEMSIZE WINAPI MmQuerySystemSize(void)
3333 FIXME("stub\n");
3334 return MmLargeSystem;
3337 /***********************************************************************
3338 * KeInitializeDpc (NTOSKRNL.EXE.@)
3340 void WINAPI KeInitializeDpc(KDPC *dpc, PKDEFERRED_ROUTINE deferred_routine, void *deferred_context)
3342 FIXME("dpc %p, deferred_routine %p, deferred_context %p semi-stub.\n",
3343 dpc, deferred_routine, deferred_context);
3345 dpc->DeferredRoutine = deferred_routine;
3346 dpc->DeferredContext = deferred_context;
3349 /***********************************************************************
3350 * KeSetImportanceDpc (NTOSKRNL.EXE.@)
3352 VOID WINAPI KeSetImportanceDpc(PRKDPC dpc, KDPC_IMPORTANCE importance)
3354 FIXME("%p, %d stub\n", dpc, importance);
3357 /***********************************************************************
3358 * KeSetTargetProcessorDpc (NTOSKRNL.EXE.@)
3360 VOID WINAPI KeSetTargetProcessorDpc(PRKDPC dpc, CCHAR number)
3362 FIXME("%p, %d stub\n", dpc, number);
3365 /***********************************************************************
3366 * READ_REGISTER_BUFFER_UCHAR (NTOSKRNL.EXE.@)
3368 VOID WINAPI READ_REGISTER_BUFFER_UCHAR(PUCHAR Register, PUCHAR Buffer, ULONG Count)
3370 FIXME("stub\n");
3373 /*****************************************************
3374 * IoWMIRegistrationControl (NTOSKRNL.EXE.@)
3376 NTSTATUS WINAPI IoWMIRegistrationControl(PDEVICE_OBJECT DeviceObject, ULONG Action)
3378 FIXME("(%p %lu) stub\n", DeviceObject, Action);
3379 return STATUS_SUCCESS;
3382 /*****************************************************
3383 * IoWMIOpenBlock (NTOSKRNL.EXE.@)
3385 NTSTATUS WINAPI IoWMIOpenBlock(LPCGUID guid, ULONG desired_access, PVOID *data_block_obj)
3387 FIXME("(%p %lu %p) stub\n", guid, desired_access, data_block_obj);
3388 return STATUS_NOT_IMPLEMENTED;
3391 /*****************************************************
3392 * PsSetLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
3394 NTSTATUS WINAPI PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine)
3396 FIXME("routine %p, semi-stub.\n", routine);
3398 if (load_image_notify_routine_count == ARRAY_SIZE(load_image_notify_routines))
3399 return STATUS_INSUFFICIENT_RESOURCES;
3401 load_image_notify_routines[load_image_notify_routine_count++] = routine;
3403 return STATUS_SUCCESS;
3406 /*****************************************************
3407 * IoSetThreadHardErrorMode (NTOSKRNL.EXE.@)
3409 BOOLEAN WINAPI IoSetThreadHardErrorMode(BOOLEAN EnableHardErrors)
3411 FIXME("stub\n");
3412 return FALSE;
3415 /*****************************************************
3416 * Ke386IoSetAccessProcess (NTOSKRNL.EXE.@)
3418 BOOLEAN WINAPI Ke386IoSetAccessProcess(PEPROCESS *process, ULONG flag)
3420 FIXME("(%p %ld) stub\n", process, flag);
3421 return FALSE;
3424 /*****************************************************
3425 * Ke386SetIoAccessMap (NTOSKRNL.EXE.@)
3427 BOOLEAN WINAPI Ke386SetIoAccessMap(ULONG flag, PVOID buffer)
3429 FIXME("(%ld %p) stub\n", flag, buffer);
3430 return FALSE;
3433 /*****************************************************
3434 * IoStartNextPacket (NTOSKRNL.EXE.@)
3436 VOID WINAPI IoStartNextPacket(PDEVICE_OBJECT deviceobject, BOOLEAN cancelable)
3438 FIXME("(%p %d) stub\n", deviceobject, cancelable);
3441 /*****************************************************
3442 * ObQueryNameString (NTOSKRNL.EXE.@)
3444 NTSTATUS WINAPI ObQueryNameString( void *object, OBJECT_NAME_INFORMATION *name, ULONG size, ULONG *ret_size )
3446 HANDLE handle;
3447 NTSTATUS ret;
3449 TRACE("object %p, name %p, size %lu, ret_size %p.\n", object, name, size, ret_size);
3451 if ((ret = ObOpenObjectByPointer( object, 0, NULL, 0, NULL, KernelMode, &handle )))
3452 return ret;
3453 ret = NtQueryObject( handle, ObjectNameInformation, name, size, ret_size );
3455 NtClose( handle );
3456 return ret;
3459 /*****************************************************
3460 * IoRegisterPlugPlayNotification (NTOSKRNL.EXE.@)
3462 NTSTATUS WINAPI IoRegisterPlugPlayNotification(IO_NOTIFICATION_EVENT_CATEGORY category, ULONG flags, PVOID data,
3463 PDRIVER_OBJECT driver, PDRIVER_NOTIFICATION_CALLBACK_ROUTINE callback,
3464 PVOID context, PVOID *notification)
3466 FIXME("(%u %lu %p %p %p %p %p) stub\n", category, flags, data, driver, callback, context, notification);
3467 return STATUS_SUCCESS;
3470 /*****************************************************
3471 * IoUnregisterPlugPlayNotification (NTOSKRNL.EXE.@)
3473 NTSTATUS WINAPI IoUnregisterPlugPlayNotification(PVOID notification)
3475 FIXME("stub: %p\n", notification);
3476 return STATUS_SUCCESS;
3479 /*****************************************************
3480 * IoCsqInitialize (NTOSKRNL.EXE.@)
3482 NTSTATUS WINAPI IoCsqInitialize(PIO_CSQ csq, PIO_CSQ_INSERT_IRP insert_irp, PIO_CSQ_REMOVE_IRP remove_irp,
3483 PIO_CSQ_PEEK_NEXT_IRP peek_irp, PIO_CSQ_ACQUIRE_LOCK acquire_lock,
3484 PIO_CSQ_RELEASE_LOCK release_lock, PIO_CSQ_COMPLETE_CANCELED_IRP complete_irp)
3486 FIXME("(%p %p %p %p %p %p %p) stub\n",
3487 csq, insert_irp, remove_irp, peek_irp, acquire_lock, release_lock, complete_irp);
3488 return STATUS_SUCCESS;
3491 /***********************************************************************
3492 * KeEnterCriticalRegion (NTOSKRNL.EXE.@)
3494 void WINAPI KeEnterCriticalRegion(void)
3496 TRACE( "semi-stub\n" );
3497 KeGetCurrentThread()->critical_region++;
3500 /***********************************************************************
3501 * KeLeaveCriticalRegion (NTOSKRNL.EXE.@)
3503 void WINAPI KeLeaveCriticalRegion(void)
3505 TRACE( "semi-stub\n" );
3506 KeGetCurrentThread()->critical_region--;
3509 /***********************************************************************
3510 * KeAreApcsDisabled (NTOSKRNL.@)
3512 BOOLEAN WINAPI KeAreApcsDisabled(void)
3514 unsigned int critical_region = KeGetCurrentThread()->critical_region;
3515 TRACE( "%u\n", critical_region );
3516 return !!critical_region;
3519 /***********************************************************************
3520 * KeBugCheck (NTOSKRNL.@)
3522 void WINAPI KeBugCheck(ULONG code)
3524 KeBugCheckEx(code, 0, 0, 0, 0);
3527 /***********************************************************************
3528 * KeBugCheckEx (NTOSKRNL.@)
3530 void WINAPI KeBugCheckEx(ULONG code, ULONG_PTR param1, ULONG_PTR param2, ULONG_PTR param3, ULONG_PTR param4)
3532 ERR( "%lx %Ix %Ix %Ix %Ix\n", code, param1, param2, param3, param4 );
3533 ExitProcess( code );
3536 /***********************************************************************
3537 * ProbeForRead (NTOSKRNL.EXE.@)
3539 void WINAPI ProbeForRead(void *address, SIZE_T length, ULONG alignment)
3541 FIXME("(%p %Iu %lu) stub\n", address, length, alignment);
3544 /***********************************************************************
3545 * ProbeForWrite (NTOSKRNL.EXE.@)
3547 void WINAPI ProbeForWrite(void *address, SIZE_T length, ULONG alignment)
3549 FIXME("(%p %Iu %lu) stub\n", address, length, alignment);
3552 /***********************************************************************
3553 * CmRegisterCallback (NTOSKRNL.EXE.@)
3555 NTSTATUS WINAPI CmRegisterCallback(EX_CALLBACK_FUNCTION *function, void *context, LARGE_INTEGER *cookie)
3557 FIXME("(%p %p %p): stub\n", function, context, cookie);
3558 return STATUS_NOT_IMPLEMENTED;
3561 /***********************************************************************
3562 * CmUnRegisterCallback (NTOSKRNL.EXE.@)
3564 NTSTATUS WINAPI CmUnRegisterCallback(LARGE_INTEGER cookie)
3566 FIXME("(%s): stub\n", wine_dbgstr_longlong(cookie.QuadPart));
3567 return STATUS_NOT_IMPLEMENTED;
3570 /***********************************************************************
3571 * IoAttachDevice (NTOSKRNL.EXE.@)
3573 NTSTATUS WINAPI IoAttachDevice(DEVICE_OBJECT *source, UNICODE_STRING *target, DEVICE_OBJECT *attached)
3575 FIXME("(%p, %s, %p): stub\n", source, debugstr_us(target), attached);
3576 return STATUS_NOT_IMPLEMENTED;
3580 static NTSTATUS open_driver( const UNICODE_STRING *service_name, SC_HANDLE *service )
3582 QUERY_SERVICE_CONFIGW *service_config = NULL;
3583 SC_HANDLE manager_handle;
3584 DWORD config_size = 0;
3585 WCHAR *name;
3587 if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, service_name->Length + sizeof(WCHAR) )))
3588 return STATUS_NO_MEMORY;
3590 memcpy( name, service_name->Buffer, service_name->Length );
3591 name[ service_name->Length / sizeof(WCHAR) ] = 0;
3593 if (wcsncmp( name, servicesW, lstrlenW(servicesW) ))
3595 FIXME( "service name %s is not a keypath\n", debugstr_us(service_name) );
3596 RtlFreeHeap( GetProcessHeap(), 0, name );
3597 return STATUS_NOT_IMPLEMENTED;
3600 if (!(manager_handle = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
3602 WARN( "failed to connect to service manager\n" );
3603 RtlFreeHeap( GetProcessHeap(), 0, name );
3604 return STATUS_NOT_SUPPORTED;
3607 *service = OpenServiceW( manager_handle, name + lstrlenW(servicesW),
3608 SERVICE_QUERY_CONFIG | SERVICE_SET_STATUS );
3609 RtlFreeHeap( GetProcessHeap(), 0, name );
3610 CloseServiceHandle( manager_handle );
3612 if (!*service)
3614 WARN( "failed to open service %s\n", debugstr_us(service_name) );
3615 return STATUS_UNSUCCESSFUL;
3618 QueryServiceConfigW( *service, NULL, 0, &config_size );
3619 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
3621 WARN( "failed to query service config\n" );
3622 goto error;
3625 if (!(service_config = RtlAllocateHeap( GetProcessHeap(), 0, config_size )))
3626 goto error;
3628 if (!QueryServiceConfigW( *service, service_config, config_size, &config_size ))
3630 WARN( "failed to query service config\n" );
3631 goto error;
3634 if (service_config->dwServiceType != SERVICE_KERNEL_DRIVER &&
3635 service_config->dwServiceType != SERVICE_FILE_SYSTEM_DRIVER)
3637 WARN( "service %s is not a kernel driver\n", debugstr_us(service_name) );
3638 goto error;
3641 TRACE( "opened service for driver %s\n", debugstr_us(service_name) );
3642 RtlFreeHeap( GetProcessHeap(), 0, service_config );
3643 return STATUS_SUCCESS;
3645 error:
3646 CloseServiceHandle( *service );
3647 RtlFreeHeap( GetProcessHeap(), 0, service_config );
3648 return STATUS_UNSUCCESSFUL;
3651 /* find the LDR_DATA_TABLE_ENTRY corresponding to the driver module */
3652 static LDR_DATA_TABLE_ENTRY *find_ldr_module( HMODULE module )
3654 LDR_DATA_TABLE_ENTRY *ldr;
3655 ULONG_PTR magic;
3657 LdrLockLoaderLock( 0, NULL, &magic );
3658 if (LdrFindEntryForAddress( module, &ldr ))
3660 WARN( "module not found for %p\n", module );
3661 ldr = NULL;
3663 LdrUnlockLoaderLock( 0, magic );
3665 return ldr;
3668 /* convert PE image VirtualAddress to Real Address */
3669 static inline void *get_rva( HMODULE module, DWORD va )
3671 return (void *)((char *)module + va);
3674 static void WINAPI ldr_notify_callback(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
3676 const IMAGE_DATA_DIRECTORY *relocs;
3677 IMAGE_BASE_RELOCATION *rel, *end;
3678 SYSTEM_BASIC_INFORMATION info;
3679 IMAGE_NT_HEADERS *nt;
3680 INT_PTR delta;
3681 char *base;
3682 HMODULE module;
3684 if (reason != LDR_DLL_NOTIFICATION_REASON_LOADED) return;
3685 TRACE( "loading %s\n", debugstr_us(data->Loaded.BaseDllName));
3687 module = data->Loaded.DllBase;
3688 nt = RtlImageNtHeader( module );
3689 base = (char *)nt->OptionalHeader.ImageBase;
3690 if (!(delta = (char *)module - base)) return;
3692 /* the loader does not apply relocations to non page-aligned binaries or executables,
3693 * we have to do it ourselves */
3695 NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info), NULL );
3696 if (nt->OptionalHeader.SectionAlignment >= info.PageSize && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
3697 return;
3699 if (nt->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
3701 WARN( "Need to relocate module from %p to %p, but there are no relocation records\n", base, module );
3702 return;
3705 relocs = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
3706 if (!relocs->Size || !relocs->VirtualAddress) return;
3708 TRACE( "relocating from %p-%p to %p-%p\n", base, base + nt->OptionalHeader.SizeOfImage,
3709 module, (char *)module + nt->OptionalHeader.SizeOfImage );
3711 rel = get_rva( module, relocs->VirtualAddress );
3712 end = get_rva( module, relocs->VirtualAddress + relocs->Size );
3714 while (rel < end - 1 && rel->SizeOfBlock)
3716 char *page = get_rva( module, rel->VirtualAddress );
3717 DWORD old_prot1, old_prot2;
3719 if (rel->VirtualAddress >= nt->OptionalHeader.SizeOfImage)
3721 WARN( "invalid address %p in relocation %p\n", get_rva( module, rel->VirtualAddress ), rel );
3722 return;
3725 /* Relocation entries may hang over the end of the page, so we need to
3726 * protect two pages. */
3727 VirtualProtect( page, info.PageSize, PAGE_READWRITE, &old_prot1 );
3728 VirtualProtect( page + info.PageSize, info.PageSize, PAGE_READWRITE, &old_prot2 );
3729 rel = LdrProcessRelocationBlock( page, (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
3730 (USHORT *)(rel + 1), delta );
3731 VirtualProtect( page, info.PageSize, old_prot1, &old_prot1 );
3732 VirtualProtect( page + info.PageSize, info.PageSize, old_prot2, &old_prot2 );
3733 if (!rel)
3735 WARN( "LdrProcessRelocationBlock failed\n" );
3736 return;
3741 /* load the .sys module for a device driver */
3742 static HMODULE load_driver( const WCHAR *driver_name, const UNICODE_STRING *keyname )
3744 static const WCHAR driversW[] = {'\\','d','r','i','v','e','r','s','\\',0};
3745 static const WCHAR systemrootW[] = {'\\','S','y','s','t','e','m','R','o','o','t','\\',0};
3746 static const WCHAR postfixW[] = {'.','s','y','s',0};
3747 static const WCHAR ntprefixW[] = {'\\','?','?','\\',0};
3748 static const WCHAR ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
3749 HKEY driver_hkey;
3750 HMODULE module;
3751 LPWSTR path = NULL, str;
3752 DWORD type, size;
3754 if (RegOpenKeyW( HKEY_LOCAL_MACHINE, keyname->Buffer + 18 /* skip \registry\machine */, &driver_hkey ))
3756 ERR( "cannot open key %s, err=%lu\n", wine_dbgstr_w(keyname->Buffer), GetLastError() );
3757 return NULL;
3760 /* read the executable path from memory */
3761 size = 0;
3762 if (!RegQueryValueExW( driver_hkey, ImagePathW, NULL, &type, NULL, &size ))
3764 str = HeapAlloc( GetProcessHeap(), 0, size );
3765 if (!RegQueryValueExW( driver_hkey, ImagePathW, NULL, &type, (LPBYTE)str, &size ))
3767 size = ExpandEnvironmentStringsW(str,NULL,0);
3768 path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
3769 ExpandEnvironmentStringsW(str,path,size);
3771 HeapFree( GetProcessHeap(), 0, str );
3772 if (!path)
3774 RegCloseKey( driver_hkey );
3775 return NULL;
3778 if (!wcsnicmp( path, systemrootW, 12 ))
3780 WCHAR buffer[MAX_PATH];
3782 GetWindowsDirectoryW(buffer, MAX_PATH);
3784 str = HeapAlloc(GetProcessHeap(), 0, (size -11 + lstrlenW(buffer))
3785 * sizeof(WCHAR));
3786 lstrcpyW(str, buffer);
3787 lstrcatW(str, path + 11);
3788 HeapFree( GetProcessHeap(), 0, path );
3789 path = str;
3791 else if (!wcsncmp( path, ntprefixW, 4 ))
3792 str = path + 4;
3793 else
3794 str = path;
3796 else
3798 /* default is to use the driver name + ".sys" */
3799 WCHAR buffer[MAX_PATH];
3800 GetSystemDirectoryW(buffer, MAX_PATH);
3801 path = HeapAlloc(GetProcessHeap(),0,
3802 (lstrlenW(buffer) + lstrlenW(driversW) + lstrlenW(driver_name) + lstrlenW(postfixW) + 1)
3803 *sizeof(WCHAR));
3804 lstrcpyW(path, buffer);
3805 lstrcatW(path, driversW);
3806 lstrcatW(path, driver_name);
3807 lstrcatW(path, postfixW);
3808 str = path;
3810 RegCloseKey( driver_hkey );
3812 TRACE( "loading driver %s\n", wine_dbgstr_w(str) );
3814 module = LoadLibraryExW( str, 0, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS );
3816 if (module && load_image_notify_routine_count)
3818 UNICODE_STRING module_name;
3819 IMAGE_NT_HEADERS *nt;
3820 IMAGE_INFO info;
3821 unsigned int i;
3823 RtlInitUnicodeString(&module_name, str);
3824 nt = RtlImageNtHeader(module);
3825 memset(&info, 0, sizeof(info));
3826 info.u.s.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT;
3827 info.u.s.SystemModeImage = TRUE;
3828 info.ImageSize = nt->OptionalHeader.SizeOfImage;
3829 info.ImageBase = module;
3831 for (i = 0; i < load_image_notify_routine_count; ++i)
3833 TRACE("Calling image load notify %p.\n", load_image_notify_routines[i]);
3834 load_image_notify_routines[i](&module_name, NULL, &info);
3835 TRACE("Called image load notify %p.\n", load_image_notify_routines[i]);
3839 HeapFree( GetProcessHeap(), 0, path );
3840 return module;
3843 /* call the driver init entry point */
3844 static NTSTATUS WINAPI init_driver( DRIVER_OBJECT *driver_object, UNICODE_STRING *keyname )
3846 unsigned int i;
3847 NTSTATUS status;
3848 const IMAGE_NT_HEADERS *nt;
3849 const WCHAR *driver_name;
3850 HMODULE module;
3852 /* Retrieve driver name from the keyname */
3853 driver_name = wcsrchr( keyname->Buffer, '\\' );
3854 driver_name++;
3856 module = load_driver( driver_name, keyname );
3857 if (!module)
3858 return STATUS_DLL_INIT_FAILED;
3860 driver_object->DriverSection = find_ldr_module( module );
3861 driver_object->DriverStart = ((LDR_DATA_TABLE_ENTRY *)driver_object->DriverSection)->DllBase;
3862 driver_object->DriverSize = ((LDR_DATA_TABLE_ENTRY *)driver_object->DriverSection)->SizeOfImage;
3864 nt = RtlImageNtHeader( module );
3865 if (!nt->OptionalHeader.AddressOfEntryPoint) return STATUS_SUCCESS;
3866 driver_object->DriverInit = (PDRIVER_INITIALIZE)((char *)module + nt->OptionalHeader.AddressOfEntryPoint);
3868 TRACE_(relay)( "\1Call driver init %p (obj=%p,str=%s)\n",
3869 driver_object->DriverInit, driver_object, wine_dbgstr_w(keyname->Buffer) );
3871 status = driver_object->DriverInit( driver_object, keyname );
3873 TRACE_(relay)( "\1Ret driver init %p (obj=%p,str=%s) retval=%08lx\n",
3874 driver_object->DriverInit, driver_object, wine_dbgstr_w(keyname->Buffer), status );
3876 TRACE( "init done for %s obj %p\n", wine_dbgstr_w(driver_name), driver_object );
3877 TRACE( "- DriverInit = %p\n", driver_object->DriverInit );
3878 TRACE( "- DriverStartIo = %p\n", driver_object->DriverStartIo );
3879 TRACE( "- DriverUnload = %p\n", driver_object->DriverUnload );
3880 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
3881 TRACE( "- MajorFunction[%d] = %p\n", i, driver_object->MajorFunction[i] );
3883 return status;
3886 static BOOLEAN get_drv_name( UNICODE_STRING *drv_name, const UNICODE_STRING *service_name )
3888 static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0};
3889 WCHAR *str;
3891 if (!(str = heap_alloc( sizeof(driverW) + service_name->Length - lstrlenW(servicesW)*sizeof(WCHAR) )))
3892 return FALSE;
3894 lstrcpyW( str, driverW );
3895 lstrcpynW( str + lstrlenW(driverW), service_name->Buffer + lstrlenW(servicesW),
3896 service_name->Length/sizeof(WCHAR) - lstrlenW(servicesW) + 1 );
3897 RtlInitUnicodeString( drv_name, str );
3898 return TRUE;
3901 /***********************************************************************
3902 * ZwLoadDriver (NTOSKRNL.EXE.@)
3904 NTSTATUS WINAPI ZwLoadDriver( const UNICODE_STRING *service_name )
3906 SERVICE_STATUS_HANDLE service_handle;
3907 struct wine_rb_entry *entry;
3908 struct wine_driver *driver;
3909 UNICODE_STRING drv_name;
3910 NTSTATUS status;
3912 TRACE( "(%s)\n", debugstr_us(service_name) );
3914 if ((status = open_driver( service_name, (SC_HANDLE *)&service_handle )) != STATUS_SUCCESS)
3915 return status;
3917 if (!get_drv_name( &drv_name, service_name ))
3919 CloseServiceHandle( (void *)service_handle );
3920 return STATUS_NO_MEMORY;
3923 if (wine_rb_get( &wine_drivers, &drv_name ))
3925 TRACE( "driver %s already loaded\n", debugstr_us(&drv_name) );
3926 RtlFreeUnicodeString( &drv_name );
3927 CloseServiceHandle( (void *)service_handle );
3928 return STATUS_IMAGE_ALREADY_LOADED;
3931 set_service_status( service_handle, SERVICE_START_PENDING, 0 );
3933 status = IoCreateDriver( &drv_name, init_driver );
3934 entry = wine_rb_get( &wine_drivers, &drv_name );
3935 RtlFreeUnicodeString( &drv_name );
3936 if (status != STATUS_SUCCESS)
3938 ERR( "failed to create driver %s: %08lx\n", debugstr_us(service_name), status );
3939 goto error;
3942 driver = WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry );
3943 driver->service_handle = service_handle;
3945 wine_enumerate_root_devices( service_name->Buffer + wcslen( servicesW ) );
3947 set_service_status( service_handle, SERVICE_RUNNING,
3948 SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN );
3949 return STATUS_SUCCESS;
3951 error:
3952 set_service_status( service_handle, SERVICE_STOPPED, 0 );
3953 CloseServiceHandle( (void *)service_handle );
3954 return status;
3957 /***********************************************************************
3958 * ZwUnloadDriver (NTOSKRNL.EXE.@)
3960 NTSTATUS WINAPI ZwUnloadDriver( const UNICODE_STRING *service_name )
3962 struct wine_rb_entry *entry;
3963 struct wine_driver *driver;
3964 UNICODE_STRING drv_name;
3966 TRACE( "(%s)\n", debugstr_us(service_name) );
3968 if (!get_drv_name( &drv_name, service_name ))
3969 return STATUS_NO_MEMORY;
3971 entry = wine_rb_get( &wine_drivers, &drv_name );
3972 RtlFreeUnicodeString( &drv_name );
3973 if (!entry)
3975 ERR( "failed to locate driver %s\n", debugstr_us(service_name) );
3976 return STATUS_OBJECT_NAME_NOT_FOUND;
3978 driver = WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry );
3980 if (!list_empty( &driver->root_pnp_devices ))
3982 ERR( "cannot unload driver %s which still has running PnP devices\n", debugstr_us(service_name) );
3983 return STATUS_UNSUCCESSFUL;
3986 unload_driver( entry, NULL );
3988 return STATUS_SUCCESS;
3991 /***********************************************************************
3992 * IoCreateFile (NTOSKRNL.EXE.@)
3994 NTSTATUS WINAPI IoCreateFile(HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
3995 IO_STATUS_BLOCK *io, LARGE_INTEGER *alloc_size, ULONG attributes, ULONG sharing,
3996 ULONG disposition, ULONG create_options, VOID *ea_buffer, ULONG ea_length,
3997 CREATE_FILE_TYPE file_type, VOID *parameters, ULONG options )
3999 FIXME(": stub\n");
4000 return STATUS_NOT_IMPLEMENTED;
4003 /***********************************************************************
4004 * IoCreateNotificationEvent (NTOSKRNL.EXE.@)
4006 PKEVENT WINAPI IoCreateNotificationEvent(UNICODE_STRING *name, HANDLE *handle)
4008 FIXME( "stub: %s %p\n", debugstr_us(name), handle );
4009 return NULL;
4013 /**************************************************************************
4014 * __chkstk (NTOSKRNL.@)
4016 #ifdef __x86_64__
4017 /* Supposed to touch all the stack pages, but we shouldn't need that. */
4018 __ASM_GLOBAL_FUNC( __chkstk, "ret" );
4019 #elif defined(__i386__)
4020 __ASM_GLOBAL_FUNC( _chkstk,
4021 "negl %eax\n\t"
4022 "addl %esp,%eax\n\t"
4023 "xchgl %esp,%eax\n\t"
4024 "movl 0(%eax),%eax\n\t" /* copy return address from old location */
4025 "movl %eax,0(%esp)\n\t"
4026 "ret" )
4027 #elif defined(__arm__)
4028 /* Incoming r4 contains words to allocate, converting to bytes then return */
4029 __ASM_GLOBAL_FUNC( __chkstk, "lsl r4, r4, #2\n\t"
4030 "bx lr" )
4031 #elif defined(__aarch64__)
4032 /* Supposed to touch all the stack pages, but we shouldn't need that. */
4033 __ASM_GLOBAL_FUNC( __chkstk, "ret" );
4034 #endif
4036 /*********************************************************************
4037 * PsAcquireProcessExitSynchronization (NTOSKRNL.@)
4039 NTSTATUS WINAPI PsAcquireProcessExitSynchronization(PEPROCESS process)
4041 FIXME("stub: %p\n", process);
4043 return STATUS_NOT_IMPLEMENTED;
4046 /*********************************************************************
4047 * PsReleaseProcessExitSynchronization (NTOSKRNL.@)
4049 void WINAPI PsReleaseProcessExitSynchronization(PEPROCESS process)
4051 FIXME("stub: %p\n", process);
4054 typedef struct _EX_PUSH_LOCK_WAIT_BLOCK *PEX_PUSH_LOCK_WAIT_BLOCK;
4055 /*********************************************************************
4056 * ExfUnblockPushLock (NTOSKRNL.@)
4058 DEFINE_FASTCALL_WRAPPER( ExfUnblockPushLock, 8 )
4059 void FASTCALL ExfUnblockPushLock( EX_PUSH_LOCK *lock, PEX_PUSH_LOCK_WAIT_BLOCK block )
4061 FIXME( "stub: %p, %p\n", lock, block );
4064 /*********************************************************************
4065 * FsRtlRegisterFileSystemFilterCallbacks (NTOSKRNL.@)
4067 NTSTATUS WINAPI FsRtlRegisterFileSystemFilterCallbacks( DRIVER_OBJECT *object, PFS_FILTER_CALLBACKS callbacks)
4069 FIXME("stub: %p %p\n", object, callbacks);
4070 return STATUS_NOT_IMPLEMENTED;
4073 /*********************************************************************
4074 * SeSinglePrivilegeCheck (NTOSKRNL.@)
4076 BOOLEAN WINAPI SeSinglePrivilegeCheck(LUID privilege, KPROCESSOR_MODE mode)
4078 static int once;
4079 if (!once++) FIXME("stub: %08lx%08lx %u\n", privilege.HighPart, privilege.LowPart, mode);
4080 return TRUE;
4083 /*********************************************************************
4084 * SePrivilegeCheck (NTOSKRNL.@)
4086 BOOLEAN WINAPI SePrivilegeCheck(PRIVILEGE_SET *privileges, SECURITY_SUBJECT_CONTEXT *context, KPROCESSOR_MODE mode)
4088 FIXME("stub: %p %p %u\n", privileges, context, mode);
4089 return TRUE;
4092 /*********************************************************************
4093 * SeLocateProcessImageName (NTOSKRNL.@)
4095 NTSTATUS WINAPI SeLocateProcessImageName(PEPROCESS process, UNICODE_STRING **image_name)
4097 FIXME("stub: %p %p\n", process, image_name);
4098 if (image_name) *image_name = NULL;
4099 return STATUS_NOT_IMPLEMENTED;
4102 /*********************************************************************
4103 * KeFlushQueuedDpcs (NTOSKRNL.@)
4105 void WINAPI KeFlushQueuedDpcs(void)
4107 FIXME("stub!\n");
4110 /*********************************************************************
4111 * DbgQueryDebugFilterState (NTOSKRNL.@)
4113 NTSTATUS WINAPI DbgQueryDebugFilterState(ULONG component, ULONG level)
4115 FIXME("stub: %ld %ld\n", component, level);
4116 return STATUS_NOT_IMPLEMENTED;
4119 /*********************************************************************
4120 * PsGetProcessWow64Process (NTOSKRNL.@)
4122 PVOID WINAPI PsGetProcessWow64Process(PEPROCESS process)
4124 FIXME("stub: %p\n", process);
4125 return NULL;
4128 /*********************************************************************
4129 * MmCopyVirtualMemory (NTOSKRNL.@)
4131 NTSTATUS WINAPI MmCopyVirtualMemory(PEPROCESS fromprocess, void *fromaddress, PEPROCESS toprocess,
4132 void *toaddress, SIZE_T bufsize, KPROCESSOR_MODE mode,
4133 SIZE_T *copied)
4135 FIXME("fromprocess %p, fromaddress %p, toprocess %p, toaddress %p, bufsize %Iu, mode %d, copied %p stub.\n",
4136 fromprocess, fromaddress, toprocess, toaddress, bufsize, mode, copied);
4138 *copied = 0;
4139 return STATUS_NOT_IMPLEMENTED;
4142 /*********************************************************************
4143 * KeEnterGuardedRegion (NTOSKRNL.@)
4145 void WINAPI KeEnterGuardedRegion(void)
4147 FIXME("\n");
4150 /*********************************************************************
4151 * KeLeaveGuardedRegion (NTOSKRNL.@)
4153 void WINAPI KeLeaveGuardedRegion(void)
4155 FIXME("\n");
4158 static const WCHAR token_type_name[] = {'T','o','k','e','n',0};
4160 static struct _OBJECT_TYPE token_type =
4162 token_type_name
4165 POBJECT_TYPE SeTokenObjectType = &token_type;
4167 /*************************************************************************
4168 * ExUuidCreate (NTOSKRNL.@)
4170 * Creates a 128bit UUID.
4172 * RETURNS
4174 * STATUS_SUCCESS if successful.
4175 * RPC_NT_UUID_LOCAL_ONLY if UUID is only locally unique.
4177 * NOTES
4179 * Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
4180 * Truly Random or Pseudo-Random Numbers)
4182 NTSTATUS WINAPI ExUuidCreate(UUID *uuid)
4184 RtlGenRandom(uuid, sizeof(*uuid));
4185 /* Clear the version bits and set the version (4) */
4186 uuid->Data3 &= 0x0fff;
4187 uuid->Data3 |= (4 << 12);
4188 /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
4189 * specified in RFC 4122, section 4.4.
4191 uuid->Data4[0] &= 0x3f;
4192 uuid->Data4[0] |= 0x80;
4194 TRACE("%s\n", debugstr_guid(uuid));
4196 return STATUS_SUCCESS;
4199 /***********************************************************************
4200 * ExSetTimerResolution (NTOSKRNL.EXE.@)
4202 ULONG WINAPI ExSetTimerResolution(ULONG time, BOOLEAN set_resolution)
4204 FIXME("stub: %lu %d\n", time, set_resolution);
4205 return KeQueryTimeIncrement();
4208 /***********************************************************************
4209 * IoGetRequestorProcess (NTOSKRNL.EXE.@)
4211 PEPROCESS WINAPI IoGetRequestorProcess(IRP *irp)
4213 TRACE("irp %p.\n", irp);
4214 return irp->Tail.Overlay.Thread->kthread.process;
4217 #ifdef _WIN64
4218 /***********************************************************************
4219 * IoIs32bitProcess (NTOSKRNL.EXE.@)
4221 BOOLEAN WINAPI IoIs32bitProcess(IRP *irp)
4223 TRACE("irp %p.\n", irp);
4224 return irp->Tail.Overlay.Thread->kthread.process->wow64;
4226 #endif
4228 /***********************************************************************
4229 * RtlIsNtDdiVersionAvailable (NTOSKRNL.EXE.@)
4231 BOOLEAN WINAPI RtlIsNtDdiVersionAvailable(ULONG version)
4233 FIXME("stub: %ld\n", version);
4234 return FALSE;
4237 BOOLEAN WINAPI KdRefreshDebuggerNotPresent(void)
4239 TRACE(".\n");
4241 return !KdDebuggerEnabled;
4244 struct generic_call_dpc_context
4246 DEFERRED_REVERSE_BARRIER *reverse_barrier;
4247 PKDEFERRED_ROUTINE routine;
4248 ULONG *cpu_count_barrier;
4249 void *context;
4250 ULONG cpu_index;
4251 ULONG current_barrier_flag;
4252 LONG *barrier_passed_count;
4255 static void WINAPI generic_call_dpc_callback(TP_CALLBACK_INSTANCE *instance, void *context)
4257 struct generic_call_dpc_context *c = context;
4258 GROUP_AFFINITY old, new;
4260 TRACE("instance %p, context %p.\n", instance, context);
4262 NtQueryInformationThread(GetCurrentThread(), ThreadGroupInformation,
4263 &old, sizeof(old), NULL);
4265 memset(&new, 0, sizeof(new));
4267 new.Mask = 1 << c->cpu_index;
4268 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation, &new, sizeof(new));
4270 TlsSetValue(dpc_call_tls_index, context);
4271 c->routine((PKDPC)0xdeadbeef, c->context, c->cpu_count_barrier, c->reverse_barrier);
4272 TlsSetValue(dpc_call_tls_index, NULL);
4273 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation, &old, sizeof(old));
4276 void WINAPI KeGenericCallDpc(PKDEFERRED_ROUTINE routine, void *context)
4278 ULONG cpu_count = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
4279 static struct generic_call_dpc_context *contexts;
4280 DEFERRED_REVERSE_BARRIER reverse_barrier;
4281 static ULONG last_cpu_count;
4282 LONG barrier_passed_count;
4283 ULONG cpu_count_barrier;
4284 ULONG i;
4286 TRACE("routine %p, context %p.\n", routine, context);
4288 EnterCriticalSection(&dpc_call_cs);
4290 if (!dpc_call_tp)
4292 if (!(dpc_call_tp = CreateThreadpool(NULL)))
4294 ERR("Could not create thread pool.\n");
4295 LeaveCriticalSection(&dpc_call_cs);
4296 return;
4299 SetThreadpoolThreadMinimum(dpc_call_tp, cpu_count);
4300 SetThreadpoolThreadMaximum(dpc_call_tp, cpu_count);
4302 memset(&dpc_call_tpe, 0, sizeof(dpc_call_tpe));
4303 dpc_call_tpe.Version = 1;
4304 dpc_call_tpe.Pool = dpc_call_tp;
4307 reverse_barrier.Barrier = cpu_count;
4308 reverse_barrier.TotalProcessors = cpu_count;
4309 cpu_count_barrier = cpu_count;
4311 if (contexts)
4313 if (last_cpu_count < cpu_count)
4315 static struct generic_call_dpc_context *new_contexts;
4316 if (!(new_contexts = heap_realloc(contexts, sizeof(*contexts) * cpu_count)))
4318 ERR("No memory.\n");
4319 LeaveCriticalSection(&dpc_call_cs);
4320 return;
4322 contexts = new_contexts;
4323 SetThreadpoolThreadMinimum(dpc_call_tp, cpu_count);
4324 SetThreadpoolThreadMaximum(dpc_call_tp, cpu_count);
4327 else if (!(contexts = heap_alloc(sizeof(*contexts) * cpu_count)))
4329 ERR("No memory.\n");
4330 LeaveCriticalSection(&dpc_call_cs);
4331 return;
4334 memset(contexts, 0, sizeof(*contexts) * cpu_count);
4335 last_cpu_count = cpu_count;
4336 barrier_passed_count = 0;
4338 for (i = 0; i < cpu_count; ++i)
4340 contexts[i].reverse_barrier = &reverse_barrier;
4341 contexts[i].cpu_count_barrier = &cpu_count_barrier;
4342 contexts[i].routine = routine;
4343 contexts[i].context = context;
4344 contexts[i].cpu_index = i;
4345 contexts[i].barrier_passed_count = &barrier_passed_count;
4347 TrySubmitThreadpoolCallback(generic_call_dpc_callback, &contexts[i], &dpc_call_tpe);
4350 while (InterlockedCompareExchange((LONG *)&cpu_count_barrier, 0, 0))
4351 SwitchToThread();
4353 LeaveCriticalSection(&dpc_call_cs);
4357 BOOLEAN WINAPI KeSignalCallDpcSynchronize(void *barrier)
4359 struct generic_call_dpc_context *context = TlsGetValue(dpc_call_tls_index);
4360 DEFERRED_REVERSE_BARRIER *b = barrier;
4361 LONG curr_flag, comp, done_value;
4362 BOOL first;
4364 TRACE("barrier %p, context %p.\n", barrier, context);
4366 if (!context)
4368 WARN("Called outside of DPC context.\n");
4369 return FALSE;
4372 context->current_barrier_flag ^= 0x80000000;
4373 curr_flag = context->current_barrier_flag;
4375 first = !context->cpu_index;
4376 comp = curr_flag + context->cpu_index;
4377 done_value = curr_flag + b->TotalProcessors;
4379 if (first)
4380 InterlockedExchange((LONG *)&b->Barrier, comp);
4382 while (InterlockedCompareExchange((LONG *)&b->Barrier, comp + 1, comp) != done_value)
4385 InterlockedIncrement(context->barrier_passed_count);
4387 while (first && InterlockedCompareExchange(context->barrier_passed_count, 0, b->TotalProcessors))
4390 return first;
4393 void WINAPI KeSignalCallDpcDone(void *barrier)
4395 InterlockedDecrement((LONG *)barrier);
4398 void * WINAPI PsGetProcessSectionBaseAddress(PEPROCESS process)
4400 void *image_base;
4401 NTSTATUS status;
4402 SIZE_T size;
4403 HANDLE h;
4405 TRACE("process %p.\n", process);
4407 if ((status = ObOpenObjectByPointer(process, 0, NULL, PROCESS_ALL_ACCESS, NULL, KernelMode, &h)))
4409 WARN("Error opening process object, status %#lx.\n", status);
4410 return NULL;
4413 status = NtReadVirtualMemory(h, &process->info.PebBaseAddress->ImageBaseAddress,
4414 &image_base, sizeof(image_base), &size);
4416 NtClose(h);
4418 if (status || size != sizeof(image_base))
4420 WARN("Error reading process memory, status %#lx, size %Iu.\n", status, size);
4421 return NULL;
4424 TRACE("returning %p.\n", image_base);
4425 return image_base;
4428 void WINAPI KeStackAttachProcess(KPROCESS *process, KAPC_STATE *apc_state)
4430 FIXME("process %p, apc_state %p stub.\n", process, apc_state);
4433 void WINAPI KeUnstackDetachProcess(KAPC_STATE *apc_state)
4435 FIXME("apc_state %p stub.\n", apc_state);
4438 NTSTATUS WINAPI KdDisableDebugger(void)
4440 FIXME(": stub.\n");
4441 return STATUS_DEBUGGER_INACTIVE;
4444 NTSTATUS WINAPI KdEnableDebugger(void)
4446 FIXME(": stub.\n");
4447 return STATUS_DEBUGGER_INACTIVE;
4450 /*****************************************************
4451 * DllMain
4453 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
4455 static void *handler;
4456 LARGE_INTEGER count;
4458 switch(reason)
4460 case DLL_PROCESS_ATTACH:
4461 DisableThreadLibraryCalls( inst );
4462 #if defined(__i386__) || defined(__x86_64__)
4463 handler = RtlAddVectoredExceptionHandler( TRUE, vectored_handler );
4464 #endif
4465 KeQueryTickCount( &count ); /* initialize the global KeTickCount */
4466 NtBuildNumber = NtCurrentTeb()->Peb->OSBuildNumber;
4467 ntoskrnl_heap = HeapCreate( HEAP_CREATE_ENABLE_EXECUTE, 0, 0 );
4468 dpc_call_tls_index = TlsAlloc();
4469 LdrRegisterDllNotification( 0, ldr_notify_callback, NULL, &ldr_notify_cookie );
4470 break;
4471 case DLL_PROCESS_DETACH:
4472 LdrUnregisterDllNotification( ldr_notify_cookie );
4474 if (reserved) break;
4476 if (dpc_call_tp)
4477 CloseThreadpool(dpc_call_tp);
4479 HeapDestroy( ntoskrnl_heap );
4480 RtlRemoveVectoredExceptionHandler( handler );
4481 break;
4483 return TRUE;