ntdll: Report end of file instead of broken pipe on char devices.
[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     SERVER_START_REQ( duplicate_token )
65     {
66         req->handle              = ExistingToken;
67         req->access              = DesiredAccess;
68         req->attributes          = ObjectAttributes ? ObjectAttributes->Attributes : 0;
69         req->primary             = (TokenType == TokenPrimary);
70         req->impersonation_level = ImpersonationLevel;
71         status = wine_server_call( req );
72         if (!status) *NewToken = reply->new_handle;
73     }
74     SERVER_END_REQ;
75
76     return status;
77 }
78
79 /******************************************************************************
80  *  NtOpenProcessToken          [NTDLL.@]
81  *  ZwOpenProcessToken          [NTDLL.@]
82  */
83 NTSTATUS WINAPI NtOpenProcessToken(
84         HANDLE ProcessHandle,
85         DWORD DesiredAccess,
86         HANDLE *TokenHandle)
87 {
88     NTSTATUS ret;
89
90     TRACE("(%p,0x%08x,%p)\n", ProcessHandle,DesiredAccess, TokenHandle);
91
92     SERVER_START_REQ( open_token )
93     {
94         req->handle     = ProcessHandle;
95         req->access     = DesiredAccess;
96         req->attributes = 0;
97         req->flags      = 0;
98         ret = wine_server_call( req );
99         if (!ret) *TokenHandle = reply->token;
100     }
101     SERVER_END_REQ;
102
103     return ret;
104 }
105
106 /******************************************************************************
107  *  NtOpenThreadToken           [NTDLL.@]
108  *  ZwOpenThreadToken           [NTDLL.@]
109  */
110 NTSTATUS WINAPI NtOpenThreadToken(
111         HANDLE ThreadHandle,
112         DWORD DesiredAccess,
113         BOOLEAN OpenAsSelf,
114         HANDLE *TokenHandle)
115 {
116     NTSTATUS ret;
117
118     TRACE("(%p,0x%08x,0x%08x,%p)\n",
119           ThreadHandle,DesiredAccess, OpenAsSelf, TokenHandle);
120
121     SERVER_START_REQ( open_token )
122     {
123         req->handle     = ThreadHandle;
124         req->access     = DesiredAccess;
125         req->attributes = 0;
126         req->flags      = OPEN_TOKEN_THREAD;
127         if (OpenAsSelf) req->flags |= OPEN_TOKEN_AS_SELF;
128         ret = wine_server_call( req );
129         if (!ret) *TokenHandle = reply->token;
130     }
131     SERVER_END_REQ;
132
133     return ret;
134 }
135
136 /******************************************************************************
137  *  NtAdjustPrivilegesToken             [NTDLL.@]
138  *  ZwAdjustPrivilegesToken             [NTDLL.@]
139  *
140  * FIXME: parameters unsafe
141  */
142 NTSTATUS WINAPI NtAdjustPrivilegesToken(
143         IN HANDLE TokenHandle,
144         IN BOOLEAN DisableAllPrivileges,
145         IN PTOKEN_PRIVILEGES NewState,
146         IN DWORD BufferLength,
147         OUT PTOKEN_PRIVILEGES PreviousState,
148         OUT PDWORD ReturnLength)
149 {
150     NTSTATUS ret;
151
152     TRACE("(%p,0x%08x,%p,0x%08x,%p,%p)\n",
153         TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength);
154
155     SERVER_START_REQ( adjust_token_privileges )
156     {
157         req->handle = TokenHandle;
158         req->disable_all = DisableAllPrivileges;
159         req->get_modified_state = (PreviousState != NULL);
160         if (!DisableAllPrivileges)
161         {
162             wine_server_add_data( req, &NewState->Privileges,
163                                   NewState->PrivilegeCount * sizeof(NewState->Privileges[0]) );
164         }
165         if (PreviousState && BufferLength >= FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ))
166             wine_server_set_reply( req, &PreviousState->Privileges,
167                                    BufferLength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) );
168         ret = wine_server_call( req );
169         if (PreviousState)
170         {
171             *ReturnLength = reply->len + FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges );
172             PreviousState->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES);
173         }
174     }
175     SERVER_END_REQ;
176
177     return ret;
178 }
179
180 /******************************************************************************
181 *  NtQueryInformationToken              [NTDLL.@]
182 *  ZwQueryInformationToken              [NTDLL.@]
183 *
184 * NOTES
185 *  Buffer for TokenUser:
186 *   0x00 TOKEN_USER the PSID field points to the SID
187 *   0x08 SID
188 *
189 */
190 NTSTATUS WINAPI NtQueryInformationToken(
191         HANDLE token,
192         TOKEN_INFORMATION_CLASS tokeninfoclass,
193         PVOID tokeninfo,
194         ULONG tokeninfolength,
195         PULONG retlen )
196 {
197     ULONG len;
198     NTSTATUS status = STATUS_SUCCESS;
199
200     TRACE("(%p,%d,%p,%d,%p)\n",
201           token,tokeninfoclass,tokeninfo,tokeninfolength,retlen);
202
203     switch (tokeninfoclass)
204     {
205     case TokenOwner:
206         len = sizeof(TOKEN_OWNER) + sizeof(SID);
207         break;
208     case TokenPrimaryGroup:
209         len = sizeof(TOKEN_PRIMARY_GROUP);
210         break;
211     case TokenDefaultDacl:
212         len = sizeof(TOKEN_DEFAULT_DACL);
213         break;
214     case TokenSource:
215         len = sizeof(TOKEN_SOURCE);
216         break;
217     case TokenType:
218         len = sizeof (TOKEN_TYPE);
219         break;
220     case TokenImpersonationLevel:
221         len = sizeof(SECURITY_IMPERSONATION_LEVEL);
222         break;
223 #if 0
224     case TokenStatistics:
225 #endif /* 0 */
226     default:
227         len = 0;
228     }
229
230     if (retlen) *retlen = len;
231
232     if (tokeninfolength < len)
233         return STATUS_BUFFER_TOO_SMALL;
234
235     switch (tokeninfoclass)
236     {
237     case TokenUser:
238         SERVER_START_REQ( get_token_user )
239         {
240             TOKEN_USER * tuser = tokeninfo;
241             PSID sid = (PSID) (tuser + 1);
242             DWORD sid_len = tokeninfolength < sizeof(TOKEN_USER) ? 0 : tokeninfolength - sizeof(TOKEN_USER);
243
244             req->handle = token;
245             wine_server_set_reply( req, sid, sid_len );
246             status = wine_server_call( req );
247             if (retlen) *retlen = reply->user_len + sizeof(TOKEN_USER);
248             if (status == STATUS_SUCCESS)
249             {
250                 tuser->User.Sid = sid;
251                 tuser->User.Attributes = 0;
252             }
253         }
254         SERVER_END_REQ;
255         break;
256     case TokenGroups:
257     {
258         char stack_buffer[256];
259         unsigned int server_buf_len = sizeof(stack_buffer);
260         void *buffer = stack_buffer;
261         BOOLEAN need_more_memory = FALSE;
262
263         /* we cannot work out the size of the server buffer required for the
264          * input size, since there are two factors affecting how much can be
265          * stored in the buffer - number of groups and lengths of sids */
266         do
267         {
268             SERVER_START_REQ( get_token_groups )
269             {
270                 TOKEN_GROUPS *groups = tokeninfo;
271
272                 req->handle = token;
273                 wine_server_set_reply( req, buffer, server_buf_len );
274                 status = wine_server_call( req );
275                 if (status == STATUS_BUFFER_TOO_SMALL)
276                 {
277                     if (buffer == stack_buffer)
278                         buffer = RtlAllocateHeap(GetProcessHeap(), 0, reply->user_len);
279                     else
280                         buffer = RtlReAllocateHeap(GetProcessHeap(), 0, buffer, reply->user_len);
281                     if (!buffer) return STATUS_NO_MEMORY;
282
283                     server_buf_len = reply->user_len;
284                     need_more_memory = TRUE;
285                 }
286                 else if (status == STATUS_SUCCESS)
287                 {
288                     struct token_groups *tg = buffer;
289                     unsigned int *attr = (unsigned int *)(tg + 1);
290                     ULONG i;
291                     const int non_sid_portion = (sizeof(struct token_groups) + tg->count * sizeof(unsigned long));
292                     SID *sids = (SID *)((char *)tokeninfo + FIELD_OFFSET( TOKEN_GROUPS, Groups[tg->count] ));
293                     ULONG needed_bytes = FIELD_OFFSET( TOKEN_GROUPS, Groups[tg->count] ) +
294                         reply->user_len - non_sid_portion;
295
296                     if (retlen) *retlen = needed_bytes;
297
298                     if (needed_bytes <= tokeninfolength)
299                     {
300                         groups->GroupCount = tg->count;
301                         memcpy( sids, (char *)buffer + non_sid_portion,
302                                 reply->user_len - non_sid_portion );
303
304                         for (i = 0; i < tg->count; i++)
305                         {
306                             groups->Groups[i].Attributes = attr[i];
307                             groups->Groups[i].Sid = sids;
308                             sids = (SID *)((char *)sids + RtlLengthSid(sids));
309                         }
310                     }
311                     else status = STATUS_BUFFER_TOO_SMALL;
312                 }
313                 else if (retlen) *retlen = 0;
314             }
315             SERVER_END_REQ;
316         } while (need_more_memory);
317         if (buffer != stack_buffer) RtlFreeHeap(GetProcessHeap(), 0, buffer);
318         break;
319     }
320     case TokenPrimaryGroup:
321         if (tokeninfo)
322         {
323             TOKEN_PRIMARY_GROUP *tgroup = tokeninfo;
324             SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
325             RtlAllocateAndInitializeSid( &sid,
326                                          2,
327                                          SECURITY_BUILTIN_DOMAIN_RID,
328                                          DOMAIN_ALIAS_RID_ADMINS,
329                                          0, 0, 0, 0, 0, 0,
330                                          &(tgroup->PrimaryGroup));
331         }
332         break;
333     case TokenPrivileges:
334         SERVER_START_REQ( get_token_privileges )
335         {
336             TOKEN_PRIVILEGES *tpriv = tokeninfo;
337             req->handle = token;
338             if (tpriv && tokeninfolength > FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ))
339                 wine_server_set_reply( req, &tpriv->Privileges, tokeninfolength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) );
340             status = wine_server_call( req );
341             if (retlen) *retlen = FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) + reply->len;
342             if (tpriv) tpriv->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES);
343         }
344         SERVER_END_REQ;
345         break;
346     case TokenOwner:
347         if (tokeninfo)
348         {
349             TOKEN_OWNER *owner = tokeninfo;
350             PSID sid = (PSID) (owner + 1);
351             SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
352             RtlInitializeSid(sid, &localSidAuthority, 1);
353             *(RtlSubAuthoritySid(sid, 0)) = SECURITY_INTERACTIVE_RID;
354             owner->Owner = sid;
355         }
356         break;
357     case TokenImpersonationLevel:
358         SERVER_START_REQ( get_token_impersonation_level )
359         {
360             SECURITY_IMPERSONATION_LEVEL *impersonation_level = tokeninfo;
361             req->handle = token;
362             status = wine_server_call( req );
363             if (status == STATUS_SUCCESS)
364                 *impersonation_level = reply->impersonation_level;
365         }
366         SERVER_END_REQ;
367         break;
368     default:
369         {
370             ERR("Unhandled Token Information class %d!\n", tokeninfoclass);
371             return STATUS_NOT_IMPLEMENTED;
372         }
373     }
374     return status;
375 }
376
377 /******************************************************************************
378 *  NtSetInformationToken                [NTDLL.@]
379 *  ZwSetInformationToken                [NTDLL.@]
380 */
381 NTSTATUS WINAPI NtSetInformationToken(
382         HANDLE TokenHandle,
383         TOKEN_INFORMATION_CLASS TokenInformationClass,
384         PVOID TokenInformation,
385         ULONG TokenInformationLength)
386 {
387     FIXME("%p %d %p %u\n", TokenHandle, TokenInformationClass,
388           TokenInformation, TokenInformationLength);
389     return STATUS_NOT_IMPLEMENTED;
390 }
391
392 /******************************************************************************
393 *  NtAdjustGroupsToken          [NTDLL.@]
394 *  ZwAdjustGroupsToken          [NTDLL.@]
395 */
396 NTSTATUS WINAPI NtAdjustGroupsToken(
397         HANDLE TokenHandle,
398         BOOLEAN ResetToDefault,
399         PTOKEN_GROUPS NewState,
400         ULONG BufferLength,
401         PTOKEN_GROUPS PreviousState,
402         PULONG ReturnLength)
403 {
404     FIXME("%p %d %p %u %p %p\n", TokenHandle, ResetToDefault,
405           NewState, BufferLength, PreviousState, ReturnLength);
406     return STATUS_NOT_IMPLEMENTED;
407 }
408
409 /******************************************************************************
410 *  NtPrivilegeCheck             [NTDLL.@]
411 *  ZwPrivilegeCheck             [NTDLL.@]
412 */
413 NTSTATUS WINAPI NtPrivilegeCheck(
414     HANDLE ClientToken,
415     PPRIVILEGE_SET RequiredPrivileges,
416     PBOOLEAN Result)
417 {
418     NTSTATUS status;
419     SERVER_START_REQ( check_token_privileges )
420     {
421         req->handle = ClientToken;
422         req->all_required = ((RequiredPrivileges->Control & PRIVILEGE_SET_ALL_NECESSARY) ? TRUE : FALSE);
423         wine_server_add_data( req, &RequiredPrivileges->Privilege,
424             RequiredPrivileges->PrivilegeCount * sizeof(RequiredPrivileges->Privilege[0]) );
425         wine_server_set_reply( req, &RequiredPrivileges->Privilege,
426             RequiredPrivileges->PrivilegeCount * sizeof(RequiredPrivileges->Privilege[0]) );
427
428         status = wine_server_call( req );
429
430         if (status == STATUS_SUCCESS)
431             *Result = (reply->has_privileges ? TRUE : FALSE);
432     }
433     SERVER_END_REQ;
434     return status;
435 }
436
437 /*
438  *      Section
439  */
440
441 /******************************************************************************
442  *  NtQuerySection      [NTDLL.@]
443  */
444 NTSTATUS WINAPI NtQuerySection(
445         IN HANDLE SectionHandle,
446         IN SECTION_INFORMATION_CLASS SectionInformationClass,
447         OUT PVOID SectionInformation,
448         IN ULONG Length,
449         OUT PULONG ResultLength)
450 {
451         FIXME("(%p,%d,%p,0x%08x,%p) stub!\n",
452         SectionHandle,SectionInformationClass,SectionInformation,Length,ResultLength);
453         return 0;
454 }
455
456 /*
457  *      ports
458  */
459
460 /******************************************************************************
461  *  NtCreatePort                [NTDLL.@]
462  *  ZwCreatePort                [NTDLL.@]
463  */
464 NTSTATUS WINAPI NtCreatePort(PHANDLE PortHandle,POBJECT_ATTRIBUTES ObjectAttributes,
465                              ULONG MaxConnectInfoLength,ULONG MaxDataLength,PULONG reserved)
466 {
467   FIXME("(%p,%p,%u,%u,%p),stub!\n",PortHandle,ObjectAttributes,
468         MaxConnectInfoLength,MaxDataLength,reserved);
469   return STATUS_NOT_IMPLEMENTED;
470 }
471
472 /******************************************************************************
473  *  NtConnectPort               [NTDLL.@]
474  *  ZwConnectPort               [NTDLL.@]
475  */
476 NTSTATUS WINAPI NtConnectPort(
477         PHANDLE PortHandle,
478         PUNICODE_STRING PortName,
479         PSECURITY_QUALITY_OF_SERVICE SecurityQos,
480         PLPC_SECTION_WRITE WriteSection,
481         PLPC_SECTION_READ ReadSection,
482         PULONG MaximumMessageLength,
483         PVOID ConnectInfo,
484         PULONG pConnectInfoLength)
485 {
486     FIXME("(%p,%s,%p,%p,%p,%p,%p,%p),stub!\n",
487           PortHandle,debugstr_w(PortName->Buffer),SecurityQos,
488           WriteSection,ReadSection,MaximumMessageLength,ConnectInfo,
489           pConnectInfoLength);
490     if (ConnectInfo && pConnectInfoLength)
491         TRACE("\tMessage = %s\n",debugstr_an(ConnectInfo,*pConnectInfoLength));
492     return STATUS_NOT_IMPLEMENTED;
493 }
494
495 /******************************************************************************
496  *  NtListenPort                [NTDLL.@]
497  *  ZwListenPort                [NTDLL.@]
498  */
499 NTSTATUS WINAPI NtListenPort(HANDLE PortHandle,PLPC_MESSAGE pLpcMessage)
500 {
501   FIXME("(%p,%p),stub!\n",PortHandle,pLpcMessage);
502   return STATUS_NOT_IMPLEMENTED;
503 }
504
505 /******************************************************************************
506  *  NtAcceptConnectPort [NTDLL.@]
507  *  ZwAcceptConnectPort [NTDLL.@]
508  */
509 NTSTATUS WINAPI NtAcceptConnectPort(
510         PHANDLE PortHandle,
511         ULONG PortIdentifier,
512         PLPC_MESSAGE pLpcMessage,
513         BOOLEAN Accept,
514         PLPC_SECTION_WRITE WriteSection,
515         PLPC_SECTION_READ ReadSection)
516 {
517   FIXME("(%p,%u,%p,%d,%p,%p),stub!\n",
518         PortHandle,PortIdentifier,pLpcMessage,Accept,WriteSection,ReadSection);
519   return STATUS_NOT_IMPLEMENTED;
520 }
521
522 /******************************************************************************
523  *  NtCompleteConnectPort       [NTDLL.@]
524  *  ZwCompleteConnectPort       [NTDLL.@]
525  */
526 NTSTATUS WINAPI NtCompleteConnectPort(HANDLE PortHandle)
527 {
528   FIXME("(%p),stub!\n",PortHandle);
529   return STATUS_NOT_IMPLEMENTED;
530 }
531
532 /******************************************************************************
533  *  NtRegisterThreadTerminatePort       [NTDLL.@]
534  *  ZwRegisterThreadTerminatePort       [NTDLL.@]
535  */
536 NTSTATUS WINAPI NtRegisterThreadTerminatePort(HANDLE PortHandle)
537 {
538   FIXME("(%p),stub!\n",PortHandle);
539   return STATUS_NOT_IMPLEMENTED;
540 }
541
542 /******************************************************************************
543  *  NtRequestWaitReplyPort              [NTDLL.@]
544  *  ZwRequestWaitReplyPort              [NTDLL.@]
545  */
546 NTSTATUS WINAPI NtRequestWaitReplyPort(
547         HANDLE PortHandle,
548         PLPC_MESSAGE pLpcMessageIn,
549         PLPC_MESSAGE pLpcMessageOut)
550 {
551   FIXME("(%p,%p,%p),stub!\n",PortHandle,pLpcMessageIn,pLpcMessageOut);
552   if(pLpcMessageIn)
553   {
554     TRACE("Message to send:\n");
555     TRACE("\tDataSize            = %u\n",pLpcMessageIn->DataSize);
556     TRACE("\tMessageSize         = %u\n",pLpcMessageIn->MessageSize);
557     TRACE("\tMessageType         = %u\n",pLpcMessageIn->MessageType);
558     TRACE("\tVirtualRangesOffset = %u\n",pLpcMessageIn->VirtualRangesOffset);
559     TRACE("\tClientId.UniqueProcess = %p\n",pLpcMessageIn->ClientId.UniqueProcess);
560     TRACE("\tClientId.UniqueThread  = %p\n",pLpcMessageIn->ClientId.UniqueThread);
561     TRACE("\tMessageId           = %u\n",pLpcMessageIn->MessageId);
562     TRACE("\tSectionSize         = %u\n",pLpcMessageIn->SectionSize);
563     TRACE("\tData                = %s\n",
564       debugstr_an((const char*)pLpcMessageIn->Data,pLpcMessageIn->DataSize));
565   }
566   return STATUS_NOT_IMPLEMENTED;
567 }
568
569 /******************************************************************************
570  *  NtReplyWaitReceivePort      [NTDLL.@]
571  *  ZwReplyWaitReceivePort      [NTDLL.@]
572  */
573 NTSTATUS WINAPI NtReplyWaitReceivePort(
574         HANDLE PortHandle,
575         PULONG PortIdentifier,
576         PLPC_MESSAGE ReplyMessage,
577         PLPC_MESSAGE Message)
578 {
579   FIXME("(%p,%p,%p,%p),stub!\n",PortHandle,PortIdentifier,ReplyMessage,Message);
580   return STATUS_NOT_IMPLEMENTED;
581 }
582
583 /*
584  *      Misc
585  */
586
587  /******************************************************************************
588  *  NtSetIntervalProfile        [NTDLL.@]
589  *  ZwSetIntervalProfile        [NTDLL.@]
590  */
591 NTSTATUS WINAPI NtSetIntervalProfile(
592         ULONG Interval,
593         KPROFILE_SOURCE Source)
594 {
595     FIXME("%u,%d\n", Interval, Source);
596     return STATUS_SUCCESS;
597 }
598
599 /******************************************************************************
600  * NtQuerySystemInformation [NTDLL.@]
601  * ZwQuerySystemInformation [NTDLL.@]
602  *
603  * ARGUMENTS:
604  *  SystemInformationClass      Index to a certain information structure
605  *      SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT
606  *      SystemCacheInformation          SYSTEM_CACHE_INFORMATION
607  *      SystemConfigurationInformation  CONFIGURATION_INFORMATION
608  *      observed (class/len):
609  *              0x0/0x2c
610  *              0x12/0x18
611  *              0x2/0x138
612  *              0x8/0x600
613  *              0x25/0xc
614  *  SystemInformation   caller supplies storage for the information structure
615  *  Length              size of the structure
616  *  ResultLength        Data written
617  */
618 NTSTATUS WINAPI NtQuerySystemInformation(
619         IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
620         OUT PVOID SystemInformation,
621         IN ULONG Length,
622         OUT PULONG ResultLength)
623 {
624     NTSTATUS    ret = STATUS_SUCCESS;
625     ULONG       len = 0;
626
627     TRACE("(0x%08x,%p,0x%08x,%p)\n",
628           SystemInformationClass,SystemInformation,Length,ResultLength);
629
630     switch (SystemInformationClass)
631     {
632     case SystemBasicInformation:
633         {
634             SYSTEM_BASIC_INFORMATION sbi;
635
636             sbi.dwUnknown1 = 0;
637             sbi.uKeMaximumIncrement = 0;
638             sbi.uPageSize = 1024; /* FIXME */
639             sbi.uMmNumberOfPhysicalPages = 12345; /* FIXME */
640             sbi.uMmLowestPhysicalPage = 0; /* FIXME */
641             sbi.uMmHighestPhysicalPage = 12345; /* FIXME */
642             sbi.uAllocationGranularity = 65536; /* FIXME */
643             sbi.pLowestUserAddress = 0; /* FIXME */
644             sbi.pMmHighestUserAddress = (void*)~0; /* FIXME */
645             sbi.uKeActiveProcessors = 1; /* FIXME */
646             sbi.bKeNumberProcessors = 1; /* FIXME */
647             len = sizeof(sbi);
648
649             if ( Length == len)
650             {
651                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
652                 else memcpy( SystemInformation, &sbi, len);
653             }
654             else ret = STATUS_INFO_LENGTH_MISMATCH;
655         }
656         break;
657     case SystemCpuInformation:
658         {
659             SYSTEM_CPU_INFORMATION sci;
660
661             /* FIXME: move some code from kernel/cpu.c to process this */
662             sci.Architecture = PROCESSOR_ARCHITECTURE_INTEL;
663             sci.Level = 6; /* 686, aka Pentium II+ */
664             sci.Revision = 0;
665             sci.Reserved = 0;
666             sci.FeatureSet = 0x1fff;
667             len = sizeof(sci);
668
669             if ( Length >= len)
670             {
671                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
672                 else memcpy( SystemInformation, &sci, len);
673             }
674             else ret = STATUS_INFO_LENGTH_MISMATCH;
675         }
676         break;
677     case SystemPerformanceInformation:
678         {
679             SYSTEM_PERFORMANCE_INFORMATION spi;
680
681             memset(&spi, 0 , sizeof(spi));
682             len = sizeof(spi);
683
684             if (Length >= len)
685             {
686                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
687                 else memcpy( SystemInformation, &spi, len);
688             }
689             else ret = STATUS_INFO_LENGTH_MISMATCH;
690         }
691         break;
692     case SystemTimeOfDayInformation:
693         {
694             SYSTEM_TIMEOFDAY_INFORMATION sti;
695
696             memset(&sti, 0 , sizeof(sti));
697
698             /* liKeSystemTime, liExpTimeZoneBias, uCurrentTimeZoneId */
699             sti.liKeBootTime.QuadPart = server_start_time;
700
701             if (Length <= sizeof(sti))
702             {
703                 len = Length;
704                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
705                 else memcpy( SystemInformation, &sti, Length);
706             }
707             else ret = STATUS_INFO_LENGTH_MISMATCH;
708         }
709         break;
710     case SystemProcessInformation:
711         {
712             SYSTEM_PROCESS_INFORMATION* spi = (SYSTEM_PROCESS_INFORMATION*)SystemInformation;
713             SYSTEM_PROCESS_INFORMATION* last = NULL;
714             HANDLE hSnap = 0;
715             WCHAR procname[1024];
716             WCHAR* exename;
717             DWORD wlen = 0;
718             DWORD procstructlen = 0;
719
720             SERVER_START_REQ( create_snapshot )
721             {
722                 req->flags      = SNAP_PROCESS | SNAP_THREAD;
723                 req->attributes = 0;
724                 req->pid        = 0;
725                 if (!(ret = wine_server_call( req ))) hSnap = reply->handle;
726             }
727             SERVER_END_REQ;
728             len = 0;
729             while (ret == STATUS_SUCCESS)
730             {
731                 SERVER_START_REQ( next_process )
732                 {
733                     req->handle = hSnap;
734                     req->reset = (len == 0);
735                     wine_server_set_reply( req, procname, sizeof(procname)-sizeof(WCHAR) );
736                     if (!(ret = wine_server_call( req )))
737                     {
738                         /* Make sure procname is 0 terminated */
739                         procname[wine_server_reply_size(reply) / sizeof(WCHAR)] = 0;
740
741                         /* Get only the executable name, not the path */
742                         if ((exename = strrchrW(procname, '\\')) != NULL) exename++;
743                         else exename = procname;
744
745                         wlen = (strlenW(exename) + 1) * sizeof(WCHAR);
746
747                         procstructlen = sizeof(*spi) + wlen + ((reply->threads - 1) * sizeof(SYSTEM_THREAD_INFORMATION));
748
749                         if (Length >= len + procstructlen)
750                         {
751                             /* ftCreationTime, ftUserTime, ftKernelTime;
752                              * vmCounters, ioCounters
753                              */
754  
755                             memset(spi, 0, sizeof(*spi));
756
757                             spi->dwOffset = procstructlen - wlen;
758                             spi->dwThreadCount = reply->threads;
759
760                             /* spi->pszProcessName will be set later on */
761
762                             spi->dwBasePriority = reply->priority;
763                             spi->dwProcessID = (DWORD)reply->pid;
764                             spi->dwParentProcessID = (DWORD)reply->ppid;
765                             spi->dwHandleCount = reply->handles;
766
767                             /* spi->ti will be set later on */
768
769                             len += procstructlen;
770                         }
771                         else ret = STATUS_INFO_LENGTH_MISMATCH;
772                     }
773                 }
774                 SERVER_END_REQ;
775  
776                 if (ret != STATUS_SUCCESS)
777                 {
778                     if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
779                     break;
780                 }
781                 else /* Length is already checked for */
782                 {
783                     int     i, j;
784
785                     /* set thread info */
786                     i = j = 0;
787                     while (ret == STATUS_SUCCESS)
788                     {
789                         SERVER_START_REQ( next_thread )
790                         {
791                             req->handle = hSnap;
792                             req->reset = (j == 0);
793                             if (!(ret = wine_server_call( req )))
794                             {
795                                 j++;
796                                 if (reply->pid == spi->dwProcessID)
797                                 {
798                                     /* ftKernelTime, ftUserTime, ftCreateTime;
799                                      * dwTickCount, dwStartAddress
800                                      */
801
802                                     memset(&spi->ti[i], 0, sizeof(spi->ti));
803
804                                     spi->ti[i].dwOwningPID = reply->pid;
805                                     spi->ti[i].dwThreadID  = reply->tid;
806                                     spi->ti[i].dwCurrentPriority = reply->base_pri + reply->delta_pri;
807                                     spi->ti[i].dwBasePriority = reply->base_pri;
808                                     i++;
809                                 }
810                             }
811                         }
812                         SERVER_END_REQ;
813                     }
814                     if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
815
816                     /* now append process name */
817                     spi->ProcessName.Buffer = (WCHAR*)((char*)spi + spi->dwOffset);
818                     spi->ProcessName.Length = wlen - sizeof(WCHAR);
819                     spi->ProcessName.MaximumLength = wlen;
820                     memcpy( spi->ProcessName.Buffer, exename, wlen );
821                     spi->dwOffset += wlen;
822
823                     last = spi;
824                     spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + spi->dwOffset);
825                 }
826             }
827             if (ret == STATUS_SUCCESS && last) last->dwOffset = 0;
828             if (hSnap) NtClose(hSnap);
829         }
830         break;
831     case SystemProcessorPerformanceInformation:
832         {
833             SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION sppi;
834
835             memset(&sppi, 0 , sizeof(sppi)); /* FIXME */
836             len = sizeof(sppi);
837
838             if (Length >= len)
839             {
840                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
841                 else memcpy( SystemInformation, &sppi, len);
842             }
843             else ret = STATUS_INFO_LENGTH_MISMATCH;
844         }
845         break;
846     case SystemModuleInformation:
847         {
848             SYSTEM_MODULE_INFORMATION smi;
849
850             memset(&smi, 0, sizeof(smi));
851             len = sizeof(smi);
852
853             if ( Length >= len)
854             {
855                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
856                 else memcpy( SystemInformation, &smi, len);
857             }
858             else ret = STATUS_INFO_LENGTH_MISMATCH;
859         }
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 }