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
, 0, &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 * ExAllocatePool (NTOSKRNL.EXE.@)
2218 PVOID WINAPI
ExAllocatePool( POOL_TYPE type
, SIZE_T size
)
2220 return ExAllocatePoolWithTag( type
, size
, 0 );
2224 /***********************************************************************
2225 * ExAllocatePoolWithQuota (NTOSKRNL.EXE.@)
2227 PVOID WINAPI
ExAllocatePoolWithQuota( POOL_TYPE type
, SIZE_T size
)
2229 return ExAllocatePoolWithTag( type
, size
, 0 );
2233 /***********************************************************************
2234 * ExAllocatePoolWithTag (NTOSKRNL.EXE.@)
2236 PVOID WINAPI
ExAllocatePoolWithTag( POOL_TYPE type
, SIZE_T size
, ULONG tag
)
2238 /* FIXME: handle page alignment constraints */
2239 void *ret
= HeapAlloc( ntoskrnl_heap
, 0, size
);
2240 TRACE( "%Iu pool %u -> %p\n", size
, type
, ret
);
2245 /***********************************************************************
2246 * ExAllocatePoolWithQuotaTag (NTOSKRNL.EXE.@)
2248 PVOID WINAPI
ExAllocatePoolWithQuotaTag( POOL_TYPE type
, SIZE_T size
, ULONG tag
)
2250 return ExAllocatePoolWithTag( type
, size
, tag
);
2254 /***********************************************************************
2255 * ExCreateCallback (NTOSKRNL.EXE.@)
2257 NTSTATUS WINAPI
ExCreateCallback(PCALLBACK_OBJECT
*obj
, POBJECT_ATTRIBUTES attr
,
2258 BOOLEAN create
, BOOLEAN allow_multiple
)
2260 FIXME("(%p, %p, %u, %u): stub\n", obj
, attr
, create
, allow_multiple
);
2262 return STATUS_SUCCESS
;
2265 void * WINAPI
ExRegisterCallback(PCALLBACK_OBJECT callback_object
,
2266 PCALLBACK_FUNCTION callback_function
, void *callback_context
)
2268 FIXME("callback_object %p, callback_function %p, callback_context %p stub.\n",
2269 callback_object
, callback_function
, callback_context
);
2271 return (void *)0xdeadbeef;
2274 void WINAPI
ExUnregisterCallback(void *callback_registration
)
2276 FIXME("callback_registration %p stub.\n", callback_registration
);
2279 /***********************************************************************
2280 * ExNotifyCallback (NTOSKRNL.EXE.@)
2282 void WINAPI
ExNotifyCallback(void *obj
, void *arg1
, void *arg2
)
2284 FIXME("(%p, %p, %p): stub\n", obj
, arg1
, arg2
);
2287 /***********************************************************************
2288 * ExFreePool (NTOSKRNL.EXE.@)
2290 void WINAPI
ExFreePool( void *ptr
)
2292 ExFreePoolWithTag( ptr
, 0 );
2296 /***********************************************************************
2297 * ExFreePoolWithTag (NTOSKRNL.EXE.@)
2299 void WINAPI
ExFreePoolWithTag( void *ptr
, ULONG tag
)
2301 TRACE( "%p\n", ptr
);
2302 HeapFree( ntoskrnl_heap
, 0, ptr
);
2305 static void initialize_lookaside_list( GENERAL_LOOKASIDE
*lookaside
, PALLOCATE_FUNCTION allocate
, PFREE_FUNCTION free
,
2306 ULONG type
, SIZE_T size
, ULONG tag
)
2309 RtlInitializeSListHead( &lookaside
->ListHead
);
2310 lookaside
->Depth
= 4;
2311 lookaside
->MaximumDepth
= 256;
2312 lookaside
->TotalAllocates
= 0;
2313 lookaside
->AllocateMisses
= 0;
2314 lookaside
->TotalFrees
= 0;
2315 lookaside
->FreeMisses
= 0;
2316 lookaside
->Type
= type
;
2317 lookaside
->Tag
= tag
;
2318 lookaside
->Size
= size
;
2319 lookaside
->Allocate
= allocate
? allocate
: ExAllocatePoolWithTag
;
2320 lookaside
->Free
= free
? free
: ExFreePool
;
2321 lookaside
->LastTotalAllocates
= 0;
2322 lookaside
->LastAllocateMisses
= 0;
2324 /* FIXME: insert in global list of lookadside lists */
2327 /***********************************************************************
2328 * ExInitializeNPagedLookasideList (NTOSKRNL.EXE.@)
2330 void WINAPI
ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST lookaside
,
2331 PALLOCATE_FUNCTION allocate
,
2332 PFREE_FUNCTION free
,
2338 TRACE( "%p, %p, %p, %lu, %Iu, %lu, %u\n", lookaside
, allocate
, free
, flags
, size
, tag
, depth
);
2339 initialize_lookaside_list( &lookaside
->L
, allocate
, free
, NonPagedPool
| flags
, size
, tag
);
2342 /***********************************************************************
2343 * ExInitializePagedLookasideList (NTOSKRNL.EXE.@)
2345 void WINAPI
ExInitializePagedLookasideList(PPAGED_LOOKASIDE_LIST lookaside
,
2346 PALLOCATE_FUNCTION allocate
,
2347 PFREE_FUNCTION free
,
2353 TRACE( "%p, %p, %p, %lu, %Iu, %lu, %u\n", lookaside
, allocate
, free
, flags
, size
, tag
, depth
);
2354 initialize_lookaside_list( &lookaside
->L
, allocate
, free
, PagedPool
| flags
, size
, tag
);
2357 static void delete_lookaside_list( GENERAL_LOOKASIDE
*lookaside
)
2360 while ((entry
= RtlInterlockedPopEntrySList(&lookaside
->ListHead
)))
2361 lookaside
->FreeEx(entry
, (LOOKASIDE_LIST_EX
*)lookaside
);
2364 /***********************************************************************
2365 * ExDeleteNPagedLookasideList (NTOSKRNL.EXE.@)
2367 void WINAPI
ExDeleteNPagedLookasideList( PNPAGED_LOOKASIDE_LIST lookaside
)
2369 TRACE( "%p\n", lookaside
);
2370 delete_lookaside_list( &lookaside
->L
);
2374 /***********************************************************************
2375 * ExDeletePagedLookasideList (NTOSKRNL.EXE.@)
2377 void WINAPI
ExDeletePagedLookasideList( PPAGED_LOOKASIDE_LIST lookaside
)
2379 TRACE( "%p\n", lookaside
);
2380 delete_lookaside_list( &lookaside
->L
);
2383 /***********************************************************************
2384 * ExInitializeZone (NTOSKRNL.EXE.@)
2386 NTSTATUS WINAPI
ExInitializeZone(PZONE_HEADER Zone
,
2388 PVOID InitialSegment
,
2389 ULONG InitialSegmentSize
)
2391 FIXME( "stub: %p, %lu, %p, %lu\n", Zone
, BlockSize
, InitialSegment
, InitialSegmentSize
);
2392 return STATUS_NOT_IMPLEMENTED
;
2395 /***********************************************************************
2396 * FsRtlIsNameInExpression (NTOSKRNL.EXE.@)
2398 BOOLEAN WINAPI
FsRtlIsNameInExpression(PUNICODE_STRING expression
, PUNICODE_STRING name
,
2399 BOOLEAN ignore
, PWCH upcase
)
2401 FIXME("stub: %p %p %d %p\n", expression
, name
, ignore
, upcase
);
2405 /***********************************************************************
2406 * FsRtlRegisterUncProvider (NTOSKRNL.EXE.@)
2408 NTSTATUS WINAPI
FsRtlRegisterUncProvider(PHANDLE MupHandle
, PUNICODE_STRING RedirDevName
,
2409 BOOLEAN MailslotsSupported
)
2411 FIXME("(%p %p %d): stub\n", MupHandle
, RedirDevName
, MailslotsSupported
);
2412 return STATUS_NOT_IMPLEMENTED
;
2416 static void *create_process_object( HANDLE handle
)
2420 if (!(process
= alloc_kernel_object( PsProcessType
, handle
, sizeof(*process
), 0 ))) return NULL
;
2422 process
->header
.Type
= 3;
2423 process
->header
.WaitListHead
.Blink
= INVALID_HANDLE_VALUE
; /* mark as kernel object */
2424 NtQueryInformationProcess( handle
, ProcessBasicInformation
, &process
->info
, sizeof(process
->info
), NULL
);
2425 IsWow64Process( handle
, &process
->wow64
);
2429 static const WCHAR process_type_name
[] = {'P','r','o','c','e','s','s',0};
2431 static struct _OBJECT_TYPE process_type
=
2434 create_process_object
2437 POBJECT_TYPE PsProcessType
= &process_type
;
2440 /***********************************************************************
2441 * IoGetCurrentProcess / PsGetCurrentProcess (NTOSKRNL.EXE.@)
2443 PEPROCESS WINAPI
IoGetCurrentProcess(void)
2445 return KeGetCurrentThread()->process
;
2448 /***********************************************************************
2449 * PsLookupProcessByProcessId (NTOSKRNL.EXE.@)
2451 NTSTATUS WINAPI
PsLookupProcessByProcessId( HANDLE processid
, PEPROCESS
*process
)
2456 TRACE( "(%p %p)\n", processid
, process
);
2458 if (!(handle
= OpenProcess( PROCESS_ALL_ACCESS
, FALSE
, HandleToUlong(processid
) )))
2459 return STATUS_INVALID_PARAMETER
;
2461 status
= ObReferenceObjectByHandle( handle
, PROCESS_ALL_ACCESS
, PsProcessType
, KernelMode
, (void**)process
, NULL
);
2467 /*********************************************************************
2468 * PsGetProcessId (NTOSKRNL.@)
2470 HANDLE WINAPI
PsGetProcessId(PEPROCESS process
)
2472 TRACE( "%p -> %Ix\n", process
, process
->info
.UniqueProcessId
);
2473 return (HANDLE
)process
->info
.UniqueProcessId
;
2476 /*********************************************************************
2477 * PsGetProcessInheritedFromUniqueProcessId (NTOSKRNL.@)
2479 HANDLE WINAPI
PsGetProcessInheritedFromUniqueProcessId( PEPROCESS process
)
2481 HANDLE id
= (HANDLE
)process
->info
.InheritedFromUniqueProcessId
;
2482 TRACE( "%p -> %p\n", process
, id
);
2486 static void *create_thread_object( HANDLE handle
)
2488 THREAD_BASIC_INFORMATION info
;
2489 struct _KTHREAD
*thread
;
2492 if (!(thread
= alloc_kernel_object( PsThreadType
, handle
, sizeof(*thread
), 0 ))) return NULL
;
2494 thread
->header
.Type
= 6;
2495 thread
->header
.WaitListHead
.Blink
= INVALID_HANDLE_VALUE
; /* mark as kernel object */
2496 thread
->user_affinity
= 0;
2498 if (!NtQueryInformationThread( handle
, ThreadBasicInformation
, &info
, sizeof(info
), NULL
))
2500 thread
->id
= info
.ClientId
;
2501 if ((process
= OpenProcess( PROCESS_QUERY_INFORMATION
, FALSE
, HandleToUlong(thread
->id
.UniqueProcess
) )))
2503 kernel_object_from_handle( process
, PsProcessType
, (void**)&thread
->process
);
2512 static const WCHAR thread_type_name
[] = {'T','h','r','e','a','d',0};
2514 static struct _OBJECT_TYPE thread_type
=
2517 create_thread_object
2520 POBJECT_TYPE PsThreadType
= &thread_type
;
2523 /***********************************************************************
2524 * KeGetCurrentThread / PsGetCurrentThread (NTOSKRNL.EXE.@)
2526 PRKTHREAD WINAPI
KeGetCurrentThread(void)
2528 struct _KTHREAD
*thread
= NtCurrentTeb()->Instrumentation
[1];
2532 HANDLE handle
= GetCurrentThread();
2534 /* FIXME: we shouldn't need it, GetCurrentThread() should be client thread already */
2535 if (GetCurrentThreadId() == request_thread
)
2536 handle
= OpenThread( THREAD_QUERY_INFORMATION
, FALSE
, client_tid
);
2538 kernel_object_from_handle( handle
, PsThreadType
, (void**)&thread
);
2539 if (handle
!= GetCurrentThread()) NtClose( handle
);
2541 NtCurrentTeb()->Instrumentation
[1] = thread
;
2547 /*****************************************************
2548 * PsLookupThreadByThreadId (NTOSKRNL.EXE.@)
2550 NTSTATUS WINAPI
PsLookupThreadByThreadId( HANDLE threadid
, PETHREAD
*thread
)
2552 OBJECT_ATTRIBUTES attr
;
2557 TRACE( "(%p %p)\n", threadid
, thread
);
2559 cid
.UniqueProcess
= 0;
2560 cid
.UniqueThread
= threadid
;
2561 InitializeObjectAttributes( &attr
, NULL
, 0, NULL
, NULL
);
2562 status
= NtOpenThread( &handle
, THREAD_QUERY_INFORMATION
, &attr
, &cid
);
2563 if (status
) return status
;
2565 status
= ObReferenceObjectByHandle( handle
, THREAD_ALL_ACCESS
, PsThreadType
, KernelMode
, (void**)thread
, NULL
);
2571 /*********************************************************************
2572 * PsGetThreadId (NTOSKRNL.@)
2574 HANDLE WINAPI
PsGetThreadId(PETHREAD thread
)
2576 TRACE( "%p -> %p\n", thread
, thread
->kthread
.id
.UniqueThread
);
2577 return thread
->kthread
.id
.UniqueThread
;
2580 /*********************************************************************
2581 * PsGetThreadProcessId (NTOSKRNL.@)
2583 HANDLE WINAPI
PsGetThreadProcessId( PETHREAD thread
)
2585 TRACE( "%p -> %p\n", thread
, thread
->kthread
.id
.UniqueProcess
);
2586 return thread
->kthread
.id
.UniqueProcess
;
2589 /***********************************************************************
2590 * KeInsertQueue (NTOSKRNL.EXE.@)
2592 LONG WINAPI
KeInsertQueue(PRKQUEUE Queue
, PLIST_ENTRY Entry
)
2594 FIXME( "stub: %p %p\n", Queue
, Entry
);
2598 /***********************************************************************
2599 * KeInsertQueueDpc (NTOSKRNL.EXE.@)
2601 BOOLEAN WINAPI
KeInsertQueueDpc(PRKDPC Dpc
, PVOID SystemArgument1
, PVOID SystemArgument2
)
2603 FIXME( "stub: (%p %p %p)\n", Dpc
, SystemArgument1
, SystemArgument2
);
2607 /**********************************************************************
2608 * KeQueryActiveProcessors (NTOSKRNL.EXE.@)
2610 * Return the active Processors as bitmask
2613 * active Processors as bitmask
2616 KAFFINITY WINAPI
KeQueryActiveProcessors( void )
2618 DWORD_PTR affinity_mask
;
2620 GetProcessAffinityMask( GetCurrentProcess(), NULL
, &affinity_mask
);
2621 return affinity_mask
;
2624 ULONG WINAPI
KeQueryActiveProcessorCountEx(USHORT group_number
)
2626 TRACE("group_number %u.\n", group_number
);
2628 return GetActiveProcessorCount(group_number
);
2631 ULONG WINAPI
KeQueryActiveProcessorCount(PKAFFINITY active_processors
)
2633 TRACE("active_processors %p.\n", active_processors
);
2635 if(active_processors
)
2636 *active_processors
= KeQueryActiveProcessors();
2638 return KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS
);
2641 /**********************************************************************
2642 * KeQueryInterruptTime (NTOSKRNL.EXE.@)
2644 * Return the interrupt time count
2647 ULONGLONG WINAPI
KeQueryInterruptTime( void )
2649 LARGE_INTEGER totaltime
;
2651 KeQueryTickCount(&totaltime
);
2652 return totaltime
.QuadPart
;
2655 /***********************************************************************
2656 * KeQueryPriorityThread (NTOSKRNL.EXE.@)
2658 KPRIORITY WINAPI
KeQueryPriorityThread( PKTHREAD Thread
)
2660 FIXME("(%p): stub.\n", Thread
);
2661 /* priority must be a value between 0 and 31 */
2665 /***********************************************************************
2666 * KeQuerySystemTime (NTOSKRNL.EXE.@)
2668 void WINAPI
KeQuerySystemTime( LARGE_INTEGER
*time
)
2670 NtQuerySystemTime( time
);
2674 /***********************************************************************
2675 * KeQueryTickCount (NTOSKRNL.EXE.@)
2677 void WINAPI
KeQueryTickCount( LARGE_INTEGER
*count
)
2679 count
->QuadPart
= NtGetTickCount();
2680 /* update the global variable too */
2681 KeTickCount
.LowPart
= count
->u
.LowPart
;
2682 KeTickCount
.High1Time
= count
->u
.HighPart
;
2683 KeTickCount
.High2Time
= count
->u
.HighPart
;
2687 /***********************************************************************
2688 * KeQueryTimeIncrement (NTOSKRNL.EXE.@)
2690 ULONG WINAPI
KeQueryTimeIncrement(void)
2696 /***********************************************************************
2697 * KeSetPriorityThread (NTOSKRNL.EXE.@)
2699 KPRIORITY WINAPI
KeSetPriorityThread( PKTHREAD Thread
, KPRIORITY Priority
)
2701 FIXME("(%p %ld)\n", Thread
, Priority
);
2705 /***********************************************************************
2706 * KeSetSystemAffinityThread (NTOSKRNL.EXE.@)
2708 VOID WINAPI
KeSetSystemAffinityThread(KAFFINITY affinity
)
2710 KeSetSystemAffinityThreadEx(affinity
);
2713 KAFFINITY WINAPI
KeSetSystemAffinityThreadEx(KAFFINITY affinity
)
2715 DWORD_PTR system_affinity
= KeQueryActiveProcessors();
2716 PKTHREAD thread
= KeGetCurrentThread();
2717 GROUP_AFFINITY old
, new;
2719 TRACE("affinity %#Ix.\n", affinity
);
2721 affinity
&= system_affinity
;
2723 NtQueryInformationThread(GetCurrentThread(), ThreadGroupInformation
,
2724 &old
, sizeof(old
), NULL
);
2726 if (old
.Mask
!= system_affinity
)
2727 thread
->user_affinity
= old
.Mask
;
2729 memset(&new, 0, sizeof(new));
2730 new.Mask
= affinity
;
2732 return NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &new, sizeof(new))
2733 ? 0 : thread
->user_affinity
;
2737 /***********************************************************************
2738 * KeRevertToUserAffinityThread (NTOSKRNL.EXE.@)
2740 void WINAPI
KeRevertToUserAffinityThread(void)
2742 KeRevertToUserAffinityThreadEx(0);
2745 void WINAPI
KeRevertToUserAffinityThreadEx(KAFFINITY affinity
)
2747 DWORD_PTR system_affinity
= KeQueryActiveProcessors();
2748 PRKTHREAD thread
= KeGetCurrentThread();
2751 TRACE("affinity %#Ix.\n", affinity
);
2753 affinity
&= system_affinity
;
2755 memset(&new, 0, sizeof(new));
2756 new.Mask
= affinity
? affinity
2757 : (thread
->user_affinity
? thread
->user_affinity
: system_affinity
);
2759 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &new, sizeof(new));
2760 thread
->user_affinity
= affinity
;
2763 /***********************************************************************
2764 * IoRegisterFileSystem (NTOSKRNL.EXE.@)
2766 VOID WINAPI
IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject
)
2768 FIXME("(%p): stub\n", DeviceObject
);
2771 /***********************************************************************
2772 * KeExpandKernelStackAndCalloutEx (NTOSKRNL.EXE.@)
2774 NTSTATUS WINAPI
KeExpandKernelStackAndCalloutEx(PEXPAND_STACK_CALLOUT callout
, void *parameter
, SIZE_T size
,
2775 BOOLEAN wait
, void *context
)
2777 WARN("(%p %p %Iu %x %p) semi-stub: ignoring stack expand\n", callout
, parameter
, size
, wait
, context
);
2779 return STATUS_SUCCESS
;
2782 /***********************************************************************
2783 * KeExpandKernelStackAndCallout (NTOSKRNL.EXE.@)
2785 NTSTATUS WINAPI
KeExpandKernelStackAndCallout(PEXPAND_STACK_CALLOUT callout
, void *parameter
, SIZE_T size
)
2787 return KeExpandKernelStackAndCalloutEx(callout
, parameter
, size
, TRUE
, NULL
);
2790 /***********************************************************************
2791 * IoUnregisterFileSystem (NTOSKRNL.EXE.@)
2793 VOID WINAPI
IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject
)
2795 FIXME("(%p): stub\n", DeviceObject
);
2798 /***********************************************************************
2799 * MmAllocateNonCachedMemory (NTOSKRNL.EXE.@)
2801 PVOID WINAPI
MmAllocateNonCachedMemory( SIZE_T size
)
2803 TRACE( "%Iu\n", size
);
2804 return VirtualAlloc( NULL
, size
, MEM_RESERVE
|MEM_COMMIT
, PAGE_READWRITE
|PAGE_NOCACHE
);
2807 /***********************************************************************
2808 * MmAllocateContiguousMemory (NTOSKRNL.EXE.@)
2810 PVOID WINAPI
MmAllocateContiguousMemory( SIZE_T size
, PHYSICAL_ADDRESS highest_valid_address
)
2812 FIXME( "%Iu, %s stub\n", size
, wine_dbgstr_longlong(highest_valid_address
.QuadPart
) );
2816 /***********************************************************************
2817 * MmAllocateContiguousMemorySpecifyCache (NTOSKRNL.EXE.@)
2819 PVOID WINAPI
MmAllocateContiguousMemorySpecifyCache( SIZE_T size
,
2820 PHYSICAL_ADDRESS lowest_valid_address
,
2821 PHYSICAL_ADDRESS highest_valid_address
,
2822 PHYSICAL_ADDRESS BoundaryAddressMultiple
,
2823 MEMORY_CACHING_TYPE CacheType
)
2829 /***********************************************************************
2830 * MmAllocatePagesForMdl (NTOSKRNL.EXE.@)
2832 PMDL WINAPI
MmAllocatePagesForMdl(PHYSICAL_ADDRESS lowaddress
, PHYSICAL_ADDRESS highaddress
,
2833 PHYSICAL_ADDRESS skipbytes
, SIZE_T size
)
2835 FIXME("%s %s %s %Iu: stub\n", wine_dbgstr_longlong(lowaddress
.QuadPart
), wine_dbgstr_longlong(highaddress
.QuadPart
),
2836 wine_dbgstr_longlong(skipbytes
.QuadPart
), size
);
2840 /***********************************************************************
2841 * MmBuildMdlForNonPagedPool (NTOSKRNL.EXE.@)
2843 void WINAPI
MmBuildMdlForNonPagedPool(MDL
*mdl
)
2845 FIXME("stub: %p\n", mdl
);
2848 /***********************************************************************
2849 * MmCreateSection (NTOSKRNL.EXE.@)
2851 NTSTATUS WINAPI
MmCreateSection( HANDLE
*handle
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
,
2852 LARGE_INTEGER
*size
, ULONG protect
, ULONG alloc_attr
,
2853 HANDLE file
, FILE_OBJECT
*file_obj
)
2855 FIXME("%p %#lx %p %s %#lx %#lx %p %p: stub\n", handle
, access
, attr
,
2856 wine_dbgstr_longlong(size
->QuadPart
), protect
, alloc_attr
, file
, file_obj
);
2857 return STATUS_NOT_IMPLEMENTED
;
2860 /***********************************************************************
2861 * MmFreeNonCachedMemory (NTOSKRNL.EXE.@)
2863 void WINAPI
MmFreeNonCachedMemory( void *addr
, SIZE_T size
)
2865 TRACE( "%p %Iu\n", addr
, size
);
2866 VirtualFree( addr
, 0, MEM_RELEASE
);
2869 /***********************************************************************
2870 * MmIsAddressValid (NTOSKRNL.EXE.@)
2872 * Check if the process can access the virtual address without a pagefault
2875 * VirtualAddress [I] Address to check
2879 * Success: TRUE (Accessing the Address works without a Pagefault)
2882 BOOLEAN WINAPI
MmIsAddressValid(PVOID VirtualAddress
)
2884 TRACE("(%p)\n", VirtualAddress
);
2885 return !IsBadReadPtr(VirtualAddress
, 1);
2888 /***********************************************************************
2889 * MmGetPhysicalAddress (NTOSKRNL.EXE.@)
2891 PHYSICAL_ADDRESS WINAPI
MmGetPhysicalAddress(void *virtual_address
)
2893 PHYSICAL_ADDRESS ret
;
2894 FIXME("(%p): semi-stub\n", virtual_address
);
2895 ret
.QuadPart
= (ULONG_PTR
)virtual_address
;
2899 /***********************************************************************
2900 * MmMapIoSpace (NTOSKRNL.EXE.@)
2902 PVOID WINAPI
MmMapIoSpace( PHYSICAL_ADDRESS PhysicalAddress
, DWORD NumberOfBytes
, DWORD CacheType
)
2904 FIXME( "stub: 0x%08lx%08lx, %ld, %ld\n", PhysicalAddress
.HighPart
, PhysicalAddress
.LowPart
, NumberOfBytes
, CacheType
);
2909 /***********************************************************************
2910 * MmLockPagableSectionByHandle (NTOSKRNL.EXE.@)
2912 VOID WINAPI
MmLockPagableSectionByHandle(PVOID ImageSectionHandle
)
2914 FIXME("stub %p\n", ImageSectionHandle
);
2917 /***********************************************************************
2918 * MmMapLockedPagesSpecifyCache (NTOSKRNL.EXE.@)
2920 PVOID WINAPI
MmMapLockedPagesSpecifyCache(PMDLX MemoryDescriptorList
, KPROCESSOR_MODE AccessMode
, MEMORY_CACHING_TYPE CacheType
,
2921 PVOID BaseAddress
, ULONG BugCheckOnFailure
, MM_PAGE_PRIORITY Priority
)
2923 FIXME("(%p, %u, %u, %p, %lu, %u): stub\n", MemoryDescriptorList
, AccessMode
, CacheType
, BaseAddress
, BugCheckOnFailure
, Priority
);
2928 /***********************************************************************
2929 * MmUnmapLockedPages (NTOSKRNL.EXE.@)
2931 void WINAPI
MmUnmapLockedPages( void *base
, MDL
*mdl
)
2933 FIXME( "(%p %p_\n", base
, mdl
);
2936 /***********************************************************************
2937 * MmUnlockPagableImageSection (NTOSKRNL.EXE.@)
2939 VOID WINAPI
MmUnlockPagableImageSection(PVOID ImageSectionHandle
)
2941 FIXME("stub %p\n", ImageSectionHandle
);
2944 /***********************************************************************
2945 * MmPageEntireDriver (NTOSKRNL.EXE.@)
2947 PVOID WINAPI
MmPageEntireDriver(PVOID AddrInSection
)
2949 TRACE("%p\n", AddrInSection
);
2950 return AddrInSection
;
2954 /***********************************************************************
2955 * MmProbeAndLockPages (NTOSKRNL.EXE.@)
2957 void WINAPI
MmProbeAndLockPages(PMDLX MemoryDescriptorList
, KPROCESSOR_MODE AccessMode
, LOCK_OPERATION Operation
)
2959 FIXME("(%p, %u, %u): stub\n", MemoryDescriptorList
, AccessMode
, Operation
);
2963 /***********************************************************************
2964 * MmResetDriverPaging (NTOSKRNL.EXE.@)
2966 void WINAPI
MmResetDriverPaging(PVOID AddrInSection
)
2968 TRACE("%p\n", AddrInSection
);
2972 /***********************************************************************
2973 * MmUnlockPages (NTOSKRNL.EXE.@)
2975 void WINAPI
MmUnlockPages(PMDLX MemoryDescriptorList
)
2977 FIXME("(%p): stub\n", MemoryDescriptorList
);
2981 /***********************************************************************
2982 * MmUnmapIoSpace (NTOSKRNL.EXE.@)
2984 VOID WINAPI
MmUnmapIoSpace( PVOID BaseAddress
, SIZE_T NumberOfBytes
)
2986 FIXME( "stub: %p, %Iu\n", BaseAddress
, NumberOfBytes
);
2990 /***********************************************************************
2991 * ObReferenceObjectByName (NTOSKRNL.EXE.@)
2993 NTSTATUS WINAPI
ObReferenceObjectByName( UNICODE_STRING
*ObjectName
,
2995 ACCESS_STATE
*AccessState
,
2996 ACCESS_MASK DesiredAccess
,
2997 POBJECT_TYPE ObjectType
,
2998 KPROCESSOR_MODE AccessMode
,
3002 struct wine_driver
*driver
;
3003 struct wine_rb_entry
*entry
;
3005 TRACE("mostly-stub:%s %li %p %li %p %i %p %p\n", debugstr_us(ObjectName
),
3006 Attributes
, AccessState
, DesiredAccess
, ObjectType
, AccessMode
,
3007 ParseContext
, Object
);
3009 if (AccessState
) FIXME("Unhandled AccessState\n");
3010 if (DesiredAccess
) FIXME("Unhandled DesiredAccess\n");
3011 if (ParseContext
) FIXME("Unhandled ParseContext\n");
3012 if (ObjectType
) FIXME("Unhandled ObjectType\n");
3014 if (AccessMode
!= KernelMode
)
3016 FIXME("UserMode access not implemented\n");
3017 return STATUS_NOT_IMPLEMENTED
;
3020 EnterCriticalSection(&drivers_cs
);
3021 entry
= wine_rb_get(&wine_drivers
, ObjectName
);
3022 LeaveCriticalSection(&drivers_cs
);
3025 FIXME("Object (%s) not found, may not be tracked.\n", debugstr_us(ObjectName
));
3026 return STATUS_NOT_IMPLEMENTED
;
3029 driver
= WINE_RB_ENTRY_VALUE(entry
, struct wine_driver
, entry
);
3030 ObReferenceObject( *Object
= &driver
->driver_obj
);
3031 return STATUS_SUCCESS
;
3035 /********************************************************************
3036 * ObOpenObjectByName (NTOSKRNL.EXE.@)
3038 NTSTATUS WINAPI
ObOpenObjectByName(POBJECT_ATTRIBUTES attr
, POBJECT_TYPE type
,
3039 KPROCESSOR_MODE mode
, ACCESS_STATE
*access_state
,
3040 ACCESS_MASK access
, PVOID ctx
, HANDLE
*handle
)
3045 TRACE( "attr(%p %s %lx) %p %u %p %lu %p %p\n", attr
->RootDirectory
, debugstr_us(attr
->ObjectName
),
3046 attr
->Attributes
, type
, mode
, access_state
, access
, ctx
, handle
);
3048 if (mode
!= KernelMode
)
3050 FIXME( "UserMode access not implemented\n" );
3051 return STATUS_NOT_IMPLEMENTED
;
3054 if (attr
->RootDirectory
) FIXME( "RootDirectory unhandled\n" );
3056 status
= ObReferenceObjectByName(attr
->ObjectName
, attr
->Attributes
, access_state
, access
, type
, mode
, ctx
, &object
);
3057 if (status
!= STATUS_SUCCESS
)
3060 status
= ObOpenObjectByPointer(object
, attr
->Attributes
, access_state
, access
, type
, mode
, handle
);
3062 ObDereferenceObject(object
);
3067 /***********************************************************************
3068 * ObReferenceObjectByPointer (NTOSKRNL.EXE.@)
3070 NTSTATUS WINAPI
ObReferenceObjectByPointer(void *obj
, ACCESS_MASK access
,
3072 KPROCESSOR_MODE mode
)
3074 FIXME("(%p, %lx, %p, %d): stub\n", obj
, access
, type
, mode
);
3076 return STATUS_NOT_IMPLEMENTED
;
3080 /***********************************************************************
3081 * ObfReferenceObject (NTOSKRNL.EXE.@)
3083 DEFINE_FASTCALL1_WRAPPER( ObfReferenceObject
)
3084 void FASTCALL
ObfReferenceObject( void *obj
)
3086 ObReferenceObject( obj
);
3090 /***********************************************************************
3091 * ObfDereferenceObject (NTOSKRNL.EXE.@)
3093 DEFINE_FASTCALL1_WRAPPER( ObfDereferenceObject
)
3094 void FASTCALL
ObfDereferenceObject( void *obj
)
3096 ObDereferenceObject( obj
);
3099 /***********************************************************************
3100 * ObRegisterCallbacks (NTOSKRNL.EXE.@)
3102 NTSTATUS WINAPI
ObRegisterCallbacks(POB_CALLBACK_REGISTRATION callback
, void **handle
)
3104 FIXME( "callback %p, handle %p.\n", callback
, handle
);
3107 *handle
= UlongToHandle(0xdeadbeaf);
3109 return STATUS_SUCCESS
;
3112 /***********************************************************************
3113 * ObUnRegisterCallbacks (NTOSKRNL.EXE.@)
3115 void WINAPI
ObUnRegisterCallbacks(void *handle
)
3117 FIXME( "stub: %p\n", handle
);
3120 /***********************************************************************
3121 * ObGetFilterVersion (NTOSKRNL.EXE.@)
3123 USHORT WINAPI
ObGetFilterVersion(void)
3127 return OB_FLT_REGISTRATION_VERSION
;
3130 /***********************************************************************
3131 * IoGetAttachedDeviceReference (NTOSKRNL.EXE.@)
3133 DEVICE_OBJECT
* WINAPI
IoGetAttachedDeviceReference( DEVICE_OBJECT
*device
)
3135 DEVICE_OBJECT
*result
= IoGetAttachedDevice( device
);
3136 ObReferenceObject( result
);
3141 /***********************************************************************
3142 * PsCreateSystemThread (NTOSKRNL.EXE.@)
3144 NTSTATUS WINAPI
PsCreateSystemThread(PHANDLE ThreadHandle
, ULONG DesiredAccess
,
3145 POBJECT_ATTRIBUTES ObjectAttributes
,
3146 HANDLE ProcessHandle
, PCLIENT_ID ClientId
,
3147 PKSTART_ROUTINE StartRoutine
, PVOID StartContext
)
3149 if (!ProcessHandle
) ProcessHandle
= GetCurrentProcess();
3150 return RtlCreateUserThread(ProcessHandle
, 0, FALSE
, 0, 0,
3151 0, StartRoutine
, StartContext
,
3152 ThreadHandle
, ClientId
);
3155 /***********************************************************************
3156 * PsGetCurrentProcessId (NTOSKRNL.EXE.@)
3158 HANDLE WINAPI
PsGetCurrentProcessId(void)
3160 return KeGetCurrentThread()->id
.UniqueProcess
;
3163 /***********************************************************************
3164 * PsGetCurrentProcessSessionId (NTOSKRNL.EXE.@)
3166 ULONG WINAPI
PsGetCurrentProcessSessionId(void)
3168 return PsGetCurrentProcess()->info
.PebBaseAddress
->SessionId
;
3171 /***********************************************************************
3172 * PsGetCurrentThreadId (NTOSKRNL.EXE.@)
3174 HANDLE WINAPI
PsGetCurrentThreadId(void)
3176 return KeGetCurrentThread()->id
.UniqueThread
;
3180 /***********************************************************************
3181 * PsIsSystemThread (NTOSKRNL.EXE.@)
3183 BOOLEAN WINAPI
PsIsSystemThread(PETHREAD thread
)
3185 return thread
->kthread
.process
== PsInitialSystemProcess
;
3189 /***********************************************************************
3190 * PsGetVersion (NTOSKRNL.EXE.@)
3192 BOOLEAN WINAPI
PsGetVersion(ULONG
*major
, ULONG
*minor
, ULONG
*build
, UNICODE_STRING
*version
)
3194 RTL_OSVERSIONINFOEXW info
;
3196 info
.dwOSVersionInfoSize
= sizeof(info
);
3197 RtlGetVersion( &info
);
3198 if (major
) *major
= info
.dwMajorVersion
;
3199 if (minor
) *minor
= info
.dwMinorVersion
;
3200 if (build
) *build
= info
.dwBuildNumber
;
3204 #if 0 /* FIXME: GameGuard passes an uninitialized pointer in version->Buffer */
3205 size_t len
= min( lstrlenW(info
.szCSDVersion
)*sizeof(WCHAR
), version
->MaximumLength
);
3206 memcpy( version
->Buffer
, info
.szCSDVersion
, len
);
3207 if (len
< version
->MaximumLength
) version
->Buffer
[len
/ sizeof(WCHAR
)] = 0;
3208 version
->Length
= len
;
3215 /***********************************************************************
3216 * PsImpersonateClient (NTOSKRNL.EXE.@)
3218 NTSTATUS WINAPI
PsImpersonateClient(PETHREAD Thread
, PACCESS_TOKEN Token
, BOOLEAN CopyOnOpen
,
3219 BOOLEAN EffectiveOnly
, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
3221 FIXME("(%p, %p, %u, %u, %u): stub\n", Thread
, Token
, CopyOnOpen
, EffectiveOnly
, ImpersonationLevel
);
3223 return STATUS_NOT_IMPLEMENTED
;
3227 /***********************************************************************
3228 * PsRevertToSelf (NTOSKRNL.EXE.@)
3230 void WINAPI
PsRevertToSelf(void)
3236 /***********************************************************************
3237 * PsSetCreateProcessNotifyRoutine (NTOSKRNL.EXE.@)
3239 NTSTATUS WINAPI
PsSetCreateProcessNotifyRoutine( PCREATE_PROCESS_NOTIFY_ROUTINE callback
, BOOLEAN remove
)
3241 FIXME( "stub: %p %d\n", callback
, remove
);
3242 return STATUS_SUCCESS
;
3246 /***********************************************************************
3247 * PsSetCreateProcessNotifyRoutineEx (NTOSKRNL.EXE.@)
3249 NTSTATUS WINAPI
PsSetCreateProcessNotifyRoutineEx( PCREATE_PROCESS_NOTIFY_ROUTINE_EX callback
, BOOLEAN remove
)
3251 FIXME( "stub: %p %d\n", callback
, remove
);
3252 return STATUS_SUCCESS
;
3256 /***********************************************************************
3257 * PsSetCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
3259 NTSTATUS WINAPI
PsSetCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
3261 FIXME( "stub: %p\n", NotifyRoutine
);
3262 return STATUS_SUCCESS
;
3266 /***********************************************************************
3267 * PsRemoveCreateThreadNotifyRoutine (NTOSKRNL.EXE.@)
3269 NTSTATUS WINAPI
PsRemoveCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine
)
3271 FIXME( "stub: %p\n", NotifyRoutine
);
3272 return STATUS_SUCCESS
;
3276 /***********************************************************************
3277 * PsRemoveLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
3279 NTSTATUS WINAPI
PsRemoveLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine
)
3283 TRACE("routine %p.\n", routine
);
3285 for (i
= 0; i
< load_image_notify_routine_count
; ++i
)
3286 if (load_image_notify_routines
[i
] == routine
)
3288 --load_image_notify_routine_count
;
3289 memmove(&load_image_notify_routines
[i
], &load_image_notify_routines
[i
+ 1],
3290 sizeof(*load_image_notify_routines
) * (load_image_notify_routine_count
- i
));
3291 return STATUS_SUCCESS
;
3293 return STATUS_PROCEDURE_NOT_FOUND
;
3297 /***********************************************************************
3298 * PsReferenceProcessFilePointer (NTOSKRNL.EXE.@)
3300 NTSTATUS WINAPI
PsReferenceProcessFilePointer(PEPROCESS process
, FILE_OBJECT
**file
)
3302 FIXME("%p %p\n", process
, file
);
3303 return STATUS_NOT_IMPLEMENTED
;
3307 /***********************************************************************
3308 * PsTerminateSystemThread (NTOSKRNL.EXE.@)
3310 NTSTATUS WINAPI
PsTerminateSystemThread(NTSTATUS status
)
3312 TRACE("status %#lx.\n", status
);
3313 ExitThread( status
);
3317 /***********************************************************************
3318 * PsSuspendProcess (NTOSKRNL.EXE.@)
3320 NTSTATUS WINAPI
PsSuspendProcess(PEPROCESS process
)
3322 FIXME("stub: %p\n", process
);
3323 return STATUS_NOT_IMPLEMENTED
;
3327 /***********************************************************************
3328 * PsResumeProcess (NTOSKRNL.EXE.@)
3330 NTSTATUS WINAPI
PsResumeProcess(PEPROCESS process
)
3332 FIXME("stub: %p\n", process
);
3333 return STATUS_NOT_IMPLEMENTED
;
3337 /***********************************************************************
3338 * MmGetSystemRoutineAddress (NTOSKRNL.EXE.@)
3340 PVOID WINAPI
MmGetSystemRoutineAddress(PUNICODE_STRING SystemRoutineName
)
3343 STRING routineNameA
;
3346 static const WCHAR ntoskrnlW
[] = {'n','t','o','s','k','r','n','l','.','e','x','e',0};
3347 static const WCHAR halW
[] = {'h','a','l','.','d','l','l',0};
3349 if (!SystemRoutineName
) return NULL
;
3351 if (RtlUnicodeStringToAnsiString( &routineNameA
, SystemRoutineName
, TRUE
) == STATUS_SUCCESS
)
3353 /* We only support functions exported from ntoskrnl.exe or hal.dll */
3354 hMod
= GetModuleHandleW( ntoskrnlW
);
3355 pFunc
= GetProcAddress( hMod
, routineNameA
.Buffer
);
3358 hMod
= LoadLibraryW( halW
);
3359 if (hMod
) pFunc
= GetProcAddress( hMod
, routineNameA
.Buffer
);
3361 RtlFreeAnsiString( &routineNameA
);
3365 TRACE( "%s -> %p\n", debugstr_us(SystemRoutineName
), pFunc
);
3367 FIXME( "%s not found\n", debugstr_us(SystemRoutineName
) );
3371 /***********************************************************************
3372 * MmIsThisAnNtAsSystem (NTOSKRNL.EXE.@)
3374 BOOLEAN WINAPI
MmIsThisAnNtAsSystem(void)
3380 /***********************************************************************
3381 * MmProtectMdlSystemAddress (NTOSKRNL.EXE.@)
3383 NTSTATUS WINAPI
MmProtectMdlSystemAddress(PMDL MemoryDescriptorList
, ULONG NewProtect
)
3385 FIXME("(%p, %lu) stub\n", MemoryDescriptorList
, NewProtect
);
3386 return STATUS_SUCCESS
;
3389 /***********************************************************************
3390 * MmQuerySystemSize (NTOSKRNL.EXE.@)
3392 MM_SYSTEMSIZE WINAPI
MmQuerySystemSize(void)
3395 return MmLargeSystem
;
3398 /***********************************************************************
3399 * KeInitializeDpc (NTOSKRNL.EXE.@)
3401 void WINAPI
KeInitializeDpc(KDPC
*dpc
, PKDEFERRED_ROUTINE deferred_routine
, void *deferred_context
)
3403 FIXME("dpc %p, deferred_routine %p, deferred_context %p semi-stub.\n",
3404 dpc
, deferred_routine
, deferred_context
);
3406 dpc
->DeferredRoutine
= deferred_routine
;
3407 dpc
->DeferredContext
= deferred_context
;
3410 /***********************************************************************
3411 * KeSetImportanceDpc (NTOSKRNL.EXE.@)
3413 VOID WINAPI
KeSetImportanceDpc(PRKDPC dpc
, KDPC_IMPORTANCE importance
)
3415 FIXME("%p, %d stub\n", dpc
, importance
);
3418 /***********************************************************************
3419 * KeSetTargetProcessorDpcEx (NTOSKRNL.EXE.@)
3421 VOID WINAPI
KeSetTargetProcessorDpcEx(PRKDPC dpc
, PPROCESSOR_NUMBER process_number
)
3423 FIXME("%p, %p stub\n", dpc
, process_number
);
3426 /***********************************************************************
3427 * KeSetTargetProcessorDpc (NTOSKRNL.EXE.@)
3429 VOID WINAPI
KeSetTargetProcessorDpc(PRKDPC dpc
, CCHAR number
)
3431 FIXME("%p, %d stub\n", dpc
, number
);
3434 /***********************************************************************
3435 * KeGetCurrentProcessorNumberEx (NTOSKRNL.EXE.@)
3437 ULONG WINAPI
KeGetCurrentProcessorNumberEx(PPROCESSOR_NUMBER process_number
)
3439 ULONG cur_number
= NtGetCurrentProcessorNumber();
3441 FIXME("%p semi-stub\n", process_number
);
3445 process_number
->Group
= 0;
3446 process_number
->Reserved
= 0;
3447 process_number
->Number
= cur_number
;
3453 /***********************************************************************
3454 * KeQueryMaximumProcessorCountEx (NTOSKRNL.EXE.@)
3456 ULONG WINAPI
KeQueryMaximumProcessorCountEx(USHORT group_number
)
3458 return GetMaximumProcessorCount(group_number
);
3461 /***********************************************************************
3462 * KeQueryMaximumProcessorCount (NTOSKRNL.EXE.@)
3464 ULONG WINAPI
KeQueryMaximumProcessorCount(void)
3466 return KeQueryMaximumProcessorCountEx(0);
3469 /***********************************************************************
3470 * READ_REGISTER_BUFFER_UCHAR (NTOSKRNL.EXE.@)
3472 VOID WINAPI
READ_REGISTER_BUFFER_UCHAR(PUCHAR Register
, PUCHAR Buffer
, ULONG Count
)
3477 /*****************************************************
3478 * IoWMIRegistrationControl (NTOSKRNL.EXE.@)
3480 NTSTATUS WINAPI
IoWMIRegistrationControl(PDEVICE_OBJECT DeviceObject
, ULONG Action
)
3482 FIXME("(%p %lu) stub\n", DeviceObject
, Action
);
3483 return STATUS_SUCCESS
;
3486 /*****************************************************
3487 * IoWMIOpenBlock (NTOSKRNL.EXE.@)
3489 NTSTATUS WINAPI
IoWMIOpenBlock(LPCGUID guid
, ULONG desired_access
, PVOID
*data_block_obj
)
3491 FIXME("(%p %lu %p) stub\n", guid
, desired_access
, data_block_obj
);
3492 return STATUS_NOT_IMPLEMENTED
;
3495 /*****************************************************
3496 * PsSetLoadImageNotifyRoutine (NTOSKRNL.EXE.@)
3498 NTSTATUS WINAPI
PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE routine
)
3500 return PsSetLoadImageNotifyRoutineEx(routine
, 0);
3503 /*****************************************************
3504 * PsSetLoadImageNotifyRoutineEx (NTOSKRNL.EXE.@)
3506 NTSTATUS WINAPI
PsSetLoadImageNotifyRoutineEx(PLOAD_IMAGE_NOTIFY_ROUTINE routine
, ULONG_PTR flags
)
3508 FIXME("routine %p, flags %Ix semi-stub.\n", routine
, flags
);
3510 if (load_image_notify_routine_count
== ARRAY_SIZE(load_image_notify_routines
))
3511 return STATUS_INSUFFICIENT_RESOURCES
;
3513 load_image_notify_routines
[load_image_notify_routine_count
++] = routine
;
3515 return STATUS_SUCCESS
;
3518 /*****************************************************
3519 * IoSetThreadHardErrorMode (NTOSKRNL.EXE.@)
3521 BOOLEAN WINAPI
IoSetThreadHardErrorMode(BOOLEAN EnableHardErrors
)
3527 /*****************************************************
3528 * Ke386IoSetAccessProcess (NTOSKRNL.EXE.@)
3530 BOOLEAN WINAPI
Ke386IoSetAccessProcess(PEPROCESS
*process
, ULONG flag
)
3532 FIXME("(%p %ld) stub\n", process
, flag
);
3536 /*****************************************************
3537 * Ke386QueryIoAccessMap (NTOSKRNL.EXE.@)
3539 BOOLEAN WINAPI
Ke386QueryIoAccessMap(ULONG flag
, PVOID buffer
)
3541 FIXME("(%ld %p) stub\n", flag
, buffer
);
3545 /*****************************************************
3546 * Ke386SetIoAccessMap (NTOSKRNL.EXE.@)
3548 BOOLEAN WINAPI
Ke386SetIoAccessMap(ULONG flag
, PVOID buffer
)
3550 FIXME("(%ld %p) stub\n", flag
, buffer
);
3554 /*****************************************************
3555 * IoStartNextPacket (NTOSKRNL.EXE.@)
3557 VOID WINAPI
IoStartNextPacket(PDEVICE_OBJECT deviceobject
, BOOLEAN cancelable
)
3559 FIXME("(%p %d) stub\n", deviceobject
, cancelable
);
3562 /*****************************************************
3563 * ObQueryNameString (NTOSKRNL.EXE.@)
3565 NTSTATUS WINAPI
ObQueryNameString( void *object
, OBJECT_NAME_INFORMATION
*name
, ULONG size
, ULONG
*ret_size
)
3570 TRACE("object %p, name %p, size %lu, ret_size %p.\n", object
, name
, size
, ret_size
);
3572 if ((ret
= ObOpenObjectByPointer( object
, 0, NULL
, 0, NULL
, KernelMode
, &handle
)))
3574 ret
= NtQueryObject( handle
, ObjectNameInformation
, name
, size
, ret_size
);
3580 /*****************************************************
3581 * IoRegisterPlugPlayNotification (NTOSKRNL.EXE.@)
3583 NTSTATUS WINAPI
IoRegisterPlugPlayNotification(IO_NOTIFICATION_EVENT_CATEGORY category
, ULONG flags
, PVOID data
,
3584 PDRIVER_OBJECT driver
, PDRIVER_NOTIFICATION_CALLBACK_ROUTINE callback
,
3585 PVOID context
, PVOID
*notification
)
3587 FIXME("(%u %lu %p %p %p %p %p) stub\n", category
, flags
, data
, driver
, callback
, context
, notification
);
3588 return STATUS_SUCCESS
;
3591 /*****************************************************
3592 * IoUnregisterPlugPlayNotification (NTOSKRNL.EXE.@)
3594 NTSTATUS WINAPI
IoUnregisterPlugPlayNotification(PVOID notification
)
3596 FIXME("stub: %p\n", notification
);
3597 return STATUS_SUCCESS
;
3600 /*****************************************************
3601 * IoCsqInitialize (NTOSKRNL.EXE.@)
3603 NTSTATUS WINAPI
IoCsqInitialize(PIO_CSQ csq
, PIO_CSQ_INSERT_IRP insert_irp
, PIO_CSQ_REMOVE_IRP remove_irp
,
3604 PIO_CSQ_PEEK_NEXT_IRP peek_irp
, PIO_CSQ_ACQUIRE_LOCK acquire_lock
,
3605 PIO_CSQ_RELEASE_LOCK release_lock
, PIO_CSQ_COMPLETE_CANCELED_IRP complete_irp
)
3607 FIXME("(%p %p %p %p %p %p %p) stub\n",
3608 csq
, insert_irp
, remove_irp
, peek_irp
, acquire_lock
, release_lock
, complete_irp
);
3609 return STATUS_SUCCESS
;
3612 /***********************************************************************
3613 * KeEnterCriticalRegion (NTOSKRNL.EXE.@)
3615 void WINAPI
KeEnterCriticalRegion(void)
3617 TRACE( "semi-stub\n" );
3618 KeGetCurrentThread()->critical_region
++;
3621 /***********************************************************************
3622 * KeLeaveCriticalRegion (NTOSKRNL.EXE.@)
3624 void WINAPI
KeLeaveCriticalRegion(void)
3626 TRACE( "semi-stub\n" );
3627 KeGetCurrentThread()->critical_region
--;
3630 /***********************************************************************
3631 * KeAreApcsDisabled (NTOSKRNL.@)
3633 BOOLEAN WINAPI
KeAreApcsDisabled(void)
3635 unsigned int critical_region
= KeGetCurrentThread()->critical_region
;
3636 TRACE( "%u\n", critical_region
);
3637 return !!critical_region
;
3640 /***********************************************************************
3641 * KeAreAllApcsDisabled (NTOSKRNL.@)
3643 BOOLEAN WINAPI
KeAreAllApcsDisabled(void)
3645 return KeAreApcsDisabled();
3648 /***********************************************************************
3649 * KeBugCheck (NTOSKRNL.@)
3651 void WINAPI
KeBugCheck(ULONG code
)
3653 KeBugCheckEx(code
, 0, 0, 0, 0);
3656 /***********************************************************************
3657 * KeBugCheckEx (NTOSKRNL.@)
3659 void WINAPI
KeBugCheckEx(ULONG code
, ULONG_PTR param1
, ULONG_PTR param2
, ULONG_PTR param3
, ULONG_PTR param4
)
3661 ERR( "%lx %Ix %Ix %Ix %Ix\n", code
, param1
, param2
, param3
, param4
);
3662 ExitProcess( code
);
3665 /***********************************************************************
3666 * ProbeForRead (NTOSKRNL.EXE.@)
3668 void WINAPI
ProbeForRead(void *address
, SIZE_T length
, ULONG alignment
)
3670 FIXME("(%p %Iu %lu) stub\n", address
, length
, alignment
);
3673 /***********************************************************************
3674 * ProbeForWrite (NTOSKRNL.EXE.@)
3676 void WINAPI
ProbeForWrite(void *address
, SIZE_T length
, ULONG alignment
)
3678 FIXME("(%p %Iu %lu) stub\n", address
, length
, alignment
);
3681 /***********************************************************************
3682 * CmRegisterCallback (NTOSKRNL.EXE.@)
3684 NTSTATUS WINAPI
CmRegisterCallback(EX_CALLBACK_FUNCTION
*function
, void *context
, LARGE_INTEGER
*cookie
)
3686 FIXME("(%p %p %p): stub\n", function
, context
, cookie
);
3687 return STATUS_NOT_IMPLEMENTED
;
3690 /***********************************************************************
3691 * CmUnRegisterCallback (NTOSKRNL.EXE.@)
3693 NTSTATUS WINAPI
CmUnRegisterCallback(LARGE_INTEGER cookie
)
3695 FIXME("(%s): stub\n", wine_dbgstr_longlong(cookie
.QuadPart
));
3696 return STATUS_NOT_IMPLEMENTED
;
3699 /***********************************************************************
3700 * IoAttachDevice (NTOSKRNL.EXE.@)
3702 NTSTATUS WINAPI
IoAttachDevice(DEVICE_OBJECT
*source
, UNICODE_STRING
*target
, DEVICE_OBJECT
*attached
)
3704 FIXME("(%p, %s, %p): stub\n", source
, debugstr_us(target
), attached
);
3705 return STATUS_NOT_IMPLEMENTED
;
3709 static NTSTATUS
open_driver( const UNICODE_STRING
*service_name
, SC_HANDLE
*service
)
3711 QUERY_SERVICE_CONFIGW
*service_config
= NULL
;
3712 SC_HANDLE manager_handle
;
3713 DWORD config_size
= 0;
3716 if (!(name
= RtlAllocateHeap( GetProcessHeap(), 0, service_name
->Length
+ sizeof(WCHAR
) )))
3717 return STATUS_NO_MEMORY
;
3719 memcpy( name
, service_name
->Buffer
, service_name
->Length
);
3720 name
[ service_name
->Length
/ sizeof(WCHAR
) ] = 0;
3722 if (wcsncmp( name
, servicesW
, lstrlenW(servicesW
) ))
3724 FIXME( "service name %s is not a keypath\n", debugstr_us(service_name
) );
3725 RtlFreeHeap( GetProcessHeap(), 0, name
);
3726 return STATUS_NOT_IMPLEMENTED
;
3729 if (!(manager_handle
= OpenSCManagerW( NULL
, NULL
, SC_MANAGER_CONNECT
)))
3731 WARN( "failed to connect to service manager\n" );
3732 RtlFreeHeap( GetProcessHeap(), 0, name
);
3733 return STATUS_NOT_SUPPORTED
;
3736 *service
= OpenServiceW( manager_handle
, name
+ lstrlenW(servicesW
),
3737 SERVICE_QUERY_CONFIG
| SERVICE_SET_STATUS
);
3738 RtlFreeHeap( GetProcessHeap(), 0, name
);
3739 CloseServiceHandle( manager_handle
);
3743 WARN( "failed to open service %s\n", debugstr_us(service_name
) );
3744 return STATUS_UNSUCCESSFUL
;
3747 QueryServiceConfigW( *service
, NULL
, 0, &config_size
);
3748 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
3750 WARN( "failed to query service config\n" );
3754 if (!(service_config
= RtlAllocateHeap( GetProcessHeap(), 0, config_size
)))
3757 if (!QueryServiceConfigW( *service
, service_config
, config_size
, &config_size
))
3759 WARN( "failed to query service config\n" );
3763 if (service_config
->dwServiceType
!= SERVICE_KERNEL_DRIVER
&&
3764 service_config
->dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
)
3766 WARN( "service %s is not a kernel driver\n", debugstr_us(service_name
) );
3770 TRACE( "opened service for driver %s\n", debugstr_us(service_name
) );
3771 RtlFreeHeap( GetProcessHeap(), 0, service_config
);
3772 return STATUS_SUCCESS
;
3775 CloseServiceHandle( *service
);
3776 RtlFreeHeap( GetProcessHeap(), 0, service_config
);
3777 return STATUS_UNSUCCESSFUL
;
3780 /* find the LDR_DATA_TABLE_ENTRY corresponding to the driver module */
3781 static LDR_DATA_TABLE_ENTRY
*find_ldr_module( HMODULE module
)
3783 LDR_DATA_TABLE_ENTRY
*ldr
;
3786 LdrLockLoaderLock( 0, NULL
, &magic
);
3787 if (LdrFindEntryForAddress( module
, &ldr
))
3789 WARN( "module not found for %p\n", module
);
3792 LdrUnlockLoaderLock( 0, magic
);
3797 /* convert PE image VirtualAddress to Real Address */
3798 static inline void *get_rva( HMODULE module
, DWORD va
)
3800 return (void *)((char *)module
+ va
);
3803 static void WINAPI
ldr_notify_callback(ULONG reason
, LDR_DLL_NOTIFICATION_DATA
*data
, void *context
)
3805 const IMAGE_DATA_DIRECTORY
*relocs
;
3806 IMAGE_BASE_RELOCATION
*rel
, *end
;
3807 SYSTEM_BASIC_INFORMATION info
;
3808 IMAGE_NT_HEADERS
*nt
;
3813 if (reason
!= LDR_DLL_NOTIFICATION_REASON_LOADED
) return;
3814 TRACE( "loading %s\n", debugstr_us(data
->Loaded
.BaseDllName
));
3816 module
= data
->Loaded
.DllBase
;
3817 nt
= RtlImageNtHeader( module
);
3818 base
= (char *)nt
->OptionalHeader
.ImageBase
;
3819 if (!(delta
= (char *)module
- base
)) return;
3821 /* the loader does not apply relocations to non page-aligned binaries or executables,
3822 * we have to do it ourselves */
3824 NtQuerySystemInformation( SystemBasicInformation
, &info
, sizeof(info
), NULL
);
3825 if (nt
->OptionalHeader
.SectionAlignment
>= info
.PageSize
&& (nt
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
))
3828 if (nt
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
3830 WARN( "Need to relocate module from %p to %p, but there are no relocation records\n", base
, module
);
3834 relocs
= &nt
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
3835 if (!relocs
->Size
|| !relocs
->VirtualAddress
) return;
3837 TRACE( "relocating from %p-%p to %p-%p\n", base
, base
+ nt
->OptionalHeader
.SizeOfImage
,
3838 module
, (char *)module
+ nt
->OptionalHeader
.SizeOfImage
);
3840 rel
= get_rva( module
, relocs
->VirtualAddress
);
3841 end
= get_rva( module
, relocs
->VirtualAddress
+ relocs
->Size
);
3843 while (rel
< end
- 1 && rel
->SizeOfBlock
)
3845 char *page
= get_rva( module
, rel
->VirtualAddress
);
3846 DWORD old_prot1
, old_prot2
;
3848 if (rel
->VirtualAddress
>= nt
->OptionalHeader
.SizeOfImage
)
3850 WARN( "invalid address %p in relocation %p\n", get_rva( module
, rel
->VirtualAddress
), rel
);
3854 /* Relocation entries may hang over the end of the page, so we need to
3855 * protect two pages. */
3856 VirtualProtect( page
, info
.PageSize
, PAGE_READWRITE
, &old_prot1
);
3857 VirtualProtect( page
+ info
.PageSize
, info
.PageSize
, PAGE_READWRITE
, &old_prot2
);
3858 rel
= LdrProcessRelocationBlock( page
, (rel
->SizeOfBlock
- sizeof(*rel
)) / sizeof(USHORT
),
3859 (USHORT
*)(rel
+ 1), delta
);
3860 VirtualProtect( page
, info
.PageSize
, old_prot1
, &old_prot1
);
3861 VirtualProtect( page
+ info
.PageSize
, info
.PageSize
, old_prot2
, &old_prot2
);
3864 WARN( "LdrProcessRelocationBlock failed\n" );
3870 /* load the .sys module for a device driver */
3871 static HMODULE
load_driver( const WCHAR
*driver_name
, const UNICODE_STRING
*keyname
)
3873 static const WCHAR driversW
[] = {'\\','d','r','i','v','e','r','s','\\',0};
3874 static const WCHAR systemrootW
[] = {'\\','S','y','s','t','e','m','R','o','o','t','\\',0};
3875 static const WCHAR postfixW
[] = {'.','s','y','s',0};
3876 static const WCHAR ntprefixW
[] = {'\\','?','?','\\',0};
3877 static const WCHAR ImagePathW
[] = {'I','m','a','g','e','P','a','t','h',0};
3880 LPWSTR path
= NULL
, str
;
3883 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, keyname
->Buffer
+ 18 /* skip \registry\machine */, &driver_hkey
))
3885 ERR( "cannot open key %s, err=%lu\n", wine_dbgstr_w(keyname
->Buffer
), GetLastError() );
3889 /* read the executable path from memory */
3891 if (!RegQueryValueExW( driver_hkey
, ImagePathW
, NULL
, &type
, NULL
, &size
))
3893 str
= HeapAlloc( GetProcessHeap(), 0, size
);
3894 if (!RegQueryValueExW( driver_hkey
, ImagePathW
, NULL
, &type
, (LPBYTE
)str
, &size
))
3896 size
= ExpandEnvironmentStringsW(str
,NULL
,0);
3897 path
= HeapAlloc(GetProcessHeap(),0,size
*sizeof(WCHAR
));
3898 ExpandEnvironmentStringsW(str
,path
,size
);
3900 HeapFree( GetProcessHeap(), 0, str
);
3903 RegCloseKey( driver_hkey
);
3907 if (!wcsnicmp( path
, systemrootW
, 12 ))
3909 WCHAR buffer
[MAX_PATH
];
3911 GetWindowsDirectoryW(buffer
, MAX_PATH
);
3913 str
= HeapAlloc(GetProcessHeap(), 0, (size
-11 + lstrlenW(buffer
))
3915 lstrcpyW(str
, buffer
);
3916 lstrcatW(str
, path
+ 11);
3917 HeapFree( GetProcessHeap(), 0, path
);
3920 else if (!wcsncmp( path
, ntprefixW
, 4 ))
3927 /* default is to use the driver name + ".sys" */
3928 WCHAR buffer
[MAX_PATH
];
3929 GetSystemDirectoryW(buffer
, MAX_PATH
);
3930 path
= HeapAlloc(GetProcessHeap(),0,
3931 (lstrlenW(buffer
) + lstrlenW(driversW
) + lstrlenW(driver_name
) + lstrlenW(postfixW
) + 1)
3933 lstrcpyW(path
, buffer
);
3934 lstrcatW(path
, driversW
);
3935 lstrcatW(path
, driver_name
);
3936 lstrcatW(path
, postfixW
);
3939 RegCloseKey( driver_hkey
);
3941 TRACE( "loading driver %s\n", wine_dbgstr_w(str
) );
3943 module
= LoadLibraryExW( str
, 0, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
| LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
);
3945 if (module
&& load_image_notify_routine_count
)
3947 UNICODE_STRING module_name
;
3948 IMAGE_NT_HEADERS
*nt
;
3952 RtlInitUnicodeString(&module_name
, str
);
3953 nt
= RtlImageNtHeader(module
);
3954 memset(&info
, 0, sizeof(info
));
3955 info
.ImageAddressingMode
= IMAGE_ADDRESSING_MODE_32BIT
;
3956 info
.SystemModeImage
= TRUE
;
3957 info
.ImageSize
= nt
->OptionalHeader
.SizeOfImage
;
3958 info
.ImageBase
= module
;
3960 for (i
= 0; i
< load_image_notify_routine_count
; ++i
)
3962 TRACE("Calling image load notify %p.\n", load_image_notify_routines
[i
]);
3963 load_image_notify_routines
[i
](&module_name
, NULL
, &info
);
3964 TRACE("Called image load notify %p.\n", load_image_notify_routines
[i
]);
3968 HeapFree( GetProcessHeap(), 0, path
);
3972 /* call the driver init entry point */
3973 static NTSTATUS WINAPI
init_driver( DRIVER_OBJECT
*driver_object
, UNICODE_STRING
*keyname
)
3977 const IMAGE_NT_HEADERS
*nt
;
3978 const WCHAR
*driver_name
;
3981 /* Retrieve driver name from the keyname */
3982 driver_name
= wcsrchr( keyname
->Buffer
, '\\' );
3985 module
= load_driver( driver_name
, keyname
);
3987 return STATUS_DLL_INIT_FAILED
;
3989 driver_object
->DriverSection
= find_ldr_module( module
);
3990 driver_object
->DriverStart
= ((LDR_DATA_TABLE_ENTRY
*)driver_object
->DriverSection
)->DllBase
;
3991 driver_object
->DriverSize
= ((LDR_DATA_TABLE_ENTRY
*)driver_object
->DriverSection
)->SizeOfImage
;
3993 nt
= RtlImageNtHeader( module
);
3994 if (!nt
->OptionalHeader
.AddressOfEntryPoint
) return STATUS_SUCCESS
;
3995 driver_object
->DriverInit
= (PDRIVER_INITIALIZE
)((char *)module
+ nt
->OptionalHeader
.AddressOfEntryPoint
);
3997 TRACE_(relay
)( "\1Call driver init %p (obj=%p,str=%s)\n",
3998 driver_object
->DriverInit
, driver_object
, wine_dbgstr_w(keyname
->Buffer
) );
4000 status
= driver_object
->DriverInit( driver_object
, keyname
);
4002 TRACE_(relay
)( "\1Ret driver init %p (obj=%p,str=%s) retval=%08lx\n",
4003 driver_object
->DriverInit
, driver_object
, wine_dbgstr_w(keyname
->Buffer
), status
);
4005 TRACE( "init done for %s obj %p\n", wine_dbgstr_w(driver_name
), driver_object
);
4006 TRACE( "- DriverInit = %p\n", driver_object
->DriverInit
);
4007 TRACE( "- DriverStartIo = %p\n", driver_object
->DriverStartIo
);
4008 TRACE( "- DriverUnload = %p\n", driver_object
->DriverUnload
);
4009 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
4010 TRACE( "- MajorFunction[%d] = %p\n", i
, driver_object
->MajorFunction
[i
] );
4015 static BOOLEAN
get_drv_name( UNICODE_STRING
*drv_name
, const UNICODE_STRING
*service_name
)
4017 static const WCHAR driverW
[] = {'\\','D','r','i','v','e','r','\\',0};
4020 if (!(str
= heap_alloc( sizeof(driverW
) + service_name
->Length
- lstrlenW(servicesW
)*sizeof(WCHAR
) )))
4023 lstrcpyW( str
, driverW
);
4024 lstrcpynW( str
+ lstrlenW(driverW
), service_name
->Buffer
+ lstrlenW(servicesW
),
4025 service_name
->Length
/sizeof(WCHAR
) - lstrlenW(servicesW
) + 1 );
4026 RtlInitUnicodeString( drv_name
, str
);
4030 /***********************************************************************
4031 * ZwLoadDriver (NTOSKRNL.EXE.@)
4033 NTSTATUS WINAPI
ZwLoadDriver( const UNICODE_STRING
*service_name
)
4035 SERVICE_STATUS_HANDLE service_handle
;
4036 struct wine_rb_entry
*entry
;
4037 struct wine_driver
*driver
;
4038 UNICODE_STRING drv_name
;
4041 TRACE( "(%s)\n", debugstr_us(service_name
) );
4043 if ((status
= open_driver( service_name
, (SC_HANDLE
*)&service_handle
)) != STATUS_SUCCESS
)
4046 if (!get_drv_name( &drv_name
, service_name
))
4048 CloseServiceHandle( (void *)service_handle
);
4049 return STATUS_NO_MEMORY
;
4052 if (wine_rb_get( &wine_drivers
, &drv_name
))
4054 TRACE( "driver %s already loaded\n", debugstr_us(&drv_name
) );
4055 RtlFreeUnicodeString( &drv_name
);
4056 CloseServiceHandle( (void *)service_handle
);
4057 return STATUS_IMAGE_ALREADY_LOADED
;
4060 set_service_status( service_handle
, SERVICE_START_PENDING
, 0 );
4062 status
= IoCreateDriver( &drv_name
, init_driver
);
4063 entry
= wine_rb_get( &wine_drivers
, &drv_name
);
4064 RtlFreeUnicodeString( &drv_name
);
4065 if (status
!= STATUS_SUCCESS
)
4067 ERR( "failed to create driver %s: %08lx\n", debugstr_us(service_name
), status
);
4071 driver
= WINE_RB_ENTRY_VALUE( entry
, struct wine_driver
, entry
);
4072 driver
->service_handle
= service_handle
;
4074 wine_enumerate_root_devices( service_name
->Buffer
+ wcslen( servicesW
) );
4076 set_service_status( service_handle
, SERVICE_RUNNING
,
4077 SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
4078 return STATUS_SUCCESS
;
4081 set_service_status( service_handle
, SERVICE_STOPPED
, 0 );
4082 CloseServiceHandle( (void *)service_handle
);
4086 /***********************************************************************
4087 * ZwUnloadDriver (NTOSKRNL.EXE.@)
4089 NTSTATUS WINAPI
ZwUnloadDriver( const UNICODE_STRING
*service_name
)
4091 struct wine_rb_entry
*entry
;
4092 struct wine_driver
*driver
;
4093 UNICODE_STRING drv_name
;
4095 TRACE( "(%s)\n", debugstr_us(service_name
) );
4097 if (!get_drv_name( &drv_name
, service_name
))
4098 return STATUS_NO_MEMORY
;
4100 entry
= wine_rb_get( &wine_drivers
, &drv_name
);
4101 RtlFreeUnicodeString( &drv_name
);
4104 ERR( "failed to locate driver %s\n", debugstr_us(service_name
) );
4105 return STATUS_OBJECT_NAME_NOT_FOUND
;
4107 driver
= WINE_RB_ENTRY_VALUE( entry
, struct wine_driver
, entry
);
4109 if (!list_empty( &driver
->root_pnp_devices
))
4111 ERR( "cannot unload driver %s which still has running PnP devices\n", debugstr_us(service_name
) );
4112 return STATUS_UNSUCCESSFUL
;
4115 unload_driver( entry
, NULL
);
4117 return STATUS_SUCCESS
;
4120 /***********************************************************************
4121 * IoCreateFileEx (NTOSKRNL.EXE.@)
4123 NTSTATUS WINAPI
IoCreateFileEx(HANDLE
*handle
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
,
4124 IO_STATUS_BLOCK
*io
, LARGE_INTEGER
*alloc_size
, ULONG attributes
, ULONG sharing
,
4125 ULONG disposition
, ULONG create_options
, VOID
*ea_buffer
, ULONG ea_length
,
4126 CREATE_FILE_TYPE file_type
, VOID
*parameters
, ULONG options
, void *driverctx
)
4128 FIXME(": semi-stub\n");
4129 return NtCreateFile(handle
, access
, attr
, io
, alloc_size
, attributes
, sharing
, disposition
,
4130 create_options
, ea_buffer
, ea_length
);
4133 /***********************************************************************
4134 * IoCreateFile (NTOSKRNL.EXE.@)
4136 NTSTATUS WINAPI
IoCreateFile(HANDLE
*handle
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
,
4137 IO_STATUS_BLOCK
*io
, LARGE_INTEGER
*alloc_size
, ULONG attributes
, ULONG sharing
,
4138 ULONG disposition
, ULONG create_options
, VOID
*ea_buffer
, ULONG ea_length
,
4139 CREATE_FILE_TYPE file_type
, VOID
*parameters
, ULONG options
)
4141 FIXME(": semi-stub\n");
4142 return IoCreateFileEx(handle
, access
, attr
, io
, alloc_size
, attributes
, sharing
, disposition
,
4143 create_options
, ea_buffer
, ea_length
, file_type
, parameters
, options
, NULL
);
4146 /**************************************************************************
4147 * __chkstk (NTOSKRNL.@)
4150 /* Supposed to touch all the stack pages, but we shouldn't need that. */
4151 __ASM_GLOBAL_FUNC( __chkstk
, "ret" );
4152 #elif defined(__i386__)
4153 __ASM_GLOBAL_FUNC( _chkstk
,
4155 "addl %esp,%eax\n\t"
4156 "xchgl %esp,%eax\n\t"
4157 "movl 0(%eax),%eax\n\t" /* copy return address from old location */
4158 "movl %eax,0(%esp)\n\t"
4160 #elif defined(__arm__)
4161 /* Incoming r4 contains words to allocate, converting to bytes then return */
4162 __ASM_GLOBAL_FUNC( __chkstk
, "lsl r4, r4, #2\n\t"
4164 #elif defined(__aarch64__)
4165 /* Supposed to touch all the stack pages, but we shouldn't need that. */
4166 __ASM_GLOBAL_FUNC( __chkstk
, "ret" );
4169 /*********************************************************************
4170 * PsAcquireProcessExitSynchronization (NTOSKRNL.@)
4172 NTSTATUS WINAPI
PsAcquireProcessExitSynchronization(PEPROCESS process
)
4174 FIXME("stub: %p\n", process
);
4176 return STATUS_NOT_IMPLEMENTED
;
4179 /*********************************************************************
4180 * PsReleaseProcessExitSynchronization (NTOSKRNL.@)
4182 void WINAPI
PsReleaseProcessExitSynchronization(PEPROCESS process
)
4184 FIXME("stub: %p\n", process
);
4187 typedef struct _EX_PUSH_LOCK_WAIT_BLOCK
*PEX_PUSH_LOCK_WAIT_BLOCK
;
4188 /*********************************************************************
4189 * ExfUnblockPushLock (NTOSKRNL.@)
4191 DEFINE_FASTCALL_WRAPPER( ExfUnblockPushLock
, 8 )
4192 void FASTCALL
ExfUnblockPushLock( EX_PUSH_LOCK
*lock
, PEX_PUSH_LOCK_WAIT_BLOCK block
)
4194 FIXME( "stub: %p, %p\n", lock
, block
);
4197 /*********************************************************************
4198 * FsRtlRegisterFileSystemFilterCallbacks (NTOSKRNL.@)
4200 NTSTATUS WINAPI
FsRtlRegisterFileSystemFilterCallbacks( DRIVER_OBJECT
*object
, PFS_FILTER_CALLBACKS callbacks
)
4202 FIXME("stub: %p %p\n", object
, callbacks
);
4203 return STATUS_NOT_IMPLEMENTED
;
4206 /*********************************************************************
4207 * SeSinglePrivilegeCheck (NTOSKRNL.@)
4209 BOOLEAN WINAPI
SeSinglePrivilegeCheck(LUID privilege
, KPROCESSOR_MODE mode
)
4212 if (!once
++) FIXME("stub: %08lx%08lx %u\n", privilege
.HighPart
, privilege
.LowPart
, mode
);
4216 /*********************************************************************
4217 * SePrivilegeCheck (NTOSKRNL.@)
4219 BOOLEAN WINAPI
SePrivilegeCheck(PRIVILEGE_SET
*privileges
, SECURITY_SUBJECT_CONTEXT
*context
, KPROCESSOR_MODE mode
)
4221 FIXME("stub: %p %p %u\n", privileges
, context
, mode
);
4225 /*********************************************************************
4226 * SeLocateProcessImageName (NTOSKRNL.@)
4228 NTSTATUS WINAPI
SeLocateProcessImageName(PEPROCESS process
, UNICODE_STRING
**image_name
)
4230 FIXME("stub: %p %p\n", process
, image_name
);
4231 if (image_name
) *image_name
= NULL
;
4232 return STATUS_NOT_IMPLEMENTED
;
4235 /*********************************************************************
4236 * KeFlushQueuedDpcs (NTOSKRNL.@)
4238 void WINAPI
KeFlushQueuedDpcs(void)
4243 /*********************************************************************
4244 * DbgQueryDebugFilterState (NTOSKRNL.@)
4246 NTSTATUS WINAPI
DbgQueryDebugFilterState(ULONG component
, ULONG level
)
4248 FIXME("stub: %ld %ld\n", component
, level
);
4249 return STATUS_NOT_IMPLEMENTED
;
4252 /*********************************************************************
4253 * PsGetProcessWow64Process (NTOSKRNL.@)
4255 PVOID WINAPI
PsGetProcessWow64Process(PEPROCESS process
)
4257 FIXME("stub: %p\n", process
);
4261 /*********************************************************************
4262 * MmCopyVirtualMemory (NTOSKRNL.@)
4264 NTSTATUS WINAPI
MmCopyVirtualMemory(PEPROCESS fromprocess
, void *fromaddress
, PEPROCESS toprocess
,
4265 void *toaddress
, SIZE_T bufsize
, KPROCESSOR_MODE mode
,
4268 FIXME("fromprocess %p, fromaddress %p, toprocess %p, toaddress %p, bufsize %Iu, mode %d, copied %p stub.\n",
4269 fromprocess
, fromaddress
, toprocess
, toaddress
, bufsize
, mode
, copied
);
4272 return STATUS_NOT_IMPLEMENTED
;
4275 /*********************************************************************
4276 * KeEnterGuardedRegion (NTOSKRNL.@)
4278 void WINAPI
KeEnterGuardedRegion(void)
4283 /*********************************************************************
4284 * KeLeaveGuardedRegion (NTOSKRNL.@)
4286 void WINAPI
KeLeaveGuardedRegion(void)
4291 static const WCHAR token_type_name
[] = {'T','o','k','e','n',0};
4293 static struct _OBJECT_TYPE token_type
=
4298 POBJECT_TYPE SeTokenObjectType
= &token_type
;
4300 /*************************************************************************
4301 * ExUuidCreate (NTOSKRNL.@)
4303 * Creates a 128bit UUID.
4307 * STATUS_SUCCESS if successful.
4308 * RPC_NT_UUID_LOCAL_ONLY if UUID is only locally unique.
4312 * Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
4313 * Truly Random or Pseudo-Random Numbers)
4315 NTSTATUS WINAPI
ExUuidCreate(UUID
*uuid
)
4317 RtlGenRandom(uuid
, sizeof(*uuid
));
4318 /* Clear the version bits and set the version (4) */
4319 uuid
->Data3
&= 0x0fff;
4320 uuid
->Data3
|= (4 << 12);
4321 /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
4322 * specified in RFC 4122, section 4.4.
4324 uuid
->Data4
[0] &= 0x3f;
4325 uuid
->Data4
[0] |= 0x80;
4327 TRACE("%s\n", debugstr_guid(uuid
));
4329 return STATUS_SUCCESS
;
4332 /***********************************************************************
4333 * ExSetTimerResolution (NTOSKRNL.EXE.@)
4335 ULONG WINAPI
ExSetTimerResolution(ULONG time
, BOOLEAN set_resolution
)
4337 FIXME("stub: %lu %d\n", time
, set_resolution
);
4338 return KeQueryTimeIncrement();
4341 /***********************************************************************
4342 * IoGetRequestorProcess (NTOSKRNL.EXE.@)
4344 PEPROCESS WINAPI
IoGetRequestorProcess(IRP
*irp
)
4346 TRACE("irp %p.\n", irp
);
4347 return irp
->Tail
.Overlay
.Thread
->kthread
.process
;
4351 /***********************************************************************
4352 * IoIs32bitProcess (NTOSKRNL.EXE.@)
4354 BOOLEAN WINAPI
IoIs32bitProcess(IRP
*irp
)
4356 TRACE("irp %p.\n", irp
);
4357 return irp
->Tail
.Overlay
.Thread
->kthread
.process
->wow64
;
4361 /***********************************************************************
4362 * RtlIsNtDdiVersionAvailable (NTOSKRNL.EXE.@)
4364 BOOLEAN WINAPI
RtlIsNtDdiVersionAvailable(ULONG version
)
4366 FIXME("stub: %ld\n", version
);
4370 BOOLEAN WINAPI
KdRefreshDebuggerNotPresent(void)
4374 return !KdDebuggerEnabled
;
4377 struct generic_call_dpc_context
4379 DEFERRED_REVERSE_BARRIER
*reverse_barrier
;
4380 PKDEFERRED_ROUTINE routine
;
4381 ULONG
*cpu_count_barrier
;
4384 ULONG current_barrier_flag
;
4385 LONG
*barrier_passed_count
;
4388 static void WINAPI
generic_call_dpc_callback(TP_CALLBACK_INSTANCE
*instance
, void *context
)
4390 struct generic_call_dpc_context
*c
= context
;
4391 GROUP_AFFINITY old
, new;
4393 TRACE("instance %p, context %p.\n", instance
, context
);
4395 NtQueryInformationThread(GetCurrentThread(), ThreadGroupInformation
,
4396 &old
, sizeof(old
), NULL
);
4398 memset(&new, 0, sizeof(new));
4400 new.Mask
= 1 << c
->cpu_index
;
4401 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &new, sizeof(new));
4403 TlsSetValue(dpc_call_tls_index
, context
);
4404 c
->routine((PKDPC
)0xdeadbeef, c
->context
, c
->cpu_count_barrier
, c
->reverse_barrier
);
4405 TlsSetValue(dpc_call_tls_index
, NULL
);
4406 NtSetInformationThread(GetCurrentThread(), ThreadGroupInformation
, &old
, sizeof(old
));
4409 void WINAPI
KeGenericCallDpc(PKDEFERRED_ROUTINE routine
, void *context
)
4411 ULONG cpu_count
= KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS
);
4412 static struct generic_call_dpc_context
*contexts
;
4413 DEFERRED_REVERSE_BARRIER reverse_barrier
;
4414 static ULONG last_cpu_count
;
4415 LONG barrier_passed_count
;
4416 ULONG cpu_count_barrier
;
4419 TRACE("routine %p, context %p.\n", routine
, context
);
4421 EnterCriticalSection(&dpc_call_cs
);
4425 if (!(dpc_call_tp
= CreateThreadpool(NULL
)))
4427 ERR("Could not create thread pool.\n");
4428 LeaveCriticalSection(&dpc_call_cs
);
4432 SetThreadpoolThreadMinimum(dpc_call_tp
, cpu_count
);
4433 SetThreadpoolThreadMaximum(dpc_call_tp
, cpu_count
);
4435 memset(&dpc_call_tpe
, 0, sizeof(dpc_call_tpe
));
4436 dpc_call_tpe
.Version
= 1;
4437 dpc_call_tpe
.Pool
= dpc_call_tp
;
4440 reverse_barrier
.Barrier
= cpu_count
;
4441 reverse_barrier
.TotalProcessors
= cpu_count
;
4442 cpu_count_barrier
= cpu_count
;
4446 if (last_cpu_count
< cpu_count
)
4448 static struct generic_call_dpc_context
*new_contexts
;
4449 if (!(new_contexts
= heap_realloc(contexts
, sizeof(*contexts
) * cpu_count
)))
4451 ERR("No memory.\n");
4452 LeaveCriticalSection(&dpc_call_cs
);
4455 contexts
= new_contexts
;
4456 SetThreadpoolThreadMinimum(dpc_call_tp
, cpu_count
);
4457 SetThreadpoolThreadMaximum(dpc_call_tp
, cpu_count
);
4460 else if (!(contexts
= heap_alloc(sizeof(*contexts
) * cpu_count
)))
4462 ERR("No memory.\n");
4463 LeaveCriticalSection(&dpc_call_cs
);
4467 memset(contexts
, 0, sizeof(*contexts
) * cpu_count
);
4468 last_cpu_count
= cpu_count
;
4469 barrier_passed_count
= 0;
4471 for (i
= 0; i
< cpu_count
; ++i
)
4473 contexts
[i
].reverse_barrier
= &reverse_barrier
;
4474 contexts
[i
].cpu_count_barrier
= &cpu_count_barrier
;
4475 contexts
[i
].routine
= routine
;
4476 contexts
[i
].context
= context
;
4477 contexts
[i
].cpu_index
= i
;
4478 contexts
[i
].barrier_passed_count
= &barrier_passed_count
;
4480 TrySubmitThreadpoolCallback(generic_call_dpc_callback
, &contexts
[i
], &dpc_call_tpe
);
4483 while (InterlockedCompareExchange((LONG
*)&cpu_count_barrier
, 0, 0))
4486 LeaveCriticalSection(&dpc_call_cs
);
4490 BOOLEAN WINAPI
KeSignalCallDpcSynchronize(void *barrier
)
4492 struct generic_call_dpc_context
*context
= TlsGetValue(dpc_call_tls_index
);
4493 DEFERRED_REVERSE_BARRIER
*b
= barrier
;
4494 LONG curr_flag
, comp
, done_value
;
4497 TRACE("barrier %p, context %p.\n", barrier
, context
);
4501 WARN("Called outside of DPC context.\n");
4505 context
->current_barrier_flag
^= 0x80000000;
4506 curr_flag
= context
->current_barrier_flag
;
4508 first
= !context
->cpu_index
;
4509 comp
= curr_flag
+ context
->cpu_index
;
4510 done_value
= curr_flag
+ b
->TotalProcessors
;
4513 InterlockedExchange((LONG
*)&b
->Barrier
, comp
);
4515 while (InterlockedCompareExchange((LONG
*)&b
->Barrier
, comp
+ 1, comp
) != done_value
)
4518 InterlockedIncrement(context
->barrier_passed_count
);
4520 while (first
&& InterlockedCompareExchange(context
->barrier_passed_count
, 0, b
->TotalProcessors
))
4526 void WINAPI
KeSignalCallDpcDone(void *barrier
)
4528 InterlockedDecrement((LONG
*)barrier
);
4531 void * WINAPI
PsGetProcessSectionBaseAddress(PEPROCESS process
)
4538 TRACE("process %p.\n", process
);
4540 if ((status
= ObOpenObjectByPointer(process
, 0, NULL
, PROCESS_ALL_ACCESS
, NULL
, KernelMode
, &h
)))
4542 WARN("Error opening process object, status %#lx.\n", status
);
4546 status
= NtReadVirtualMemory(h
, &process
->info
.PebBaseAddress
->ImageBaseAddress
,
4547 &image_base
, sizeof(image_base
), &size
);
4551 if (status
|| size
!= sizeof(image_base
))
4553 WARN("Error reading process memory, status %#lx, size %Iu.\n", status
, size
);
4557 TRACE("returning %p.\n", image_base
);
4561 void WINAPI
KeStackAttachProcess(KPROCESS
*process
, KAPC_STATE
*apc_state
)
4563 FIXME("process %p, apc_state %p stub.\n", process
, apc_state
);
4566 void WINAPI
KeUnstackDetachProcess(KAPC_STATE
*apc_state
)
4568 FIXME("apc_state %p stub.\n", apc_state
);
4571 NTSTATUS WINAPI
KdDisableDebugger(void)
4574 return STATUS_DEBUGGER_INACTIVE
;
4577 NTSTATUS WINAPI
KdEnableDebugger(void)
4580 return STATUS_DEBUGGER_INACTIVE
;
4583 KPROCESSOR_MODE WINAPI
ExGetPreviousMode(void)
4586 return PsIsSystemThread((PETHREAD
)KeGetCurrentThread()) ? KernelMode
: UserMode
;
4591 void WINAPI
KfRaiseIrql(KIRQL
new, KIRQL
*old
)
4593 FIXME("new %u old %p: stub.\n", new, old
);
4596 void WINAPI
KeLowerIrql(KIRQL
new)
4598 FIXME("new %u: stub.\n", new);
4603 typedef void (WINAPI
*PETW_CLASSIC_CALLBACK
)(
4604 const GUID
*guid
, UCHAR control_code
, void *enable_context
, void *callback_context
);
4606 NTSTATUS WINAPI
EtwRegisterClassicProvider(const GUID
*provider
, ULONG type
, PETW_CLASSIC_CALLBACK callback
,
4607 void *context
, REGHANDLE
*handle
)
4609 FIXME("provider %s, type %lu, enable_callback %p, context %p, handle %p\n", debugstr_guid(provider
), type
,
4610 callback
, context
, handle
);
4612 *handle
= 0xdeadbeef;
4613 return STATUS_SUCCESS
;
4616 NTSTATUS WINAPI
EtwUnregister(REGHANDLE handle
)
4618 FIXME("handle %I64x\n", handle
);
4619 return STATUS_SUCCESS
;
4622 /*****************************************************
4625 BOOL WINAPI
DllMain( HINSTANCE inst
, DWORD reason
, LPVOID reserved
)
4627 static void *handler
;
4628 LARGE_INTEGER count
;
4632 case DLL_PROCESS_ATTACH
:
4633 DisableThreadLibraryCalls( inst
);
4634 #if defined(__i386__) || defined(__x86_64__)
4635 handler
= RtlAddVectoredExceptionHandler( TRUE
, vectored_handler
);
4637 KeQueryTickCount( &count
); /* initialize the global KeTickCount */
4638 NtBuildNumber
= NtCurrentTeb()->Peb
->OSBuildNumber
;
4639 ntoskrnl_heap
= HeapCreate( HEAP_CREATE_ENABLE_EXECUTE
, 0, 0 );
4640 dpc_call_tls_index
= TlsAlloc();
4641 LdrRegisterDllNotification( 0, ldr_notify_callback
, NULL
, &ldr_notify_cookie
);
4643 case DLL_PROCESS_DETACH
:
4644 LdrUnregisterDllNotification( ldr_notify_cookie
);
4646 if (reserved
) break;
4649 CloseThreadpool(dpc_call_tp
);
4651 HeapDestroy( ntoskrnl_heap
);
4652 RtlRemoveVectoredExceptionHandler( handler
);