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