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