Sort entry points alphabetically.
[wine] / dlls / ntdll / nt.c
1 /*
2  * NT basis DLL
3  *
4  * This file contains the Nt* API functions of NTDLL.DLL.
5  * In the original ntdll.dll they all seem to just call int 0x2e (down to the NTOSKRNL)
6  *
7  * Copyright 1996-1998 Marcus Meissner
8  *
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.
13  *
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.
18  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include "wine/debug.h"
30 #include "wine/unicode.h"
31
32 #include "windef.h"
33 #include "winternl.h"
34 #include "ntdll_misc.h"
35 #include "wine/server.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
38
39 /* FIXME: fixed at 2005/2/22 */
40 static LONGLONG boottime = (LONGLONG)1275356510 * 100000000;
41
42 /*
43  *      Token
44  */
45
46 /******************************************************************************
47  *  NtDuplicateToken            [NTDLL.@]
48  *  ZwDuplicateToken            [NTDLL.@]
49  */
50 NTSTATUS WINAPI NtDuplicateToken(
51         IN HANDLE ExistingToken,
52         IN ACCESS_MASK DesiredAccess,
53         IN POBJECT_ATTRIBUTES ObjectAttributes,
54         IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
55         IN TOKEN_TYPE TokenType,
56         OUT PHANDLE NewToken)
57 {
58     NTSTATUS status;
59
60     TRACE("(%p,0x%08lx,%p,0x%08x,0x%08x,%p)\n",
61         ExistingToken, DesiredAccess, ObjectAttributes,
62         ImpersonationLevel, TokenType, NewToken);
63         dump_ObjectAttributes(ObjectAttributes);
64
65     SERVER_START_REQ( duplicate_token )
66     {
67         req->handle = ExistingToken;
68         req->access = DesiredAccess;
69         req->inherit = ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT);
70         req->primary = (TokenType == TokenPrimary);
71         req->impersonation_level = ImpersonationLevel;
72         status = wine_server_call( req );
73         if (!status) *NewToken = reply->new_handle;
74     }
75     SERVER_END_REQ;
76
77     return status;
78 }
79
80 /******************************************************************************
81  *  NtOpenProcessToken          [NTDLL.@]
82  *  ZwOpenProcessToken          [NTDLL.@]
83  */
84 NTSTATUS WINAPI NtOpenProcessToken(
85         HANDLE ProcessHandle,
86         DWORD DesiredAccess,
87         HANDLE *TokenHandle)
88 {
89     NTSTATUS ret;
90
91     TRACE("(%p,0x%08lx,%p)\n", ProcessHandle,DesiredAccess, TokenHandle);
92
93     SERVER_START_REQ( open_token )
94     {
95         req->handle = ProcessHandle;
96         req->flags  = 0;
97         ret = wine_server_call( req );
98         if (!ret) *TokenHandle = reply->token;
99     }
100     SERVER_END_REQ;
101
102     return ret;
103 }
104
105 /******************************************************************************
106  *  NtOpenThreadToken           [NTDLL.@]
107  *  ZwOpenThreadToken           [NTDLL.@]
108  */
109 NTSTATUS WINAPI NtOpenThreadToken(
110         HANDLE ThreadHandle,
111         DWORD DesiredAccess,
112         BOOLEAN OpenAsSelf,
113         HANDLE *TokenHandle)
114 {
115     NTSTATUS ret;
116
117     TRACE("(%p,0x%08lx,0x%08x,%p)\n",
118           ThreadHandle,DesiredAccess, OpenAsSelf, TokenHandle);
119
120     SERVER_START_REQ( open_token )
121     {
122         req->handle = ThreadHandle;
123         req->flags  = OPEN_TOKEN_THREAD;
124         if (OpenAsSelf) req->flags |= OPEN_TOKEN_AS_SELF;
125         ret = wine_server_call( req );
126         if (!ret) *TokenHandle = reply->token;
127     }
128     SERVER_END_REQ;
129
130     return ret;
131 }
132
133 /******************************************************************************
134  *  NtAdjustPrivilegesToken             [NTDLL.@]
135  *  ZwAdjustPrivilegesToken             [NTDLL.@]
136  *
137  * FIXME: parameters unsafe
138  */
139 NTSTATUS WINAPI NtAdjustPrivilegesToken(
140         IN HANDLE TokenHandle,
141         IN BOOLEAN DisableAllPrivileges,
142         IN PTOKEN_PRIVILEGES NewState,
143         IN DWORD BufferLength,
144         OUT PTOKEN_PRIVILEGES PreviousState,
145         OUT PDWORD ReturnLength)
146 {
147     NTSTATUS ret;
148
149     TRACE("(%p,0x%08x,%p,0x%08lx,%p,%p)\n",
150         TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength);
151
152     SERVER_START_REQ( adjust_token_privileges )
153     {
154         req->handle = TokenHandle;
155         req->disable_all = DisableAllPrivileges;
156         req->get_modified_state = (PreviousState != NULL);
157         if (!DisableAllPrivileges)
158         {
159             wine_server_add_data( req, &NewState->Privileges,
160                                   NewState->PrivilegeCount * sizeof(NewState->Privileges[0]) );
161         }
162         if (PreviousState && BufferLength >= FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ))
163             wine_server_set_reply( req, &PreviousState->Privileges,
164                                    BufferLength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) );
165         ret = wine_server_call( req );
166         if (PreviousState)
167         {
168             *ReturnLength = reply->len + FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges );
169             PreviousState->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES);
170         }
171     }
172     SERVER_END_REQ;
173
174     return ret;
175 }
176
177 /******************************************************************************
178 *  NtQueryInformationToken              [NTDLL.@]
179 *  ZwQueryInformationToken              [NTDLL.@]
180 *
181 * NOTES
182 *  Buffer for TokenUser:
183 *   0x00 TOKEN_USER the PSID field points to the SID
184 *   0x08 SID
185 *
186 */
187 NTSTATUS WINAPI NtQueryInformationToken(
188         HANDLE token,
189         DWORD tokeninfoclass,
190         LPVOID tokeninfo,
191         DWORD tokeninfolength,
192         LPDWORD retlen )
193 {
194     unsigned int len = 0;
195     NTSTATUS status = STATUS_SUCCESS;
196
197     TRACE("(%p,%ld,%p,%ld,%p)\n",
198           token,tokeninfoclass,tokeninfo,tokeninfolength,retlen);
199
200     switch (tokeninfoclass)
201     {
202     case TokenUser:
203         len = sizeof(TOKEN_USER) + sizeof(SID);
204         break;
205     case TokenGroups:
206         len = sizeof(TOKEN_GROUPS);
207         break;
208     case TokenOwner:
209         len = sizeof(TOKEN_OWNER) + sizeof(SID);
210         break;
211     case TokenPrimaryGroup:
212         len = sizeof(TOKEN_PRIMARY_GROUP);
213         break;
214     case TokenDefaultDacl:
215         len = sizeof(TOKEN_DEFAULT_DACL);
216         break;
217     case TokenSource:
218         len = sizeof(TOKEN_SOURCE);
219         break;
220     case TokenType:
221         len = sizeof (TOKEN_TYPE);
222         break;
223 #if 0
224     case TokenImpersonationLevel:
225     case TokenStatistics:
226 #endif /* 0 */
227     }
228
229     /* FIXME: what if retlen == NULL ? */
230     *retlen = len;
231
232     if (tokeninfolength < len)
233         return STATUS_BUFFER_TOO_SMALL;
234
235     switch (tokeninfoclass)
236     {
237     case TokenUser:
238         if( tokeninfo )
239         {
240             TOKEN_USER * tuser = tokeninfo;
241             PSID sid = (PSID) (tuser + 1);
242             SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
243             RtlInitializeSid(sid, &localSidAuthority, 1);
244             *(RtlSubAuthoritySid(sid, 0)) = SECURITY_INTERACTIVE_RID;
245             tuser->User.Sid = sid;
246         }
247         break;
248     case TokenGroups:
249         if (tokeninfo)
250         {
251             TOKEN_GROUPS *tgroups = tokeninfo;
252             SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
253
254             /* we need to show admin privileges ! */
255             tgroups->GroupCount = 1;
256             tgroups->Groups->Attributes = SE_GROUP_ENABLED;
257             RtlAllocateAndInitializeSid( &sid,
258                                          2,
259                                          SECURITY_BUILTIN_DOMAIN_RID,
260                                          DOMAIN_ALIAS_RID_ADMINS,
261                                          0, 0, 0, 0, 0, 0,
262                                          &(tgroups->Groups->Sid));
263         }
264         break;
265     case TokenPrimaryGroup:
266         if (tokeninfo)
267         {
268             TOKEN_PRIMARY_GROUP *tgroup = tokeninfo;
269             SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
270             RtlAllocateAndInitializeSid( &sid,
271                                          2,
272                                          SECURITY_BUILTIN_DOMAIN_RID,
273                                          DOMAIN_ALIAS_RID_ADMINS,
274                                          0, 0, 0, 0, 0, 0,
275                                          &(tgroup->PrimaryGroup));
276         }
277         break;
278     case TokenPrivileges:
279         SERVER_START_REQ( get_token_privileges )
280         {
281             TOKEN_PRIVILEGES *tpriv = tokeninfo;
282             req->handle = token;
283             if (tpriv && tokeninfolength > FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ))
284                 wine_server_set_reply( req, &tpriv->Privileges, tokeninfolength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) );
285             status = wine_server_call( req );
286             *retlen = FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) + reply->len;
287             if (tpriv) tpriv->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES);
288         }
289         SERVER_END_REQ;
290         break;
291     case TokenOwner:
292         if (tokeninfo)
293         {
294             TOKEN_OWNER *owner = tokeninfo;
295             PSID sid = (PSID) (owner + 1);
296             SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
297             RtlInitializeSid(sid, &localSidAuthority, 1);
298             *(RtlSubAuthoritySid(sid, 0)) = SECURITY_INTERACTIVE_RID;
299             owner->Owner = sid;
300         }
301         break;
302     default:
303         {
304             ERR("Unhandled Token Information class %ld!\n", tokeninfoclass);
305             return STATUS_NOT_IMPLEMENTED;
306         }
307     }
308     return status;
309 }
310
311 /******************************************************************************
312 *  NtSetInformationToken                [NTDLL.@]
313 *  ZwSetInformationToken                [NTDLL.@]
314 */
315 NTSTATUS WINAPI NtSetInformationToken(
316         HANDLE TokenHandle,
317         TOKEN_INFORMATION_CLASS TokenInformationClass,
318         PVOID TokenInformation,
319         ULONG TokenInformationLength)
320 {
321     FIXME("%p %d %p %lu\n", TokenHandle, TokenInformationClass,
322           TokenInformation, TokenInformationLength);
323     return STATUS_NOT_IMPLEMENTED;
324 }
325
326 /******************************************************************************
327 *  NtAdjustGroupsToken          [NTDLL.@]
328 *  ZwAdjustGroupsToken          [NTDLL.@]
329 */
330 NTSTATUS WINAPI NtAdjustGroupsToken(
331         HANDLE TokenHandle,
332         BOOLEAN ResetToDefault,
333         PTOKEN_GROUPS NewState,
334         ULONG BufferLength,
335         PTOKEN_GROUPS PreviousState,
336         PULONG ReturnLength)
337 {
338     FIXME("%p %d %p %lu %p %p\n", TokenHandle, ResetToDefault,
339           NewState, BufferLength, PreviousState, ReturnLength);
340     return STATUS_NOT_IMPLEMENTED;
341 }
342
343 /******************************************************************************
344 *  NtPrivilegeCheck             [NTDLL.@]
345 *  ZwPrivilegeCheck             [NTDLL.@]
346 */
347 NTSTATUS WINAPI NtPrivilegeCheck(
348     HANDLE ClientToken,
349     PPRIVILEGE_SET RequiredPrivileges,
350     PBOOLEAN Result)
351 {
352     NTSTATUS status;
353     SERVER_START_REQ( check_token_privileges )
354     {
355         req->handle = ClientToken;
356         req->all_required = ((RequiredPrivileges->Control & PRIVILEGE_SET_ALL_NECESSARY) ? TRUE : FALSE);
357         wine_server_add_data( req, &RequiredPrivileges->Privilege,
358             RequiredPrivileges->PrivilegeCount * sizeof(RequiredPrivileges->Privilege[0]) );
359         wine_server_set_reply( req, &RequiredPrivileges->Privilege,
360             RequiredPrivileges->PrivilegeCount * sizeof(RequiredPrivileges->Privilege[0]) );
361
362         status = wine_server_call( req );
363
364         if (status == STATUS_SUCCESS)
365             *Result = (reply->has_privileges ? TRUE : FALSE);
366     }
367     SERVER_END_REQ;
368     return status;
369 }
370
371 /*
372  *      Section
373  */
374
375 /******************************************************************************
376  *  NtQuerySection      [NTDLL.@]
377  */
378 NTSTATUS WINAPI NtQuerySection(
379         IN HANDLE SectionHandle,
380         IN SECTION_INFORMATION_CLASS SectionInformationClass,
381         OUT PVOID SectionInformation,
382         IN ULONG Length,
383         OUT PULONG ResultLength)
384 {
385         FIXME("(%p,%d,%p,0x%08lx,%p) stub!\n",
386         SectionHandle,SectionInformationClass,SectionInformation,Length,ResultLength);
387         return 0;
388 }
389
390 /*
391  *      ports
392  */
393
394 /******************************************************************************
395  *  NtCreatePort                [NTDLL.@]
396  *  ZwCreatePort                [NTDLL.@]
397  */
398 NTSTATUS WINAPI NtCreatePort(PHANDLE PortHandle,POBJECT_ATTRIBUTES ObjectAttributes,
399                              ULONG MaxConnectInfoLength,ULONG MaxDataLength,PULONG reserved)
400 {
401   FIXME("(%p,%p,%lu,%lu,%p),stub!\n",PortHandle,ObjectAttributes,
402         MaxConnectInfoLength,MaxDataLength,reserved);
403   return 0;
404 }
405
406 /******************************************************************************
407  *  NtConnectPort               [NTDLL.@]
408  *  ZwConnectPort               [NTDLL.@]
409  */
410 NTSTATUS WINAPI NtConnectPort(
411         PHANDLE PortHandle,
412         PUNICODE_STRING PortName,
413         PSECURITY_QUALITY_OF_SERVICE SecurityQos,
414         PLPC_SECTION_WRITE WriteSection,
415         PLPC_SECTION_READ ReadSection,
416         PULONG MaximumMessageLength,
417         PVOID ConnectInfo,
418         PULONG pConnectInfoLength)
419 {
420     FIXME("(%p,%s,%p,%p,%p,%p,%p,%p),stub!\n",
421           PortHandle,debugstr_w(PortName->Buffer),SecurityQos,
422           WriteSection,ReadSection,MaximumMessageLength,ConnectInfo,
423           pConnectInfoLength);
424     if (ConnectInfo && pConnectInfoLength)
425         TRACE("\tMessage = %s\n",debugstr_an(ConnectInfo,*pConnectInfoLength));
426     return 0;
427 }
428
429 /******************************************************************************
430  *  NtListenPort                [NTDLL.@]
431  *  ZwListenPort                [NTDLL.@]
432  */
433 NTSTATUS WINAPI NtListenPort(HANDLE PortHandle,PLPC_MESSAGE pLpcMessage)
434 {
435   FIXME("(%p,%p),stub!\n",PortHandle,pLpcMessage);
436   return 0;
437 }
438
439 /******************************************************************************
440  *  NtAcceptConnectPort [NTDLL.@]
441  *  ZwAcceptConnectPort [NTDLL.@]
442  */
443 NTSTATUS WINAPI NtAcceptConnectPort(
444         PHANDLE PortHandle,
445         ULONG PortIdentifier,
446         PLPC_MESSAGE pLpcMessage,
447         BOOLEAN Accept,
448         PLPC_SECTION_WRITE WriteSection,
449         PLPC_SECTION_READ ReadSection)
450 {
451   FIXME("(%p,%lu,%p,%d,%p,%p),stub!\n",
452         PortHandle,PortIdentifier,pLpcMessage,Accept,WriteSection,ReadSection);
453   return 0;
454 }
455
456 /******************************************************************************
457  *  NtCompleteConnectPort       [NTDLL.@]
458  *  ZwCompleteConnectPort       [NTDLL.@]
459  */
460 NTSTATUS WINAPI NtCompleteConnectPort(HANDLE PortHandle)
461 {
462   FIXME("(%p),stub!\n",PortHandle);
463   return 0;
464 }
465
466 /******************************************************************************
467  *  NtRegisterThreadTerminatePort       [NTDLL.@]
468  *  ZwRegisterThreadTerminatePort       [NTDLL.@]
469  */
470 NTSTATUS WINAPI NtRegisterThreadTerminatePort(HANDLE PortHandle)
471 {
472   FIXME("(%p),stub!\n",PortHandle);
473   return 0;
474 }
475
476 /******************************************************************************
477  *  NtRequestWaitReplyPort              [NTDLL.@]
478  *  ZwRequestWaitReplyPort              [NTDLL.@]
479  */
480 NTSTATUS WINAPI NtRequestWaitReplyPort(
481         HANDLE PortHandle,
482         PLPC_MESSAGE pLpcMessageIn,
483         PLPC_MESSAGE pLpcMessageOut)
484 {
485   FIXME("(%p,%p,%p),stub!\n",PortHandle,pLpcMessageIn,pLpcMessageOut);
486   if(pLpcMessageIn)
487   {
488     TRACE("Message to send:\n");
489     TRACE("\tDataSize            = %u\n",pLpcMessageIn->DataSize);
490     TRACE("\tMessageSize         = %u\n",pLpcMessageIn->MessageSize);
491     TRACE("\tMessageType         = %u\n",pLpcMessageIn->MessageType);
492     TRACE("\tVirtualRangesOffset = %u\n",pLpcMessageIn->VirtualRangesOffset);
493     TRACE("\tClientId.UniqueProcess = %p\n",pLpcMessageIn->ClientId.UniqueProcess);
494     TRACE("\tClientId.UniqueThread  = %p\n",pLpcMessageIn->ClientId.UniqueThread);
495     TRACE("\tMessageId           = %lu\n",pLpcMessageIn->MessageId);
496     TRACE("\tSectionSize         = %lu\n",pLpcMessageIn->SectionSize);
497     TRACE("\tData                = %s\n",
498       debugstr_an(pLpcMessageIn->Data,pLpcMessageIn->DataSize));
499   }
500   return 0;
501 }
502
503 /******************************************************************************
504  *  NtReplyWaitReceivePort      [NTDLL.@]
505  *  ZwReplyWaitReceivePort      [NTDLL.@]
506  */
507 NTSTATUS WINAPI NtReplyWaitReceivePort(
508         HANDLE PortHandle,
509         PULONG PortIdentifier,
510         PLPC_MESSAGE ReplyMessage,
511         PLPC_MESSAGE Message)
512 {
513   FIXME("(%p,%p,%p,%p),stub!\n",PortHandle,PortIdentifier,ReplyMessage,Message);
514   return 0;
515 }
516
517 /*
518  *      Misc
519  */
520
521  /******************************************************************************
522  *  NtSetIntervalProfile        [NTDLL.@]
523  *  ZwSetIntervalProfile        [NTDLL.@]
524  */
525 NTSTATUS WINAPI NtSetIntervalProfile(
526         ULONG Interval,
527         KPROFILE_SOURCE Source)
528 {
529     FIXME("%lu,%d\n", Interval, Source);
530     return STATUS_SUCCESS;
531 }
532
533 /******************************************************************************
534  *  NtQueryPerformanceCounter   [NTDLL.@]
535  *
536  *  Note: Windows uses a timer clocked at a multiple of 1193182 Hz. There is a
537  *  good number of applications that crash when the returned frequency is either
538  *  lower or higher then what Windows gives. Also too high counter values are
539  *  reported to give problems.
540  */
541 NTSTATUS WINAPI NtQueryPerformanceCounter(
542         OUT PLARGE_INTEGER Counter,
543         OUT PLARGE_INTEGER Frequency)
544 {
545     LARGE_INTEGER time;
546
547     if (!Counter) return STATUS_ACCESS_VIOLATION;
548     NtQuerySystemTime( &time );
549     time.QuadPart -= boottime;
550     /* convert a counter that increments at a rate of 10 MHz
551      * to one of 1193182 Hz, with some care for arithmetic
552      * overflow ( will not overflow until 3396 or so ) and
553      * good accuracy ( 21/176 = 0.119318182) */
554     Counter->QuadPart = (time.QuadPart * 21) / 176;
555     if (Frequency)
556         Frequency->QuadPart = 1193182;
557     return 0;
558 }
559
560 /******************************************************************************
561  * NtQuerySystemInformation [NTDLL.@]
562  * ZwQuerySystemInformation [NTDLL.@]
563  *
564  * ARGUMENTS:
565  *  SystemInformationClass      Index to a certain information structure
566  *      SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT
567  *      SystemCacheInformation          SYSTEM_CACHE_INFORMATION
568  *      SystemConfigurationInformation  CONFIGURATION_INFORMATION
569  *      observed (class/len):
570  *              0x0/0x2c
571  *              0x12/0x18
572  *              0x2/0x138
573  *              0x8/0x600
574  *              0x25/0xc
575  *  SystemInformation   caller supplies storage for the information structure
576  *  Length              size of the structure
577  *  ResultLength        Data written
578  */
579 NTSTATUS WINAPI NtQuerySystemInformation(
580         IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
581         OUT PVOID SystemInformation,
582         IN ULONG Length,
583         OUT PULONG ResultLength)
584 {
585     NTSTATUS    ret = STATUS_SUCCESS;
586     ULONG       len = 0;
587
588     TRACE("(0x%08x,%p,0x%08lx,%p)\n",
589           SystemInformationClass,SystemInformation,Length,ResultLength);
590
591     switch (SystemInformationClass)
592     {
593     case SystemBasicInformation:
594         {
595             SYSTEM_BASIC_INFORMATION sbi;
596
597             sbi.dwUnknown1 = 0;
598             sbi.uKeMaximumIncrement = 0;
599             sbi.uPageSize = 1024; /* FIXME */
600             sbi.uMmNumberOfPhysicalPages = 12345; /* FIXME */
601             sbi.uMmLowestPhysicalPage = 0; /* FIXME */
602             sbi.uMmHighestPhysicalPage = 12345; /* FIXME */
603             sbi.uAllocationGranularity = 65536; /* FIXME */
604             sbi.pLowestUserAddress = 0; /* FIXME */
605             sbi.pMmHighestUserAddress = (void*)~0; /* FIXME */
606             sbi.uKeActiveProcessors = 1; /* FIXME */
607             sbi.bKeNumberProcessors = 1; /* FIXME */
608             len = sizeof(sbi);
609
610             if ( Length == len)
611             {
612                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
613                 else memcpy( SystemInformation, &sbi, len);
614             }
615             else ret = STATUS_INFO_LENGTH_MISMATCH;
616         }
617         break;
618     case SystemCpuInformation:
619         {
620             SYSTEM_CPU_INFORMATION sci;
621
622             /* FIXME: move some code from kernel/cpu.c to process this */
623             sci.Architecture = PROCESSOR_ARCHITECTURE_INTEL;
624             sci.Level = 6; /* 686, aka Pentium II+ */
625             sci.Revision = 0;
626             sci.Reserved = 0;
627             sci.FeatureSet = 0x1fff;
628             len = sizeof(sci);
629
630             if ( Length >= len)
631             {
632                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
633                 else memcpy( SystemInformation, &sci, len);
634             }
635             else ret = STATUS_INFO_LENGTH_MISMATCH;
636         }
637         break;
638     case SystemPerformanceInformation:
639         {
640             SYSTEM_PERFORMANCE_INFORMATION* spi = (SYSTEM_PERFORMANCE_INFORMATION*)SystemInformation;
641             if (Length >= sizeof(*spi))
642             {
643                 memset(spi, 0, sizeof(*spi)); /* FIXME */
644                 len = sizeof(*spi);
645             }
646             else ret = STATUS_INFO_LENGTH_MISMATCH;
647         }
648         break;
649     case SystemTimeOfDayInformation:
650         {
651             SYSTEM_TIMEOFDAY_INFORMATION sti;
652
653             memset(&sti, 0 , sizeof(sti));
654
655             /* liKeSystemTime, liExpTimeZoneBias, uCurrentTimeZoneId */
656             sti.liKeBootTime.QuadPart = boottime;
657
658             if (Length <= sizeof(sti))
659             {
660                 len = Length;
661                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
662                 else memcpy( SystemInformation, &sti, Length);
663             }
664             else ret = STATUS_INFO_LENGTH_MISMATCH;
665         }
666         break;
667     case SystemProcessInformation:
668         {
669             SYSTEM_PROCESS_INFORMATION* spi = (SYSTEM_PROCESS_INFORMATION*)SystemInformation;
670             SYSTEM_PROCESS_INFORMATION* last = NULL;
671             HANDLE hSnap = 0;
672             WCHAR procname[1024];
673             WCHAR* exename;
674             DWORD wlen = 0;
675             DWORD procstructlen = 0;
676
677             SERVER_START_REQ( create_snapshot )
678             {
679                 req->flags   = SNAP_PROCESS | SNAP_THREAD;
680                 req->inherit = FALSE;
681                 req->pid     = 0;
682                 if (!(ret = wine_server_call( req ))) hSnap = reply->handle;
683             }
684             SERVER_END_REQ;
685             len = 0;
686             while (ret == STATUS_SUCCESS)
687             {
688                 SERVER_START_REQ( next_process )
689                 {
690                     req->handle = hSnap;
691                     req->reset = (len == 0);
692                     wine_server_set_reply( req, procname, sizeof(procname)-sizeof(WCHAR) );
693                     if (!(ret = wine_server_call( req )))
694                     {
695                         /* Make sure procname is 0 terminated */
696                         procname[wine_server_reply_size(reply) / sizeof(WCHAR)] = 0;
697
698                         /* Get only the executable name, not the path */
699                         if ((exename = strrchrW(procname, '\\')) != NULL) exename++;
700                         else exename = procname;
701
702                         wlen = (strlenW(exename) + 1) * sizeof(WCHAR);
703
704                         procstructlen = sizeof(*spi) + wlen + ((reply->threads - 1) * sizeof(SYSTEM_THREAD_INFORMATION));
705
706                         if (Length >= len + procstructlen)
707                         {
708                             /* ftCreationTime, ftUserTime, ftKernelTime;
709                              * vmCounters, ioCounters
710                              */
711  
712                             memset(spi, 0, sizeof(*spi));
713
714                             spi->dwOffset = procstructlen - wlen;
715                             spi->dwThreadCount = reply->threads;
716
717                             /* spi->pszProcessName will be set later on */
718
719                             spi->dwBasePriority = reply->priority;
720                             spi->dwProcessID = (DWORD)reply->pid;
721                             spi->dwParentProcessID = (DWORD)reply->ppid;
722                             spi->dwHandleCount = reply->handles;
723
724                             /* spi->ti will be set later on */
725
726                             len += procstructlen;
727                         }
728                         else ret = STATUS_INFO_LENGTH_MISMATCH;
729                     }
730                 }
731                 SERVER_END_REQ;
732  
733                 if (ret != STATUS_SUCCESS)
734                 {
735                     if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
736                     break;
737                 }
738                 else /* Length is already checked for */
739                 {
740                     int     i, j;
741
742                     /* set thread info */
743                     i = j = 0;
744                     while (ret == STATUS_SUCCESS)
745                     {
746                         SERVER_START_REQ( next_thread )
747                         {
748                             req->handle = hSnap;
749                             req->reset = (j == 0);
750                             if (!(ret = wine_server_call( req )))
751                             {
752                                 j++;
753                                 if (reply->pid == spi->dwProcessID)
754                                 {
755                                     /* ftKernelTime, ftUserTime, ftCreateTime;
756                                      * dwTickCount, dwStartAddress
757                                      */
758
759                                     memset(&spi->ti[i], 0, sizeof(spi->ti));
760
761                                     spi->ti[i].dwOwningPID = reply->pid;
762                                     spi->ti[i].dwThreadID  = reply->tid;
763                                     spi->ti[i].dwCurrentPriority = reply->base_pri + reply->delta_pri;
764                                     spi->ti[i].dwBasePriority = reply->base_pri;
765                                     i++;
766                                 }
767                             }
768                         }
769                         SERVER_END_REQ;
770                     }
771                     if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
772
773                     /* now append process name */
774                     spi->ProcessName.Buffer = (WCHAR*)((char*)spi + spi->dwOffset);
775                     spi->ProcessName.Length = wlen - sizeof(WCHAR);
776                     spi->ProcessName.MaximumLength = wlen;
777                     memcpy( spi->ProcessName.Buffer, exename, wlen );
778                     spi->dwOffset += wlen;
779
780                     last = spi;
781                     spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + spi->dwOffset);
782                 }
783             }
784             if (ret == STATUS_SUCCESS && last) last->dwOffset = 0;
785             if (hSnap) NtClose(hSnap);
786         }
787         break;
788     case SystemProcessorPerformanceInformation:
789         {
790             SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*)SystemInformation;
791             if (Length >= sizeof(*sppi))
792             {
793                 memset(sppi, 0, sizeof(*sppi)); /* FIXME */
794                 len = sizeof(*sppi);
795             }
796             else ret = STATUS_INFO_LENGTH_MISMATCH;
797         }
798         break;
799     case SystemModuleInformation:
800         {
801             SYSTEM_DRIVER_INFORMATION sdi;
802
803             memset(&sdi, 0, sizeof(sdi));
804             len = sizeof(sdi);
805
806             if ( Length >= len)
807             {
808                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
809                 else memcpy( SystemInformation, &sdi, len);
810             }
811             else ret = STATUS_INFO_LENGTH_MISMATCH;
812         }
813         break;
814     case SystemHandleInformation:
815         {
816             SYSTEM_HANDLE_INFORMATION shi;
817
818             memset(&shi, 0, sizeof(shi));
819             len = sizeof(shi);
820
821             if ( Length >= len)
822             {
823                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
824                 else memcpy( SystemInformation, &shi, len);
825             }
826             else ret = STATUS_INFO_LENGTH_MISMATCH;
827         }
828         break;
829     case SystemCacheInformation:
830         {
831             SYSTEM_CACHE_INFORMATION* sci = (SYSTEM_CACHE_INFORMATION*)SystemInformation;
832             if (Length >= sizeof(*sci))
833             {
834                 memset(sci, 0, sizeof(*sci)); /* FIXME */
835                 len = sizeof(*sci);
836             }
837             else ret = STATUS_INFO_LENGTH_MISMATCH;
838         }
839         break;
840     case SystemInterruptInformation:
841         {
842             SYSTEM_INTERRUPT_INFORMATION sii;
843
844             memset(&sii, 0, sizeof(sii));
845             len = sizeof(sii);
846
847             if ( Length >= len)
848             {
849                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
850                 else memcpy( SystemInformation, &sii, len);
851             }
852             else ret = STATUS_INFO_LENGTH_MISMATCH;
853         }
854         break;
855     case SystemKernelDebuggerInformation:
856         {
857             PSYSTEM_KERNEL_DEBUGGER_INFORMATION pkdi;
858             if( Length >= sizeof(*pkdi))
859             {
860                 pkdi = SystemInformation;
861                 pkdi->DebuggerEnabled = FALSE;
862                 pkdi->DebuggerNotPresent = TRUE;
863                 len = sizeof(*pkdi);
864             }
865             else ret = STATUS_INFO_LENGTH_MISMATCH;
866         }
867         break;
868     case SystemRegistryQuotaInformation:
869         /* Something to do with the size of the registry             *
870          * Since we don't have a size limitation, fake it            *
871          * This is almost certainly wrong.                           *
872          * This sets each of the three words in the struct to 32 MB, *
873          * which is enough to make the IE 5 installer happy.         */
874         {
875             SYSTEM_REGISTRY_QUOTA_INFORMATION* srqi = (SYSTEM_REGISTRY_QUOTA_INFORMATION*)SystemInformation;
876             if (Length >= sizeof(*srqi))
877             {
878                 FIXME("(0x%08x,%p,0x%08lx,%p) faking max registry size of 32 MB\n",
879                       SystemInformationClass,SystemInformation,Length,ResultLength);
880                 srqi->RegistryQuotaAllowed = 0x2000000;
881                 srqi->RegistryQuotaUsed = 0x200000;
882                 srqi->Reserved1 = (void*)0x200000;
883                 len = sizeof(*srqi);
884             }
885             else ret = STATUS_INFO_LENGTH_MISMATCH;
886         }
887         break;
888     default:
889         FIXME("(0x%08x,%p,0x%08lx,%p) stub\n",
890               SystemInformationClass,SystemInformation,Length,ResultLength);
891
892         /* Several Information Classes are not implemented on Windows and return 2 different values 
893          * STATUS_NOT_IMPLEMENTED or STATUS_INVALID_INFO_CLASS
894          * in 95% of the cases it's STATUS_INVALID_INFO_CLASS, so use this as the default
895         */
896         ret = STATUS_INVALID_INFO_CLASS;
897     }
898
899     if (ResultLength) *ResultLength = len;
900
901     return ret;
902 }
903
904
905 /******************************************************************************
906  *  NtCreatePagingFile          [NTDLL.@]
907  *  ZwCreatePagingFile          [NTDLL.@]
908  */
909 NTSTATUS WINAPI NtCreatePagingFile(
910         PUNICODE_STRING PageFileName,
911         PLARGE_INTEGER MiniumSize,
912         PLARGE_INTEGER MaxiumSize,
913         PLARGE_INTEGER ActualSize)
914 {
915     FIXME("%p %p %p %p\n", PageFileName, MiniumSize, MaxiumSize, ActualSize);
916     return STATUS_SUCCESS;
917 }
918
919 /******************************************************************************
920  *  NtDisplayString                             [NTDLL.@]
921  *
922  * writes a string to the nt-textmode screen eg. during startup
923  */
924 NTSTATUS WINAPI NtDisplayString ( PUNICODE_STRING string )
925 {
926     STRING stringA;
927     NTSTATUS ret;
928
929     if (!(ret = RtlUnicodeStringToAnsiString( &stringA, string, TRUE )))
930     {
931         MESSAGE( "%.*s", stringA.Length, stringA.Buffer );
932         RtlFreeAnsiString( &stringA );
933     }
934     return ret;
935 }
936
937 /******************************************************************************
938  *  NtInitiatePowerAction                       [NTDLL.@]
939  *
940  */
941 NTSTATUS WINAPI NtInitiatePowerAction(
942         IN POWER_ACTION SystemAction,
943         IN SYSTEM_POWER_STATE MinSystemState,
944         IN ULONG Flags,
945         IN BOOLEAN Asynchronous)
946 {
947         FIXME("(%d,%d,0x%08lx,%d),stub\n",
948                 SystemAction,MinSystemState,Flags,Asynchronous);
949         return STATUS_NOT_IMPLEMENTED;
950 }
951         
952
953 /******************************************************************************
954  *  NtPowerInformation                          [NTDLL.@]
955  *
956  */
957 NTSTATUS WINAPI NtPowerInformation(
958         IN POWER_INFORMATION_LEVEL InformationLevel,
959         IN PVOID lpInputBuffer,
960         IN ULONG nInputBufferSize,
961         IN PVOID lpOutputBuffer,
962         IN ULONG nOutputBufferSize)
963 {
964         TRACE("(%d,%p,%ld,%p,%ld)\n",
965                 InformationLevel,lpInputBuffer,nInputBufferSize,lpOutputBuffer,nOutputBufferSize);
966         switch(InformationLevel) {
967                 case SystemPowerCapabilities: {
968                         PSYSTEM_POWER_CAPABILITIES PowerCaps = (PSYSTEM_POWER_CAPABILITIES)lpOutputBuffer;
969                         FIXME("semi-stub: SystemPowerCapabilities\n");
970                         if (nOutputBufferSize < sizeof(SYSTEM_POWER_CAPABILITIES))
971                                 return STATUS_BUFFER_TOO_SMALL;
972                         /* FIXME: These values are based off a native XP desktop, should probably use APM/ACPI to get the 'real' values */
973                         PowerCaps->PowerButtonPresent = TRUE;
974                         PowerCaps->SleepButtonPresent = FALSE;
975                         PowerCaps->LidPresent = FALSE;
976                         PowerCaps->SystemS1 = TRUE;
977                         PowerCaps->SystemS2 = FALSE;
978                         PowerCaps->SystemS3 = FALSE;
979                         PowerCaps->SystemS4 = TRUE;
980                         PowerCaps->SystemS5 = TRUE;
981                         PowerCaps->HiberFilePresent = TRUE;
982                         PowerCaps->FullWake = TRUE;
983                         PowerCaps->VideoDimPresent = FALSE;
984                         PowerCaps->ApmPresent = FALSE;
985                         PowerCaps->UpsPresent = FALSE;
986                         PowerCaps->ThermalControl = FALSE;
987                         PowerCaps->ProcessorThrottle = FALSE;
988                         PowerCaps->ProcessorMinThrottle = 100;
989                         PowerCaps->ProcessorMaxThrottle = 100;
990                         PowerCaps->DiskSpinDown = TRUE;
991                         PowerCaps->SystemBatteriesPresent = FALSE;
992                         PowerCaps->BatteriesAreShortTerm = FALSE;
993                         PowerCaps->BatteryScale[0].Granularity = 0;
994                         PowerCaps->BatteryScale[0].Capacity = 0;
995                         PowerCaps->BatteryScale[1].Granularity = 0;
996                         PowerCaps->BatteryScale[1].Capacity = 0;
997                         PowerCaps->BatteryScale[2].Granularity = 0;
998                         PowerCaps->BatteryScale[2].Capacity = 0;
999                         PowerCaps->AcOnLineWake = PowerSystemUnspecified;
1000                         PowerCaps->SoftLidWake = PowerSystemUnspecified;
1001                         PowerCaps->RtcWake = PowerSystemSleeping1;
1002                         PowerCaps->MinDeviceWakeState = PowerSystemUnspecified;
1003                         PowerCaps->DefaultLowLatencyWake = PowerSystemUnspecified;
1004                         return STATUS_SUCCESS;
1005                 }
1006                 default:
1007                         FIXME("Unimplemented NtPowerInformation action: %d\n", InformationLevel);
1008                         return STATUS_NOT_IMPLEMENTED;
1009         }
1010 }
1011
1012 /******************************************************************************
1013  *  NtShutdownSystem                            [NTDLL.@]
1014  *
1015  */
1016 NTSTATUS WINAPI NtShutdownSystem(SHUTDOWN_ACTION Action)
1017 {
1018     FIXME("%d\n",Action);
1019     return STATUS_SUCCESS;
1020 }
1021
1022 /******************************************************************************
1023  *  NtAllocateLocallyUniqueId (NTDLL.@)
1024  *
1025  * FIXME: the server should do that
1026  */
1027 NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID Luid)
1028 {
1029     static LUID luid = { SE_MAX_WELL_KNOWN_PRIVILEGE, 0 };
1030
1031     FIXME("%p\n", Luid);
1032
1033     if (!Luid)
1034         return STATUS_ACCESS_VIOLATION;
1035
1036     luid.LowPart++;
1037     if (luid.LowPart==0)
1038         luid.HighPart++;
1039     Luid->HighPart = luid.HighPart;
1040     Luid->LowPart = luid.LowPart;
1041
1042     return STATUS_SUCCESS;
1043 }
1044
1045 /******************************************************************************
1046  *        VerSetConditionMask   (NTDLL.@)
1047  */
1048 ULONGLONG WINAPI VerSetConditionMask( ULONGLONG dwlConditionMask, DWORD dwTypeBitMask,
1049                                       BYTE dwConditionMask)
1050 {
1051     if(dwTypeBitMask == 0)
1052         return dwlConditionMask;
1053     dwConditionMask &= 0x07;
1054     if(dwConditionMask == 0)
1055         return dwlConditionMask;
1056
1057     if(dwTypeBitMask & VER_PRODUCT_TYPE)
1058         dwlConditionMask |= dwConditionMask << 7*3;
1059     else if (dwTypeBitMask & VER_SUITENAME)
1060         dwlConditionMask |= dwConditionMask << 6*3;
1061     else if (dwTypeBitMask & VER_SERVICEPACKMAJOR)
1062         dwlConditionMask |= dwConditionMask << 5*3;
1063     else if (dwTypeBitMask & VER_SERVICEPACKMINOR)
1064         dwlConditionMask |= dwConditionMask << 4*3;
1065     else if (dwTypeBitMask & VER_PLATFORMID)
1066         dwlConditionMask |= dwConditionMask << 3*3;
1067     else if (dwTypeBitMask & VER_BUILDNUMBER)
1068         dwlConditionMask |= dwConditionMask << 2*3;
1069     else if (dwTypeBitMask & VER_MAJORVERSION)
1070         dwlConditionMask |= dwConditionMask << 1*3;
1071     else if (dwTypeBitMask & VER_MINORVERSION)
1072         dwlConditionMask |= dwConditionMask << 0*3;
1073     return dwlConditionMask;
1074 }
1075
1076 /******************************************************************************
1077  *        NtAlertThread   (NTDLL.@)
1078  */
1079 NTSTATUS WINAPI NtAlertThread(HANDLE ThreadHandle)
1080 {
1081     FIXME("%p\n", ThreadHandle);
1082     return STATUS_NOT_IMPLEMENTED;
1083 }