kernel: Moved the get_startup_info call to ntdll.
[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
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%08lx,%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%08lx,%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%08lx,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%08lx,%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,%ld,%p)\n",
201           token,tokeninfoclass,tokeninfo,tokeninfolength,retlen);
202
203     switch (tokeninfoclass)
204     {
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     default:
228         len = 0;
229     }
230
231     if (retlen) *retlen = len;
232
233     if (tokeninfolength < len)
234         return STATUS_BUFFER_TOO_SMALL;
235
236     switch (tokeninfoclass)
237     {
238     case TokenUser:
239         SERVER_START_REQ( get_token_user )
240         {
241             TOKEN_USER * tuser = tokeninfo;
242             PSID sid = (PSID) (tuser + 1);
243             DWORD sid_len = tokeninfolength < sizeof(TOKEN_USER) ? 0 : tokeninfolength - sizeof(TOKEN_USER);
244
245             req->handle = token;
246             wine_server_set_reply( req, sid, sid_len );
247             status = wine_server_call( req );
248             if (retlen) *retlen = reply->user_len + sizeof(TOKEN_USER);
249             if (status == STATUS_SUCCESS)
250             {
251                 tuser->User.Sid = sid;
252                 tuser->User.Attributes = 0;
253             }
254         }
255         SERVER_END_REQ;
256         break;
257     case TokenGroups:
258         if (tokeninfo)
259         {
260             TOKEN_GROUPS *tgroups = tokeninfo;
261             SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
262
263             /* we need to show admin privileges ! */
264             tgroups->GroupCount = 1;
265             tgroups->Groups->Attributes = SE_GROUP_ENABLED;
266             RtlAllocateAndInitializeSid( &sid,
267                                          2,
268                                          SECURITY_BUILTIN_DOMAIN_RID,
269                                          DOMAIN_ALIAS_RID_ADMINS,
270                                          0, 0, 0, 0, 0, 0,
271                                          &(tgroups->Groups->Sid));
272         }
273         break;
274     case TokenPrimaryGroup:
275         if (tokeninfo)
276         {
277             TOKEN_PRIMARY_GROUP *tgroup = tokeninfo;
278             SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
279             RtlAllocateAndInitializeSid( &sid,
280                                          2,
281                                          SECURITY_BUILTIN_DOMAIN_RID,
282                                          DOMAIN_ALIAS_RID_ADMINS,
283                                          0, 0, 0, 0, 0, 0,
284                                          &(tgroup->PrimaryGroup));
285         }
286         break;
287     case TokenPrivileges:
288         SERVER_START_REQ( get_token_privileges )
289         {
290             TOKEN_PRIVILEGES *tpriv = tokeninfo;
291             req->handle = token;
292             if (tpriv && tokeninfolength > FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ))
293                 wine_server_set_reply( req, &tpriv->Privileges, tokeninfolength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) );
294             status = wine_server_call( req );
295             if (retlen) *retlen = FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) + reply->len;
296             if (tpriv) tpriv->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES);
297         }
298         SERVER_END_REQ;
299         break;
300     case TokenOwner:
301         if (tokeninfo)
302         {
303             TOKEN_OWNER *owner = tokeninfo;
304             PSID sid = (PSID) (owner + 1);
305             SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
306             RtlInitializeSid(sid, &localSidAuthority, 1);
307             *(RtlSubAuthoritySid(sid, 0)) = SECURITY_INTERACTIVE_RID;
308             owner->Owner = sid;
309         }
310         break;
311     default:
312         {
313             ERR("Unhandled Token Information class %d!\n", tokeninfoclass);
314             return STATUS_NOT_IMPLEMENTED;
315         }
316     }
317     return status;
318 }
319
320 /******************************************************************************
321 *  NtSetInformationToken                [NTDLL.@]
322 *  ZwSetInformationToken                [NTDLL.@]
323 */
324 NTSTATUS WINAPI NtSetInformationToken(
325         HANDLE TokenHandle,
326         TOKEN_INFORMATION_CLASS TokenInformationClass,
327         PVOID TokenInformation,
328         ULONG TokenInformationLength)
329 {
330     FIXME("%p %d %p %lu\n", TokenHandle, TokenInformationClass,
331           TokenInformation, TokenInformationLength);
332     return STATUS_NOT_IMPLEMENTED;
333 }
334
335 /******************************************************************************
336 *  NtAdjustGroupsToken          [NTDLL.@]
337 *  ZwAdjustGroupsToken          [NTDLL.@]
338 */
339 NTSTATUS WINAPI NtAdjustGroupsToken(
340         HANDLE TokenHandle,
341         BOOLEAN ResetToDefault,
342         PTOKEN_GROUPS NewState,
343         ULONG BufferLength,
344         PTOKEN_GROUPS PreviousState,
345         PULONG ReturnLength)
346 {
347     FIXME("%p %d %p %lu %p %p\n", TokenHandle, ResetToDefault,
348           NewState, BufferLength, PreviousState, ReturnLength);
349     return STATUS_NOT_IMPLEMENTED;
350 }
351
352 /******************************************************************************
353 *  NtPrivilegeCheck             [NTDLL.@]
354 *  ZwPrivilegeCheck             [NTDLL.@]
355 */
356 NTSTATUS WINAPI NtPrivilegeCheck(
357     HANDLE ClientToken,
358     PPRIVILEGE_SET RequiredPrivileges,
359     PBOOLEAN Result)
360 {
361     NTSTATUS status;
362     SERVER_START_REQ( check_token_privileges )
363     {
364         req->handle = ClientToken;
365         req->all_required = ((RequiredPrivileges->Control & PRIVILEGE_SET_ALL_NECESSARY) ? TRUE : FALSE);
366         wine_server_add_data( req, &RequiredPrivileges->Privilege,
367             RequiredPrivileges->PrivilegeCount * sizeof(RequiredPrivileges->Privilege[0]) );
368         wine_server_set_reply( req, &RequiredPrivileges->Privilege,
369             RequiredPrivileges->PrivilegeCount * sizeof(RequiredPrivileges->Privilege[0]) );
370
371         status = wine_server_call( req );
372
373         if (status == STATUS_SUCCESS)
374             *Result = (reply->has_privileges ? TRUE : FALSE);
375     }
376     SERVER_END_REQ;
377     return status;
378 }
379
380 /*
381  *      Section
382  */
383
384 /******************************************************************************
385  *  NtQuerySection      [NTDLL.@]
386  */
387 NTSTATUS WINAPI NtQuerySection(
388         IN HANDLE SectionHandle,
389         IN SECTION_INFORMATION_CLASS SectionInformationClass,
390         OUT PVOID SectionInformation,
391         IN ULONG Length,
392         OUT PULONG ResultLength)
393 {
394         FIXME("(%p,%d,%p,0x%08lx,%p) stub!\n",
395         SectionHandle,SectionInformationClass,SectionInformation,Length,ResultLength);
396         return 0;
397 }
398
399 /*
400  *      ports
401  */
402
403 /******************************************************************************
404  *  NtCreatePort                [NTDLL.@]
405  *  ZwCreatePort                [NTDLL.@]
406  */
407 NTSTATUS WINAPI NtCreatePort(PHANDLE PortHandle,POBJECT_ATTRIBUTES ObjectAttributes,
408                              ULONG MaxConnectInfoLength,ULONG MaxDataLength,PULONG reserved)
409 {
410   FIXME("(%p,%p,%lu,%lu,%p),stub!\n",PortHandle,ObjectAttributes,
411         MaxConnectInfoLength,MaxDataLength,reserved);
412   return 0;
413 }
414
415 /******************************************************************************
416  *  NtConnectPort               [NTDLL.@]
417  *  ZwConnectPort               [NTDLL.@]
418  */
419 NTSTATUS WINAPI NtConnectPort(
420         PHANDLE PortHandle,
421         PUNICODE_STRING PortName,
422         PSECURITY_QUALITY_OF_SERVICE SecurityQos,
423         PLPC_SECTION_WRITE WriteSection,
424         PLPC_SECTION_READ ReadSection,
425         PULONG MaximumMessageLength,
426         PVOID ConnectInfo,
427         PULONG pConnectInfoLength)
428 {
429     FIXME("(%p,%s,%p,%p,%p,%p,%p,%p),stub!\n",
430           PortHandle,debugstr_w(PortName->Buffer),SecurityQos,
431           WriteSection,ReadSection,MaximumMessageLength,ConnectInfo,
432           pConnectInfoLength);
433     if (ConnectInfo && pConnectInfoLength)
434         TRACE("\tMessage = %s\n",debugstr_an(ConnectInfo,*pConnectInfoLength));
435     return 0;
436 }
437
438 /******************************************************************************
439  *  NtListenPort                [NTDLL.@]
440  *  ZwListenPort                [NTDLL.@]
441  */
442 NTSTATUS WINAPI NtListenPort(HANDLE PortHandle,PLPC_MESSAGE pLpcMessage)
443 {
444   FIXME("(%p,%p),stub!\n",PortHandle,pLpcMessage);
445   return 0;
446 }
447
448 /******************************************************************************
449  *  NtAcceptConnectPort [NTDLL.@]
450  *  ZwAcceptConnectPort [NTDLL.@]
451  */
452 NTSTATUS WINAPI NtAcceptConnectPort(
453         PHANDLE PortHandle,
454         ULONG PortIdentifier,
455         PLPC_MESSAGE pLpcMessage,
456         BOOLEAN Accept,
457         PLPC_SECTION_WRITE WriteSection,
458         PLPC_SECTION_READ ReadSection)
459 {
460   FIXME("(%p,%lu,%p,%d,%p,%p),stub!\n",
461         PortHandle,PortIdentifier,pLpcMessage,Accept,WriteSection,ReadSection);
462   return 0;
463 }
464
465 /******************************************************************************
466  *  NtCompleteConnectPort       [NTDLL.@]
467  *  ZwCompleteConnectPort       [NTDLL.@]
468  */
469 NTSTATUS WINAPI NtCompleteConnectPort(HANDLE PortHandle)
470 {
471   FIXME("(%p),stub!\n",PortHandle);
472   return 0;
473 }
474
475 /******************************************************************************
476  *  NtRegisterThreadTerminatePort       [NTDLL.@]
477  *  ZwRegisterThreadTerminatePort       [NTDLL.@]
478  */
479 NTSTATUS WINAPI NtRegisterThreadTerminatePort(HANDLE PortHandle)
480 {
481   FIXME("(%p),stub!\n",PortHandle);
482   return 0;
483 }
484
485 /******************************************************************************
486  *  NtRequestWaitReplyPort              [NTDLL.@]
487  *  ZwRequestWaitReplyPort              [NTDLL.@]
488  */
489 NTSTATUS WINAPI NtRequestWaitReplyPort(
490         HANDLE PortHandle,
491         PLPC_MESSAGE pLpcMessageIn,
492         PLPC_MESSAGE pLpcMessageOut)
493 {
494   FIXME("(%p,%p,%p),stub!\n",PortHandle,pLpcMessageIn,pLpcMessageOut);
495   if(pLpcMessageIn)
496   {
497     TRACE("Message to send:\n");
498     TRACE("\tDataSize            = %u\n",pLpcMessageIn->DataSize);
499     TRACE("\tMessageSize         = %u\n",pLpcMessageIn->MessageSize);
500     TRACE("\tMessageType         = %u\n",pLpcMessageIn->MessageType);
501     TRACE("\tVirtualRangesOffset = %u\n",pLpcMessageIn->VirtualRangesOffset);
502     TRACE("\tClientId.UniqueProcess = %p\n",pLpcMessageIn->ClientId.UniqueProcess);
503     TRACE("\tClientId.UniqueThread  = %p\n",pLpcMessageIn->ClientId.UniqueThread);
504     TRACE("\tMessageId           = %lu\n",pLpcMessageIn->MessageId);
505     TRACE("\tSectionSize         = %lu\n",pLpcMessageIn->SectionSize);
506     TRACE("\tData                = %s\n",
507       debugstr_an((const char*)pLpcMessageIn->Data,pLpcMessageIn->DataSize));
508   }
509   return 0;
510 }
511
512 /******************************************************************************
513  *  NtReplyWaitReceivePort      [NTDLL.@]
514  *  ZwReplyWaitReceivePort      [NTDLL.@]
515  */
516 NTSTATUS WINAPI NtReplyWaitReceivePort(
517         HANDLE PortHandle,
518         PULONG PortIdentifier,
519         PLPC_MESSAGE ReplyMessage,
520         PLPC_MESSAGE Message)
521 {
522   FIXME("(%p,%p,%p,%p),stub!\n",PortHandle,PortIdentifier,ReplyMessage,Message);
523   return 0;
524 }
525
526 /*
527  *      Misc
528  */
529
530  /******************************************************************************
531  *  NtSetIntervalProfile        [NTDLL.@]
532  *  ZwSetIntervalProfile        [NTDLL.@]
533  */
534 NTSTATUS WINAPI NtSetIntervalProfile(
535         ULONG Interval,
536         KPROFILE_SOURCE Source)
537 {
538     FIXME("%lu,%d\n", Interval, Source);
539     return STATUS_SUCCESS;
540 }
541
542 /******************************************************************************
543  * NtQuerySystemInformation [NTDLL.@]
544  * ZwQuerySystemInformation [NTDLL.@]
545  *
546  * ARGUMENTS:
547  *  SystemInformationClass      Index to a certain information structure
548  *      SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT
549  *      SystemCacheInformation          SYSTEM_CACHE_INFORMATION
550  *      SystemConfigurationInformation  CONFIGURATION_INFORMATION
551  *      observed (class/len):
552  *              0x0/0x2c
553  *              0x12/0x18
554  *              0x2/0x138
555  *              0x8/0x600
556  *              0x25/0xc
557  *  SystemInformation   caller supplies storage for the information structure
558  *  Length              size of the structure
559  *  ResultLength        Data written
560  */
561 NTSTATUS WINAPI NtQuerySystemInformation(
562         IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
563         OUT PVOID SystemInformation,
564         IN ULONG Length,
565         OUT PULONG ResultLength)
566 {
567     NTSTATUS    ret = STATUS_SUCCESS;
568     ULONG       len = 0;
569
570     TRACE("(0x%08x,%p,0x%08lx,%p)\n",
571           SystemInformationClass,SystemInformation,Length,ResultLength);
572
573     switch (SystemInformationClass)
574     {
575     case SystemBasicInformation:
576         {
577             SYSTEM_BASIC_INFORMATION sbi;
578
579             sbi.dwUnknown1 = 0;
580             sbi.uKeMaximumIncrement = 0;
581             sbi.uPageSize = 1024; /* FIXME */
582             sbi.uMmNumberOfPhysicalPages = 12345; /* FIXME */
583             sbi.uMmLowestPhysicalPage = 0; /* FIXME */
584             sbi.uMmHighestPhysicalPage = 12345; /* FIXME */
585             sbi.uAllocationGranularity = 65536; /* FIXME */
586             sbi.pLowestUserAddress = 0; /* FIXME */
587             sbi.pMmHighestUserAddress = (void*)~0; /* FIXME */
588             sbi.uKeActiveProcessors = 1; /* FIXME */
589             sbi.bKeNumberProcessors = 1; /* FIXME */
590             len = sizeof(sbi);
591
592             if ( Length == len)
593             {
594                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
595                 else memcpy( SystemInformation, &sbi, len);
596             }
597             else ret = STATUS_INFO_LENGTH_MISMATCH;
598         }
599         break;
600     case SystemCpuInformation:
601         {
602             SYSTEM_CPU_INFORMATION sci;
603
604             /* FIXME: move some code from kernel/cpu.c to process this */
605             sci.Architecture = PROCESSOR_ARCHITECTURE_INTEL;
606             sci.Level = 6; /* 686, aka Pentium II+ */
607             sci.Revision = 0;
608             sci.Reserved = 0;
609             sci.FeatureSet = 0x1fff;
610             len = sizeof(sci);
611
612             if ( Length >= len)
613             {
614                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
615                 else memcpy( SystemInformation, &sci, len);
616             }
617             else ret = STATUS_INFO_LENGTH_MISMATCH;
618         }
619         break;
620     case SystemPerformanceInformation:
621         {
622             SYSTEM_PERFORMANCE_INFORMATION spi;
623
624             memset(&spi, 0 , sizeof(spi));
625             len = sizeof(spi);
626
627             if (Length >= len)
628             {
629                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
630                 else memcpy( SystemInformation, &spi, len);
631             }
632             else ret = STATUS_INFO_LENGTH_MISMATCH;
633         }
634         break;
635     case SystemTimeOfDayInformation:
636         {
637             SYSTEM_TIMEOFDAY_INFORMATION sti;
638
639             memset(&sti, 0 , sizeof(sti));
640
641             /* liKeSystemTime, liExpTimeZoneBias, uCurrentTimeZoneId */
642             RtlSecondsSince1970ToTime( server_start_time, &sti.liKeBootTime );
643
644             if (Length <= sizeof(sti))
645             {
646                 len = Length;
647                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
648                 else memcpy( SystemInformation, &sti, Length);
649             }
650             else ret = STATUS_INFO_LENGTH_MISMATCH;
651         }
652         break;
653     case SystemProcessInformation:
654         {
655             SYSTEM_PROCESS_INFORMATION* spi = (SYSTEM_PROCESS_INFORMATION*)SystemInformation;
656             SYSTEM_PROCESS_INFORMATION* last = NULL;
657             HANDLE hSnap = 0;
658             WCHAR procname[1024];
659             WCHAR* exename;
660             DWORD wlen = 0;
661             DWORD procstructlen = 0;
662
663             SERVER_START_REQ( create_snapshot )
664             {
665                 req->flags      = SNAP_PROCESS | SNAP_THREAD;
666                 req->attributes = 0;
667                 req->pid        = 0;
668                 if (!(ret = wine_server_call( req ))) hSnap = reply->handle;
669             }
670             SERVER_END_REQ;
671             len = 0;
672             while (ret == STATUS_SUCCESS)
673             {
674                 SERVER_START_REQ( next_process )
675                 {
676                     req->handle = hSnap;
677                     req->reset = (len == 0);
678                     wine_server_set_reply( req, procname, sizeof(procname)-sizeof(WCHAR) );
679                     if (!(ret = wine_server_call( req )))
680                     {
681                         /* Make sure procname is 0 terminated */
682                         procname[wine_server_reply_size(reply) / sizeof(WCHAR)] = 0;
683
684                         /* Get only the executable name, not the path */
685                         if ((exename = strrchrW(procname, '\\')) != NULL) exename++;
686                         else exename = procname;
687
688                         wlen = (strlenW(exename) + 1) * sizeof(WCHAR);
689
690                         procstructlen = sizeof(*spi) + wlen + ((reply->threads - 1) * sizeof(SYSTEM_THREAD_INFORMATION));
691
692                         if (Length >= len + procstructlen)
693                         {
694                             /* ftCreationTime, ftUserTime, ftKernelTime;
695                              * vmCounters, ioCounters
696                              */
697  
698                             memset(spi, 0, sizeof(*spi));
699
700                             spi->dwOffset = procstructlen - wlen;
701                             spi->dwThreadCount = reply->threads;
702
703                             /* spi->pszProcessName will be set later on */
704
705                             spi->dwBasePriority = reply->priority;
706                             spi->dwProcessID = (DWORD)reply->pid;
707                             spi->dwParentProcessID = (DWORD)reply->ppid;
708                             spi->dwHandleCount = reply->handles;
709
710                             /* spi->ti will be set later on */
711
712                             len += procstructlen;
713                         }
714                         else ret = STATUS_INFO_LENGTH_MISMATCH;
715                     }
716                 }
717                 SERVER_END_REQ;
718  
719                 if (ret != STATUS_SUCCESS)
720                 {
721                     if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
722                     break;
723                 }
724                 else /* Length is already checked for */
725                 {
726                     int     i, j;
727
728                     /* set thread info */
729                     i = j = 0;
730                     while (ret == STATUS_SUCCESS)
731                     {
732                         SERVER_START_REQ( next_thread )
733                         {
734                             req->handle = hSnap;
735                             req->reset = (j == 0);
736                             if (!(ret = wine_server_call( req )))
737                             {
738                                 j++;
739                                 if (reply->pid == spi->dwProcessID)
740                                 {
741                                     /* ftKernelTime, ftUserTime, ftCreateTime;
742                                      * dwTickCount, dwStartAddress
743                                      */
744
745                                     memset(&spi->ti[i], 0, sizeof(spi->ti));
746
747                                     spi->ti[i].dwOwningPID = reply->pid;
748                                     spi->ti[i].dwThreadID  = reply->tid;
749                                     spi->ti[i].dwCurrentPriority = reply->base_pri + reply->delta_pri;
750                                     spi->ti[i].dwBasePriority = reply->base_pri;
751                                     i++;
752                                 }
753                             }
754                         }
755                         SERVER_END_REQ;
756                     }
757                     if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
758
759                     /* now append process name */
760                     spi->ProcessName.Buffer = (WCHAR*)((char*)spi + spi->dwOffset);
761                     spi->ProcessName.Length = wlen - sizeof(WCHAR);
762                     spi->ProcessName.MaximumLength = wlen;
763                     memcpy( spi->ProcessName.Buffer, exename, wlen );
764                     spi->dwOffset += wlen;
765
766                     last = spi;
767                     spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + spi->dwOffset);
768                 }
769             }
770             if (ret == STATUS_SUCCESS && last) last->dwOffset = 0;
771             if (hSnap) NtClose(hSnap);
772         }
773         break;
774     case SystemProcessorPerformanceInformation:
775         {
776             SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION sppi;
777
778             memset(&sppi, 0 , sizeof(sppi)); /* FIXME */
779             len = sizeof(sppi);
780
781             if (Length >= len)
782             {
783                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
784                 else memcpy( SystemInformation, &sppi, len);
785             }
786             else ret = STATUS_INFO_LENGTH_MISMATCH;
787         }
788         break;
789     case SystemModuleInformation:
790         {
791             SYSTEM_MODULE_INFORMATION smi;
792
793             memset(&smi, 0, sizeof(smi));
794             len = sizeof(smi);
795
796             if ( Length >= len)
797             {
798                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
799                 else memcpy( SystemInformation, &smi, len);
800             }
801             else ret = STATUS_INFO_LENGTH_MISMATCH;
802         }
803         break;
804     case SystemHandleInformation:
805         {
806             SYSTEM_HANDLE_INFORMATION shi;
807
808             memset(&shi, 0, sizeof(shi));
809             len = sizeof(shi);
810
811             if ( Length >= len)
812             {
813                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
814                 else memcpy( SystemInformation, &shi, len);
815             }
816             else ret = STATUS_INFO_LENGTH_MISMATCH;
817         }
818         break;
819     case SystemCacheInformation:
820         {
821             SYSTEM_CACHE_INFORMATION sci;
822
823             memset(&sci, 0, sizeof(sci)); /* FIXME */
824             len = sizeof(sci);
825
826             if ( Length >= len)
827             {
828                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
829                 else memcpy( SystemInformation, &sci, len);
830             }
831             else ret = STATUS_INFO_LENGTH_MISMATCH;
832         }
833         break;
834     case SystemInterruptInformation:
835         {
836             SYSTEM_INTERRUPT_INFORMATION sii;
837
838             memset(&sii, 0, sizeof(sii));
839             len = sizeof(sii);
840
841             if ( Length >= len)
842             {
843                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
844                 else memcpy( SystemInformation, &sii, len);
845             }
846             else ret = STATUS_INFO_LENGTH_MISMATCH;
847         }
848         break;
849     case SystemKernelDebuggerInformation:
850         {
851             SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi;
852
853             skdi.DebuggerEnabled = FALSE;
854             skdi.DebuggerNotPresent = TRUE;
855             len = sizeof(skdi);
856
857             if ( Length >= len)
858             {
859                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
860                 else memcpy( SystemInformation, &skdi, len);
861             }
862             else ret = STATUS_INFO_LENGTH_MISMATCH;
863         }
864         break;
865     case SystemRegistryQuotaInformation:
866         {
867             /* Something to do with the size of the registry             *
868              * Since we don't have a size limitation, fake it            *
869              * This is almost certainly wrong.                           *
870              * This sets each of the three words in the struct to 32 MB, *
871              * which is enough to make the IE 5 installer happy.         */
872             SYSTEM_REGISTRY_QUOTA_INFORMATION srqi;
873
874             srqi.RegistryQuotaAllowed = 0x2000000;
875             srqi.RegistryQuotaUsed = 0x200000;
876             srqi.Reserved1 = (void*)0x200000;
877             len = sizeof(srqi);
878
879             if ( Length >= len)
880             {
881                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
882                 else
883                 {
884                     FIXME("SystemRegistryQuotaInformation: faking max registry size of 32 MB\n");
885                     memcpy( SystemInformation, &srqi, len);
886                 }
887             }
888             else ret = STATUS_INFO_LENGTH_MISMATCH;
889         }
890         break;
891     default:
892         FIXME("(0x%08x,%p,0x%08lx,%p) stub\n",
893               SystemInformationClass,SystemInformation,Length,ResultLength);
894
895         /* Several Information Classes are not implemented on Windows and return 2 different values 
896          * STATUS_NOT_IMPLEMENTED or STATUS_INVALID_INFO_CLASS
897          * in 95% of the cases it's STATUS_INVALID_INFO_CLASS, so use this as the default
898         */
899         ret = STATUS_INVALID_INFO_CLASS;
900     }
901
902     if (ResultLength) *ResultLength = len;
903
904     return ret;
905 }
906
907 /******************************************************************************
908  * NtSetSystemInformation [NTDLL.@]
909  * ZwSetSystemInformation [NTDLL.@]
910  */
911 NTSTATUS WINAPI NtSetSystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG Length)
912 {
913     FIXME("(0x%08x,%p,0x%08lx) stub\n",SystemInformationClass,SystemInformation,Length);
914     return STATUS_SUCCESS;
915 }
916
917 /******************************************************************************
918  *  NtCreatePagingFile          [NTDLL.@]
919  *  ZwCreatePagingFile          [NTDLL.@]
920  */
921 NTSTATUS WINAPI NtCreatePagingFile(
922         PUNICODE_STRING PageFileName,
923         PLARGE_INTEGER MinimumSize,
924         PLARGE_INTEGER MaximumSize,
925         PLARGE_INTEGER ActualSize)
926 {
927     FIXME("(%p %p %p %p) stub\n", PageFileName, MinimumSize, MaximumSize, ActualSize);
928     return STATUS_SUCCESS;
929 }
930
931 /******************************************************************************
932  *  NtDisplayString                             [NTDLL.@]
933  *
934  * writes a string to the nt-textmode screen eg. during startup
935  */
936 NTSTATUS WINAPI NtDisplayString ( PUNICODE_STRING string )
937 {
938     STRING stringA;
939     NTSTATUS ret;
940
941     if (!(ret = RtlUnicodeStringToAnsiString( &stringA, string, TRUE )))
942     {
943         MESSAGE( "%.*s", stringA.Length, stringA.Buffer );
944         RtlFreeAnsiString( &stringA );
945     }
946     return ret;
947 }
948
949 /******************************************************************************
950  *  NtInitiatePowerAction                       [NTDLL.@]
951  *
952  */
953 NTSTATUS WINAPI NtInitiatePowerAction(
954         IN POWER_ACTION SystemAction,
955         IN SYSTEM_POWER_STATE MinSystemState,
956         IN ULONG Flags,
957         IN BOOLEAN Asynchronous)
958 {
959         FIXME("(%d,%d,0x%08lx,%d),stub\n",
960                 SystemAction,MinSystemState,Flags,Asynchronous);
961         return STATUS_NOT_IMPLEMENTED;
962 }
963         
964
965 /******************************************************************************
966  *  NtPowerInformation                          [NTDLL.@]
967  *
968  */
969 NTSTATUS WINAPI NtPowerInformation(
970         IN POWER_INFORMATION_LEVEL InformationLevel,
971         IN PVOID lpInputBuffer,
972         IN ULONG nInputBufferSize,
973         IN PVOID lpOutputBuffer,
974         IN ULONG nOutputBufferSize)
975 {
976         TRACE("(%d,%p,%ld,%p,%ld)\n",
977                 InformationLevel,lpInputBuffer,nInputBufferSize,lpOutputBuffer,nOutputBufferSize);
978         switch(InformationLevel) {
979                 case SystemPowerCapabilities: {
980                         PSYSTEM_POWER_CAPABILITIES PowerCaps = (PSYSTEM_POWER_CAPABILITIES)lpOutputBuffer;
981                         FIXME("semi-stub: SystemPowerCapabilities\n");
982                         if (nOutputBufferSize < sizeof(SYSTEM_POWER_CAPABILITIES))
983                                 return STATUS_BUFFER_TOO_SMALL;
984                         /* FIXME: These values are based off a native XP desktop, should probably use APM/ACPI to get the 'real' values */
985                         PowerCaps->PowerButtonPresent = TRUE;
986                         PowerCaps->SleepButtonPresent = FALSE;
987                         PowerCaps->LidPresent = FALSE;
988                         PowerCaps->SystemS1 = TRUE;
989                         PowerCaps->SystemS2 = FALSE;
990                         PowerCaps->SystemS3 = FALSE;
991                         PowerCaps->SystemS4 = TRUE;
992                         PowerCaps->SystemS5 = TRUE;
993                         PowerCaps->HiberFilePresent = TRUE;
994                         PowerCaps->FullWake = TRUE;
995                         PowerCaps->VideoDimPresent = FALSE;
996                         PowerCaps->ApmPresent = FALSE;
997                         PowerCaps->UpsPresent = FALSE;
998                         PowerCaps->ThermalControl = FALSE;
999                         PowerCaps->ProcessorThrottle = FALSE;
1000                         PowerCaps->ProcessorMinThrottle = 100;
1001                         PowerCaps->ProcessorMaxThrottle = 100;
1002                         PowerCaps->DiskSpinDown = TRUE;
1003                         PowerCaps->SystemBatteriesPresent = FALSE;
1004                         PowerCaps->BatteriesAreShortTerm = FALSE;
1005                         PowerCaps->BatteryScale[0].Granularity = 0;
1006                         PowerCaps->BatteryScale[0].Capacity = 0;
1007                         PowerCaps->BatteryScale[1].Granularity = 0;
1008                         PowerCaps->BatteryScale[1].Capacity = 0;
1009                         PowerCaps->BatteryScale[2].Granularity = 0;
1010                         PowerCaps->BatteryScale[2].Capacity = 0;
1011                         PowerCaps->AcOnLineWake = PowerSystemUnspecified;
1012                         PowerCaps->SoftLidWake = PowerSystemUnspecified;
1013                         PowerCaps->RtcWake = PowerSystemSleeping1;
1014                         PowerCaps->MinDeviceWakeState = PowerSystemUnspecified;
1015                         PowerCaps->DefaultLowLatencyWake = PowerSystemUnspecified;
1016                         return STATUS_SUCCESS;
1017                 }
1018                 default:
1019                         FIXME("Unimplemented NtPowerInformation action: %d\n", InformationLevel);
1020                         return STATUS_NOT_IMPLEMENTED;
1021         }
1022 }
1023
1024 /******************************************************************************
1025  *  NtShutdownSystem                            [NTDLL.@]
1026  *
1027  */
1028 NTSTATUS WINAPI NtShutdownSystem(SHUTDOWN_ACTION Action)
1029 {
1030     FIXME("%d\n",Action);
1031     return STATUS_SUCCESS;
1032 }
1033
1034 /******************************************************************************
1035  *  NtAllocateLocallyUniqueId (NTDLL.@)
1036  *
1037  * FIXME: the server should do that
1038  */
1039 NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID Luid)
1040 {
1041     static LUID luid = { SE_MAX_WELL_KNOWN_PRIVILEGE, 0 };
1042
1043     FIXME("%p\n", Luid);
1044
1045     if (!Luid)
1046         return STATUS_ACCESS_VIOLATION;
1047
1048     luid.LowPart++;
1049     if (luid.LowPart==0)
1050         luid.HighPart++;
1051     Luid->HighPart = luid.HighPart;
1052     Luid->LowPart = luid.LowPart;
1053
1054     return STATUS_SUCCESS;
1055 }
1056
1057 /******************************************************************************
1058  *        VerSetConditionMask   (NTDLL.@)
1059  */
1060 ULONGLONG WINAPI VerSetConditionMask( ULONGLONG dwlConditionMask, DWORD dwTypeBitMask,
1061                                       BYTE dwConditionMask)
1062 {
1063     if(dwTypeBitMask == 0)
1064         return dwlConditionMask;
1065     dwConditionMask &= 0x07;
1066     if(dwConditionMask == 0)
1067         return dwlConditionMask;
1068
1069     if(dwTypeBitMask & VER_PRODUCT_TYPE)
1070         dwlConditionMask |= dwConditionMask << 7*3;
1071     else if (dwTypeBitMask & VER_SUITENAME)
1072         dwlConditionMask |= dwConditionMask << 6*3;
1073     else if (dwTypeBitMask & VER_SERVICEPACKMAJOR)
1074         dwlConditionMask |= dwConditionMask << 5*3;
1075     else if (dwTypeBitMask & VER_SERVICEPACKMINOR)
1076         dwlConditionMask |= dwConditionMask << 4*3;
1077     else if (dwTypeBitMask & VER_PLATFORMID)
1078         dwlConditionMask |= dwConditionMask << 3*3;
1079     else if (dwTypeBitMask & VER_BUILDNUMBER)
1080         dwlConditionMask |= dwConditionMask << 2*3;
1081     else if (dwTypeBitMask & VER_MAJORVERSION)
1082         dwlConditionMask |= dwConditionMask << 1*3;
1083     else if (dwTypeBitMask & VER_MINORVERSION)
1084         dwlConditionMask |= dwConditionMask << 0*3;
1085     return dwlConditionMask;
1086 }
1087
1088 /******************************************************************************
1089  *  NtAccessCheckAndAuditAlarm   (NTDLL.@)
1090  *  ZwAccessCheckAndAuditAlarm   (NTDLL.@)
1091  */
1092 NTSTATUS WINAPI NtAccessCheckAndAuditAlarm(PUNICODE_STRING SubsystemName, HANDLE HandleId, PUNICODE_STRING ObjectTypeName,
1093                                            PUNICODE_STRING ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor,
1094                                            ACCESS_MASK DesiredAccess, PGENERIC_MAPPING GenericMapping, BOOLEAN ObjectCreation,
1095                                            PACCESS_MASK GrantedAccess, PBOOLEAN AccessStatus, PBOOLEAN GenerateOnClose)
1096 {
1097     FIXME("(%s, %p, %s, %p, 0x%08lx, %p, %d, %p, %p, %p), stub\n", debugstr_us(SubsystemName), HandleId,
1098           debugstr_us(ObjectTypeName), SecurityDescriptor, DesiredAccess, GenericMapping, ObjectCreation,
1099           GrantedAccess, AccessStatus, GenerateOnClose);
1100
1101     return STATUS_NOT_IMPLEMENTED;
1102 }