ntoskrnl.exe: Add stub for KeGetCurrentThread/PsGetCurrentThread.
[wine] / dlls / ntoskrnl.exe / ntoskrnl.c
1 /*
2  * ntoskrnl.exe implementation
3  *
4  * Copyright (C) 2007 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdarg.h>
25
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "windef.h"
32 #include "winternl.h"
33 #include "excpt.h"
34 #include "ddk/ntddk.h"
35 #include "wine/unicode.h"
36 #include "wine/server.h"
37 #include "wine/list.h"
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
41 WINE_DECLARE_DEBUG_CHANNEL(relay);
42
43 extern LONG CALLBACK vectored_handler( EXCEPTION_POINTERS *ptrs );
44
45 KSYSTEM_TIME KeTickCount = { 0, 0, 0 };
46
47 typedef struct _KSERVICE_TABLE_DESCRIPTOR
48 {
49     PULONG_PTR Base;
50     PULONG Count;
51     ULONG Limit;
52     PUCHAR Number;
53 } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
54
55 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[4] = { { 0 } };
56
57 typedef void (WINAPI *PCREATE_PROCESS_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
58 typedef void (WINAPI *PCREATE_THREAD_NOTIFY_ROUTINE)(HANDLE,HANDLE,BOOLEAN);
59
60 static struct list Irps = LIST_INIT(Irps);
61
62 struct IrpInstance
63 {
64     struct list entry;
65     IRP *irp;
66 };
67
68 #ifdef __i386__
69 #define DEFINE_FASTCALL1_ENTRYPOINT( name ) \
70     __ASM_STDCALL_FUNC( name, 4, \
71                        "popl %eax\n\t" \
72                        "pushl %ecx\n\t" \
73                        "pushl %eax\n\t" \
74                        "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(4))
75 #define DEFINE_FASTCALL2_ENTRYPOINT( name ) \
76     __ASM_STDCALL_FUNC( name, 8, \
77                        "popl %eax\n\t" \
78                        "pushl %edx\n\t" \
79                        "pushl %ecx\n\t" \
80                        "pushl %eax\n\t" \
81                        "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(8))
82 #define DEFINE_FASTCALL3_ENTRYPOINT( name ) \
83     __ASM_STDCALL_FUNC( name, 12, \
84                        "popl %eax\n\t" \
85                        "pushl %edx\n\t" \
86                        "pushl %ecx\n\t" \
87                        "pushl %eax\n\t" \
88                        "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(12))
89 #endif
90
91 static inline LPCSTR debugstr_us( const UNICODE_STRING *us )
92 {
93     if (!us) return "<null>";
94     return debugstr_wn( us->Buffer, us->Length / sizeof(WCHAR) );
95 }
96
97 static HANDLE get_device_manager(void)
98 {
99     static HANDLE device_manager;
100     HANDLE handle = 0, ret = device_manager;
101
102     if (!ret)
103     {
104         SERVER_START_REQ( create_device_manager )
105         {
106             req->access     = SYNCHRONIZE;
107             req->attributes = 0;
108             if (!wine_server_call( req )) handle = wine_server_ptr_handle( reply->handle );
109         }
110         SERVER_END_REQ;
111
112         if (!handle)
113         {
114             ERR( "failed to create the device manager\n" );
115             return 0;
116         }
117         if (!(ret = InterlockedCompareExchangePointer( &device_manager, handle, 0 )))
118             ret = handle;
119         else
120             NtClose( handle );  /* somebody beat us to it */
121     }
122     return ret;
123 }
124
125 /* process an ioctl request for a given device */
126 static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff, ULONG in_size,
127                                void *out_buff, ULONG *out_size )
128 {
129     IRP irp;
130     MDL mdl;
131     IO_STACK_LOCATION irpsp;
132     PDRIVER_DISPATCH dispatch = device->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];
133     NTSTATUS status;
134     LARGE_INTEGER count;
135
136     TRACE( "ioctl %x device %p in_size %u out_size %u\n", code, device, in_size, *out_size );
137
138     /* so we can spot things that we should initialize */
139     memset( &irp, 0x55, sizeof(irp) );
140     memset( &irpsp, 0x66, sizeof(irpsp) );
141     memset( &mdl, 0x77, sizeof(mdl) );
142
143     irp.RequestorMode = UserMode;
144     irp.AssociatedIrp.SystemBuffer = in_buff;
145     irp.UserBuffer = out_buff;
146     irp.MdlAddress = &mdl;
147     irp.Tail.Overlay.s.u.CurrentStackLocation = &irpsp;
148     irp.UserIosb = NULL;
149
150     irpsp.MajorFunction = IRP_MJ_DEVICE_CONTROL;
151     irpsp.Parameters.DeviceIoControl.OutputBufferLength = *out_size;
152     irpsp.Parameters.DeviceIoControl.InputBufferLength = in_size;
153     irpsp.Parameters.DeviceIoControl.IoControlCode = code;
154     irpsp.Parameters.DeviceIoControl.Type3InputBuffer = in_buff;
155     irpsp.DeviceObject = device;
156     irpsp.CompletionRoutine = NULL;
157
158     mdl.Next = NULL;
159     mdl.Size = 0;
160     mdl.StartVa = out_buff;
161     mdl.ByteCount = *out_size;
162     mdl.ByteOffset = 0;
163
164     device->CurrentIrp = &irp;
165
166     KeQueryTickCount( &count );  /* update the global KeTickCount */
167
168     if (TRACE_ON(relay))
169         DPRINTF( "%04x:Call driver dispatch %p (device=%p,irp=%p)\n",
170                  GetCurrentThreadId(), dispatch, device, &irp );
171
172     status = dispatch( device, &irp );
173
174     if (TRACE_ON(relay))
175         DPRINTF( "%04x:Ret  driver dispatch %p (device=%p,irp=%p) retval=%08x\n",
176                  GetCurrentThreadId(), dispatch, device, &irp, status );
177
178     *out_size = (irp.IoStatus.u.Status >= 0) ? irp.IoStatus.Information : 0;
179     return irp.IoStatus.u.Status;
180 }
181
182
183 /***********************************************************************
184  *           wine_ntoskrnl_main_loop   (Not a Windows API)
185  */
186 NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
187 {
188     HANDLE manager = get_device_manager();
189     obj_handle_t ioctl = 0;
190     NTSTATUS status = STATUS_SUCCESS;
191     ULONG code = 0;
192     void *in_buff, *out_buff = NULL;
193     DEVICE_OBJECT *device = NULL;
194     ULONG in_size = 4096, out_size = 0;
195     HANDLE handles[2];
196
197     if (!(in_buff = HeapAlloc( GetProcessHeap(), 0, in_size )))
198     {
199         ERR( "failed to allocate buffer\n" );
200         return STATUS_NO_MEMORY;
201     }
202
203     handles[0] = stop_event;
204     handles[1] = manager;
205
206     for (;;)
207     {
208         SERVER_START_REQ( get_next_device_request )
209         {
210             req->manager = wine_server_obj_handle( manager );
211             req->prev = ioctl;
212             req->status = status;
213             wine_server_add_data( req, out_buff, out_size );
214             wine_server_set_reply( req, in_buff, in_size );
215             if (!(status = wine_server_call( req )))
216             {
217                 code     = reply->code;
218                 ioctl    = reply->next;
219                 device   = wine_server_get_ptr( reply->user_ptr );
220                 in_size  = reply->in_size;
221                 out_size = reply->out_size;
222             }
223             else
224             {
225                 ioctl = 0; /* no previous ioctl */
226                 out_size = 0;
227                 in_size = reply->in_size;
228             }
229         }
230         SERVER_END_REQ;
231
232         switch(status)
233         {
234         case STATUS_SUCCESS:
235             HeapFree( GetProcessHeap(), 0, out_buff );
236             if (out_size) out_buff = HeapAlloc( GetProcessHeap(), 0, out_size );
237             else out_buff = NULL;
238             status = process_ioctl( device, code, in_buff, in_size, out_buff, &out_size );
239             break;
240         case STATUS_BUFFER_OVERFLOW:
241             HeapFree( GetProcessHeap(), 0, in_buff );
242             in_buff = HeapAlloc( GetProcessHeap(), 0, in_size );
243             /* restart with larger buffer */
244             break;
245         case STATUS_PENDING:
246             if (WaitForMultipleObjects( 2, handles, FALSE, INFINITE ) == WAIT_OBJECT_0)
247             {
248                 HeapFree( GetProcessHeap(), 0, in_buff );
249                 HeapFree( GetProcessHeap(), 0, out_buff );
250                 return STATUS_SUCCESS;
251             }
252             break;
253         }
254     }
255 }
256
257
258 /***********************************************************************
259  *           IoAllocateDriverObjectExtension  (NTOSKRNL.EXE.@)
260  */
261 NTSTATUS WINAPI IoAllocateDriverObjectExtension( PDRIVER_OBJECT DriverObject,
262                                                  PVOID ClientIdentificationAddress,
263                                                  ULONG DriverObjectExtensionSize,
264                                                  PVOID *DriverObjectExtension )
265 {
266     FIXME( "stub: %p, %p, %u, %p\n", DriverObject, ClientIdentificationAddress,
267             DriverObjectExtensionSize, DriverObjectExtension );
268     return STATUS_NOT_IMPLEMENTED;
269 }
270
271
272 /***********************************************************************
273  *           IoGetDriverObjectExtension  (NTOSKRNL.EXE.@)
274  */
275 PVOID WINAPI IoGetDriverObjectExtension( PDRIVER_OBJECT DriverObject,
276                                          PVOID ClientIdentificationAddress )
277 {
278     FIXME( "stub: %p, %p\n", DriverObject, ClientIdentificationAddress );
279     return NULL;
280 }
281
282
283 /***********************************************************************
284  *           IoInitializeIrp  (NTOSKRNL.EXE.@)
285  */
286 void WINAPI IoInitializeIrp( IRP *irp, USHORT size, CCHAR stack_size )
287 {
288     TRACE( "%p, %u, %d\n", irp, size, stack_size );
289
290     RtlZeroMemory( irp, size );
291
292     irp->Type = IO_TYPE_IRP;
293     irp->Size = size;
294     InitializeListHead( &irp->ThreadListEntry );
295     irp->StackCount = stack_size;
296     irp->CurrentLocation = stack_size + 1;
297     irp->Tail.Overlay.s.u.CurrentStackLocation =
298             (PIO_STACK_LOCATION)(irp + 1) + stack_size;
299 }
300
301
302 /***********************************************************************
303  *           IoInitializeTimer   (NTOSKRNL.EXE.@)
304  */
305 NTSTATUS WINAPI IoInitializeTimer(PDEVICE_OBJECT DeviceObject,
306                                   PIO_TIMER_ROUTINE TimerRoutine,
307                                   PVOID Context)
308 {
309     FIXME( "stub: %p, %p, %p\n", DeviceObject, TimerRoutine, Context );
310     return STATUS_NOT_IMPLEMENTED;
311 }
312
313
314 /***********************************************************************
315  *           IoStartTimer   (NTOSKRNL.EXE.@)
316  */
317 void WINAPI IoStartTimer(PDEVICE_OBJECT DeviceObject)
318 {
319     FIXME( "stub: %p\n", DeviceObject );
320 }
321
322
323 /***********************************************************************
324  *           IoAllocateIrp  (NTOSKRNL.EXE.@)
325  */
326 PIRP WINAPI IoAllocateIrp( CCHAR stack_size, BOOLEAN charge_quota )
327 {
328     SIZE_T size;
329     PIRP irp;
330
331     TRACE( "%d, %d\n", stack_size, charge_quota );
332
333     size = sizeof(IRP) + stack_size * sizeof(IO_STACK_LOCATION);
334     irp = ExAllocatePool( NonPagedPool, size );
335     if (irp == NULL)
336         return NULL;
337     IoInitializeIrp( irp, size, stack_size );
338     irp->AllocationFlags = IRP_ALLOCATED_FIXED_SIZE;
339     if (charge_quota)
340         irp->AllocationFlags |= IRP_LOOKASIDE_ALLOCATION;
341     return irp;
342 }
343
344
345 /***********************************************************************
346  *           IoFreeIrp  (NTOSKRNL.EXE.@)
347  */
348 void WINAPI IoFreeIrp( IRP *irp )
349 {
350     TRACE( "%p\n", irp );
351
352     ExFreePool( irp );
353 }
354
355
356 /***********************************************************************
357  *           IoAllocateErrorLogEntry  (NTOSKRNL.EXE.@)
358  */
359 PVOID WINAPI IoAllocateErrorLogEntry( PVOID IoObject, UCHAR EntrySize )
360 {
361     FIXME( "stub: %p, %u\n", IoObject, EntrySize );
362     return NULL;
363 }
364
365
366 /***********************************************************************
367  *           IoAllocateMdl  (NTOSKRNL.EXE.@)
368  */
369 PMDL WINAPI IoAllocateMdl( PVOID VirtualAddress, ULONG Length, BOOLEAN SecondaryBuffer, BOOLEAN ChargeQuota, PIRP Irp )
370 {
371     FIXME( "stub: %p, %u, %i, %i, %p\n", VirtualAddress, Length, SecondaryBuffer, ChargeQuota, Irp );
372     return NULL;
373 }
374
375
376 /***********************************************************************
377  *           IoAllocateWorkItem  (NTOSKRNL.EXE.@)
378  */
379 PIO_WORKITEM WINAPI IoAllocateWorkItem( PDEVICE_OBJECT DeviceObject )
380 {
381     FIXME( "stub: %p\n", DeviceObject );
382     return NULL;
383 }
384
385
386 /***********************************************************************
387  *           IoAttachDeviceToDeviceStack  (NTOSKRNL.EXE.@)
388  */
389 PDEVICE_OBJECT WINAPI IoAttachDeviceToDeviceStack( DEVICE_OBJECT *source,
390                                                    DEVICE_OBJECT *target )
391 {
392     TRACE( "%p, %p\n", source, target );
393     target->AttachedDevice = source;
394     source->StackSize = target->StackSize + 1;
395     return target;
396 }
397
398
399 /***********************************************************************
400  *           IoBuildDeviceIoControlRequest  (NTOSKRNL.EXE.@)
401  */
402 PIRP WINAPI IoBuildDeviceIoControlRequest( ULONG IoControlCode,
403                                            PDEVICE_OBJECT DeviceObject,
404                                            PVOID InputBuffer,
405                                            ULONG InputBufferLength,
406                                            PVOID OutputBuffer,
407                                            ULONG OutputBufferLength,
408                                            BOOLEAN InternalDeviceIoControl,
409                                            PKEVENT Event,
410                                            PIO_STATUS_BLOCK IoStatusBlock )
411 {
412     PIRP irp;
413     PIO_STACK_LOCATION irpsp;
414     struct IrpInstance *instance;
415
416     TRACE( "%x, %p, %p, %u, %p, %u, %u, %p, %p\n",
417            IoControlCode, DeviceObject, InputBuffer, InputBufferLength,
418            OutputBuffer, OutputBufferLength, InternalDeviceIoControl,
419            Event, IoStatusBlock );
420
421     if (DeviceObject == NULL)
422         return NULL;
423
424     irp = IoAllocateIrp( DeviceObject->StackSize, FALSE );
425     if (irp == NULL)
426         return NULL;
427
428     instance = HeapAlloc( GetProcessHeap(), 0, sizeof(struct IrpInstance) );
429     if (instance == NULL)
430     {
431         IoFreeIrp( irp );
432         return NULL;
433     }
434     instance->irp = irp;
435     list_add_tail( &Irps, &instance->entry );
436
437     irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation - 1;
438     irpsp->MajorFunction = InternalDeviceIoControl ?
439             IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
440     irpsp->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
441     irp->UserIosb = IoStatusBlock;
442     irp->UserEvent = Event;
443
444     return irp;
445 }
446
447
448 /***********************************************************************
449  *           IoCreateDriver   (NTOSKRNL.EXE.@)
450  */
451 NTSTATUS WINAPI IoCreateDriver( UNICODE_STRING *name, PDRIVER_INITIALIZE init )
452 {
453     DRIVER_OBJECT *driver;
454     DRIVER_EXTENSION *extension;
455     NTSTATUS status;
456
457     if (!(driver = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
458                                     sizeof(*driver) + sizeof(*extension) )))
459         return STATUS_NO_MEMORY;
460
461     if ((status = RtlDuplicateUnicodeString( 1, name, &driver->DriverName )))
462     {
463         RtlFreeHeap( GetProcessHeap(), 0, driver );
464         return status;
465     }
466
467     extension = (DRIVER_EXTENSION *)(driver + 1);
468     driver->Size            = sizeof(*driver);
469     driver->DriverInit      = init;
470     driver->DriverExtension = extension;
471     extension->DriverObject   = driver;
472     extension->ServiceKeyName = driver->DriverName;
473
474     status = driver->DriverInit( driver, name );
475
476     if (status)
477     {
478         RtlFreeUnicodeString( &driver->DriverName );
479         RtlFreeHeap( GetProcessHeap(), 0, driver );
480     }
481     return status;
482 }
483
484
485 /***********************************************************************
486  *           IoDeleteDriver   (NTOSKRNL.EXE.@)
487  */
488 void WINAPI IoDeleteDriver( DRIVER_OBJECT *driver )
489 {
490     RtlFreeUnicodeString( &driver->DriverName );
491     RtlFreeHeap( GetProcessHeap(), 0, driver );
492 }
493
494
495 /***********************************************************************
496  *           IoCreateDevice   (NTOSKRNL.EXE.@)
497  */
498 NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size,
499                                 UNICODE_STRING *name, DEVICE_TYPE type,
500                                 ULONG characteristics, BOOLEAN exclusive,
501                                 DEVICE_OBJECT **ret_device )
502 {
503     NTSTATUS status;
504     DEVICE_OBJECT *device;
505     HANDLE handle = 0;
506     HANDLE manager = get_device_manager();
507
508     TRACE( "(%p, %u, %s, %u, %x, %u, %p)\n",
509            driver, ext_size, debugstr_us(name), type, characteristics, exclusive, ret_device );
510
511     if (!(device = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*device) + ext_size )))
512         return STATUS_NO_MEMORY;
513
514     SERVER_START_REQ( create_device )
515     {
516         req->access     = 0;
517         req->attributes = 0;
518         req->rootdir    = 0;
519         req->manager    = wine_server_obj_handle( manager );
520         req->user_ptr   = wine_server_client_ptr( device );
521         if (name) wine_server_add_data( req, name->Buffer, name->Length );
522         if (!(status = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle );
523     }
524     SERVER_END_REQ;
525
526     if (status == STATUS_SUCCESS)
527     {
528         device->DriverObject    = driver;
529         device->DeviceExtension = device + 1;
530         device->DeviceType      = type;
531         device->StackSize       = 1;
532         device->Reserved        = handle;
533
534         device->NextDevice   = driver->DeviceObject;
535         driver->DeviceObject = device;
536
537         *ret_device = device;
538     }
539     else HeapFree( GetProcessHeap(), 0, device );
540
541     return status;
542 }
543
544
545 /***********************************************************************
546  *           IoDeleteDevice   (NTOSKRNL.EXE.@)
547  */
548 void WINAPI IoDeleteDevice( DEVICE_OBJECT *device )
549 {
550     NTSTATUS status;
551
552     TRACE( "%p\n", device );
553
554     SERVER_START_REQ( delete_device )
555     {
556         req->handle = wine_server_obj_handle( device->Reserved );
557         status = wine_server_call( req );
558     }
559     SERVER_END_REQ;
560
561     if (status == STATUS_SUCCESS)
562     {
563         DEVICE_OBJECT **prev = &device->DriverObject->DeviceObject;
564         while (*prev && *prev != device) prev = &(*prev)->NextDevice;
565         if (*prev) *prev = (*prev)->NextDevice;
566         NtClose( device->Reserved );
567         HeapFree( GetProcessHeap(), 0, device );
568     }
569 }
570
571
572 /***********************************************************************
573  *           IoCreateSymbolicLink   (NTOSKRNL.EXE.@)
574  */
575 NTSTATUS WINAPI IoCreateSymbolicLink( UNICODE_STRING *name, UNICODE_STRING *target )
576 {
577     HANDLE handle;
578     OBJECT_ATTRIBUTES attr;
579
580     attr.Length                   = sizeof(attr);
581     attr.RootDirectory            = 0;
582     attr.ObjectName               = name;
583     attr.Attributes               = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
584     attr.SecurityDescriptor       = NULL;
585     attr.SecurityQualityOfService = NULL;
586
587     TRACE( "%s -> %s\n", debugstr_us(name), debugstr_us(target) );
588     /* FIXME: store handle somewhere */
589     return NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, target );
590 }
591
592
593 /***********************************************************************
594  *           IoDeleteSymbolicLink   (NTOSKRNL.EXE.@)
595  */
596 NTSTATUS WINAPI IoDeleteSymbolicLink( UNICODE_STRING *name )
597 {
598     HANDLE handle;
599     OBJECT_ATTRIBUTES attr;
600     NTSTATUS status;
601
602     attr.Length                   = sizeof(attr);
603     attr.RootDirectory            = 0;
604     attr.ObjectName               = name;
605     attr.Attributes               = OBJ_CASE_INSENSITIVE;
606     attr.SecurityDescriptor       = NULL;
607     attr.SecurityQualityOfService = NULL;
608
609     if (!(status = NtOpenSymbolicLinkObject( &handle, 0, &attr )))
610     {
611         SERVER_START_REQ( unlink_object )
612         {
613             req->handle = wine_server_obj_handle( handle );
614             status = wine_server_call( req );
615         }
616         SERVER_END_REQ;
617         NtClose( handle );
618     }
619     return status;
620 }
621
622
623 /***********************************************************************
624  *           IoGetDeviceObjectPointer   (NTOSKRNL.EXE.@)
625  */
626 NTSTATUS  WINAPI IoGetDeviceObjectPointer( UNICODE_STRING *name, ACCESS_MASK access, PFILE_OBJECT *file, PDEVICE_OBJECT *device )
627 {
628     FIXME( "stub: %s %x %p %p\n", debugstr_us(name), access, file, device );
629     return STATUS_NOT_IMPLEMENTED;
630 }
631
632
633 /***********************************************************************
634  *           IofCallDriver   (NTOSKRNL.EXE.@)
635  */
636 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
637 DEFINE_FASTCALL2_ENTRYPOINT( IofCallDriver )
638 NTSTATUS WINAPI __regs_IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
639 #else
640 NTSTATUS WINAPI IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
641 #endif
642 {
643     PDRIVER_DISPATCH dispatch;
644     IO_STACK_LOCATION *irpsp;
645     NTSTATUS status;
646
647     TRACE( "%p %p\n", device, irp );
648
649     --irp->CurrentLocation;
650     irpsp = --irp->Tail.Overlay.s.u.CurrentStackLocation;
651     dispatch = device->DriverObject->MajorFunction[irpsp->MajorFunction];
652     status = dispatch( device, irp );
653
654     return status;
655 }
656
657
658 /***********************************************************************
659  *           IoGetRelatedDeviceObject    (NTOSKRNL.EXE.@)
660  */
661 PDEVICE_OBJECT WINAPI IoGetRelatedDeviceObject( PFILE_OBJECT obj )
662 {
663     FIXME( "stub: %p\n", obj );
664     return NULL;
665 }
666
667 static CONFIGURATION_INFORMATION configuration_information;
668
669 /***********************************************************************
670  *           IoGetConfigurationInformation    (NTOSKRNL.EXE.@)
671  */
672 PCONFIGURATION_INFORMATION WINAPI IoGetConfigurationInformation(void)
673 {
674     FIXME( "partial stub\n" );
675     /* FIXME: return actual devices on system */
676     return &configuration_information;
677 }
678
679
680 /***********************************************************************
681  *           IoQueryDeviceDescription    (NTOSKRNL.EXE.@)
682  */
683 NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE itype, PULONG bus, PCONFIGURATION_TYPE ctype,
684                                      PULONG cnum, PCONFIGURATION_TYPE ptype, PULONG pnum,
685                                      PIO_QUERY_DEVICE_ROUTINE callout, PVOID context)
686 {
687     FIXME( "(%p %p %p %p %p %p %p %p)\n", itype, bus, ctype, cnum, ptype, pnum, callout, context);
688     return STATUS_NOT_IMPLEMENTED;
689 }
690
691
692 /***********************************************************************
693  *           IoRegisterDriverReinitialization    (NTOSKRNL.EXE.@)
694  */
695 void WINAPI IoRegisterDriverReinitialization( PDRIVER_OBJECT obj, PDRIVER_REINITIALIZE reinit, PVOID context )
696 {
697     FIXME( "stub: %p %p %p\n", obj, reinit, context );
698 }
699
700
701 /***********************************************************************
702  *           IoRegisterShutdownNotification    (NTOSKRNL.EXE.@)
703  */
704 NTSTATUS WINAPI IoRegisterShutdownNotification( PDEVICE_OBJECT obj )
705 {
706     FIXME( "stub: %p\n", obj );
707     return STATUS_SUCCESS;
708 }
709
710
711 /***********************************************************************
712  *           IoReportResourceUsage    (NTOSKRNL.EXE.@)
713  */
714 NTSTATUS WINAPI IoReportResourceUsage(PUNICODE_STRING name, PDRIVER_OBJECT drv_obj, PCM_RESOURCE_LIST drv_list,
715                                       ULONG drv_size, PDRIVER_OBJECT dev_obj, PCM_RESOURCE_LIST dev_list,
716                                       ULONG dev_size, BOOLEAN overwrite, PBOOLEAN detected)
717 {
718     FIXME("(%s %p %p %u %p %p %u %d %p) stub\n", debugstr_w(name? name->Buffer : NULL),
719           drv_obj, drv_list, drv_size, dev_obj, dev_list, dev_size, overwrite, detected);
720     return STATUS_NOT_IMPLEMENTED;
721 }
722
723
724 /***********************************************************************
725  *           IofCompleteRequest   (NTOSKRNL.EXE.@)
726  */
727 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
728 DEFINE_FASTCALL2_ENTRYPOINT( IofCompleteRequest )
729 void WINAPI __regs_IofCompleteRequest( IRP *irp, UCHAR priority_boost )
730 #else
731 void WINAPI IofCompleteRequest( IRP *irp, UCHAR priority_boost )
732 #endif
733 {
734     IO_STACK_LOCATION *irpsp;
735     PIO_COMPLETION_ROUTINE routine;
736     IO_STATUS_BLOCK *iosb;
737     struct IrpInstance *instance;
738     NTSTATUS status, stat;
739     int call_flag = 0;
740
741     TRACE( "%p %u\n", irp, priority_boost );
742
743     iosb = irp->UserIosb;
744     status = irp->IoStatus.u.Status;
745     while (irp->CurrentLocation <= irp->StackCount)
746     {
747         irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation;
748         routine = irpsp->CompletionRoutine;
749         call_flag = 0;
750         /* FIXME: add SL_INVOKE_ON_CANCEL support */
751         if (routine)
752         {
753             if ((irpsp->Control & SL_INVOKE_ON_SUCCESS) && STATUS_SUCCESS == status)
754                 call_flag = 1;
755             if ((irpsp->Control & SL_INVOKE_ON_ERROR) && STATUS_SUCCESS != status)
756                 call_flag = 1;
757         }
758         ++irp->CurrentLocation;
759         ++irp->Tail.Overlay.s.u.CurrentStackLocation;
760         if (call_flag)
761         {
762             TRACE( "calling %p( %p, %p, %p )\n", routine,
763                     irpsp->DeviceObject, irp, irpsp->Context );
764             stat = routine( irpsp->DeviceObject, irp, irpsp->Context );
765             TRACE( "CompletionRoutine returned %x\n", stat );
766             if (STATUS_MORE_PROCESSING_REQUIRED == stat)
767                 return;
768         }
769     }
770     if (iosb && STATUS_SUCCESS == status)
771     {
772         iosb->u.Status = irp->IoStatus.u.Status;
773         iosb->Information = irp->IoStatus.Information;
774     }
775     LIST_FOR_EACH_ENTRY( instance, &Irps, struct IrpInstance, entry )
776     {
777         if (instance->irp == irp)
778         {
779             list_remove( &instance->entry );
780             HeapFree( GetProcessHeap(), 0, instance );
781             IoFreeIrp( irp );
782             break;
783         }
784     }
785 }
786
787
788 /***********************************************************************
789  *           InterlockedCompareExchange   (NTOSKRNL.EXE.@)
790  */
791 #ifdef DEFINE_FASTCALL3_ENTRYPOINT
792 DEFINE_FASTCALL3_ENTRYPOINT( NTOSKRNL_InterlockedCompareExchange )
793 LONG WINAPI __regs_NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
794 #else
795 LONG WINAPI NTOSKRNL_InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
796 #endif
797 {
798     return InterlockedCompareExchange( dest, xchg, compare );
799 }
800
801
802 /***********************************************************************
803  *           InterlockedDecrement   (NTOSKRNL.EXE.@)
804  */
805 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
806 DEFINE_FASTCALL1_ENTRYPOINT( NTOSKRNL_InterlockedDecrement )
807 LONG WINAPI __regs_NTOSKRNL_InterlockedDecrement( LONG volatile *dest )
808 #else
809 LONG WINAPI NTOSKRNL_InterlockedDecrement( LONG volatile *dest )
810 #endif
811 {
812     return InterlockedDecrement( dest );
813 }
814
815
816 /***********************************************************************
817  *           InterlockedExchange   (NTOSKRNL.EXE.@)
818  */
819 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
820 DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedExchange )
821 LONG WINAPI __regs_NTOSKRNL_InterlockedExchange( LONG volatile *dest, LONG val )
822 #else
823 LONG WINAPI NTOSKRNL_InterlockedExchange( LONG volatile *dest, LONG val )
824 #endif
825 {
826     return InterlockedExchange( dest, val );
827 }
828
829
830 /***********************************************************************
831  *           InterlockedExchangeAdd   (NTOSKRNL.EXE.@)
832  */
833 #ifdef DEFINE_FASTCALL2_ENTRYPOINT
834 DEFINE_FASTCALL2_ENTRYPOINT( NTOSKRNL_InterlockedExchangeAdd )
835 LONG WINAPI __regs_NTOSKRNL_InterlockedExchangeAdd( LONG volatile *dest, LONG incr )
836 #else
837 LONG WINAPI NTOSKRNL_InterlockedExchangeAdd( LONG volatile *dest, LONG incr )
838 #endif
839 {
840     return InterlockedExchangeAdd( dest, incr );
841 }
842
843
844 /***********************************************************************
845  *           InterlockedIncrement   (NTOSKRNL.EXE.@)
846  */
847 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
848 DEFINE_FASTCALL1_ENTRYPOINT( NTOSKRNL_InterlockedIncrement )
849 LONG WINAPI __regs_NTOSKRNL_InterlockedIncrement( LONG volatile *dest )
850 #else
851 LONG WINAPI NTOSKRNL_InterlockedIncrement( LONG volatile *dest )
852 #endif
853 {
854     return InterlockedIncrement( dest );
855 }
856
857
858 /***********************************************************************
859  *           ExAllocatePool   (NTOSKRNL.EXE.@)
860  */
861 PVOID WINAPI ExAllocatePool( POOL_TYPE type, SIZE_T size )
862 {
863     return ExAllocatePoolWithTag( type, size, 0 );
864 }
865
866
867 /***********************************************************************
868  *           ExAllocatePoolWithQuota   (NTOSKRNL.EXE.@)
869  */
870 PVOID WINAPI ExAllocatePoolWithQuota( POOL_TYPE type, SIZE_T size )
871 {
872     return ExAllocatePoolWithTag( type, size, 0 );
873 }
874
875
876 /***********************************************************************
877  *           ExAllocatePoolWithTag   (NTOSKRNL.EXE.@)
878  */
879 PVOID WINAPI ExAllocatePoolWithTag( POOL_TYPE type, SIZE_T size, ULONG tag )
880 {
881     /* FIXME: handle page alignment constraints */
882     void *ret = HeapAlloc( GetProcessHeap(), 0, size );
883     TRACE( "%lu pool %u -> %p\n", size, type, ret );
884     return ret;
885 }
886
887
888 /***********************************************************************
889  *           ExAllocatePoolWithQuotaTag   (NTOSKRNL.EXE.@)
890  */
891 PVOID WINAPI ExAllocatePoolWithQuotaTag( POOL_TYPE type, SIZE_T size, ULONG tag )
892 {
893     return ExAllocatePoolWithTag( type, size, tag );
894 }
895
896
897 /***********************************************************************
898  *           ExFreePool   (NTOSKRNL.EXE.@)
899  */
900 void WINAPI ExFreePool( void *ptr )
901 {
902     ExFreePoolWithTag( ptr, 0 );
903 }
904
905
906 /***********************************************************************
907  *           ExFreePoolWithTag   (NTOSKRNL.EXE.@)
908  */
909 void WINAPI ExFreePoolWithTag( void *ptr, ULONG tag )
910 {
911     TRACE( "%p\n", ptr );
912     HeapFree( GetProcessHeap(), 0, ptr );
913 }
914
915
916 /***********************************************************************
917  *           ExInitializeResourceLite   (NTOSKRNL.EXE.@)
918  */
919 NTSTATUS WINAPI ExInitializeResourceLite(PERESOURCE Resource)
920 {
921     FIXME( "stub: %p\n", Resource );
922     return STATUS_NOT_IMPLEMENTED;
923 }
924
925
926 /***********************************************************************
927  *           ExInitializeNPagedLookasideList   (NTOSKRNL.EXE.@)
928  */
929 void WINAPI ExInitializeNPagedLookasideList(PNPAGED_LOOKASIDE_LIST Lookaside,
930                                             PALLOCATE_FUNCTION Allocate,
931                                             PFREE_FUNCTION Free,
932                                             ULONG Flags,
933                                             SIZE_T Size,
934                                             ULONG Tag,
935                                             USHORT Depth)
936 {
937     FIXME( "stub: %p, %p, %p, %u, %lu, %u, %u\n", Lookaside, Allocate, Free, Flags, Size, Tag, Depth );
938 }
939
940
941 /***********************************************************************
942  *           ExInitializeZone   (NTOSKRNL.EXE.@)
943  */
944 NTSTATUS WINAPI ExInitializeZone(PZONE_HEADER Zone,
945                                  ULONG BlockSize,
946                                  PVOID InitialSegment,
947                                  ULONG InitialSegmentSize)
948 {
949     FIXME( "stub: %p, %u, %p, %u\n", Zone, BlockSize, InitialSegment, InitialSegmentSize );
950     return STATUS_NOT_IMPLEMENTED;
951 }
952
953 /***********************************************************************
954 *           FsRtlRegisterUncProvider   (NTOSKRNL.EXE.@)
955 */
956 NTSTATUS WINAPI FsRtlRegisterUncProvider(PHANDLE MupHandle, PUNICODE_STRING RedirDevName,
957                                          BOOLEAN MailslotsSupported)
958 {
959     FIXME("(%p %p %d): stub\n", MupHandle, RedirDevName, MailslotsSupported);
960     return STATUS_NOT_IMPLEMENTED;
961 }
962
963 /***********************************************************************
964  *           KeGetCurrentThread / PsGetCurrentThread   (NTOSKRNL.EXE.@)
965  */
966 PRKTHREAD WINAPI KeGetCurrentThread(void)
967 {
968     FIXME("() stub\n");
969     return NULL;
970 }
971
972 /***********************************************************************
973  *           KeInitializeEvent   (NTOSKRNL.EXE.@)
974  */
975 void WINAPI KeInitializeEvent( PRKEVENT Event, EVENT_TYPE Type, BOOLEAN State )
976 {
977     FIXME( "stub: %p %d %d\n", Event, Type, State );
978 }
979
980
981  /***********************************************************************
982  *           KeInitializeMutex   (NTOSKRNL.EXE.@)
983  */
984 void WINAPI KeInitializeMutex(PRKMUTEX Mutex, ULONG Level)
985 {
986     FIXME( "stub: %p, %u\n", Mutex, Level );
987 }
988
989
990 /***********************************************************************
991  *           KeInitializeSemaphore   (NTOSKRNL.EXE.@)
992  */
993 void WINAPI KeInitializeSemaphore( PRKSEMAPHORE Semaphore, LONG Count, LONG Limit )
994 {
995     FIXME( "(%p %d %d) stub\n", Semaphore , Count, Limit );
996 }
997
998
999 /***********************************************************************
1000  *           KeInitializeSpinLock   (NTOSKRNL.EXE.@)
1001  */
1002 void WINAPI KeInitializeSpinLock( PKSPIN_LOCK SpinLock )
1003 {
1004     FIXME( "stub: %p\n", SpinLock );
1005 }
1006
1007
1008 /***********************************************************************
1009  *           KeInitializeTimerEx   (NTOSKRNL.EXE.@)
1010  */
1011 void WINAPI KeInitializeTimerEx( PKTIMER Timer, TIMER_TYPE Type )
1012 {
1013     FIXME( "stub: %p %d\n", Timer, Type );
1014 }
1015
1016
1017 /***********************************************************************
1018  *           KeInitializeTimer   (NTOSKRNL.EXE.@)
1019  */
1020 void WINAPI KeInitializeTimer( PKTIMER Timer )
1021 {
1022     KeInitializeTimerEx(Timer, NotificationTimer);
1023 }
1024
1025
1026 /**********************************************************************
1027  *           KeQueryActiveProcessors   (NTOSKRNL.EXE.@)
1028  *
1029  * Return the active Processors as bitmask
1030  *
1031  * RETURNS
1032  *   active Processors as bitmask
1033  *
1034  */
1035 KAFFINITY WINAPI KeQueryActiveProcessors( void )
1036 {
1037     DWORD_PTR AffinityMask;
1038
1039     GetProcessAffinityMask( GetCurrentProcess(), &AffinityMask, NULL);
1040     return AffinityMask;
1041 }
1042
1043
1044 /**********************************************************************
1045  *           KeQueryInterruptTime   (NTOSKRNL.EXE.@)
1046  *
1047  * Return the interrupt time count
1048  *
1049  */
1050 ULONGLONG WINAPI KeQueryInterruptTime( void )
1051 {
1052     LARGE_INTEGER totaltime;
1053
1054     KeQueryTickCount(&totaltime);
1055     return totaltime.QuadPart;
1056 }
1057
1058
1059 /***********************************************************************
1060  *           KeQuerySystemTime   (NTOSKRNL.EXE.@)
1061  */
1062 void WINAPI KeQuerySystemTime( LARGE_INTEGER *time )
1063 {
1064     NtQuerySystemTime( time );
1065 }
1066
1067
1068 /***********************************************************************
1069  *           KeQueryTickCount   (NTOSKRNL.EXE.@)
1070  */
1071 void WINAPI KeQueryTickCount( LARGE_INTEGER *count )
1072 {
1073     count->QuadPart = NtGetTickCount();
1074     /* update the global variable too */
1075     KeTickCount.LowPart   = count->u.LowPart;
1076     KeTickCount.High1Time = count->u.HighPart;
1077     KeTickCount.High2Time = count->u.HighPart;
1078 }
1079
1080
1081 /***********************************************************************
1082  *           KeReleaseSemaphore   (NTOSKRNL.EXE.@)
1083  */
1084 LONG WINAPI KeReleaseSemaphore( PRKSEMAPHORE Semaphore, KPRIORITY Increment,
1085                                 LONG Adjustment, BOOLEAN Wait )
1086 {
1087     FIXME("(%p %d %d %d) stub\n", Semaphore, Increment, Adjustment, Wait );
1088     return 0;
1089 }
1090
1091
1092 /***********************************************************************
1093  *           KeQueryTimeIncrement   (NTOSKRNL.EXE.@)
1094  */
1095 ULONG WINAPI KeQueryTimeIncrement(void)
1096 {
1097     return 10000;
1098 }
1099
1100
1101 /***********************************************************************
1102  *           KeSetPriorityThread   (NTOSKRNL.EXE.@)
1103  */
1104 KPRIORITY WINAPI KeSetPriorityThread( PKTHREAD Thread, KPRIORITY Priority )
1105 {
1106     FIXME("(%p %d)\n", Thread, Priority);
1107     return Priority;
1108 }
1109
1110
1111 /***********************************************************************
1112  *           KeWaitForSingleObject   (NTOSKRNL.EXE.@)
1113  */
1114 NTSTATUS WINAPI KeWaitForSingleObject(PVOID Object,
1115                                       KWAIT_REASON WaitReason,
1116                                       KPROCESSOR_MODE WaitMode,
1117                                       BOOLEAN Alertable,
1118                                       PLARGE_INTEGER Timeout)
1119 {
1120     FIXME( "stub: %p, %d, %d, %d, %p\n", Object, WaitReason, WaitMode, Alertable, Timeout );
1121     return STATUS_NOT_IMPLEMENTED;
1122 }
1123
1124 /***********************************************************************
1125  *           IoRegisterFileSystem   (NTOSKRNL.EXE.@)
1126  */
1127 VOID WINAPI IoRegisterFileSystem(PDEVICE_OBJECT DeviceObject)
1128 {
1129     FIXME("(%p): stub\n", DeviceObject);
1130 }
1131
1132 /***********************************************************************
1133 *           IoUnregisterFileSystem   (NTOSKRNL.EXE.@)
1134 */
1135 VOID WINAPI IoUnregisterFileSystem(PDEVICE_OBJECT DeviceObject)
1136 {
1137     FIXME("(%p): stub\n", DeviceObject);
1138 }
1139
1140 /***********************************************************************
1141  *           MmAllocateNonCachedMemory   (NTOSKRNL.EXE.@)
1142  */
1143 PVOID WINAPI MmAllocateNonCachedMemory( SIZE_T size )
1144 {
1145     TRACE( "%lu\n", size );
1146     return VirtualAlloc( NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE|PAGE_NOCACHE );
1147 }
1148
1149 /***********************************************************************
1150  *           MmAllocateContiguousMemory   (NTOSKRNL.EXE.@)
1151  */
1152 PVOID WINAPI MmAllocateContiguousMemory( SIZE_T size, PHYSICAL_ADDRESS highest_valid_address )
1153 {
1154     FIXME( "%lu, %s stub\n", size, wine_dbgstr_longlong(highest_valid_address.QuadPart) );
1155     return NULL;
1156 }
1157
1158 /***********************************************************************
1159  *           MmAllocatePagesForMdl   (NTOSKRNL.EXE.@)
1160  */
1161 PMDL WINAPI MmAllocatePagesForMdl(PHYSICAL_ADDRESS lowaddress, PHYSICAL_ADDRESS highaddress,
1162                                   PHYSICAL_ADDRESS skipbytes, SIZE_T size)
1163 {
1164     FIXME("%s %s %s %lu: stub\n", wine_dbgstr_longlong(lowaddress.QuadPart), wine_dbgstr_longlong(highaddress.QuadPart),
1165                                   wine_dbgstr_longlong(skipbytes.QuadPart), size);
1166     return NULL;
1167 }
1168
1169 /***********************************************************************
1170  *           MmFreeNonCachedMemory   (NTOSKRNL.EXE.@)
1171  */
1172 void WINAPI MmFreeNonCachedMemory( void *addr, SIZE_T size )
1173 {
1174     TRACE( "%p %lu\n", addr, size );
1175     VirtualFree( addr, 0, MEM_RELEASE );
1176 }
1177
1178 /***********************************************************************
1179  *           MmIsAddressValid   (NTOSKRNL.EXE.@)
1180  *
1181  * Check if the process can access the virtual address without a pagefault
1182  *
1183  * PARAMS
1184  *  VirtualAddress [I] Address to check
1185  *
1186  * RETURNS
1187  *  Failure: FALSE
1188  *  Success: TRUE  (Accessing the Address works without a Pagefault)
1189  *
1190  */
1191 BOOLEAN WINAPI MmIsAddressValid(PVOID VirtualAddress)
1192 {
1193     TRACE("(%p)\n", VirtualAddress);
1194     return !IsBadWritePtr(VirtualAddress, 1);
1195 }
1196
1197 /***********************************************************************
1198  *           MmPageEntireDriver   (NTOSKRNL.EXE.@)
1199  */
1200 PVOID WINAPI MmPageEntireDriver(PVOID AddrInSection)
1201 {
1202     TRACE("%p\n", AddrInSection);
1203     return AddrInSection;
1204 }
1205
1206 /***********************************************************************
1207  *           MmResetDriverPaging   (NTOSKRNL.EXE.@)
1208  */
1209 void WINAPI MmResetDriverPaging(PVOID AddrInSection)
1210 {
1211     TRACE("%p\n", AddrInSection);
1212 }
1213
1214 /***********************************************************************
1215  *           ObfReferenceObject   (NTOSKRNL.EXE.@)
1216  */
1217 VOID WINAPI ObfReferenceObject(PVOID Object)
1218 {
1219     FIXME("(%p): stub\n", Object);
1220 }
1221
1222  /***********************************************************************
1223  *           ObReferenceObjectByHandle    (NTOSKRNL.EXE.@)
1224  */
1225 NTSTATUS WINAPI ObReferenceObjectByHandle( HANDLE obj, ACCESS_MASK access,
1226                                            POBJECT_TYPE type,
1227                                            KPROCESSOR_MODE mode, PVOID* ptr,
1228                                            POBJECT_HANDLE_INFORMATION info)
1229 {
1230     FIXME( "stub: %p %x %p %d %p %p\n", obj, access, type, mode, ptr, info);
1231     return STATUS_NOT_IMPLEMENTED;
1232 }
1233
1234
1235 /***********************************************************************
1236  *           ObfDereferenceObject   (NTOSKRNL.EXE.@)
1237  */
1238 #ifdef DEFINE_FASTCALL1_ENTRYPOINT
1239 DEFINE_FASTCALL1_ENTRYPOINT( ObfDereferenceObject )
1240 void WINAPI __regs_ObfDereferenceObject( VOID *obj )
1241 #else
1242 void WINAPI ObfDereferenceObject( VOID *obj )
1243 #endif
1244 {
1245     FIXME( "stub: %p\n", obj );
1246 }
1247
1248
1249 /***********************************************************************
1250  *           PsCreateSystemThread   (NTOSKRNL.EXE.@)
1251  */
1252 NTSTATUS WINAPI PsCreateSystemThread(PHANDLE ThreadHandle, ULONG DesiredAccess,
1253                                      POBJECT_ATTRIBUTES ObjectAttributes,
1254                                      HANDLE ProcessHandle, PCLIENT_ID ClientId,
1255                                      PKSTART_ROUTINE StartRoutine, PVOID StartContext)
1256 {
1257     if (!ProcessHandle) ProcessHandle = GetCurrentProcess();
1258     return RtlCreateUserThread(ProcessHandle, 0, FALSE, 0, 0,
1259                                0, StartRoutine, StartContext,
1260                                ThreadHandle, ClientId);
1261 }
1262
1263 /***********************************************************************
1264  *           PsGetCurrentProcessId   (NTOSKRNL.EXE.@)
1265  */
1266 HANDLE WINAPI PsGetCurrentProcessId(void)
1267 {
1268     return UlongToHandle(GetCurrentProcessId());  /* FIXME: not quite right... */
1269 }
1270
1271
1272 /***********************************************************************
1273  *           PsGetCurrentThreadId   (NTOSKRNL.EXE.@)
1274  */
1275 HANDLE WINAPI PsGetCurrentThreadId(void)
1276 {
1277     return UlongToHandle(GetCurrentThreadId());  /* FIXME: not quite right... */
1278 }
1279
1280
1281 /***********************************************************************
1282  *           PsGetVersion   (NTOSKRNL.EXE.@)
1283  */
1284 BOOLEAN WINAPI PsGetVersion(ULONG *major, ULONG *minor, ULONG *build, UNICODE_STRING *version )
1285 {
1286     RTL_OSVERSIONINFOEXW info;
1287
1288     info.dwOSVersionInfoSize = sizeof(info);
1289     RtlGetVersion( &info );
1290     if (major) *major = info.dwMajorVersion;
1291     if (minor) *minor = info.dwMinorVersion;
1292     if (build) *build = info.dwBuildNumber;
1293
1294     if (version)
1295     {
1296 #if 0  /* FIXME: GameGuard passes an uninitialized pointer in version->Buffer */
1297         size_t len = min( strlenW(info.szCSDVersion)*sizeof(WCHAR), version->MaximumLength );
1298         memcpy( version->Buffer, info.szCSDVersion, len );
1299         if (len < version->MaximumLength) version->Buffer[len / sizeof(WCHAR)] = 0;
1300         version->Length = len;
1301 #endif
1302     }
1303     return TRUE;
1304 }
1305
1306
1307 /***********************************************************************
1308  *           PsSetCreateProcessNotifyRoutine   (NTOSKRNL.EXE.@)
1309  */
1310 NTSTATUS WINAPI PsSetCreateProcessNotifyRoutine( PCREATE_PROCESS_NOTIFY_ROUTINE callback, BOOLEAN remove )
1311 {
1312     FIXME( "stub: %p %d\n", callback, remove );
1313     return STATUS_SUCCESS;
1314 }
1315
1316
1317 /***********************************************************************
1318  *           PsSetCreateThreadNotifyRoutine   (NTOSKRNL.EXE.@)
1319  */
1320 NTSTATUS WINAPI PsSetCreateThreadNotifyRoutine( PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
1321 {
1322     FIXME( "stub: %p\n", NotifyRoutine );
1323     return STATUS_SUCCESS;
1324 }
1325
1326
1327 /***********************************************************************
1328  *           PsTerminateSystemThread   (NTOSKRNL.EXE.@)
1329  */
1330 NTSTATUS WINAPI PsTerminateSystemThread(NTSTATUS ExitStatus)
1331 {
1332     FIXME( "stub: %u\n", ExitStatus );
1333     return STATUS_NOT_IMPLEMENTED;
1334 }
1335
1336
1337 /***********************************************************************
1338  *           MmGetSystemRoutineAddress   (NTOSKRNL.EXE.@)
1339  */
1340 PVOID WINAPI MmGetSystemRoutineAddress(PUNICODE_STRING SystemRoutineName)
1341 {
1342     HMODULE hMod;
1343     STRING routineNameA;
1344     PVOID pFunc = NULL;
1345
1346     static const WCHAR ntoskrnlW[] = {'n','t','o','s','k','r','n','l','.','e','x','e',0};
1347     static const WCHAR halW[] = {'h','a','l','.','d','l','l',0};
1348
1349     if (!SystemRoutineName) return NULL;
1350
1351     if (RtlUnicodeStringToAnsiString( &routineNameA, SystemRoutineName, TRUE ) == STATUS_SUCCESS)
1352     {
1353         /* We only support functions exported from ntoskrnl.exe or hal.dll */
1354         hMod = GetModuleHandleW( ntoskrnlW );
1355         pFunc = GetProcAddress( hMod, routineNameA.Buffer );
1356         if (!pFunc)
1357         {
1358            hMod = GetModuleHandleW( halW );
1359            if (hMod) pFunc = GetProcAddress( hMod, routineNameA.Buffer );
1360         }
1361         RtlFreeAnsiString( &routineNameA );
1362     }
1363
1364     TRACE( "%s -> %p\n", debugstr_us(SystemRoutineName), pFunc );
1365     return pFunc;
1366 }
1367
1368
1369 /***********************************************************************
1370  *           MmQuerySystemSize   (NTOSKRNL.EXE.@)
1371  */
1372 MM_SYSTEMSIZE WINAPI MmQuerySystemSize(void)
1373 {
1374     FIXME("stub\n");
1375     return MmLargeSystem;
1376 }
1377
1378
1379 /*****************************************************
1380  *           DllMain
1381  */
1382 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
1383 {
1384     static void *handler;
1385     LARGE_INTEGER count;
1386
1387     switch(reason)
1388     {
1389     case DLL_PROCESS_ATTACH:
1390         DisableThreadLibraryCalls( inst );
1391 #ifdef __i386__
1392         handler = RtlAddVectoredExceptionHandler( TRUE, vectored_handler );
1393 #endif
1394         KeQueryTickCount( &count );  /* initialize the global KeTickCount */
1395         break;
1396     case DLL_PROCESS_DETACH:
1397         RtlRemoveVectoredExceptionHandler( handler );
1398         break;
1399     }
1400     return TRUE;
1401 }