Reverse the order for deleting the items in resetcontent to correctly
[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
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winreg.h"
34 #include "winternl.h"
35 #include "ntdll_misc.h"
36 #include "wine/server.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
39
40 /* Structures used by NtConnectPort */
41
42 typedef struct LpcSectionInfo
43 {
44   DWORD Length;
45   HANDLE SectionHandle;
46   DWORD Param1;
47   DWORD SectionSize;
48   DWORD ClientBaseAddress;
49   DWORD ServerBaseAddress;
50 } LPCSECTIONINFO, *PLPCSECTIONINFO;
51
52 typedef struct LpcSectionMapInfo
53 {
54   DWORD Length;
55   DWORD SectionSize;
56   DWORD ServerBaseAddress;
57 } LPCSECTIONMAPINFO, *PLPCSECTIONMAPINFO;
58
59 /* Structure used by NtAcceptConnectPort, NtReplyWaitReceivePort */
60
61 #define MAX_MESSAGE_DATA 328
62
63 typedef struct LpcMessage
64 {
65   WORD ActualMessageLength;
66   WORD TotalMessageLength;
67   DWORD MessageType;
68   DWORD ClientProcessId;
69   DWORD ClientThreadId;
70   DWORD MessageId;
71   DWORD SharedSectionSize;
72   BYTE MessageData[MAX_MESSAGE_DATA];
73 } LPCMESSAGE, *PLPCMESSAGE;
74
75 /*
76  *      Token
77  */
78
79 /******************************************************************************
80  *  NtDuplicateToken            [NTDLL.@]
81  *  ZwDuplicateToken            [NTDLL.@]
82  */
83 NTSTATUS WINAPI NtDuplicateToken(
84         IN HANDLE ExistingToken,
85         IN ACCESS_MASK DesiredAccess,
86         IN POBJECT_ATTRIBUTES ObjectAttributes,
87         IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
88         IN TOKEN_TYPE TokenType,
89         OUT PHANDLE NewToken)
90 {
91     NTSTATUS status;
92
93     TRACE("(%p,0x%08lx,%p,0x%08x,0x%08x,%p)\n",
94         ExistingToken, DesiredAccess, ObjectAttributes,
95         ImpersonationLevel, TokenType, NewToken);
96         dump_ObjectAttributes(ObjectAttributes);
97
98     SERVER_START_REQ( duplicate_token )
99     {
100         req->handle = ExistingToken;
101         req->access = DesiredAccess;
102         req->inherit = ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT);
103         req->primary = (TokenType == TokenPrimary);
104         req->impersonation_level = ImpersonationLevel;
105         status = wine_server_call( req );
106         if (!status) *NewToken = reply->new_handle;
107     }
108     SERVER_END_REQ;
109
110     return status;
111 }
112
113 /******************************************************************************
114  *  NtOpenProcessToken          [NTDLL.@]
115  *  ZwOpenProcessToken          [NTDLL.@]
116  */
117 NTSTATUS WINAPI NtOpenProcessToken(
118         HANDLE ProcessHandle,
119         DWORD DesiredAccess,
120         HANDLE *TokenHandle)
121 {
122     NTSTATUS ret;
123
124     TRACE("(%p,0x%08lx,%p)\n", ProcessHandle,DesiredAccess, TokenHandle);
125
126     SERVER_START_REQ( open_token )
127     {
128         req->handle = ProcessHandle;
129         req->flags  = 0;
130         ret = wine_server_call( req );
131         if (!ret) *TokenHandle = reply->token;
132     }
133     SERVER_END_REQ;
134
135     return ret;
136 }
137
138 /******************************************************************************
139  *  NtOpenThreadToken           [NTDLL.@]
140  *  ZwOpenThreadToken           [NTDLL.@]
141  */
142 NTSTATUS WINAPI NtOpenThreadToken(
143         HANDLE ThreadHandle,
144         DWORD DesiredAccess,
145         BOOLEAN OpenAsSelf,
146         HANDLE *TokenHandle)
147 {
148     NTSTATUS ret;
149
150     TRACE("(%p,0x%08lx,0x%08x,%p)\n",
151           ThreadHandle,DesiredAccess, OpenAsSelf, TokenHandle);
152
153     SERVER_START_REQ( open_token )
154     {
155         req->handle = ThreadHandle;
156         req->flags  = OPEN_TOKEN_THREAD;
157         if (OpenAsSelf) req->flags |= OPEN_TOKEN_AS_SELF;
158         ret = wine_server_call( req );
159         if (!ret) *TokenHandle = reply->token;
160     }
161     SERVER_END_REQ;
162
163     return ret;
164 }
165
166 /******************************************************************************
167  *  NtAdjustPrivilegesToken             [NTDLL.@]
168  *  ZwAdjustPrivilegesToken             [NTDLL.@]
169  *
170  * FIXME: parameters unsafe
171  */
172 NTSTATUS WINAPI NtAdjustPrivilegesToken(
173         IN HANDLE TokenHandle,
174         IN BOOLEAN DisableAllPrivileges,
175         IN PTOKEN_PRIVILEGES NewState,
176         IN DWORD BufferLength,
177         OUT PTOKEN_PRIVILEGES PreviousState,
178         OUT PDWORD ReturnLength)
179 {
180     NTSTATUS ret;
181
182     TRACE("(%p,0x%08x,%p,0x%08lx,%p,%p)\n",
183         TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength);
184
185     SERVER_START_REQ( adjust_token_privileges )
186     {
187         req->handle = TokenHandle;
188         req->disable_all = DisableAllPrivileges;
189         req->get_modified_state = (PreviousState != NULL);
190         if (!DisableAllPrivileges)
191         {
192             wine_server_add_data( req, &NewState->Privileges,
193                                   NewState->PrivilegeCount * sizeof(NewState->Privileges[0]) );
194         }
195         if (PreviousState && BufferLength >= FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ))
196             wine_server_set_reply( req, &PreviousState->Privileges,
197                                    BufferLength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) );
198         ret = wine_server_call( req );
199         if (PreviousState)
200         {
201             *ReturnLength = reply->len + FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges );
202             PreviousState->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES);
203         }
204     }
205     SERVER_END_REQ;
206
207     return ret;
208 }
209
210 /******************************************************************************
211 *  NtQueryInformationToken              [NTDLL.@]
212 *  ZwQueryInformationToken              [NTDLL.@]
213 *
214 * NOTES
215 *  Buffer for TokenUser:
216 *   0x00 TOKEN_USER the PSID field points to the SID
217 *   0x08 SID
218 *
219 */
220 NTSTATUS WINAPI NtQueryInformationToken(
221         HANDLE token,
222         DWORD tokeninfoclass,
223         LPVOID tokeninfo,
224         DWORD tokeninfolength,
225         LPDWORD retlen )
226 {
227     unsigned int len = 0;
228     NTSTATUS status = STATUS_SUCCESS;
229
230     TRACE("(%p,%ld,%p,%ld,%p)\n",
231           token,tokeninfoclass,tokeninfo,tokeninfolength,retlen);
232
233     switch (tokeninfoclass)
234     {
235     case TokenUser:
236         len = sizeof(TOKEN_USER) + sizeof(SID);
237         break;
238     case TokenGroups:
239         len = sizeof(TOKEN_GROUPS);
240         break;
241     case TokenOwner:
242         len = sizeof(TOKEN_OWNER) + sizeof(SID);
243         break;
244     case TokenPrimaryGroup:
245         len = sizeof(TOKEN_PRIMARY_GROUP);
246         break;
247     case TokenDefaultDacl:
248         len = sizeof(TOKEN_DEFAULT_DACL);
249         break;
250     case TokenSource:
251         len = sizeof(TOKEN_SOURCE);
252         break;
253     case TokenType:
254         len = sizeof (TOKEN_TYPE);
255         break;
256 #if 0
257     case TokenImpersonationLevel:
258     case TokenStatistics:
259 #endif /* 0 */
260     }
261
262     /* FIXME: what if retlen == NULL ? */
263     *retlen = len;
264
265     if (tokeninfolength < len)
266         return STATUS_BUFFER_TOO_SMALL;
267
268     switch (tokeninfoclass)
269     {
270     case TokenUser:
271         if( tokeninfo )
272         {
273             TOKEN_USER * tuser = tokeninfo;
274             PSID sid = (PSID) (tuser + 1);
275             SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
276             RtlInitializeSid(sid, &localSidAuthority, 1);
277             *(RtlSubAuthoritySid(sid, 0)) = SECURITY_INTERACTIVE_RID;
278             tuser->User.Sid = sid;
279         }
280         break;
281     case TokenGroups:
282         if (tokeninfo)
283         {
284             TOKEN_GROUPS *tgroups = tokeninfo;
285             SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
286
287             /* we need to show admin privileges ! */
288             tgroups->GroupCount = 1;
289             tgroups->Groups->Attributes = SE_GROUP_ENABLED;
290             RtlAllocateAndInitializeSid( &sid,
291                                          2,
292                                          SECURITY_BUILTIN_DOMAIN_RID,
293                                          DOMAIN_ALIAS_RID_ADMINS,
294                                          0, 0, 0, 0, 0, 0,
295                                          &(tgroups->Groups->Sid));
296         }
297         break;
298     case TokenPrimaryGroup:
299         if (tokeninfo)
300         {
301             TOKEN_PRIMARY_GROUP *tgroup = tokeninfo;
302             SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
303             RtlAllocateAndInitializeSid( &sid,
304                                          2,
305                                          SECURITY_BUILTIN_DOMAIN_RID,
306                                          DOMAIN_ALIAS_RID_ADMINS,
307                                          0, 0, 0, 0, 0, 0,
308                                          &(tgroup->PrimaryGroup));
309         }
310         break;
311     case TokenPrivileges:
312         SERVER_START_REQ( get_token_privileges )
313         {
314             TOKEN_PRIVILEGES *tpriv = tokeninfo;
315             req->handle = token;
316             if (tpriv && tokeninfolength > FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ))
317                 wine_server_set_reply( req, &tpriv->Privileges, tokeninfolength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) );
318             status = wine_server_call( req );
319             *retlen = FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) + reply->len;
320             if (tpriv) tpriv->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES);
321         }
322         SERVER_END_REQ;
323         break;
324     case TokenOwner:
325         if (tokeninfo)
326         {
327             TOKEN_OWNER *owner = tokeninfo;
328             PSID sid = (PSID) (owner + 1);
329             SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
330             RtlInitializeSid(sid, &localSidAuthority, 1);
331             *(RtlSubAuthoritySid(sid, 0)) = SECURITY_INTERACTIVE_RID;
332             owner->Owner = sid;
333         }
334         break;
335     default:
336         {
337             ERR("Unhandled Token Information class %ld!\n", tokeninfoclass);
338             return STATUS_NOT_IMPLEMENTED;
339         }
340     }
341     return status;
342 }
343
344 /******************************************************************************
345 *  NtSetInformationToken                [NTDLL.@]
346 *  ZwSetInformationToken                [NTDLL.@]
347 */
348 NTSTATUS WINAPI NtSetInformationToken(
349         HANDLE TokenHandle,
350         TOKEN_INFORMATION_CLASS TokenInformationClass,
351         PVOID TokenInformation,
352         ULONG TokenInformationLength)
353 {
354     FIXME("%p %d %p %lu\n", TokenHandle, TokenInformationClass,
355           TokenInformation, TokenInformationLength);
356     return STATUS_NOT_IMPLEMENTED;
357 }
358
359 /******************************************************************************
360 *  NtAdjustGroupsToken          [NTDLL.@]
361 *  ZwAdjustGroupsToken          [NTDLL.@]
362 */
363 NTSTATUS WINAPI NtAdjustGroupsToken(
364         HANDLE TokenHandle,
365         BOOLEAN ResetToDefault,
366         PTOKEN_GROUPS NewState,
367         ULONG BufferLength,
368         PTOKEN_GROUPS PreviousState,
369         PULONG ReturnLength)
370 {
371     FIXME("%p %d %p %lu %p %p\n", TokenHandle, ResetToDefault,
372           NewState, BufferLength, PreviousState, ReturnLength);
373     return STATUS_NOT_IMPLEMENTED;
374 }
375
376 /*
377  *      Section
378  */
379
380 /******************************************************************************
381  *  NtQuerySection      [NTDLL.@]
382  */
383 NTSTATUS WINAPI NtQuerySection(
384         IN HANDLE SectionHandle,
385         IN PVOID SectionInformationClass,
386         OUT PVOID SectionInformation,
387         IN ULONG Length,
388         OUT PULONG ResultLength)
389 {
390         FIXME("(%p,%p,%p,0x%08lx,%p) stub!\n",
391         SectionHandle,SectionInformationClass,SectionInformation,Length,ResultLength);
392         return 0;
393 }
394
395 /*
396  *      ports
397  */
398
399 /******************************************************************************
400  *  NtCreatePort                [NTDLL.@]
401  *  ZwCreatePort                [NTDLL.@]
402  */
403 NTSTATUS WINAPI NtCreatePort(PHANDLE PortHandle,POBJECT_ATTRIBUTES ObjectAttributes,
404                              DWORD MaxConnectInfoLength,DWORD MaxDataLength,DWORD unknown)
405 {
406   FIXME("(%p,%p,0x%08lx,0x%08lx,0x%08lx),stub!\n",PortHandle,ObjectAttributes,
407         MaxConnectInfoLength,MaxDataLength,unknown);
408   return 0;
409 }
410
411 /******************************************************************************
412  *  NtConnectPort               [NTDLL.@]
413  *  ZwConnectPort               [NTDLL.@]
414  */
415 NTSTATUS WINAPI NtConnectPort(PHANDLE PortHandle,PUNICODE_STRING PortName,PVOID Unknown1,
416                               PLPCSECTIONINFO sectionInfo,PLPCSECTIONMAPINFO mapInfo,PVOID Unknown2,
417                               PVOID ConnectInfo,PDWORD pConnectInfoLength)
418 {
419   FIXME("(%p,%s,%p,%p,%p,%p,%p,%p (%ld)),stub!\n",PortHandle,debugstr_w(PortName->Buffer),Unknown1,
420         sectionInfo,mapInfo,Unknown2,ConnectInfo,pConnectInfoLength,pConnectInfoLength?*pConnectInfoLength:-1);
421   if(ConnectInfo && pConnectInfoLength)
422     TRACE("\tMessage = %s\n",debugstr_an(ConnectInfo,*pConnectInfoLength));
423   return 0;
424 }
425
426 /******************************************************************************
427  *  NtListenPort                [NTDLL.@]
428  *  ZwListenPort                [NTDLL.@]
429  */
430 NTSTATUS WINAPI NtListenPort(HANDLE PortHandle,PLPCMESSAGE pLpcMessage)
431 {
432   FIXME("(%p,%p),stub!\n",PortHandle,pLpcMessage);
433   return 0;
434 }
435
436 /******************************************************************************
437  *  NtAcceptConnectPort [NTDLL.@]
438  *  ZwAcceptConnectPort [NTDLL.@]
439  */
440 NTSTATUS WINAPI NtAcceptConnectPort(PHANDLE PortHandle,DWORD Unknown,PLPCMESSAGE pLpcMessage,
441                                     DWORD acceptIt,DWORD Unknown2,PLPCSECTIONMAPINFO mapInfo)
442 {
443   FIXME("(%p,0x%08lx,%p,0x%08lx,0x%08lx,%p),stub!\n",PortHandle,Unknown,pLpcMessage,acceptIt,Unknown2,mapInfo);
444   return 0;
445 }
446
447 /******************************************************************************
448  *  NtCompleteConnectPort       [NTDLL.@]
449  *  ZwCompleteConnectPort       [NTDLL.@]
450  */
451 NTSTATUS WINAPI NtCompleteConnectPort(HANDLE PortHandle)
452 {
453   FIXME("(%p),stub!\n",PortHandle);
454   return 0;
455 }
456
457 /******************************************************************************
458  *  NtRegisterThreadTerminatePort       [NTDLL.@]
459  *  ZwRegisterThreadTerminatePort       [NTDLL.@]
460  */
461 NTSTATUS WINAPI NtRegisterThreadTerminatePort(HANDLE PortHandle)
462 {
463   FIXME("(%p),stub!\n",PortHandle);
464   return 0;
465 }
466
467 /******************************************************************************
468  *  NtRequestWaitReplyPort              [NTDLL.@]
469  *  ZwRequestWaitReplyPort              [NTDLL.@]
470  */
471 NTSTATUS WINAPI NtRequestWaitReplyPort(HANDLE PortHandle,PLPCMESSAGE pLpcMessageIn,PLPCMESSAGE pLpcMessageOut)
472 {
473   FIXME("(%p,%p,%p),stub!\n",PortHandle,pLpcMessageIn,pLpcMessageOut);
474   if(pLpcMessageIn)
475   {
476     TRACE("Message to send:\n");
477     TRACE("\tActualMessageLength = %d\n",pLpcMessageIn->ActualMessageLength);
478     TRACE("\tTotalMessageLength  = %d\n",pLpcMessageIn->TotalMessageLength);
479     TRACE("\tMessageType         = %ld\n",pLpcMessageIn->MessageType);
480     TRACE("\tClientProcessId     = %ld\n",pLpcMessageIn->ClientProcessId);
481     TRACE("\tClientThreadId      = %ld\n",pLpcMessageIn->ClientThreadId);
482     TRACE("\tMessageId           = %ld\n",pLpcMessageIn->MessageId);
483     TRACE("\tSharedSectionSize   = %ld\n",pLpcMessageIn->SharedSectionSize);
484     TRACE("\tMessageData         = %s\n",debugstr_an(pLpcMessageIn->MessageData,pLpcMessageIn->ActualMessageLength));
485   }
486   return 0;
487 }
488
489 /******************************************************************************
490  *  NtReplyWaitReceivePort      [NTDLL.@]
491  *  ZwReplyWaitReceivePort      [NTDLL.@]
492  */
493 NTSTATUS WINAPI NtReplyWaitReceivePort(HANDLE PortHandle,PDWORD Unknown,PLPCMESSAGE pLpcMessageOut,PLPCMESSAGE pLpcMessageIn)
494 {
495   FIXME("(%p,%p,%p,%p),stub!\n",PortHandle,Unknown,pLpcMessageOut,pLpcMessageIn);
496   return 0;
497 }
498
499 /*
500  *      Misc
501  */
502
503  /******************************************************************************
504  *  NtSetIntervalProfile        [NTDLL.@]
505  *  ZwSetIntervalProfile        [NTDLL.@]
506  */
507 NTSTATUS WINAPI NtSetIntervalProfile(DWORD x1,DWORD x2) {
508         FIXME("(0x%08lx,0x%08lx),stub!\n",x1,x2);
509         return 0;
510 }
511
512 /******************************************************************************
513  *  NtQueryPerformanceCounter   [NTDLL.@]
514  *
515  *  Note: Windows uses a timer clocked at a multiple of 1193182 Hz.
516  *  
517  */
518 NTSTATUS WINAPI NtQueryPerformanceCounter(
519         OUT PLARGE_INTEGER Counter,
520         OUT PLARGE_INTEGER Frequency)
521 {
522     LARGE_INTEGER time;
523
524     if (!Counter) return STATUS_ACCESS_VIOLATION;
525     NtQuerySystemTime( &time );
526     Counter->QuadPart = time.QuadPart;
527     if (Frequency)
528         Frequency->QuadPart = 10000000;
529     return 0;
530 }
531
532 /******************************************************************************
533  *  NtCreateMailslotFile        [NTDLL.@]
534  *  ZwCreateMailslotFile        [NTDLL.@]
535  */
536 NTSTATUS WINAPI NtCreateMailslotFile(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6,DWORD x7,DWORD x8)
537 {
538         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4,x5,x6,x7,x8);
539         return 0;
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 = (SYSTEM_BASIC_INFORMATION*)SystemInformation;
578             if (Length >= sizeof(*sbi))
579             {
580                 sbi->dwUnknown1 = 0;
581                 sbi->uKeMaximumIncrement = 0;
582                 sbi->uPageSize = 1024; /* FIXME */
583                 sbi->uMmNumberOfPhysicalPages = 12345; /* FIXME */
584                 sbi->uMmLowestPhysicalPage = 0; /* FIXME */
585                 sbi->uMmHighestPhysicalPage = 12345; /* FIXME */
586                 sbi->uAllocationGranularity = 65536; /* FIXME */
587                 sbi->pLowestUserAddress = 0; /* FIXME */
588                 sbi->pMmHighestUserAddress = (void*)~0; /* FIXME */
589                 sbi->uKeActiveProcessors = 1; /* FIXME */
590                 sbi->bKeNumberProcessors = 1; /* FIXME */
591                 len = sizeof(*sbi);
592             }
593             else ret = STATUS_INFO_LENGTH_MISMATCH;
594         }
595         break;
596     case SystemCpuInformation:
597         {
598             SYSTEM_CPU_INFORMATION* sci;
599             sci = (SYSTEM_CPU_INFORMATION *) SystemInformation;
600             if (Length >= sizeof(*sci))
601             {
602                 /* FIXME: move some code from kernel/cpu.c to process this */
603                 sci->Architecture = PROCESSOR_ARCHITECTURE_INTEL;
604                 sci->Level = 6; /* 686, aka Pentium II+ */
605                 sci->Revision = 0;
606                 sci->Reserved = 0;
607                 sci->FeatureSet = 0x1fff;
608             }
609             else ret = STATUS_INFO_LENGTH_MISMATCH;
610         }
611         break;
612     case SystemPerformanceInformation:
613         {
614             SYSTEM_PERFORMANCE_INFORMATION* spi = (SYSTEM_PERFORMANCE_INFORMATION*)SystemInformation;
615             if (Length >= sizeof(*spi))
616             {
617                 memset(spi, 0, sizeof(*spi)); /* FIXME */
618                 len = sizeof(*spi);
619             }
620             else ret = STATUS_INFO_LENGTH_MISMATCH;
621         }
622         break;
623     case SystemTimeOfDayInformation:
624         {
625             SYSTEM_TIMEOFDAY_INFORMATION* sti = (SYSTEM_TIMEOFDAY_INFORMATION*)SystemInformation;
626             if (Length >= sizeof(*sti))
627             {
628                 sti->liKeBootTime.QuadPart = 0; /* FIXME */
629                 sti->liKeSystemTime.QuadPart = 0; /* FIXME */
630                 sti->liExpTimeZoneBias.QuadPart  = 0; /* FIXME */
631                 sti->uCurrentTimeZoneId = 0; /* FIXME */
632                 sti->dwReserved = 0;
633                 len = sizeof(*sti);
634             }
635             else ret = STATUS_INFO_LENGTH_MISMATCH;
636         }
637         break;
638     case SystemProcessInformation:
639         {
640             SYSTEM_PROCESS_INFORMATION* spi = (SYSTEM_PROCESS_INFORMATION*)SystemInformation;
641             SYSTEM_PROCESS_INFORMATION* last = NULL;
642             HANDLE hSnap = 0;
643             WCHAR procname[1024];
644             DWORD wlen = 0;
645
646             SERVER_START_REQ( create_snapshot )
647             {
648                 req->flags   = SNAP_PROCESS | SNAP_THREAD;
649                 req->inherit = FALSE;
650                 req->pid     = 0;
651                 if (!(ret = wine_server_call( req ))) hSnap = reply->handle;
652             }
653             SERVER_END_REQ;
654             len = 0;
655             while (ret == STATUS_SUCCESS)
656             {
657                 SERVER_START_REQ( next_process )
658                 {
659                     req->handle = hSnap;
660                     req->reset = (len == 0);
661                     wine_server_set_reply( req, procname, sizeof(procname) );
662                     if (!(ret = wine_server_call( req )))
663                     {
664                         wlen = wine_server_reply_size(reply) + sizeof(WCHAR);
665                         if (Length >= len + sizeof(*spi))
666                         {
667                             memset(spi, 0, sizeof(*spi));
668                             spi->dwOffset = sizeof(*spi);
669                             spi->dwThreadCount = reply->threads;
670                             memset(&spi->ftCreationTime, 0, sizeof(spi->ftCreationTime));
671                             /* spi->pszProcessName will be set later on */
672                             spi->dwBasePriority = reply->priority;
673                             spi->dwProcessID = (DWORD)reply->pid;
674                             spi->dwParentProcessID = (DWORD)reply->ppid;
675                             spi->dwHandleCount = reply->handles;
676                             spi->dwVirtualBytesPeak = 0; /* FIXME */
677                             spi->dwVirtualBytes = 0; /* FIXME */
678                             spi->dwPageFaults = 0; /* FIXME */
679                             spi->dwWorkingSetPeak = 0; /* FIXME */
680                             spi->dwWorkingSet = 0; /* FIXME */
681                             spi->dwUnknown5 = 0; /* FIXME */
682                             spi->dwPagedPool = 0; /* FIXME */
683                             spi->dwUnknown6 = 0; /* FIXME */
684                             spi->dwNonPagedPool = 0; /* FIXME */
685                             spi->dwPageFileBytesPeak = 0; /* FIXME */
686                             spi->dwPrivateBytes = 0; /* FIXME */
687                             spi->dwPageFileBytes = 0; /* FIXME */
688                             /* spi->ti will be set later on */
689                             len += sizeof(*spi) - sizeof(spi->ti);
690                         }
691                         else ret = STATUS_INFO_LENGTH_MISMATCH;
692                     }
693                 }
694                 SERVER_END_REQ;
695                 if (ret != STATUS_SUCCESS)
696                 {
697                     if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
698                     break;
699                 }
700                 if (Length >= len + wlen + spi->dwThreadCount * sizeof(THREAD_INFO))
701                 {
702                     int     i, j;
703
704                     /* set thread info */
705                     spi->dwOffset += spi->dwThreadCount * sizeof(THREAD_INFO);
706                     len += spi->dwThreadCount * sizeof(THREAD_INFO);
707                     i = j = 0;
708                     while (ret == STATUS_SUCCESS)
709                     {
710                         SERVER_START_REQ( next_thread )
711                         {
712                             req->handle = hSnap;
713                             req->reset = (j == 0);
714                             if (!(ret = wine_server_call( req )))
715                             {
716                                 j++;
717                                 if (reply->pid == spi->dwProcessID)
718                                 {
719                                     /* ftKernelTime, ftUserTime, ftCreateTime;
720                                      * dwTickCount, dwStartAddress
721                                      */
722                                     spi->ti[i].dwOwningPID = reply->pid;
723                                     spi->ti[i].dwThreadID  = reply->tid;
724                                     spi->ti[i].dwCurrentPriority = reply->base_pri + reply->delta_pri;
725                                     spi->ti[i].dwBasePriority = reply->base_pri;
726                                     i++;
727                                 }
728                             }
729                         }
730                         SERVER_END_REQ;
731                     }
732                     if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
733
734                     /* now append process name */
735                     spi->pszProcessName = (WCHAR*)((char*)spi + spi->dwOffset);
736                     memcpy( spi->pszProcessName, procname, wlen - sizeof(WCHAR) );
737                     spi->pszProcessName[wlen / sizeof(WCHAR)] = 0;
738                     len += wlen;
739                     spi->dwOffset += wlen;
740
741                     last = spi;
742                     spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + spi->dwOffset);
743                 }
744                 else ret = STATUS_INFO_LENGTH_MISMATCH;
745             }
746             if (ret == STATUS_SUCCESS && last) last->dwOffset = 0;
747             if (hSnap) NtClose(hSnap);
748         }
749         break;
750     case SystemProcessorPerformanceInformation:
751         {
752             SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*)SystemInformation;
753             if (Length >= sizeof(*sppi))
754             {
755                 memset(sppi, 0, sizeof(*sppi)); /* FIXME */
756                 len = sizeof(*sppi);
757             }
758             else ret = STATUS_INFO_LENGTH_MISMATCH;
759         }
760         break;
761
762     case SystemCacheInformation:
763         {
764             SYSTEM_CACHE_INFORMATION* sci = (SYSTEM_CACHE_INFORMATION*)SystemInformation;
765             if (Length >= sizeof(*sci))
766             {
767                 memset(sci, 0, sizeof(*sci)); /* FIXME */
768                 len = sizeof(*sci);
769             }
770             else ret = STATUS_INFO_LENGTH_MISMATCH;
771         }
772         break;
773     case SystemRegistryQuotaInformation:
774         /* Something to do with the size of the registry             *
775          * Since we don't have a size limitation, fake it            *
776          * This is almost certainly wrong.                           *
777          * This sets each of the three words in the struct to 32 MB, *
778          * which is enough to make the IE 5 installer happy.         */
779         {
780             SYSTEM_REGISTRY_QUOTA_INFORMATION* srqi = (SYSTEM_REGISTRY_QUOTA_INFORMATION*)SystemInformation;
781             if (Length >= sizeof(*srqi))
782             {
783                 FIXME("(0x%08x,%p,0x%08lx,%p) faking max registry size of 32 MB\n",
784                       SystemInformationClass,SystemInformation,Length,ResultLength);
785                 srqi->RegistryQuotaAllowed = 0x2000000;
786                 srqi->RegistryQuotaUsed = 0x200000;
787                 srqi->Reserved1 = (void*)0x200000;
788                 len = sizeof(*srqi);
789             }
790             else ret = STATUS_INFO_LENGTH_MISMATCH;
791         }
792         break;
793
794     case SystemKernelDebuggerInformation:
795         {
796             PSYSTEM_KERNEL_DEBUGGER_INFORMATION pkdi;
797             if( Length >= sizeof(*pkdi))
798             {
799                 pkdi = SystemInformation;
800                 pkdi->DebuggerEnabled = FALSE;
801                 pkdi->DebuggerNotPresent = TRUE;
802                 len = sizeof(*pkdi);
803             }
804             else ret = STATUS_INFO_LENGTH_MISMATCH;
805         }
806         break;
807
808     default:
809         FIXME("(0x%08x,%p,0x%08lx,%p) stub\n",
810               SystemInformationClass,SystemInformation,Length,ResultLength);
811         ret = STATUS_NOT_IMPLEMENTED;
812     }
813     if (ResultLength) *ResultLength = len;
814
815     return ret;
816 }
817
818
819 /******************************************************************************
820  *  NtCreatePagingFile          [NTDLL.@]
821  *  ZwCreatePagingFile          [NTDLL.@]
822  */
823 NTSTATUS WINAPI NtCreatePagingFile(
824         IN PUNICODE_STRING PageFileName,
825         IN ULONG MiniumSize,
826         IN ULONG MaxiumSize,
827         OUT PULONG ActualSize)
828 {
829         FIXME("(%p(%s),0x%08lx,0x%08lx,%p),stub!\n",
830         PageFileName->Buffer, debugstr_w(PageFileName->Buffer),MiniumSize,MaxiumSize,ActualSize);
831         return 0;
832 }
833
834 /******************************************************************************
835  *  NtDisplayString                             [NTDLL.@]
836  *
837  * writes a string to the nt-textmode screen eg. during startup
838  */
839 NTSTATUS WINAPI NtDisplayString ( PUNICODE_STRING string )
840 {
841     STRING stringA;
842     NTSTATUS ret;
843
844     if (!(ret = RtlUnicodeStringToAnsiString( &stringA, string, TRUE )))
845     {
846         MESSAGE( "%.*s", stringA.Length, stringA.Buffer );
847         RtlFreeAnsiString( &stringA );
848     }
849     return ret;
850 }
851
852 /******************************************************************************
853  *  NtPowerInformation                          [NTDLL.@]
854  *
855  */
856 NTSTATUS WINAPI NtPowerInformation(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5)
857 {
858         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub\n",x1,x2,x3,x4,x5);
859         return 0;
860 }
861
862 /******************************************************************************
863  *  NtShutdownSystem                            [NTDLL.@]
864  *
865  */
866 NTSTATUS WINAPI NtShutdownSystem(DWORD x1)
867 {
868         FIXME("(0x%08lx),stub\n",x1);
869         return 0;
870 }
871
872 /******************************************************************************
873  *  NtAllocateLocallyUniqueId (NTDLL.@)
874  *
875  * FIXME: the server should do that
876  */
877 NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID Luid)
878 {
879     static LUID luid = { SE_MAX_WELL_KNOWN_PRIVILEGE, 0 };
880
881     FIXME("%p\n", Luid);
882
883     if (!Luid)
884         return STATUS_ACCESS_VIOLATION;
885
886     luid.LowPart++;
887     if (luid.LowPart==0)
888         luid.HighPart++;
889     Luid->HighPart = luid.HighPart;
890     Luid->LowPart = luid.LowPart;
891
892     return STATUS_SUCCESS;
893 }
894
895 /******************************************************************************
896  *        VerSetConditionMask   (NTDLL.@)
897  */
898 ULONGLONG WINAPI VerSetConditionMask( ULONGLONG dwlConditionMask, DWORD dwTypeBitMask,
899                                       BYTE dwConditionMask)
900 {
901     if(dwTypeBitMask == 0)
902         return dwlConditionMask;
903     dwConditionMask &= 0x07;
904     if(dwConditionMask == 0)
905         return dwlConditionMask;
906
907     if(dwTypeBitMask & VER_PRODUCT_TYPE)
908         dwlConditionMask |= dwConditionMask << 7*3;
909     else if (dwTypeBitMask & VER_SUITENAME)
910         dwlConditionMask |= dwConditionMask << 6*3;
911     else if (dwTypeBitMask & VER_SERVICEPACKMAJOR)
912         dwlConditionMask |= dwConditionMask << 5*3;
913     else if (dwTypeBitMask & VER_SERVICEPACKMINOR)
914         dwlConditionMask |= dwConditionMask << 4*3;
915     else if (dwTypeBitMask & VER_PLATFORMID)
916         dwlConditionMask |= dwConditionMask << 3*3;
917     else if (dwTypeBitMask & VER_BUILDNUMBER)
918         dwlConditionMask |= dwConditionMask << 2*3;
919     else if (dwTypeBitMask & VER_MAJORVERSION)
920         dwlConditionMask |= dwConditionMask << 1*3;
921     else if (dwTypeBitMask & VER_MINORVERSION)
922         dwlConditionMask |= dwConditionMask << 0*3;
923     return dwlConditionMask;
924 }
925
926 /******************************************************************************
927  *        NtAlertThread   (NTDLL.@)
928  */
929 NTSTATUS WINAPI NtAlertThread(HANDLE ThreadHandle)
930 {
931     FIXME("%p\n", ThreadHandle);
932     return STATUS_NOT_IMPLEMENTED;
933 }