ntdll: Add missing RtlReAllocateHeap Valgrind hook, add tests.
[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 #define NONAMELESSUNION
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
35 #include "windef.h"
36 #include "winternl.h"
37 #include "ntdll_misc.h"
38 #include "wine/server.h"
39
40 #ifdef __APPLE__
41 #include <mach/mach_init.h>
42 #include <mach/mach_host.h>
43 #include <mach/vm_map.h>
44 #endif
45
46 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
47
48 /*
49  *      Token
50  */
51
52 /******************************************************************************
53  *  NtDuplicateToken            [NTDLL.@]
54  *  ZwDuplicateToken            [NTDLL.@]
55  */
56 NTSTATUS WINAPI NtDuplicateToken(
57         IN HANDLE ExistingToken,
58         IN ACCESS_MASK DesiredAccess,
59         IN POBJECT_ATTRIBUTES ObjectAttributes,
60         IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
61         IN TOKEN_TYPE TokenType,
62         OUT PHANDLE NewToken)
63 {
64     NTSTATUS status;
65
66     TRACE("(%p,0x%08x,%s,0x%08x,0x%08x,%p)\n",
67           ExistingToken, DesiredAccess, debugstr_ObjectAttributes(ObjectAttributes),
68           ImpersonationLevel, TokenType, NewToken);
69
70     if (ObjectAttributes && ObjectAttributes->SecurityQualityOfService)
71     {
72         SECURITY_QUALITY_OF_SERVICE *SecurityQOS = ObjectAttributes->SecurityQualityOfService;
73         TRACE("ObjectAttributes->SecurityQualityOfService = {%d, %d, %d, %s}\n",
74             SecurityQOS->Length, SecurityQOS->ImpersonationLevel,
75             SecurityQOS->ContextTrackingMode,
76             SecurityQOS->EffectiveOnly ? "TRUE" : "FALSE");
77         ImpersonationLevel = SecurityQOS->ImpersonationLevel;
78     }
79
80     SERVER_START_REQ( duplicate_token )
81     {
82         req->handle              = wine_server_obj_handle( ExistingToken );
83         req->access              = DesiredAccess;
84         req->attributes          = ObjectAttributes ? ObjectAttributes->Attributes : 0;
85         req->primary             = (TokenType == TokenPrimary);
86         req->impersonation_level = ImpersonationLevel;
87         status = wine_server_call( req );
88         if (!status) *NewToken = wine_server_ptr_handle( reply->new_handle );
89     }
90     SERVER_END_REQ;
91
92     return status;
93 }
94
95 /******************************************************************************
96  *  NtOpenProcessToken          [NTDLL.@]
97  *  ZwOpenProcessToken          [NTDLL.@]
98  */
99 NTSTATUS WINAPI NtOpenProcessToken(
100         HANDLE ProcessHandle,
101         DWORD DesiredAccess,
102         HANDLE *TokenHandle)
103 {
104     return NtOpenProcessTokenEx( ProcessHandle, DesiredAccess, 0, TokenHandle );
105 }
106
107 /******************************************************************************
108  *  NtOpenProcessTokenEx   [NTDLL.@]
109  *  ZwOpenProcessTokenEx   [NTDLL.@]
110  */
111 NTSTATUS WINAPI NtOpenProcessTokenEx( HANDLE process, DWORD access, DWORD attributes,
112                                       HANDLE *handle )
113 {
114     NTSTATUS ret;
115
116     TRACE("(%p,0x%08x,0x%08x,%p)\n", process, access, attributes, handle);
117
118     SERVER_START_REQ( open_token )
119     {
120         req->handle     = wine_server_obj_handle( process );
121         req->access     = access;
122         req->attributes = attributes;
123         req->flags      = 0;
124         ret = wine_server_call( req );
125         if (!ret) *handle = wine_server_ptr_handle( reply->token );
126     }
127     SERVER_END_REQ;
128     return ret;
129 }
130
131 /******************************************************************************
132  *  NtOpenThreadToken           [NTDLL.@]
133  *  ZwOpenThreadToken           [NTDLL.@]
134  */
135 NTSTATUS WINAPI NtOpenThreadToken(
136         HANDLE ThreadHandle,
137         DWORD DesiredAccess,
138         BOOLEAN OpenAsSelf,
139         HANDLE *TokenHandle)
140 {
141     return NtOpenThreadTokenEx( ThreadHandle, DesiredAccess, OpenAsSelf, 0, TokenHandle );
142 }
143
144 /******************************************************************************
145  *  NtOpenThreadTokenEx   [NTDLL.@]
146  *  ZwOpenThreadTokenEx   [NTDLL.@]
147  */
148 NTSTATUS WINAPI NtOpenThreadTokenEx( HANDLE thread, DWORD access, BOOLEAN as_self, DWORD attributes,
149                                      HANDLE *handle )
150 {
151     NTSTATUS ret;
152
153     TRACE("(%p,0x%08x,%u,0x%08x,%p)\n", thread, access, as_self, attributes, handle );
154
155     SERVER_START_REQ( open_token )
156     {
157         req->handle     = wine_server_obj_handle( thread );
158         req->access     = access;
159         req->attributes = attributes;
160         req->flags      = OPEN_TOKEN_THREAD;
161         if (as_self) req->flags |= OPEN_TOKEN_AS_SELF;
162         ret = wine_server_call( req );
163         if (!ret) *handle = wine_server_ptr_handle( reply->token );
164     }
165     SERVER_END_REQ;
166
167     return ret;
168 }
169
170 /******************************************************************************
171  *  NtAdjustPrivilegesToken             [NTDLL.@]
172  *  ZwAdjustPrivilegesToken             [NTDLL.@]
173  *
174  * FIXME: parameters unsafe
175  */
176 NTSTATUS WINAPI NtAdjustPrivilegesToken(
177         IN HANDLE TokenHandle,
178         IN BOOLEAN DisableAllPrivileges,
179         IN PTOKEN_PRIVILEGES NewState,
180         IN DWORD BufferLength,
181         OUT PTOKEN_PRIVILEGES PreviousState,
182         OUT PDWORD ReturnLength)
183 {
184     NTSTATUS ret;
185
186     TRACE("(%p,0x%08x,%p,0x%08x,%p,%p)\n",
187         TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength);
188
189     SERVER_START_REQ( adjust_token_privileges )
190     {
191         req->handle = wine_server_obj_handle( TokenHandle );
192         req->disable_all = DisableAllPrivileges;
193         req->get_modified_state = (PreviousState != NULL);
194         if (!DisableAllPrivileges)
195         {
196             wine_server_add_data( req, NewState->Privileges,
197                                   NewState->PrivilegeCount * sizeof(NewState->Privileges[0]) );
198         }
199         if (PreviousState && BufferLength >= FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ))
200             wine_server_set_reply( req, PreviousState->Privileges,
201                                    BufferLength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) );
202         ret = wine_server_call( req );
203         if (PreviousState)
204         {
205             *ReturnLength = reply->len + FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges );
206             PreviousState->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES);
207         }
208     }
209     SERVER_END_REQ;
210
211     return ret;
212 }
213
214 /******************************************************************************
215 *  NtQueryInformationToken              [NTDLL.@]
216 *  ZwQueryInformationToken              [NTDLL.@]
217 *
218 * NOTES
219 *  Buffer for TokenUser:
220 *   0x00 TOKEN_USER the PSID field points to the SID
221 *   0x08 SID
222 *
223 */
224 NTSTATUS WINAPI NtQueryInformationToken(
225         HANDLE token,
226         TOKEN_INFORMATION_CLASS tokeninfoclass,
227         PVOID tokeninfo,
228         ULONG tokeninfolength,
229         PULONG retlen )
230 {
231     ULONG len;
232     NTSTATUS status = STATUS_SUCCESS;
233
234     TRACE("(%p,%d,%p,%d,%p)\n",
235           token,tokeninfoclass,tokeninfo,tokeninfolength,retlen);
236
237     switch (tokeninfoclass)
238     {
239     case TokenOwner:
240         len = sizeof(TOKEN_OWNER) + sizeof(SID);
241         break;
242     case TokenPrimaryGroup:
243         len = sizeof(TOKEN_PRIMARY_GROUP);
244         break;
245     case TokenSource:
246         len = sizeof(TOKEN_SOURCE);
247         break;
248     case TokenType:
249         len = sizeof (TOKEN_TYPE);
250         break;
251     case TokenImpersonationLevel:
252         len = sizeof(SECURITY_IMPERSONATION_LEVEL);
253         break;
254     case TokenStatistics:
255         len = sizeof(TOKEN_STATISTICS);
256         break;
257     default:
258         len = 0;
259     }
260
261     if (retlen) *retlen = len;
262
263     if (tokeninfolength < len)
264         return STATUS_BUFFER_TOO_SMALL;
265
266     switch (tokeninfoclass)
267     {
268     case TokenUser:
269         SERVER_START_REQ( get_token_user )
270         {
271             TOKEN_USER * tuser = tokeninfo;
272             PSID sid = tuser + 1;
273             DWORD sid_len = tokeninfolength < sizeof(TOKEN_USER) ? 0 : tokeninfolength - sizeof(TOKEN_USER);
274
275             req->handle = wine_server_obj_handle( token );
276             wine_server_set_reply( req, sid, sid_len );
277             status = wine_server_call( req );
278             if (retlen) *retlen = reply->user_len + sizeof(TOKEN_USER);
279             if (status == STATUS_SUCCESS)
280             {
281                 tuser->User.Sid = sid;
282                 tuser->User.Attributes = 0;
283             }
284         }
285         SERVER_END_REQ;
286         break;
287     case TokenGroups:
288     {
289         char stack_buffer[256];
290         unsigned int server_buf_len = sizeof(stack_buffer);
291         void *buffer = stack_buffer;
292         BOOLEAN need_more_memory;
293
294         /* we cannot work out the size of the server buffer required for the
295          * input size, since there are two factors affecting how much can be
296          * stored in the buffer - number of groups and lengths of sids */
297         do
298         {
299             need_more_memory = FALSE;
300
301             SERVER_START_REQ( get_token_groups )
302             {
303                 TOKEN_GROUPS *groups = tokeninfo;
304
305                 req->handle = wine_server_obj_handle( token );
306                 wine_server_set_reply( req, buffer, server_buf_len );
307                 status = wine_server_call( req );
308                 if (status == STATUS_BUFFER_TOO_SMALL)
309                 {
310                     if (buffer == stack_buffer)
311                         buffer = RtlAllocateHeap(GetProcessHeap(), 0, reply->user_len);
312                     else
313                         buffer = RtlReAllocateHeap(GetProcessHeap(), 0, buffer, reply->user_len);
314                     if (!buffer) return STATUS_NO_MEMORY;
315
316                     server_buf_len = reply->user_len;
317                     need_more_memory = TRUE;
318                 }
319                 else if (status == STATUS_SUCCESS)
320                 {
321                     struct token_groups *tg = buffer;
322                     unsigned int *attr = (unsigned int *)(tg + 1);
323                     ULONG i;
324                     const int non_sid_portion = (sizeof(struct token_groups) + tg->count * sizeof(unsigned long));
325                     SID *sids = (SID *)((char *)tokeninfo + FIELD_OFFSET( TOKEN_GROUPS, Groups[tg->count] ));
326                     ULONG needed_bytes = FIELD_OFFSET( TOKEN_GROUPS, Groups[tg->count] ) +
327                         reply->user_len - non_sid_portion;
328
329                     if (retlen) *retlen = needed_bytes;
330
331                     if (needed_bytes <= tokeninfolength)
332                     {
333                         groups->GroupCount = tg->count;
334                         memcpy( sids, (char *)buffer + non_sid_portion,
335                                 reply->user_len - non_sid_portion );
336
337                         for (i = 0; i < tg->count; i++)
338                         {
339                             groups->Groups[i].Attributes = attr[i];
340                             groups->Groups[i].Sid = sids;
341                             sids = (SID *)((char *)sids + RtlLengthSid(sids));
342                         }
343                     }
344                     else status = STATUS_BUFFER_TOO_SMALL;
345                 }
346                 else if (retlen) *retlen = 0;
347             }
348             SERVER_END_REQ;
349         } while (need_more_memory);
350         if (buffer != stack_buffer) RtlFreeHeap(GetProcessHeap(), 0, buffer);
351         break;
352     }
353     case TokenPrimaryGroup:
354         if (tokeninfo)
355         {
356             TOKEN_PRIMARY_GROUP *tgroup = tokeninfo;
357             SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
358             RtlAllocateAndInitializeSid( &sid,
359                                          2,
360                                          SECURITY_BUILTIN_DOMAIN_RID,
361                                          DOMAIN_ALIAS_RID_ADMINS,
362                                          0, 0, 0, 0, 0, 0,
363                                          &(tgroup->PrimaryGroup));
364         }
365         break;
366     case TokenPrivileges:
367         SERVER_START_REQ( get_token_privileges )
368         {
369             TOKEN_PRIVILEGES *tpriv = tokeninfo;
370             req->handle = wine_server_obj_handle( token );
371             if (tpriv && tokeninfolength > FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ))
372                 wine_server_set_reply( req, tpriv->Privileges, tokeninfolength - FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) );
373             status = wine_server_call( req );
374             if (retlen) *retlen = FIELD_OFFSET( TOKEN_PRIVILEGES, Privileges ) + reply->len;
375             if (tpriv) tpriv->PrivilegeCount = reply->len / sizeof(LUID_AND_ATTRIBUTES);
376         }
377         SERVER_END_REQ;
378         break;
379     case TokenOwner:
380         if (tokeninfo)
381         {
382             TOKEN_OWNER *owner = tokeninfo;
383             PSID sid = owner + 1;
384             SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
385             RtlInitializeSid(sid, &localSidAuthority, 1);
386             *(RtlSubAuthoritySid(sid, 0)) = SECURITY_INTERACTIVE_RID;
387             owner->Owner = sid;
388         }
389         break;
390     case TokenImpersonationLevel:
391         SERVER_START_REQ( get_token_impersonation_level )
392         {
393             SECURITY_IMPERSONATION_LEVEL *impersonation_level = tokeninfo;
394             req->handle = wine_server_obj_handle( token );
395             status = wine_server_call( req );
396             if (status == STATUS_SUCCESS)
397                 *impersonation_level = reply->impersonation_level;
398         }
399         SERVER_END_REQ;
400         break;
401     case TokenStatistics:
402         SERVER_START_REQ( get_token_statistics )
403         {
404             TOKEN_STATISTICS *statistics = tokeninfo;
405             req->handle = wine_server_obj_handle( token );
406             status = wine_server_call( req );
407             if (status == STATUS_SUCCESS)
408             {
409                 statistics->TokenId.LowPart  = reply->token_id.low_part;
410                 statistics->TokenId.HighPart = reply->token_id.high_part;
411                 statistics->AuthenticationId.LowPart  = 0; /* FIXME */
412                 statistics->AuthenticationId.HighPart = 0; /* FIXME */
413                 statistics->ExpirationTime.u.HighPart = 0x7fffffff;
414                 statistics->ExpirationTime.u.LowPart  = 0xffffffff;
415                 statistics->TokenType = reply->primary ? TokenPrimary : TokenImpersonation;
416                 statistics->ImpersonationLevel = reply->impersonation_level;
417
418                 /* kernel information not relevant to us */
419                 statistics->DynamicCharged = 0;
420                 statistics->DynamicAvailable = 0;
421
422                 statistics->GroupCount = reply->group_count;
423                 statistics->PrivilegeCount = reply->privilege_count;
424                 statistics->ModifiedId.LowPart  = reply->modified_id.low_part;
425                 statistics->ModifiedId.HighPart = reply->modified_id.high_part;
426             }
427         }
428         SERVER_END_REQ;
429         break;
430     case TokenType:
431         SERVER_START_REQ( get_token_statistics )
432         {
433             TOKEN_TYPE *token_type = tokeninfo;
434             req->handle = wine_server_obj_handle( token );
435             status = wine_server_call( req );
436             if (status == STATUS_SUCCESS)
437                 *token_type = reply->primary ? TokenPrimary : TokenImpersonation;
438         }
439         SERVER_END_REQ;
440         break;
441     case TokenDefaultDacl:
442         SERVER_START_REQ( get_token_default_dacl )
443         {
444             TOKEN_DEFAULT_DACL *default_dacl = tokeninfo;
445             ACL *acl = (ACL *)(default_dacl + 1);
446             DWORD acl_len;
447
448             if (tokeninfolength < sizeof(TOKEN_DEFAULT_DACL)) acl_len = 0;
449             else acl_len = tokeninfolength - sizeof(TOKEN_DEFAULT_DACL);
450
451             req->handle = wine_server_obj_handle( token );
452             wine_server_set_reply( req, acl, acl_len );
453             status = wine_server_call( req );
454
455             if (retlen) *retlen = reply->acl_len + sizeof(TOKEN_DEFAULT_DACL);
456             if (status == STATUS_SUCCESS)
457             {
458                 if (reply->acl_len)
459                     default_dacl->DefaultDacl = acl;
460                 else
461                     default_dacl->DefaultDacl = NULL;
462             }
463         }
464         SERVER_END_REQ;
465         break;
466     default:
467         {
468             ERR("Unhandled Token Information class %d!\n", tokeninfoclass);
469             return STATUS_NOT_IMPLEMENTED;
470         }
471     }
472     return status;
473 }
474
475 /******************************************************************************
476 *  NtSetInformationToken                [NTDLL.@]
477 *  ZwSetInformationToken                [NTDLL.@]
478 */
479 NTSTATUS WINAPI NtSetInformationToken(
480         HANDLE TokenHandle,
481         TOKEN_INFORMATION_CLASS TokenInformationClass,
482         PVOID TokenInformation,
483         ULONG TokenInformationLength)
484 {
485     NTSTATUS ret = STATUS_NOT_IMPLEMENTED;
486
487     TRACE("%p %d %p %u\n", TokenHandle, TokenInformationClass,
488            TokenInformation, TokenInformationLength);
489
490     switch (TokenInformationClass)
491     {
492     case TokenDefaultDacl:
493         if (TokenInformationLength < sizeof(TOKEN_DEFAULT_DACL))
494         {
495             ret = STATUS_INFO_LENGTH_MISMATCH;
496             break;
497         }
498         if (!TokenInformation)
499         {
500             ret = STATUS_ACCESS_VIOLATION;
501             break;
502         }
503         SERVER_START_REQ( set_token_default_dacl )
504         {
505             ACL *acl = ((TOKEN_DEFAULT_DACL *)TokenInformation)->DefaultDacl;
506             WORD size;
507
508             if (acl) size = acl->AclSize;
509             else size = 0;
510
511             req->handle = wine_server_obj_handle( TokenHandle );
512             wine_server_add_data( req, acl, size );
513             ret = wine_server_call( req );
514         }
515         SERVER_END_REQ;
516         break;
517     default:
518         FIXME("unimplemented class %u\n", TokenInformationClass);
519         break;
520     }
521
522     return ret;
523 }
524
525 /******************************************************************************
526 *  NtAdjustGroupsToken          [NTDLL.@]
527 *  ZwAdjustGroupsToken          [NTDLL.@]
528 */
529 NTSTATUS WINAPI NtAdjustGroupsToken(
530         HANDLE TokenHandle,
531         BOOLEAN ResetToDefault,
532         PTOKEN_GROUPS NewState,
533         ULONG BufferLength,
534         PTOKEN_GROUPS PreviousState,
535         PULONG ReturnLength)
536 {
537     FIXME("%p %d %p %u %p %p\n", TokenHandle, ResetToDefault,
538           NewState, BufferLength, PreviousState, ReturnLength);
539     return STATUS_NOT_IMPLEMENTED;
540 }
541
542 /******************************************************************************
543 *  NtPrivilegeCheck             [NTDLL.@]
544 *  ZwPrivilegeCheck             [NTDLL.@]
545 */
546 NTSTATUS WINAPI NtPrivilegeCheck(
547     HANDLE ClientToken,
548     PPRIVILEGE_SET RequiredPrivileges,
549     PBOOLEAN Result)
550 {
551     NTSTATUS status;
552     SERVER_START_REQ( check_token_privileges )
553     {
554         req->handle = wine_server_obj_handle( ClientToken );
555         req->all_required = ((RequiredPrivileges->Control & PRIVILEGE_SET_ALL_NECESSARY) ? TRUE : FALSE);
556         wine_server_add_data( req, RequiredPrivileges->Privilege,
557             RequiredPrivileges->PrivilegeCount * sizeof(RequiredPrivileges->Privilege[0]) );
558         wine_server_set_reply( req, RequiredPrivileges->Privilege,
559             RequiredPrivileges->PrivilegeCount * sizeof(RequiredPrivileges->Privilege[0]) );
560
561         status = wine_server_call( req );
562
563         if (status == STATUS_SUCCESS)
564             *Result = (reply->has_privileges ? TRUE : FALSE);
565     }
566     SERVER_END_REQ;
567     return status;
568 }
569
570 /*
571  *      Section
572  */
573
574 /******************************************************************************
575  *  NtQuerySection      [NTDLL.@]
576  */
577 NTSTATUS WINAPI NtQuerySection(
578         IN HANDLE SectionHandle,
579         IN SECTION_INFORMATION_CLASS SectionInformationClass,
580         OUT PVOID SectionInformation,
581         IN ULONG Length,
582         OUT PULONG ResultLength)
583 {
584         FIXME("(%p,%d,%p,0x%08x,%p) stub!\n",
585         SectionHandle,SectionInformationClass,SectionInformation,Length,ResultLength);
586         return 0;
587 }
588
589 /*
590  *      ports
591  */
592
593 /******************************************************************************
594  *  NtCreatePort                [NTDLL.@]
595  *  ZwCreatePort                [NTDLL.@]
596  */
597 NTSTATUS WINAPI NtCreatePort(PHANDLE PortHandle,POBJECT_ATTRIBUTES ObjectAttributes,
598                              ULONG MaxConnectInfoLength,ULONG MaxDataLength,PULONG reserved)
599 {
600   FIXME("(%p,%p,%u,%u,%p),stub!\n",PortHandle,ObjectAttributes,
601         MaxConnectInfoLength,MaxDataLength,reserved);
602   return STATUS_NOT_IMPLEMENTED;
603 }
604
605 /******************************************************************************
606  *  NtConnectPort               [NTDLL.@]
607  *  ZwConnectPort               [NTDLL.@]
608  */
609 NTSTATUS WINAPI NtConnectPort(
610         PHANDLE PortHandle,
611         PUNICODE_STRING PortName,
612         PSECURITY_QUALITY_OF_SERVICE SecurityQos,
613         PLPC_SECTION_WRITE WriteSection,
614         PLPC_SECTION_READ ReadSection,
615         PULONG MaximumMessageLength,
616         PVOID ConnectInfo,
617         PULONG pConnectInfoLength)
618 {
619     FIXME("(%p,%s,%p,%p,%p,%p,%p,%p),stub!\n",
620           PortHandle,debugstr_w(PortName->Buffer),SecurityQos,
621           WriteSection,ReadSection,MaximumMessageLength,ConnectInfo,
622           pConnectInfoLength);
623     if (ConnectInfo && pConnectInfoLength)
624         TRACE("\tMessage = %s\n",debugstr_an(ConnectInfo,*pConnectInfoLength));
625     return STATUS_NOT_IMPLEMENTED;
626 }
627
628 /******************************************************************************
629  *  NtListenPort                [NTDLL.@]
630  *  ZwListenPort                [NTDLL.@]
631  */
632 NTSTATUS WINAPI NtListenPort(HANDLE PortHandle,PLPC_MESSAGE pLpcMessage)
633 {
634   FIXME("(%p,%p),stub!\n",PortHandle,pLpcMessage);
635   return STATUS_NOT_IMPLEMENTED;
636 }
637
638 /******************************************************************************
639  *  NtAcceptConnectPort [NTDLL.@]
640  *  ZwAcceptConnectPort [NTDLL.@]
641  */
642 NTSTATUS WINAPI NtAcceptConnectPort(
643         PHANDLE PortHandle,
644         ULONG PortIdentifier,
645         PLPC_MESSAGE pLpcMessage,
646         BOOLEAN Accept,
647         PLPC_SECTION_WRITE WriteSection,
648         PLPC_SECTION_READ ReadSection)
649 {
650   FIXME("(%p,%u,%p,%d,%p,%p),stub!\n",
651         PortHandle,PortIdentifier,pLpcMessage,Accept,WriteSection,ReadSection);
652   return STATUS_NOT_IMPLEMENTED;
653 }
654
655 /******************************************************************************
656  *  NtCompleteConnectPort       [NTDLL.@]
657  *  ZwCompleteConnectPort       [NTDLL.@]
658  */
659 NTSTATUS WINAPI NtCompleteConnectPort(HANDLE PortHandle)
660 {
661   FIXME("(%p),stub!\n",PortHandle);
662   return STATUS_NOT_IMPLEMENTED;
663 }
664
665 /******************************************************************************
666  *  NtRegisterThreadTerminatePort       [NTDLL.@]
667  *  ZwRegisterThreadTerminatePort       [NTDLL.@]
668  */
669 NTSTATUS WINAPI NtRegisterThreadTerminatePort(HANDLE PortHandle)
670 {
671   FIXME("(%p),stub!\n",PortHandle);
672   return STATUS_NOT_IMPLEMENTED;
673 }
674
675 /******************************************************************************
676  *  NtRequestWaitReplyPort              [NTDLL.@]
677  *  ZwRequestWaitReplyPort              [NTDLL.@]
678  */
679 NTSTATUS WINAPI NtRequestWaitReplyPort(
680         HANDLE PortHandle,
681         PLPC_MESSAGE pLpcMessageIn,
682         PLPC_MESSAGE pLpcMessageOut)
683 {
684   FIXME("(%p,%p,%p),stub!\n",PortHandle,pLpcMessageIn,pLpcMessageOut);
685   if(pLpcMessageIn)
686   {
687     TRACE("Message to send:\n");
688     TRACE("\tDataSize            = %u\n",pLpcMessageIn->DataSize);
689     TRACE("\tMessageSize         = %u\n",pLpcMessageIn->MessageSize);
690     TRACE("\tMessageType         = %u\n",pLpcMessageIn->MessageType);
691     TRACE("\tVirtualRangesOffset = %u\n",pLpcMessageIn->VirtualRangesOffset);
692     TRACE("\tClientId.UniqueProcess = %p\n",pLpcMessageIn->ClientId.UniqueProcess);
693     TRACE("\tClientId.UniqueThread  = %p\n",pLpcMessageIn->ClientId.UniqueThread);
694     TRACE("\tMessageId           = %u\n",pLpcMessageIn->MessageId);
695     TRACE("\tSectionSize         = %u\n",pLpcMessageIn->SectionSize);
696     TRACE("\tData                = %s\n",
697       debugstr_an((const char*)pLpcMessageIn->Data,pLpcMessageIn->DataSize));
698   }
699   return STATUS_NOT_IMPLEMENTED;
700 }
701
702 /******************************************************************************
703  *  NtReplyWaitReceivePort      [NTDLL.@]
704  *  ZwReplyWaitReceivePort      [NTDLL.@]
705  */
706 NTSTATUS WINAPI NtReplyWaitReceivePort(
707         HANDLE PortHandle,
708         PULONG PortIdentifier,
709         PLPC_MESSAGE ReplyMessage,
710         PLPC_MESSAGE Message)
711 {
712   FIXME("(%p,%p,%p,%p),stub!\n",PortHandle,PortIdentifier,ReplyMessage,Message);
713   return STATUS_NOT_IMPLEMENTED;
714 }
715
716 /*
717  *      Misc
718  */
719
720  /******************************************************************************
721  *  NtSetIntervalProfile        [NTDLL.@]
722  *  ZwSetIntervalProfile        [NTDLL.@]
723  */
724 NTSTATUS WINAPI NtSetIntervalProfile(
725         ULONG Interval,
726         KPROFILE_SOURCE Source)
727 {
728     FIXME("%u,%d\n", Interval, Source);
729     return STATUS_SUCCESS;
730 }
731
732 /******************************************************************************
733  * NtQuerySystemInformation [NTDLL.@]
734  * ZwQuerySystemInformation [NTDLL.@]
735  *
736  * ARGUMENTS:
737  *  SystemInformationClass      Index to a certain information structure
738  *      SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT
739  *      SystemCacheInformation          SYSTEM_CACHE_INFORMATION
740  *      SystemConfigurationInformation  CONFIGURATION_INFORMATION
741  *      observed (class/len):
742  *              0x0/0x2c
743  *              0x12/0x18
744  *              0x2/0x138
745  *              0x8/0x600
746  *              0x25/0xc
747  *  SystemInformation   caller supplies storage for the information structure
748  *  Length              size of the structure
749  *  ResultLength        Data written
750  */
751 NTSTATUS WINAPI NtQuerySystemInformation(
752         IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
753         OUT PVOID SystemInformation,
754         IN ULONG Length,
755         OUT PULONG ResultLength)
756 {
757     NTSTATUS    ret = STATUS_SUCCESS;
758     ULONG       len = 0;
759
760     TRACE("(0x%08x,%p,0x%08x,%p)\n",
761           SystemInformationClass,SystemInformation,Length,ResultLength);
762
763     switch (SystemInformationClass)
764     {
765     case SystemBasicInformation:
766         {
767             SYSTEM_BASIC_INFORMATION sbi;
768
769             virtual_get_system_info( &sbi );
770             len = sizeof(sbi);
771
772             if ( Length == len)
773             {
774                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
775                 else memcpy( SystemInformation, &sbi, len);
776             }
777             else ret = STATUS_INFO_LENGTH_MISMATCH;
778         }
779         break;
780     case SystemCpuInformation:
781         {
782             SYSTEM_CPU_INFORMATION sci;
783
784             /* FIXME: move some code from kernel/cpu.c to process this */
785             sci.Architecture = PROCESSOR_ARCHITECTURE_INTEL;
786             sci.Level = 6; /* 686, aka Pentium II+ */
787             sci.Revision = 0;
788             sci.Reserved = 0;
789             sci.FeatureSet = 0x1fff;
790             len = sizeof(sci);
791
792             if ( Length >= len)
793             {
794                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
795                 else memcpy( SystemInformation, &sci, len);
796             }
797             else ret = STATUS_INFO_LENGTH_MISMATCH;
798         }
799         break;
800     case SystemPerformanceInformation:
801         {
802             SYSTEM_PERFORMANCE_INFORMATION spi;
803             static BOOL fixme_written = FALSE;
804
805             memset(&spi, 0 , sizeof(spi));
806             len = sizeof(spi);
807
808             if (Length >= len)
809             {
810                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
811                 else memcpy( SystemInformation, &spi, len);
812             }
813             else ret = STATUS_INFO_LENGTH_MISMATCH;
814             if(!fixme_written) {
815                 FIXME("info_class SYSTEM_PERFORMANCE_INFORMATION\n");
816                 fixme_written = TRUE;
817             }
818         }
819         break;
820     case SystemTimeOfDayInformation:
821         {
822             SYSTEM_TIMEOFDAY_INFORMATION sti;
823
824             memset(&sti, 0 , sizeof(sti));
825
826             /* liKeSystemTime, liExpTimeZoneBias, uCurrentTimeZoneId */
827             sti.liKeBootTime.QuadPart = server_start_time;
828
829             if (Length <= sizeof(sti))
830             {
831                 len = Length;
832                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
833                 else memcpy( SystemInformation, &sti, Length);
834             }
835             else ret = STATUS_INFO_LENGTH_MISMATCH;
836         }
837         break;
838     case SystemProcessInformation:
839         {
840             SYSTEM_PROCESS_INFORMATION* spi = SystemInformation;
841             SYSTEM_PROCESS_INFORMATION* last = NULL;
842             HANDLE hSnap = 0;
843             WCHAR procname[1024];
844             WCHAR* exename;
845             DWORD wlen = 0;
846             DWORD procstructlen = 0;
847
848             SERVER_START_REQ( create_snapshot )
849             {
850                 req->flags      = SNAP_PROCESS | SNAP_THREAD;
851                 req->attributes = 0;
852                 if (!(ret = wine_server_call( req )))
853                     hSnap = wine_server_ptr_handle( reply->handle );
854             }
855             SERVER_END_REQ;
856             len = 0;
857             while (ret == STATUS_SUCCESS)
858             {
859                 SERVER_START_REQ( next_process )
860                 {
861                     req->handle = wine_server_obj_handle( hSnap );
862                     req->reset = (len == 0);
863                     wine_server_set_reply( req, procname, sizeof(procname)-sizeof(WCHAR) );
864                     if (!(ret = wine_server_call( req )))
865                     {
866                         /* Make sure procname is 0 terminated */
867                         procname[wine_server_reply_size(reply) / sizeof(WCHAR)] = 0;
868
869                         /* Get only the executable name, not the path */
870                         if ((exename = strrchrW(procname, '\\')) != NULL) exename++;
871                         else exename = procname;
872
873                         wlen = (strlenW(exename) + 1) * sizeof(WCHAR);
874
875                         procstructlen = sizeof(*spi) + wlen + ((reply->threads - 1) * sizeof(SYSTEM_THREAD_INFORMATION));
876
877                         if (Length >= len + procstructlen)
878                         {
879                             /* ftCreationTime, ftUserTime, ftKernelTime;
880                              * vmCounters, ioCounters
881                              */
882  
883                             memset(spi, 0, sizeof(*spi));
884
885                             spi->NextEntryOffset = procstructlen - wlen;
886                             spi->dwThreadCount = reply->threads;
887
888                             /* spi->pszProcessName will be set later on */
889
890                             spi->dwBasePriority = reply->priority;
891                             spi->UniqueProcessId = UlongToHandle(reply->pid);
892                             spi->ParentProcessId = UlongToHandle(reply->ppid);
893                             spi->HandleCount = reply->handles;
894
895                             /* spi->ti will be set later on */
896
897                             len += procstructlen;
898                         }
899                         else ret = STATUS_INFO_LENGTH_MISMATCH;
900                     }
901                 }
902                 SERVER_END_REQ;
903  
904                 if (ret != STATUS_SUCCESS)
905                 {
906                     if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
907                     break;
908                 }
909                 else /* Length is already checked for */
910                 {
911                     int     i, j;
912
913                     /* set thread info */
914                     i = j = 0;
915                     while (ret == STATUS_SUCCESS)
916                     {
917                         SERVER_START_REQ( next_thread )
918                         {
919                             req->handle = wine_server_obj_handle( hSnap );
920                             req->reset = (j == 0);
921                             if (!(ret = wine_server_call( req )))
922                             {
923                                 j++;
924                                 if (UlongToHandle(reply->pid) == spi->UniqueProcessId)
925                                 {
926                                     /* ftKernelTime, ftUserTime, ftCreateTime;
927                                      * dwTickCount, dwStartAddress
928                                      */
929
930                                     memset(&spi->ti[i], 0, sizeof(spi->ti));
931
932                                     spi->ti[i].CreateTime.QuadPart = 0xdeadbeef;
933                                     spi->ti[i].ClientId.UniqueProcess = UlongToHandle(reply->pid);
934                                     spi->ti[i].ClientId.UniqueThread  = UlongToHandle(reply->tid);
935                                     spi->ti[i].dwCurrentPriority = reply->base_pri + reply->delta_pri;
936                                     spi->ti[i].dwBasePriority = reply->base_pri;
937                                     i++;
938                                 }
939                             }
940                         }
941                         SERVER_END_REQ;
942                     }
943                     if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
944
945                     /* now append process name */
946                     spi->ProcessName.Buffer = (WCHAR*)((char*)spi + spi->NextEntryOffset);
947                     spi->ProcessName.Length = wlen - sizeof(WCHAR);
948                     spi->ProcessName.MaximumLength = wlen;
949                     memcpy( spi->ProcessName.Buffer, exename, wlen );
950                     spi->NextEntryOffset += wlen;
951
952                     last = spi;
953                     spi = (SYSTEM_PROCESS_INFORMATION*)((char*)spi + spi->NextEntryOffset);
954                 }
955             }
956             if (ret == STATUS_SUCCESS && last) last->NextEntryOffset = 0;
957             if (hSnap) NtClose(hSnap);
958         }
959         break;
960     case SystemProcessorPerformanceInformation:
961         {
962             SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL;
963             unsigned int cpus = 0;
964             int out_cpus = Length / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
965
966             if (out_cpus == 0)
967             {
968                 len = 0;
969                 ret = STATUS_INFO_LENGTH_MISMATCH;
970                 break;
971             }
972             else
973 #ifdef __APPLE__
974             {
975                 processor_cpu_load_info_data_t *pinfo;
976                 mach_msg_type_number_t info_count;
977
978                 if (host_processor_info (mach_host_self (),
979                                          PROCESSOR_CPU_LOAD_INFO,
980                                          &cpus,
981                                          (processor_info_array_t*)&pinfo,
982                                          &info_count) == 0)
983                 {
984                     int i;
985                     cpus = min(cpus,out_cpus);
986                     len = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * cpus;
987                     sppi = RtlAllocateHeap(GetProcessHeap(), 0,len);
988                     for (i = 0; i < cpus; i++)
989                     {
990                         sppi[i].liIdleTime.QuadPart = pinfo[i].cpu_ticks[CPU_STATE_IDLE];
991                         sppi[i].liKernelTime.QuadPart = pinfo[i].cpu_ticks[CPU_STATE_SYSTEM];
992                         sppi[i].liUserTime.QuadPart = pinfo[i].cpu_ticks[CPU_STATE_USER];
993                     }
994                     vm_deallocate (mach_task_self (), (vm_address_t) pinfo, info_count * sizeof(natural_t));
995                 }
996             }
997 #else
998             {
999                 FILE *cpuinfo = fopen("/proc/stat","r");
1000                 if (cpuinfo)
1001                 {
1002                     unsigned usr,nice,sys;
1003                     unsigned long idle;
1004                     int count;
1005                     char name[10];
1006                     char line[255];
1007
1008                     /* first line is combined usage */
1009                     if (fgets(line,255,cpuinfo))
1010                         count = sscanf(line,"%s %u %u %u %lu",name, &usr, &nice,
1011                                    &sys, &idle);
1012                     else
1013                         count = 0;
1014                     /* we set this up in the for older non-smp enabled kernels */
1015                     if (count == 5 && strcmp(name,"cpu")==0)
1016                     {
1017                         sppi = RtlAllocateHeap(GetProcessHeap(), 0,
1018                                                sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
1019                         sppi->liIdleTime.QuadPart = idle;
1020                         sppi->liKernelTime.QuadPart = sys;
1021                         sppi->liUserTime.QuadPart = usr;
1022                         cpus = 1;
1023                         len = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
1024                     }
1025
1026                     do
1027                     {
1028                         if (fgets(line,255,cpuinfo))
1029                             count = sscanf(line,"%s %u %u %u %lu",name, &usr,
1030                                        &nice, &sys, &idle);
1031                         else
1032                             count = 0;
1033                         if (count == 5 && strncmp(name,"cpu",3)==0)
1034                         {
1035                             out_cpus --;
1036                             if (name[3]=='0') /* first cpu */
1037                             {
1038                                 sppi->liIdleTime.QuadPart = idle;
1039                                 sppi->liKernelTime.QuadPart = sys;
1040                                 sppi->liUserTime.QuadPart = usr;
1041                             }
1042                             else /* new cpu */
1043                             {
1044                                 len = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * (cpus+1);
1045                                 sppi = RtlReAllocateHeap(GetProcessHeap(), 0, sppi, len);
1046                                 sppi[cpus].liIdleTime.QuadPart = idle;
1047                                 sppi[cpus].liKernelTime.QuadPart = sys;
1048                                 sppi[cpus].liUserTime.QuadPart = usr;
1049                                 cpus++;
1050                             }
1051                         }
1052                         else
1053                             break;
1054                     } while (out_cpus > 0);
1055                     fclose(cpuinfo);
1056                 }
1057             }
1058 #endif
1059
1060             if (cpus == 0)
1061             {
1062                 static int i = 1;
1063
1064                 sppi = RtlAllocateHeap(GetProcessHeap(),0,sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
1065
1066                 memset(sppi, 0 , sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
1067                 FIXME("stub info_class SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION\n");
1068
1069                 /* many programs expect these values to change so fake change */
1070                 len = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
1071                 sppi->liKernelTime.QuadPart = 1 * i;
1072                 sppi->liUserTime.QuadPart = 2 * i;
1073                 sppi->liIdleTime.QuadPart = 3 * i;
1074                 i++;
1075             }
1076
1077             if (Length >= len)
1078             {
1079                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
1080                 else memcpy( SystemInformation, sppi, len);
1081             }
1082             else ret = STATUS_INFO_LENGTH_MISMATCH;
1083
1084             RtlFreeHeap(GetProcessHeap(),0,sppi);
1085         }
1086         break;
1087     case SystemModuleInformation:
1088         /* FIXME: should be system-wide */
1089         if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
1090         else ret = LdrQueryProcessModuleInformation( SystemInformation, Length, &len );
1091         break;
1092     case SystemHandleInformation:
1093         {
1094             SYSTEM_HANDLE_INFORMATION shi;
1095
1096             memset(&shi, 0, sizeof(shi));
1097             len = sizeof(shi);
1098
1099             if ( Length >= len)
1100             {
1101                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
1102                 else memcpy( SystemInformation, &shi, len);
1103             }
1104             else ret = STATUS_INFO_LENGTH_MISMATCH;
1105             FIXME("info_class SYSTEM_HANDLE_INFORMATION\n");
1106         }
1107         break;
1108     case SystemCacheInformation:
1109         {
1110             SYSTEM_CACHE_INFORMATION sci;
1111
1112             memset(&sci, 0, sizeof(sci)); /* FIXME */
1113             len = sizeof(sci);
1114
1115             if ( Length >= len)
1116             {
1117                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
1118                 else memcpy( SystemInformation, &sci, len);
1119             }
1120             else ret = STATUS_INFO_LENGTH_MISMATCH;
1121             FIXME("info_class SYSTEM_CACHE_INFORMATION\n");
1122         }
1123         break;
1124     case SystemInterruptInformation:
1125         {
1126             SYSTEM_INTERRUPT_INFORMATION sii;
1127
1128             memset(&sii, 0, sizeof(sii));
1129             len = sizeof(sii);
1130
1131             if ( Length >= len)
1132             {
1133                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
1134                 else memcpy( SystemInformation, &sii, len);
1135             }
1136             else ret = STATUS_INFO_LENGTH_MISMATCH;
1137             FIXME("info_class SYSTEM_INTERRUPT_INFORMATION\n");
1138         }
1139         break;
1140     case SystemKernelDebuggerInformation:
1141         {
1142             SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi;
1143
1144             skdi.DebuggerEnabled = FALSE;
1145             skdi.DebuggerNotPresent = TRUE;
1146             len = sizeof(skdi);
1147
1148             if ( Length >= len)
1149             {
1150                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
1151                 else memcpy( SystemInformation, &skdi, len);
1152             }
1153             else ret = STATUS_INFO_LENGTH_MISMATCH;
1154         }
1155         break;
1156     case SystemRegistryQuotaInformation:
1157         {
1158             /* Something to do with the size of the registry             *
1159              * Since we don't have a size limitation, fake it            *
1160              * This is almost certainly wrong.                           *
1161              * This sets each of the three words in the struct to 32 MB, *
1162              * which is enough to make the IE 5 installer happy.         */
1163             SYSTEM_REGISTRY_QUOTA_INFORMATION srqi;
1164
1165             srqi.RegistryQuotaAllowed = 0x2000000;
1166             srqi.RegistryQuotaUsed = 0x200000;
1167             srqi.Reserved1 = (void*)0x200000;
1168             len = sizeof(srqi);
1169
1170             if ( Length >= len)
1171             {
1172                 if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
1173                 else
1174                 {
1175                     FIXME("SystemRegistryQuotaInformation: faking max registry size of 32 MB\n");
1176                     memcpy( SystemInformation, &srqi, len);
1177                 }
1178             }
1179             else ret = STATUS_INFO_LENGTH_MISMATCH;
1180         }
1181         break;
1182     default:
1183         FIXME("(0x%08x,%p,0x%08x,%p) stub\n",
1184               SystemInformationClass,SystemInformation,Length,ResultLength);
1185
1186         /* Several Information Classes are not implemented on Windows and return 2 different values 
1187          * STATUS_NOT_IMPLEMENTED or STATUS_INVALID_INFO_CLASS
1188          * in 95% of the cases it's STATUS_INVALID_INFO_CLASS, so use this as the default
1189         */
1190         ret = STATUS_INVALID_INFO_CLASS;
1191     }
1192
1193     if (ResultLength) *ResultLength = len;
1194
1195     return ret;
1196 }
1197
1198 /******************************************************************************
1199  * NtSetSystemInformation [NTDLL.@]
1200  * ZwSetSystemInformation [NTDLL.@]
1201  */
1202 NTSTATUS WINAPI NtSetSystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG Length)
1203 {
1204     FIXME("(0x%08x,%p,0x%08x) stub\n",SystemInformationClass,SystemInformation,Length);
1205     return STATUS_SUCCESS;
1206 }
1207
1208 /******************************************************************************
1209  *  NtCreatePagingFile          [NTDLL.@]
1210  *  ZwCreatePagingFile          [NTDLL.@]
1211  */
1212 NTSTATUS WINAPI NtCreatePagingFile(
1213         PUNICODE_STRING PageFileName,
1214         PLARGE_INTEGER MinimumSize,
1215         PLARGE_INTEGER MaximumSize,
1216         PLARGE_INTEGER ActualSize)
1217 {
1218     FIXME("(%p %p %p %p) stub\n", PageFileName, MinimumSize, MaximumSize, ActualSize);
1219     return STATUS_SUCCESS;
1220 }
1221
1222 /******************************************************************************
1223  *  NtDisplayString                             [NTDLL.@]
1224  *
1225  * writes a string to the nt-textmode screen eg. during startup
1226  */
1227 NTSTATUS WINAPI NtDisplayString ( PUNICODE_STRING string )
1228 {
1229     STRING stringA;
1230     NTSTATUS ret;
1231
1232     if (!(ret = RtlUnicodeStringToAnsiString( &stringA, string, TRUE )))
1233     {
1234         MESSAGE( "%.*s", stringA.Length, stringA.Buffer );
1235         RtlFreeAnsiString( &stringA );
1236     }
1237     return ret;
1238 }
1239
1240 /******************************************************************************
1241  *  NtInitiatePowerAction                       [NTDLL.@]
1242  *
1243  */
1244 NTSTATUS WINAPI NtInitiatePowerAction(
1245         IN POWER_ACTION SystemAction,
1246         IN SYSTEM_POWER_STATE MinSystemState,
1247         IN ULONG Flags,
1248         IN BOOLEAN Asynchronous)
1249 {
1250         FIXME("(%d,%d,0x%08x,%d),stub\n",
1251                 SystemAction,MinSystemState,Flags,Asynchronous);
1252         return STATUS_NOT_IMPLEMENTED;
1253 }
1254         
1255
1256 /******************************************************************************
1257  *  NtPowerInformation                          [NTDLL.@]
1258  *
1259  */
1260 NTSTATUS WINAPI NtPowerInformation(
1261         IN POWER_INFORMATION_LEVEL InformationLevel,
1262         IN PVOID lpInputBuffer,
1263         IN ULONG nInputBufferSize,
1264         IN PVOID lpOutputBuffer,
1265         IN ULONG nOutputBufferSize)
1266 {
1267         TRACE("(%d,%p,%d,%p,%d)\n",
1268                 InformationLevel,lpInputBuffer,nInputBufferSize,lpOutputBuffer,nOutputBufferSize);
1269         switch(InformationLevel) {
1270                 case SystemPowerCapabilities: {
1271                         PSYSTEM_POWER_CAPABILITIES PowerCaps = lpOutputBuffer;
1272                         FIXME("semi-stub: SystemPowerCapabilities\n");
1273                         if (nOutputBufferSize < sizeof(SYSTEM_POWER_CAPABILITIES))
1274                                 return STATUS_BUFFER_TOO_SMALL;
1275                         /* FIXME: These values are based off a native XP desktop, should probably use APM/ACPI to get the 'real' values */
1276                         PowerCaps->PowerButtonPresent = TRUE;
1277                         PowerCaps->SleepButtonPresent = FALSE;
1278                         PowerCaps->LidPresent = FALSE;
1279                         PowerCaps->SystemS1 = TRUE;
1280                         PowerCaps->SystemS2 = FALSE;
1281                         PowerCaps->SystemS3 = FALSE;
1282                         PowerCaps->SystemS4 = TRUE;
1283                         PowerCaps->SystemS5 = TRUE;
1284                         PowerCaps->HiberFilePresent = TRUE;
1285                         PowerCaps->FullWake = TRUE;
1286                         PowerCaps->VideoDimPresent = FALSE;
1287                         PowerCaps->ApmPresent = FALSE;
1288                         PowerCaps->UpsPresent = FALSE;
1289                         PowerCaps->ThermalControl = FALSE;
1290                         PowerCaps->ProcessorThrottle = FALSE;
1291                         PowerCaps->ProcessorMinThrottle = 100;
1292                         PowerCaps->ProcessorMaxThrottle = 100;
1293                         PowerCaps->DiskSpinDown = TRUE;
1294                         PowerCaps->SystemBatteriesPresent = FALSE;
1295                         PowerCaps->BatteriesAreShortTerm = FALSE;
1296                         PowerCaps->BatteryScale[0].Granularity = 0;
1297                         PowerCaps->BatteryScale[0].Capacity = 0;
1298                         PowerCaps->BatteryScale[1].Granularity = 0;
1299                         PowerCaps->BatteryScale[1].Capacity = 0;
1300                         PowerCaps->BatteryScale[2].Granularity = 0;
1301                         PowerCaps->BatteryScale[2].Capacity = 0;
1302                         PowerCaps->AcOnLineWake = PowerSystemUnspecified;
1303                         PowerCaps->SoftLidWake = PowerSystemUnspecified;
1304                         PowerCaps->RtcWake = PowerSystemSleeping1;
1305                         PowerCaps->MinDeviceWakeState = PowerSystemUnspecified;
1306                         PowerCaps->DefaultLowLatencyWake = PowerSystemUnspecified;
1307                         return STATUS_SUCCESS;
1308                 }
1309                 default:
1310                         FIXME("Unimplemented NtPowerInformation action: %d\n", InformationLevel);
1311                         return STATUS_NOT_IMPLEMENTED;
1312         }
1313 }
1314
1315 /******************************************************************************
1316  *  NtShutdownSystem                            [NTDLL.@]
1317  *
1318  */
1319 NTSTATUS WINAPI NtShutdownSystem(SHUTDOWN_ACTION Action)
1320 {
1321     FIXME("%d\n",Action);
1322     return STATUS_SUCCESS;
1323 }
1324
1325 /******************************************************************************
1326  *  NtAllocateLocallyUniqueId (NTDLL.@)
1327  */
1328 NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID Luid)
1329 {
1330     NTSTATUS status;
1331
1332     TRACE("%p\n", Luid);
1333
1334     if (!Luid)
1335         return STATUS_ACCESS_VIOLATION;
1336
1337     SERVER_START_REQ( allocate_locally_unique_id )
1338     {
1339         status = wine_server_call( req );
1340         if (!status)
1341         {
1342             Luid->LowPart = reply->luid.low_part;
1343             Luid->HighPart = reply->luid.high_part;
1344         }
1345     }
1346     SERVER_END_REQ;
1347
1348     return status;
1349 }
1350
1351 /******************************************************************************
1352  *        VerSetConditionMask   (NTDLL.@)
1353  */
1354 ULONGLONG WINAPI VerSetConditionMask( ULONGLONG dwlConditionMask, DWORD dwTypeBitMask,
1355                                       BYTE dwConditionMask)
1356 {
1357     if(dwTypeBitMask == 0)
1358         return dwlConditionMask;
1359     dwConditionMask &= 0x07;
1360     if(dwConditionMask == 0)
1361         return dwlConditionMask;
1362
1363     if(dwTypeBitMask & VER_PRODUCT_TYPE)
1364         dwlConditionMask |= dwConditionMask << 7*3;
1365     else if (dwTypeBitMask & VER_SUITENAME)
1366         dwlConditionMask |= dwConditionMask << 6*3;
1367     else if (dwTypeBitMask & VER_SERVICEPACKMAJOR)
1368         dwlConditionMask |= dwConditionMask << 5*3;
1369     else if (dwTypeBitMask & VER_SERVICEPACKMINOR)
1370         dwlConditionMask |= dwConditionMask << 4*3;
1371     else if (dwTypeBitMask & VER_PLATFORMID)
1372         dwlConditionMask |= dwConditionMask << 3*3;
1373     else if (dwTypeBitMask & VER_BUILDNUMBER)
1374         dwlConditionMask |= dwConditionMask << 2*3;
1375     else if (dwTypeBitMask & VER_MAJORVERSION)
1376         dwlConditionMask |= dwConditionMask << 1*3;
1377     else if (dwTypeBitMask & VER_MINORVERSION)
1378         dwlConditionMask |= dwConditionMask << 0*3;
1379     return dwlConditionMask;
1380 }
1381
1382 /******************************************************************************
1383  *  NtAccessCheckAndAuditAlarm   (NTDLL.@)
1384  *  ZwAccessCheckAndAuditAlarm   (NTDLL.@)
1385  */
1386 NTSTATUS WINAPI NtAccessCheckAndAuditAlarm(PUNICODE_STRING SubsystemName, HANDLE HandleId, PUNICODE_STRING ObjectTypeName,
1387                                            PUNICODE_STRING ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor,
1388                                            ACCESS_MASK DesiredAccess, PGENERIC_MAPPING GenericMapping, BOOLEAN ObjectCreation,
1389                                            PACCESS_MASK GrantedAccess, PBOOLEAN AccessStatus, PBOOLEAN GenerateOnClose)
1390 {
1391     FIXME("(%s, %p, %s, %p, 0x%08x, %p, %d, %p, %p, %p), stub\n", debugstr_us(SubsystemName), HandleId,
1392           debugstr_us(ObjectTypeName), SecurityDescriptor, DesiredAccess, GenericMapping, ObjectCreation,
1393           GrantedAccess, AccessStatus, GenerateOnClose);
1394
1395     return STATUS_NOT_IMPLEMENTED;
1396 }