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