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