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