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