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
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
31 #define WIN32_NO_STATUS
41 #include "ddk/ntddk.h"
42 #include "ddk/ntifs.h"
44 #include "wine/server.h"
45 #include "wine/debug.h"
46 #include "wine/heap.h"
47 #include "wine/rbtree.h"
48 #include "wine/svcctl.h"
50 #include "ntoskrnl_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl
);
53 WINE_DECLARE_DEBUG_CHANNEL(relay
);
55 BOOLEAN KdDebuggerEnabled
= FALSE
;
56 ULONG InitSafeBootMode
= 0;
57 USHORT NtBuildNumber
= 0;
59 extern LONG CALLBACK
vectored_handler( EXCEPTION_POINTERS
*ptrs
);
61 KSYSTEM_TIME KeTickCount
= { 0, 0, 0 };
63 typedef struct _KSERVICE_TABLE_DESCRIPTOR
69 } KSERVICE_TABLE_DESCRIPTOR
, *PKSERVICE_TABLE_DESCRIPTOR
;
71 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable
[4] = { { 0 } };
73 #define MAX_SERVICE_NAME 260
75 static TP_POOL
*dpc_call_tp
;
76 static TP_CALLBACK_ENVIRON dpc_call_tpe
;
77 DECLARE_CRITICAL_SECTION(dpc_call_cs
);
78 static DWORD dpc_call_tls_index
;
80 /* tid of the thread running client request */
81 static DWORD request_thread
;
83 /* tid of the client thread */
84 static DWORD client_tid
;
86 static HANDLE ntoskrnl_heap
;
88 static void *ldr_notify_cookie
;
90 static PLOAD_IMAGE_NOTIFY_ROUTINE load_image_notify_routines
[8];
91 static unsigned int load_image_notify_routine_count
;
95 DRIVER_OBJECT driver_obj
;
96 DRIVER_EXTENSION driver_extension
;
97 SERVICE_STATUS_HANDLE service_handle
;
98 struct wine_rb_entry entry
;
101 static int wine_drivers_rb_compare( const void *key
, const struct wine_rb_entry
*entry
)
103 const struct wine_driver
*driver
= WINE_RB_ENTRY_VALUE( entry
, const struct wine_driver
, entry
);
104 const UNICODE_STRING
*k
= key
;
106 return RtlCompareUnicodeString( k
, &driver
->driver_obj
.DriverName
, TRUE
);
109 static struct wine_rb_tree wine_drivers
= { wine_drivers_rb_compare
};
111 DECLARE_CRITICAL_SECTION(drivers_cs
);
113 static HANDLE
get_device_manager(void)
115 static HANDLE device_manager
;
116 HANDLE handle
= 0, ret
= device_manager
;
120 SERVER_START_REQ( create_device_manager
)
122 req
->access
= SYNCHRONIZE
;
124 if (!wine_server_call( req
)) handle
= wine_server_ptr_handle( reply
->handle
);
130 ERR( "failed to create the device manager\n" );
133 if (!(ret
= InterlockedCompareExchangePointer( &device_manager
, handle
, 0 )))
136 NtClose( handle
); /* somebody beat us to it */
148 static void free_kernel_object( void *obj
)
150 struct object_header
*header
= (struct object_header
*)obj
- 1;
151 HeapFree( GetProcessHeap(), 0, header
);
154 void *alloc_kernel_object( POBJECT_TYPE type
, HANDLE handle
, SIZE_T size
, LONG ref
)
156 struct object_header
*header
;
158 if (!(header
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*header
) + size
)) )
164 SERVER_START_REQ( set_kernel_object_ptr
)
166 req
->manager
= wine_server_obj_handle( get_device_manager() );
167 req
->handle
= wine_server_obj_handle( handle
);
168 req
->user_ptr
= wine_server_client_ptr( header
+ 1 );
169 status
= wine_server_call( req
);
172 if (status
) FIXME( "set_object_reference failed: %#x\n", status
);
180 DECLARE_CRITICAL_SECTION(obref_cs
);
182 /***********************************************************************
183 * ObDereferenceObject (NTOSKRNL.EXE.@)
185 void WINAPI
ObDereferenceObject( void *obj
)
187 struct object_header
*header
= (struct object_header
*)obj
- 1;
196 EnterCriticalSection( &obref_cs
);
199 TRACE( "(%p) ref=%u\n", obj
, ref
);
202 if (header
->type
->release
)
204 header
->type
->release( obj
);
208 SERVER_START_REQ( release_kernel_object
)
210 req
->manager
= wine_server_obj_handle( get_device_manager() );
211 req
->user_ptr
= wine_server_client_ptr( obj
);
212 if (wine_server_call( req
)) FIXME( "failed to release %p\n", obj
);
218 LeaveCriticalSection( &obref_cs
);
221 void ObReferenceObject( void *obj
)
223 struct object_header
*header
= (struct object_header
*)obj
- 1;
232 EnterCriticalSection( &obref_cs
);
235 TRACE( "(%p) ref=%u\n", obj
, ref
);
238 SERVER_START_REQ( grab_kernel_object
)
240 req
->manager
= wine_server_obj_handle( get_device_manager() );
241 req
->user_ptr
= wine_server_client_ptr( obj
);
242 if (wine_server_call( req
)) FIXME( "failed to grab %p reference\n", obj
);
247 LeaveCriticalSection( &obref_cs
);
250 /***********************************************************************
251 * ObGetObjectType (NTOSKRNL.EXE.@)
253 POBJECT_TYPE WINAPI
ObGetObjectType( void *object
)
255 struct object_header
*header
= (struct object_header
*)object
- 1;
259 static const POBJECT_TYPE
*known_types
[] =
262 &ExSemaphoreObjectType
,
271 DECLARE_CRITICAL_SECTION(handle_map_cs
);
273 NTSTATUS
kernel_object_from_handle( HANDLE handle
, POBJECT_TYPE type
, void **ret
)
278 EnterCriticalSection( &handle_map_cs
);
280 SERVER_START_REQ( get_kernel_object_ptr
)
282 req
->manager
= wine_server_obj_handle( get_device_manager() );
283 req
->handle
= wine_server_obj_handle( handle
);
284 status
= wine_server_call( req
);
285 obj
= wine_server_get_ptr( reply
->user_ptr
);
290 LeaveCriticalSection( &handle_map_cs
);
297 OBJECT_TYPE_INFORMATION
*type_info
= (OBJECT_TYPE_INFORMATION
*)buf
;
300 status
= NtQueryObject( handle
, ObjectTypeInformation
, buf
, sizeof(buf
), &size
);
303 LeaveCriticalSection( &handle_map_cs
);
309 for (i
= 0; i
< ARRAY_SIZE(known_types
); i
++)
311 type
= *known_types
[i
];
312 if (!RtlCompareUnicodeStrings( type
->name
, lstrlenW(type
->name
), type_info
->TypeName
.Buffer
,
313 type_info
->TypeName
.Length
/ sizeof(WCHAR
), FALSE
))
316 if (i
== ARRAY_SIZE(known_types
))
318 FIXME("Unsupported type %s\n", debugstr_us(&type_info
->TypeName
));
319 LeaveCriticalSection( &handle_map_cs
);
320 return STATUS_INVALID_HANDLE
;
323 else if (RtlCompareUnicodeStrings( type
->name
, lstrlenW(type
->name
), type_info
->TypeName
.Buffer
,
324 type_info
->TypeName
.Length
/ sizeof(WCHAR
), FALSE
) )
326 LeaveCriticalSection( &handle_map_cs
);
327 return STATUS_OBJECT_TYPE_MISMATCH
;
330 if (type
->constructor
)
331 obj
= type
->constructor( handle
);
334 FIXME( "No constructor for type %s\n", debugstr_w(type
->name
) );
335 obj
= alloc_kernel_object( type
, handle
, 0, 0 );
337 if (!obj
) status
= STATUS_NO_MEMORY
;
339 else if (type
&& ObGetObjectType( obj
) != type
) status
= STATUS_OBJECT_TYPE_MISMATCH
;
341 LeaveCriticalSection( &handle_map_cs
);
342 if (!status
) *ret
= obj
;
346 /***********************************************************************
347 * ObReferenceObjectByHandle (NTOSKRNL.EXE.@)
349 NTSTATUS WINAPI
ObReferenceObjectByHandle( HANDLE handle
, ACCESS_MASK access
,
351 KPROCESSOR_MODE mode
, void **ptr
,
352 POBJECT_HANDLE_INFORMATION info
)
356 TRACE( "%p %x %p %d %p %p\n", handle
, access
, type
, mode
, ptr
, info
);
358 if (mode
!= KernelMode
)
360 FIXME("UserMode access not implemented\n");
361 return STATUS_NOT_IMPLEMENTED
;
364 status
= kernel_object_from_handle( handle
, type
, ptr
);
365 if (!status
) ObReferenceObject( *ptr
);
369 /***********************************************************************
370 * ObOpenObjectByPointer (NTOSKRNL.EXE.@)
372 NTSTATUS WINAPI
ObOpenObjectByPointer( void *obj
, ULONG attr
, ACCESS_STATE
*access_state
,
373 ACCESS_MASK access
, POBJECT_TYPE type
,
374 KPROCESSOR_MODE mode
, HANDLE
*handle
)
378 TRACE( "%p %x %p %x %p %d %p\n", obj
, attr
, access_state
, access
, type
, mode
, handle
);
380 if (mode
!= KernelMode
)
382 FIXME( "UserMode access not implemented\n" );
383 return STATUS_NOT_IMPLEMENTED
;
386 if (attr
& ~OBJ_KERNEL_HANDLE
) FIXME( "attr %#x not supported\n", attr
);
387 if (access_state
) FIXME( "access_state not implemented\n" );
389 if (type
&& ObGetObjectType( obj
) != type
) return STATUS_OBJECT_TYPE_MISMATCH
;
391 SERVER_START_REQ( get_kernel_object_handle
)
393 req
->manager
= wine_server_obj_handle( get_device_manager() );
394 req
->user_ptr
= wine_server_client_ptr( obj
);
395 req
->access
= access
;
396 if (!(status
= wine_server_call( req
)))
397 *handle
= wine_server_ptr_handle( reply
->handle
);
404 static void *create_file_object( HANDLE handle
);
406 static const WCHAR file_type_name
[] = {'F','i','l','e',0};
408 static struct _OBJECT_TYPE file_type
= {
413 POBJECT_TYPE IoFileObjectType
= &file_type
;
415 static void *create_file_object( HANDLE handle
)
418 if (!(file
= alloc_kernel_object( IoFileObjectType
, handle
, sizeof(*file
), 0 ))) return NULL
;
419 file
->Type
= 5; /* MSDN */
420 file
->Size
= sizeof(*file
);
424 DECLARE_CRITICAL_SECTION(irp_completion_cs
);
426 static void WINAPI
cancel_completed_irp( DEVICE_OBJECT
*device
, IRP
*irp
)
428 TRACE( "(%p %p)\n", device
, irp
);
430 IoReleaseCancelSpinLock(irp
->CancelIrql
);
432 irp
->IoStatus
.u
.Status
= STATUS_CANCELLED
;
433 irp
->IoStatus
.Information
= 0;
434 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
437 /* transfer result of IRP back to wineserver */
438 static NTSTATUS WINAPI
dispatch_irp_completion( DEVICE_OBJECT
*device
, IRP
*irp
, void *context
)
440 HANDLE irp_handle
= context
;
441 void *out_buff
= irp
->UserBuffer
;
444 if (irp
->Flags
& IRP_WRITE_OPERATION
)
445 out_buff
= NULL
; /* do not transfer back input buffer */
447 EnterCriticalSection( &irp_completion_cs
);
449 SERVER_START_REQ( set_irp_result
)
451 req
->handle
= wine_server_obj_handle( irp_handle
);
452 req
->status
= irp
->IoStatus
.u
.Status
;
453 req
->size
= irp
->IoStatus
.Information
;
454 if (!NT_ERROR(irp
->IoStatus
.u
.Status
))
456 if (out_buff
) wine_server_add_data( req
, out_buff
, irp
->IoStatus
.Information
);
458 status
= wine_server_call( req
);
462 if (status
== STATUS_MORE_PROCESSING_REQUIRED
)
464 /* IRP is complete, but server may have already ordered cancel call. In such case,
465 * it will return STATUS_MORE_PROCESSING_REQUIRED, leaving the IRP alive until
466 * cancel frees it. */
468 status
= STATUS_SUCCESS
;
470 IoSetCancelRoutine( irp
, cancel_completed_irp
);
473 if (irp
->UserBuffer
!= irp
->AssociatedIrp
.SystemBuffer
)
475 HeapFree( GetProcessHeap(), 0, irp
->UserBuffer
);
476 irp
->UserBuffer
= NULL
;
479 LeaveCriticalSection( &irp_completion_cs
);
483 struct dispatch_context
492 static void dispatch_irp( DEVICE_OBJECT
*device
, IRP
*irp
, struct dispatch_context
*context
)
496 IoSetCompletionRoutine( irp
, dispatch_irp_completion
, context
->handle
, TRUE
, TRUE
, TRUE
);
499 KeQueryTickCount( &count
); /* update the global KeTickCount */
502 device
->CurrentIrp
= irp
;
503 KeEnterCriticalRegion();
504 IoCallDriver( device
, irp
);
505 KeLeaveCriticalRegion();
506 device
->CurrentIrp
= NULL
;
509 /* process a create request for a given file */
510 static NTSTATUS
dispatch_create( struct dispatch_context
*context
)
513 IO_STACK_LOCATION
*irpsp
;
515 DEVICE_OBJECT
*device
= wine_server_get_ptr( context
->params
.create
.device
);
516 HANDLE handle
= wine_server_ptr_handle( context
->params
.create
.file
);
518 if (!(file
= alloc_kernel_object( IoFileObjectType
, handle
, sizeof(*file
), 0 )))
519 return STATUS_NO_MEMORY
;
521 TRACE( "device %p -> file %p\n", device
, file
);
523 file
->Type
= 5; /* MSDN */
524 file
->Size
= sizeof(*file
);
525 file
->DeviceObject
= device
;
527 device
= IoGetAttachedDevice( device
);
529 if (!(irp
= IoAllocateIrp( device
->StackSize
, FALSE
))) return STATUS_NO_MEMORY
;
531 irpsp
= IoGetNextIrpStackLocation( irp
);
532 irpsp
->MajorFunction
= IRP_MJ_CREATE
;
533 irpsp
->FileObject
= file
;
534 irpsp
->Parameters
.Create
.SecurityContext
= NULL
; /* FIXME */
535 irpsp
->Parameters
.Create
.Options
= context
->params
.create
.options
;
536 irpsp
->Parameters
.Create
.ShareAccess
= context
->params
.create
.sharing
;
537 irpsp
->Parameters
.Create
.FileAttributes
= 0;
538 irpsp
->Parameters
.Create
.EaLength
= 0;
540 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
541 irp
->Tail
.Overlay
.Thread
= (PETHREAD
)KeGetCurrentThread();
542 irp
->RequestorMode
= UserMode
;
543 irp
->AssociatedIrp
.SystemBuffer
= NULL
;
544 irp
->UserBuffer
= NULL
;
545 irp
->UserIosb
= NULL
;
546 irp
->UserEvent
= NULL
;
548 irp
->Flags
|= IRP_CREATE_OPERATION
;
549 dispatch_irp( device
, irp
, context
);
551 return STATUS_SUCCESS
;
554 /* process a close request for a given file */
555 static NTSTATUS
dispatch_close( struct dispatch_context
*context
)
558 IO_STACK_LOCATION
*irpsp
;
559 DEVICE_OBJECT
*device
;
560 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.close
.file
);
562 if (!file
) return STATUS_INVALID_HANDLE
;
564 device
= IoGetAttachedDevice( file
->DeviceObject
);
566 TRACE( "device %p file %p\n", device
, file
);
568 if (!(irp
= IoAllocateIrp( device
->StackSize
, FALSE
)))
570 ObDereferenceObject( file
);
571 return STATUS_NO_MEMORY
;
574 irpsp
= IoGetNextIrpStackLocation( irp
);
575 irpsp
->MajorFunction
= IRP_MJ_CLOSE
;
576 irpsp
->FileObject
= file
;
578 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
579 irp
->Tail
.Overlay
.Thread
= (PETHREAD
)KeGetCurrentThread();
580 irp
->RequestorMode
= UserMode
;
581 irp
->AssociatedIrp
.SystemBuffer
= NULL
;
582 irp
->UserBuffer
= NULL
;
583 irp
->UserIosb
= NULL
;
584 irp
->UserEvent
= NULL
;
586 irp
->Flags
|= IRP_CLOSE_OPERATION
;
587 dispatch_irp( device
, irp
, context
);
589 return STATUS_SUCCESS
;
592 /* process a read request for a given device */
593 static NTSTATUS
dispatch_read( struct dispatch_context
*context
)
597 LARGE_INTEGER offset
;
598 IO_STACK_LOCATION
*irpsp
;
599 DEVICE_OBJECT
*device
;
600 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.read
.file
);
601 ULONG out_size
= context
->params
.read
.out_size
;
603 if (!file
) return STATUS_INVALID_HANDLE
;
605 device
= IoGetAttachedDevice( file
->DeviceObject
);
607 TRACE( "device %p file %p size %u\n", device
, file
, out_size
);
609 if (!(out_buff
= HeapAlloc( GetProcessHeap(), 0, out_size
))) return STATUS_NO_MEMORY
;
611 offset
.QuadPart
= context
->params
.read
.pos
;
613 if (!(irp
= IoBuildSynchronousFsdRequest( IRP_MJ_READ
, device
, out_buff
, out_size
,
614 &offset
, NULL
, NULL
)))
616 HeapFree( GetProcessHeap(), 0, out_buff
);
617 return STATUS_NO_MEMORY
;
620 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
621 irp
->RequestorMode
= UserMode
;
623 irpsp
= IoGetNextIrpStackLocation( irp
);
624 irpsp
->FileObject
= file
;
625 irpsp
->Parameters
.Read
.Key
= context
->params
.read
.key
;
627 irp
->Flags
|= IRP_READ_OPERATION
;
628 irp
->Flags
|= IRP_DEALLOCATE_BUFFER
; /* deallocate out_buff */
629 dispatch_irp( device
, irp
, context
);
631 return STATUS_SUCCESS
;
634 /* process a write request for a given device */
635 static NTSTATUS
dispatch_write( struct dispatch_context
*context
)
638 LARGE_INTEGER offset
;
639 IO_STACK_LOCATION
*irpsp
;
640 DEVICE_OBJECT
*device
;
641 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.write
.file
);
643 if (!file
) return STATUS_INVALID_HANDLE
;
645 device
= IoGetAttachedDevice( file
->DeviceObject
);
647 TRACE( "device %p file %p size %u\n", device
, file
, context
->in_size
);
649 offset
.QuadPart
= context
->params
.write
.pos
;
651 if (!(irp
= IoBuildSynchronousFsdRequest( IRP_MJ_WRITE
, device
, context
->in_buff
, context
->in_size
,
652 &offset
, NULL
, NULL
)))
653 return STATUS_NO_MEMORY
;
654 context
->in_buff
= NULL
;
656 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
657 irp
->RequestorMode
= UserMode
;
659 irpsp
= IoGetNextIrpStackLocation( irp
);
660 irpsp
->FileObject
= file
;
661 irpsp
->Parameters
.Write
.Key
= context
->params
.write
.key
;
663 irp
->Flags
|= IRP_WRITE_OPERATION
;
664 irp
->Flags
|= IRP_DEALLOCATE_BUFFER
; /* deallocate in_buff */
665 dispatch_irp( device
, irp
, context
);
667 return STATUS_SUCCESS
;
670 /* process a flush request for a given device */
671 static NTSTATUS
dispatch_flush( struct dispatch_context
*context
)
674 IO_STACK_LOCATION
*irpsp
;
675 DEVICE_OBJECT
*device
;
676 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.flush
.file
);
678 if (!file
) return STATUS_INVALID_HANDLE
;
680 device
= IoGetAttachedDevice( file
->DeviceObject
);
682 TRACE( "device %p file %p\n", device
, file
);
684 if (!(irp
= IoBuildSynchronousFsdRequest( IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0,
686 return STATUS_NO_MEMORY
;
688 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
689 irp
->RequestorMode
= UserMode
;
691 irpsp
= IoGetNextIrpStackLocation( irp
);
692 irpsp
->FileObject
= file
;
694 dispatch_irp( device
, irp
, context
);
696 return STATUS_SUCCESS
;
699 /* process an ioctl request for a given device */
700 static NTSTATUS
dispatch_ioctl( struct dispatch_context
*context
)
702 IO_STACK_LOCATION
*irpsp
;
704 void *out_buff
= NULL
;
705 void *to_free
= NULL
;
706 DEVICE_OBJECT
*device
;
707 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.ioctl
.file
);
708 ULONG out_size
= context
->params
.ioctl
.out_size
;
710 if (!file
) return STATUS_INVALID_HANDLE
;
712 device
= IoGetAttachedDevice( file
->DeviceObject
);
714 TRACE( "ioctl %x device %p file %p in_size %u out_size %u\n",
715 context
->params
.ioctl
.code
, device
, file
, context
->in_size
, out_size
);
719 if ((context
->params
.ioctl
.code
& 3) != METHOD_BUFFERED
)
721 if (context
->in_size
< out_size
) return STATUS_INVALID_DEVICE_REQUEST
;
722 context
->in_size
-= out_size
;
723 if (!(out_buff
= HeapAlloc( GetProcessHeap(), 0, out_size
))) return STATUS_NO_MEMORY
;
724 memcpy( out_buff
, (char *)context
->in_buff
+ context
->in_size
, out_size
);
726 else if (out_size
> context
->in_size
)
728 if (!(out_buff
= HeapAlloc( GetProcessHeap(), 0, out_size
))) return STATUS_NO_MEMORY
;
729 memcpy( out_buff
, context
->in_buff
, context
->in_size
);
730 to_free
= context
->in_buff
;
731 context
->in_buff
= out_buff
;
734 out_buff
= context
->in_buff
;
737 irp
= IoBuildDeviceIoControlRequest( context
->params
.ioctl
.code
, device
, context
->in_buff
,
738 context
->in_size
, out_buff
, out_size
, FALSE
, NULL
, NULL
);
741 HeapFree( GetProcessHeap(), 0, out_buff
);
742 return STATUS_NO_MEMORY
;
745 if (out_size
&& (context
->params
.ioctl
.code
& 3) != METHOD_BUFFERED
)
746 HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY
, context
->in_buff
, context
->in_size
);
748 irpsp
= IoGetNextIrpStackLocation( irp
);
749 irpsp
->FileObject
= file
;
751 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
752 irp
->RequestorMode
= UserMode
;
753 irp
->AssociatedIrp
.SystemBuffer
= context
->in_buff
;
754 context
->in_buff
= NULL
;
756 irp
->Flags
|= IRP_DEALLOCATE_BUFFER
; /* deallocate in_buff */
757 dispatch_irp( device
, irp
, context
);
759 HeapFree( GetProcessHeap(), 0, to_free
);
760 return STATUS_SUCCESS
;
763 static NTSTATUS
dispatch_free( struct dispatch_context
*context
)
765 void *obj
= wine_server_get_ptr( context
->params
.free
.obj
);
766 TRACE( "freeing %p object\n", obj
);
767 free_kernel_object( obj
);
768 return STATUS_SUCCESS
;
771 static NTSTATUS
dispatch_cancel( struct dispatch_context
*context
)
773 IRP
*irp
= wine_server_get_ptr( context
->params
.cancel
.irp
);
775 TRACE( "%p\n", irp
);
777 EnterCriticalSection( &irp_completion_cs
);
779 LeaveCriticalSection( &irp_completion_cs
);
780 return STATUS_SUCCESS
;
783 typedef NTSTATUS (*dispatch_func
)( struct dispatch_context
*context
);
785 static const dispatch_func dispatch_funcs
[] =
787 NULL
, /* IRP_CALL_NONE */
788 dispatch_create
, /* IRP_CALL_CREATE */
789 dispatch_close
, /* IRP_CALL_CLOSE */
790 dispatch_read
, /* IRP_CALL_READ */
791 dispatch_write
, /* IRP_CALL_WRITE */
792 dispatch_flush
, /* IRP_CALL_FLUSH */
793 dispatch_ioctl
, /* IRP_CALL_IOCTL */
794 dispatch_free
, /* IRP_CALL_FREE */
795 dispatch_cancel
/* IRP_CALL_CANCEL */
798 /* helper function to update service status */
799 static void set_service_status( SERVICE_STATUS_HANDLE handle
, DWORD state
, DWORD accepted
)
801 SERVICE_STATUS status
;
802 status
.dwServiceType
= SERVICE_WIN32
;
803 status
.dwCurrentState
= state
;
804 status
.dwControlsAccepted
= accepted
;
805 status
.dwWin32ExitCode
= 0;
806 status
.dwServiceSpecificExitCode
= 0;
807 status
.dwCheckPoint
= 0;
808 status
.dwWaitHint
= (state
== SERVICE_START_PENDING
) ? 10000 : 0;
809 SetServiceStatus( handle
, &status
);
812 static void unload_driver( struct wine_rb_entry
*entry
, void *context
)
814 struct wine_driver
*driver
= WINE_RB_ENTRY_VALUE( entry
, struct wine_driver
, entry
);
815 SERVICE_STATUS_HANDLE service_handle
= driver
->service_handle
;
816 LDR_DATA_TABLE_ENTRY
*ldr
;
818 if (!service_handle
) return; /* not a service */
820 TRACE("%s\n", debugstr_us(&driver
->driver_obj
.DriverName
));
822 if (!driver
->driver_obj
.DriverUnload
)
824 TRACE( "driver %s does not support unloading\n", debugstr_us(&driver
->driver_obj
.DriverName
) );
828 ldr
= driver
->driver_obj
.DriverSection
;
830 set_service_status( service_handle
, SERVICE_STOP_PENDING
, 0 );
832 TRACE_(relay
)( "\1Call driver unload %p (obj=%p)\n", driver
->driver_obj
.DriverUnload
, &driver
->driver_obj
);
834 driver
->driver_obj
.DriverUnload( &driver
->driver_obj
);
836 TRACE_(relay
)( "\1Ret driver unload %p (obj=%p)\n", driver
->driver_obj
.DriverUnload
, &driver
->driver_obj
);
838 FreeLibrary( ldr
->DllBase
);
839 IoDeleteDriver( &driver
->driver_obj
);
841 set_service_status( service_handle
, SERVICE_STOPPED
, 0 );
842 CloseServiceHandle( (void *)service_handle
);
845 PEPROCESS PsInitialSystemProcess
= NULL
;
847 /***********************************************************************
848 * wine_ntoskrnl_main_loop (Not a Windows API)
850 NTSTATUS CDECL
wine_ntoskrnl_main_loop( HANDLE stop_event
)
852 HANDLE manager
= get_device_manager();
853 struct dispatch_context context
;
854 NTSTATUS status
= STATUS_SUCCESS
;
857 context
.handle
= NULL
;
859 context
.in_size
= 4096;
860 context
.in_buff
= NULL
;
862 /* Set the system process global before setting up the request thread trickery */
863 PsInitialSystemProcess
= IoGetCurrentProcess();
864 request_thread
= GetCurrentThreadId();
868 handles
[0] = stop_event
;
869 handles
[1] = manager
;
873 NtCurrentTeb()->Reserved5
[1] = NULL
;
874 if (!context
.in_buff
&& !(context
.in_buff
= HeapAlloc( GetProcessHeap(), 0, context
.in_size
)))
876 ERR( "failed to allocate buffer\n" );
877 status
= STATUS_NO_MEMORY
;
881 SERVER_START_REQ( get_next_device_request
)
883 req
->manager
= wine_server_obj_handle( manager
);
884 req
->prev
= wine_server_obj_handle( context
.handle
);
885 req
->user_ptr
= wine_server_client_ptr( context
.irp
);
886 req
->status
= status
;
887 wine_server_set_reply( req
, context
.in_buff
, context
.in_size
);
888 if (!(status
= wine_server_call( req
)))
890 context
.handle
= wine_server_ptr_handle( reply
->next
);
891 context
.params
= reply
->params
;
892 context
.in_size
= reply
->in_size
;
893 client_tid
= reply
->client_tid
;
894 NtCurrentTeb()->Reserved5
[1] = wine_server_get_ptr( reply
->client_thread
);
898 context
.handle
= 0; /* no previous irp */
899 if (status
== STATUS_BUFFER_OVERFLOW
)
900 context
.in_size
= reply
->in_size
;
909 assert( context
.params
.type
!= IRP_CALL_NONE
&& context
.params
.type
< ARRAY_SIZE(dispatch_funcs
) );
910 status
= dispatch_funcs
[context
.params
.type
]( &context
);
911 if (!context
.in_buff
) context
.in_size
= 4096;
913 case STATUS_BUFFER_OVERFLOW
:
914 HeapFree( GetProcessHeap(), 0, context
.in_buff
);
915 context
.in_buff
= NULL
;
916 /* restart with larger buffer */
921 DWORD ret
= WaitForMultipleObjectsEx( 2, handles
, FALSE
, INFINITE
, TRUE
);
922 if (ret
== WAIT_OBJECT_0
)
924 HeapFree( GetProcessHeap(), 0, context
.in_buff
);
925 status
= STATUS_SUCCESS
;
928 if (ret
!= WAIT_IO_COMPLETION
) break;
935 /* Native PnP drivers expect that all of their devices will be removed when
936 * their unload routine is called, so we must stop the PnP manager first. */
938 wine_rb_destroy( &wine_drivers
, unload_driver
, NULL
);
942 /***********************************************************************
943 * IoAllocateDriverObjectExtension (NTOSKRNL.EXE.@)
945 NTSTATUS WINAPI
IoAllocateDriverObjectExtension( PDRIVER_OBJECT DriverObject
,
946 PVOID ClientIdentificationAddress
,
947 ULONG DriverObjectExtensionSize
,
948 PVOID
*DriverObjectExtension
)
950 FIXME( "stub: %p, %p, %u, %p\n", DriverObject
, ClientIdentificationAddress
,
951 DriverObjectExtensionSize
, DriverObjectExtension
);
952 return STATUS_NOT_IMPLEMENTED
;
956 /***********************************************************************
957 * IoGetDriverObjectExtension (NTOSKRNL.EXE.@)
959 PVOID WINAPI
IoGetDriverObjectExtension( PDRIVER_OBJECT DriverObject
,
960 PVOID ClientIdentificationAddress
)
962 FIXME( "stub: %p, %p\n", DriverObject
, ClientIdentificationAddress
);
967 /***********************************************************************
968 * IoInitializeIrp (NTOSKRNL.EXE.@)
970 void WINAPI
IoInitializeIrp( IRP
*irp
, USHORT size
, CCHAR stack_size
)
972 TRACE( "%p, %u, %d\n", irp
, size
, stack_size
);
974 RtlZeroMemory( irp
, size
);
976 irp
->Type
= IO_TYPE_IRP
;
978 InitializeListHead( &irp
->ThreadListEntry
);
979 irp
->StackCount
= stack_size
;
980 irp
->CurrentLocation
= stack_size
+ 1;
981 irp
->Tail
.Overlay
.s
.u2
.CurrentStackLocation
=
982 (PIO_STACK_LOCATION
)(irp
+ 1) + stack_size
;
985 void WINAPI
IoReuseIrp(IRP
*irp
, NTSTATUS iostatus
)
987 UCHAR AllocationFlags
;
989 TRACE("irp %p, iostatus %#x.\n", irp
, iostatus
);
991 AllocationFlags
= irp
->AllocationFlags
;
992 IoInitializeIrp(irp
, irp
->Size
, irp
->StackCount
);
993 irp
->AllocationFlags
= AllocationFlags
;
994 irp
->IoStatus
.u
.Status
= iostatus
;
997 /***********************************************************************
998 * IoInitializeTimer (NTOSKRNL.EXE.@)
1000 NTSTATUS WINAPI
IoInitializeTimer(PDEVICE_OBJECT DeviceObject
,
1001 PIO_TIMER_ROUTINE TimerRoutine
,
1004 FIXME( "stub: %p, %p, %p\n", DeviceObject
, TimerRoutine
, Context
);
1005 return STATUS_NOT_IMPLEMENTED
;
1009 /***********************************************************************
1010 * IoStartTimer (NTOSKRNL.EXE.@)
1012 void WINAPI
IoStartTimer(PDEVICE_OBJECT DeviceObject
)
1014 FIXME( "stub: %p\n", DeviceObject
);
1018 /***********************************************************************
1019 * IoStopTimer (NTOSKRNL.EXE.@)
1021 void WINAPI
IoStopTimer(PDEVICE_OBJECT DeviceObject
)
1023 FIXME( "stub: %p\n", DeviceObject
);
1027 /***********************************************************************
1028 * IoAllocateIrp (NTOSKRNL.EXE.@)
1030 PIRP WINAPI
IoAllocateIrp( CCHAR stack_size
, BOOLEAN charge_quota
)
1034 CCHAR loc_count
= stack_size
;
1036 TRACE( "%d, %d\n", stack_size
, charge_quota
);
1038 if (loc_count
< 8 && loc_count
!= 1)
1041 size
= sizeof(IRP
) + loc_count
* sizeof(IO_STACK_LOCATION
);
1042 irp
= ExAllocatePool( NonPagedPool
, size
);
1045 IoInitializeIrp( irp
, size
, stack_size
);
1046 if (stack_size
>= 1 && stack_size
<= 8)
1047 irp
->AllocationFlags
= IRP_ALLOCATED_FIXED_SIZE
;
1049 irp
->AllocationFlags
|= IRP_LOOKASIDE_ALLOCATION
;
1054 /***********************************************************************
1055 * IoFreeIrp (NTOSKRNL.EXE.@)
1057 void WINAPI
IoFreeIrp( IRP
*irp
)
1061 TRACE( "%p\n", irp
);
1063 mdl
= irp
->MdlAddress
;
1066 MDL
*next
= mdl
->Next
;
1075 /***********************************************************************
1076 * IoAllocateErrorLogEntry (NTOSKRNL.EXE.@)
1078 PVOID WINAPI
IoAllocateErrorLogEntry( PVOID IoObject
, UCHAR EntrySize
)
1080 FIXME( "stub: %p, %u\n", IoObject
, EntrySize
);
1085 /***********************************************************************
1086 * IoAllocateMdl (NTOSKRNL.EXE.@)
1088 PMDL WINAPI
IoAllocateMdl( PVOID va
, ULONG length
, BOOLEAN secondary
, BOOLEAN charge_quota
, IRP
*irp
)
1093 TRACE("(%p, %u, %i, %i, %p)\n", va
, length
, secondary
, charge_quota
, irp
);
1096 FIXME("Charge quota is not yet supported\n");
1098 mdl_size
= sizeof(MDL
) + sizeof(PFN_NUMBER
) * ADDRESS_AND_SIZE_TO_SPAN_PAGES(va
, length
);
1099 mdl
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, mdl_size
);
1103 MmInitializeMdl( mdl
, va
, length
);
1105 if (!irp
) return mdl
;
1107 if (secondary
) /* add it at the end */
1109 MDL
**pmdl
= &irp
->MdlAddress
;
1110 while (*pmdl
) pmdl
= &(*pmdl
)->Next
;
1115 mdl
->Next
= irp
->MdlAddress
;
1116 irp
->MdlAddress
= mdl
;
1122 /***********************************************************************
1123 * IoFreeMdl (NTOSKRNL.EXE.@)
1125 void WINAPI
IoFreeMdl(PMDL mdl
)
1128 HeapFree(GetProcessHeap(), 0, mdl
);
1134 DEVICE_OBJECT
*device
;
1135 PIO_WORKITEM_ROUTINE worker
;
1139 /***********************************************************************
1140 * IoAllocateWorkItem (NTOSKRNL.EXE.@)
1142 PIO_WORKITEM WINAPI
IoAllocateWorkItem( PDEVICE_OBJECT device
)
1144 PIO_WORKITEM work_item
;
1146 TRACE( "%p\n", device
);
1148 if (!(work_item
= ExAllocatePool( PagedPool
, sizeof(*work_item
) ))) return NULL
;
1149 work_item
->device
= device
;
1154 /***********************************************************************
1155 * IoFreeWorkItem (NTOSKRNL.EXE.@)
1157 void WINAPI
IoFreeWorkItem( PIO_WORKITEM work_item
)
1159 TRACE( "%p\n", work_item
);
1160 ExFreePool( work_item
);
1164 static void WINAPI
run_work_item_worker(TP_CALLBACK_INSTANCE
*instance
, void *context
)
1166 PIO_WORKITEM work_item
= context
;
1167 DEVICE_OBJECT
*device
= work_item
->device
;
1169 TRACE( "%p: calling %p(%p %p)\n", work_item
, work_item
->worker
, device
, work_item
->context
);
1170 work_item
->worker( device
, work_item
->context
);
1173 ObDereferenceObject( device
);
1176 /***********************************************************************
1177 * IoQueueWorkItem (NTOSKRNL.EXE.@)
1179 void WINAPI
IoQueueWorkItem( PIO_WORKITEM work_item
, PIO_WORKITEM_ROUTINE worker
,
1180 WORK_QUEUE_TYPE type
, void *context
)
1182 TRACE( "%p %p %u %p\n", work_item
, worker
, type
, context
);
1184 ObReferenceObject( work_item
->device
);
1185 work_item
->worker
= worker
;
1186 work_item
->context
= context
;
1187 TrySubmitThreadpoolCallback( run_work_item_worker
, work_item
, NULL
);
1190 /***********************************************************************
1191 * IoGetAttachedDevice (NTOSKRNL.EXE.@)
1193 DEVICE_OBJECT
* WINAPI
IoGetAttachedDevice( DEVICE_OBJECT
*device
)
1195 DEVICE_OBJECT
*result
= device
;
1197 TRACE( "(%p)\n", device
);
1199 while (result
->AttachedDevice
)
1200 result
= result
->AttachedDevice
;
1205 void WINAPI
IoDetachDevice( DEVICE_OBJECT
*device
)
1207 device
->AttachedDevice
= NULL
;
1210 /***********************************************************************
1211 * IoAttachDeviceToDeviceStack (NTOSKRNL.EXE.@)
1213 PDEVICE_OBJECT WINAPI
IoAttachDeviceToDeviceStack( DEVICE_OBJECT
*source
,
1214 DEVICE_OBJECT
*target
)
1216 TRACE( "%p, %p\n", source
, target
);
1217 target
= IoGetAttachedDevice( target
);
1218 target
->AttachedDevice
= source
;
1219 source
->StackSize
= target
->StackSize
+ 1;
1223 /***********************************************************************
1224 * IoBuildDeviceIoControlRequest (NTOSKRNL.EXE.@)
1226 PIRP WINAPI
IoBuildDeviceIoControlRequest( ULONG code
, PDEVICE_OBJECT device
,
1227 PVOID in_buff
, ULONG in_len
,
1228 PVOID out_buff
, ULONG out_len
,
1229 BOOLEAN internal
, PKEVENT event
,
1230 PIO_STATUS_BLOCK iosb
)
1233 PIO_STACK_LOCATION irpsp
;
1236 TRACE( "%x, %p, %p, %u, %p, %u, %u, %p, %p\n",
1237 code
, device
, in_buff
, in_len
, out_buff
, out_len
, internal
, event
, iosb
);
1242 irp
= IoAllocateIrp( device
->StackSize
, FALSE
);
1246 irpsp
= IoGetNextIrpStackLocation( irp
);
1247 irpsp
->MajorFunction
= internal
? IRP_MJ_INTERNAL_DEVICE_CONTROL
: IRP_MJ_DEVICE_CONTROL
;
1248 irpsp
->Parameters
.DeviceIoControl
.IoControlCode
= code
;
1249 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
= in_len
;
1250 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
= out_len
;
1251 irpsp
->DeviceObject
= NULL
;
1252 irpsp
->CompletionRoutine
= NULL
;
1256 case METHOD_BUFFERED
:
1257 irp
->AssociatedIrp
.SystemBuffer
= in_buff
;
1259 case METHOD_IN_DIRECT
:
1260 case METHOD_OUT_DIRECT
:
1261 irp
->AssociatedIrp
.SystemBuffer
= in_buff
;
1263 mdl
= IoAllocateMdl( out_buff
, out_len
, FALSE
, FALSE
, irp
);
1270 mdl
->MdlFlags
|= MDL_MAPPED_TO_SYSTEM_VA
;
1271 mdl
->MappedSystemVa
= out_buff
;
1273 case METHOD_NEITHER
:
1274 irpsp
->Parameters
.DeviceIoControl
.Type3InputBuffer
= in_buff
;
1278 irp
->RequestorMode
= KernelMode
;
1279 irp
->UserBuffer
= out_buff
;
1280 irp
->UserIosb
= iosb
;
1281 irp
->UserEvent
= event
;
1282 irp
->Tail
.Overlay
.Thread
= (PETHREAD
)KeGetCurrentThread();
1286 /***********************************************************************
1287 * IoBuildAsynchronousFsdRequest (NTOSKRNL.EXE.@)
1289 PIRP WINAPI
IoBuildAsynchronousFsdRequest(ULONG majorfunc
, DEVICE_OBJECT
*device
,
1290 void *buffer
, ULONG length
, LARGE_INTEGER
*startoffset
,
1291 IO_STATUS_BLOCK
*iosb
)
1294 PIO_STACK_LOCATION irpsp
;
1296 TRACE( "(%d %p %p %d %p %p)\n", majorfunc
, device
, buffer
, length
, startoffset
, iosb
);
1298 if (!(irp
= IoAllocateIrp( device
->StackSize
, FALSE
))) return NULL
;
1300 irpsp
= IoGetNextIrpStackLocation( irp
);
1301 irpsp
->MajorFunction
= majorfunc
;
1302 irpsp
->DeviceObject
= NULL
;
1303 irpsp
->CompletionRoutine
= NULL
;
1305 irp
->AssociatedIrp
.SystemBuffer
= buffer
;
1307 if (device
->Flags
& DO_DIRECT_IO
)
1309 MDL
*mdl
= IoAllocateMdl( buffer
, length
, FALSE
, FALSE
, irp
);
1316 mdl
->MdlFlags
|= MDL_MAPPED_TO_SYSTEM_VA
;
1317 mdl
->MappedSystemVa
= buffer
;
1323 irpsp
->Parameters
.Read
.Length
= length
;
1324 irpsp
->Parameters
.Read
.ByteOffset
.QuadPart
= startoffset
? startoffset
->QuadPart
: 0;
1327 irpsp
->Parameters
.Write
.Length
= length
;
1328 irpsp
->Parameters
.Write
.ByteOffset
.QuadPart
= startoffset
? startoffset
->QuadPart
: 0;
1331 irp
->RequestorMode
= KernelMode
;
1332 irp
->UserIosb
= iosb
;
1333 irp
->UserEvent
= NULL
;
1334 irp
->UserBuffer
= buffer
;
1335 irp
->Tail
.Overlay
.Thread
= (PETHREAD
)KeGetCurrentThread();
1341 /***********************************************************************
1342 * IoBuildSynchronousFsdRequest (NTOSKRNL.EXE.@)
1344 PIRP WINAPI
IoBuildSynchronousFsdRequest(ULONG majorfunc
, PDEVICE_OBJECT device
,
1345 PVOID buffer
, ULONG length
, PLARGE_INTEGER startoffset
,
1346 PKEVENT event
, PIO_STATUS_BLOCK iosb
)
1350 TRACE("(%d %p %p %d %p %p)\n", majorfunc
, device
, buffer
, length
, startoffset
, iosb
);
1352 irp
= IoBuildAsynchronousFsdRequest( majorfunc
, device
, buffer
, length
, startoffset
, iosb
);
1353 if (!irp
) return NULL
;
1355 irp
->UserEvent
= event
;
1359 static void build_driver_keypath( const WCHAR
*name
, UNICODE_STRING
*keypath
)
1361 static const WCHAR driverW
[] = {'\\','D','r','i','v','e','r','\\',0};
1364 /* Check what prefix is present */
1365 if (wcsncmp( name
, servicesW
, lstrlenW(servicesW
) ) == 0)
1367 FIXME( "Driver name %s is malformed as the keypath\n", debugstr_w(name
) );
1368 RtlCreateUnicodeString( keypath
, name
);
1371 if (wcsncmp( name
, driverW
, lstrlenW(driverW
) ) == 0)
1372 name
+= lstrlenW(driverW
);
1374 FIXME( "Driver name %s does not properly begin with \\Driver\\\n", debugstr_w(name
) );
1376 str
= HeapAlloc( GetProcessHeap(), 0, sizeof(servicesW
) + lstrlenW(name
)*sizeof(WCHAR
));
1377 lstrcpyW( str
, servicesW
);
1378 lstrcatW( str
, name
);
1379 RtlInitUnicodeString( keypath
, str
);
1383 static NTSTATUS WINAPI
unhandled_irp( DEVICE_OBJECT
*device
, IRP
*irp
)
1385 TRACE( "(%p, %p)\n", device
, irp
);
1386 irp
->IoStatus
.u
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1387 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1388 return STATUS_INVALID_DEVICE_REQUEST
;
1392 static void free_driver_object( void *obj
)
1394 struct wine_driver
*driver
= obj
;
1395 RtlFreeUnicodeString( &driver
->driver_obj
.DriverName
);
1396 RtlFreeUnicodeString( &driver
->driver_obj
.DriverExtension
->ServiceKeyName
);
1397 free_kernel_object( driver
);
1400 static const WCHAR driver_type_name
[] = {'D','r','i','v','e','r',0};
1402 static struct _OBJECT_TYPE driver_type
=
1409 POBJECT_TYPE IoDriverObjectType
= &driver_type
;
1412 /***********************************************************************
1413 * IoCreateDriver (NTOSKRNL.EXE.@)
1415 NTSTATUS WINAPI
IoCreateDriver( UNICODE_STRING
*name
, PDRIVER_INITIALIZE init
)
1417 struct wine_driver
*driver
;
1421 TRACE("(%s, %p)\n", debugstr_us(name
), init
);
1423 if (!(driver
= alloc_kernel_object( IoDriverObjectType
, NULL
, sizeof(*driver
), 1 )))
1424 return STATUS_NO_MEMORY
;
1426 if ((status
= RtlDuplicateUnicodeString( 1, name
, &driver
->driver_obj
.DriverName
)))
1428 free_kernel_object( driver
);
1432 driver
->driver_obj
.Size
= sizeof(driver
->driver_obj
);
1433 driver
->driver_obj
.DriverInit
= init
;
1434 driver
->driver_obj
.DriverExtension
= &driver
->driver_extension
;
1435 driver
->driver_extension
.DriverObject
= &driver
->driver_obj
;
1436 build_driver_keypath( driver
->driver_obj
.DriverName
.Buffer
, &driver
->driver_extension
.ServiceKeyName
);
1437 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
1438 driver
->driver_obj
.MajorFunction
[i
] = unhandled_irp
;
1440 EnterCriticalSection( &drivers_cs
);
1441 if (wine_rb_put( &wine_drivers
, &driver
->driver_obj
.DriverName
, &driver
->entry
))
1442 ERR( "failed to insert driver %s in tree\n", debugstr_us(name
) );
1443 LeaveCriticalSection( &drivers_cs
);
1445 status
= driver
->driver_obj
.DriverInit( &driver
->driver_obj
, &driver
->driver_extension
.ServiceKeyName
);
1448 IoDeleteDriver( &driver
->driver_obj
);
1452 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
1454 if (driver
->driver_obj
.MajorFunction
[i
]) continue;
1455 driver
->driver_obj
.MajorFunction
[i
] = unhandled_irp
;
1458 return STATUS_SUCCESS
;
1462 /***********************************************************************
1463 * IoDeleteDriver (NTOSKRNL.EXE.@)
1465 void WINAPI
IoDeleteDriver( DRIVER_OBJECT
*driver_object
)
1467 TRACE( "(%p)\n", driver_object
);
1469 EnterCriticalSection( &drivers_cs
);
1470 wine_rb_remove_key( &wine_drivers
, &driver_object
->DriverName
);
1471 LeaveCriticalSection( &drivers_cs
);
1473 ObDereferenceObject( driver_object
);
1477 static const WCHAR device_type_name
[] = {'D','e','v','i','c','e',0};
1479 static struct _OBJECT_TYPE device_type
=
1484 POBJECT_TYPE IoDeviceObjectType
= &device_type
;
1487 /***********************************************************************
1488 * IoCreateDevice (NTOSKRNL.EXE.@)
1490 NTSTATUS WINAPI
IoCreateDevice( DRIVER_OBJECT
*driver
, ULONG ext_size
,
1491 UNICODE_STRING
*name
, DEVICE_TYPE type
,
1492 ULONG characteristics
, BOOLEAN exclusive
,
1493 DEVICE_OBJECT
**ret_device
)
1495 static const WCHAR auto_format
[] = {'\\','D','e','v','i','c','e','\\','%','0','8','x',0};
1497 struct wine_device
*wine_device
;
1498 DEVICE_OBJECT
*device
;
1499 HANDLE manager
= get_device_manager();
1500 static unsigned int auto_idx
= 0;
1503 TRACE( "(%p, %u, %s, %u, %x, %u, %p)\n",
1504 driver
, ext_size
, debugstr_us(name
), type
, characteristics
, exclusive
, ret_device
);
1506 if (!(wine_device
= alloc_kernel_object( IoDeviceObjectType
, NULL
, sizeof(struct wine_device
) + ext_size
, 1 )))
1507 return STATUS_NO_MEMORY
;
1508 device
= &wine_device
->device_obj
;
1510 device
->DriverObject
= driver
;
1511 device
->DeviceExtension
= wine_device
+ 1;
1512 device
->DeviceType
= type
;
1513 device
->StackSize
= 1;
1515 if (characteristics
& FILE_AUTOGENERATED_DEVICE_NAME
)
1519 swprintf( autoW
, ARRAY_SIZE(autoW
), auto_format
, auto_idx
++ );
1520 SERVER_START_REQ( create_device
)
1523 req
->manager
= wine_server_obj_handle( manager
);
1524 req
->user_ptr
= wine_server_client_ptr( device
);
1525 wine_server_add_data( req
, autoW
, lstrlenW(autoW
) * sizeof(WCHAR
) );
1526 status
= wine_server_call( req
);
1529 } while (status
== STATUS_OBJECT_NAME_COLLISION
);
1533 SERVER_START_REQ( create_device
)
1536 req
->manager
= wine_server_obj_handle( manager
);
1537 req
->user_ptr
= wine_server_client_ptr( device
);
1538 if (name
) wine_server_add_data( req
, name
->Buffer
, name
->Length
);
1539 status
= wine_server_call( req
);
1546 free_kernel_object( device
);
1550 device
->NextDevice
= driver
->DeviceObject
;
1551 driver
->DeviceObject
= device
;
1553 *ret_device
= device
;
1554 return STATUS_SUCCESS
;
1558 /***********************************************************************
1559 * IoDeleteDevice (NTOSKRNL.EXE.@)
1561 void WINAPI
IoDeleteDevice( DEVICE_OBJECT
*device
)
1565 TRACE( "%p\n", device
);
1567 SERVER_START_REQ( delete_device
)
1569 req
->manager
= wine_server_obj_handle( get_device_manager() );
1570 req
->device
= wine_server_client_ptr( device
);
1571 status
= wine_server_call( req
);
1575 if (status
== STATUS_SUCCESS
)
1577 struct wine_device
*wine_device
= CONTAINING_RECORD(device
, struct wine_device
, device_obj
);
1578 DEVICE_OBJECT
**prev
= &device
->DriverObject
->DeviceObject
;
1579 while (*prev
&& *prev
!= device
) prev
= &(*prev
)->NextDevice
;
1580 if (*prev
) *prev
= (*prev
)->NextDevice
;
1581 ExFreePool( wine_device
->children
);
1582 ObDereferenceObject( device
);
1587 /***********************************************************************
1588 * IoCreateSymbolicLink (NTOSKRNL.EXE.@)
1590 NTSTATUS WINAPI
IoCreateSymbolicLink( UNICODE_STRING
*name
, UNICODE_STRING
*target
)
1593 OBJECT_ATTRIBUTES attr
;
1596 attr
.Length
= sizeof(attr
);
1597 attr
.RootDirectory
= 0;
1598 attr
.ObjectName
= name
;
1599 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_PERMANENT
;
1600 attr
.SecurityDescriptor
= NULL
;
1601 attr
.SecurityQualityOfService
= NULL
;
1603 TRACE( "%s -> %s\n", debugstr_us(name
), debugstr_us(target
) );
1604 if (!(ret
= NtCreateSymbolicLinkObject( &handle
, SYMBOLIC_LINK_ALL_ACCESS
, &attr
, target
)))
1610 /***********************************************************************
1611 * IoCreateUnprotectedSymbolicLink (NTOSKRNL.EXE.@)
1613 NTSTATUS WINAPI
IoCreateUnprotectedSymbolicLink( UNICODE_STRING
*name
, UNICODE_STRING
*target
)
1616 OBJECT_ATTRIBUTES attr
;
1619 attr
.Length
= sizeof(attr
);
1620 attr
.RootDirectory
= 0;
1621 attr
.ObjectName
= name
;
1622 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_PERMANENT
;
1623 attr
.SecurityDescriptor
= NULL
;
1624 attr
.SecurityQualityOfService
= NULL
;
1626 TRACE( "%s -> %s\n", debugstr_us(name
), debugstr_us(target
) );
1627 if (!(ret
= NtCreateSymbolicLinkObject( &handle
, SYMBOLIC_LINK_ALL_ACCESS
, &attr
, target
)))
1633 /***********************************************************************
1634 * IoDeleteSymbolicLink (NTOSKRNL.EXE.@)
1636 NTSTATUS WINAPI
IoDeleteSymbolicLink( UNICODE_STRING
*name
)
1639 OBJECT_ATTRIBUTES attr
;
1642 attr
.Length
= sizeof(attr
);
1643 attr
.RootDirectory
= 0;
1644 attr
.ObjectName
= name
;
1645 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1646 attr
.SecurityDescriptor
= NULL
;
1647 attr
.SecurityQualityOfService
= NULL
;
1649 if (!(status
= NtOpenSymbolicLinkObject( &handle
, 0, &attr
)))
1651 NtMakeTemporaryObject( handle
);
1657 /***********************************************************************
1658 * IoGetDeviceInterfaces (NTOSKRNL.EXE.@)
1660 NTSTATUS WINAPI
IoGetDeviceInterfaces( const GUID
*InterfaceClassGuid
,
1661 PDEVICE_OBJECT PhysicalDeviceObject
,
1662 ULONG Flags
, PWSTR
*SymbolicLinkList
)
1664 FIXME( "stub: %s %p %x %p\n", debugstr_guid(InterfaceClassGuid
),
1665 PhysicalDeviceObject
, Flags
, SymbolicLinkList
);
1666 return STATUS_NOT_IMPLEMENTED
;
1670 /***********************************************************************
1671 * IoGetDeviceObjectPointer (NTOSKRNL.EXE.@)
1673 NTSTATUS WINAPI
IoGetDeviceObjectPointer( UNICODE_STRING
*name
, ACCESS_MASK access
, PFILE_OBJECT
*file
, PDEVICE_OBJECT
*device
)
1675 static DEVICE_OBJECT stub_device
;
1676 static DRIVER_OBJECT stub_driver
;
1678 FIXME( "stub: %s %x %p %p\n", debugstr_us(name
), access
, file
, device
);
1680 stub_device
.StackSize
= 0x80; /* minimum value to appease SecuROM 5.x */
1681 stub_device
.DriverObject
= &stub_driver
;
1684 *device
= &stub_device
;
1686 return STATUS_SUCCESS
;
1689 /***********************************************************************
1690 * IoCallDriver (NTOSKRNL.EXE.@)
1692 NTSTATUS WINAPI
IoCallDriver( DEVICE_OBJECT
*device
, IRP
*irp
)
1694 PDRIVER_DISPATCH dispatch
;
1695 IO_STACK_LOCATION
*irpsp
;
1698 --irp
->CurrentLocation
;
1699 irpsp
= --irp
->Tail
.Overlay
.s
.u2
.CurrentStackLocation
;
1700 irpsp
->DeviceObject
= device
;
1701 dispatch
= device
->DriverObject
->MajorFunction
[irpsp
->MajorFunction
];
1703 TRACE_(relay
)( "\1Call driver dispatch %p (device=%p,irp=%p)\n", dispatch
, device
, irp
);
1705 status
= dispatch( device
, irp
);
1707 TRACE_(relay
)( "\1Ret driver dispatch %p (device=%p,irp=%p) retval=%08x\n",
1708 dispatch
, device
, irp
, status
);
1714 /***********************************************************************
1715 * IofCallDriver (NTOSKRNL.EXE.@)
1717 DEFINE_FASTCALL_WRAPPER( IofCallDriver
, 8 )
1718 NTSTATUS FASTCALL
IofCallDriver( DEVICE_OBJECT
*device
, IRP
*irp
)
1720 TRACE( "%p %p\n", device
, irp
);
1721 return IoCallDriver( device
, irp
);
1725 /***********************************************************************
1726 * IoGetRelatedDeviceObject (NTOSKRNL.EXE.@)
1728 PDEVICE_OBJECT WINAPI
IoGetRelatedDeviceObject( PFILE_OBJECT obj
)
1730 FIXME( "stub: %p\n", obj
);
1734 static CONFIGURATION_INFORMATION configuration_information
;
1736 /***********************************************************************
1737 * IoGetConfigurationInformation (NTOSKRNL.EXE.@)
1739 PCONFIGURATION_INFORMATION WINAPI
IoGetConfigurationInformation(void)
1741 FIXME( "partial stub\n" );
1742 /* FIXME: return actual devices on system */
1743 return &configuration_information
;
1746 /***********************************************************************
1747 * IoGetStackLimits (NTOSKRNL.EXE.@)
1749 void WINAPI
IoGetStackLimits(ULONG_PTR
*low
, ULONG_PTR
*high
)
1751 TEB
*teb
= NtCurrentTeb();
1753 TRACE( "%p %p\n", low
, high
);
1755 *low
= (DWORD_PTR
)teb
->Tib
.StackLimit
;
1756 *high
= (DWORD_PTR
)teb
->Tib
.StackBase
;
1759 /***********************************************************************
1760 * IoIsWdmVersionAvailable (NTOSKRNL.EXE.@)
1762 NTSTATUS WINAPI
IoIsWdmVersionAvailable(UCHAR MajorVersion
, UCHAR MinorVersion
)
1768 TRACE( "%d, 0x%X\n", MajorVersion
, MinorVersion
);
1770 version
= GetVersion();
1771 major
= LOBYTE(version
);
1772 minor
= HIBYTE(LOWORD(version
));
1774 if (MajorVersion
== 6 && MinorVersion
== 0)
1776 /* Windows Vista, Windows Server 2008, Windows 7 */
1778 else if (MajorVersion
== 1)
1780 if (MinorVersion
== 0x30)
1782 /* Windows server 2003 */
1786 else if (MinorVersion
== 0x20)
1792 else if (MinorVersion
== 0x10)
1798 else if (MinorVersion
== 0x05)
1802 MinorVersion
= 0x5a;
1804 else if (MinorVersion
== 0x00)
1808 MinorVersion
= 0x0a;
1812 FIXME( "unknown major %d minor 0x%X\n", MajorVersion
, MinorVersion
);
1818 FIXME( "unknown major %d minor 0x%X\n", MajorVersion
, MinorVersion
);
1821 return major
> MajorVersion
|| (major
== MajorVersion
&& minor
>= MinorVersion
);
1824 /***********************************************************************
1825 * IoQueryDeviceDescription (NTOSKRNL.EXE.@)
1827 NTSTATUS WINAPI
IoQueryDeviceDescription(PINTERFACE_TYPE itype
, PULONG bus
, PCONFIGURATION_TYPE ctype
,
1828 PULONG cnum
, PCONFIGURATION_TYPE ptype
, PULONG pnum
,
1829 PIO_QUERY_DEVICE_ROUTINE callout
, PVOID context
)
1831 FIXME( "(%p %p %p %p %p %p %p %p)\n", itype
, bus
, ctype
, cnum
, ptype
, pnum
, callout
, context
);
1832 return STATUS_NOT_IMPLEMENTED
;
1835 /***********************************************************************
1836 * IoRegisterDriverReinitialization (NTOSKRNL.EXE.@)
1838 void WINAPI
IoRegisterDriverReinitialization( PDRIVER_OBJECT obj
, PDRIVER_REINITIALIZE reinit
, PVOID context
)
1840 FIXME( "stub: %p %p %p\n", obj
, reinit
, context
);
1843 /***********************************************************************
1844 * IoRegisterBootDriverReinitialization (NTOSKRNL.EXE.@)
1846 void WINAPI
IoRegisterBootDriverReinitialization(DRIVER_OBJECT
*driver
, PDRIVER_REINITIALIZE proc
, void *ctx
)
1848 FIXME("driver %p, proc %p, ctx %p, stub!\n", driver
, proc
, ctx
);
1851 /***********************************************************************
1852 * IoRegisterShutdownNotification (NTOSKRNL.EXE.@)
1854 NTSTATUS WINAPI
IoRegisterShutdownNotification( PDEVICE_OBJECT obj
)
1856 FIXME( "stub: %p\n", obj
);
1857 return STATUS_SUCCESS
;
1861 /***********************************************************************
1862 * IoUnregisterShutdownNotification (NTOSKRNL.EXE.@)
1864 VOID WINAPI
IoUnregisterShutdownNotification( PDEVICE_OBJECT obj
)
1866 FIXME( "stub: %p\n", obj
);
1870 /***********************************************************************
1871 * IoReportResourceForDetection (NTOSKRNL.EXE.@)
1873 NTSTATUS WINAPI
IoReportResourceForDetection( DRIVER_OBJECT
*drv_obj
, CM_RESOURCE_LIST
*drv_list
, ULONG drv_size
,
1874 DEVICE_OBJECT
*dev_obj
, CM_RESOURCE_LIST
*dev_list
, ULONG dev_size
,
1877 FIXME( "(%p, %p, %u, %p, %p, %u, %p): stub\n", drv_obj
, drv_list
, drv_size
,
1878 dev_obj
, dev_list
, dev_size
, conflict
);
1880 return STATUS_NOT_IMPLEMENTED
;
1884 /***********************************************************************
1885 * IoReportResourceUsage (NTOSKRNL.EXE.@)
1887 NTSTATUS WINAPI
IoReportResourceUsage( UNICODE_STRING
*name
, DRIVER_OBJECT
*drv_obj
, CM_RESOURCE_LIST
*drv_list
,
1888 ULONG drv_size
, DRIVER_OBJECT
*dev_obj
, CM_RESOURCE_LIST
*dev_list
,
1889 ULONG dev_size
, BOOLEAN overwrite
, BOOLEAN
*conflict
)
1891 FIXME( "(%s, %p, %p, %u, %p, %p, %u, %d, %p): stub\n", debugstr_us(name
),
1892 drv_obj
, drv_list
, drv_size
, dev_obj
, dev_list
, dev_size
, overwrite
, conflict
);
1894 return STATUS_NOT_IMPLEMENTED
;
1898 /***********************************************************************
1899 * IoCompleteRequest (NTOSKRNL.EXE.@)
1901 VOID WINAPI
IoCompleteRequest( IRP
*irp
, UCHAR priority_boost
)
1903 IO_STACK_LOCATION
*irpsp
;
1904 PIO_COMPLETION_ROUTINE routine
;
1905 NTSTATUS status
, stat
;
1906 DEVICE_OBJECT
*device
;
1909 TRACE( "%p %u\n", irp
, priority_boost
);
1911 status
= irp
->IoStatus
.u
.Status
;
1912 while (irp
->CurrentLocation
<= irp
->StackCount
)
1914 irpsp
= irp
->Tail
.Overlay
.s
.u2
.CurrentStackLocation
;
1915 routine
= irpsp
->CompletionRoutine
;
1919 if ((irpsp
->Control
& SL_INVOKE_ON_SUCCESS
) && STATUS_SUCCESS
== status
)
1921 if ((irpsp
->Control
& SL_INVOKE_ON_ERROR
) && STATUS_SUCCESS
!= status
)
1923 if ((irpsp
->Control
& SL_INVOKE_ON_CANCEL
) && irp
->Cancel
)
1926 ++irp
->CurrentLocation
;
1927 ++irp
->Tail
.Overlay
.s
.u2
.CurrentStackLocation
;
1928 if (irp
->CurrentLocation
<= irp
->StackCount
)
1929 device
= IoGetCurrentIrpStackLocation(irp
)->DeviceObject
;
1934 TRACE( "calling %p( %p, %p, %p )\n", routine
, device
, irp
, irpsp
->Context
);
1935 stat
= routine( device
, irp
, irpsp
->Context
);
1936 TRACE( "CompletionRoutine returned %x\n", stat
);
1937 if (STATUS_MORE_PROCESSING_REQUIRED
== stat
)
1942 if (irp
->Flags
& IRP_DEALLOCATE_BUFFER
)
1943 HeapFree( GetProcessHeap(), 0, irp
->AssociatedIrp
.SystemBuffer
);
1944 if (irp
->UserEvent
) KeSetEvent( irp
->UserEvent
, IO_NO_INCREMENT
, FALSE
);
1950 /***********************************************************************
1951 * IofCompleteRequest (NTOSKRNL.EXE.@)
1953 DEFINE_FASTCALL_WRAPPER( IofCompleteRequest
, 8 )
1954 void FASTCALL
IofCompleteRequest( IRP
*irp
, UCHAR priority_boost
)
1956 TRACE( "%p %u\n", irp
, priority_boost
);
1957 IoCompleteRequest( irp
, priority_boost
);
1961 /***********************************************************************
1962 * IoCancelIrp (NTOSKRNL.EXE.@)
1964 BOOLEAN WINAPI
IoCancelIrp( IRP
*irp
)
1966 PDRIVER_CANCEL cancel_routine
;
1969 TRACE( "(%p)\n", irp
);
1971 IoAcquireCancelSpinLock( &irql
);
1973 if (!(cancel_routine
= IoSetCancelRoutine( irp
, NULL
)))
1975 IoReleaseCancelSpinLock( irp
->CancelIrql
);
1979 /* CancelRoutine is responsible for calling IoReleaseCancelSpinLock */
1980 irp
->CancelIrql
= irql
;
1981 cancel_routine( IoGetCurrentIrpStackLocation(irp
)->DeviceObject
, irp
);
1986 /***********************************************************************
1987 * InterlockedCompareExchange (NTOSKRNL.EXE.@)
1989 DEFINE_FASTCALL_WRAPPER( NTOSKRNL_InterlockedCompareExchange
, 12 )
1990 LONG FASTCALL
NTOSKRNL_InterlockedCompareExchange( LONG
volatile *dest
, LONG xchg
, LONG compare
)
1992 return InterlockedCompareExchange( dest
, xchg
, compare
);
1996 /***********************************************************************
1997 * InterlockedDecrement (NTOSKRNL.EXE.@)
1999 DEFINE_FASTCALL1_WRAPPER( NTOSKRNL_InterlockedDecrement
)
2000 LONG FASTCALL
NTOSKRNL_InterlockedDecrement( LONG
volatile *dest
)
2002 return InterlockedDecrement( dest
);
2006 /***********************************************************************
2007 * InterlockedExchange (NTOSKRNL.EXE.@)
2009 DEFINE_FASTCALL_WRAPPER( NTOSKRNL_InterlockedExchange
, 8 )
2010 LONG FASTCALL
NTOSKRNL_InterlockedExchange( LONG
volatile *dest
, LONG val
)
2012 return InterlockedExchange( dest
, val
);
2016 /***********************************************************************
2017 * InterlockedExchangeAdd (NTOSKRNL.EXE.@)
2019 DEFINE_FASTCALL_WRAPPER( NTOSKRNL_InterlockedExchangeAdd
, 8 )
2020 LONG FASTCALL
NTOSKRNL_InterlockedExchangeAdd( LONG
volatile *dest
, LONG incr
)
2022 return InterlockedExchangeAdd( dest
, incr
);
2026 /***********************************************************************
2027 * InterlockedIncrement (NTOSKRNL.EXE.@)
2029 DEFINE_FASTCALL1_WRAPPER( NTOSKRNL_InterlockedIncrement
)
2030 LONG FASTCALL
NTOSKRNL_InterlockedIncrement( LONG
volatile *dest
)
2032 return InterlockedIncrement( dest
);
2036 /***********************************************************************
2037 * ExAllocatePool (NTOSKRNL.EXE.@)
2039 PVOID WINAPI
ExAllocatePool( POOL_TYPE type
, SIZE_T size
)
2041 return ExAllocatePoolWithTag( type
, size
, 0 );
2045 /***********************************************************************
2046 * ExAllocatePoolWithQuota (NTOSKRNL.EXE.@)
2048 PVOID WINAPI
ExAllocatePoolWithQuota( POOL_TYPE type
, SIZE_T size
)
2050 return ExAllocatePoolWithTag( type
, size
, 0 );
2054 /***********************************************************************
2055 * ExAllocatePoolWithTag (NTOSKRNL.EXE.@)
2057 PVOID WINAPI
ExAllocatePoolWithTag( POOL_TYPE type
, SIZE_T size
, ULONG tag
)
2059 /* FIXME: handle page alignment constraints */
2060 void *ret
= HeapAlloc( ntoskrnl_heap
, 0, size
);
2061 TRACE( "%lu pool %u -> %p\n", size
, type
, ret
);
2066 /***********************************************************************
2067 * ExAllocatePoolWithQuotaTag (NTOSKRNL.EXE.@)
2069 PVOID WINAPI
ExAllocatePoolWithQuotaTag( POOL_TYPE type
, SIZE_T size
, ULONG tag
)
2071 return ExAllocatePoolWithTag( type
, size
, tag
);
2075 /***********************************************************************
2076 * ExCreateCallback (NTOSKRNL.EXE.@)
2078 NTSTATUS WINAPI
ExCreateCallback(PCALLBACK_OBJECT
*obj
, POBJECT_ATTRIBUTES attr
,
2079 BOOLEAN create
, BOOLEAN allow_multiple
)
2081 FIXME("(%p, %p, %u, %u): stub\n", obj
, attr
, create
, allow_multiple
);
2083 return STATUS_SUCCESS
;
2086 void * WINAPI
ExRegisterCallback(PCALLBACK_OBJECT callback_object
,
2087 PCALLBACK_FUNCTION callback_function
, void *callback_context
)
2089 FIXME("callback_object %p, callback_function %p, callback_context %p stub.\n",
2090 callback_object
, callback_function
, callback_context
);
2092 return (void *)0xdeadbeef;
2095 void WINAPI
ExUnregisterCallback(void *callback_registration
)
2097 FIXME("callback_registration %p stub.\n", callback_registration
);
2100 /***********************************************************************
2101 * ExFreePool (NTOSKRNL.EXE.@)
2103 void WINAPI
ExFreePool( void *ptr
)
2105 ExFreePoolWithTag( ptr
, 0 );
2109 /***********************************************************************
2110 * ExFreePoolWithTag (NTOSKRNL.EXE.@)
2112 void WINAPI
ExFreePoolWithTag( void *ptr
, ULONG tag
)
2114 TRACE( "%p\n", ptr
);
2115 HeapFree( ntoskrnl_heap
, 0, ptr
);
2118 static void initialize_lookaside_list( GENERAL_LOOKASIDE
*lookaside
, PALLOCATE_FUNCTION allocate
, PFREE_FUNCTION free
,
2119 ULONG type
, SIZE_T size
, ULONG tag
)
2122 RtlInitializeSListHead( &lookaside
->u
.ListHead
);
2123 lookaside
->Depth
= 4;
2124 lookaside
->MaximumDepth
= 256;
2125 lookaside
->TotalAllocates
= 0;
2126 lookaside
->u2
.AllocateMisses
= 0;
2127 lookaside
->TotalFrees
= 0;
2128 lookaside
->u3
.FreeMisses
= 0;
2129 lookaside
->Type
= type
;
2130 lookaside
->Tag
= tag
;
2131 lookaside
->Size
= size
;
2132 lookaside
->u4
.Allocate
= allocate
? allocate
: ExAllocatePoolWithTag
;
2133 lookaside
->u5
.Free
= free
? free
: ExFreePool
;
2134 lookaside
->LastTotalAllocates
= 0;
2135 lookaside
->u6
.LastAllocateMisses
= 0;
2137 /* FIXME: insert in global list of lookadside lists */
2140 /***********************************************************************
2141 * ExInitializeNPagedLookasideList (NTOSKRNL.EXE.@)
2143 void WINAPI
ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST lookaside
,
2144 PALLOCATE_FUNCTION allocate
,
2145 PFREE_FUNCTION free
,
2151 TRACE( "%p, %p, %p, %u, %lu, %u, %u\n", lookaside
, allocate
, free
, flags
, size
, tag
, depth
);
2152 initialize_lookaside_list( &lookaside
->L
, allocate
, free
, NonPagedPool
| flags
, size
, tag
);
2155 /***********************************************************************
2156 * ExInitializePagedLookasideList (NTOSKRNL.EXE.@)
2158 void WINAPI
ExInitializePagedLookasideList(PPAGED_LOOKASIDE_LIST lookaside
,
2159 PALLOCATE_FUNCTION allocate
,
2160 PFREE_FUNCTION free
,
2166 TRACE( "%p, %p, %p, %u, %lu, %u, %u\n", lookaside
, allocate
, free
, flags
, size
, tag
, depth
);
2167 initialize_lookaside_list( &lookaside
->L
, allocate
, free
, PagedPool
| flags
, size
, tag
);
2170 static void delete_lookaside_list( GENERAL_LOOKASIDE
*lookaside
)
2173 while ((entry
= RtlInterlockedPopEntrySList(&lookaside
->u
.ListHead
)))
2174 lookaside
->u5
.FreeEx(entry
, (LOOKASIDE_LIST_EX
*)lookaside
);
2177 /***********************************************************************
2178 * ExDeleteNPagedLookasideList (NTOSKRNL.EXE.@)
2180 void WINAPI
ExDeleteNPagedLookasideList( PNPAGED_LOOKASIDE_LIST lookaside
)
2182 TRACE( "%p\n", lookaside
);
2183 delete_lookaside_list( &lookaside
->L
);
2187 /***********************************************************************
2188 * ExDeletePagedLookasideList (NTOSKRNL.EXE.@)
2190 void WINAPI
ExDeletePagedLookasideList( PPAGED_LOOKASIDE_LIST lookaside
)
2192 TRACE( "%p\n", lookaside
);
2193 delete_lookaside_list( &lookaside
->L
);
2196 /***********************************************************************
2197 * ExInitializeZone (NTOSKRNL.EXE.@)
2199 NTSTATUS WINAPI
ExInitializeZone(PZONE_HEADER Zone
,
2201 PVOID InitialSegment
,
2202 ULONG InitialSegmentSize
)
2204 FIXME( "stub: %p, %u, %p, %u\n", Zone
, BlockSize
, InitialSegment
, InitialSegmentSize
);
2205 return STATUS_NOT_IMPLEMENTED
;
2208 /***********************************************************************
2209 * FsRtlIsNameInExpression (NTOSKRNL.EXE.@)
2211 BOOLEAN WINAPI
FsRtlIsNameInExpression(PUNICODE_STRING expression
, PUNICODE_STRING name
,
2212 BOOLEAN ignore
, PWCH upcase
)
2214 FIXME("stub: %p %p %d %p\n", expression
, name
, ignore
, upcase
);
2218 /***********************************************************************
2219 * FsRtlRegisterUncProvider (NTOSKRNL.EXE.@)
2221 NTSTATUS WINAPI
FsRtlRegisterUncProvider(PHANDLE MupHandle
, PUNICODE_STRING RedirDevName
,
2222 BOOLEAN MailslotsSupported
)
2224 FIXME("(%p %p %d): stub\n", MupHandle
, RedirDevName
, MailslotsSupported
);
2225 return STATUS_NOT_IMPLEMENTED
;
2229 static void *create_process_object( HANDLE handle
)
2233 if (!(process
= alloc_kernel_object( PsProcessType
, handle
, sizeof(*process
), 0 ))) return NULL
;
2235 process
->header
.Type
= 3;
2236 process
->header
.WaitListHead
.Blink
= INVALID_HANDLE_VALUE
; /* mark as kernel object */
2237 NtQueryInformationProcess( handle
, ProcessBasicInformation
, &process
->info
, sizeof(process
->info
), NULL
);
2238 IsWow64Process( handle
, &process
->wow64
);
2242 static const WCHAR process_type_name
[] = {'P','r','o','c','e','s','s',0};
2244 static struct _OBJECT_TYPE process_type
=
2247 create_process_object
2250 POBJECT_TYPE PsProcessType
= &process_type
;
2253 /***********************************************************************
2254 * IoGetCurrentProcess / PsGetCurrentProcess (NTOSKRNL.EXE.@)
2256 PEPROCESS WINAPI
IoGetCurrentProcess(void)
2258 return KeGetCurrentThread()->process
;
2261 /***********************************************************************
2262 * PsLookupProcessByProcessId (NTOSKRNL.EXE.@)
2264 NTSTATUS WINAPI
PsLookupProcessByProcessId( HANDLE processid
, PEPROCESS
*process
)
2269 TRACE( "(%p %p)\n", processid
, process
);
2271 if (!(handle
= OpenProcess( PROCESS_ALL_ACCESS
, FALSE
, HandleToUlong(processid
) )))
2272 return STATUS_INVALID_PARAMETER
;
2274 status
= ObReferenceObjectByHandle( handle
, PROCESS_ALL_ACCESS
, PsProcessType
, KernelMode
, (void**)process
, NULL
);
2280 /*********************************************************************
2281 * PsGetProcessId (NTOSKRNL.@)
2283 HANDLE WINAPI
PsGetProcessId(PEPROCESS process
)
2285 TRACE( "%p -> %lx\n", process
, process
->info
.UniqueProcessId
);
2286 return (HANDLE
)process
->info
.UniqueProcessId
;
2289 /*********************************************************************
2290 * PsGetProcessInheritedFromUniqueProcessId (NTOSKRNL.@)
2292 HANDLE WINAPI
PsGetProcessInheritedFromUniqueProcessId( PEPROCESS process
)
2294 HANDLE id
= (HANDLE
)process
->info
.InheritedFromUniqueProcessId
;
2295 TRACE( "%p -> %p\n", process
, id
);
2299 static void *create_thread_object( HANDLE handle
)
2301 THREAD_BASIC_INFORMATION info
;
2302 struct _KTHREAD
*thread
;
2305 if (!(thread
= alloc_kernel_object( PsThreadType
, handle
, sizeof(*thread
), 0 ))) return NULL
;
2307 thread
->header
.Type
= 6;
2308 thread
->header
.WaitListHead
.Blink
= INVALID_HANDLE_VALUE
; /* mark as kernel object */
2309 thread
->user_affinity
= 0;
2311 if (!NtQueryInformationThread( handle
, ThreadBasicInformation
, &info
, sizeof(info
), NULL
))
2313 thread
->id
= info
.ClientId
;
2314 if ((process
= OpenProcess( PROCESS_QUERY_INFORMATION
, FALSE
, HandleToUlong(thread
->id
.UniqueProcess
) )))
2316 kernel_object_from_handle( process
, PsProcessType
, (void**)&thread
->process
);
2325 static const WCHAR thread_type_name
[] = {'T','h','r','e','a','d',0};
2327 static struct _OBJECT_TYPE thread_type
=
2330 create_thread_object
2333 POBJECT_TYPE PsThreadType
= &thread_type
;
2336 /***********************************************************************
2337 * KeGetCurrentThread / PsGetCurrentThread (NTOSKRNL.EXE.@)
2339 PRKTHREAD WINAPI
KeGetCurrentThread(void)
2341 struct _KTHREAD
*thread
= NtCurrentTeb()->Reserved5
[1];
2345 HANDLE handle
= GetCurrentThread();
2347 /* FIXME: we shouldn't need it, GetCurrentThread() should be client thread already */
2348 if (GetCurrentThreadId() == request_thread
)
2349 handle
= OpenThread( THREAD_QUERY_INFORMATION
, FALSE
, client_tid
);
2351 kernel_object_from_handle( handle
, PsThreadType
, (void**)&thread
);
2352 if (handle
!= GetCurrentThread()) NtClose( handle
);
2354 NtCurrentTeb()->Reserved5
[1] = thread
;
2360 /*****************************************************
2361 * PsLookupThreadByThreadId (NTOSKRNL.EXE.@)
2363 NTSTATUS WINAPI
PsLookupThreadByThreadId( HANDLE threadid
, PETHREAD
*thread
)
2365 OBJECT_ATTRIBUTES attr
;
2370 TRACE( "(%p %p)\n", threadid
, thread
);
2372 cid
.UniqueProcess
= 0;
2373 cid
.UniqueThread
= threadid
;
2374 InitializeObjectAttributes( &attr
, NULL
, 0, NULL
, NULL
);
2375 status
= NtOpenThread( &handle
, THREAD_QUERY_INFORMATION
, &attr
, &cid
);
2376 if (status
) return status
;
2378 status
= ObReferenceObjectByHandle( handle
, THREAD_ALL_ACCESS
, PsThreadType
, KernelMode
, (void**)thread
, NULL
);
2384 /*********************************************************************
2385 * PsGetThreadId (NTOSKRNL.@)
2387 HANDLE WINAPI
PsGetThreadId(PETHREAD thread
)
2389 TRACE( "%p -> %p\n", thread
, thread
->kthread
.id
.UniqueThread
);
2390 return thread
->kthread
.id
.UniqueThread
;
2393 /*********************************************************************
2394 * PsGetThreadProcessId (NTOSKRNL.@)
2396 HANDLE WINAPI
PsGetThreadProcessId( PETHREAD thread
)
2398 TRACE( "%p -> %p\n", thread
, thread
->kthread
.id
.UniqueProcess
);
2399 return thread
->kthread
.id
.UniqueProcess
;
2402 /***********************************************************************
2403 * KeInsertQueue (NTOSKRNL.EXE.@)
2405 LONG WINAPI
KeInsertQueue(PRKQUEUE Queue
, PLIST_ENTRY Entry
)
2407 FIXME( "stub: %p %p\n", Queue
, Entry
);
2411 /**********************************************************************
2412 * KeQueryActiveProcessors (NTOSKRNL.EXE.@)
2414 * Return the active Processors as bitmask
2417 * active Processors as bitmask
2420 KAFFINITY WINAPI
KeQueryActiveProcessors( void )
2422 DWORD_PTR affinity_mask
;
2424 GetProcessAffinityMask( GetCurrentProcess(), NULL
, &affinity_mask
);
2425 return affinity_mask
;
2428 ULONG WINAPI
KeQueryActiveProcessorCountEx(USHORT group_number
)
2430 TRACE("group_number %u.\n", group_number
);
2432 return GetActiveProcessorCount(group_number
);
2435 /**********************************************************************
2436 * KeQueryInterruptTime (NTOSKRNL.EXE.@)
2438 * Return the interrupt time count
2441 ULONGLONG WINAPI
KeQueryInterruptTime( void )
2443 LARGE_INTEGER totaltime
;
2445 KeQueryTickCount(&totaltime
);
2446 return totaltime
.QuadPart
;
2450 /***********************************************************************
2451 * KeQuerySystemTime (NTOSKRNL.EXE.@)
2453 void WINAPI
KeQuerySystemTime( LARGE_INTEGER
*time
)
2455 NtQuerySystemTime( time
);
2459 /***********************************************************************
2460 * KeQueryTickCount (NTOSKRNL.EXE.@)
2462 void WINAPI
KeQueryTickCount( LARGE_INTEGER
*count
)
2464 count
->QuadPart
= NtGetTickCount();
2465 /* update the global variable too */
2466 KeTickCount
.LowPart
= count
->u
.LowPart
;
2467 KeTickCount
.High1Time
= count
->u
.HighPart
;
2468 KeTickCount
.High2Time
= count
->u
.HighPart
;
2472 /***********************************************************************
2473 * KeQueryTimeIncrement (NTOSKRNL.EXE.@)
2475 ULONG WINAPI
KeQueryTimeIncrement(void)
2481 /***********************************************************************
2482 * KeSetPriorityThread (NTOSKRNL.EXE.@)
2484 KPRIORITY WINAPI
KeSetPriorityThread( PKTHREAD Thread
, KPRIORITY Priority
)
2486 FIXME("(%p %d)\n", Thread
, Priority
);
2490 /***********************************************************************
2491 * KeSetSystemAffinityThread (NTOSKRNL.EXE.@)
2493 VOID WINAPI
KeSetSystemAffinityThread(KAFFINITY affinity
)
2495 KeSetSystemAffinityThreadEx(affinity
);
2498 KAFFINITY WINAPI
KeSetSystemAffinityThreadEx(KAFFINITY affinity
)
2500 DWORD_PTR system_affinity
= KeQueryActiveProcessors();
2501 PKTHREAD thread
= KeGetCurrentThread();
2502 GROUP_AFFINITY old
, new;
2504 TRACE("affinity %#lx.\n", affinity
);
2506 affinity
&= system_affinity
;
2508 NtQueryInformationThread(GetCurrentThread(), ThreadGroupInformation
,
2509 &old
, sizeof(old
), NULL
);
2511 if (old
.Mask
!= system_affinity
)
2512 thread
->user_affinity
= old
.Mask
;
2514 memset(&new, 0, sizeof(new));
2515 new.Mask
= affinity
;
2517 return NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &new, sizeof(new))
2518 ? 0 : thread
->user_affinity
;
2522 /***********************************************************************
2523 * KeRevertToUserAffinityThread (NTOSKRNL.EXE.@)
2525 void WINAPI
KeRevertToUserAffinityThread(void)
2527 KeRevertToUserAffinityThreadEx(0);
2530 void WINAPI
KeRevertToUserAffinityThreadEx(KAFFINITY affinity
)
2532 DWORD_PTR system_affinity
= KeQueryActiveProcessors();
2533 PRKTHREAD thread
= KeGetCurrentThread();
2536 TRACE("affinity %#lx.\n", affinity
);
2538 affinity
&= system_affinity
;
2540 memset(&new, 0, sizeof(new));
2541 new.Mask
= affinity
? affinity
2542 : (thread
->user_affinity
? thread
->user_affinity
: system_affinity
);
2544 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &new, sizeof(new));
2545 thread
->user_affinity
= affinity
;
2548 /***********************************************************************
2549 * IoRegisterFileSystem (NTOSKRNL.EXE.@)
2551 VOID WINAPI
IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject
)
2553 FIXME("(%p): stub\n", DeviceObject
);
2556 /***********************************************************************
2557 * KeExpandKernelStackAndCalloutEx (NTOSKRNL.EXE.@)
2559 NTSTATUS WINAPI
KeExpandKernelStackAndCalloutEx(PEXPAND_STACK_CALLOUT callout
, void *parameter
, SIZE_T size
,
2560 BOOLEAN wait
, void *context
)
2562 WARN("(%p %p %lu %x %p) semi-stub: ignoring stack expand\n", callout
, parameter
, size
, wait
, context
);
2564 return STATUS_SUCCESS
;
2567 /***********************************************************************
2568 * KeExpandKernelStackAndCallout (NTOSKRNL.EXE.@)
2570 NTSTATUS WINAPI
KeExpandKernelStackAndCallout(PEXPAND_STACK_CALLOUT callout
, void *parameter
, SIZE_T size
)
2572 return KeExpandKernelStackAndCalloutEx(callout
, parameter
, size
, TRUE
, NULL
);
2575 /***********************************************************************
2576 * IoUnregisterFileSystem (NTOSKRNL.EXE.@)
2578 VOID WINAPI
IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject
)
2580 FIXME("(%p): stub\n", DeviceObject
);
2583 /***********************************************************************
2584 * MmAllocateNonCachedMemory (NTOSKRNL.EXE.@)
2586 PVOID WINAPI
MmAllocateNonCachedMemory( SIZE_T size
)
2588 TRACE( "%lu\n", size
);
2589 return VirtualAlloc( NULL
, size
, MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
|PAGE_NOCACHE
);
2592 /***********************************************************************
2593 * MmAllocateContiguousMemory (NTOSKRNL.EXE.@)
2595 PVOID WINAPI
MmAllocateContiguousMemory( SIZE_T size
, PHYSICAL_ADDRESS highest_valid_address
)
2597 FIXME( "%lu, %s stub\n", size
, wine_dbgstr_longlong(highest_valid_address
.QuadPart
) );
2601 /***********************************************************************
2602 * MmAllocateContiguousMemorySpecifyCache (NTOSKRNL.EXE.@)
2604 PVOID WINAPI
MmAllocateContiguousMemorySpecifyCache( SIZE_T size
,
2605 PHYSICAL_ADDRESS lowest_valid_address
,
2606 PHYSICAL_ADDRESS highest_valid_address
,
2607 PHYSICAL_ADDRESS BoundaryAddressMultiple
,
2608 MEMORY_CACHING_TYPE CacheType
)
2614 /***********************************************************************
2615 * MmAllocatePagesForMdl (NTOSKRNL.EXE.@)
2617 PMDL WINAPI
MmAllocatePagesForMdl(PHYSICAL_ADDRESS lowaddress
, PHYSICAL_ADDRESS highaddress
,
2618 PHYSICAL_ADDRESS skipbytes
, SIZE_T size
)
2620 FIXME("%s %s %s %lu: stub\n", wine_dbgstr_longlong(lowaddress
.QuadPart
), wine_dbgstr_longlong(highaddress
.QuadPart
),
2621 wine_dbgstr_longlong(skipbytes
.QuadPart
), size
);
2625 /***********************************************************************
2626 * MmBuildMdlForNonPagedPool (NTOSKRNL.EXE.@)
2628 void WINAPI
MmBuildMdlForNonPagedPool(MDL
*mdl
)
2630 FIXME("stub: %p\n", mdl
);
2633 /***********************************************************************
2634 * MmCreateSection (NTOSKRNL.EXE.@)
2636 NTSTATUS WINAPI
MmCreateSection( HANDLE
*handle
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
,
2637 LARGE_INTEGER
*size
, ULONG protect
, ULONG alloc_attr
,
2638 HANDLE file
, FILE_OBJECT
*file_obj
)
2640 FIXME("%p %#x %p %s %#x %#x %p %p: stub\n", handle
, access
, attr
,
2641 wine_dbgstr_longlong(size
->QuadPart
), protect
, alloc_attr
, file
, file_obj
);
2642 return STATUS_NOT_IMPLEMENTED
;
2645 /***********************************************************************
2646 * MmFreeNonCachedMemory (NTOSKRNL.EXE.@)
2648 void WINAPI
MmFreeNonCachedMemory( void *addr
, SIZE_T size
)
2650 TRACE( "%p %lu\n", addr
, size
);
2651 VirtualFree( addr
, 0, MEM_RELEASE
);
2654 /***********************************************************************
2655 * MmIsAddressValid (NTOSKRNL.EXE.@)
2657 * Check if the process can access the virtual address without a pagefault
2660 * VirtualAddress [I] Address to check
2664 * Success: TRUE (Accessing the Address works without a Pagefault)
2667 BOOLEAN WINAPI
MmIsAddressValid(PVOID VirtualAddress
)
2669 TRACE("(%p)\n", VirtualAddress
);
2670 return !IsBadReadPtr(VirtualAddress
, 1);
2673 /***********************************************************************
2674 * MmMapIoSpace (NTOSKRNL.EXE.@)
2676 PVOID WINAPI
MmMapIoSpace( PHYSICAL_ADDRESS PhysicalAddress
, DWORD NumberOfBytes
, DWORD CacheType
)
2678 FIXME( "stub: 0x%08x%08x, %d, %d\n", PhysicalAddress
.u
.HighPart
, PhysicalAddress
.u
.LowPart
, NumberOfBytes
, CacheType
);
2683 /***********************************************************************
2684 * MmLockPagableSectionByHandle (NTOSKRNL.EXE.@)
2686 VOID WINAPI
MmLockPagableSectionByHandle(PVOID ImageSectionHandle
)
2688 FIXME("stub %p\n", ImageSectionHandle
);
2691 /***********************************************************************
2692 * MmMapLockedPagesSpecifyCache (NTOSKRNL.EXE.@)
2694 PVOID WINAPI
MmMapLockedPagesSpecifyCache(PMDLX MemoryDescriptorList
, KPROCESSOR_MODE AccessMode
, MEMORY_CACHING_TYPE CacheType
,
2695 PVOID BaseAddress
, ULONG BugCheckOnFailure
, MM_PAGE_PRIORITY Priority
)
2697 FIXME("(%p, %u, %u, %p, %u, %u): stub\n", MemoryDescriptorList
, AccessMode
, CacheType
, BaseAddress
, BugCheckOnFailure
, Priority
);
2702 /***********************************************************************
2703 * MmUnmapLockedPages (NTOSKRNL.EXE.@)
2705 void WINAPI
MmUnmapLockedPages( void *base
, MDL
*mdl
)
2707 FIXME( "(%p %p_\n", base
, mdl
);
2710 /***********************************************************************
2711 * MmUnlockPagableImageSection (NTOSKRNL.EXE.@)
2713 VOID WINAPI
MmUnlockPagableImageSection(PVOID ImageSectionHandle
)
2715 FIXME("stub %p\n", ImageSectionHandle
);
2718 /***********************************************************************
2719 * MmPageEntireDriver (NTOSKRNL.EXE.@)
2721 PVOID WINAPI
MmPageEntireDriver(PVOID AddrInSection
)
2723 TRACE("%p\n", AddrInSection
);
2724 return AddrInSection
;
2728 /***********************************************************************
2729 * MmProbeAndLockPages (NTOSKRNL.EXE.@)
2731 void WINAPI
MmProbeAndLockPages(PMDLX MemoryDescriptorList
, KPROCESSOR_MODE AccessMode
, LOCK_OPERATION Operation
)
2733 FIXME("(%p, %u, %u): stub\n", MemoryDescriptorList
, AccessMode
, Operation
);
2737 /***********************************************************************
2738 * MmResetDriverPaging (NTOSKRNL.EXE.@)
2740 void WINAPI
MmResetDriverPaging(PVOID AddrInSection
)
2742 TRACE("%p\n", AddrInSection
);
2746 /***********************************************************************
2747 * MmUnlockPages (NTOSKRNL.EXE.@)
2749 void WINAPI
MmUnlockPages(PMDLX MemoryDescriptorList
)
2751 FIXME("(%p): stub\n", MemoryDescriptorList
);
2755 /***********************************************************************
2756 * MmUnmapIoSpace (NTOSKRNL.EXE.@)
2758 VOID WINAPI
MmUnmapIoSpace( PVOID BaseAddress
, SIZE_T NumberOfBytes
)
2760 FIXME( "stub: %p, %lu\n", BaseAddress
, NumberOfBytes
);
2764 /***********************************************************************
2765 * ObReferenceObjectByName (NTOSKRNL.EXE.@)
2767 NTSTATUS WINAPI
ObReferenceObjectByName( UNICODE_STRING
*ObjectName
,
2769 ACCESS_STATE
*AccessState
,
2770 ACCESS_MASK DesiredAccess
,
2771 POBJECT_TYPE ObjectType
,
2772 KPROCESSOR_MODE AccessMode
,
2776 struct wine_driver
*driver
;
2777 struct wine_rb_entry
*entry
;
2779 TRACE("mostly-stub:%s %i %p %i %p %i %p %p\n", debugstr_us(ObjectName
),
2780 Attributes
, AccessState
, DesiredAccess
, ObjectType
, AccessMode
,
2781 ParseContext
, Object
);
2783 if (AccessState
) FIXME("Unhandled AccessState\n");
2784 if (DesiredAccess
) FIXME("Unhandled DesiredAccess\n");
2785 if (ParseContext
) FIXME("Unhandled ParseContext\n");
2786 if (ObjectType
) FIXME("Unhandled ObjectType\n");
2788 if (AccessMode
!= KernelMode
)
2790 FIXME("UserMode access not implemented\n");
2791 return STATUS_NOT_IMPLEMENTED
;
2794 EnterCriticalSection(&drivers_cs
);
2795 entry
= wine_rb_get(&wine_drivers
, ObjectName
);
2796 LeaveCriticalSection(&drivers_cs
);
2799 FIXME("Object (%s) not found, may not be tracked.\n", debugstr_us(ObjectName
));
2800 return STATUS_NOT_IMPLEMENTED
;
2803 driver
= WINE_RB_ENTRY_VALUE(entry
, struct wine_driver
, entry
);
2804 ObReferenceObject( *Object
= &driver
->driver_obj
);
2805 return STATUS_SUCCESS
;
2809 /********************************************************************
2810 * ObOpenObjectByName (NTOSKRNL.EXE.@)
2812 NTSTATUS WINAPI
ObOpenObjectByName(POBJECT_ATTRIBUTES attr
, POBJECT_TYPE type
,
2813 KPROCESSOR_MODE mode
, ACCESS_STATE
*access_state
,
2814 ACCESS_MASK access
, PVOID ctx
, HANDLE
*handle
)
2819 TRACE( "attr(%p %s %x) %p %u %p %u %p %p\n", attr
->RootDirectory
, debugstr_us(attr
->ObjectName
),
2820 attr
->Attributes
, type
, mode
, access_state
, access
, ctx
, handle
);
2822 if (mode
!= KernelMode
)
2824 FIXME( "UserMode access not implemented\n" );
2825 return STATUS_NOT_IMPLEMENTED
;
2828 if (attr
->RootDirectory
) FIXME( "RootDirectory unhandled\n" );
2830 status
= ObReferenceObjectByName(attr
->ObjectName
, attr
->Attributes
, access_state
, access
, type
, mode
, ctx
, &object
);
2831 if (status
!= STATUS_SUCCESS
)
2834 status
= ObOpenObjectByPointer(object
, attr
->Attributes
, access_state
, access
, type
, mode
, handle
);
2836 ObDereferenceObject(object
);
2841 /***********************************************************************
2842 * ObReferenceObjectByPointer (NTOSKRNL.EXE.@)
2844 NTSTATUS WINAPI
ObReferenceObjectByPointer(void *obj
, ACCESS_MASK access
,
2846 KPROCESSOR_MODE mode
)
2848 FIXME("(%p, %x, %p, %d): stub\n", obj
, access
, type
, mode
);
2850 return STATUS_NOT_IMPLEMENTED
;
2854 /***********************************************************************
2855 * ObfReferenceObject (NTOSKRNL.EXE.@)
2857 DEFINE_FASTCALL1_WRAPPER( ObfReferenceObject
)
2858 void FASTCALL
ObfReferenceObject( void *obj
)
2860 ObReferenceObject( obj
);
2864 /***********************************************************************
2865 * ObfDereferenceObject (NTOSKRNL.EXE.@)
2867 DEFINE_FASTCALL1_WRAPPER( ObfDereferenceObject
)
2868 void FASTCALL
ObfDereferenceObject( void *obj
)
2870 ObDereferenceObject( obj
);
2873 /***********************************************************************
2874 * ObRegisterCallbacks (NTOSKRNL.EXE.@)
2876 NTSTATUS WINAPI
ObRegisterCallbacks(POB_CALLBACK_REGISTRATION callback
, void **handle
)
2878 FIXME( "callback %p, handle %p.\n", callback
, handle
);
2881 *handle
= UlongToHandle(0xdeadbeaf);
2883 return STATUS_SUCCESS
;
2886 /***********************************************************************
2887 * ObUnRegisterCallbacks (NTOSKRNL.EXE.@)
2889 void WINAPI
ObUnRegisterCallbacks(void *handle
)
2891 FIXME( "stub: %p\n", handle
);
2894 /***********************************************************************
2895 * ObGetFilterVersion (NTOSKRNL.EXE.@)
2897 USHORT WINAPI
ObGetFilterVersion(void)
2901 return OB_FLT_REGISTRATION_VERSION
;
2904 /***********************************************************************
2905 * IoGetAttachedDeviceReference (NTOSKRNL.EXE.@)
2907 DEVICE_OBJECT
* WINAPI
IoGetAttachedDeviceReference( DEVICE_OBJECT
*device
)
2909 DEVICE_OBJECT
*result
= IoGetAttachedDevice( device
);
2910 ObReferenceObject( result
);
2915 /***********************************************************************
2916 * PsCreateSystemThread (NTOSKRNL.EXE.@)
2918 NTSTATUS WINAPI
PsCreateSystemThread(PHANDLE ThreadHandle
, ULONG DesiredAccess
,
2919 POBJECT_ATTRIBUTES ObjectAttributes
,
2920 HANDLE ProcessHandle
, PCLIENT_ID ClientId
,
2921 PKSTART_ROUTINE StartRoutine
, PVOID StartContext
)
2923 if (!ProcessHandle
) ProcessHandle
= GetCurrentProcess();
2924 return RtlCreateUserThread(ProcessHandle
, 0, FALSE
, 0, 0,
2925 0, StartRoutine
, StartContext
,
2926 ThreadHandle
, ClientId
);
2929 /***********************************************************************
2930 * PsGetCurrentProcessId (NTOSKRNL.EXE.@)
2932 HANDLE WINAPI
PsGetCurrentProcessId(void)
2934 return KeGetCurrentThread()->id
.UniqueProcess
;
2938 /***********************************************************************
2939 * PsGetCurrentThreadId (NTOSKRNL.EXE.@)
2941 HANDLE WINAPI
PsGetCurrentThreadId(void)
2943 return KeGetCurrentThread()->id
.UniqueThread
;
2947 /***********************************************************************
2948 * PsIsSystemThread (NTOSKRNL.EXE.@)
2950 BOOLEAN WINAPI
PsIsSystemThread(PETHREAD thread
)
2952 return thread
->kthread
.process
== PsInitialSystemProcess
;
2956 /***********************************************************************
2957 * PsGetVersion (NTOSKRNL.EXE.@)
2959 BOOLEAN WINAPI
PsGetVersion(ULONG
*major
, ULONG
*minor
, ULONG
*build
, UNICODE_STRING
*version
)
2961 RTL_OSVERSIONINFOEXW info
;
2963 info
.dwOSVersionInfoSize
= sizeof(info
);
2964 RtlGetVersion( &info
);
2965 if (major
) *major
= info
.dwMajorVersion
;
2966 if (minor
) *minor
= info
.dwMinorVersion
;
2967 if (build
) *build
= info
.dwBuildNumber
;
2971 #if 0 /* FIXME: GameGuard passes an uninitialized pointer in version->Buffer */
2972 size_t len
= min( lstrlenW(info
.szCSDVersion
)*sizeof(WCHAR
), version
->MaximumLength
);
2973 memcpy( version
->Buffer
, info
.szCSDVersion
, len
);
2974 if (len
< version
->MaximumLength
) version
->Buffer
[len
/ sizeof(WCHAR
)] = 0;
2975 version
->Length
= len
;
2982 /***********************************************************************
2983 * PsImpersonateClient (NTOSKRNL.EXE.@)
2985 NTSTATUS WINAPI
PsImpersonateClient(PETHREAD Thread
, PACCESS_TOKEN Token
, BOOLEAN CopyOnOpen
,
2986 BOOLEAN EffectiveOnly
, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
2988 FIXME("(%p, %p, %u, %u, %u): stub\n", Thread
, Token
, CopyOnOpen
, EffectiveOnly
, ImpersonationLevel
);
2990 return STATUS_NOT_IMPLEMENTED
;
2994 /***********************************************************************
2995 * PsRevertToSelf (NTOSKRNL.EXE.@)
2997 void WINAPI
PsRevertToSelf(void)
3003 /***********************************************************************
3004 * PsSetCreateProcessNotifyRoutine (NTOSKRNL.EXE.@)
3006 NTSTATUS WINAPI
PsSetCreateProcessNotifyRoutine( PCREATE_PROCESS_NOTIFY_ROUTINE callback
, BOOLEAN remove
)
3008 FIXME( "stub: %p %d\n", callback
, remove
);
3009 return STATUS_SUCCESS
;
3013 /***********************************************************************
3014 * PsSetCreateProcessNotifyRoutineEx (NTOSKRNL.EXE.@)
3016 NTSTATUS WINAPI
PsSetCreateProcessNotifyRoutineEx( PCREATE_PROCESS_NOTIFY_ROUTINE_EX callback
, BOOLEAN remove
)
3018 FIXME( "stub: %p %d\n", callback
, remove
);
3019 return STATUS_SUCCESS
;
3023 /***********************************************************************
3024 * PsSetCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
3026 NTSTATUS WINAPI
PsSetCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
3028 FIXME( "stub: %p\n", NotifyRoutine
);
3029 return STATUS_SUCCESS
;
3033 /***********************************************************************
3034 * PsRemoveCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
3036 NTSTATUS WINAPI
PsRemoveCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
3038 FIXME( "stub: %p\n", NotifyRoutine
);
3039 return STATUS_SUCCESS
;
3043 /***********************************************************************
3044 * PsRemoveLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
3046 NTSTATUS WINAPI
PsRemoveLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine
)
3050 TRACE("routine %p.\n", routine
);
3052 for (i
= 0; i
< load_image_notify_routine_count
; ++i
)
3053 if (load_image_notify_routines
[i
] == routine
)
3055 --load_image_notify_routine_count
;
3056 memmove(&load_image_notify_routines
[i
], &load_image_notify_routines
[i
+ 1],
3057 sizeof(*load_image_notify_routines
) * (load_image_notify_routine_count
- i
));
3058 return STATUS_SUCCESS
;
3060 return STATUS_PROCEDURE_NOT_FOUND
;
3064 /***********************************************************************
3065 * PsReferenceProcessFilePointer (NTOSKRNL.EXE.@)
3067 NTSTATUS WINAPI
PsReferenceProcessFilePointer(PEPROCESS process
, FILE_OBJECT
**file
)
3069 FIXME("%p %p\n", process
, file
);
3070 return STATUS_NOT_IMPLEMENTED
;
3074 /***********************************************************************
3075 * PsTerminateSystemThread (NTOSKRNL.EXE.@)
3077 NTSTATUS WINAPI
PsTerminateSystemThread(NTSTATUS status
)
3079 TRACE("status %#x.\n", status
);
3080 ExitThread( status
);
3084 /***********************************************************************
3085 * PsSuspendProcess (NTOSKRNL.EXE.@)
3087 NTSTATUS WINAPI
PsSuspendProcess(PEPROCESS process
)
3089 FIXME("stub: %p\n", process
);
3090 return STATUS_NOT_IMPLEMENTED
;
3094 /***********************************************************************
3095 * PsResumeProcess (NTOSKRNL.EXE.@)
3097 NTSTATUS WINAPI
PsResumeProcess(PEPROCESS process
)
3099 FIXME("stub: %p\n", process
);
3100 return STATUS_NOT_IMPLEMENTED
;
3104 /***********************************************************************
3105 * MmGetSystemRoutineAddress (NTOSKRNL.EXE.@)
3107 PVOID WINAPI
MmGetSystemRoutineAddress(PUNICODE_STRING SystemRoutineName
)
3110 STRING routineNameA
;
3113 static const WCHAR ntoskrnlW
[] = {'n','t','o','s','k','r','n','l','.','e','x','e',0};
3114 static const WCHAR halW
[] = {'h','a','l','.','d','l','l',0};
3116 if (!SystemRoutineName
) return NULL
;
3118 if (RtlUnicodeStringToAnsiString( &routineNameA
, SystemRoutineName
, TRUE
) == STATUS_SUCCESS
)
3120 /* We only support functions exported from ntoskrnl.exe or hal.dll */
3121 hMod
= GetModuleHandleW( ntoskrnlW
);
3122 pFunc
= GetProcAddress( hMod
, routineNameA
.Buffer
);
3125 hMod
= GetModuleHandleW( halW
);
3127 if (hMod
) pFunc
= GetProcAddress( hMod
, routineNameA
.Buffer
);
3129 RtlFreeAnsiString( &routineNameA
);
3133 TRACE( "%s -> %p\n", debugstr_us(SystemRoutineName
), pFunc
);
3135 FIXME( "%s not found\n", debugstr_us(SystemRoutineName
) );
3139 /***********************************************************************
3140 * MmIsThisAnNtAsSystem (NTOSKRNL.EXE.@)
3142 BOOLEAN WINAPI
MmIsThisAnNtAsSystem(void)
3148 /***********************************************************************
3149 * MmProtectMdlSystemAddress (NTOSKRNL.EXE.@)
3151 NTSTATUS WINAPI
MmProtectMdlSystemAddress(PMDL MemoryDescriptorList
, ULONG NewProtect
)
3153 FIXME("(%p, %u) stub\n", MemoryDescriptorList
, NewProtect
);
3154 return STATUS_SUCCESS
;
3157 /***********************************************************************
3158 * MmQuerySystemSize (NTOSKRNL.EXE.@)
3160 MM_SYSTEMSIZE WINAPI
MmQuerySystemSize(void)
3163 return MmLargeSystem
;
3166 /***********************************************************************
3167 * KeInitializeDpc (NTOSKRNL.EXE.@)
3169 void WINAPI
KeInitializeDpc(KDPC
*dpc
, PKDEFERRED_ROUTINE deferred_routine
, void *deferred_context
)
3171 FIXME("dpc %p, deferred_routine %p, deferred_context %p semi-stub.\n",
3172 dpc
, deferred_routine
, deferred_context
);
3174 dpc
->DeferredRoutine
= deferred_routine
;
3175 dpc
->DeferredContext
= deferred_context
;
3178 /***********************************************************************
3179 * KeSetImportanceDpc (NTOSKRNL.EXE.@)
3181 VOID WINAPI
KeSetImportanceDpc(PRKDPC dpc
, KDPC_IMPORTANCE importance
)
3183 FIXME("%p, %d stub\n", dpc
, importance
);
3186 /***********************************************************************
3187 * KeSetTargetProcessorDpc (NTOSKRNL.EXE.@)
3189 VOID WINAPI
KeSetTargetProcessorDpc(PRKDPC dpc
, CCHAR number
)
3191 FIXME("%p, %d stub\n", dpc
, number
);
3194 /***********************************************************************
3195 * READ_REGISTER_BUFFER_UCHAR (NTOSKRNL.EXE.@)
3197 VOID WINAPI
READ_REGISTER_BUFFER_UCHAR(PUCHAR Register
, PUCHAR Buffer
, ULONG Count
)
3202 /*****************************************************
3203 * IoWMIRegistrationControl (NTOSKRNL.EXE.@)
3205 NTSTATUS WINAPI
IoWMIRegistrationControl(PDEVICE_OBJECT DeviceObject
, ULONG Action
)
3207 FIXME("(%p %u) stub\n", DeviceObject
, Action
);
3208 return STATUS_SUCCESS
;
3211 /*****************************************************
3212 * IoWMIOpenBlock (NTOSKRNL.EXE.@)
3214 NTSTATUS WINAPI
IoWMIOpenBlock(LPCGUID guid
, ULONG desired_access
, PVOID
*data_block_obj
)
3216 FIXME("(%p %u %p) stub\n", guid
, desired_access
, data_block_obj
);
3217 return STATUS_NOT_IMPLEMENTED
;
3220 /*****************************************************
3221 * PsSetLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
3223 NTSTATUS WINAPI
PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine
)
3225 FIXME("routine %p, semi-stub.\n", routine
);
3227 if (load_image_notify_routine_count
== ARRAY_SIZE(load_image_notify_routines
))
3228 return STATUS_INSUFFICIENT_RESOURCES
;
3230 load_image_notify_routines
[load_image_notify_routine_count
++] = routine
;
3232 return STATUS_SUCCESS
;
3235 /*****************************************************
3236 * IoSetThreadHardErrorMode (NTOSKRNL.EXE.@)
3238 BOOLEAN WINAPI
IoSetThreadHardErrorMode(BOOLEAN EnableHardErrors
)
3244 /*****************************************************
3245 * Ke386IoSetAccessProcess (NTOSKRNL.EXE.@)
3247 BOOLEAN WINAPI
Ke386IoSetAccessProcess(PEPROCESS
*process
, ULONG flag
)
3249 FIXME("(%p %d) stub\n", process
, flag
);
3253 /*****************************************************
3254 * Ke386SetIoAccessMap (NTOSKRNL.EXE.@)
3256 BOOLEAN WINAPI
Ke386SetIoAccessMap(ULONG flag
, PVOID buffer
)
3258 FIXME("(%d %p) stub\n", flag
, buffer
);
3262 /*****************************************************
3263 * IoStartNextPacket (NTOSKRNL.EXE.@)
3265 VOID WINAPI
IoStartNextPacket(PDEVICE_OBJECT deviceobject
, BOOLEAN cancelable
)
3267 FIXME("(%p %d) stub\n", deviceobject
, cancelable
);
3270 /*****************************************************
3271 * ObQueryNameString (NTOSKRNL.EXE.@)
3273 NTSTATUS WINAPI
ObQueryNameString( void *object
, OBJECT_NAME_INFORMATION
*name
, ULONG size
, ULONG
*ret_size
)
3278 TRACE("object %p, name %p, size %u, ret_size %p.\n", object
, name
, size
, ret_size
);
3280 if ((ret
= ObOpenObjectByPointer( object
, 0, NULL
, 0, NULL
, KernelMode
, &handle
)))
3282 ret
= NtQueryObject( handle
, ObjectNameInformation
, name
, size
, ret_size
);
3288 /*****************************************************
3289 * IoRegisterPlugPlayNotification (NTOSKRNL.EXE.@)
3291 NTSTATUS WINAPI
IoRegisterPlugPlayNotification(IO_NOTIFICATION_EVENT_CATEGORY category
, ULONG flags
, PVOID data
,
3292 PDRIVER_OBJECT driver
, PDRIVER_NOTIFICATION_CALLBACK_ROUTINE callback
,
3293 PVOID context
, PVOID
*notification
)
3295 FIXME("(%u %u %p %p %p %p %p) stub\n", category
, flags
, data
, driver
, callback
, context
, notification
);
3296 return STATUS_SUCCESS
;
3299 /*****************************************************
3300 * IoUnregisterPlugPlayNotification (NTOSKRNL.EXE.@)
3302 NTSTATUS WINAPI
IoUnregisterPlugPlayNotification(PVOID notification
)
3304 FIXME("stub: %p\n", notification
);
3305 return STATUS_SUCCESS
;
3308 /*****************************************************
3309 * IoCsqInitialize (NTOSKRNL.EXE.@)
3311 NTSTATUS WINAPI
IoCsqInitialize(PIO_CSQ csq
, PIO_CSQ_INSERT_IRP insert_irp
, PIO_CSQ_REMOVE_IRP remove_irp
,
3312 PIO_CSQ_PEEK_NEXT_IRP peek_irp
, PIO_CSQ_ACQUIRE_LOCK acquire_lock
,
3313 PIO_CSQ_RELEASE_LOCK release_lock
, PIO_CSQ_COMPLETE_CANCELED_IRP complete_irp
)
3315 FIXME("(%p %p %p %p %p %p %p) stub\n",
3316 csq
, insert_irp
, remove_irp
, peek_irp
, acquire_lock
, release_lock
, complete_irp
);
3317 return STATUS_SUCCESS
;
3320 /***********************************************************************
3321 * KeEnterCriticalRegion (NTOSKRNL.EXE.@)
3323 void WINAPI
KeEnterCriticalRegion(void)
3325 TRACE( "semi-stub\n" );
3326 KeGetCurrentThread()->critical_region
++;
3329 /***********************************************************************
3330 * KeLeaveCriticalRegion (NTOSKRNL.EXE.@)
3332 void WINAPI
KeLeaveCriticalRegion(void)
3334 TRACE( "semi-stub\n" );
3335 KeGetCurrentThread()->critical_region
--;
3338 /***********************************************************************
3339 * KeAreApcsDisabled (NTOSKRNL.@)
3341 BOOLEAN WINAPI
KeAreApcsDisabled(void)
3343 unsigned int critical_region
= KeGetCurrentThread()->critical_region
;
3344 TRACE( "%u\n", critical_region
);
3345 return !!critical_region
;
3348 /***********************************************************************
3349 * KeBugCheck (NTOSKRNL.@)
3351 void WINAPI
KeBugCheck(ULONG code
)
3353 KeBugCheckEx(code
, 0, 0, 0, 0);
3356 /***********************************************************************
3357 * KeBugCheckEx (NTOSKRNL.@)
3359 void WINAPI
KeBugCheckEx(ULONG code
, ULONG_PTR param1
, ULONG_PTR param2
, ULONG_PTR param3
, ULONG_PTR param4
)
3361 ERR( "%x %lx %lx %lx %lx\n", code
, param1
, param2
, param3
, param4
);
3362 ExitProcess( code
);
3365 /***********************************************************************
3366 * ProbeForRead (NTOSKRNL.EXE.@)
3368 void WINAPI
ProbeForRead(void *address
, SIZE_T length
, ULONG alignment
)
3370 FIXME("(%p %lu %u) stub\n", address
, length
, alignment
);
3373 /***********************************************************************
3374 * ProbeForWrite (NTOSKRNL.EXE.@)
3376 void WINAPI
ProbeForWrite(void *address
, SIZE_T length
, ULONG alignment
)
3378 FIXME("(%p %lu %u) stub\n", address
, length
, alignment
);
3381 /***********************************************************************
3382 * CmRegisterCallback (NTOSKRNL.EXE.@)
3384 NTSTATUS WINAPI
CmRegisterCallback(EX_CALLBACK_FUNCTION
*function
, void *context
, LARGE_INTEGER
*cookie
)
3386 FIXME("(%p %p %p): stub\n", function
, context
, cookie
);
3387 return STATUS_NOT_IMPLEMENTED
;
3390 /***********************************************************************
3391 * CmUnRegisterCallback (NTOSKRNL.EXE.@)
3393 NTSTATUS WINAPI
CmUnRegisterCallback(LARGE_INTEGER cookie
)
3395 FIXME("(%s): stub\n", wine_dbgstr_longlong(cookie
.QuadPart
));
3396 return STATUS_NOT_IMPLEMENTED
;
3399 /***********************************************************************
3400 * IoAttachDevice (NTOSKRNL.EXE.@)
3402 NTSTATUS WINAPI
IoAttachDevice(DEVICE_OBJECT
*source
, UNICODE_STRING
*target
, DEVICE_OBJECT
*attached
)
3404 FIXME("(%p, %s, %p): stub\n", source
, debugstr_us(target
), attached
);
3405 return STATUS_NOT_IMPLEMENTED
;
3409 static NTSTATUS
open_driver( const UNICODE_STRING
*service_name
, SC_HANDLE
*service
)
3411 QUERY_SERVICE_CONFIGW
*service_config
= NULL
;
3412 SC_HANDLE manager_handle
;
3413 DWORD config_size
= 0;
3416 if (!(name
= RtlAllocateHeap( GetProcessHeap(), 0, service_name
->Length
+ sizeof(WCHAR
) )))
3417 return STATUS_NO_MEMORY
;
3419 memcpy( name
, service_name
->Buffer
, service_name
->Length
);
3420 name
[ service_name
->Length
/ sizeof(WCHAR
) ] = 0;
3422 if (wcsncmp( name
, servicesW
, lstrlenW(servicesW
) ))
3424 FIXME( "service name %s is not a keypath\n", debugstr_us(service_name
) );
3425 RtlFreeHeap( GetProcessHeap(), 0, name
);
3426 return STATUS_NOT_IMPLEMENTED
;
3429 if (!(manager_handle
= OpenSCManagerW( NULL
, NULL
, SC_MANAGER_CONNECT
)))
3431 WARN( "failed to connect to service manager\n" );
3432 RtlFreeHeap( GetProcessHeap(), 0, name
);
3433 return STATUS_NOT_SUPPORTED
;
3436 *service
= OpenServiceW( manager_handle
, name
+ lstrlenW(servicesW
),
3437 SERVICE_QUERY_CONFIG
| SERVICE_SET_STATUS
);
3438 RtlFreeHeap( GetProcessHeap(), 0, name
);
3439 CloseServiceHandle( manager_handle
);
3443 WARN( "failed to open service %s\n", debugstr_us(service_name
) );
3444 return STATUS_UNSUCCESSFUL
;
3447 QueryServiceConfigW( *service
, NULL
, 0, &config_size
);
3448 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
3450 WARN( "failed to query service config\n" );
3454 if (!(service_config
= RtlAllocateHeap( GetProcessHeap(), 0, config_size
)))
3457 if (!QueryServiceConfigW( *service
, service_config
, config_size
, &config_size
))
3459 WARN( "failed to query service config\n" );
3463 if (service_config
->dwServiceType
!= SERVICE_KERNEL_DRIVER
&&
3464 service_config
->dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
)
3466 WARN( "service %s is not a kernel driver\n", debugstr_us(service_name
) );
3470 TRACE( "opened service for driver %s\n", debugstr_us(service_name
) );
3471 RtlFreeHeap( GetProcessHeap(), 0, service_config
);
3472 return STATUS_SUCCESS
;
3475 CloseServiceHandle( *service
);
3476 RtlFreeHeap( GetProcessHeap(), 0, service_config
);
3477 return STATUS_UNSUCCESSFUL
;
3480 /* find the LDR_DATA_TABLE_ENTRY corresponding to the driver module */
3481 static LDR_DATA_TABLE_ENTRY
*find_ldr_module( HMODULE module
)
3483 LDR_DATA_TABLE_ENTRY
*ldr
;
3486 LdrLockLoaderLock( 0, NULL
, &magic
);
3487 if (LdrFindEntryForAddress( module
, &ldr
))
3489 WARN( "module not found for %p\n", module
);
3492 LdrUnlockLoaderLock( 0, magic
);
3497 /* convert PE image VirtualAddress to Real Address */
3498 static inline void *get_rva( HMODULE module
, DWORD va
)
3500 return (void *)((char *)module
+ va
);
3503 static void WINAPI
ldr_notify_callback(ULONG reason
, LDR_DLL_NOTIFICATION_DATA
*data
, void *context
)
3505 const IMAGE_DATA_DIRECTORY
*relocs
;
3506 IMAGE_BASE_RELOCATION
*rel
, *end
;
3507 SYSTEM_BASIC_INFORMATION info
;
3508 IMAGE_NT_HEADERS
*nt
;
3513 if (reason
!= LDR_DLL_NOTIFICATION_REASON_LOADED
) return;
3514 TRACE( "loading %s\n", debugstr_us(data
->Loaded
.BaseDllName
));
3516 module
= data
->Loaded
.DllBase
;
3517 nt
= RtlImageNtHeader( module
);
3518 base
= (char *)nt
->OptionalHeader
.ImageBase
;
3519 if (!(delta
= (char *)module
- base
)) return;
3521 /* the loader does not apply relocations to non page-aligned binaries or executables,
3522 * we have to do it ourselves */
3524 NtQuerySystemInformation( SystemBasicInformation
, &info
, sizeof(info
), NULL
);
3525 if (nt
->OptionalHeader
.SectionAlignment
>= info
.PageSize
&& (nt
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
))
3528 if (nt
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
3530 WARN( "Need to relocate module from %p to %p, but there are no relocation records\n", base
, module
);
3534 relocs
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
3535 if (!relocs
->Size
|| !relocs
->VirtualAddress
) return;
3537 TRACE( "relocating from %p-%p to %p-%p\n", base
, base
+ nt
->OptionalHeader
.SizeOfImage
,
3538 module
, (char *)module
+ nt
->OptionalHeader
.SizeOfImage
);
3540 rel
= get_rva( module
, relocs
->VirtualAddress
);
3541 end
= get_rva( module
, relocs
->VirtualAddress
+ relocs
->Size
);
3543 while (rel
< end
- 1 && rel
->SizeOfBlock
)
3545 char *page
= get_rva( module
, rel
->VirtualAddress
);
3546 DWORD old_prot1
, old_prot2
;
3548 if (rel
->VirtualAddress
>= nt
->OptionalHeader
.SizeOfImage
)
3550 WARN( "invalid address %p in relocation %p\n", get_rva( module
, rel
->VirtualAddress
), rel
);
3554 /* Relocation entries may hang over the end of the page, so we need to
3555 * protect two pages. */
3556 VirtualProtect( page
, info
.PageSize
, PAGE_READWRITE
, &old_prot1
);
3557 VirtualProtect( page
+ info
.PageSize
, info
.PageSize
, PAGE_READWRITE
, &old_prot2
);
3558 rel
= LdrProcessRelocationBlock( page
, (rel
->SizeOfBlock
- sizeof(*rel
)) / sizeof(USHORT
),
3559 (USHORT
*)(rel
+ 1), delta
);
3560 VirtualProtect( page
, info
.PageSize
, old_prot1
, &old_prot1
);
3561 VirtualProtect( page
+ info
.PageSize
, info
.PageSize
, old_prot2
, &old_prot2
);
3564 WARN( "LdrProcessRelocationBlock failed\n" );
3570 /* load the .sys module for a device driver */
3571 static HMODULE
load_driver( const WCHAR
*driver_name
, const UNICODE_STRING
*keyname
)
3573 static const WCHAR driversW
[] = {'\\','d','r','i','v','e','r','s','\\',0};
3574 static const WCHAR systemrootW
[] = {'\\','S','y','s','t','e','m','R','o','o','t','\\',0};
3575 static const WCHAR postfixW
[] = {'.','s','y','s',0};
3576 static const WCHAR ntprefixW
[] = {'\\','?','?','\\',0};
3577 static const WCHAR ImagePathW
[] = {'I','m','a','g','e','P','a','t','h',0};
3580 LPWSTR path
= NULL
, str
;
3583 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, keyname
->Buffer
+ 18 /* skip \registry\machine */, &driver_hkey
))
3585 ERR( "cannot open key %s, err=%u\n", wine_dbgstr_w(keyname
->Buffer
), GetLastError() );
3589 /* read the executable path from memory */
3591 if (!RegQueryValueExW( driver_hkey
, ImagePathW
, NULL
, &type
, NULL
, &size
))
3593 str
= HeapAlloc( GetProcessHeap(), 0, size
);
3594 if (!RegQueryValueExW( driver_hkey
, ImagePathW
, NULL
, &type
, (LPBYTE
)str
, &size
))
3596 size
= ExpandEnvironmentStringsW(str
,NULL
,0);
3597 path
= HeapAlloc(GetProcessHeap(),0,size
*sizeof(WCHAR
));
3598 ExpandEnvironmentStringsW(str
,path
,size
);
3600 HeapFree( GetProcessHeap(), 0, str
);
3603 RegCloseKey( driver_hkey
);
3607 if (!wcsnicmp( path
, systemrootW
, 12 ))
3609 WCHAR buffer
[MAX_PATH
];
3611 GetWindowsDirectoryW(buffer
, MAX_PATH
);
3613 str
= HeapAlloc(GetProcessHeap(), 0, (size
-11 + lstrlenW(buffer
))
3615 lstrcpyW(str
, buffer
);
3616 lstrcatW(str
, path
+ 11);
3617 HeapFree( GetProcessHeap(), 0, path
);
3620 else if (!wcsncmp( path
, ntprefixW
, 4 ))
3627 /* default is to use the driver name + ".sys" */
3628 WCHAR buffer
[MAX_PATH
];
3629 GetSystemDirectoryW(buffer
, MAX_PATH
);
3630 path
= HeapAlloc(GetProcessHeap(),0,
3631 (lstrlenW(buffer
) + lstrlenW(driversW
) + lstrlenW(driver_name
) + lstrlenW(postfixW
) + 1)
3633 lstrcpyW(path
, buffer
);
3634 lstrcatW(path
, driversW
);
3635 lstrcatW(path
, driver_name
);
3636 lstrcatW(path
, postfixW
);
3639 RegCloseKey( driver_hkey
);
3641 TRACE( "loading driver %s\n", wine_dbgstr_w(str
) );
3643 module
= LoadLibraryW( str
);
3645 if (module
&& load_image_notify_routine_count
)
3647 UNICODE_STRING module_name
;
3648 IMAGE_NT_HEADERS
*nt
;
3652 RtlInitUnicodeString(&module_name
, str
);
3653 nt
= RtlImageNtHeader(module
);
3654 memset(&info
, 0, sizeof(info
));
3655 info
.u
.s
.ImageAddressingMode
= IMAGE_ADDRESSING_MODE_32BIT
;
3656 info
.u
.s
.SystemModeImage
= TRUE
;
3657 info
.ImageSize
= nt
->OptionalHeader
.SizeOfImage
;
3658 info
.ImageBase
= module
;
3660 for (i
= 0; i
< load_image_notify_routine_count
; ++i
)
3662 TRACE("Calling image load notify %p.\n", load_image_notify_routines
[i
]);
3663 load_image_notify_routines
[i
](&module_name
, NULL
, &info
);
3664 TRACE("Called image load notify %p.\n", load_image_notify_routines
[i
]);
3668 HeapFree( GetProcessHeap(), 0, path
);
3672 /* call the driver init entry point */
3673 static NTSTATUS WINAPI
init_driver( DRIVER_OBJECT
*driver_object
, UNICODE_STRING
*keyname
)
3677 const IMAGE_NT_HEADERS
*nt
;
3678 const WCHAR
*driver_name
;
3681 /* Retrieve driver name from the keyname */
3682 driver_name
= wcsrchr( keyname
->Buffer
, '\\' );
3685 module
= load_driver( driver_name
, keyname
);
3687 return STATUS_DLL_INIT_FAILED
;
3689 driver_object
->DriverSection
= find_ldr_module( module
);
3690 driver_object
->DriverStart
= ((LDR_DATA_TABLE_ENTRY
*)driver_object
->DriverSection
)->DllBase
;
3691 driver_object
->DriverSize
= ((LDR_DATA_TABLE_ENTRY
*)driver_object
->DriverSection
)->SizeOfImage
;
3693 nt
= RtlImageNtHeader( module
);
3694 if (!nt
->OptionalHeader
.AddressOfEntryPoint
) return STATUS_SUCCESS
;
3695 driver_object
->DriverInit
= (PDRIVER_INITIALIZE
)((char *)module
+ nt
->OptionalHeader
.AddressOfEntryPoint
);
3697 TRACE_(relay
)( "\1Call driver init %p (obj=%p,str=%s)\n",
3698 driver_object
->DriverInit
, driver_object
, wine_dbgstr_w(keyname
->Buffer
) );
3700 status
= driver_object
->DriverInit( driver_object
, keyname
);
3702 TRACE_(relay
)( "\1Ret driver init %p (obj=%p,str=%s) retval=%08x\n",
3703 driver_object
->DriverInit
, driver_object
, wine_dbgstr_w(keyname
->Buffer
), status
);
3705 TRACE( "init done for %s obj %p\n", wine_dbgstr_w(driver_name
), driver_object
);
3706 TRACE( "- DriverInit = %p\n", driver_object
->DriverInit
);
3707 TRACE( "- DriverStartIo = %p\n", driver_object
->DriverStartIo
);
3708 TRACE( "- DriverUnload = %p\n", driver_object
->DriverUnload
);
3709 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
3710 TRACE( "- MajorFunction[%d] = %p\n", i
, driver_object
->MajorFunction
[i
] );
3715 static BOOLEAN
get_drv_name( UNICODE_STRING
*drv_name
, const UNICODE_STRING
*service_name
)
3717 static const WCHAR driverW
[] = {'\\','D','r','i','v','e','r','\\',0};
3720 if (!(str
= heap_alloc( sizeof(driverW
) + service_name
->Length
- lstrlenW(servicesW
)*sizeof(WCHAR
) )))
3723 lstrcpyW( str
, driverW
);
3724 lstrcpynW( str
+ lstrlenW(driverW
), service_name
->Buffer
+ lstrlenW(servicesW
),
3725 service_name
->Length
/sizeof(WCHAR
) - lstrlenW(servicesW
) + 1 );
3726 RtlInitUnicodeString( drv_name
, str
);
3730 /***********************************************************************
3731 * ZwLoadDriver (NTOSKRNL.EXE.@)
3733 NTSTATUS WINAPI
ZwLoadDriver( const UNICODE_STRING
*service_name
)
3735 SERVICE_STATUS_HANDLE service_handle
;
3736 struct wine_rb_entry
*entry
;
3737 struct wine_driver
*driver
;
3738 UNICODE_STRING drv_name
;
3741 TRACE( "(%s)\n", debugstr_us(service_name
) );
3743 if ((status
= open_driver( service_name
, (SC_HANDLE
*)&service_handle
)) != STATUS_SUCCESS
)
3746 if (!get_drv_name( &drv_name
, service_name
))
3748 CloseServiceHandle( (void *)service_handle
);
3749 return STATUS_NO_MEMORY
;
3752 if (wine_rb_get( &wine_drivers
, &drv_name
))
3754 TRACE( "driver %s already loaded\n", debugstr_us(&drv_name
) );
3755 RtlFreeUnicodeString( &drv_name
);
3756 CloseServiceHandle( (void *)service_handle
);
3757 return STATUS_IMAGE_ALREADY_LOADED
;
3760 set_service_status( service_handle
, SERVICE_START_PENDING
, 0 );
3762 status
= IoCreateDriver( &drv_name
, init_driver
);
3763 entry
= wine_rb_get( &wine_drivers
, &drv_name
);
3764 RtlFreeUnicodeString( &drv_name
);
3765 if (status
!= STATUS_SUCCESS
)
3767 ERR( "failed to create driver %s: %08x\n", debugstr_us(service_name
), status
);
3771 driver
= WINE_RB_ENTRY_VALUE( entry
, struct wine_driver
, entry
);
3772 driver
->service_handle
= service_handle
;
3774 pnp_manager_enumerate_root_devices( service_name
->Buffer
+ wcslen( servicesW
) );
3776 set_service_status( service_handle
, SERVICE_RUNNING
,
3777 SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
3778 return STATUS_SUCCESS
;
3781 set_service_status( service_handle
, SERVICE_STOPPED
, 0 );
3782 CloseServiceHandle( (void *)service_handle
);
3786 /***********************************************************************
3787 * ZwUnloadDriver (NTOSKRNL.EXE.@)
3789 NTSTATUS WINAPI
ZwUnloadDriver( const UNICODE_STRING
*service_name
)
3791 struct wine_rb_entry
*entry
;
3792 UNICODE_STRING drv_name
;
3794 TRACE( "(%s)\n", debugstr_us(service_name
) );
3796 if (!get_drv_name( &drv_name
, service_name
))
3797 return STATUS_NO_MEMORY
;
3799 entry
= wine_rb_get( &wine_drivers
, &drv_name
);
3800 RtlFreeUnicodeString( &drv_name
);
3803 ERR( "failed to locate driver %s\n", debugstr_us(service_name
) );
3804 return STATUS_OBJECT_NAME_NOT_FOUND
;
3807 unload_driver( entry
, NULL
);
3809 return STATUS_SUCCESS
;
3812 /***********************************************************************
3813 * IoCreateFile (NTOSKRNL.EXE.@)
3815 NTSTATUS WINAPI
IoCreateFile(HANDLE
*handle
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
,
3816 IO_STATUS_BLOCK
*io
, LARGE_INTEGER
*alloc_size
, ULONG attributes
, ULONG sharing
,
3817 ULONG disposition
, ULONG create_options
, VOID
*ea_buffer
, ULONG ea_length
,
3818 CREATE_FILE_TYPE file_type
, VOID
*parameters
, ULONG options
)
3821 return STATUS_NOT_IMPLEMENTED
;
3824 /***********************************************************************
3825 * IoCreateNotificationEvent (NTOSKRNL.EXE.@)
3827 PKEVENT WINAPI
IoCreateNotificationEvent(UNICODE_STRING
*name
, HANDLE
*handle
)
3829 FIXME( "stub: %s %p\n", debugstr_us(name
), handle
);
3834 /**************************************************************************
3835 * __chkstk (NTOSKRNL.@)
3838 /* Supposed to touch all the stack pages, but we shouldn't need that. */
3839 __ASM_GLOBAL_FUNC( __chkstk
, "ret" );
3840 #elif defined(__i386__)
3841 __ASM_GLOBAL_FUNC( _chkstk
,
3843 "addl %esp,%eax\n\t"
3844 "xchgl %esp,%eax\n\t"
3845 "movl 0(%eax),%eax\n\t" /* copy return address from old location */
3846 "movl %eax,0(%esp)\n\t"
3848 #elif defined(__arm__)
3849 /* Incoming r4 contains words to allocate, converting to bytes then return */
3850 __ASM_GLOBAL_FUNC( __chkstk
, "lsl r4, r4, #2\n\t"
3852 #elif defined(__aarch64__)
3853 /* Supposed to touch all the stack pages, but we shouldn't need that. */
3854 __ASM_GLOBAL_FUNC( __chkstk
, "ret" );
3857 /*********************************************************************
3858 * PsAcquireProcessExitSynchronization (NTOSKRNL.@)
3860 NTSTATUS WINAPI
PsAcquireProcessExitSynchronization(PEPROCESS process
)
3862 FIXME("stub: %p\n", process
);
3864 return STATUS_NOT_IMPLEMENTED
;
3867 /*********************************************************************
3868 * PsReleaseProcessExitSynchronization (NTOSKRNL.@)
3870 void WINAPI
PsReleaseProcessExitSynchronization(PEPROCESS process
)
3872 FIXME("stub: %p\n", process
);
3875 typedef struct _EX_PUSH_LOCK_WAIT_BLOCK
*PEX_PUSH_LOCK_WAIT_BLOCK
;
3876 /*********************************************************************
3877 * ExfUnblockPushLock (NTOSKRNL.@)
3879 DEFINE_FASTCALL_WRAPPER( ExfUnblockPushLock
, 8 )
3880 void FASTCALL
ExfUnblockPushLock( EX_PUSH_LOCK
*lock
, PEX_PUSH_LOCK_WAIT_BLOCK block
)
3882 FIXME( "stub: %p, %p\n", lock
, block
);
3885 /*********************************************************************
3886 * FsRtlRegisterFileSystemFilterCallbacks (NTOSKRNL.@)
3888 NTSTATUS WINAPI
FsRtlRegisterFileSystemFilterCallbacks( DRIVER_OBJECT
*object
, PFS_FILTER_CALLBACKS callbacks
)
3890 FIXME("stub: %p %p\n", object
, callbacks
);
3891 return STATUS_NOT_IMPLEMENTED
;
3894 /*********************************************************************
3895 * SeSinglePrivilegeCheck (NTOSKRNL.@)
3897 BOOLEAN WINAPI
SeSinglePrivilegeCheck(LUID privilege
, KPROCESSOR_MODE mode
)
3900 if (!once
++) FIXME("stub: %08x%08x %u\n", privilege
.HighPart
, privilege
.LowPart
, mode
);
3904 /*********************************************************************
3905 * SePrivilegeCheck (NTOSKRNL.@)
3907 BOOLEAN WINAPI
SePrivilegeCheck(PRIVILEGE_SET
*privileges
, SECURITY_SUBJECT_CONTEXT
*context
, KPROCESSOR_MODE mode
)
3909 FIXME("stub: %p %p %u\n", privileges
, context
, mode
);
3913 /*********************************************************************
3914 * SeLocateProcessImageName (NTOSKRNL.@)
3916 NTSTATUS WINAPI
SeLocateProcessImageName(PEPROCESS process
, UNICODE_STRING
**image_name
)
3918 FIXME("stub: %p %p\n", process
, image_name
);
3919 if (image_name
) *image_name
= NULL
;
3920 return STATUS_NOT_IMPLEMENTED
;
3923 /*********************************************************************
3924 * KeFlushQueuedDpcs (NTOSKRNL.@)
3926 void WINAPI
KeFlushQueuedDpcs(void)
3931 /*********************************************************************
3932 * DbgQueryDebugFilterState (NTOSKRNL.@)
3934 NTSTATUS WINAPI
DbgQueryDebugFilterState(ULONG component
, ULONG level
)
3936 FIXME("stub: %d %d\n", component
, level
);
3937 return STATUS_NOT_IMPLEMENTED
;
3940 /*********************************************************************
3941 * PsGetProcessWow64Process (NTOSKRNL.@)
3943 PVOID WINAPI
PsGetProcessWow64Process(PEPROCESS process
)
3945 FIXME("stub: %p\n", process
);
3949 /*********************************************************************
3950 * MmCopyVirtualMemory (NTOSKRNL.@)
3952 NTSTATUS WINAPI
MmCopyVirtualMemory(PEPROCESS fromprocess
, void *fromaddress
, PEPROCESS toprocess
,
3953 void *toaddress
, SIZE_T bufsize
, KPROCESSOR_MODE mode
,
3956 FIXME("fromprocess %p, fromaddress %p, toprocess %p, toaddress %p, bufsize %lu, mode %d, copied %p stub.\n",
3957 fromprocess
, fromaddress
, toprocess
, toaddress
, bufsize
, mode
, copied
);
3960 return STATUS_NOT_IMPLEMENTED
;
3963 /*********************************************************************
3964 * KeEnterGuardedRegion (NTOSKRNL.@)
3966 void WINAPI
KeEnterGuardedRegion(void)
3971 /*********************************************************************
3972 * KeLeaveGuardedRegion (NTOSKRNL.@)
3974 void WINAPI
KeLeaveGuardedRegion(void)
3979 static const WCHAR token_type_name
[] = {'T','o','k','e','n',0};
3981 static struct _OBJECT_TYPE token_type
=
3986 POBJECT_TYPE SeTokenObjectType
= &token_type
;
3988 /*************************************************************************
3989 * ExUuidCreate (NTOSKRNL.@)
3991 * Creates a 128bit UUID.
3995 * STATUS_SUCCESS if successful.
3996 * RPC_NT_UUID_LOCAL_ONLY if UUID is only locally unique.
4000 * Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
4001 * Truly Random or Pseudo-Random Numbers)
4003 NTSTATUS WINAPI
ExUuidCreate(UUID
*uuid
)
4005 RtlGenRandom(uuid
, sizeof(*uuid
));
4006 /* Clear the version bits and set the version (4) */
4007 uuid
->Data3
&= 0x0fff;
4008 uuid
->Data3
|= (4 << 12);
4009 /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
4010 * specified in RFC 4122, section 4.4.
4012 uuid
->Data4
[0] &= 0x3f;
4013 uuid
->Data4
[0] |= 0x80;
4015 TRACE("%s\n", debugstr_guid(uuid
));
4017 return STATUS_SUCCESS
;
4020 /***********************************************************************
4021 * ExSetTimerResolution (NTOSKRNL.EXE.@)
4023 ULONG WINAPI
ExSetTimerResolution(ULONG time
, BOOLEAN set_resolution
)
4025 FIXME("stub: %u %d\n", time
, set_resolution
);
4026 return KeQueryTimeIncrement();
4029 /***********************************************************************
4030 * IoGetRequestorProcess (NTOSKRNL.EXE.@)
4032 PEPROCESS WINAPI
IoGetRequestorProcess(IRP
*irp
)
4034 TRACE("irp %p.\n", irp
);
4035 return irp
->Tail
.Overlay
.Thread
->kthread
.process
;
4039 /***********************************************************************
4040 * IoIs32bitProcess (NTOSKRNL.EXE.@)
4042 BOOLEAN WINAPI
IoIs32bitProcess(IRP
*irp
)
4044 TRACE("irp %p.\n", irp
);
4045 return irp
->Tail
.Overlay
.Thread
->kthread
.process
->wow64
;
4049 /***********************************************************************
4050 * RtlIsNtDdiVersionAvailable (NTOSKRNL.EXE.@)
4052 BOOLEAN WINAPI
RtlIsNtDdiVersionAvailable(ULONG version
)
4054 FIXME("stub: %d\n", version
);
4058 BOOLEAN WINAPI
KdRefreshDebuggerNotPresent(void)
4062 return !KdDebuggerEnabled
;
4065 struct generic_call_dpc_context
4067 DEFERRED_REVERSE_BARRIER
*reverse_barrier
;
4068 PKDEFERRED_ROUTINE routine
;
4069 ULONG
*cpu_count_barrier
;
4072 ULONG current_barrier_flag
;
4073 LONG
*barrier_passed_count
;
4076 static void WINAPI
generic_call_dpc_callback(TP_CALLBACK_INSTANCE
*instance
, void *context
)
4078 struct generic_call_dpc_context
*c
= context
;
4079 GROUP_AFFINITY old
, new;
4081 TRACE("instance %p, context %p.\n", instance
, context
);
4083 NtQueryInformationThread(GetCurrentThread(), ThreadGroupInformation
,
4084 &old
, sizeof(old
), NULL
);
4086 memset(&new, 0, sizeof(new));
4088 new.Mask
= 1 << c
->cpu_index
;
4089 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &new, sizeof(new));
4091 TlsSetValue(dpc_call_tls_index
, context
);
4092 c
->routine((PKDPC
)0xdeadbeef, c
->context
, c
->cpu_count_barrier
, c
->reverse_barrier
);
4093 TlsSetValue(dpc_call_tls_index
, NULL
);
4094 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &old
, sizeof(old
));
4097 void WINAPI
KeGenericCallDpc(PKDEFERRED_ROUTINE routine
, void *context
)
4099 ULONG cpu_count
= KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS
);
4100 static struct generic_call_dpc_context
*contexts
;
4101 DEFERRED_REVERSE_BARRIER reverse_barrier
;
4102 static ULONG last_cpu_count
;
4103 LONG barrier_passed_count
;
4104 ULONG cpu_count_barrier
;
4107 TRACE("routine %p, context %p.\n", routine
, context
);
4109 EnterCriticalSection(&dpc_call_cs
);
4113 if (!(dpc_call_tp
= CreateThreadpool(NULL
)))
4115 ERR("Could not create thread pool.\n");
4116 LeaveCriticalSection(&dpc_call_cs
);
4120 SetThreadpoolThreadMinimum(dpc_call_tp
, cpu_count
);
4121 SetThreadpoolThreadMaximum(dpc_call_tp
, cpu_count
);
4123 memset(&dpc_call_tpe
, 0, sizeof(dpc_call_tpe
));
4124 dpc_call_tpe
.Version
= 1;
4125 dpc_call_tpe
.Pool
= dpc_call_tp
;
4128 reverse_barrier
.Barrier
= cpu_count
;
4129 reverse_barrier
.TotalProcessors
= cpu_count
;
4130 cpu_count_barrier
= cpu_count
;
4134 if (last_cpu_count
< cpu_count
)
4136 static struct generic_call_dpc_context
*new_contexts
;
4137 if (!(new_contexts
= heap_realloc(contexts
, sizeof(*contexts
) * cpu_count
)))
4139 ERR("No memory.\n");
4140 LeaveCriticalSection(&dpc_call_cs
);
4143 contexts
= new_contexts
;
4144 SetThreadpoolThreadMinimum(dpc_call_tp
, cpu_count
);
4145 SetThreadpoolThreadMaximum(dpc_call_tp
, cpu_count
);
4148 else if (!(contexts
= heap_alloc(sizeof(*contexts
) * cpu_count
)))
4150 ERR("No memory.\n");
4151 LeaveCriticalSection(&dpc_call_cs
);
4155 memset(contexts
, 0, sizeof(*contexts
) * cpu_count
);
4156 last_cpu_count
= cpu_count
;
4157 barrier_passed_count
= 0;
4159 for (i
= 0; i
< cpu_count
; ++i
)
4161 contexts
[i
].reverse_barrier
= &reverse_barrier
;
4162 contexts
[i
].cpu_count_barrier
= &cpu_count_barrier
;
4163 contexts
[i
].routine
= routine
;
4164 contexts
[i
].context
= context
;
4165 contexts
[i
].cpu_index
= i
;
4166 contexts
[i
].barrier_passed_count
= &barrier_passed_count
;
4168 TrySubmitThreadpoolCallback(generic_call_dpc_callback
, &contexts
[i
], &dpc_call_tpe
);
4171 while (InterlockedCompareExchange((LONG
*)&cpu_count_barrier
, 0, 0))
4174 LeaveCriticalSection(&dpc_call_cs
);
4178 BOOLEAN WINAPI
KeSignalCallDpcSynchronize(void *barrier
)
4180 struct generic_call_dpc_context
*context
= TlsGetValue(dpc_call_tls_index
);
4181 DEFERRED_REVERSE_BARRIER
*b
= barrier
;
4182 LONG curr_flag
, comp
, done_value
;
4185 TRACE("barrier %p, context %p.\n", barrier
, context
);
4189 WARN("Called outside of DPC context.\n");
4193 context
->current_barrier_flag
^= 0x80000000;
4194 curr_flag
= context
->current_barrier_flag
;
4196 first
= !context
->cpu_index
;
4197 comp
= curr_flag
+ context
->cpu_index
;
4198 done_value
= curr_flag
+ b
->TotalProcessors
;
4201 InterlockedExchange((LONG
*)&b
->Barrier
, comp
);
4203 while (InterlockedCompareExchange((LONG
*)&b
->Barrier
, comp
+ 1, comp
) != done_value
)
4206 InterlockedIncrement(context
->barrier_passed_count
);
4208 while (first
&& InterlockedCompareExchange(context
->barrier_passed_count
, 0, b
->TotalProcessors
))
4214 void WINAPI
KeSignalCallDpcDone(void *barrier
)
4216 InterlockedDecrement((LONG
*)barrier
);
4219 void * WINAPI
PsGetProcessSectionBaseAddress(PEPROCESS process
)
4226 TRACE("process %p.\n", process
);
4228 if ((status
= ObOpenObjectByPointer(process
, 0, NULL
, PROCESS_ALL_ACCESS
, NULL
, KernelMode
, &h
)))
4230 WARN("Error opening process object, status %#x.\n", status
);
4234 status
= NtReadVirtualMemory(h
, &process
->info
.PebBaseAddress
->ImageBaseAddress
,
4235 &image_base
, sizeof(image_base
), &size
);
4239 if (status
|| size
!= sizeof(image_base
))
4241 WARN("Error reading process memory, status %#x, size %lu.\n", status
, size
);
4245 TRACE("returning %p.\n", image_base
);
4249 void WINAPI
KeStackAttachProcess(KPROCESS
*process
, KAPC_STATE
*apc_state
)
4251 FIXME("process %p, apc_state %p stub.\n", process
, apc_state
);
4254 void WINAPI
KeUnstackDetachProcess(KAPC_STATE
*apc_state
)
4256 FIXME("apc_state %p stub.\n", apc_state
);
4259 NTSTATUS WINAPI
KdDisableDebugger(void)
4262 return STATUS_DEBUGGER_INACTIVE
;
4265 NTSTATUS WINAPI
KdEnableDebugger(void)
4268 return STATUS_DEBUGGER_INACTIVE
;
4271 /*****************************************************
4274 BOOL WINAPI
DllMain( HINSTANCE inst
, DWORD reason
, LPVOID reserved
)
4276 static void *handler
;
4277 LARGE_INTEGER count
;
4281 case DLL_PROCESS_ATTACH
:
4282 DisableThreadLibraryCalls( inst
);
4283 #if defined(__i386__) || defined(__x86_64__)
4284 handler
= RtlAddVectoredExceptionHandler( TRUE
, vectored_handler
);
4286 KeQueryTickCount( &count
); /* initialize the global KeTickCount */
4287 NtBuildNumber
= NtCurrentTeb()->Peb
->OSBuildNumber
;
4288 ntoskrnl_heap
= HeapCreate( HEAP_CREATE_ENABLE_EXECUTE
, 0, 0 );
4289 dpc_call_tls_index
= TlsAlloc();
4290 LdrRegisterDllNotification( 0, ldr_notify_callback
, NULL
, &ldr_notify_cookie
);
4292 case DLL_PROCESS_DETACH
:
4293 LdrUnregisterDllNotification( ldr_notify_cookie
);
4295 if (reserved
) break;
4298 CloseThreadpool(dpc_call_tp
);
4300 HeapDestroy( ntoskrnl_heap
);
4301 RtlRemoveVectoredExceptionHandler( handler
);