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