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
26 #include "ntoskrnl_private.h"
32 #include "wine/server.h"
33 #include "wine/heap.h"
34 #include "wine/svcctl.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl
);
37 WINE_DECLARE_DEBUG_CHANNEL(relay
);
39 BOOLEAN KdDebuggerEnabled
= FALSE
;
40 ULONG InitSafeBootMode
= 0;
41 USHORT NtBuildNumber
= 0;
43 extern LONG CALLBACK
vectored_handler( EXCEPTION_POINTERS
*ptrs
);
45 KSYSTEM_TIME KeTickCount
= { 0, 0, 0 };
47 typedef struct _KSERVICE_TABLE_DESCRIPTOR
53 } KSERVICE_TABLE_DESCRIPTOR
, *PKSERVICE_TABLE_DESCRIPTOR
;
55 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable
[4] = { { 0 } };
57 #define MAX_SERVICE_NAME 260
59 static TP_POOL
*dpc_call_tp
;
60 static TP_CALLBACK_ENVIRON dpc_call_tpe
;
61 DECLARE_CRITICAL_SECTION(dpc_call_cs
);
62 static DWORD dpc_call_tls_index
;
64 /* tid of the thread running client request */
65 static DWORD request_thread
;
67 /* tid of the client thread */
68 static DWORD client_tid
;
70 static HANDLE ntoskrnl_heap
;
72 static void *ldr_notify_cookie
;
74 static PLOAD_IMAGE_NOTIFY_ROUTINE load_image_notify_routines
[8];
75 static unsigned int load_image_notify_routine_count
;
85 static int wine_drivers_rb_compare( const void *key
, const struct wine_rb_entry
*entry
)
87 const struct wine_driver
*driver
= WINE_RB_ENTRY_VALUE( entry
, const struct wine_driver
, entry
);
88 const UNICODE_STRING
*k
= key
;
90 return RtlCompareUnicodeString( k
, &driver
->driver_obj
.DriverName
, TRUE
);
93 static struct wine_rb_tree wine_drivers
= { wine_drivers_rb_compare
};
95 DECLARE_CRITICAL_SECTION(drivers_cs
);
97 struct wine_driver
*get_driver( const WCHAR
*name
)
99 static const WCHAR driverW
[] = L
"\\Driver\\";
100 struct wine_rb_entry
*entry
;
101 UNICODE_STRING drv_name
;
103 drv_name
.Length
= (wcslen( driverW
) + wcslen( name
)) * sizeof(WCHAR
);
104 if (!(drv_name
.Buffer
= malloc( drv_name
.Length
+ sizeof(WCHAR
) )))
106 wcscpy( drv_name
.Buffer
, driverW
);
107 wcscat( drv_name
.Buffer
, name
);
108 entry
= wine_rb_get( &wine_drivers
, &drv_name
);
109 free( drv_name
.Buffer
);
111 if (entry
) return WINE_RB_ENTRY_VALUE( entry
, struct wine_driver
, entry
);
115 static HANDLE
get_device_manager(void)
117 static HANDLE device_manager
;
118 HANDLE handle
= 0, ret
= device_manager
;
122 SERVER_START_REQ( create_device_manager
)
124 req
->access
= SYNCHRONIZE
;
126 if (!wine_server_call( req
)) handle
= wine_server_ptr_handle( reply
->handle
);
132 ERR( "failed to create the device manager\n" );
135 if (!(ret
= InterlockedCompareExchangePointer( &device_manager
, handle
, 0 )))
138 NtClose( handle
); /* somebody beat us to it */
150 static void free_kernel_object( void *obj
)
152 struct object_header
*header
= (struct object_header
*)obj
- 1;
153 HeapFree( GetProcessHeap(), 0, header
);
156 void *alloc_kernel_object( POBJECT_TYPE type
, HANDLE handle
, SIZE_T size
, LONG ref
)
158 struct object_header
*header
;
160 if (!(header
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*header
) + size
)) )
166 SERVER_START_REQ( set_kernel_object_ptr
)
168 req
->manager
= wine_server_obj_handle( get_device_manager() );
169 req
->handle
= wine_server_obj_handle( handle
);
170 req
->user_ptr
= wine_server_client_ptr( header
+ 1 );
171 status
= wine_server_call( req
);
174 if (status
) FIXME( "set_object_reference failed: %#lx\n", status
);
182 DECLARE_CRITICAL_SECTION(obref_cs
);
184 /***********************************************************************
185 * ObDereferenceObject (NTOSKRNL.EXE.@)
187 void WINAPI
ObDereferenceObject( void *obj
)
189 struct object_header
*header
= (struct object_header
*)obj
- 1;
198 EnterCriticalSection( &obref_cs
);
201 TRACE( "(%p) ref=%lu\n", obj
, ref
);
204 if (header
->type
->release
)
206 header
->type
->release( obj
);
210 SERVER_START_REQ( release_kernel_object
)
212 req
->manager
= wine_server_obj_handle( get_device_manager() );
213 req
->user_ptr
= wine_server_client_ptr( obj
);
214 if (wine_server_call( req
)) FIXME( "failed to release %p\n", obj
);
220 LeaveCriticalSection( &obref_cs
);
223 void ObReferenceObject( void *obj
)
225 struct object_header
*header
= (struct object_header
*)obj
- 1;
234 EnterCriticalSection( &obref_cs
);
237 TRACE( "(%p) ref=%lu\n", obj
, ref
);
240 SERVER_START_REQ( grab_kernel_object
)
242 req
->manager
= wine_server_obj_handle( get_device_manager() );
243 req
->user_ptr
= wine_server_client_ptr( obj
);
244 if (wine_server_call( req
)) FIXME( "failed to grab %p reference\n", obj
);
249 LeaveCriticalSection( &obref_cs
);
252 /***********************************************************************
253 * ObGetObjectType (NTOSKRNL.EXE.@)
255 POBJECT_TYPE WINAPI
ObGetObjectType( void *object
)
257 struct object_header
*header
= (struct object_header
*)object
- 1;
261 static const POBJECT_TYPE
*known_types
[] =
264 &ExSemaphoreObjectType
,
273 DECLARE_CRITICAL_SECTION(handle_map_cs
);
275 NTSTATUS
kernel_object_from_handle( HANDLE handle
, POBJECT_TYPE type
, void **ret
)
280 EnterCriticalSection( &handle_map_cs
);
282 SERVER_START_REQ( get_kernel_object_ptr
)
284 req
->manager
= wine_server_obj_handle( get_device_manager() );
285 req
->handle
= wine_server_obj_handle( handle
);
286 status
= wine_server_call( req
);
287 obj
= wine_server_get_ptr( reply
->user_ptr
);
292 LeaveCriticalSection( &handle_map_cs
);
299 OBJECT_TYPE_INFORMATION
*type_info
= (OBJECT_TYPE_INFORMATION
*)buf
;
302 status
= NtQueryObject( handle
, ObjectTypeInformation
, buf
, sizeof(buf
), &size
);
305 LeaveCriticalSection( &handle_map_cs
);
311 for (i
= 0; i
< ARRAY_SIZE(known_types
); i
++)
313 type
= *known_types
[i
];
314 if (!RtlCompareUnicodeStrings( type
->name
, lstrlenW(type
->name
), type_info
->TypeName
.Buffer
,
315 type_info
->TypeName
.Length
/ sizeof(WCHAR
), FALSE
))
318 if (i
== ARRAY_SIZE(known_types
))
320 FIXME("Unsupported type %s\n", debugstr_us(&type_info
->TypeName
));
321 LeaveCriticalSection( &handle_map_cs
);
322 return STATUS_INVALID_HANDLE
;
325 else if (RtlCompareUnicodeStrings( type
->name
, lstrlenW(type
->name
), type_info
->TypeName
.Buffer
,
326 type_info
->TypeName
.Length
/ sizeof(WCHAR
), FALSE
) )
328 LeaveCriticalSection( &handle_map_cs
);
329 return STATUS_OBJECT_TYPE_MISMATCH
;
332 if (type
->constructor
)
333 obj
= type
->constructor( handle
);
336 FIXME( "No constructor for type %s\n", debugstr_w(type
->name
) );
337 obj
= alloc_kernel_object( type
, handle
, 0, 0 );
339 if (!obj
) status
= STATUS_NO_MEMORY
;
341 else if (type
&& ObGetObjectType( obj
) != type
) status
= STATUS_OBJECT_TYPE_MISMATCH
;
343 LeaveCriticalSection( &handle_map_cs
);
344 if (!status
) *ret
= obj
;
348 /***********************************************************************
349 * ObReferenceObjectByHandle (NTOSKRNL.EXE.@)
351 NTSTATUS WINAPI
ObReferenceObjectByHandle( HANDLE handle
, ACCESS_MASK access
,
353 KPROCESSOR_MODE mode
, void **ptr
,
354 POBJECT_HANDLE_INFORMATION info
)
358 TRACE( "%p %lx %p %d %p %p\n", handle
, access
, type
, mode
, ptr
, info
);
360 if (mode
!= KernelMode
)
362 FIXME("UserMode access not implemented\n");
363 return STATUS_NOT_IMPLEMENTED
;
366 status
= kernel_object_from_handle( handle
, type
, ptr
);
367 if (!status
) ObReferenceObject( *ptr
);
371 /***********************************************************************
372 * ObOpenObjectByPointer (NTOSKRNL.EXE.@)
374 NTSTATUS WINAPI
ObOpenObjectByPointer( void *obj
, ULONG attr
, ACCESS_STATE
*access_state
,
375 ACCESS_MASK access
, POBJECT_TYPE type
,
376 KPROCESSOR_MODE mode
, HANDLE
*handle
)
380 TRACE( "%p %lx %p %lx %p %d %p\n", obj
, attr
, access_state
, access
, type
, mode
, handle
);
382 if (mode
!= KernelMode
)
384 FIXME( "UserMode access not implemented\n" );
385 return STATUS_NOT_IMPLEMENTED
;
388 if (attr
& ~OBJ_KERNEL_HANDLE
) FIXME( "attr %#lx not supported\n", attr
);
389 if (access_state
) FIXME( "access_state not implemented\n" );
391 if (type
&& ObGetObjectType( obj
) != type
) return STATUS_OBJECT_TYPE_MISMATCH
;
393 SERVER_START_REQ( get_kernel_object_handle
)
395 req
->manager
= wine_server_obj_handle( get_device_manager() );
396 req
->user_ptr
= wine_server_client_ptr( obj
);
397 req
->access
= access
;
398 if (!(status
= wine_server_call( req
)))
399 *handle
= wine_server_ptr_handle( reply
->handle
);
406 static void *create_file_object( HANDLE handle
);
408 static const WCHAR file_type_name
[] = {'F','i','l','e',0};
410 static struct _OBJECT_TYPE file_type
= {
415 POBJECT_TYPE IoFileObjectType
= &file_type
;
417 static void *create_file_object( HANDLE handle
)
420 if (!(file
= alloc_kernel_object( IoFileObjectType
, handle
, sizeof(*file
), 0 ))) return NULL
;
421 file
->Type
= 5; /* MSDN */
422 file
->Size
= sizeof(*file
);
426 DECLARE_CRITICAL_SECTION(irp_completion_cs
);
428 static void free_dispatch_irp( struct irp_data
*irp_data
)
430 IRP
*irp
= irp_data
->irp
;
432 if (irp
->UserBuffer
!= irp
->AssociatedIrp
.SystemBuffer
)
434 HeapFree( GetProcessHeap(), 0, irp
->UserBuffer
);
435 irp
->UserBuffer
= NULL
;
441 static ULONG
get_irp_output_size( IRP
*irp
)
443 IO_STACK_LOCATION
*stack
= IoGetNextIrpStackLocation( irp
);
445 if (!irp
->UserBuffer
|| (irp
->Flags
& IRP_WRITE_OPERATION
))
448 /* For IRPs not using buffered I/O, the driver is supposed to have direct
449 * access to the user's output buffer, either via an MDL (direct I/O) or
450 * with the raw user VA (neither). We can't fully support this, but we
451 * should at least copy the entire buffer back to the caller. */
452 switch (stack
->MajorFunction
)
454 case IRP_MJ_FILE_SYSTEM_CONTROL
:
455 case IRP_MJ_DEVICE_CONTROL
:
456 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
457 if ((stack
->Parameters
.DeviceIoControl
.IoControlCode
& 3) != METHOD_BUFFERED
)
458 return stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
462 /* FIXME: Handle non-buffered reads. */
467 if (NT_ERROR(irp
->IoStatus
.Status
))
469 return irp
->IoStatus
.Information
;
472 /* transfer result of IRP back to wineserver */
473 static NTSTATUS WINAPI
dispatch_irp_completion( DEVICE_OBJECT
*device
, IRP
*irp
, void *context
)
475 struct irp_data
*irp_data
= context
;
479 EnterCriticalSection( &irp_completion_cs
);
481 irp_data
->complete
= TRUE
;
482 if (!irp_data
->async
)
484 /* main loop will report completion via get_next_device_request */
485 LeaveCriticalSection( &irp_completion_cs
);
486 return STATUS_MORE_PROCESSING_REQUIRED
;
489 out_size
= get_irp_output_size( irp
);
491 SERVER_START_REQ( set_irp_result
)
493 req
->handle
= wine_server_obj_handle( irp_data
->handle
);
494 req
->status
= irp
->IoStatus
.Status
;
495 req
->size
= irp
->IoStatus
.Information
;
496 if (out_size
) wine_server_add_data( req
, irp
->UserBuffer
, out_size
);
497 status
= wine_server_call( req
);
501 free_dispatch_irp( irp_data
);
503 LeaveCriticalSection( &irp_completion_cs
);
507 struct dispatch_context
511 struct irp_data
*irp_data
;
516 static NTSTATUS
dispatch_irp( DEVICE_OBJECT
*device
, IRP
*irp
, struct dispatch_context
*context
)
518 struct irp_data
*irp_data
;
522 if (!(irp_data
= malloc( sizeof(*irp_data
) )))
523 return STATUS_NO_MEMORY
;
524 irp_data
->handle
= context
->handle
;
526 irp_data
->async
= FALSE
;
527 irp_data
->complete
= FALSE
;
529 IoSetCompletionRoutine( irp
, dispatch_irp_completion
, irp_data
, TRUE
, TRUE
, TRUE
);
530 context
->irp_data
= irp_data
;
533 KeQueryTickCount( &count
); /* update the global KeTickCount */
535 device
->CurrentIrp
= irp
;
536 KeEnterCriticalRegion();
537 status
= IoCallDriver( device
, irp
);
538 KeLeaveCriticalRegion();
539 device
->CurrentIrp
= NULL
;
541 if (status
!= STATUS_PENDING
&& !irp_data
->complete
)
542 ERR( "dispatch routine returned %#lx but didn't complete the IRP\n", status
);
547 /* process a create request for a given file */
548 static NTSTATUS
dispatch_create( struct dispatch_context
*context
)
551 IO_STACK_LOCATION
*irpsp
;
553 DEVICE_OBJECT
*device
= wine_server_get_ptr( context
->params
.create
.device
);
554 HANDLE handle
= wine_server_ptr_handle( context
->params
.create
.file
);
556 if (!(file
= alloc_kernel_object( IoFileObjectType
, handle
, sizeof(*file
), 0 )))
557 return STATUS_NO_MEMORY
;
559 TRACE( "device %p -> file %p\n", device
, file
);
561 file
->Type
= 5; /* MSDN */
562 file
->Size
= sizeof(*file
);
563 file
->DeviceObject
= device
;
565 device
= IoGetAttachedDevice( device
);
567 if (!(irp
= IoAllocateIrp( device
->StackSize
, FALSE
))) return STATUS_NO_MEMORY
;
569 irpsp
= IoGetNextIrpStackLocation( irp
);
570 irpsp
->MajorFunction
= IRP_MJ_CREATE
;
571 irpsp
->FileObject
= file
;
572 irpsp
->Parameters
.Create
.SecurityContext
= NULL
; /* FIXME */
573 irpsp
->Parameters
.Create
.Options
= context
->params
.create
.options
;
574 irpsp
->Parameters
.Create
.ShareAccess
= context
->params
.create
.sharing
;
575 irpsp
->Parameters
.Create
.FileAttributes
= 0;
576 irpsp
->Parameters
.Create
.EaLength
= 0;
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_CREATE_OPERATION
;
587 return dispatch_irp( device
, irp
, context
);
590 /* process a close request for a given file */
591 static NTSTATUS
dispatch_close( struct dispatch_context
*context
)
594 IO_STACK_LOCATION
*irpsp
;
595 DEVICE_OBJECT
*device
;
596 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.close
.file
);
598 if (!file
) return STATUS_INVALID_HANDLE
;
600 device
= IoGetAttachedDevice( file
->DeviceObject
);
602 TRACE( "device %p file %p\n", device
, file
);
604 if (!(irp
= IoAllocateIrp( device
->StackSize
, FALSE
)))
606 ObDereferenceObject( file
);
607 return STATUS_NO_MEMORY
;
610 irpsp
= IoGetNextIrpStackLocation( irp
);
611 irpsp
->MajorFunction
= IRP_MJ_CLOSE
;
612 irpsp
->FileObject
= file
;
614 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
615 irp
->Tail
.Overlay
.Thread
= (PETHREAD
)KeGetCurrentThread();
616 irp
->RequestorMode
= UserMode
;
617 irp
->AssociatedIrp
.SystemBuffer
= NULL
;
618 irp
->UserBuffer
= NULL
;
619 irp
->UserIosb
= NULL
;
620 irp
->UserEvent
= NULL
;
622 irp
->Flags
|= IRP_CLOSE_OPERATION
;
623 return dispatch_irp( device
, irp
, context
);
626 /* process a read request for a given device */
627 static NTSTATUS
dispatch_read( struct dispatch_context
*context
)
631 LARGE_INTEGER offset
;
632 IO_STACK_LOCATION
*irpsp
;
633 DEVICE_OBJECT
*device
;
634 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.read
.file
);
635 ULONG out_size
= context
->params
.read
.out_size
;
637 if (!file
) return STATUS_INVALID_HANDLE
;
639 device
= IoGetAttachedDevice( file
->DeviceObject
);
641 TRACE( "device %p file %p size %lu\n", device
, file
, out_size
);
643 if (!(out_buff
= HeapAlloc( GetProcessHeap(), 0, out_size
))) return STATUS_NO_MEMORY
;
645 offset
.QuadPart
= context
->params
.read
.pos
;
647 if (!(irp
= IoBuildSynchronousFsdRequest( IRP_MJ_READ
, device
, out_buff
, out_size
,
648 &offset
, NULL
, NULL
)))
650 HeapFree( GetProcessHeap(), 0, out_buff
);
651 return STATUS_NO_MEMORY
;
654 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
655 irp
->RequestorMode
= UserMode
;
657 irpsp
= IoGetNextIrpStackLocation( irp
);
658 irpsp
->FileObject
= file
;
659 irpsp
->Parameters
.Read
.Key
= context
->params
.read
.key
;
661 irp
->Flags
|= IRP_READ_OPERATION
;
662 irp
->Flags
|= IRP_DEALLOCATE_BUFFER
; /* deallocate out_buff */
663 return dispatch_irp( device
, irp
, context
);
666 /* process a write request for a given device */
667 static NTSTATUS
dispatch_write( struct dispatch_context
*context
)
670 LARGE_INTEGER offset
;
671 IO_STACK_LOCATION
*irpsp
;
672 DEVICE_OBJECT
*device
;
673 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.write
.file
);
675 if (!file
) return STATUS_INVALID_HANDLE
;
677 device
= IoGetAttachedDevice( file
->DeviceObject
);
679 TRACE( "device %p file %p size %lu\n", device
, file
, context
->in_size
);
681 offset
.QuadPart
= context
->params
.write
.pos
;
683 if (!(irp
= IoBuildSynchronousFsdRequest( IRP_MJ_WRITE
, device
, context
->in_buff
, context
->in_size
,
684 &offset
, NULL
, NULL
)))
685 return STATUS_NO_MEMORY
;
686 context
->in_buff
= NULL
;
688 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
689 irp
->RequestorMode
= UserMode
;
691 irpsp
= IoGetNextIrpStackLocation( irp
);
692 irpsp
->FileObject
= file
;
693 irpsp
->Parameters
.Write
.Key
= context
->params
.write
.key
;
695 irp
->Flags
|= IRP_WRITE_OPERATION
;
696 irp
->Flags
|= IRP_DEALLOCATE_BUFFER
; /* deallocate in_buff */
697 return dispatch_irp( device
, irp
, context
);
700 /* process a flush request for a given device */
701 static NTSTATUS
dispatch_flush( struct dispatch_context
*context
)
704 IO_STACK_LOCATION
*irpsp
;
705 DEVICE_OBJECT
*device
;
706 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.flush
.file
);
708 if (!file
) return STATUS_INVALID_HANDLE
;
710 device
= IoGetAttachedDevice( file
->DeviceObject
);
712 TRACE( "device %p file %p\n", device
, file
);
714 if (!(irp
= IoBuildSynchronousFsdRequest( IRP_MJ_FLUSH_BUFFERS
, device
, NULL
, 0,
716 return STATUS_NO_MEMORY
;
718 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
719 irp
->RequestorMode
= UserMode
;
721 irpsp
= IoGetNextIrpStackLocation( irp
);
722 irpsp
->FileObject
= file
;
724 return dispatch_irp( device
, irp
, context
);
727 /* process an ioctl request for a given device */
728 static NTSTATUS
dispatch_ioctl( struct dispatch_context
*context
)
730 IO_STACK_LOCATION
*irpsp
;
732 void *out_buff
= NULL
;
733 void *to_free
= NULL
;
734 DEVICE_OBJECT
*device
;
735 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.ioctl
.file
);
736 ULONG out_size
= context
->params
.ioctl
.out_size
;
739 if (!file
) return STATUS_INVALID_HANDLE
;
741 device
= IoGetAttachedDevice( file
->DeviceObject
);
743 TRACE( "ioctl %x device %p file %p in_size %lu out_size %lu\n",
744 context
->params
.ioctl
.code
, device
, file
, context
->in_size
, out_size
);
748 if ((context
->params
.ioctl
.code
& 3) != METHOD_BUFFERED
)
750 if (context
->in_size
< out_size
) return STATUS_INVALID_DEVICE_REQUEST
;
751 context
->in_size
-= out_size
;
752 if (!(out_buff
= HeapAlloc( GetProcessHeap(), 0, out_size
))) return STATUS_NO_MEMORY
;
753 memcpy( out_buff
, (char *)context
->in_buff
+ context
->in_size
, out_size
);
755 else if (out_size
> context
->in_size
)
757 if (!(out_buff
= HeapAlloc( GetProcessHeap(), 0, out_size
))) return STATUS_NO_MEMORY
;
758 memcpy( out_buff
, context
->in_buff
, context
->in_size
);
759 to_free
= context
->in_buff
;
760 context
->in_buff
= out_buff
;
763 out_buff
= context
->in_buff
;
766 irp
= IoBuildDeviceIoControlRequest( context
->params
.ioctl
.code
, device
, context
->in_buff
,
767 context
->in_size
, out_buff
, out_size
, FALSE
, NULL
, NULL
);
770 HeapFree( GetProcessHeap(), 0, out_buff
);
771 return STATUS_NO_MEMORY
;
774 if (out_size
&& (context
->params
.ioctl
.code
& 3) != METHOD_BUFFERED
)
775 HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY
, context
->in_buff
, context
->in_size
);
777 irpsp
= IoGetNextIrpStackLocation( irp
);
778 irpsp
->FileObject
= file
;
780 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
781 irp
->RequestorMode
= UserMode
;
782 irp
->AssociatedIrp
.SystemBuffer
= context
->in_buff
;
783 context
->in_buff
= NULL
;
785 irp
->Flags
|= IRP_DEALLOCATE_BUFFER
; /* deallocate in_buff */
786 status
= dispatch_irp( device
, irp
, context
);
788 HeapFree( GetProcessHeap(), 0, to_free
);
792 /* process a volume information request for a given device */
793 static NTSTATUS
dispatch_volume( struct dispatch_context
*context
)
795 IO_STACK_LOCATION
*irpsp
;
797 void *out_buff
= NULL
;
798 DEVICE_OBJECT
*device
;
799 FILE_OBJECT
*file
= wine_server_get_ptr( context
->params
.volume
.file
);
800 ULONG out_size
= context
->params
.volume
.out_size
;
802 if (!file
) return STATUS_INVALID_HANDLE
;
804 device
= IoGetAttachedDevice( file
->DeviceObject
);
806 TRACE( "class 0x%x device %p file %p in_size %lu out_size %lu\n",
807 context
->params
.volume
.info_class
, device
, file
, context
->in_size
, out_size
);
809 if (!(out_buff
= HeapAlloc( GetProcessHeap(), 0, out_size
))) return STATUS_NO_MEMORY
;
811 irp
= IoAllocateIrp( device
->StackSize
, FALSE
);
814 HeapFree( GetProcessHeap(), 0, out_buff
);
815 return STATUS_NO_MEMORY
;
818 irpsp
= IoGetNextIrpStackLocation( irp
);
819 irpsp
->MajorFunction
= IRP_MJ_QUERY_VOLUME_INFORMATION
;
820 irpsp
->Parameters
.QueryVolume
.FsInformationClass
= context
->params
.volume
.info_class
;
821 irpsp
->Parameters
.QueryVolume
.Length
= out_size
;
822 irpsp
->DeviceObject
= NULL
;
823 irpsp
->CompletionRoutine
= NULL
;
824 irpsp
->FileObject
= file
;
825 irp
->AssociatedIrp
.SystemBuffer
= out_buff
;
826 irp
->RequestorMode
= KernelMode
;
827 irp
->UserBuffer
= out_buff
;
828 irp
->UserIosb
= NULL
;
829 irp
->UserEvent
= NULL
;
830 irp
->Tail
.Overlay
.Thread
= (PETHREAD
)KeGetCurrentThread();
831 irp
->Tail
.Overlay
.OriginalFileObject
= file
;
832 irp
->RequestorMode
= UserMode
;
834 irp
->Flags
|= IRP_DEALLOCATE_BUFFER
; /* deallocate out_buff */
835 return dispatch_irp( device
, irp
, context
);
838 static NTSTATUS
dispatch_free( struct dispatch_context
*context
)
840 void *obj
= wine_server_get_ptr( context
->params
.free
.obj
);
841 TRACE( "freeing %p object\n", obj
);
842 free_kernel_object( obj
);
843 return STATUS_SUCCESS
;
846 static NTSTATUS
dispatch_cancel( struct dispatch_context
*context
)
848 IRP
*irp
= wine_server_get_ptr( context
->params
.cancel
.irp
);
850 TRACE( "%p\n", irp
);
852 EnterCriticalSection( &irp_completion_cs
);
854 LeaveCriticalSection( &irp_completion_cs
);
855 return STATUS_SUCCESS
;
858 typedef NTSTATUS (*dispatch_func
)( struct dispatch_context
*context
);
860 static const dispatch_func dispatch_funcs
[] =
862 NULL
, /* IRP_CALL_NONE */
863 dispatch_create
, /* IRP_CALL_CREATE */
864 dispatch_close
, /* IRP_CALL_CLOSE */
865 dispatch_read
, /* IRP_CALL_READ */
866 dispatch_write
, /* IRP_CALL_WRITE */
867 dispatch_flush
, /* IRP_CALL_FLUSH */
868 dispatch_ioctl
, /* IRP_CALL_IOCTL */
869 dispatch_volume
, /* IRP_CALL_VOLUME */
870 dispatch_free
, /* IRP_CALL_FREE */
871 dispatch_cancel
/* IRP_CALL_CANCEL */
874 /* helper function to update service status */
875 static void set_service_status( SERVICE_STATUS_HANDLE handle
, DWORD state
, DWORD accepted
)
877 SERVICE_STATUS status
;
878 status
.dwServiceType
= SERVICE_WIN32
;
879 status
.dwCurrentState
= state
;
880 status
.dwControlsAccepted
= accepted
;
881 status
.dwWin32ExitCode
= 0;
882 status
.dwServiceSpecificExitCode
= 0;
883 status
.dwCheckPoint
= 0;
884 status
.dwWaitHint
= (state
== SERVICE_START_PENDING
) ? 10000 : 0;
885 SetServiceStatus( handle
, &status
);
888 static void unload_driver( struct wine_rb_entry
*entry
, void *context
)
890 struct wine_driver
*driver
= WINE_RB_ENTRY_VALUE( entry
, struct wine_driver
, entry
);
891 SERVICE_STATUS_HANDLE service_handle
= driver
->service_handle
;
892 LDR_DATA_TABLE_ENTRY
*ldr
;
894 if (!service_handle
) return; /* not a service */
896 TRACE("%s\n", debugstr_us(&driver
->driver_obj
.DriverName
));
898 if (!driver
->driver_obj
.DriverUnload
)
900 TRACE( "driver %s does not support unloading\n", debugstr_us(&driver
->driver_obj
.DriverName
) );
904 ldr
= driver
->driver_obj
.DriverSection
;
906 set_service_status( service_handle
, SERVICE_STOP_PENDING
, 0 );
908 TRACE_(relay
)( "\1Call driver unload %p (obj=%p)\n", driver
->driver_obj
.DriverUnload
, &driver
->driver_obj
);
910 driver
->driver_obj
.DriverUnload( &driver
->driver_obj
);
912 TRACE_(relay
)( "\1Ret driver unload %p (obj=%p)\n", driver
->driver_obj
.DriverUnload
, &driver
->driver_obj
);
914 FreeLibrary( ldr
->DllBase
);
915 IoDeleteDriver( &driver
->driver_obj
);
917 set_service_status( service_handle
, SERVICE_STOPPED
, 0 );
918 CloseServiceHandle( (void *)service_handle
);
921 PEPROCESS PsInitialSystemProcess
= NULL
;
923 /***********************************************************************
924 * wine_ntoskrnl_main_loop (Not a Windows API)
926 NTSTATUS CDECL
wine_ntoskrnl_main_loop( HANDLE stop_event
)
928 HANDLE manager
= get_device_manager();
929 struct dispatch_context context
= {.in_size
= 4096};
930 NTSTATUS status
= STATUS_SUCCESS
;
931 struct wine_driver
*driver
;
934 /* Set the system process global before setting up the request thread trickery */
935 PsInitialSystemProcess
= IoGetCurrentProcess();
936 request_thread
= GetCurrentThreadId();
940 handles
[0] = stop_event
;
941 handles
[1] = manager
;
945 NtCurrentTeb()->Instrumentation
[1] = NULL
;
946 if (!context
.in_buff
&& !(context
.in_buff
= HeapAlloc( GetProcessHeap(), 0, context
.in_size
)))
948 ERR( "failed to allocate buffer\n" );
949 status
= STATUS_NO_MEMORY
;
953 EnterCriticalSection( &irp_completion_cs
);
955 SERVER_START_REQ( get_next_device_request
)
957 req
->manager
= wine_server_obj_handle( manager
);
958 req
->prev
= wine_server_obj_handle( context
.handle
);
960 if (context
.irp_data
)
962 IRP
*irp
= context
.irp_data
->irp
;
964 req
->user_ptr
= wine_server_client_ptr( irp
);
965 req
->status
= status
;
967 if (context
.irp_data
->complete
)
969 /* IRP completed even before we got here; we can report completion now */
970 unsigned int out_size
= get_irp_output_size( irp
);
972 req
->prev
= wine_server_obj_handle( context
.irp_data
->handle
);
973 req
->pending
= irp
->PendingReturned
;
974 req
->iosb_status
= irp
->IoStatus
.Status
;
975 req
->result
= irp
->IoStatus
.Information
;
976 if (out_size
) wine_server_add_data( req
, irp
->UserBuffer
, out_size
);
986 req
->status
= status
;
989 wine_server_set_reply( req
, context
.in_buff
, context
.in_size
);
990 if (!(status
= wine_server_call( req
)))
992 context
.handle
= wine_server_ptr_handle( reply
->next
);
993 context
.params
= reply
->params
;
994 context
.in_size
= reply
->in_size
;
995 client_tid
= reply
->client_tid
;
996 NtCurrentTeb()->Instrumentation
[1] = wine_server_get_ptr( reply
->client_thread
);
1000 context
.handle
= 0; /* no previous irp */
1001 if (status
== STATUS_BUFFER_OVERFLOW
)
1002 context
.in_size
= reply
->in_size
;
1007 if (context
.irp_data
)
1009 if (context
.irp_data
->complete
)
1011 IRP
*irp
= context
.irp_data
->irp
;
1012 free_dispatch_irp( context
.irp_data
);
1013 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1017 context
.irp_data
->async
= TRUE
;
1021 LeaveCriticalSection( &irp_completion_cs
);
1023 context
.irp_data
= NULL
;
1027 case STATUS_SUCCESS
:
1028 assert( context
.params
.type
!= IRP_CALL_NONE
&& context
.params
.type
< ARRAY_SIZE(dispatch_funcs
) );
1029 status
= dispatch_funcs
[context
.params
.type
]( &context
);
1030 if (!context
.in_buff
) context
.in_size
= 4096;
1032 case STATUS_BUFFER_OVERFLOW
:
1033 HeapFree( GetProcessHeap(), 0, context
.in_buff
);
1034 context
.in_buff
= NULL
;
1035 /* restart with larger buffer */
1037 case STATUS_PENDING
:
1040 DWORD ret
= WaitForMultipleObjectsEx( 2, handles
, FALSE
, INFINITE
, TRUE
);
1041 if (ret
== WAIT_OBJECT_0
)
1043 HeapFree( GetProcessHeap(), 0, context
.in_buff
);
1044 status
= STATUS_SUCCESS
;
1047 if (ret
!= WAIT_IO_COMPLETION
) break;
1054 /* Native PnP drivers expect that all of their devices will be removed when
1055 * their unload routine is called. Moreover, we cannot unload a module
1056 * until we have removed devices for all lower drivers, so we have to stop
1057 * all devices first, and then unload all drivers. */
1058 WINE_RB_FOR_EACH_ENTRY( driver
, &wine_drivers
, struct wine_driver
, entry
)
1059 pnp_manager_stop_driver( driver
);
1060 wine_rb_destroy( &wine_drivers
, unload_driver
, NULL
);
1065 /***********************************************************************
1066 * IoAllocateDriverObjectExtension (NTOSKRNL.EXE.@)
1068 NTSTATUS WINAPI
IoAllocateDriverObjectExtension( PDRIVER_OBJECT DriverObject
,
1069 PVOID ClientIdentificationAddress
,
1070 ULONG DriverObjectExtensionSize
,
1071 PVOID
*DriverObjectExtension
)
1073 FIXME( "stub: %p, %p, %lu, %p\n", DriverObject
, ClientIdentificationAddress
,
1074 DriverObjectExtensionSize
, DriverObjectExtension
);
1075 return STATUS_NOT_IMPLEMENTED
;
1079 /***********************************************************************
1080 * IoGetDriverObjectExtension (NTOSKRNL.EXE.@)
1082 PVOID WINAPI
IoGetDriverObjectExtension( PDRIVER_OBJECT DriverObject
,
1083 PVOID ClientIdentificationAddress
)
1085 FIXME( "stub: %p, %p\n", DriverObject
, ClientIdentificationAddress
);
1090 /***********************************************************************
1091 * IoInitializeIrp (NTOSKRNL.EXE.@)
1093 void WINAPI
IoInitializeIrp( IRP
*irp
, USHORT size
, CCHAR stack_size
)
1095 TRACE( "%p, %u, %d\n", irp
, size
, stack_size
);
1097 RtlZeroMemory( irp
, size
);
1099 irp
->Type
= IO_TYPE_IRP
;
1101 InitializeListHead( &irp
->ThreadListEntry
);
1102 irp
->StackCount
= stack_size
;
1103 irp
->CurrentLocation
= stack_size
+ 1;
1104 irp
->Tail
.Overlay
.CurrentStackLocation
=
1105 (PIO_STACK_LOCATION
)(irp
+ 1) + stack_size
;
1108 void WINAPI
IoReuseIrp(IRP
*irp
, NTSTATUS iostatus
)
1110 UCHAR AllocationFlags
;
1112 TRACE("irp %p, iostatus %#lx.\n", irp
, iostatus
);
1114 AllocationFlags
= irp
->AllocationFlags
;
1115 IoInitializeIrp(irp
, irp
->Size
, irp
->StackCount
);
1116 irp
->AllocationFlags
= AllocationFlags
;
1117 irp
->IoStatus
.Status
= iostatus
;
1120 /***********************************************************************
1121 * IoInitializeTimer (NTOSKRNL.EXE.@)
1123 NTSTATUS WINAPI
IoInitializeTimer(PDEVICE_OBJECT DeviceObject
,
1124 PIO_TIMER_ROUTINE TimerRoutine
,
1127 FIXME( "stub: %p, %p, %p\n", DeviceObject
, TimerRoutine
, Context
);
1128 return STATUS_NOT_IMPLEMENTED
;
1132 /***********************************************************************
1133 * IoStartTimer (NTOSKRNL.EXE.@)
1135 void WINAPI
IoStartTimer(PDEVICE_OBJECT DeviceObject
)
1137 FIXME( "stub: %p\n", DeviceObject
);
1141 /***********************************************************************
1142 * IoStopTimer (NTOSKRNL.EXE.@)
1144 void WINAPI
IoStopTimer(PDEVICE_OBJECT DeviceObject
)
1146 FIXME( "stub: %p\n", DeviceObject
);
1150 /***********************************************************************
1151 * IoAllocateIrp (NTOSKRNL.EXE.@)
1153 PIRP WINAPI
IoAllocateIrp( CCHAR stack_size
, BOOLEAN charge_quota
)
1157 CCHAR loc_count
= stack_size
;
1159 TRACE( "%d, %d\n", stack_size
, charge_quota
);
1161 if (loc_count
< 8 && loc_count
!= 1)
1164 size
= sizeof(IRP
) + loc_count
* sizeof(IO_STACK_LOCATION
);
1165 irp
= ExAllocatePool( NonPagedPool
, size
);
1168 IoInitializeIrp( irp
, size
, stack_size
);
1169 if (stack_size
>= 1 && stack_size
<= 8)
1170 irp
->AllocationFlags
= IRP_ALLOCATED_FIXED_SIZE
;
1172 irp
->AllocationFlags
|= IRP_LOOKASIDE_ALLOCATION
;
1177 /***********************************************************************
1178 * IoFreeIrp (NTOSKRNL.EXE.@)
1180 void WINAPI
IoFreeIrp( IRP
*irp
)
1184 TRACE( "%p\n", irp
);
1186 mdl
= irp
->MdlAddress
;
1189 MDL
*next
= mdl
->Next
;
1198 /***********************************************************************
1199 * IoAllocateErrorLogEntry (NTOSKRNL.EXE.@)
1201 PVOID WINAPI
IoAllocateErrorLogEntry( PVOID IoObject
, UCHAR EntrySize
)
1203 FIXME( "stub: %p, %u\n", IoObject
, EntrySize
);
1208 /***********************************************************************
1209 * IoAllocateMdl (NTOSKRNL.EXE.@)
1211 PMDL WINAPI
IoAllocateMdl( PVOID va
, ULONG length
, BOOLEAN secondary
, BOOLEAN charge_quota
, IRP
*irp
)
1216 TRACE("(%p, %lu, %i, %i, %p)\n", va
, length
, secondary
, charge_quota
, irp
);
1219 FIXME("Charge quota is not yet supported\n");
1221 mdl_size
= sizeof(MDL
) + sizeof(PFN_NUMBER
) * ADDRESS_AND_SIZE_TO_SPAN_PAGES(va
, length
);
1222 mdl
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, mdl_size
);
1226 MmInitializeMdl( mdl
, va
, length
);
1228 if (!irp
) return mdl
;
1230 if (secondary
) /* add it at the end */
1232 MDL
**pmdl
= &irp
->MdlAddress
;
1233 while (*pmdl
) pmdl
= &(*pmdl
)->Next
;
1238 mdl
->Next
= irp
->MdlAddress
;
1239 irp
->MdlAddress
= mdl
;
1245 /***********************************************************************
1246 * IoFreeMdl (NTOSKRNL.EXE.@)
1248 void WINAPI
IoFreeMdl(PMDL mdl
)
1251 HeapFree(GetProcessHeap(), 0, mdl
);
1257 DEVICE_OBJECT
*device
;
1258 PIO_WORKITEM_ROUTINE worker
;
1262 /***********************************************************************
1263 * IoAllocateWorkItem (NTOSKRNL.EXE.@)
1265 PIO_WORKITEM WINAPI
IoAllocateWorkItem( PDEVICE_OBJECT device
)
1267 PIO_WORKITEM work_item
;
1269 TRACE( "%p\n", device
);
1271 if (!(work_item
= ExAllocatePool( PagedPool
, sizeof(*work_item
) ))) return NULL
;
1272 work_item
->device
= device
;
1277 /***********************************************************************
1278 * IoFreeWorkItem (NTOSKRNL.EXE.@)
1280 void WINAPI
IoFreeWorkItem( PIO_WORKITEM work_item
)
1282 TRACE( "%p\n", work_item
);
1283 ExFreePool( work_item
);
1287 static void WINAPI
run_work_item_worker(TP_CALLBACK_INSTANCE
*instance
, void *context
)
1289 PIO_WORKITEM work_item
= context
;
1290 DEVICE_OBJECT
*device
= work_item
->device
;
1292 TRACE( "%p: calling %p(%p %p)\n", work_item
, work_item
->worker
, device
, work_item
->context
);
1293 work_item
->worker( device
, work_item
->context
);
1296 ObDereferenceObject( device
);
1299 /***********************************************************************
1300 * IoQueueWorkItem (NTOSKRNL.EXE.@)
1302 void WINAPI
IoQueueWorkItem( PIO_WORKITEM work_item
, PIO_WORKITEM_ROUTINE worker
,
1303 WORK_QUEUE_TYPE type
, void *context
)
1305 TRACE( "%p %p %u %p\n", work_item
, worker
, type
, context
);
1307 ObReferenceObject( work_item
->device
);
1308 work_item
->worker
= worker
;
1309 work_item
->context
= context
;
1310 TrySubmitThreadpoolCallback( run_work_item_worker
, work_item
, NULL
);
1313 /***********************************************************************
1314 * IoGetAttachedDevice (NTOSKRNL.EXE.@)
1316 DEVICE_OBJECT
* WINAPI
IoGetAttachedDevice( DEVICE_OBJECT
*device
)
1318 DEVICE_OBJECT
*result
= device
;
1320 TRACE( "(%p)\n", device
);
1322 while (result
->AttachedDevice
)
1323 result
= result
->AttachedDevice
;
1328 void WINAPI
IoDetachDevice( DEVICE_OBJECT
*device
)
1330 device
->AttachedDevice
= NULL
;
1333 /***********************************************************************
1334 * IoAttachDeviceToDeviceStack (NTOSKRNL.EXE.@)
1336 PDEVICE_OBJECT WINAPI
IoAttachDeviceToDeviceStack( DEVICE_OBJECT
*source
,
1337 DEVICE_OBJECT
*target
)
1339 TRACE( "%p, %p\n", source
, target
);
1340 target
= IoGetAttachedDevice( target
);
1341 target
->AttachedDevice
= source
;
1342 source
->StackSize
= target
->StackSize
+ 1;
1346 /***********************************************************************
1347 * IoBuildDeviceIoControlRequest (NTOSKRNL.EXE.@)
1349 PIRP WINAPI
IoBuildDeviceIoControlRequest( ULONG code
, PDEVICE_OBJECT device
,
1350 PVOID in_buff
, ULONG in_len
,
1351 PVOID out_buff
, ULONG out_len
,
1352 BOOLEAN internal
, PKEVENT event
,
1353 PIO_STATUS_BLOCK iosb
)
1356 PIO_STACK_LOCATION irpsp
;
1359 TRACE( "%lx, %p, %p, %lu, %p, %lu, %u, %p, %p\n",
1360 code
, device
, in_buff
, in_len
, out_buff
, out_len
, internal
, event
, iosb
);
1365 irp
= IoAllocateIrp( device
->StackSize
, FALSE
);
1369 irpsp
= IoGetNextIrpStackLocation( irp
);
1370 irpsp
->MajorFunction
= internal
? IRP_MJ_INTERNAL_DEVICE_CONTROL
: IRP_MJ_DEVICE_CONTROL
;
1371 irpsp
->Parameters
.DeviceIoControl
.IoControlCode
= code
;
1372 irpsp
->Parameters
.DeviceIoControl
.InputBufferLength
= in_len
;
1373 irpsp
->Parameters
.DeviceIoControl
.OutputBufferLength
= out_len
;
1374 irpsp
->DeviceObject
= NULL
;
1375 irpsp
->CompletionRoutine
= NULL
;
1379 case METHOD_BUFFERED
:
1380 irp
->AssociatedIrp
.SystemBuffer
= in_buff
;
1382 case METHOD_IN_DIRECT
:
1383 case METHOD_OUT_DIRECT
:
1384 irp
->AssociatedIrp
.SystemBuffer
= in_buff
;
1386 mdl
= IoAllocateMdl( out_buff
, out_len
, FALSE
, FALSE
, irp
);
1393 mdl
->MdlFlags
|= MDL_MAPPED_TO_SYSTEM_VA
;
1394 mdl
->MappedSystemVa
= out_buff
;
1396 case METHOD_NEITHER
:
1397 irpsp
->Parameters
.DeviceIoControl
.Type3InputBuffer
= in_buff
;
1401 irp
->RequestorMode
= KernelMode
;
1402 irp
->UserBuffer
= out_buff
;
1403 irp
->UserIosb
= iosb
;
1404 irp
->UserEvent
= event
;
1405 irp
->Tail
.Overlay
.Thread
= (PETHREAD
)KeGetCurrentThread();
1409 /***********************************************************************
1410 * IoBuildAsynchronousFsdRequest (NTOSKRNL.EXE.@)
1412 PIRP WINAPI
IoBuildAsynchronousFsdRequest(ULONG majorfunc
, DEVICE_OBJECT
*device
,
1413 void *buffer
, ULONG length
, LARGE_INTEGER
*startoffset
,
1414 IO_STATUS_BLOCK
*iosb
)
1417 PIO_STACK_LOCATION irpsp
;
1419 TRACE( "(%ld %p %p %ld %p %p)\n", majorfunc
, device
, buffer
, length
, startoffset
, iosb
);
1421 if (!(irp
= IoAllocateIrp( device
->StackSize
, FALSE
))) return NULL
;
1423 irpsp
= IoGetNextIrpStackLocation( irp
);
1424 irpsp
->MajorFunction
= majorfunc
;
1425 irpsp
->DeviceObject
= NULL
;
1426 irpsp
->CompletionRoutine
= NULL
;
1428 irp
->AssociatedIrp
.SystemBuffer
= buffer
;
1430 if (device
->Flags
& DO_DIRECT_IO
)
1432 MDL
*mdl
= IoAllocateMdl( buffer
, length
, FALSE
, FALSE
, irp
);
1439 mdl
->MdlFlags
|= MDL_MAPPED_TO_SYSTEM_VA
;
1440 mdl
->MappedSystemVa
= buffer
;
1446 irpsp
->Parameters
.Read
.Length
= length
;
1447 irpsp
->Parameters
.Read
.ByteOffset
.QuadPart
= startoffset
? startoffset
->QuadPart
: 0;
1450 irpsp
->Parameters
.Write
.Length
= length
;
1451 irpsp
->Parameters
.Write
.ByteOffset
.QuadPart
= startoffset
? startoffset
->QuadPart
: 0;
1454 irp
->RequestorMode
= KernelMode
;
1455 irp
->UserIosb
= iosb
;
1456 irp
->UserEvent
= NULL
;
1457 irp
->UserBuffer
= buffer
;
1458 irp
->Tail
.Overlay
.Thread
= (PETHREAD
)KeGetCurrentThread();
1464 /***********************************************************************
1465 * IoBuildSynchronousFsdRequest (NTOSKRNL.EXE.@)
1467 PIRP WINAPI
IoBuildSynchronousFsdRequest(ULONG majorfunc
, PDEVICE_OBJECT device
,
1468 PVOID buffer
, ULONG length
, PLARGE_INTEGER startoffset
,
1469 PKEVENT event
, PIO_STATUS_BLOCK iosb
)
1473 TRACE("(%ld %p %p %ld %p %p)\n", majorfunc
, device
, buffer
, length
, startoffset
, iosb
);
1475 irp
= IoBuildAsynchronousFsdRequest( majorfunc
, device
, buffer
, length
, startoffset
, iosb
);
1476 if (!irp
) return NULL
;
1478 irp
->UserEvent
= event
;
1482 static void build_driver_keypath( const WCHAR
*name
, UNICODE_STRING
*keypath
)
1484 static const WCHAR driverW
[] = {'\\','D','r','i','v','e','r','\\',0};
1487 /* Check what prefix is present */
1488 if (wcsncmp( name
, servicesW
, lstrlenW(servicesW
) ) == 0)
1490 FIXME( "Driver name %s is malformed as the keypath\n", debugstr_w(name
) );
1491 RtlCreateUnicodeString( keypath
, name
);
1494 if (wcsncmp( name
, driverW
, lstrlenW(driverW
) ) == 0)
1495 name
+= lstrlenW(driverW
);
1497 FIXME( "Driver name %s does not properly begin with \\Driver\\\n", debugstr_w(name
) );
1499 str
= HeapAlloc( GetProcessHeap(), 0, sizeof(servicesW
) + lstrlenW(name
)*sizeof(WCHAR
));
1500 lstrcpyW( str
, servicesW
);
1501 lstrcatW( str
, name
);
1502 RtlInitUnicodeString( keypath
, str
);
1506 static NTSTATUS WINAPI
unhandled_irp( DEVICE_OBJECT
*device
, IRP
*irp
)
1508 TRACE( "(%p, %p)\n", device
, irp
);
1509 irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1510 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1511 return STATUS_INVALID_DEVICE_REQUEST
;
1515 static void free_driver_object( void *obj
)
1517 struct wine_driver
*driver
= obj
;
1518 RtlFreeUnicodeString( &driver
->driver_obj
.DriverName
);
1519 RtlFreeUnicodeString( &driver
->driver_obj
.DriverExtension
->ServiceKeyName
);
1520 free_kernel_object( driver
);
1523 static const WCHAR driver_type_name
[] = {'D','r','i','v','e','r',0};
1525 static struct _OBJECT_TYPE driver_type
=
1532 POBJECT_TYPE IoDriverObjectType
= &driver_type
;
1535 /***********************************************************************
1536 * IoCreateDriver (NTOSKRNL.EXE.@)
1538 NTSTATUS WINAPI
IoCreateDriver( UNICODE_STRING
*name
, PDRIVER_INITIALIZE init
)
1540 struct wine_driver
*driver
;
1544 TRACE("(%s, %p)\n", debugstr_us(name
), init
);
1546 if (!(driver
= alloc_kernel_object( IoDriverObjectType
, NULL
, sizeof(*driver
), 1 )))
1547 return STATUS_NO_MEMORY
;
1549 if ((status
= RtlDuplicateUnicodeString( 1, name
, &driver
->driver_obj
.DriverName
)))
1551 free_kernel_object( driver
);
1555 driver
->driver_obj
.Size
= sizeof(driver
->driver_obj
);
1556 driver
->driver_obj
.DriverInit
= init
;
1557 driver
->driver_obj
.DriverExtension
= &driver
->driver_extension
;
1558 driver
->driver_extension
.DriverObject
= &driver
->driver_obj
;
1559 build_driver_keypath( driver
->driver_obj
.DriverName
.Buffer
, &driver
->driver_extension
.ServiceKeyName
);
1560 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
1561 driver
->driver_obj
.MajorFunction
[i
] = unhandled_irp
;
1562 list_init( &driver
->root_pnp_devices
);
1564 EnterCriticalSection( &drivers_cs
);
1565 if (wine_rb_put( &wine_drivers
, &driver
->driver_obj
.DriverName
, &driver
->entry
))
1566 ERR( "failed to insert driver %s in tree\n", debugstr_us(name
) );
1567 LeaveCriticalSection( &drivers_cs
);
1569 status
= driver
->driver_obj
.DriverInit( &driver
->driver_obj
, &driver
->driver_extension
.ServiceKeyName
);
1572 IoDeleteDriver( &driver
->driver_obj
);
1576 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
1578 if (driver
->driver_obj
.MajorFunction
[i
]) continue;
1579 driver
->driver_obj
.MajorFunction
[i
] = unhandled_irp
;
1582 return STATUS_SUCCESS
;
1586 /***********************************************************************
1587 * IoDeleteDriver (NTOSKRNL.EXE.@)
1589 void WINAPI
IoDeleteDriver( DRIVER_OBJECT
*driver_object
)
1591 TRACE( "(%p)\n", driver_object
);
1593 EnterCriticalSection( &drivers_cs
);
1594 wine_rb_remove_key( &wine_drivers
, &driver_object
->DriverName
);
1595 LeaveCriticalSection( &drivers_cs
);
1597 ObDereferenceObject( driver_object
);
1601 static const WCHAR device_type_name
[] = {'D','e','v','i','c','e',0};
1603 static struct _OBJECT_TYPE device_type
=
1608 POBJECT_TYPE IoDeviceObjectType
= &device_type
;
1610 /***********************************************************************
1611 * IoCreateDeviceSecure (NTOSKRNL.EXE.@)
1613 NTSTATUS WINAPI
IoCreateDeviceSecure( DRIVER_OBJECT
*driver
, ULONG ext_size
,
1614 UNICODE_STRING
*name
, DEVICE_TYPE type
,
1615 ULONG characteristics
, BOOLEAN exclusive
,
1616 PCUNICODE_STRING sddl
, LPCGUID guid
,
1617 DEVICE_OBJECT
**ret_device
)
1619 FIXME( "(%p, %lu, %s, %lu, %lx, %u, %s, %s, %p): semi-stub\n",
1620 driver
, ext_size
, debugstr_us(name
), type
, characteristics
, exclusive
,
1621 debugstr_us(sddl
), wine_dbgstr_guid(guid
), ret_device
);
1623 return IoCreateDevice( driver
, ext_size
, name
, type
, characteristics
, exclusive
, ret_device
);
1626 /***********************************************************************
1627 * IoCreateDevice (NTOSKRNL.EXE.@)
1629 NTSTATUS WINAPI
IoCreateDevice( DRIVER_OBJECT
*driver
, ULONG ext_size
,
1630 UNICODE_STRING
*name
, DEVICE_TYPE type
,
1631 ULONG characteristics
, BOOLEAN exclusive
,
1632 DEVICE_OBJECT
**ret_device
)
1634 static const WCHAR auto_format
[] = {'\\','D','e','v','i','c','e','\\','%','0','8','x',0};
1636 struct wine_device
*wine_device
;
1637 DEVICE_OBJECT
*device
;
1638 HANDLE manager
= get_device_manager();
1639 static unsigned int auto_idx
= 0;
1642 TRACE( "(%p, %lu, %s, %lu, %lx, %u, %p)\n",
1643 driver
, ext_size
, debugstr_us(name
), type
, characteristics
, exclusive
, ret_device
);
1645 if (!(wine_device
= alloc_kernel_object( IoDeviceObjectType
, NULL
, sizeof(struct wine_device
) + ext_size
, 1 )))
1646 return STATUS_NO_MEMORY
;
1647 device
= &wine_device
->device_obj
;
1649 device
->DriverObject
= driver
;
1650 device
->DeviceExtension
= wine_device
+ 1;
1651 device
->DeviceType
= type
;
1652 device
->StackSize
= 1;
1654 if (characteristics
& FILE_AUTOGENERATED_DEVICE_NAME
)
1658 swprintf( autoW
, ARRAY_SIZE(autoW
), auto_format
, auto_idx
++ );
1659 SERVER_START_REQ( create_device
)
1662 req
->manager
= wine_server_obj_handle( manager
);
1663 req
->user_ptr
= wine_server_client_ptr( device
);
1664 wine_server_add_data( req
, autoW
, lstrlenW(autoW
) * sizeof(WCHAR
) );
1665 status
= wine_server_call( req
);
1668 } while (status
== STATUS_OBJECT_NAME_COLLISION
);
1672 SERVER_START_REQ( create_device
)
1675 req
->manager
= wine_server_obj_handle( manager
);
1676 req
->user_ptr
= wine_server_client_ptr( device
);
1677 if (name
) wine_server_add_data( req
, name
->Buffer
, name
->Length
);
1678 status
= wine_server_call( req
);
1685 free_kernel_object( device
);
1689 device
->NextDevice
= driver
->DeviceObject
;
1690 driver
->DeviceObject
= device
;
1692 *ret_device
= device
;
1693 return STATUS_SUCCESS
;
1697 /***********************************************************************
1698 * IoDeleteDevice (NTOSKRNL.EXE.@)
1700 void WINAPI
IoDeleteDevice( DEVICE_OBJECT
*device
)
1704 TRACE( "%p\n", device
);
1706 SERVER_START_REQ( delete_device
)
1708 req
->manager
= wine_server_obj_handle( get_device_manager() );
1709 req
->device
= wine_server_client_ptr( device
);
1710 status
= wine_server_call( req
);
1714 if (status
== STATUS_SUCCESS
)
1716 struct wine_device
*wine_device
= CONTAINING_RECORD(device
, struct wine_device
, device_obj
);
1717 DEVICE_OBJECT
**prev
= &device
->DriverObject
->DeviceObject
;
1718 DEVICE_RELATIONS
*children
;
1721 while (*prev
&& *prev
!= device
) prev
= &(*prev
)->NextDevice
;
1722 if (*prev
) *prev
= (*prev
)->NextDevice
;
1723 if ((children
= wine_device
->children
))
1725 for (i
= 0; i
< children
->Count
; ++i
)
1726 ObDereferenceObject( children
->Objects
[i
] );
1727 ExFreePool( children
);
1729 ObDereferenceObject( device
);
1734 /***********************************************************************
1735 * IoCreateSymbolicLink (NTOSKRNL.EXE.@)
1737 NTSTATUS WINAPI
IoCreateSymbolicLink( UNICODE_STRING
*name
, UNICODE_STRING
*target
)
1740 OBJECT_ATTRIBUTES attr
;
1743 attr
.Length
= sizeof(attr
);
1744 attr
.RootDirectory
= 0;
1745 attr
.ObjectName
= name
;
1746 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_PERMANENT
;
1747 attr
.SecurityDescriptor
= NULL
;
1748 attr
.SecurityQualityOfService
= NULL
;
1750 TRACE( "%s -> %s\n", debugstr_us(name
), debugstr_us(target
) );
1751 if (!(ret
= NtCreateSymbolicLinkObject( &handle
, SYMBOLIC_LINK_ALL_ACCESS
, &attr
, target
)))
1757 /***********************************************************************
1758 * IoCreateUnprotectedSymbolicLink (NTOSKRNL.EXE.@)
1760 NTSTATUS WINAPI
IoCreateUnprotectedSymbolicLink( UNICODE_STRING
*name
, UNICODE_STRING
*target
)
1763 OBJECT_ATTRIBUTES attr
;
1766 attr
.Length
= sizeof(attr
);
1767 attr
.RootDirectory
= 0;
1768 attr
.ObjectName
= name
;
1769 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_PERMANENT
;
1770 attr
.SecurityDescriptor
= NULL
;
1771 attr
.SecurityQualityOfService
= NULL
;
1773 TRACE( "%s -> %s\n", debugstr_us(name
), debugstr_us(target
) );
1774 if (!(ret
= NtCreateSymbolicLinkObject( &handle
, SYMBOLIC_LINK_ALL_ACCESS
, &attr
, target
)))
1780 /***********************************************************************
1781 * IoDeleteSymbolicLink (NTOSKRNL.EXE.@)
1783 NTSTATUS WINAPI
IoDeleteSymbolicLink( UNICODE_STRING
*name
)
1786 OBJECT_ATTRIBUTES attr
;
1789 attr
.Length
= sizeof(attr
);
1790 attr
.RootDirectory
= 0;
1791 attr
.ObjectName
= name
;
1792 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1793 attr
.SecurityDescriptor
= NULL
;
1794 attr
.SecurityQualityOfService
= NULL
;
1796 if (!(status
= NtOpenSymbolicLinkObject( &handle
, DELETE
, &attr
)))
1798 NtMakeTemporaryObject( handle
);
1804 /***********************************************************************
1805 * IoGetDeviceInterfaces (NTOSKRNL.EXE.@)
1807 NTSTATUS WINAPI
IoGetDeviceInterfaces( const GUID
*InterfaceClassGuid
,
1808 PDEVICE_OBJECT PhysicalDeviceObject
,
1809 ULONG Flags
, PWSTR
*SymbolicLinkList
)
1811 FIXME( "stub: %s %p %lx %p\n", debugstr_guid(InterfaceClassGuid
),
1812 PhysicalDeviceObject
, Flags
, SymbolicLinkList
);
1813 return STATUS_NOT_IMPLEMENTED
;
1817 /***********************************************************************
1818 * IoGetDeviceObjectPointer (NTOSKRNL.EXE.@)
1820 NTSTATUS WINAPI
IoGetDeviceObjectPointer( UNICODE_STRING
*name
, ACCESS_MASK access
, PFILE_OBJECT
*file
, PDEVICE_OBJECT
*device
)
1822 static DEVICE_OBJECT stub_device
;
1823 static DRIVER_OBJECT stub_driver
;
1825 FIXME( "stub: %s %lx %p %p\n", debugstr_us(name
), access
, file
, device
);
1827 stub_device
.StackSize
= 0x80; /* minimum value to appease SecuROM 5.x */
1828 stub_device
.DriverObject
= &stub_driver
;
1831 *device
= &stub_device
;
1833 return STATUS_SUCCESS
;
1836 /***********************************************************************
1837 * IoCallDriver (NTOSKRNL.EXE.@)
1839 NTSTATUS WINAPI
IoCallDriver( DEVICE_OBJECT
*device
, IRP
*irp
)
1841 PDRIVER_DISPATCH dispatch
;
1842 IO_STACK_LOCATION
*irpsp
;
1845 --irp
->CurrentLocation
;
1846 irpsp
= --irp
->Tail
.Overlay
.CurrentStackLocation
;
1847 irpsp
->DeviceObject
= device
;
1848 dispatch
= device
->DriverObject
->MajorFunction
[irpsp
->MajorFunction
];
1850 TRACE_(relay
)( "\1Call driver dispatch %p (device=%p,irp=%p)\n", dispatch
, device
, irp
);
1852 status
= dispatch( device
, irp
);
1854 TRACE_(relay
)( "\1Ret driver dispatch %p (device=%p,irp=%p) retval=%08lx\n",
1855 dispatch
, device
, irp
, status
);
1861 /***********************************************************************
1862 * IofCallDriver (NTOSKRNL.EXE.@)
1864 DEFINE_FASTCALL_WRAPPER( IofCallDriver
, 8 )
1865 NTSTATUS FASTCALL
IofCallDriver( DEVICE_OBJECT
*device
, IRP
*irp
)
1867 TRACE( "%p %p\n", device
, irp
);
1868 return IoCallDriver( device
, irp
);
1872 /***********************************************************************
1873 * IoGetRelatedDeviceObject (NTOSKRNL.EXE.@)
1875 PDEVICE_OBJECT WINAPI
IoGetRelatedDeviceObject( PFILE_OBJECT obj
)
1877 FIXME( "stub: %p\n", obj
);
1881 static CONFIGURATION_INFORMATION configuration_information
;
1883 /***********************************************************************
1884 * IoGetConfigurationInformation (NTOSKRNL.EXE.@)
1886 PCONFIGURATION_INFORMATION WINAPI
IoGetConfigurationInformation(void)
1888 FIXME( "partial stub\n" );
1889 /* FIXME: return actual devices on system */
1890 return &configuration_information
;
1893 /***********************************************************************
1894 * IoGetStackLimits (NTOSKRNL.EXE.@)
1896 void WINAPI
IoGetStackLimits(ULONG_PTR
*low
, ULONG_PTR
*high
)
1898 TEB
*teb
= NtCurrentTeb();
1900 TRACE( "%p %p\n", low
, high
);
1902 *low
= (DWORD_PTR
)teb
->Tib
.StackLimit
;
1903 *high
= (DWORD_PTR
)teb
->Tib
.StackBase
;
1906 /***********************************************************************
1907 * IoIsWdmVersionAvailable (NTOSKRNL.EXE.@)
1909 NTSTATUS WINAPI
IoIsWdmVersionAvailable(UCHAR MajorVersion
, UCHAR MinorVersion
)
1915 TRACE( "%d, 0x%X\n", MajorVersion
, MinorVersion
);
1917 version
= GetVersion();
1918 major
= LOBYTE(version
);
1919 minor
= HIBYTE(LOWORD(version
));
1921 if (MajorVersion
== 6 && MinorVersion
== 0)
1923 /* Windows Vista, Windows Server 2008, Windows 7 */
1925 else if (MajorVersion
== 1)
1927 if (MinorVersion
== 0x30)
1929 /* Windows server 2003 */
1933 else if (MinorVersion
== 0x20)
1939 else if (MinorVersion
== 0x10)
1945 else if (MinorVersion
== 0x05)
1949 MinorVersion
= 0x5a;
1951 else if (MinorVersion
== 0x00)
1955 MinorVersion
= 0x0a;
1959 FIXME( "unknown major %d minor 0x%X\n", MajorVersion
, MinorVersion
);
1965 FIXME( "unknown major %d minor 0x%X\n", MajorVersion
, MinorVersion
);
1968 return major
> MajorVersion
|| (major
== MajorVersion
&& minor
>= MinorVersion
);
1971 /***********************************************************************
1972 * IoQueryDeviceDescription (NTOSKRNL.EXE.@)
1974 NTSTATUS WINAPI
IoQueryDeviceDescription(PINTERFACE_TYPE itype
, PULONG bus
, PCONFIGURATION_TYPE ctype
,
1975 PULONG cnum
, PCONFIGURATION_TYPE ptype
, PULONG pnum
,
1976 PIO_QUERY_DEVICE_ROUTINE callout
, PVOID context
)
1978 FIXME( "(%p %p %p %p %p %p %p %p)\n", itype
, bus
, ctype
, cnum
, ptype
, pnum
, callout
, context
);
1979 return STATUS_NOT_IMPLEMENTED
;
1982 /***********************************************************************
1983 * IoRegisterDriverReinitialization (NTOSKRNL.EXE.@)
1985 void WINAPI
IoRegisterDriverReinitialization( PDRIVER_OBJECT obj
, PDRIVER_REINITIALIZE reinit
, PVOID context
)
1987 FIXME( "stub: %p %p %p\n", obj
, reinit
, context
);
1990 /***********************************************************************
1991 * IoRegisterBootDriverReinitialization (NTOSKRNL.EXE.@)
1993 void WINAPI
IoRegisterBootDriverReinitialization(DRIVER_OBJECT
*driver
, PDRIVER_REINITIALIZE proc
, void *ctx
)
1995 FIXME("driver %p, proc %p, ctx %p, stub!\n", driver
, proc
, ctx
);
1998 /***********************************************************************
1999 * IoRegisterShutdownNotification (NTOSKRNL.EXE.@)
2001 NTSTATUS WINAPI
IoRegisterShutdownNotification( PDEVICE_OBJECT obj
)
2003 FIXME( "stub: %p\n", obj
);
2004 return STATUS_SUCCESS
;
2008 /***********************************************************************
2009 * IoUnregisterShutdownNotification (NTOSKRNL.EXE.@)
2011 VOID WINAPI
IoUnregisterShutdownNotification( PDEVICE_OBJECT obj
)
2013 FIXME( "stub: %p\n", obj
);
2017 /***********************************************************************
2018 * IoReportResourceForDetection (NTOSKRNL.EXE.@)
2020 NTSTATUS WINAPI
IoReportResourceForDetection( DRIVER_OBJECT
*drv_obj
, CM_RESOURCE_LIST
*drv_list
, ULONG drv_size
,
2021 DEVICE_OBJECT
*dev_obj
, CM_RESOURCE_LIST
*dev_list
, ULONG dev_size
,
2024 FIXME( "(%p, %p, %lu, %p, %p, %lu, %p): stub\n", drv_obj
, drv_list
, drv_size
,
2025 dev_obj
, dev_list
, dev_size
, conflict
);
2027 return STATUS_NOT_IMPLEMENTED
;
2031 /***********************************************************************
2032 * IoReportResourceUsage (NTOSKRNL.EXE.@)
2034 NTSTATUS WINAPI
IoReportResourceUsage( UNICODE_STRING
*name
, DRIVER_OBJECT
*drv_obj
, CM_RESOURCE_LIST
*drv_list
,
2035 ULONG drv_size
, DRIVER_OBJECT
*dev_obj
, CM_RESOURCE_LIST
*dev_list
,
2036 ULONG dev_size
, BOOLEAN overwrite
, BOOLEAN
*conflict
)
2038 FIXME( "(%s, %p, %p, %lu, %p, %p, %lu, %d, %p): stub\n", debugstr_us(name
),
2039 drv_obj
, drv_list
, drv_size
, dev_obj
, dev_list
, dev_size
, overwrite
, conflict
);
2041 return STATUS_NOT_IMPLEMENTED
;
2045 /***********************************************************************
2046 * IoCompleteRequest (NTOSKRNL.EXE.@)
2048 VOID WINAPI
IoCompleteRequest( IRP
*irp
, UCHAR priority_boost
)
2050 IO_STACK_LOCATION
*irpsp
;
2051 PIO_COMPLETION_ROUTINE routine
;
2052 NTSTATUS status
, stat
;
2053 DEVICE_OBJECT
*device
;
2056 TRACE( "%p %u\n", irp
, priority_boost
);
2058 status
= irp
->IoStatus
.Status
;
2059 while (irp
->CurrentLocation
<= irp
->StackCount
)
2061 irpsp
= irp
->Tail
.Overlay
.CurrentStackLocation
;
2062 routine
= irpsp
->CompletionRoutine
;
2066 if ((irpsp
->Control
& SL_INVOKE_ON_SUCCESS
) && STATUS_SUCCESS
== status
)
2068 if ((irpsp
->Control
& SL_INVOKE_ON_ERROR
) && STATUS_SUCCESS
!= status
)
2070 if ((irpsp
->Control
& SL_INVOKE_ON_CANCEL
) && irp
->Cancel
)
2073 ++irp
->CurrentLocation
;
2074 ++irp
->Tail
.Overlay
.CurrentStackLocation
;
2075 if (irp
->CurrentLocation
<= irp
->StackCount
)
2076 device
= IoGetCurrentIrpStackLocation(irp
)->DeviceObject
;
2079 irp
->PendingReturned
= !!(irpsp
->Control
& SL_PENDING_RETURNED
);
2083 TRACE( "calling %p( %p, %p, %p )\n", routine
, device
, irp
, irpsp
->Context
);
2084 stat
= routine( device
, irp
, irpsp
->Context
);
2085 TRACE( "CompletionRoutine returned %lx\n", stat
);
2086 if (STATUS_MORE_PROCESSING_REQUIRED
== stat
)
2091 if (irp
->Flags
& IRP_DEALLOCATE_BUFFER
)
2092 HeapFree( GetProcessHeap(), 0, irp
->AssociatedIrp
.SystemBuffer
);
2093 if (irp
->UserIosb
) *irp
->UserIosb
= irp
->IoStatus
;
2094 if (irp
->UserEvent
) KeSetEvent( irp
->UserEvent
, IO_NO_INCREMENT
, FALSE
);
2100 /***********************************************************************
2101 * IofCompleteRequest (NTOSKRNL.EXE.@)
2103 DEFINE_FASTCALL_WRAPPER( IofCompleteRequest
, 8 )
2104 void FASTCALL
IofCompleteRequest( IRP
*irp
, UCHAR priority_boost
)
2106 TRACE( "%p %u\n", irp
, priority_boost
);
2107 IoCompleteRequest( irp
, priority_boost
);
2111 /***********************************************************************
2112 * IoCancelIrp (NTOSKRNL.EXE.@)
2114 BOOLEAN WINAPI
IoCancelIrp( IRP
*irp
)
2116 PDRIVER_CANCEL cancel_routine
;
2119 TRACE( "(%p)\n", irp
);
2121 IoAcquireCancelSpinLock( &irql
);
2123 if (!(cancel_routine
= IoSetCancelRoutine( irp
, NULL
)))
2125 IoReleaseCancelSpinLock( irp
->CancelIrql
);
2129 /* CancelRoutine is responsible for calling IoReleaseCancelSpinLock */
2130 irp
->CancelIrql
= irql
;
2131 cancel_routine( IoGetCurrentIrpStackLocation(irp
)->DeviceObject
, irp
);
2136 /***********************************************************************
2137 * InterlockedCompareExchange (NTOSKRNL.EXE.@)
2139 DEFINE_FASTCALL_WRAPPER( NTOSKRNL_InterlockedCompareExchange
, 12 )
2140 LONG FASTCALL
NTOSKRNL_InterlockedCompareExchange( LONG
volatile *dest
, LONG xchg
, LONG compare
)
2142 return InterlockedCompareExchange( dest
, xchg
, compare
);
2146 /***********************************************************************
2147 * InterlockedDecrement (NTOSKRNL.EXE.@)
2149 DEFINE_FASTCALL1_WRAPPER( NTOSKRNL_InterlockedDecrement
)
2150 LONG FASTCALL
NTOSKRNL_InterlockedDecrement( LONG
volatile *dest
)
2152 return InterlockedDecrement( dest
);
2156 /***********************************************************************
2157 * InterlockedExchange (NTOSKRNL.EXE.@)
2159 DEFINE_FASTCALL_WRAPPER( NTOSKRNL_InterlockedExchange
, 8 )
2160 LONG FASTCALL
NTOSKRNL_InterlockedExchange( LONG
volatile *dest
, LONG val
)
2162 return InterlockedExchange( dest
, val
);
2166 /***********************************************************************
2167 * InterlockedExchangeAdd (NTOSKRNL.EXE.@)
2169 DEFINE_FASTCALL_WRAPPER( NTOSKRNL_InterlockedExchangeAdd
, 8 )
2170 LONG FASTCALL
NTOSKRNL_InterlockedExchangeAdd( LONG
volatile *dest
, LONG incr
)
2172 return InterlockedExchangeAdd( dest
, incr
);
2176 /***********************************************************************
2177 * InterlockedIncrement (NTOSKRNL.EXE.@)
2179 DEFINE_FASTCALL1_WRAPPER( NTOSKRNL_InterlockedIncrement
)
2180 LONG FASTCALL
NTOSKRNL_InterlockedIncrement( LONG
volatile *dest
)
2182 return InterlockedIncrement( dest
);
2187 /*************************************************************************
2188 * RtlUshortByteSwap (NTOSKRNL.EXE.@)
2190 __ASM_FASTCALL_FUNC(RtlUshortByteSwap
, 4,
2195 /*************************************************************************
2196 * RtlUlongByteSwap (NTOSKRNL.EXE.@)
2198 __ASM_FASTCALL_FUNC(RtlUlongByteSwap
, 4,
2199 "movl %ecx,%eax\n\t"
2203 /*************************************************************************
2204 * RtlUlonglongByteSwap (NTOSKRNL.EXE.@)
2206 __ASM_FASTCALL_FUNC(RtlUlonglongByteSwap
, 8,
2207 "movl 4(%esp),%edx\n\t"
2209 "movl 8(%esp),%eax\n\t"
2213 #endif /* __i386__ */
2215 /***********************************************************************
2216 * ExAllocatePool2 (NTOSKRNL.EXE.@)
2218 void * WINAPI
ExAllocatePool2( POOL_FLAGS flags
, SIZE_T size
, ULONG tag
)
2220 /* FIXME: handle page alignment constraints */
2221 void *ret
= HeapAlloc( ntoskrnl_heap
, 0, size
);
2222 TRACE( "(0x%I64x, %Iu, %s) -> %p\n", flags
, size
, debugstr_fourcc(tag
), ret
);
2226 static POOL_FLAGS
pool_type_to_flags( POOL_TYPE type
)
2231 case NonPagedPoolMustSucceed
:
2232 return POOL_FLAG_NON_PAGED
;
2234 return POOL_FLAG_PAGED
;
2235 case NonPagedPoolCacheAligned
:
2236 case NonPagedPoolCacheAlignedMustS
:
2237 return POOL_FLAG_NON_PAGED
|POOL_FLAG_CACHE_ALIGNED
;
2238 case PagedPoolCacheAligned
:
2239 return POOL_FLAG_PAGED
|POOL_FLAG_CACHE_ALIGNED
;
2245 /***********************************************************************
2246 * ExAllocatePool (NTOSKRNL.EXE.@)
2248 PVOID WINAPI
ExAllocatePool( POOL_TYPE type
, SIZE_T size
)
2250 POOL_FLAGS flags
= pool_type_to_flags( type
);
2251 if (type
& POOL_RAISE_IF_ALLOCATION_FAILURE
)
2252 flags
|= POOL_FLAG_RAISE_ON_FAILURE
;
2254 return ExAllocatePool2( flags
, size
, 0 );
2257 /***********************************************************************
2258 * ExAllocatePoolWithQuota (NTOSKRNL.EXE.@)
2260 PVOID WINAPI
ExAllocatePoolWithQuota( POOL_TYPE type
, SIZE_T size
)
2262 POOL_FLAGS flags
= pool_type_to_flags( type
) | POOL_FLAG_USE_QUOTA
;
2263 if (!(type
& POOL_QUOTA_FAIL_INSTEAD_OF_RAISE
))
2264 flags
|= POOL_FLAG_RAISE_ON_FAILURE
;
2266 return ExAllocatePool2( flags
, size
, 0 );
2269 /***********************************************************************
2270 * ExAllocatePoolWithTag (NTOSKRNL.EXE.@)
2272 PVOID WINAPI
ExAllocatePoolWithTag( POOL_TYPE type
, SIZE_T size
, ULONG tag
)
2274 POOL_FLAGS flags
= pool_type_to_flags( type
);
2275 if (type
& POOL_RAISE_IF_ALLOCATION_FAILURE
)
2276 flags
|= POOL_FLAG_RAISE_ON_FAILURE
;
2278 return ExAllocatePool2( flags
, size
, tag
);
2281 /***********************************************************************
2282 * ExAllocatePoolWithQuotaTag (NTOSKRNL.EXE.@)
2284 PVOID WINAPI
ExAllocatePoolWithQuotaTag( POOL_TYPE type
, SIZE_T size
, ULONG tag
)
2286 POOL_FLAGS flags
= pool_type_to_flags( type
) | POOL_FLAG_USE_QUOTA
;
2287 if (!(type
& POOL_QUOTA_FAIL_INSTEAD_OF_RAISE
))
2288 flags
|= POOL_FLAG_RAISE_ON_FAILURE
;
2290 return ExAllocatePool2( flags
, size
, tag
);
2293 /***********************************************************************
2294 * ExCreateCallback (NTOSKRNL.EXE.@)
2296 NTSTATUS WINAPI
ExCreateCallback(PCALLBACK_OBJECT
*obj
, POBJECT_ATTRIBUTES attr
,
2297 BOOLEAN create
, BOOLEAN allow_multiple
)
2299 FIXME("(%p, %p, %u, %u): stub\n", obj
, attr
, create
, allow_multiple
);
2301 return STATUS_SUCCESS
;
2304 void * WINAPI
ExRegisterCallback(PCALLBACK_OBJECT callback_object
,
2305 PCALLBACK_FUNCTION callback_function
, void *callback_context
)
2307 FIXME("callback_object %p, callback_function %p, callback_context %p stub.\n",
2308 callback_object
, callback_function
, callback_context
);
2310 return (void *)0xdeadbeef;
2313 void WINAPI
ExUnregisterCallback(void *callback_registration
)
2315 FIXME("callback_registration %p stub.\n", callback_registration
);
2318 /***********************************************************************
2319 * ExNotifyCallback (NTOSKRNL.EXE.@)
2321 void WINAPI
ExNotifyCallback(void *obj
, void *arg1
, void *arg2
)
2323 FIXME("(%p, %p, %p): stub\n", obj
, arg1
, arg2
);
2326 /***********************************************************************
2327 * ExFreePool (NTOSKRNL.EXE.@)
2329 void WINAPI
ExFreePool( void *ptr
)
2331 ExFreePoolWithTag( ptr
, 0 );
2335 /***********************************************************************
2336 * ExFreePoolWithTag (NTOSKRNL.EXE.@)
2338 void WINAPI
ExFreePoolWithTag( void *ptr
, ULONG tag
)
2340 TRACE( "%p\n", ptr
);
2341 HeapFree( ntoskrnl_heap
, 0, ptr
);
2344 static void initialize_lookaside_list( GENERAL_LOOKASIDE
*lookaside
, PALLOCATE_FUNCTION allocate
, PFREE_FUNCTION free
,
2345 ULONG type
, SIZE_T size
, ULONG tag
)
2348 RtlInitializeSListHead( &lookaside
->ListHead
);
2349 lookaside
->Depth
= 4;
2350 lookaside
->MaximumDepth
= 256;
2351 lookaside
->TotalAllocates
= 0;
2352 lookaside
->AllocateMisses
= 0;
2353 lookaside
->TotalFrees
= 0;
2354 lookaside
->FreeMisses
= 0;
2355 lookaside
->Type
= type
;
2356 lookaside
->Tag
= tag
;
2357 lookaside
->Size
= size
;
2358 lookaside
->Allocate
= allocate
? allocate
: ExAllocatePoolWithTag
;
2359 lookaside
->Free
= free
? free
: ExFreePool
;
2360 lookaside
->LastTotalAllocates
= 0;
2361 lookaside
->LastAllocateMisses
= 0;
2363 /* FIXME: insert in global list of lookadside lists */
2366 /***********************************************************************
2367 * ExInitializeNPagedLookasideList (NTOSKRNL.EXE.@)
2369 void WINAPI
ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST lookaside
,
2370 PALLOCATE_FUNCTION allocate
,
2371 PFREE_FUNCTION free
,
2377 TRACE( "%p, %p, %p, %lu, %Iu, %lu, %u\n", lookaside
, allocate
, free
, flags
, size
, tag
, depth
);
2378 initialize_lookaside_list( &lookaside
->L
, allocate
, free
, NonPagedPool
| flags
, size
, tag
);
2381 /***********************************************************************
2382 * ExInitializePagedLookasideList (NTOSKRNL.EXE.@)
2384 void WINAPI
ExInitializePagedLookasideList(PPAGED_LOOKASIDE_LIST lookaside
,
2385 PALLOCATE_FUNCTION allocate
,
2386 PFREE_FUNCTION free
,
2392 TRACE( "%p, %p, %p, %lu, %Iu, %lu, %u\n", lookaside
, allocate
, free
, flags
, size
, tag
, depth
);
2393 initialize_lookaside_list( &lookaside
->L
, allocate
, free
, PagedPool
| flags
, size
, tag
);
2396 static void delete_lookaside_list( GENERAL_LOOKASIDE
*lookaside
)
2399 while ((entry
= RtlInterlockedPopEntrySList(&lookaside
->ListHead
)))
2400 lookaside
->FreeEx(entry
, (LOOKASIDE_LIST_EX
*)lookaside
);
2403 /***********************************************************************
2404 * ExDeleteNPagedLookasideList (NTOSKRNL.EXE.@)
2406 void WINAPI
ExDeleteNPagedLookasideList( PNPAGED_LOOKASIDE_LIST lookaside
)
2408 TRACE( "%p\n", lookaside
);
2409 delete_lookaside_list( &lookaside
->L
);
2413 /***********************************************************************
2414 * ExDeletePagedLookasideList (NTOSKRNL.EXE.@)
2416 void WINAPI
ExDeletePagedLookasideList( PPAGED_LOOKASIDE_LIST lookaside
)
2418 TRACE( "%p\n", lookaside
);
2419 delete_lookaside_list( &lookaside
->L
);
2422 /***********************************************************************
2423 * ExInitializeZone (NTOSKRNL.EXE.@)
2425 NTSTATUS WINAPI
ExInitializeZone(PZONE_HEADER Zone
,
2427 PVOID InitialSegment
,
2428 ULONG InitialSegmentSize
)
2430 FIXME( "stub: %p, %lu, %p, %lu\n", Zone
, BlockSize
, InitialSegment
, InitialSegmentSize
);
2431 return STATUS_NOT_IMPLEMENTED
;
2434 /***********************************************************************
2435 * FsRtlIsNameInExpression (NTOSKRNL.EXE.@)
2437 BOOLEAN WINAPI
FsRtlIsNameInExpression(PUNICODE_STRING expression
, PUNICODE_STRING name
,
2438 BOOLEAN ignore
, PWCH upcase
)
2440 FIXME("stub: %p %p %d %p\n", expression
, name
, ignore
, upcase
);
2444 /***********************************************************************
2445 * FsRtlRegisterUncProvider (NTOSKRNL.EXE.@)
2447 NTSTATUS WINAPI
FsRtlRegisterUncProvider(PHANDLE MupHandle
, PUNICODE_STRING RedirDevName
,
2448 BOOLEAN MailslotsSupported
)
2450 FIXME("(%p %p %d): stub\n", MupHandle
, RedirDevName
, MailslotsSupported
);
2451 return STATUS_NOT_IMPLEMENTED
;
2455 static void *create_process_object( HANDLE handle
)
2459 if (!(process
= alloc_kernel_object( PsProcessType
, handle
, sizeof(*process
), 0 ))) return NULL
;
2461 process
->header
.Type
= 3;
2462 process
->header
.WaitListHead
.Blink
= INVALID_HANDLE_VALUE
; /* mark as kernel object */
2463 NtQueryInformationProcess( handle
, ProcessBasicInformation
, &process
->info
, sizeof(process
->info
), NULL
);
2464 IsWow64Process( handle
, &process
->wow64
);
2468 static const WCHAR process_type_name
[] = {'P','r','o','c','e','s','s',0};
2470 static struct _OBJECT_TYPE process_type
=
2473 create_process_object
2476 POBJECT_TYPE PsProcessType
= &process_type
;
2479 /***********************************************************************
2480 * IoGetCurrentProcess / PsGetCurrentProcess (NTOSKRNL.EXE.@)
2482 PEPROCESS WINAPI
IoGetCurrentProcess(void)
2484 return KeGetCurrentThread()->process
;
2487 /***********************************************************************
2488 * PsLookupProcessByProcessId (NTOSKRNL.EXE.@)
2490 NTSTATUS WINAPI
PsLookupProcessByProcessId( HANDLE processid
, PEPROCESS
*process
)
2495 TRACE( "(%p %p)\n", processid
, process
);
2497 if (!(handle
= OpenProcess( PROCESS_ALL_ACCESS
, FALSE
, HandleToUlong(processid
) )))
2498 return STATUS_INVALID_PARAMETER
;
2500 status
= ObReferenceObjectByHandle( handle
, PROCESS_ALL_ACCESS
, PsProcessType
, KernelMode
, (void**)process
, NULL
);
2506 /*********************************************************************
2507 * PsGetProcessId (NTOSKRNL.@)
2509 HANDLE WINAPI
PsGetProcessId(PEPROCESS process
)
2511 TRACE( "%p -> %Ix\n", process
, process
->info
.UniqueProcessId
);
2512 return (HANDLE
)process
->info
.UniqueProcessId
;
2515 /*********************************************************************
2516 * PsGetProcessInheritedFromUniqueProcessId (NTOSKRNL.@)
2518 HANDLE WINAPI
PsGetProcessInheritedFromUniqueProcessId( PEPROCESS process
)
2520 HANDLE id
= (HANDLE
)process
->info
.InheritedFromUniqueProcessId
;
2521 TRACE( "%p -> %p\n", process
, id
);
2525 static void *create_thread_object( HANDLE handle
)
2527 THREAD_BASIC_INFORMATION info
;
2528 struct _KTHREAD
*thread
;
2531 if (!(thread
= alloc_kernel_object( PsThreadType
, handle
, sizeof(*thread
), 0 ))) return NULL
;
2533 thread
->header
.Type
= 6;
2534 thread
->header
.WaitListHead
.Blink
= INVALID_HANDLE_VALUE
; /* mark as kernel object */
2535 thread
->user_affinity
= 0;
2537 if (!NtQueryInformationThread( handle
, ThreadBasicInformation
, &info
, sizeof(info
), NULL
))
2539 thread
->id
= info
.ClientId
;
2540 if ((process
= OpenProcess( PROCESS_QUERY_INFORMATION
, FALSE
, HandleToUlong(thread
->id
.UniqueProcess
) )))
2542 kernel_object_from_handle( process
, PsProcessType
, (void**)&thread
->process
);
2551 static const WCHAR thread_type_name
[] = {'T','h','r','e','a','d',0};
2553 static struct _OBJECT_TYPE thread_type
=
2556 create_thread_object
2559 POBJECT_TYPE PsThreadType
= &thread_type
;
2562 /***********************************************************************
2563 * KeGetCurrentThread / PsGetCurrentThread (NTOSKRNL.EXE.@)
2565 PRKTHREAD WINAPI
KeGetCurrentThread(void)
2567 struct _KTHREAD
*thread
= NtCurrentTeb()->Instrumentation
[1];
2571 HANDLE handle
= GetCurrentThread();
2573 /* FIXME: we shouldn't need it, GetCurrentThread() should be client thread already */
2574 if (GetCurrentThreadId() == request_thread
)
2575 handle
= OpenThread( THREAD_QUERY_INFORMATION
, FALSE
, client_tid
);
2577 kernel_object_from_handle( handle
, PsThreadType
, (void**)&thread
);
2578 if (handle
!= GetCurrentThread()) NtClose( handle
);
2580 NtCurrentTeb()->Instrumentation
[1] = thread
;
2586 /*****************************************************
2587 * PsLookupThreadByThreadId (NTOSKRNL.EXE.@)
2589 NTSTATUS WINAPI
PsLookupThreadByThreadId( HANDLE threadid
, PETHREAD
*thread
)
2591 OBJECT_ATTRIBUTES attr
;
2596 TRACE( "(%p %p)\n", threadid
, thread
);
2598 cid
.UniqueProcess
= 0;
2599 cid
.UniqueThread
= threadid
;
2600 InitializeObjectAttributes( &attr
, NULL
, 0, NULL
, NULL
);
2601 status
= NtOpenThread( &handle
, THREAD_QUERY_INFORMATION
, &attr
, &cid
);
2602 if (status
) return status
;
2604 status
= ObReferenceObjectByHandle( handle
, THREAD_ALL_ACCESS
, PsThreadType
, KernelMode
, (void**)thread
, NULL
);
2610 /*********************************************************************
2611 * PsGetThreadId (NTOSKRNL.@)
2613 HANDLE WINAPI
PsGetThreadId(PETHREAD thread
)
2615 TRACE( "%p -> %p\n", thread
, thread
->kthread
.id
.UniqueThread
);
2616 return thread
->kthread
.id
.UniqueThread
;
2619 /*********************************************************************
2620 * PsGetThreadProcessId (NTOSKRNL.@)
2622 HANDLE WINAPI
PsGetThreadProcessId( PETHREAD thread
)
2624 TRACE( "%p -> %p\n", thread
, thread
->kthread
.id
.UniqueProcess
);
2625 return thread
->kthread
.id
.UniqueProcess
;
2628 /***********************************************************************
2629 * KeInsertQueue (NTOSKRNL.EXE.@)
2631 LONG WINAPI
KeInsertQueue(PRKQUEUE Queue
, PLIST_ENTRY Entry
)
2633 FIXME( "stub: %p %p\n", Queue
, Entry
);
2637 /***********************************************************************
2638 * KeInsertQueueDpc (NTOSKRNL.EXE.@)
2640 BOOLEAN WINAPI
KeInsertQueueDpc(PRKDPC Dpc
, PVOID SystemArgument1
, PVOID SystemArgument2
)
2642 FIXME( "stub: (%p %p %p)\n", Dpc
, SystemArgument1
, SystemArgument2
);
2646 /**********************************************************************
2647 * KeQueryActiveProcessors (NTOSKRNL.EXE.@)
2649 * Return the active Processors as bitmask
2652 * active Processors as bitmask
2655 KAFFINITY WINAPI
KeQueryActiveProcessors( void )
2657 DWORD_PTR affinity_mask
;
2659 GetProcessAffinityMask( GetCurrentProcess(), NULL
, &affinity_mask
);
2660 return affinity_mask
;
2663 ULONG WINAPI
KeQueryActiveProcessorCountEx(USHORT group_number
)
2665 TRACE("group_number %u.\n", group_number
);
2667 return GetActiveProcessorCount(group_number
);
2670 ULONG WINAPI
KeQueryActiveProcessorCount(PKAFFINITY active_processors
)
2672 TRACE("active_processors %p.\n", active_processors
);
2674 if(active_processors
)
2675 *active_processors
= KeQueryActiveProcessors();
2677 return KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS
);
2680 /**********************************************************************
2681 * KeQueryInterruptTime (NTOSKRNL.EXE.@)
2683 * Return the interrupt time count
2686 ULONGLONG WINAPI
KeQueryInterruptTime( void )
2688 LARGE_INTEGER totaltime
;
2690 KeQueryTickCount(&totaltime
);
2691 return totaltime
.QuadPart
;
2694 /***********************************************************************
2695 * KeQueryPriorityThread (NTOSKRNL.EXE.@)
2697 KPRIORITY WINAPI
KeQueryPriorityThread( PKTHREAD Thread
)
2699 FIXME("(%p): stub.\n", Thread
);
2700 /* priority must be a value between 0 and 31 */
2704 /***********************************************************************
2705 * KeQuerySystemTime (NTOSKRNL.EXE.@)
2707 void WINAPI
KeQuerySystemTime( LARGE_INTEGER
*time
)
2709 NtQuerySystemTime( time
);
2713 /***********************************************************************
2714 * KeQueryTickCount (NTOSKRNL.EXE.@)
2716 void WINAPI
KeQueryTickCount( LARGE_INTEGER
*count
)
2718 count
->QuadPart
= NtGetTickCount();
2719 /* update the global variable too */
2720 KeTickCount
.LowPart
= count
->u
.LowPart
;
2721 KeTickCount
.High1Time
= count
->u
.HighPart
;
2722 KeTickCount
.High2Time
= count
->u
.HighPart
;
2726 /***********************************************************************
2727 * KeQueryTimeIncrement (NTOSKRNL.EXE.@)
2729 ULONG WINAPI
KeQueryTimeIncrement(void)
2735 /***********************************************************************
2736 * KeSetPriorityThread (NTOSKRNL.EXE.@)
2738 KPRIORITY WINAPI
KeSetPriorityThread( PKTHREAD Thread
, KPRIORITY Priority
)
2740 FIXME("(%p %ld)\n", Thread
, Priority
);
2744 /***********************************************************************
2745 * KeSetSystemAffinityThread (NTOSKRNL.EXE.@)
2747 VOID WINAPI
KeSetSystemAffinityThread(KAFFINITY affinity
)
2749 KeSetSystemAffinityThreadEx(affinity
);
2752 KAFFINITY WINAPI
KeSetSystemAffinityThreadEx(KAFFINITY affinity
)
2754 DWORD_PTR system_affinity
= KeQueryActiveProcessors();
2755 PKTHREAD thread
= KeGetCurrentThread();
2756 GROUP_AFFINITY old
, new;
2758 TRACE("affinity %#Ix.\n", affinity
);
2760 affinity
&= system_affinity
;
2762 NtQueryInformationThread(GetCurrentThread(), ThreadGroupInformation
,
2763 &old
, sizeof(old
), NULL
);
2765 if (old
.Mask
!= system_affinity
)
2766 thread
->user_affinity
= old
.Mask
;
2768 memset(&new, 0, sizeof(new));
2769 new.Mask
= affinity
;
2771 return NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &new, sizeof(new))
2772 ? 0 : thread
->user_affinity
;
2776 /***********************************************************************
2777 * KeRevertToUserAffinityThread (NTOSKRNL.EXE.@)
2779 void WINAPI
KeRevertToUserAffinityThread(void)
2781 KeRevertToUserAffinityThreadEx(0);
2784 void WINAPI
KeRevertToUserAffinityThreadEx(KAFFINITY affinity
)
2786 DWORD_PTR system_affinity
= KeQueryActiveProcessors();
2787 PRKTHREAD thread
= KeGetCurrentThread();
2790 TRACE("affinity %#Ix.\n", affinity
);
2792 affinity
&= system_affinity
;
2794 memset(&new, 0, sizeof(new));
2795 new.Mask
= affinity
? affinity
2796 : (thread
->user_affinity
? thread
->user_affinity
: system_affinity
);
2798 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &new, sizeof(new));
2799 thread
->user_affinity
= affinity
;
2802 /***********************************************************************
2803 * IoRegisterFileSystem (NTOSKRNL.EXE.@)
2805 VOID WINAPI
IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject
)
2807 FIXME("(%p): stub\n", DeviceObject
);
2810 /***********************************************************************
2811 * KeExpandKernelStackAndCalloutEx (NTOSKRNL.EXE.@)
2813 NTSTATUS WINAPI
KeExpandKernelStackAndCalloutEx(PEXPAND_STACK_CALLOUT callout
, void *parameter
, SIZE_T size
,
2814 BOOLEAN wait
, void *context
)
2816 WARN("(%p %p %Iu %x %p) semi-stub: ignoring stack expand\n", callout
, parameter
, size
, wait
, context
);
2818 return STATUS_SUCCESS
;
2821 /***********************************************************************
2822 * KeExpandKernelStackAndCallout (NTOSKRNL.EXE.@)
2824 NTSTATUS WINAPI
KeExpandKernelStackAndCallout(PEXPAND_STACK_CALLOUT callout
, void *parameter
, SIZE_T size
)
2826 return KeExpandKernelStackAndCalloutEx(callout
, parameter
, size
, TRUE
, NULL
);
2829 /***********************************************************************
2830 * IoUnregisterFileSystem (NTOSKRNL.EXE.@)
2832 VOID WINAPI
IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject
)
2834 FIXME("(%p): stub\n", DeviceObject
);
2837 /***********************************************************************
2838 * MmAllocateNonCachedMemory (NTOSKRNL.EXE.@)
2840 PVOID WINAPI
MmAllocateNonCachedMemory( SIZE_T size
)
2842 TRACE( "%Iu\n", size
);
2843 return VirtualAlloc( NULL
, size
, MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
|PAGE_NOCACHE
);
2846 /***********************************************************************
2847 * MmAllocateContiguousMemory (NTOSKRNL.EXE.@)
2849 PVOID WINAPI
MmAllocateContiguousMemory( SIZE_T size
, PHYSICAL_ADDRESS highest_valid_address
)
2851 FIXME( "%Iu, %s stub\n", size
, wine_dbgstr_longlong(highest_valid_address
.QuadPart
) );
2855 /***********************************************************************
2856 * MmAllocateContiguousMemorySpecifyCache (NTOSKRNL.EXE.@)
2858 PVOID WINAPI
MmAllocateContiguousMemorySpecifyCache( SIZE_T size
,
2859 PHYSICAL_ADDRESS lowest_valid_address
,
2860 PHYSICAL_ADDRESS highest_valid_address
,
2861 PHYSICAL_ADDRESS BoundaryAddressMultiple
,
2862 MEMORY_CACHING_TYPE CacheType
)
2868 /***********************************************************************
2869 * MmAllocatePagesForMdl (NTOSKRNL.EXE.@)
2871 PMDL WINAPI
MmAllocatePagesForMdl(PHYSICAL_ADDRESS lowaddress
, PHYSICAL_ADDRESS highaddress
,
2872 PHYSICAL_ADDRESS skipbytes
, SIZE_T size
)
2874 FIXME("%s %s %s %Iu: stub\n", wine_dbgstr_longlong(lowaddress
.QuadPart
), wine_dbgstr_longlong(highaddress
.QuadPart
),
2875 wine_dbgstr_longlong(skipbytes
.QuadPart
), size
);
2879 /***********************************************************************
2880 * MmBuildMdlForNonPagedPool (NTOSKRNL.EXE.@)
2882 void WINAPI
MmBuildMdlForNonPagedPool(MDL
*mdl
)
2884 FIXME("stub: %p\n", mdl
);
2887 /***********************************************************************
2888 * MmCreateSection (NTOSKRNL.EXE.@)
2890 NTSTATUS WINAPI
MmCreateSection( HANDLE
*handle
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
,
2891 LARGE_INTEGER
*size
, ULONG protect
, ULONG alloc_attr
,
2892 HANDLE file
, FILE_OBJECT
*file_obj
)
2894 FIXME("%p %#lx %p %s %#lx %#lx %p %p: stub\n", handle
, access
, attr
,
2895 wine_dbgstr_longlong(size
->QuadPart
), protect
, alloc_attr
, file
, file_obj
);
2896 return STATUS_NOT_IMPLEMENTED
;
2899 /***********************************************************************
2900 * MmFreeNonCachedMemory (NTOSKRNL.EXE.@)
2902 void WINAPI
MmFreeNonCachedMemory( void *addr
, SIZE_T size
)
2904 TRACE( "%p %Iu\n", addr
, size
);
2905 VirtualFree( addr
, 0, MEM_RELEASE
);
2908 /***********************************************************************
2909 * MmIsAddressValid (NTOSKRNL.EXE.@)
2911 * Check if the process can access the virtual address without a pagefault
2914 * VirtualAddress [I] Address to check
2918 * Success: TRUE (Accessing the Address works without a Pagefault)
2921 BOOLEAN WINAPI
MmIsAddressValid(PVOID VirtualAddress
)
2923 TRACE("(%p)\n", VirtualAddress
);
2924 return !IsBadReadPtr(VirtualAddress
, 1);
2927 /***********************************************************************
2928 * MmGetPhysicalAddress (NTOSKRNL.EXE.@)
2930 PHYSICAL_ADDRESS WINAPI
MmGetPhysicalAddress(void *virtual_address
)
2932 PHYSICAL_ADDRESS ret
;
2933 FIXME("(%p): semi-stub\n", virtual_address
);
2934 ret
.QuadPart
= (ULONG_PTR
)virtual_address
;
2938 /***********************************************************************
2939 * MmMapIoSpace (NTOSKRNL.EXE.@)
2941 PVOID WINAPI
MmMapIoSpace( PHYSICAL_ADDRESS PhysicalAddress
, DWORD NumberOfBytes
, DWORD CacheType
)
2943 FIXME( "stub: 0x%08lx%08lx, %ld, %ld\n", PhysicalAddress
.HighPart
, PhysicalAddress
.LowPart
, NumberOfBytes
, CacheType
);
2948 /***********************************************************************
2949 * MmLockPagableSectionByHandle (NTOSKRNL.EXE.@)
2951 VOID WINAPI
MmLockPagableSectionByHandle(PVOID ImageSectionHandle
)
2953 FIXME("stub %p\n", ImageSectionHandle
);
2956 /***********************************************************************
2957 * MmMapLockedPagesSpecifyCache (NTOSKRNL.EXE.@)
2959 PVOID WINAPI
MmMapLockedPagesSpecifyCache(PMDLX MemoryDescriptorList
, KPROCESSOR_MODE AccessMode
, MEMORY_CACHING_TYPE CacheType
,
2960 PVOID BaseAddress
, ULONG BugCheckOnFailure
, MM_PAGE_PRIORITY Priority
)
2962 FIXME("(%p, %u, %u, %p, %lu, %u): stub\n", MemoryDescriptorList
, AccessMode
, CacheType
, BaseAddress
, BugCheckOnFailure
, Priority
);
2967 /***********************************************************************
2968 * MmUnmapLockedPages (NTOSKRNL.EXE.@)
2970 void WINAPI
MmUnmapLockedPages( void *base
, MDL
*mdl
)
2972 FIXME( "(%p %p_\n", base
, mdl
);
2975 /***********************************************************************
2976 * MmUnlockPagableImageSection (NTOSKRNL.EXE.@)
2978 VOID WINAPI
MmUnlockPagableImageSection(PVOID ImageSectionHandle
)
2980 FIXME("stub %p\n", ImageSectionHandle
);
2983 /***********************************************************************
2984 * MmPageEntireDriver (NTOSKRNL.EXE.@)
2986 PVOID WINAPI
MmPageEntireDriver(PVOID AddrInSection
)
2988 TRACE("%p\n", AddrInSection
);
2989 return AddrInSection
;
2993 /***********************************************************************
2994 * MmProbeAndLockPages (NTOSKRNL.EXE.@)
2996 void WINAPI
MmProbeAndLockPages(PMDLX MemoryDescriptorList
, KPROCESSOR_MODE AccessMode
, LOCK_OPERATION Operation
)
2998 FIXME("(%p, %u, %u): stub\n", MemoryDescriptorList
, AccessMode
, Operation
);
3002 /***********************************************************************
3003 * MmResetDriverPaging (NTOSKRNL.EXE.@)
3005 void WINAPI
MmResetDriverPaging(PVOID AddrInSection
)
3007 TRACE("%p\n", AddrInSection
);
3011 /***********************************************************************
3012 * MmUnlockPages (NTOSKRNL.EXE.@)
3014 void WINAPI
MmUnlockPages(PMDLX MemoryDescriptorList
)
3016 FIXME("(%p): stub\n", MemoryDescriptorList
);
3020 /***********************************************************************
3021 * MmUnmapIoSpace (NTOSKRNL.EXE.@)
3023 VOID WINAPI
MmUnmapIoSpace( PVOID BaseAddress
, SIZE_T NumberOfBytes
)
3025 FIXME( "stub: %p, %Iu\n", BaseAddress
, NumberOfBytes
);
3029 /***********************************************************************
3030 * ObReferenceObjectByName (NTOSKRNL.EXE.@)
3032 NTSTATUS WINAPI
ObReferenceObjectByName( UNICODE_STRING
*ObjectName
,
3034 ACCESS_STATE
*AccessState
,
3035 ACCESS_MASK DesiredAccess
,
3036 POBJECT_TYPE ObjectType
,
3037 KPROCESSOR_MODE AccessMode
,
3041 struct wine_driver
*driver
;
3042 struct wine_rb_entry
*entry
;
3044 TRACE("mostly-stub:%s %li %p %li %p %i %p %p\n", debugstr_us(ObjectName
),
3045 Attributes
, AccessState
, DesiredAccess
, ObjectType
, AccessMode
,
3046 ParseContext
, Object
);
3048 if (AccessState
) FIXME("Unhandled AccessState\n");
3049 if (DesiredAccess
) FIXME("Unhandled DesiredAccess\n");
3050 if (ParseContext
) FIXME("Unhandled ParseContext\n");
3051 if (ObjectType
) FIXME("Unhandled ObjectType\n");
3053 if (AccessMode
!= KernelMode
)
3055 FIXME("UserMode access not implemented\n");
3056 return STATUS_NOT_IMPLEMENTED
;
3059 EnterCriticalSection(&drivers_cs
);
3060 entry
= wine_rb_get(&wine_drivers
, ObjectName
);
3061 LeaveCriticalSection(&drivers_cs
);
3064 FIXME("Object (%s) not found, may not be tracked.\n", debugstr_us(ObjectName
));
3065 return STATUS_NOT_IMPLEMENTED
;
3068 driver
= WINE_RB_ENTRY_VALUE(entry
, struct wine_driver
, entry
);
3069 ObReferenceObject( *Object
= &driver
->driver_obj
);
3070 return STATUS_SUCCESS
;
3074 /********************************************************************
3075 * ObOpenObjectByName (NTOSKRNL.EXE.@)
3077 NTSTATUS WINAPI
ObOpenObjectByName(POBJECT_ATTRIBUTES attr
, POBJECT_TYPE type
,
3078 KPROCESSOR_MODE mode
, ACCESS_STATE
*access_state
,
3079 ACCESS_MASK access
, PVOID ctx
, HANDLE
*handle
)
3084 TRACE( "attr(%p %s %lx) %p %u %p %lu %p %p\n", attr
->RootDirectory
, debugstr_us(attr
->ObjectName
),
3085 attr
->Attributes
, type
, mode
, access_state
, access
, ctx
, handle
);
3087 if (mode
!= KernelMode
)
3089 FIXME( "UserMode access not implemented\n" );
3090 return STATUS_NOT_IMPLEMENTED
;
3093 if (attr
->RootDirectory
) FIXME( "RootDirectory unhandled\n" );
3095 status
= ObReferenceObjectByName(attr
->ObjectName
, attr
->Attributes
, access_state
, access
, type
, mode
, ctx
, &object
);
3096 if (status
!= STATUS_SUCCESS
)
3099 status
= ObOpenObjectByPointer(object
, attr
->Attributes
, access_state
, access
, type
, mode
, handle
);
3101 ObDereferenceObject(object
);
3106 /***********************************************************************
3107 * ObReferenceObjectByPointer (NTOSKRNL.EXE.@)
3109 NTSTATUS WINAPI
ObReferenceObjectByPointer(void *obj
, ACCESS_MASK access
,
3111 KPROCESSOR_MODE mode
)
3113 FIXME("(%p, %lx, %p, %d): stub\n", obj
, access
, type
, mode
);
3115 return STATUS_NOT_IMPLEMENTED
;
3119 /***********************************************************************
3120 * ObfReferenceObject (NTOSKRNL.EXE.@)
3122 DEFINE_FASTCALL1_WRAPPER( ObfReferenceObject
)
3123 void FASTCALL
ObfReferenceObject( void *obj
)
3125 ObReferenceObject( obj
);
3129 /***********************************************************************
3130 * ObfDereferenceObject (NTOSKRNL.EXE.@)
3132 DEFINE_FASTCALL1_WRAPPER( ObfDereferenceObject
)
3133 void FASTCALL
ObfDereferenceObject( void *obj
)
3135 ObDereferenceObject( obj
);
3138 /***********************************************************************
3139 * ObRegisterCallbacks (NTOSKRNL.EXE.@)
3141 NTSTATUS WINAPI
ObRegisterCallbacks(POB_CALLBACK_REGISTRATION callback
, void **handle
)
3143 FIXME( "callback %p, handle %p.\n", callback
, handle
);
3146 *handle
= UlongToHandle(0xdeadbeaf);
3148 return STATUS_SUCCESS
;
3151 /***********************************************************************
3152 * ObUnRegisterCallbacks (NTOSKRNL.EXE.@)
3154 void WINAPI
ObUnRegisterCallbacks(void *handle
)
3156 FIXME( "stub: %p\n", handle
);
3159 /***********************************************************************
3160 * ObGetFilterVersion (NTOSKRNL.EXE.@)
3162 USHORT WINAPI
ObGetFilterVersion(void)
3166 return OB_FLT_REGISTRATION_VERSION
;
3169 /***********************************************************************
3170 * IoGetAttachedDeviceReference (NTOSKRNL.EXE.@)
3172 DEVICE_OBJECT
* WINAPI
IoGetAttachedDeviceReference( DEVICE_OBJECT
*device
)
3174 DEVICE_OBJECT
*result
= IoGetAttachedDevice( device
);
3175 ObReferenceObject( result
);
3180 /***********************************************************************
3181 * PsCreateSystemThread (NTOSKRNL.EXE.@)
3183 NTSTATUS WINAPI
PsCreateSystemThread(PHANDLE ThreadHandle
, ULONG DesiredAccess
,
3184 POBJECT_ATTRIBUTES ObjectAttributes
,
3185 HANDLE ProcessHandle
, PCLIENT_ID ClientId
,
3186 PKSTART_ROUTINE StartRoutine
, PVOID StartContext
)
3188 if (!ProcessHandle
) ProcessHandle
= GetCurrentProcess();
3189 return RtlCreateUserThread(ProcessHandle
, 0, FALSE
, 0, 0,
3190 0, StartRoutine
, StartContext
,
3191 ThreadHandle
, ClientId
);
3194 /***********************************************************************
3195 * PsGetCurrentProcessId (NTOSKRNL.EXE.@)
3197 HANDLE WINAPI
PsGetCurrentProcessId(void)
3199 return KeGetCurrentThread()->id
.UniqueProcess
;
3202 /***********************************************************************
3203 * PsGetCurrentProcessSessionId (NTOSKRNL.EXE.@)
3205 ULONG WINAPI
PsGetCurrentProcessSessionId(void)
3207 return PsGetCurrentProcess()->info
.PebBaseAddress
->SessionId
;
3210 /***********************************************************************
3211 * PsGetCurrentThreadId (NTOSKRNL.EXE.@)
3213 HANDLE WINAPI
PsGetCurrentThreadId(void)
3215 return KeGetCurrentThread()->id
.UniqueThread
;
3219 /***********************************************************************
3220 * PsIsSystemThread (NTOSKRNL.EXE.@)
3222 BOOLEAN WINAPI
PsIsSystemThread(PETHREAD thread
)
3224 return thread
->kthread
.process
== PsInitialSystemProcess
;
3228 /***********************************************************************
3229 * PsGetVersion (NTOSKRNL.EXE.@)
3231 BOOLEAN WINAPI
PsGetVersion(ULONG
*major
, ULONG
*minor
, ULONG
*build
, UNICODE_STRING
*version
)
3233 RTL_OSVERSIONINFOEXW info
;
3235 info
.dwOSVersionInfoSize
= sizeof(info
);
3236 RtlGetVersion( &info
);
3237 if (major
) *major
= info
.dwMajorVersion
;
3238 if (minor
) *minor
= info
.dwMinorVersion
;
3239 if (build
) *build
= info
.dwBuildNumber
;
3243 #if 0 /* FIXME: GameGuard passes an uninitialized pointer in version->Buffer */
3244 size_t len
= min( lstrlenW(info
.szCSDVersion
)*sizeof(WCHAR
), version
->MaximumLength
);
3245 memcpy( version
->Buffer
, info
.szCSDVersion
, len
);
3246 if (len
< version
->MaximumLength
) version
->Buffer
[len
/ sizeof(WCHAR
)] = 0;
3247 version
->Length
= len
;
3254 /***********************************************************************
3255 * PsImpersonateClient (NTOSKRNL.EXE.@)
3257 NTSTATUS WINAPI
PsImpersonateClient(PETHREAD Thread
, PACCESS_TOKEN Token
, BOOLEAN CopyOnOpen
,
3258 BOOLEAN EffectiveOnly
, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
3260 FIXME("(%p, %p, %u, %u, %u): stub\n", Thread
, Token
, CopyOnOpen
, EffectiveOnly
, ImpersonationLevel
);
3262 return STATUS_NOT_IMPLEMENTED
;
3266 /***********************************************************************
3267 * PsRevertToSelf (NTOSKRNL.EXE.@)
3269 void WINAPI
PsRevertToSelf(void)
3275 /***********************************************************************
3276 * PsSetCreateProcessNotifyRoutine (NTOSKRNL.EXE.@)
3278 NTSTATUS WINAPI
PsSetCreateProcessNotifyRoutine( PCREATE_PROCESS_NOTIFY_ROUTINE callback
, BOOLEAN remove
)
3280 FIXME( "stub: %p %d\n", callback
, remove
);
3281 return STATUS_SUCCESS
;
3285 /***********************************************************************
3286 * PsSetCreateProcessNotifyRoutineEx (NTOSKRNL.EXE.@)
3288 NTSTATUS WINAPI
PsSetCreateProcessNotifyRoutineEx( PCREATE_PROCESS_NOTIFY_ROUTINE_EX callback
, BOOLEAN remove
)
3290 FIXME( "stub: %p %d\n", callback
, remove
);
3291 return STATUS_SUCCESS
;
3295 /***********************************************************************
3296 * PsSetCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
3298 NTSTATUS WINAPI
PsSetCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
3300 FIXME( "stub: %p\n", NotifyRoutine
);
3301 return STATUS_SUCCESS
;
3305 /***********************************************************************
3306 * PsRemoveCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
3308 NTSTATUS WINAPI
PsRemoveCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
3310 FIXME( "stub: %p\n", NotifyRoutine
);
3311 return STATUS_SUCCESS
;
3315 /***********************************************************************
3316 * PsRemoveLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
3318 NTSTATUS WINAPI
PsRemoveLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine
)
3322 TRACE("routine %p.\n", routine
);
3324 for (i
= 0; i
< load_image_notify_routine_count
; ++i
)
3325 if (load_image_notify_routines
[i
] == routine
)
3327 --load_image_notify_routine_count
;
3328 memmove(&load_image_notify_routines
[i
], &load_image_notify_routines
[i
+ 1],
3329 sizeof(*load_image_notify_routines
) * (load_image_notify_routine_count
- i
));
3330 return STATUS_SUCCESS
;
3332 return STATUS_PROCEDURE_NOT_FOUND
;
3336 /***********************************************************************
3337 * PsReferenceProcessFilePointer (NTOSKRNL.EXE.@)
3339 NTSTATUS WINAPI
PsReferenceProcessFilePointer(PEPROCESS process
, FILE_OBJECT
**file
)
3341 FIXME("%p %p\n", process
, file
);
3342 return STATUS_NOT_IMPLEMENTED
;
3346 /***********************************************************************
3347 * PsTerminateSystemThread (NTOSKRNL.EXE.@)
3349 NTSTATUS WINAPI
PsTerminateSystemThread(NTSTATUS status
)
3351 TRACE("status %#lx.\n", status
);
3352 ExitThread( status
);
3356 /***********************************************************************
3357 * PsSuspendProcess (NTOSKRNL.EXE.@)
3359 NTSTATUS WINAPI
PsSuspendProcess(PEPROCESS process
)
3361 FIXME("stub: %p\n", process
);
3362 return STATUS_NOT_IMPLEMENTED
;
3366 /***********************************************************************
3367 * PsResumeProcess (NTOSKRNL.EXE.@)
3369 NTSTATUS WINAPI
PsResumeProcess(PEPROCESS process
)
3371 FIXME("stub: %p\n", process
);
3372 return STATUS_NOT_IMPLEMENTED
;
3376 /***********************************************************************
3377 * MmGetSystemRoutineAddress (NTOSKRNL.EXE.@)
3379 PVOID WINAPI
MmGetSystemRoutineAddress(PUNICODE_STRING SystemRoutineName
)
3382 STRING routineNameA
;
3385 static const WCHAR ntoskrnlW
[] = {'n','t','o','s','k','r','n','l','.','e','x','e',0};
3386 static const WCHAR halW
[] = {'h','a','l','.','d','l','l',0};
3388 if (!SystemRoutineName
) return NULL
;
3390 if (RtlUnicodeStringToAnsiString( &routineNameA
, SystemRoutineName
, TRUE
) == STATUS_SUCCESS
)
3392 /* We only support functions exported from ntoskrnl.exe or hal.dll */
3393 hMod
= GetModuleHandleW( ntoskrnlW
);
3394 pFunc
= GetProcAddress( hMod
, routineNameA
.Buffer
);
3397 hMod
= LoadLibraryW( halW
);
3398 if (hMod
) pFunc
= GetProcAddress( hMod
, routineNameA
.Buffer
);
3400 RtlFreeAnsiString( &routineNameA
);
3404 TRACE( "%s -> %p\n", debugstr_us(SystemRoutineName
), pFunc
);
3406 FIXME( "%s not found\n", debugstr_us(SystemRoutineName
) );
3410 /***********************************************************************
3411 * MmIsThisAnNtAsSystem (NTOSKRNL.EXE.@)
3413 BOOLEAN WINAPI
MmIsThisAnNtAsSystem(void)
3419 /***********************************************************************
3420 * MmProtectMdlSystemAddress (NTOSKRNL.EXE.@)
3422 NTSTATUS WINAPI
MmProtectMdlSystemAddress(PMDL MemoryDescriptorList
, ULONG NewProtect
)
3424 FIXME("(%p, %lu) stub\n", MemoryDescriptorList
, NewProtect
);
3425 return STATUS_SUCCESS
;
3428 /***********************************************************************
3429 * MmQuerySystemSize (NTOSKRNL.EXE.@)
3431 MM_SYSTEMSIZE WINAPI
MmQuerySystemSize(void)
3434 return MmLargeSystem
;
3437 /***********************************************************************
3438 * KeInitializeDpc (NTOSKRNL.EXE.@)
3440 void WINAPI
KeInitializeDpc(KDPC
*dpc
, PKDEFERRED_ROUTINE deferred_routine
, void *deferred_context
)
3442 FIXME("dpc %p, deferred_routine %p, deferred_context %p semi-stub.\n",
3443 dpc
, deferred_routine
, deferred_context
);
3445 dpc
->DeferredRoutine
= deferred_routine
;
3446 dpc
->DeferredContext
= deferred_context
;
3449 /***********************************************************************
3450 * KeSetImportanceDpc (NTOSKRNL.EXE.@)
3452 VOID WINAPI
KeSetImportanceDpc(PRKDPC dpc
, KDPC_IMPORTANCE importance
)
3454 FIXME("%p, %d stub\n", dpc
, importance
);
3457 /***********************************************************************
3458 * KeSetTargetProcessorDpcEx (NTOSKRNL.EXE.@)
3460 VOID WINAPI
KeSetTargetProcessorDpcEx(PRKDPC dpc
, PPROCESSOR_NUMBER process_number
)
3462 FIXME("%p, %p stub\n", dpc
, process_number
);
3465 /***********************************************************************
3466 * KeSetTargetProcessorDpc (NTOSKRNL.EXE.@)
3468 VOID WINAPI
KeSetTargetProcessorDpc(PRKDPC dpc
, CCHAR number
)
3470 FIXME("%p, %d stub\n", dpc
, number
);
3473 /***********************************************************************
3474 * KeGetCurrentProcessorNumberEx (NTOSKRNL.EXE.@)
3476 ULONG WINAPI
KeGetCurrentProcessorNumberEx(PPROCESSOR_NUMBER process_number
)
3478 ULONG cur_number
= NtGetCurrentProcessorNumber();
3480 FIXME("%p semi-stub\n", process_number
);
3484 process_number
->Group
= 0;
3485 process_number
->Reserved
= 0;
3486 process_number
->Number
= cur_number
;
3492 /***********************************************************************
3493 * KeQueryMaximumProcessorCountEx (NTOSKRNL.EXE.@)
3495 ULONG WINAPI
KeQueryMaximumProcessorCountEx(USHORT group_number
)
3497 return GetMaximumProcessorCount(group_number
);
3500 /***********************************************************************
3501 * KeQueryMaximumProcessorCount (NTOSKRNL.EXE.@)
3503 ULONG WINAPI
KeQueryMaximumProcessorCount(void)
3505 return KeQueryMaximumProcessorCountEx(0);
3508 /***********************************************************************
3509 * READ_REGISTER_BUFFER_UCHAR (NTOSKRNL.EXE.@)
3511 VOID WINAPI
READ_REGISTER_BUFFER_UCHAR(PUCHAR Register
, PUCHAR Buffer
, ULONG Count
)
3516 /*****************************************************
3517 * IoWMIRegistrationControl (NTOSKRNL.EXE.@)
3519 NTSTATUS WINAPI
IoWMIRegistrationControl(PDEVICE_OBJECT DeviceObject
, ULONG Action
)
3521 FIXME("(%p %lu) stub\n", DeviceObject
, Action
);
3522 return STATUS_SUCCESS
;
3525 /*****************************************************
3526 * IoWMIOpenBlock (NTOSKRNL.EXE.@)
3528 NTSTATUS WINAPI
IoWMIOpenBlock(LPCGUID guid
, ULONG desired_access
, PVOID
*data_block_obj
)
3530 FIXME("(%p %lu %p) stub\n", guid
, desired_access
, data_block_obj
);
3531 return STATUS_NOT_IMPLEMENTED
;
3534 /*****************************************************
3535 * PsSetLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
3537 NTSTATUS WINAPI
PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine
)
3539 return PsSetLoadImageNotifyRoutineEx(routine
, 0);
3542 /*****************************************************
3543 * PsSetLoadImageNotifyRoutineEx (NTOSKRNL.EXE.@)
3545 NTSTATUS WINAPI
PsSetLoadImageNotifyRoutineEx(PLOAD_IMAGE_NOTIFY_ROUTINE routine
, ULONG_PTR flags
)
3547 FIXME("routine %p, flags %Ix semi-stub.\n", routine
, flags
);
3549 if (load_image_notify_routine_count
== ARRAY_SIZE(load_image_notify_routines
))
3550 return STATUS_INSUFFICIENT_RESOURCES
;
3552 load_image_notify_routines
[load_image_notify_routine_count
++] = routine
;
3554 return STATUS_SUCCESS
;
3557 /*****************************************************
3558 * IoSetThreadHardErrorMode (NTOSKRNL.EXE.@)
3560 BOOLEAN WINAPI
IoSetThreadHardErrorMode(BOOLEAN EnableHardErrors
)
3566 /*****************************************************
3567 * Ke386IoSetAccessProcess (NTOSKRNL.EXE.@)
3569 BOOLEAN WINAPI
Ke386IoSetAccessProcess(PEPROCESS
*process
, ULONG flag
)
3571 FIXME("(%p %ld) stub\n", process
, flag
);
3575 /*****************************************************
3576 * Ke386QueryIoAccessMap (NTOSKRNL.EXE.@)
3578 BOOLEAN WINAPI
Ke386QueryIoAccessMap(ULONG flag
, PVOID buffer
)
3580 FIXME("(%ld %p) stub\n", flag
, buffer
);
3584 /*****************************************************
3585 * Ke386SetIoAccessMap (NTOSKRNL.EXE.@)
3587 BOOLEAN WINAPI
Ke386SetIoAccessMap(ULONG flag
, PVOID buffer
)
3589 FIXME("(%ld %p) stub\n", flag
, buffer
);
3593 /*****************************************************
3594 * IoStartNextPacket (NTOSKRNL.EXE.@)
3596 VOID WINAPI
IoStartNextPacket(PDEVICE_OBJECT deviceobject
, BOOLEAN cancelable
)
3598 FIXME("(%p %d) stub\n", deviceobject
, cancelable
);
3601 /*****************************************************
3602 * ObQueryNameString (NTOSKRNL.EXE.@)
3604 NTSTATUS WINAPI
ObQueryNameString( void *object
, OBJECT_NAME_INFORMATION
*name
, ULONG size
, ULONG
*ret_size
)
3609 TRACE("object %p, name %p, size %lu, ret_size %p.\n", object
, name
, size
, ret_size
);
3611 if ((ret
= ObOpenObjectByPointer( object
, 0, NULL
, 0, NULL
, KernelMode
, &handle
)))
3613 ret
= NtQueryObject( handle
, ObjectNameInformation
, name
, size
, ret_size
);
3619 /*****************************************************
3620 * IoRegisterPlugPlayNotification (NTOSKRNL.EXE.@)
3622 NTSTATUS WINAPI
IoRegisterPlugPlayNotification(IO_NOTIFICATION_EVENT_CATEGORY category
, ULONG flags
, PVOID data
,
3623 PDRIVER_OBJECT driver
, PDRIVER_NOTIFICATION_CALLBACK_ROUTINE callback
,
3624 PVOID context
, PVOID
*notification
)
3626 FIXME("(%u %lu %p %p %p %p %p) stub\n", category
, flags
, data
, driver
, callback
, context
, notification
);
3627 return STATUS_SUCCESS
;
3630 /*****************************************************
3631 * IoUnregisterPlugPlayNotification (NTOSKRNL.EXE.@)
3633 NTSTATUS WINAPI
IoUnregisterPlugPlayNotification(PVOID notification
)
3635 FIXME("stub: %p\n", notification
);
3636 return STATUS_SUCCESS
;
3639 /*****************************************************
3640 * IoCsqInitialize (NTOSKRNL.EXE.@)
3642 NTSTATUS WINAPI
IoCsqInitialize(PIO_CSQ csq
, PIO_CSQ_INSERT_IRP insert_irp
, PIO_CSQ_REMOVE_IRP remove_irp
,
3643 PIO_CSQ_PEEK_NEXT_IRP peek_irp
, PIO_CSQ_ACQUIRE_LOCK acquire_lock
,
3644 PIO_CSQ_RELEASE_LOCK release_lock
, PIO_CSQ_COMPLETE_CANCELED_IRP complete_irp
)
3646 FIXME("(%p %p %p %p %p %p %p) stub\n",
3647 csq
, insert_irp
, remove_irp
, peek_irp
, acquire_lock
, release_lock
, complete_irp
);
3648 return STATUS_SUCCESS
;
3651 /***********************************************************************
3652 * KeEnterCriticalRegion (NTOSKRNL.EXE.@)
3654 void WINAPI
KeEnterCriticalRegion(void)
3656 TRACE( "semi-stub\n" );
3657 KeGetCurrentThread()->critical_region
++;
3660 /***********************************************************************
3661 * KeLeaveCriticalRegion (NTOSKRNL.EXE.@)
3663 void WINAPI
KeLeaveCriticalRegion(void)
3665 TRACE( "semi-stub\n" );
3666 KeGetCurrentThread()->critical_region
--;
3669 /***********************************************************************
3670 * KeAreApcsDisabled (NTOSKRNL.@)
3672 BOOLEAN WINAPI
KeAreApcsDisabled(void)
3674 unsigned int critical_region
= KeGetCurrentThread()->critical_region
;
3675 TRACE( "%u\n", critical_region
);
3676 return !!critical_region
;
3679 /***********************************************************************
3680 * KeAreAllApcsDisabled (NTOSKRNL.@)
3682 BOOLEAN WINAPI
KeAreAllApcsDisabled(void)
3684 return KeAreApcsDisabled();
3687 /***********************************************************************
3688 * KeBugCheck (NTOSKRNL.@)
3690 void WINAPI
KeBugCheck(ULONG code
)
3692 KeBugCheckEx(code
, 0, 0, 0, 0);
3695 /***********************************************************************
3696 * KeBugCheckEx (NTOSKRNL.@)
3698 void WINAPI
KeBugCheckEx(ULONG code
, ULONG_PTR param1
, ULONG_PTR param2
, ULONG_PTR param3
, ULONG_PTR param4
)
3700 ERR( "%lx %Ix %Ix %Ix %Ix\n", code
, param1
, param2
, param3
, param4
);
3701 ExitProcess( code
);
3704 /***********************************************************************
3705 * ProbeForRead (NTOSKRNL.EXE.@)
3707 void WINAPI
ProbeForRead(void *address
, SIZE_T length
, ULONG alignment
)
3709 FIXME("(%p %Iu %lu) stub\n", address
, length
, alignment
);
3712 /***********************************************************************
3713 * ProbeForWrite (NTOSKRNL.EXE.@)
3715 void WINAPI
ProbeForWrite(void *address
, SIZE_T length
, ULONG alignment
)
3717 FIXME("(%p %Iu %lu) stub\n", address
, length
, alignment
);
3720 /***********************************************************************
3721 * CmRegisterCallback (NTOSKRNL.EXE.@)
3723 NTSTATUS WINAPI
CmRegisterCallback(EX_CALLBACK_FUNCTION
*function
, void *context
, LARGE_INTEGER
*cookie
)
3725 FIXME("(%p %p %p): stub\n", function
, context
, cookie
);
3726 return STATUS_NOT_IMPLEMENTED
;
3729 /***********************************************************************
3730 * CmUnRegisterCallback (NTOSKRNL.EXE.@)
3732 NTSTATUS WINAPI
CmUnRegisterCallback(LARGE_INTEGER cookie
)
3734 FIXME("(%s): stub\n", wine_dbgstr_longlong(cookie
.QuadPart
));
3735 return STATUS_NOT_IMPLEMENTED
;
3738 /***********************************************************************
3739 * IoAttachDevice (NTOSKRNL.EXE.@)
3741 NTSTATUS WINAPI
IoAttachDevice(DEVICE_OBJECT
*source
, UNICODE_STRING
*target
, DEVICE_OBJECT
*attached
)
3743 FIXME("(%p, %s, %p): stub\n", source
, debugstr_us(target
), attached
);
3744 return STATUS_NOT_IMPLEMENTED
;
3748 static NTSTATUS
open_driver( const UNICODE_STRING
*service_name
, SC_HANDLE
*service
)
3750 QUERY_SERVICE_CONFIGW
*service_config
= NULL
;
3751 SC_HANDLE manager_handle
;
3752 DWORD config_size
= 0;
3755 if (!(name
= RtlAllocateHeap( GetProcessHeap(), 0, service_name
->Length
+ sizeof(WCHAR
) )))
3756 return STATUS_NO_MEMORY
;
3758 memcpy( name
, service_name
->Buffer
, service_name
->Length
);
3759 name
[ service_name
->Length
/ sizeof(WCHAR
) ] = 0;
3761 if (wcsncmp( name
, servicesW
, lstrlenW(servicesW
) ))
3763 FIXME( "service name %s is not a keypath\n", debugstr_us(service_name
) );
3764 RtlFreeHeap( GetProcessHeap(), 0, name
);
3765 return STATUS_NOT_IMPLEMENTED
;
3768 if (!(manager_handle
= OpenSCManagerW( NULL
, NULL
, SC_MANAGER_CONNECT
)))
3770 WARN( "failed to connect to service manager\n" );
3771 RtlFreeHeap( GetProcessHeap(), 0, name
);
3772 return STATUS_NOT_SUPPORTED
;
3775 *service
= OpenServiceW( manager_handle
, name
+ lstrlenW(servicesW
),
3776 SERVICE_QUERY_CONFIG
| SERVICE_SET_STATUS
);
3777 RtlFreeHeap( GetProcessHeap(), 0, name
);
3778 CloseServiceHandle( manager_handle
);
3782 WARN( "failed to open service %s\n", debugstr_us(service_name
) );
3783 return STATUS_UNSUCCESSFUL
;
3786 QueryServiceConfigW( *service
, NULL
, 0, &config_size
);
3787 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
3789 WARN( "failed to query service config\n" );
3793 if (!(service_config
= RtlAllocateHeap( GetProcessHeap(), 0, config_size
)))
3796 if (!QueryServiceConfigW( *service
, service_config
, config_size
, &config_size
))
3798 WARN( "failed to query service config\n" );
3802 if (service_config
->dwServiceType
!= SERVICE_KERNEL_DRIVER
&&
3803 service_config
->dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
)
3805 WARN( "service %s is not a kernel driver\n", debugstr_us(service_name
) );
3809 TRACE( "opened service for driver %s\n", debugstr_us(service_name
) );
3810 RtlFreeHeap( GetProcessHeap(), 0, service_config
);
3811 return STATUS_SUCCESS
;
3814 CloseServiceHandle( *service
);
3815 RtlFreeHeap( GetProcessHeap(), 0, service_config
);
3816 return STATUS_UNSUCCESSFUL
;
3819 /* find the LDR_DATA_TABLE_ENTRY corresponding to the driver module */
3820 static LDR_DATA_TABLE_ENTRY
*find_ldr_module( HMODULE module
)
3822 LDR_DATA_TABLE_ENTRY
*ldr
;
3825 LdrLockLoaderLock( 0, NULL
, &magic
);
3826 if (LdrFindEntryForAddress( module
, &ldr
))
3828 WARN( "module not found for %p\n", module
);
3831 LdrUnlockLoaderLock( 0, magic
);
3836 /* convert PE image VirtualAddress to Real Address */
3837 static inline void *get_rva( HMODULE module
, DWORD va
)
3839 return (void *)((char *)module
+ va
);
3842 static void WINAPI
ldr_notify_callback(ULONG reason
, LDR_DLL_NOTIFICATION_DATA
*data
, void *context
)
3844 const IMAGE_DATA_DIRECTORY
*relocs
;
3845 IMAGE_BASE_RELOCATION
*rel
, *end
;
3846 SYSTEM_BASIC_INFORMATION info
;
3847 IMAGE_NT_HEADERS
*nt
;
3852 if (reason
!= LDR_DLL_NOTIFICATION_REASON_LOADED
) return;
3853 TRACE( "loading %s\n", debugstr_us(data
->Loaded
.BaseDllName
));
3855 module
= data
->Loaded
.DllBase
;
3856 nt
= RtlImageNtHeader( module
);
3857 base
= (char *)nt
->OptionalHeader
.ImageBase
;
3858 if (!(delta
= (char *)module
- base
)) return;
3860 /* the loader does not apply relocations to non page-aligned binaries or executables,
3861 * we have to do it ourselves */
3863 NtQuerySystemInformation( SystemBasicInformation
, &info
, sizeof(info
), NULL
);
3864 if (nt
->OptionalHeader
.SectionAlignment
>= info
.PageSize
&& (nt
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
))
3867 if (nt
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
3869 WARN( "Need to relocate module from %p to %p, but there are no relocation records\n", base
, module
);
3873 relocs
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
3874 if (!relocs
->Size
|| !relocs
->VirtualAddress
) return;
3876 TRACE( "relocating from %p-%p to %p-%p\n", base
, base
+ nt
->OptionalHeader
.SizeOfImage
,
3877 module
, (char *)module
+ nt
->OptionalHeader
.SizeOfImage
);
3879 rel
= get_rva( module
, relocs
->VirtualAddress
);
3880 end
= get_rva( module
, relocs
->VirtualAddress
+ relocs
->Size
);
3882 while (rel
< end
- 1 && rel
->SizeOfBlock
)
3884 char *page
= get_rva( module
, rel
->VirtualAddress
);
3885 DWORD old_prot1
, old_prot2
;
3887 if (rel
->VirtualAddress
>= nt
->OptionalHeader
.SizeOfImage
)
3889 WARN( "invalid address %p in relocation %p\n", get_rva( module
, rel
->VirtualAddress
), rel
);
3893 /* Relocation entries may hang over the end of the page, so we need to
3894 * protect two pages. */
3895 VirtualProtect( page
, info
.PageSize
, PAGE_READWRITE
, &old_prot1
);
3896 VirtualProtect( page
+ info
.PageSize
, info
.PageSize
, PAGE_READWRITE
, &old_prot2
);
3897 rel
= LdrProcessRelocationBlock( page
, (rel
->SizeOfBlock
- sizeof(*rel
)) / sizeof(USHORT
),
3898 (USHORT
*)(rel
+ 1), delta
);
3899 VirtualProtect( page
, info
.PageSize
, old_prot1
, &old_prot1
);
3900 VirtualProtect( page
+ info
.PageSize
, info
.PageSize
, old_prot2
, &old_prot2
);
3903 WARN( "LdrProcessRelocationBlock failed\n" );
3909 /* load the .sys module for a device driver */
3910 static HMODULE
load_driver( const WCHAR
*driver_name
, const UNICODE_STRING
*keyname
)
3912 static const WCHAR driversW
[] = {'\\','d','r','i','v','e','r','s','\\',0};
3913 static const WCHAR systemrootW
[] = {'\\','S','y','s','t','e','m','R','o','o','t','\\',0};
3914 static const WCHAR postfixW
[] = {'.','s','y','s',0};
3915 static const WCHAR ntprefixW
[] = {'\\','?','?','\\',0};
3916 static const WCHAR ImagePathW
[] = {'I','m','a','g','e','P','a','t','h',0};
3919 LPWSTR path
= NULL
, str
;
3922 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, keyname
->Buffer
+ 18 /* skip \registry\machine */, &driver_hkey
))
3924 ERR( "cannot open key %s, err=%lu\n", wine_dbgstr_w(keyname
->Buffer
), GetLastError() );
3928 /* read the executable path from memory */
3930 if (!RegQueryValueExW( driver_hkey
, ImagePathW
, NULL
, &type
, NULL
, &size
))
3932 str
= HeapAlloc( GetProcessHeap(), 0, size
);
3933 if (!RegQueryValueExW( driver_hkey
, ImagePathW
, NULL
, &type
, (LPBYTE
)str
, &size
))
3935 size
= ExpandEnvironmentStringsW(str
,NULL
,0);
3936 path
= HeapAlloc(GetProcessHeap(),0,size
*sizeof(WCHAR
));
3937 ExpandEnvironmentStringsW(str
,path
,size
);
3939 HeapFree( GetProcessHeap(), 0, str
);
3942 RegCloseKey( driver_hkey
);
3946 if (!wcsnicmp( path
, systemrootW
, 12 ))
3948 WCHAR buffer
[MAX_PATH
];
3950 GetWindowsDirectoryW(buffer
, MAX_PATH
);
3952 str
= HeapAlloc(GetProcessHeap(), 0, (size
-11 + lstrlenW(buffer
))
3954 lstrcpyW(str
, buffer
);
3955 lstrcatW(str
, path
+ 11);
3956 HeapFree( GetProcessHeap(), 0, path
);
3959 else if (!wcsncmp( path
, ntprefixW
, 4 ))
3966 /* default is to use the driver name + ".sys" */
3967 WCHAR buffer
[MAX_PATH
];
3968 GetSystemDirectoryW(buffer
, MAX_PATH
);
3969 path
= HeapAlloc(GetProcessHeap(),0,
3970 (lstrlenW(buffer
) + lstrlenW(driversW
) + lstrlenW(driver_name
) + lstrlenW(postfixW
) + 1)
3972 lstrcpyW(path
, buffer
);
3973 lstrcatW(path
, driversW
);
3974 lstrcatW(path
, driver_name
);
3975 lstrcatW(path
, postfixW
);
3978 RegCloseKey( driver_hkey
);
3980 TRACE( "loading driver %s\n", wine_dbgstr_w(str
) );
3982 module
= LoadLibraryExW( str
, 0, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
| LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
);
3984 if (module
&& load_image_notify_routine_count
)
3986 UNICODE_STRING module_name
;
3987 IMAGE_NT_HEADERS
*nt
;
3991 RtlInitUnicodeString(&module_name
, str
);
3992 nt
= RtlImageNtHeader(module
);
3993 memset(&info
, 0, sizeof(info
));
3994 info
.ImageAddressingMode
= IMAGE_ADDRESSING_MODE_32BIT
;
3995 info
.SystemModeImage
= TRUE
;
3996 info
.ImageSize
= nt
->OptionalHeader
.SizeOfImage
;
3997 info
.ImageBase
= module
;
3999 for (i
= 0; i
< load_image_notify_routine_count
; ++i
)
4001 TRACE("Calling image load notify %p.\n", load_image_notify_routines
[i
]);
4002 load_image_notify_routines
[i
](&module_name
, NULL
, &info
);
4003 TRACE("Called image load notify %p.\n", load_image_notify_routines
[i
]);
4007 HeapFree( GetProcessHeap(), 0, path
);
4011 /* call the driver init entry point */
4012 static NTSTATUS WINAPI
init_driver( DRIVER_OBJECT
*driver_object
, UNICODE_STRING
*keyname
)
4016 const IMAGE_NT_HEADERS
*nt
;
4017 const WCHAR
*driver_name
;
4020 /* Retrieve driver name from the keyname */
4021 driver_name
= wcsrchr( keyname
->Buffer
, '\\' );
4024 module
= load_driver( driver_name
, keyname
);
4026 return STATUS_DLL_INIT_FAILED
;
4028 driver_object
->DriverSection
= find_ldr_module( module
);
4029 driver_object
->DriverStart
= ((LDR_DATA_TABLE_ENTRY
*)driver_object
->DriverSection
)->DllBase
;
4030 driver_object
->DriverSize
= ((LDR_DATA_TABLE_ENTRY
*)driver_object
->DriverSection
)->SizeOfImage
;
4032 nt
= RtlImageNtHeader( module
);
4033 if (!nt
->OptionalHeader
.AddressOfEntryPoint
) return STATUS_SUCCESS
;
4034 driver_object
->DriverInit
= (PDRIVER_INITIALIZE
)((char *)module
+ nt
->OptionalHeader
.AddressOfEntryPoint
);
4036 TRACE_(relay
)( "\1Call driver init %p (obj=%p,str=%s)\n",
4037 driver_object
->DriverInit
, driver_object
, wine_dbgstr_w(keyname
->Buffer
) );
4039 status
= driver_object
->DriverInit( driver_object
, keyname
);
4041 TRACE_(relay
)( "\1Ret driver init %p (obj=%p,str=%s) retval=%08lx\n",
4042 driver_object
->DriverInit
, driver_object
, wine_dbgstr_w(keyname
->Buffer
), status
);
4044 TRACE( "init done for %s obj %p\n", wine_dbgstr_w(driver_name
), driver_object
);
4045 TRACE( "- DriverInit = %p\n", driver_object
->DriverInit
);
4046 TRACE( "- DriverStartIo = %p\n", driver_object
->DriverStartIo
);
4047 TRACE( "- DriverUnload = %p\n", driver_object
->DriverUnload
);
4048 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
4049 TRACE( "- MajorFunction[%d] = %p\n", i
, driver_object
->MajorFunction
[i
] );
4054 static BOOLEAN
get_drv_name( UNICODE_STRING
*drv_name
, const UNICODE_STRING
*service_name
)
4056 static const WCHAR driverW
[] = {'\\','D','r','i','v','e','r','\\',0};
4059 if (!(str
= heap_alloc( sizeof(driverW
) + service_name
->Length
- lstrlenW(servicesW
)*sizeof(WCHAR
) )))
4062 lstrcpyW( str
, driverW
);
4063 lstrcpynW( str
+ lstrlenW(driverW
), service_name
->Buffer
+ lstrlenW(servicesW
),
4064 service_name
->Length
/sizeof(WCHAR
) - lstrlenW(servicesW
) + 1 );
4065 RtlInitUnicodeString( drv_name
, str
);
4069 /***********************************************************************
4070 * ZwLoadDriver (NTOSKRNL.EXE.@)
4072 NTSTATUS WINAPI
ZwLoadDriver( const UNICODE_STRING
*service_name
)
4074 SERVICE_STATUS_HANDLE service_handle
;
4075 struct wine_rb_entry
*entry
;
4076 struct wine_driver
*driver
;
4077 UNICODE_STRING drv_name
;
4080 TRACE( "(%s)\n", debugstr_us(service_name
) );
4082 if ((status
= open_driver( service_name
, (SC_HANDLE
*)&service_handle
)) != STATUS_SUCCESS
)
4085 if (!get_drv_name( &drv_name
, service_name
))
4087 CloseServiceHandle( (void *)service_handle
);
4088 return STATUS_NO_MEMORY
;
4091 if (wine_rb_get( &wine_drivers
, &drv_name
))
4093 TRACE( "driver %s already loaded\n", debugstr_us(&drv_name
) );
4094 RtlFreeUnicodeString( &drv_name
);
4095 CloseServiceHandle( (void *)service_handle
);
4096 return STATUS_IMAGE_ALREADY_LOADED
;
4099 set_service_status( service_handle
, SERVICE_START_PENDING
, 0 );
4101 status
= IoCreateDriver( &drv_name
, init_driver
);
4102 entry
= wine_rb_get( &wine_drivers
, &drv_name
);
4103 RtlFreeUnicodeString( &drv_name
);
4104 if (status
!= STATUS_SUCCESS
)
4106 ERR( "failed to create driver %s: %08lx\n", debugstr_us(service_name
), status
);
4110 driver
= WINE_RB_ENTRY_VALUE( entry
, struct wine_driver
, entry
);
4111 driver
->service_handle
= service_handle
;
4113 wine_enumerate_root_devices( service_name
->Buffer
+ wcslen( servicesW
) );
4115 set_service_status( service_handle
, SERVICE_RUNNING
,
4116 SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
4117 return STATUS_SUCCESS
;
4120 set_service_status( service_handle
, SERVICE_STOPPED
, 0 );
4121 CloseServiceHandle( (void *)service_handle
);
4125 /***********************************************************************
4126 * ZwUnloadDriver (NTOSKRNL.EXE.@)
4128 NTSTATUS WINAPI
ZwUnloadDriver( const UNICODE_STRING
*service_name
)
4130 struct wine_rb_entry
*entry
;
4131 struct wine_driver
*driver
;
4132 UNICODE_STRING drv_name
;
4134 TRACE( "(%s)\n", debugstr_us(service_name
) );
4136 if (!get_drv_name( &drv_name
, service_name
))
4137 return STATUS_NO_MEMORY
;
4139 entry
= wine_rb_get( &wine_drivers
, &drv_name
);
4140 RtlFreeUnicodeString( &drv_name
);
4143 ERR( "failed to locate driver %s\n", debugstr_us(service_name
) );
4144 return STATUS_OBJECT_NAME_NOT_FOUND
;
4146 driver
= WINE_RB_ENTRY_VALUE( entry
, struct wine_driver
, entry
);
4148 if (!list_empty( &driver
->root_pnp_devices
))
4150 ERR( "cannot unload driver %s which still has running PnP devices\n", debugstr_us(service_name
) );
4151 return STATUS_UNSUCCESSFUL
;
4154 unload_driver( entry
, NULL
);
4156 return STATUS_SUCCESS
;
4159 /***********************************************************************
4160 * IoCreateFileEx (NTOSKRNL.EXE.@)
4162 NTSTATUS WINAPI
IoCreateFileEx(HANDLE
*handle
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
,
4163 IO_STATUS_BLOCK
*io
, LARGE_INTEGER
*alloc_size
, ULONG attributes
, ULONG sharing
,
4164 ULONG disposition
, ULONG create_options
, VOID
*ea_buffer
, ULONG ea_length
,
4165 CREATE_FILE_TYPE file_type
, VOID
*parameters
, ULONG options
, void *driverctx
)
4167 FIXME(": semi-stub\n");
4168 return NtCreateFile(handle
, access
, attr
, io
, alloc_size
, attributes
, sharing
, disposition
,
4169 create_options
, ea_buffer
, ea_length
);
4172 /***********************************************************************
4173 * IoCreateFile (NTOSKRNL.EXE.@)
4175 NTSTATUS WINAPI
IoCreateFile(HANDLE
*handle
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
,
4176 IO_STATUS_BLOCK
*io
, LARGE_INTEGER
*alloc_size
, ULONG attributes
, ULONG sharing
,
4177 ULONG disposition
, ULONG create_options
, VOID
*ea_buffer
, ULONG ea_length
,
4178 CREATE_FILE_TYPE file_type
, VOID
*parameters
, ULONG options
)
4180 FIXME(": semi-stub\n");
4181 return IoCreateFileEx(handle
, access
, attr
, io
, alloc_size
, attributes
, sharing
, disposition
,
4182 create_options
, ea_buffer
, ea_length
, file_type
, parameters
, options
, NULL
);
4185 /**************************************************************************
4186 * __chkstk (NTOSKRNL.@)
4189 /* Supposed to touch all the stack pages, but we shouldn't need that. */
4190 __ASM_GLOBAL_FUNC( __chkstk
, "ret" );
4191 #elif defined(__i386__)
4192 __ASM_GLOBAL_FUNC( _chkstk
,
4194 "addl %esp,%eax\n\t"
4195 "xchgl %esp,%eax\n\t"
4196 "movl 0(%eax),%eax\n\t" /* copy return address from old location */
4197 "movl %eax,0(%esp)\n\t"
4199 #elif defined(__arm__)
4200 /* Incoming r4 contains words to allocate, converting to bytes then return */
4201 __ASM_GLOBAL_FUNC( __chkstk
, "lsl r4, r4, #2\n\t"
4203 #elif defined(__aarch64__)
4204 /* Supposed to touch all the stack pages, but we shouldn't need that. */
4205 __ASM_GLOBAL_FUNC( __chkstk
, "ret" );
4208 /*********************************************************************
4209 * PsAcquireProcessExitSynchronization (NTOSKRNL.@)
4211 NTSTATUS WINAPI
PsAcquireProcessExitSynchronization(PEPROCESS process
)
4213 FIXME("stub: %p\n", process
);
4215 return STATUS_NOT_IMPLEMENTED
;
4218 /*********************************************************************
4219 * PsReleaseProcessExitSynchronization (NTOSKRNL.@)
4221 void WINAPI
PsReleaseProcessExitSynchronization(PEPROCESS process
)
4223 FIXME("stub: %p\n", process
);
4226 typedef struct _EX_PUSH_LOCK_WAIT_BLOCK
*PEX_PUSH_LOCK_WAIT_BLOCK
;
4227 /*********************************************************************
4228 * ExfUnblockPushLock (NTOSKRNL.@)
4230 DEFINE_FASTCALL_WRAPPER( ExfUnblockPushLock
, 8 )
4231 void FASTCALL
ExfUnblockPushLock( EX_PUSH_LOCK
*lock
, PEX_PUSH_LOCK_WAIT_BLOCK block
)
4233 FIXME( "stub: %p, %p\n", lock
, block
);
4236 /*********************************************************************
4237 * FsRtlRegisterFileSystemFilterCallbacks (NTOSKRNL.@)
4239 NTSTATUS WINAPI
FsRtlRegisterFileSystemFilterCallbacks( DRIVER_OBJECT
*object
, PFS_FILTER_CALLBACKS callbacks
)
4241 FIXME("stub: %p %p\n", object
, callbacks
);
4242 return STATUS_NOT_IMPLEMENTED
;
4245 /*********************************************************************
4246 * SeSinglePrivilegeCheck (NTOSKRNL.@)
4248 BOOLEAN WINAPI
SeSinglePrivilegeCheck(LUID privilege
, KPROCESSOR_MODE mode
)
4251 if (!once
++) FIXME("stub: %08lx%08lx %u\n", privilege
.HighPart
, privilege
.LowPart
, mode
);
4255 /*********************************************************************
4256 * SePrivilegeCheck (NTOSKRNL.@)
4258 BOOLEAN WINAPI
SePrivilegeCheck(PRIVILEGE_SET
*privileges
, SECURITY_SUBJECT_CONTEXT
*context
, KPROCESSOR_MODE mode
)
4260 FIXME("stub: %p %p %u\n", privileges
, context
, mode
);
4264 /*********************************************************************
4265 * SeLocateProcessImageName (NTOSKRNL.@)
4267 NTSTATUS WINAPI
SeLocateProcessImageName(PEPROCESS process
, UNICODE_STRING
**image_name
)
4269 FIXME("stub: %p %p\n", process
, image_name
);
4270 if (image_name
) *image_name
= NULL
;
4271 return STATUS_NOT_IMPLEMENTED
;
4274 /*********************************************************************
4275 * KeFlushQueuedDpcs (NTOSKRNL.@)
4277 void WINAPI
KeFlushQueuedDpcs(void)
4282 /*********************************************************************
4283 * DbgQueryDebugFilterState (NTOSKRNL.@)
4285 NTSTATUS WINAPI
DbgQueryDebugFilterState(ULONG component
, ULONG level
)
4287 FIXME("stub: %ld %ld\n", component
, level
);
4288 return STATUS_NOT_IMPLEMENTED
;
4291 /*********************************************************************
4292 * PsGetProcessWow64Process (NTOSKRNL.@)
4294 PVOID WINAPI
PsGetProcessWow64Process(PEPROCESS process
)
4296 FIXME("stub: %p\n", process
);
4300 /*********************************************************************
4301 * MmCopyVirtualMemory (NTOSKRNL.@)
4303 NTSTATUS WINAPI
MmCopyVirtualMemory(PEPROCESS fromprocess
, void *fromaddress
, PEPROCESS toprocess
,
4304 void *toaddress
, SIZE_T bufsize
, KPROCESSOR_MODE mode
,
4307 FIXME("fromprocess %p, fromaddress %p, toprocess %p, toaddress %p, bufsize %Iu, mode %d, copied %p stub.\n",
4308 fromprocess
, fromaddress
, toprocess
, toaddress
, bufsize
, mode
, copied
);
4311 return STATUS_NOT_IMPLEMENTED
;
4314 /*********************************************************************
4315 * KeEnterGuardedRegion (NTOSKRNL.@)
4317 void WINAPI
KeEnterGuardedRegion(void)
4322 /*********************************************************************
4323 * KeLeaveGuardedRegion (NTOSKRNL.@)
4325 void WINAPI
KeLeaveGuardedRegion(void)
4330 static const WCHAR token_type_name
[] = {'T','o','k','e','n',0};
4332 static struct _OBJECT_TYPE token_type
=
4337 POBJECT_TYPE SeTokenObjectType
= &token_type
;
4339 /*************************************************************************
4340 * ExUuidCreate (NTOSKRNL.@)
4342 * Creates a 128bit UUID.
4346 * STATUS_SUCCESS if successful.
4347 * RPC_NT_UUID_LOCAL_ONLY if UUID is only locally unique.
4351 * Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
4352 * Truly Random or Pseudo-Random Numbers)
4354 NTSTATUS WINAPI
ExUuidCreate(UUID
*uuid
)
4356 RtlGenRandom(uuid
, sizeof(*uuid
));
4357 /* Clear the version bits and set the version (4) */
4358 uuid
->Data3
&= 0x0fff;
4359 uuid
->Data3
|= (4 << 12);
4360 /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
4361 * specified in RFC 4122, section 4.4.
4363 uuid
->Data4
[0] &= 0x3f;
4364 uuid
->Data4
[0] |= 0x80;
4366 TRACE("%s\n", debugstr_guid(uuid
));
4368 return STATUS_SUCCESS
;
4371 /***********************************************************************
4372 * ExSetTimerResolution (NTOSKRNL.EXE.@)
4374 ULONG WINAPI
ExSetTimerResolution(ULONG time
, BOOLEAN set_resolution
)
4376 FIXME("stub: %lu %d\n", time
, set_resolution
);
4377 return KeQueryTimeIncrement();
4380 /***********************************************************************
4381 * IoGetRequestorProcess (NTOSKRNL.EXE.@)
4383 PEPROCESS WINAPI
IoGetRequestorProcess(IRP
*irp
)
4385 TRACE("irp %p.\n", irp
);
4386 return irp
->Tail
.Overlay
.Thread
->kthread
.process
;
4390 /***********************************************************************
4391 * IoIs32bitProcess (NTOSKRNL.EXE.@)
4393 BOOLEAN WINAPI
IoIs32bitProcess(IRP
*irp
)
4395 TRACE("irp %p.\n", irp
);
4396 return irp
->Tail
.Overlay
.Thread
->kthread
.process
->wow64
;
4400 /***********************************************************************
4401 * RtlIsNtDdiVersionAvailable (NTOSKRNL.EXE.@)
4403 BOOLEAN WINAPI
RtlIsNtDdiVersionAvailable(ULONG version
)
4405 FIXME("stub: %ld\n", version
);
4409 BOOLEAN WINAPI
KdRefreshDebuggerNotPresent(void)
4413 return !KdDebuggerEnabled
;
4416 struct generic_call_dpc_context
4418 DEFERRED_REVERSE_BARRIER
*reverse_barrier
;
4419 PKDEFERRED_ROUTINE routine
;
4420 ULONG
*cpu_count_barrier
;
4423 ULONG current_barrier_flag
;
4424 LONG
*barrier_passed_count
;
4427 static void WINAPI
generic_call_dpc_callback(TP_CALLBACK_INSTANCE
*instance
, void *context
)
4429 struct generic_call_dpc_context
*c
= context
;
4430 GROUP_AFFINITY old
, new;
4432 TRACE("instance %p, context %p.\n", instance
, context
);
4434 NtQueryInformationThread(GetCurrentThread(), ThreadGroupInformation
,
4435 &old
, sizeof(old
), NULL
);
4437 memset(&new, 0, sizeof(new));
4439 new.Mask
= 1 << c
->cpu_index
;
4440 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &new, sizeof(new));
4442 TlsSetValue(dpc_call_tls_index
, context
);
4443 c
->routine((PKDPC
)0xdeadbeef, c
->context
, c
->cpu_count_barrier
, c
->reverse_barrier
);
4444 TlsSetValue(dpc_call_tls_index
, NULL
);
4445 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &old
, sizeof(old
));
4448 void WINAPI
KeGenericCallDpc(PKDEFERRED_ROUTINE routine
, void *context
)
4450 ULONG cpu_count
= KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS
);
4451 static struct generic_call_dpc_context
*contexts
;
4452 DEFERRED_REVERSE_BARRIER reverse_barrier
;
4453 static ULONG last_cpu_count
;
4454 LONG barrier_passed_count
;
4455 ULONG cpu_count_barrier
;
4458 TRACE("routine %p, context %p.\n", routine
, context
);
4460 EnterCriticalSection(&dpc_call_cs
);
4464 if (!(dpc_call_tp
= CreateThreadpool(NULL
)))
4466 ERR("Could not create thread pool.\n");
4467 LeaveCriticalSection(&dpc_call_cs
);
4471 SetThreadpoolThreadMinimum(dpc_call_tp
, cpu_count
);
4472 SetThreadpoolThreadMaximum(dpc_call_tp
, cpu_count
);
4474 memset(&dpc_call_tpe
, 0, sizeof(dpc_call_tpe
));
4475 dpc_call_tpe
.Version
= 1;
4476 dpc_call_tpe
.Pool
= dpc_call_tp
;
4479 reverse_barrier
.Barrier
= cpu_count
;
4480 reverse_barrier
.TotalProcessors
= cpu_count
;
4481 cpu_count_barrier
= cpu_count
;
4485 if (last_cpu_count
< cpu_count
)
4487 static struct generic_call_dpc_context
*new_contexts
;
4488 if (!(new_contexts
= heap_realloc(contexts
, sizeof(*contexts
) * cpu_count
)))
4490 ERR("No memory.\n");
4491 LeaveCriticalSection(&dpc_call_cs
);
4494 contexts
= new_contexts
;
4495 SetThreadpoolThreadMinimum(dpc_call_tp
, cpu_count
);
4496 SetThreadpoolThreadMaximum(dpc_call_tp
, cpu_count
);
4499 else if (!(contexts
= heap_alloc(sizeof(*contexts
) * cpu_count
)))
4501 ERR("No memory.\n");
4502 LeaveCriticalSection(&dpc_call_cs
);
4506 memset(contexts
, 0, sizeof(*contexts
) * cpu_count
);
4507 last_cpu_count
= cpu_count
;
4508 barrier_passed_count
= 0;
4510 for (i
= 0; i
< cpu_count
; ++i
)
4512 contexts
[i
].reverse_barrier
= &reverse_barrier
;
4513 contexts
[i
].cpu_count_barrier
= &cpu_count_barrier
;
4514 contexts
[i
].routine
= routine
;
4515 contexts
[i
].context
= context
;
4516 contexts
[i
].cpu_index
= i
;
4517 contexts
[i
].barrier_passed_count
= &barrier_passed_count
;
4519 TrySubmitThreadpoolCallback(generic_call_dpc_callback
, &contexts
[i
], &dpc_call_tpe
);
4522 while (InterlockedCompareExchange((LONG
*)&cpu_count_barrier
, 0, 0))
4525 LeaveCriticalSection(&dpc_call_cs
);
4529 BOOLEAN WINAPI
KeSignalCallDpcSynchronize(void *barrier
)
4531 struct generic_call_dpc_context
*context
= TlsGetValue(dpc_call_tls_index
);
4532 DEFERRED_REVERSE_BARRIER
*b
= barrier
;
4533 LONG curr_flag
, comp
, done_value
;
4536 TRACE("barrier %p, context %p.\n", barrier
, context
);
4540 WARN("Called outside of DPC context.\n");
4544 context
->current_barrier_flag
^= 0x80000000;
4545 curr_flag
= context
->current_barrier_flag
;
4547 first
= !context
->cpu_index
;
4548 comp
= curr_flag
+ context
->cpu_index
;
4549 done_value
= curr_flag
+ b
->TotalProcessors
;
4552 InterlockedExchange((LONG
*)&b
->Barrier
, comp
);
4554 while (InterlockedCompareExchange((LONG
*)&b
->Barrier
, comp
+ 1, comp
) != done_value
)
4557 InterlockedIncrement(context
->barrier_passed_count
);
4559 while (first
&& InterlockedCompareExchange(context
->barrier_passed_count
, 0, b
->TotalProcessors
))
4565 void WINAPI
KeSignalCallDpcDone(void *barrier
)
4567 InterlockedDecrement((LONG
*)barrier
);
4570 void * WINAPI
PsGetProcessSectionBaseAddress(PEPROCESS process
)
4577 TRACE("process %p.\n", process
);
4579 if ((status
= ObOpenObjectByPointer(process
, 0, NULL
, PROCESS_ALL_ACCESS
, NULL
, KernelMode
, &h
)))
4581 WARN("Error opening process object, status %#lx.\n", status
);
4585 status
= NtReadVirtualMemory(h
, &process
->info
.PebBaseAddress
->ImageBaseAddress
,
4586 &image_base
, sizeof(image_base
), &size
);
4590 if (status
|| size
!= sizeof(image_base
))
4592 WARN("Error reading process memory, status %#lx, size %Iu.\n", status
, size
);
4596 TRACE("returning %p.\n", image_base
);
4600 void WINAPI
KeStackAttachProcess(KPROCESS
*process
, KAPC_STATE
*apc_state
)
4602 FIXME("process %p, apc_state %p stub.\n", process
, apc_state
);
4605 void WINAPI
KeUnstackDetachProcess(KAPC_STATE
*apc_state
)
4607 FIXME("apc_state %p stub.\n", apc_state
);
4610 NTSTATUS WINAPI
KdDisableDebugger(void)
4613 return STATUS_DEBUGGER_INACTIVE
;
4616 NTSTATUS WINAPI
KdEnableDebugger(void)
4619 return STATUS_DEBUGGER_INACTIVE
;
4622 KPROCESSOR_MODE WINAPI
ExGetPreviousMode(void)
4625 return PsIsSystemThread((PETHREAD
)KeGetCurrentThread()) ? KernelMode
: UserMode
;
4630 void WINAPI
KfRaiseIrql(KIRQL
new, KIRQL
*old
)
4632 FIXME("new %u old %p: stub.\n", new, old
);
4635 void WINAPI
KeLowerIrql(KIRQL
new)
4637 FIXME("new %u: stub.\n", new);
4642 typedef void (WINAPI
*PETW_CLASSIC_CALLBACK
)(
4643 const GUID
*guid
, UCHAR control_code
, void *enable_context
, void *callback_context
);
4645 NTSTATUS WINAPI
EtwRegisterClassicProvider(const GUID
*provider
, ULONG type
, PETW_CLASSIC_CALLBACK callback
,
4646 void *context
, REGHANDLE
*handle
)
4648 FIXME("provider %s, type %lu, enable_callback %p, context %p, handle %p\n", debugstr_guid(provider
), type
,
4649 callback
, context
, handle
);
4651 *handle
= 0xdeadbeef;
4652 return STATUS_SUCCESS
;
4655 NTSTATUS WINAPI
EtwUnregister(REGHANDLE handle
)
4657 FIXME("handle %I64x\n", handle
);
4658 return STATUS_SUCCESS
;
4661 /*****************************************************
4664 BOOL WINAPI
DllMain( HINSTANCE inst
, DWORD reason
, LPVOID reserved
)
4666 static void *handler
;
4667 LARGE_INTEGER count
;
4671 case DLL_PROCESS_ATTACH
:
4672 DisableThreadLibraryCalls( inst
);
4673 #if defined(__i386__) || defined(__x86_64__)
4674 handler
= RtlAddVectoredExceptionHandler( TRUE
, vectored_handler
);
4676 KeQueryTickCount( &count
); /* initialize the global KeTickCount */
4677 NtBuildNumber
= NtCurrentTeb()->Peb
->OSBuildNumber
;
4678 ntoskrnl_heap
= HeapCreate( HEAP_CREATE_ENABLE_EXECUTE
, 0, 0 );
4679 dpc_call_tls_index
= TlsAlloc();
4680 LdrRegisterDllNotification( 0, ldr_notify_callback
, NULL
, &ldr_notify_cookie
);
4682 case DLL_PROCESS_DETACH
:
4683 LdrUnregisterDllNotification( ldr_notify_cookie
);
4685 if (reserved
) break;
4688 CloseThreadpool(dpc_call_tp
);
4690 HeapDestroy( ntoskrnl_heap
);
4691 RtlRemoveVectoredExceptionHandler( handler
);