xref: /reactos/dll/win32/advapi32/wine/security.c (revision 3e42f7b4)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * WINE COPYRIGHT:
4  * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
5  * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6  * Copyright 2006 Robert Reif
7  * Copyright 2006 Hervé Poussineau
8  *
9  * PROJECT:         ReactOS system libraries
10  * FILE:            dll/win32/advapi32/wine/security.c
11  */
12 
13 #include <advapi32.h>
14 
15 #include <sddl.h>
16 
17 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
18 
19 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
20 #ifdef __REACTOS__
21 VOID WINAPI QuerySecurityAccessMask(SECURITY_INFORMATION,LPDWORD);
22 VOID WINAPI SetSecurityAccessMask(SECURITY_INFORMATION,LPDWORD);
23 #endif
24 
25 typedef struct _ACEFLAG
26 {
27    LPCWSTR wstr;
28    DWORD value;
29 } ACEFLAG, *LPACEFLAG;
30 
31 typedef struct _MAX_SID
32 {
33     /* same fields as struct _SID */
34     BYTE Revision;
35     BYTE SubAuthorityCount;
36     SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
37     DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
38 } MAX_SID;
39 
40 typedef struct WELLKNOWNSID
41 {
42     WCHAR wstr[2];
43     WELL_KNOWN_SID_TYPE Type;
44     MAX_SID Sid;
45 } WELLKNOWNSID;
46 
47 static const WELLKNOWNSID WellKnownSids[] =
48 {
49     { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
50     { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
51     { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
52     { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
53     { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
54     { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
55     { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
56     { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
57     { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
58     { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
59     { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
60     { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
61     { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
62     { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
63     { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
64     { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
65     { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
66     { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
67     { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
68     { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
69     { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
70     { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
71     { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
72     { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
73     { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
74     { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
75     { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
76     { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
77     { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
78     { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
79     { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
80     { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
81     { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
82     { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
83     { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
84     { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
85     { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
86     { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
87     { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
88     { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
89     { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
90     { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
91     { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS  } } },
92     { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
93     { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
94     { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
95     { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
96     { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
97     { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
98     { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
99     { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
100     { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
101 };
102 
103 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */
104 typedef struct WELLKNOWNRID
105 {
106     WCHAR wstr[2];
107     WELL_KNOWN_SID_TYPE Type;
108     DWORD Rid;
109 } WELLKNOWNRID;
110 
111 static const WELLKNOWNRID WellKnownRids[] = {
112     { {'L','A'}, WinAccountAdministratorSid,    DOMAIN_USER_RID_ADMIN },
113     { {'L','G'}, WinAccountGuestSid,            DOMAIN_USER_RID_GUEST },
114     { {0,0}, WinAccountKrbtgtSid,           DOMAIN_USER_RID_KRBTGT },
115     { {'D','A'}, WinAccountDomainAdminsSid,     DOMAIN_GROUP_RID_ADMINS },
116     { {'D','U'}, WinAccountDomainUsersSid,      DOMAIN_GROUP_RID_USERS },
117     { {'D','G'}, WinAccountDomainGuestsSid,     DOMAIN_GROUP_RID_GUESTS },
118     { {'D','C'}, WinAccountComputersSid,        DOMAIN_GROUP_RID_COMPUTERS },
119     { {'D','D'}, WinAccountControllersSid,      DOMAIN_GROUP_RID_CONTROLLERS },
120     { {'C','A'}, WinAccountCertAdminsSid,       DOMAIN_GROUP_RID_CERT_ADMINS },
121     { {'S','A'}, WinAccountSchemaAdminsSid,     DOMAIN_GROUP_RID_SCHEMA_ADMINS },
122     { {'E','A'}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
123     { {'P','A'}, WinAccountPolicyAdminsSid,     DOMAIN_GROUP_RID_POLICY_ADMINS },
124     { {'R','S'}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
125 };
126 
127 #ifndef __REACTOS__
128 static const SID sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
129 #endif
130 
131 static const WCHAR SDDL_NO_READ_UP[]       = {'N','R',0};
132 static const WCHAR SDDL_NO_WRITE_UP[]      = {'N','W',0};
133 static const WCHAR SDDL_NO_EXECUTE_UP[]    = {'N','X',0};
134 
135 /*
136  * ACE types
137  */
138 static const WCHAR SDDL_ACCESS_ALLOWED[]        = {'A',0};
139 static const WCHAR SDDL_ACCESS_DENIED[]         = {'D',0};
140 #ifndef __REACTOS__
141 static const WCHAR SDDL_OBJECT_ACCESS_ALLOWED[] = {'O','A',0};
142 static const WCHAR SDDL_OBJECT_ACCESS_DENIED[]  = {'O','D',0};
143 #endif
144 static const WCHAR SDDL_AUDIT[]                 = {'A','U',0};
145 static const WCHAR SDDL_ALARM[]                 = {'A','L',0};
146 static const WCHAR SDDL_MANDATORY_LABEL[]       = {'M','L',0};
147 #ifndef __REACTOS__
148 static const WCHAR SDDL_OBJECT_AUDIT[]          = {'O','U',0};
149 static const WCHAR SDDL_OBJECT_ALARM[]          = {'O','L',0};
150 #endif
151 
152 /*
153  * SDDL ADS Rights
154  */
155 #define ADS_RIGHT_DS_CREATE_CHILD   0x0001
156 #define ADS_RIGHT_DS_DELETE_CHILD   0x0002
157 #define ADS_RIGHT_ACTRL_DS_LIST     0x0004
158 #define ADS_RIGHT_DS_SELF           0x0008
159 #define ADS_RIGHT_DS_READ_PROP      0x0010
160 #define ADS_RIGHT_DS_WRITE_PROP     0x0020
161 #define ADS_RIGHT_DS_DELETE_TREE    0x0040
162 #define ADS_RIGHT_DS_LIST_OBJECT    0x0080
163 #define ADS_RIGHT_DS_CONTROL_ACCESS 0x0100
164 
165 /*
166  * ACE flags
167  */
168 static const WCHAR SDDL_CONTAINER_INHERIT[]  = {'C','I',0};
169 static const WCHAR SDDL_OBJECT_INHERIT[]     = {'O','I',0};
170 static const WCHAR SDDL_NO_PROPAGATE[]       = {'N','P',0};
171 static const WCHAR SDDL_INHERIT_ONLY[]       = {'I','O',0};
172 static const WCHAR SDDL_INHERITED[]          = {'I','D',0};
173 static const WCHAR SDDL_AUDIT_SUCCESS[]      = {'S','A',0};
174 static const WCHAR SDDL_AUDIT_FAILURE[]      = {'F','A',0};
175 
176 static const char * debugstr_sid(PSID sid)
177 {
178     int auth = 0;
179     SID * psid = (SID *)sid;
180 
181     if (psid == NULL)
182         return "(null)";
183 
184     auth = psid->IdentifierAuthority.Value[5] +
185            (psid->IdentifierAuthority.Value[4] << 8) +
186            (psid->IdentifierAuthority.Value[3] << 16) +
187            (psid->IdentifierAuthority.Value[2] << 24);
188 
189     switch (psid->SubAuthorityCount) {
190     case 0:
191         return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
192     case 1:
193         return wine_dbg_sprintf("S-%d-%d-%lu", psid->Revision, auth,
194             psid->SubAuthority[0]);
195     case 2:
196         return wine_dbg_sprintf("S-%d-%d-%lu-%lu", psid->Revision, auth,
197             psid->SubAuthority[0], psid->SubAuthority[1]);
198     case 3:
199         return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu", psid->Revision, auth,
200             psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
201     case 4:
202         return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu", psid->Revision, auth,
203             psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
204             psid->SubAuthority[3]);
205     case 5:
206         return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
207             psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
208             psid->SubAuthority[3], psid->SubAuthority[4]);
209     case 6:
210         return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
211             psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
212             psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
213     case 7:
214         return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
215             psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
216             psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
217             psid->SubAuthority[6]);
218     case 8:
219         return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
220             psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
221             psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
222             psid->SubAuthority[6], psid->SubAuthority[7]);
223     }
224     return "(too-big)";
225 }
226 
227 /* set last error code from NT status and get the proper boolean return value */
228 /* used for functions that are a simple wrapper around the corresponding ntdll API */
229 static __inline BOOL set_ntstatus( NTSTATUS status )
230 {
231     if (!NT_SUCCESS(status)) SetLastError( RtlNtStatusToDosError( status ));
232     return NT_SUCCESS(status);
233 }
234 
235 static LPWSTR SERV_dup( LPCSTR str )
236 {
237     UINT len;
238     LPWSTR wstr;
239 
240     if( !str )
241         return NULL;
242     len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
243     wstr = heap_alloc( len*sizeof (WCHAR) );
244     MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
245     return wstr;
246 }
247 
248 /************************************************************
249  *                ADVAPI_IsLocalComputer
250  *
251  * Checks whether the server name indicates local machine.
252  */
253 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
254 {
255     DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
256     BOOL Result;
257     LPWSTR buf;
258 
259     if (!ServerName || !ServerName[0])
260         return TRUE;
261 
262     buf = heap_alloc(dwSize * sizeof(WCHAR));
263     Result = GetComputerNameW(buf,  &dwSize);
264     if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
265         ServerName += 2;
266     Result = Result && !lstrcmpW(ServerName, buf);
267     heap_free(buf);
268 
269     return Result;
270 }
271 
272 /************************************************************
273  *                ADVAPI_GetComputerSid
274  */
275 BOOL ADVAPI_GetComputerSid(PSID sid)
276 {
277     static const struct /* same fields as struct SID */
278     {
279         BYTE Revision;
280         BYTE SubAuthorityCount;
281         SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
282         DWORD SubAuthority[4];
283     } computer_sid =
284     { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } };
285 
286     memcpy( sid, &computer_sid, sizeof(computer_sid) );
287     return TRUE;
288 }
289 
290 /* Exported functions */
291 
292 /*
293  * @implemented
294  */
295 BOOL WINAPI
296 OpenProcessToken(HANDLE ProcessHandle,
297                  DWORD DesiredAccess,
298                  PHANDLE TokenHandle)
299 {
300     NTSTATUS Status;
301 
302     TRACE("%p, %x, %p.\n", ProcessHandle, DesiredAccess, TokenHandle);
303 
304     Status = NtOpenProcessToken(ProcessHandle,
305                                 DesiredAccess,
306                                 TokenHandle);
307     if (!NT_SUCCESS(Status))
308     {
309         ERR("NtOpenProcessToken failed! Status %08x.\n", Status);
310         SetLastError(RtlNtStatusToDosError(Status));
311         return FALSE;
312     }
313 
314     TRACE("Returning token %p.\n", *TokenHandle);
315 
316     return TRUE;
317 }
318 
319 /******************************************************************************
320  * OpenThreadToken [ADVAPI32.@]
321  *
322  * Opens the access token associated with a thread handle.
323  *
324  * PARAMS
325  *   ThreadHandle  [I] Handle to process
326  *   DesiredAccess [I] Desired access to the thread
327  *   OpenAsSelf    [I] ???
328  *   TokenHandle   [O] Destination for the token handle
329  *
330  * RETURNS
331  *  Success: TRUE. TokenHandle contains the access token.
332  *  Failure: FALSE.
333  *
334  * NOTES
335  *  See NtOpenThreadToken.
336  */
337 BOOL WINAPI
338 OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess,
339 		 BOOL OpenAsSelf, HANDLE *TokenHandle)
340 {
341 	return set_ntstatus( NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle));
342 }
343 
344 /*
345  * @implemented
346  */
347 BOOL WINAPI
348 AdjustTokenGroups(HANDLE TokenHandle,
349                   BOOL ResetToDefault,
350                   PTOKEN_GROUPS NewState,
351                   DWORD BufferLength,
352                   PTOKEN_GROUPS PreviousState,
353                   PDWORD ReturnLength)
354 {
355     NTSTATUS Status;
356 
357     Status = NtAdjustGroupsToken(TokenHandle,
358                                  ResetToDefault,
359                                  NewState,
360                                  BufferLength,
361                                  PreviousState,
362                                  (PULONG)ReturnLength);
363     if (!NT_SUCCESS(Status))
364     {
365        SetLastError(RtlNtStatusToDosError(Status));
366        return FALSE;
367     }
368 
369     return TRUE;
370 }
371 
372 /*
373  * @implemented
374  */
375 BOOL WINAPI
376 AdjustTokenPrivileges(HANDLE TokenHandle,
377                       BOOL DisableAllPrivileges,
378                       PTOKEN_PRIVILEGES NewState,
379                       DWORD BufferLength,
380                       PTOKEN_PRIVILEGES PreviousState,
381                       PDWORD ReturnLength)
382 {
383     NTSTATUS Status;
384 
385     Status = NtAdjustPrivilegesToken(TokenHandle,
386                                      DisableAllPrivileges,
387                                      NewState,
388                                      BufferLength,
389                                      PreviousState,
390                                      (PULONG)ReturnLength);
391     if (STATUS_NOT_ALL_ASSIGNED == Status)
392     {
393         SetLastError(ERROR_NOT_ALL_ASSIGNED);
394         return TRUE;
395     }
396 
397     if (!NT_SUCCESS(Status))
398     {
399         SetLastError(RtlNtStatusToDosError(Status));
400         return FALSE;
401     }
402 
403     /* AdjustTokenPrivileges is documented to do this */
404     SetLastError(ERROR_SUCCESS);
405 
406     return TRUE;
407 }
408 
409 /*
410  * @implemented
411  */
412 BOOL WINAPI
413 GetTokenInformation(HANDLE TokenHandle,
414                     TOKEN_INFORMATION_CLASS TokenInformationClass,
415                     LPVOID TokenInformation,
416                     DWORD TokenInformationLength,
417                     PDWORD ReturnLength)
418 {
419     NTSTATUS Status;
420 
421     Status = NtQueryInformationToken(TokenHandle,
422                                      TokenInformationClass,
423                                      TokenInformation,
424                                      TokenInformationLength,
425                                      (PULONG)ReturnLength);
426     if (!NT_SUCCESS(Status))
427     {
428         SetLastError(RtlNtStatusToDosError(Status));
429         return FALSE;
430     }
431 
432   return TRUE;
433 }
434 
435 /*
436  * @implemented
437  */
438 BOOL WINAPI
439 SetTokenInformation(HANDLE TokenHandle,
440                     TOKEN_INFORMATION_CLASS TokenInformationClass,
441                     LPVOID TokenInformation,
442                     DWORD TokenInformationLength)
443 {
444     NTSTATUS Status;
445 
446     Status = NtSetInformationToken(TokenHandle,
447                                    TokenInformationClass,
448                                    TokenInformation,
449                                    TokenInformationLength);
450     if (!NT_SUCCESS(Status))
451     {
452         SetLastError(RtlNtStatusToDosError(Status));
453         return FALSE;
454     }
455 
456     return TRUE;
457 }
458 
459 /*
460  * @implemented
461  */
462 BOOL WINAPI
463 SetThreadToken(IN PHANDLE ThreadHandle  OPTIONAL,
464                IN HANDLE TokenHandle)
465 {
466     NTSTATUS Status;
467     HANDLE hThread;
468 
469     hThread = (ThreadHandle != NULL) ? *ThreadHandle : NtCurrentThread();
470 
471     Status = NtSetInformationThread(hThread,
472                                     ThreadImpersonationToken,
473                                     &TokenHandle,
474                                     sizeof(HANDLE));
475     if (!NT_SUCCESS(Status))
476     {
477         SetLastError(RtlNtStatusToDosError(Status));
478         return FALSE;
479     }
480 
481     return TRUE;
482 }
483 
484 /**
485  * @brief
486  * Creates a filtered token that is a restricted one
487  * of the regular access token. A restricted token
488  * can have disabled SIDs, deleted privileges and/or
489  * restricted SIDs added.
490  *
491  * @param[in] ExistingTokenHandle
492  * An existing handle to a token where it's to be
493  * filtered.
494  *
495  * @param[in] Flags
496  * Privilege flag options. This parameter argument influences how the token
497  * is filtered. Such parameter can be 0.
498  *
499  * @param[in] DisableSidCount
500  * The count number of SIDs to disable.
501  *
502  * @param[in] SidsToDisable
503  * An array list with SIDs that have to be disabled in
504  * a token.
505  *
506  * @param[in] DeletePrivilegeCount
507  * The count number of privileges to be deleted.
508  *
509  * @param[in] PrivilegesToDelete
510  * An array list with privileges that have to be deleted
511  * in a token.
512  *
513  * @param[in] RestrictedSidCount
514  * The count number of restricted SIDs.
515  *
516  * @param[in] SidsToRestrict
517  * An array list with restricted SIDs to be added into
518  * the token. If the token already has restricted SIDs
519  * then the array provided by the caller is redundant
520  * information alongside with the existing restricted
521  * SIDs in the token.
522  *
523  * @param[out] NewTokenHandle
524  * The newly received handle to a restricted (filtered)
525  * token. The caller can use such handle to duplicate
526  * a new token.
527  *
528  * @return
529  * Returns TRUE if the function has successfully completed
530  * the operations, otherwise FALSE is returned to indicate
531  * failure. For further details the caller has to invoke
532  * GetLastError() API call for extended information
533  * about the failure.
534  */
535 BOOL WINAPI CreateRestrictedToken(
536     _In_ HANDLE ExistingTokenHandle,
537     _In_ DWORD Flags,
538     _In_ DWORD DisableSidCount,
539     _In_reads_opt_(DisableSidCount) PSID_AND_ATTRIBUTES SidsToDisable,
540     _In_ DWORD DeletePrivilegeCount,
541     _In_reads_opt_(DeletePrivilegeCount) PLUID_AND_ATTRIBUTES PrivilegesToDelete,
542     _In_ DWORD RestrictedSidCount,
543     _In_reads_opt_(RestrictedSidCount) PSID_AND_ATTRIBUTES SidsToRestrict,
544     _Outptr_ PHANDLE NewTokenHandle)
545 {
546     NTSTATUS Status;
547     BOOL Success;
548     ULONG Index;
549     PTOKEN_GROUPS DisableSids = NULL;
550     PTOKEN_GROUPS RestrictedSids = NULL;
551     PTOKEN_PRIVILEGES DeletePrivileges = NULL;
552 
553     /*
554      * Capture the elements we're being given from
555      * the caller and allocate the groups and/or
556      * privileges that have to be filtered in
557      * the token.
558      */
559     if (SidsToDisable != NULL)
560     {
561         DisableSids = (PTOKEN_GROUPS)LocalAlloc(LMEM_FIXED, DisableSidCount * sizeof(TOKEN_GROUPS));
562         if (DisableSids == NULL)
563         {
564             /* We failed, bail out */
565             SetLastError(RtlNtStatusToDosError(STATUS_INSUFFICIENT_RESOURCES));
566             return FALSE;
567         }
568 
569         /* Copy the counter and loop the elements to copy the rest */
570         DisableSids->GroupCount = DisableSidCount;
571         for (Index = 0; Index < DisableSidCount; Index++)
572         {
573             DisableSids->Groups[Index].Sid = SidsToDisable[Index].Sid;
574             DisableSids->Groups[Index].Attributes = SidsToDisable[Index].Attributes;
575         }
576     }
577 
578     if (PrivilegesToDelete != NULL)
579     {
580         DeletePrivileges = (PTOKEN_PRIVILEGES)LocalAlloc(LMEM_FIXED, DeletePrivilegeCount * sizeof(TOKEN_PRIVILEGES));
581         if (DeletePrivileges == NULL)
582         {
583             /* We failed, bail out */
584             SetLastError(RtlNtStatusToDosError(STATUS_INSUFFICIENT_RESOURCES));
585             Success = FALSE;
586             goto Cleanup;
587         }
588 
589         /* Copy the counter and loop the elements to copy the rest */
590         DeletePrivileges->PrivilegeCount = DeletePrivilegeCount;
591         for (Index = 0; Index < DeletePrivilegeCount; Index++)
592         {
593             DeletePrivileges->Privileges[Index].Luid = PrivilegesToDelete[Index].Luid;
594             DeletePrivileges->Privileges[Index].Attributes = PrivilegesToDelete[Index].Attributes;
595         }
596     }
597 
598     if (SidsToRestrict != NULL)
599     {
600         RestrictedSids = (PTOKEN_GROUPS)LocalAlloc(LMEM_FIXED, RestrictedSidCount * sizeof(TOKEN_GROUPS));
601         if (RestrictedSids == NULL)
602         {
603             /* We failed, bail out */
604             SetLastError(RtlNtStatusToDosError(STATUS_INSUFFICIENT_RESOURCES));
605             Success = FALSE;
606             goto Cleanup;
607         }
608 
609         /* Copy the counter and loop the elements to copy the rest */
610         RestrictedSids->GroupCount = RestrictedSidCount;
611         for (Index = 0; Index < RestrictedSidCount; Index++)
612         {
613             RestrictedSids->Groups[Index].Sid = SidsToRestrict[Index].Sid;
614             RestrictedSids->Groups[Index].Attributes = SidsToRestrict[Index].Attributes;
615         }
616     }
617 
618     /*
619      * Call the NT API to request a token filtering
620      * operation for us.
621      */
622     Status = NtFilterToken(ExistingTokenHandle,
623                            Flags,
624                            DisableSids,
625                            DeletePrivileges,
626                            RestrictedSids,
627                            NewTokenHandle);
628     if (!NT_SUCCESS(Status))
629     {
630         /* We failed to do the job, bail out */
631         SetLastError(RtlNtStatusToDosError(Status));
632         Success = FALSE;
633         goto Cleanup;
634     }
635 
636     /* If we reach here then we've successfully filtered the token */
637     Success = TRUE;
638 
639 Cleanup:
640     /* Free whatever we allocated before */
641     if (DisableSids != NULL)
642     {
643         LocalFree(DisableSids);
644     }
645 
646     if (DeletePrivileges != NULL)
647     {
648         LocalFree(DeletePrivileges);
649     }
650 
651     if (RestrictedSids != NULL)
652     {
653         LocalFree(RestrictedSids);
654     }
655 
656     return Success;
657 }
658 
659 /******************************************************************************
660  * AllocateAndInitializeSid [ADVAPI32.@]
661  *
662  * PARAMS
663  *   pIdentifierAuthority []
664  *   nSubAuthorityCount   []
665  *   nSubAuthority0       []
666  *   nSubAuthority1       []
667  *   nSubAuthority2       []
668  *   nSubAuthority3       []
669  *   nSubAuthority4       []
670  *   nSubAuthority5       []
671  *   nSubAuthority6       []
672  *   nSubAuthority7       []
673  *   pSid                 []
674  */
675 BOOL WINAPI
676 AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
677                           BYTE nSubAuthorityCount,
678                           DWORD nSubAuthority0, DWORD nSubAuthority1,
679                           DWORD nSubAuthority2, DWORD nSubAuthority3,
680                           DWORD nSubAuthority4, DWORD nSubAuthority5,
681                           DWORD nSubAuthority6, DWORD nSubAuthority7,
682                           PSID *pSid )
683 {
684     return set_ntstatus( RtlAllocateAndInitializeSid(
685                              pIdentifierAuthority, nSubAuthorityCount,
686                              nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
687                              nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7,
688                              pSid ));
689 }
690 
691 /*
692  * @implemented
693  *
694  * RETURNS
695  *  Docs says this function does NOT return a value
696  *  even thou it's defined to return a PVOID...
697  */
698 PVOID
699 WINAPI
700 FreeSid(PSID pSid)
701 {
702     return RtlFreeSid(pSid);
703 }
704 
705 /******************************************************************************
706  * CopySid [ADVAPI32.@]
707  *
708  * PARAMS
709  *   nDestinationSidLength []
710  *   pDestinationSid       []
711  *   pSourceSid            []
712  */
713 BOOL WINAPI
714 CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
715 {
716 	return set_ntstatus(RtlCopySid(nDestinationSidLength, pDestinationSid, pSourceSid));
717 }
718 
719 /*
720  * @unimplemented
721  */
722 BOOL
723 WINAPI
724 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
725                    IN PSID DomainSid  OPTIONAL,
726                    OUT PSID pSid,
727                    IN OUT DWORD* cbSid)
728 {
729     unsigned int i;
730     TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
731 
732     if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
733     {
734         SetLastError(ERROR_INVALID_PARAMETER);
735         return FALSE;
736     }
737 
738     for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
739         if (WellKnownSids[i].Type == WellKnownSidType) {
740             DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
741 
742             if (*cbSid < length)
743             {
744                 *cbSid = length;
745                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
746                 return FALSE;
747             }
748             if (!pSid)
749             {
750                 SetLastError(ERROR_INVALID_PARAMETER);
751                 return FALSE;
752             }
753             CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
754             *cbSid = length;
755             return TRUE;
756         }
757     }
758 
759     if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
760     {
761         SetLastError(ERROR_INVALID_PARAMETER);
762         return FALSE;
763     }
764 
765     for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
766         if (WellKnownRids[i].Type == WellKnownSidType) {
767             UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
768             DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
769             DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
770 
771             if (*cbSid < output_sid_length)
772             {
773                 *cbSid = output_sid_length;
774                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
775                 return FALSE;
776             }
777             if (!pSid)
778             {
779                 SetLastError(ERROR_INVALID_PARAMETER);
780                 return FALSE;
781             }
782             CopyMemory(pSid, DomainSid, domain_sid_length);
783             (*GetSidSubAuthorityCount(pSid))++;
784             (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
785             *cbSid = output_sid_length;
786             return TRUE;
787         }
788 
789     SetLastError(ERROR_INVALID_PARAMETER);
790     return FALSE;
791 }
792 
793 /*
794  * @unimplemented
795  */
796 BOOL
797 WINAPI
798 IsWellKnownSid(IN PSID pSid,
799                IN WELL_KNOWN_SID_TYPE WellKnownSidType)
800 {
801     unsigned int i;
802     TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
803 
804     for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
805     {
806         if (WellKnownSids[i].Type == WellKnownSidType)
807         {
808             if (EqualSid(pSid, (PSID)(&WellKnownSids[i].Sid.Revision)))
809                 return TRUE;
810         }
811     }
812 
813     return FALSE;
814 }
815 
816 /*
817  * @implemented
818  */
819 BOOL
820 WINAPI
821 IsValidSid(PSID pSid)
822 {
823     return (BOOL)RtlValidSid(pSid);
824 }
825 
826 /*
827  * @implemented
828  */
829 BOOL
830 WINAPI
831 EqualSid(PSID pSid1,
832          PSID pSid2)
833 {
834     SetLastError(ERROR_SUCCESS);
835     return RtlEqualSid (pSid1, pSid2);
836 }
837 
838 /*
839  * @implemented
840  */
841 BOOL
842 WINAPI
843 EqualPrefixSid(PSID pSid1,
844                PSID pSid2)
845 {
846     return RtlEqualPrefixSid (pSid1, pSid2);
847 }
848 
849 /*
850  * @implemented
851  */
852 DWORD
853 WINAPI
854 GetSidLengthRequired(UCHAR nSubAuthorityCount)
855 {
856     return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
857 }
858 
859 /*
860  * @implemented
861  */
862 BOOL
863 WINAPI
864 InitializeSid(PSID Sid,
865               PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
866               BYTE nSubAuthorityCount)
867 {
868     NTSTATUS Status;
869 
870     Status = RtlInitializeSid(Sid,
871                               pIdentifierAuthority,
872                               nSubAuthorityCount);
873     if (!NT_SUCCESS(Status))
874     {
875         SetLastError(RtlNtStatusToDosError(Status));
876         return FALSE;
877     }
878 
879     return TRUE;
880 }
881 
882 /*
883  * @implemented
884  */
885 PSID_IDENTIFIER_AUTHORITY
886 WINAPI
887 GetSidIdentifierAuthority(PSID pSid)
888 {
889     SetLastError(ERROR_SUCCESS);
890     return RtlIdentifierAuthoritySid(pSid);
891 }
892 
893 /*
894  * @implemented
895  */
896 PDWORD
897 WINAPI
898 GetSidSubAuthority(PSID pSid,
899                    DWORD nSubAuthority)
900 {
901     SetLastError(ERROR_SUCCESS);
902     return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority);
903 }
904 
905 /*
906  * @implemented
907  */
908 PUCHAR
909 WINAPI
910 GetSidSubAuthorityCount(PSID pSid)
911 {
912     SetLastError(ERROR_SUCCESS);
913     return RtlSubAuthorityCountSid(pSid);
914 }
915 
916 /*
917  * @implemented
918  */
919 DWORD
920 WINAPI
921 GetLengthSid(PSID pSid)
922 {
923     return (DWORD)RtlLengthSid(pSid);
924 }
925 
926 /*
927  * @implemented
928  */
929 BOOL
930 WINAPI
931 InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor,
932                              DWORD dwRevision)
933 {
934     NTSTATUS Status;
935 
936     Status = RtlCreateSecurityDescriptor(pSecurityDescriptor,
937                                          dwRevision);
938     if (!NT_SUCCESS(Status))
939     {
940         SetLastError(RtlNtStatusToDosError(Status));
941         return FALSE;
942     }
943 
944     return TRUE;
945 }
946 
947 /*
948  * @implemented
949  */
950 BOOL
951 WINAPI
952 MakeAbsoluteSD(PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
953                PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
954                LPDWORD lpdwAbsoluteSecurityDescriptorSize,
955                PACL pDacl,
956                LPDWORD lpdwDaclSize,
957                PACL pSacl,
958                LPDWORD lpdwSaclSize,
959                PSID pOwner,
960                LPDWORD lpdwOwnerSize,
961                PSID pPrimaryGroup,
962                LPDWORD lpdwPrimaryGroupSize)
963 {
964     NTSTATUS Status;
965 
966     Status = RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor,
967                                          pAbsoluteSecurityDescriptor,
968                                          lpdwAbsoluteSecurityDescriptorSize,
969                                          pDacl,
970                                          lpdwDaclSize,
971                                          pSacl,
972                                          lpdwSaclSize,
973                                          pOwner,
974                                          lpdwOwnerSize,
975                                          pPrimaryGroup,
976                                          lpdwPrimaryGroupSize);
977     if (!NT_SUCCESS(Status))
978     {
979         SetLastError(RtlNtStatusToDosError(Status));
980         return FALSE;
981     }
982 
983     return TRUE;
984 }
985 
986 /******************************************************************************
987  * GetKernelObjectSecurity [ADVAPI32.@]
988  */
989 BOOL WINAPI GetKernelObjectSecurity(
990         HANDLE Handle,
991         SECURITY_INFORMATION RequestedInformation,
992         PSECURITY_DESCRIPTOR pSecurityDescriptor,
993         DWORD nLength,
994         LPDWORD lpnLengthNeeded )
995 {
996     TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation,
997           pSecurityDescriptor, nLength, lpnLengthNeeded);
998 
999     return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor,
1000                                                nLength, lpnLengthNeeded ));
1001 }
1002 
1003 /*
1004  * @implemented
1005  */
1006 BOOL
1007 WINAPI
1008 InitializeAcl(PACL pAcl,
1009               DWORD nAclLength,
1010               DWORD dwAclRevision)
1011 {
1012     NTSTATUS Status;
1013 
1014     Status = RtlCreateAcl(pAcl,
1015                           nAclLength,
1016                           dwAclRevision);
1017     if (!NT_SUCCESS(Status))
1018     {
1019         SetLastError(RtlNtStatusToDosError(Status));
1020         return FALSE;
1021     }
1022 
1023     return TRUE;
1024 }
1025 
1026 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe )
1027 {
1028     IO_STATUS_BLOCK io_block;
1029 
1030     TRACE("(%p)\n", hNamedPipe);
1031 
1032     return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL,
1033                          &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) );
1034 }
1035 
1036 /*
1037  * @implemented
1038  */
1039 BOOL
1040 WINAPI
1041 AddAccessAllowedAce(PACL pAcl,
1042                     DWORD dwAceRevision,
1043                     DWORD AccessMask,
1044                     PSID pSid)
1045 {
1046     NTSTATUS Status;
1047 
1048     Status = RtlAddAccessAllowedAce(pAcl,
1049                                     dwAceRevision,
1050                                     AccessMask,
1051                                     pSid);
1052     if (!NT_SUCCESS(Status))
1053     {
1054         SetLastError(RtlNtStatusToDosError(Status));
1055         return FALSE;
1056     }
1057 
1058     return TRUE;
1059 }
1060 
1061 /*
1062  * @implemented
1063  */
1064 BOOL WINAPI
1065 AddAccessAllowedAceEx(PACL pAcl,
1066                       DWORD dwAceRevision,
1067                       DWORD AceFlags,
1068                       DWORD AccessMask,
1069                       PSID pSid)
1070 {
1071     NTSTATUS Status;
1072 
1073     Status = RtlAddAccessAllowedAceEx(pAcl,
1074                                       dwAceRevision,
1075                                       AceFlags,
1076                                       AccessMask,
1077                                       pSid);
1078     if (!NT_SUCCESS(Status))
1079     {
1080         SetLastError(RtlNtStatusToDosError(Status));
1081         return FALSE;
1082     }
1083 
1084     return TRUE;
1085 }
1086 
1087 /*
1088  * @implemented
1089  */
1090 BOOL
1091 WINAPI
1092 AddAccessDeniedAce(PACL pAcl,
1093                    DWORD dwAceRevision,
1094                    DWORD AccessMask,
1095                    PSID pSid)
1096 {
1097     NTSTATUS Status;
1098 
1099     Status = RtlAddAccessDeniedAce(pAcl,
1100                                    dwAceRevision,
1101                                    AccessMask,
1102                                    pSid);
1103     if (!NT_SUCCESS(Status))
1104     {
1105         SetLastError(RtlNtStatusToDosError(Status));
1106         return FALSE;
1107     }
1108 
1109     return TRUE;
1110 }
1111 
1112 /*
1113  * @implemented
1114  */
1115 BOOL WINAPI
1116 AddAccessDeniedAceEx(PACL pAcl,
1117                      DWORD dwAceRevision,
1118                      DWORD AceFlags,
1119                      DWORD AccessMask,
1120                      PSID pSid)
1121 {
1122     NTSTATUS Status;
1123 
1124     Status = RtlAddAccessDeniedAceEx(pAcl,
1125                                      dwAceRevision,
1126                                      AceFlags,
1127                                      AccessMask,
1128                                      pSid);
1129     if (!NT_SUCCESS(Status))
1130     {
1131         SetLastError(RtlNtStatusToDosError(Status));
1132         return FALSE;
1133     }
1134 
1135     return TRUE;
1136 }
1137 
1138 /*
1139  * @implemented
1140  */
1141 BOOL
1142 WINAPI
1143 AddAce(PACL pAcl,
1144        DWORD dwAceRevision,
1145        DWORD dwStartingAceIndex,
1146        LPVOID pAceList,
1147        DWORD nAceListLength)
1148 {
1149     NTSTATUS Status;
1150 
1151     Status = RtlAddAce(pAcl,
1152                        dwAceRevision,
1153                        dwStartingAceIndex,
1154                        pAceList,
1155                        nAceListLength);
1156     if (!NT_SUCCESS(Status))
1157     {
1158         SetLastError(RtlNtStatusToDosError(Status));
1159         return FALSE;
1160     }
1161 
1162     return TRUE;
1163 }
1164 
1165 /******************************************************************************
1166  * DeleteAce [ADVAPI32.@]
1167  */
1168 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex)
1169 {
1170     return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex));
1171 }
1172 
1173 /*
1174  * @implemented
1175  */
1176 BOOL
1177 WINAPI
1178 FindFirstFreeAce(PACL pAcl,
1179                  LPVOID *pAce)
1180 {
1181     return RtlFirstFreeAce(pAcl,
1182                            (PACE*)pAce);
1183 }
1184 
1185 /******************************************************************************
1186  * GetAce [ADVAPI32.@]
1187  */
1188 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1189 {
1190     return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce));
1191 }
1192 
1193 /******************************************************************************
1194  * GetAclInformation [ADVAPI32.@]
1195  */
1196 BOOL WINAPI GetAclInformation(
1197   PACL pAcl,
1198   LPVOID pAclInformation,
1199   DWORD nAclInformationLength,
1200   ACL_INFORMATION_CLASS dwAclInformationClass)
1201 {
1202     return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation,
1203                                                nAclInformationLength, dwAclInformationClass));
1204 }
1205 
1206 /*
1207  * @implemented
1208  */
1209 BOOL
1210 WINAPI
1211 IsValidAcl(PACL pAcl)
1212 {
1213     return RtlValidAcl (pAcl);
1214 }
1215 
1216 /*
1217  * @implemented
1218  */
1219 BOOL WINAPI
1220 AllocateLocallyUniqueId(PLUID Luid)
1221 {
1222     NTSTATUS Status;
1223 
1224     Status = NtAllocateLocallyUniqueId (Luid);
1225     if (!NT_SUCCESS (Status))
1226     {
1227         SetLastError(RtlNtStatusToDosError(Status));
1228         return FALSE;
1229     }
1230 
1231     return TRUE;
1232 }
1233 
1234 /**********************************************************************
1235  * LookupPrivilegeDisplayNameA			EXPORTED
1236  *
1237  * @unimplemented
1238  */
1239 BOOL
1240 WINAPI
1241 LookupPrivilegeDisplayNameA(LPCSTR lpSystemName,
1242                             LPCSTR lpName,
1243                             LPSTR lpDisplayName,
1244                             LPDWORD cchDisplayName,
1245                             LPDWORD lpLanguageId)
1246 {
1247     UNICODE_STRING lpSystemNameW;
1248     UNICODE_STRING lpNameW;
1249     BOOL ret;
1250     DWORD wLen = 0;
1251 
1252     TRACE("%s %s %p %p %p\n", debugstr_a(lpSystemName), debugstr_a(lpName), lpName, cchDisplayName, lpLanguageId);
1253 
1254     RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1255     RtlCreateUnicodeStringFromAsciiz(&lpNameW, lpName);
1256     ret = LookupPrivilegeDisplayNameW(lpSystemNameW.Buffer, lpNameW.Buffer, NULL, &wLen, lpLanguageId);
1257     if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1258     {
1259         LPWSTR lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR));
1260 
1261         ret = LookupPrivilegeDisplayNameW(lpSystemNameW.Buffer, lpNameW.Buffer, lpDisplayNameW,
1262                                           &wLen, lpLanguageId);
1263         if (ret)
1264         {
1265             unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, lpDisplayName,
1266                                                    *cchDisplayName, NULL, NULL);
1267 
1268             if (len == 0)
1269             {
1270                 /* WideCharToMultiByte failed */
1271                 ret = FALSE;
1272             }
1273             else if (len > *cchDisplayName)
1274             {
1275                 *cchDisplayName = len;
1276                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1277                 ret = FALSE;
1278             }
1279             else
1280             {
1281                 /* WideCharToMultiByte succeeded, output length needs to be
1282                  * length not including NULL terminator
1283                  */
1284                 *cchDisplayName = len - 1;
1285             }
1286         }
1287         HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1288     }
1289     RtlFreeUnicodeString(&lpSystemNameW);
1290     RtlFreeUnicodeString(&lpNameW);
1291     return ret;
1292 }
1293 
1294 /**********************************************************************
1295  * LookupPrivilegeNameA				EXPORTED
1296  *
1297  * @implemented
1298  */
1299 BOOL
1300 WINAPI
1301 LookupPrivilegeNameA(LPCSTR lpSystemName,
1302                      PLUID lpLuid,
1303                      LPSTR lpName,
1304                      LPDWORD cchName)
1305 {
1306     UNICODE_STRING lpSystemNameW;
1307     BOOL ret;
1308     DWORD wLen = 0;
1309 
1310     TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1311 
1312     RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1313     ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1314     if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1315     {
1316         LPWSTR lpNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR));
1317 
1318         ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1319          &wLen);
1320         if (ret)
1321         {
1322             /* Windows crashes if cchName is NULL, so will I */
1323             unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1324              *cchName, NULL, NULL);
1325 
1326             if (len == 0)
1327             {
1328                 /* WideCharToMultiByte failed */
1329                 ret = FALSE;
1330             }
1331             else if (len > *cchName)
1332             {
1333                 *cchName = len;
1334                 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1335                 ret = FALSE;
1336             }
1337             else
1338             {
1339                 /* WideCharToMultiByte succeeded, output length needs to be
1340                  * length not including NULL terminator
1341                  */
1342                 *cchName = len - 1;
1343             }
1344         }
1345         HeapFree(GetProcessHeap(), 0, lpNameW);
1346     }
1347     RtlFreeUnicodeString(&lpSystemNameW);
1348     return ret;
1349 }
1350 
1351 /******************************************************************************
1352  * GetFileSecurityA [ADVAPI32.@]
1353  *
1354  * Obtains Specified information about the security of a file or directory.
1355  *
1356  * PARAMS
1357  *  lpFileName           [I] Name of the file to get info for
1358  *  RequestedInformation [I] SE_ flags from "winnt.h"
1359  *  pSecurityDescriptor  [O] Destination for security information
1360  *  nLength              [I] Length of pSecurityDescriptor
1361  *  lpnLengthNeeded      [O] Destination for length of returned security information
1362  *
1363  * RETURNS
1364  *  Success: TRUE. pSecurityDescriptor contains the requested information.
1365  *  Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
1366  *
1367  * NOTES
1368  *  The information returned is constrained by the callers access rights and
1369  *  privileges.
1370  *
1371  * @implemented
1372  */
1373 BOOL
1374 WINAPI
1375 GetFileSecurityA(LPCSTR lpFileName,
1376                  SECURITY_INFORMATION RequestedInformation,
1377                  PSECURITY_DESCRIPTOR pSecurityDescriptor,
1378                  DWORD nLength,
1379                  LPDWORD lpnLengthNeeded)
1380 {
1381     UNICODE_STRING FileName;
1382     BOOL bResult;
1383 
1384     if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName))
1385     {
1386         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1387         return FALSE;
1388     }
1389 
1390     bResult = GetFileSecurityW(FileName.Buffer,
1391                                RequestedInformation,
1392                                pSecurityDescriptor,
1393                                nLength,
1394                                lpnLengthNeeded);
1395 
1396     RtlFreeUnicodeString(&FileName);
1397 
1398     return bResult;
1399 }
1400 
1401 /*
1402  * @implemented
1403  */
1404 BOOL
1405 WINAPI
1406 GetFileSecurityW(LPCWSTR lpFileName,
1407                  SECURITY_INFORMATION RequestedInformation,
1408                  PSECURITY_DESCRIPTOR pSecurityDescriptor,
1409                  DWORD nLength,
1410                  LPDWORD lpnLengthNeeded)
1411 {
1412     OBJECT_ATTRIBUTES ObjectAttributes;
1413     IO_STATUS_BLOCK StatusBlock;
1414     UNICODE_STRING FileName;
1415     ULONG AccessMask = 0;
1416     HANDLE FileHandle;
1417     NTSTATUS Status;
1418 
1419     TRACE("GetFileSecurityW() called\n");
1420 
1421     QuerySecurityAccessMask(RequestedInformation, &AccessMask);
1422 
1423     if (!RtlDosPathNameToNtPathName_U(lpFileName,
1424                                       &FileName,
1425                                       NULL,
1426                                       NULL))
1427     {
1428         ERR("Invalid path\n");
1429         SetLastError(ERROR_INVALID_NAME);
1430         return FALSE;
1431     }
1432 
1433     InitializeObjectAttributes(&ObjectAttributes,
1434                                &FileName,
1435                                OBJ_CASE_INSENSITIVE,
1436                                NULL,
1437                                NULL);
1438 
1439     Status = NtOpenFile(&FileHandle,
1440                         AccessMask,
1441                         &ObjectAttributes,
1442                         &StatusBlock,
1443                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1444                         0);
1445 
1446     RtlFreeHeap(RtlGetProcessHeap(),
1447                 0,
1448                 FileName.Buffer);
1449 
1450     if (!NT_SUCCESS(Status))
1451     {
1452         ERR("NtOpenFile() failed (Status %lx)\n", Status);
1453         SetLastError(RtlNtStatusToDosError(Status));
1454         return FALSE;
1455     }
1456 
1457     Status = NtQuerySecurityObject(FileHandle,
1458                                    RequestedInformation,
1459                                    pSecurityDescriptor,
1460                                    nLength,
1461                                    lpnLengthNeeded);
1462     NtClose(FileHandle);
1463     if (!NT_SUCCESS(Status))
1464     {
1465         ERR("NtQuerySecurityObject() failed (Status %lx)\n", Status);
1466         SetLastError(RtlNtStatusToDosError(Status));
1467         return FALSE;
1468     }
1469 
1470     return TRUE;
1471 }
1472 
1473 /******************************************************************************
1474  * SetFileSecurityA [ADVAPI32.@]
1475  * Sets the security of a file or directory
1476  *
1477  * @implemented
1478  */
1479 BOOL
1480 WINAPI
1481 SetFileSecurityA(LPCSTR lpFileName,
1482                  SECURITY_INFORMATION SecurityInformation,
1483                  PSECURITY_DESCRIPTOR pSecurityDescriptor)
1484 {
1485     UNICODE_STRING FileName;
1486     BOOL bResult;
1487 
1488     if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName))
1489     {
1490         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1491         return FALSE;
1492     }
1493 
1494     bResult = SetFileSecurityW(FileName.Buffer,
1495                                SecurityInformation,
1496                                pSecurityDescriptor);
1497 
1498     RtlFreeUnicodeString(&FileName);
1499 
1500     return bResult;
1501 }
1502 
1503 /******************************************************************************
1504  * SetFileSecurityW [ADVAPI32.@]
1505  * Sets the security of a file or directory
1506  *
1507  * @implemented
1508  */
1509 BOOL
1510 WINAPI
1511 SetFileSecurityW(LPCWSTR lpFileName,
1512                  SECURITY_INFORMATION SecurityInformation,
1513                  PSECURITY_DESCRIPTOR pSecurityDescriptor)
1514 {
1515     OBJECT_ATTRIBUTES ObjectAttributes;
1516     IO_STATUS_BLOCK StatusBlock;
1517     UNICODE_STRING FileName;
1518     ULONG AccessMask = 0;
1519     HANDLE FileHandle;
1520     NTSTATUS Status;
1521 
1522     TRACE("SetFileSecurityW() called\n");
1523 
1524     SetSecurityAccessMask(SecurityInformation, &AccessMask);
1525 
1526     if (!RtlDosPathNameToNtPathName_U(lpFileName,
1527                                       &FileName,
1528                                       NULL,
1529                                       NULL))
1530     {
1531         ERR("Invalid path\n");
1532         SetLastError(ERROR_INVALID_NAME);
1533         return FALSE;
1534     }
1535 
1536     InitializeObjectAttributes(&ObjectAttributes,
1537                                &FileName,
1538                                OBJ_CASE_INSENSITIVE,
1539                                NULL,
1540                                NULL);
1541 
1542     Status = NtOpenFile(&FileHandle,
1543                         AccessMask,
1544                         &ObjectAttributes,
1545                         &StatusBlock,
1546                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1547                         0);
1548 
1549     RtlFreeHeap(RtlGetProcessHeap(),
1550                 0,
1551                 FileName.Buffer);
1552 
1553     if (!NT_SUCCESS(Status))
1554     {
1555         ERR("NtOpenFile() failed (Status %lx)\n", Status);
1556         SetLastError(RtlNtStatusToDosError(Status));
1557         return FALSE;
1558     }
1559 
1560     Status = NtSetSecurityObject(FileHandle,
1561                                  SecurityInformation,
1562                                  pSecurityDescriptor);
1563     NtClose(FileHandle);
1564 
1565     if (!NT_SUCCESS(Status))
1566     {
1567         ERR("NtSetSecurityObject() failed (Status %lx)\n", Status);
1568         SetLastError(RtlNtStatusToDosError(Status));
1569         return FALSE;
1570     }
1571 
1572     return TRUE;
1573 }
1574 
1575 /******************************************************************************
1576  * QueryWindows31FilesMigration [ADVAPI32.@]
1577  *
1578  * PARAMS
1579  *   x1 []
1580  */
1581 BOOL WINAPI
1582 QueryWindows31FilesMigration( DWORD x1 )
1583 {
1584 	FIXME("(%d):stub\n",x1);
1585 	return TRUE;
1586 }
1587 
1588 /******************************************************************************
1589  * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
1590  *
1591  * PARAMS
1592  *   x1 []
1593  *   x2 []
1594  *   x3 []
1595  *   x4 []
1596  */
1597 BOOL WINAPI
1598 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
1599                                                DWORD x4 )
1600 {
1601 	FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
1602 	return TRUE;
1603 }
1604 
1605 /*
1606  * @implemented
1607  */
1608 BOOL
1609 WINAPI
1610 RevertToSelf(VOID)
1611 {
1612     NTSTATUS Status;
1613     HANDLE Token = NULL;
1614 
1615     Status = NtSetInformationThread(NtCurrentThread(),
1616                                     ThreadImpersonationToken,
1617                                     &Token,
1618                                     sizeof(HANDLE));
1619     if (!NT_SUCCESS(Status))
1620     {
1621         SetLastError(RtlNtStatusToDosError(Status));
1622         return FALSE;
1623     }
1624 
1625     return TRUE;
1626 }
1627 
1628 /*
1629  * @implemented
1630  */
1631 BOOL
1632 WINAPI
1633 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1634 {
1635     NTSTATUS Status;
1636 
1637     Status = RtlImpersonateSelf(ImpersonationLevel);
1638     if (!NT_SUCCESS(Status))
1639     {
1640         SetLastError(RtlNtStatusToDosError(Status));
1641         return FALSE;
1642     }
1643 
1644     return TRUE;
1645 }
1646 
1647 /*
1648  * @implemented
1649  */
1650 BOOL
1651 WINAPI
1652 AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1653             IN HANDLE ClientToken,
1654             IN DWORD DesiredAccess,
1655             IN PGENERIC_MAPPING GenericMapping,
1656             OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
1657             IN OUT LPDWORD PrivilegeSetLength,
1658             OUT LPDWORD GrantedAccess,
1659             OUT LPBOOL AccessStatus)
1660 {
1661     NTSTATUS Status;
1662     NTSTATUS NtAccessStatus;
1663 
1664     /* Do the access check */
1665     Status = NtAccessCheck(pSecurityDescriptor,
1666                            ClientToken,
1667                            DesiredAccess,
1668                            GenericMapping,
1669                            PrivilegeSet,
1670                            (PULONG)PrivilegeSetLength,
1671                            (PACCESS_MASK)GrantedAccess,
1672                            &NtAccessStatus);
1673 
1674     /* See if the access check operation succeeded */
1675     if (!NT_SUCCESS(Status))
1676     {
1677         /* Check failed */
1678         SetLastError(RtlNtStatusToDosError(Status));
1679         return FALSE;
1680     }
1681 
1682     /* Now check the access status  */
1683     if (!NT_SUCCESS(NtAccessStatus))
1684     {
1685         /* Access denied */
1686         SetLastError(RtlNtStatusToDosError(NtAccessStatus));
1687         *AccessStatus = FALSE;
1688     }
1689     else
1690     {
1691         /* Access granted */
1692         *AccessStatus = TRUE;
1693     }
1694 
1695     /* Check succeeded */
1696     return TRUE;
1697 }
1698 
1699 /*
1700  * @unimplemented
1701  */
1702 BOOL WINAPI AccessCheckByType(
1703     PSECURITY_DESCRIPTOR pSecurityDescriptor,
1704     PSID PrincipalSelfSid,
1705     HANDLE ClientToken,
1706     DWORD DesiredAccess,
1707     POBJECT_TYPE_LIST ObjectTypeList,
1708     DWORD ObjectTypeListLength,
1709     PGENERIC_MAPPING GenericMapping,
1710     PPRIVILEGE_SET PrivilegeSet,
1711     LPDWORD PrivilegeSetLength,
1712     LPDWORD GrantedAccess,
1713     LPBOOL AccessStatus)
1714 {
1715 	FIXME("stub\n");
1716 
1717 	*AccessStatus = TRUE;
1718 
1719 	return !*AccessStatus;
1720 }
1721 
1722 /*
1723  * @implemented
1724  */
1725 BOOL
1726 WINAPI
1727 SetKernelObjectSecurity(HANDLE Handle,
1728                         SECURITY_INFORMATION SecurityInformation,
1729                         PSECURITY_DESCRIPTOR SecurityDescriptor)
1730 {
1731     NTSTATUS Status;
1732 
1733     Status = NtSetSecurityObject(Handle,
1734                                  SecurityInformation,
1735                                  SecurityDescriptor);
1736     if (!NT_SUCCESS(Status))
1737     {
1738         SetLastError(RtlNtStatusToDosError(Status));
1739         return FALSE;
1740     }
1741 
1742     return TRUE;
1743 }
1744 
1745 /*
1746  * @implemented
1747  */
1748 BOOL
1749 WINAPI
1750 AddAuditAccessAce(PACL pAcl,
1751                   DWORD dwAceRevision,
1752                   DWORD dwAccessMask,
1753                   PSID pSid,
1754                   BOOL bAuditSuccess,
1755                   BOOL bAuditFailure)
1756 {
1757     NTSTATUS Status;
1758 
1759     Status = RtlAddAuditAccessAce(pAcl,
1760                                   dwAceRevision,
1761                                   dwAccessMask,
1762                                   pSid,
1763                                   bAuditSuccess,
1764                                   bAuditFailure);
1765     if (!NT_SUCCESS(Status))
1766     {
1767         SetLastError(RtlNtStatusToDosError(Status));
1768         return FALSE;
1769     }
1770 
1771     return TRUE;
1772 }
1773 
1774 /*
1775  * @implemented
1776  */
1777 BOOL WINAPI
1778 AddAuditAccessAceEx(PACL pAcl,
1779                     DWORD dwAceRevision,
1780                     DWORD AceFlags,
1781                     DWORD dwAccessMask,
1782                     PSID pSid,
1783                     BOOL bAuditSuccess,
1784                     BOOL bAuditFailure)
1785 {
1786     NTSTATUS Status;
1787 
1788     Status = RtlAddAuditAccessAceEx(pAcl,
1789                                     dwAceRevision,
1790                                     AceFlags,
1791                                     dwAccessMask,
1792                                     pSid,
1793                                     bAuditSuccess,
1794                                     bAuditFailure);
1795     if (!NT_SUCCESS(Status))
1796     {
1797         SetLastError(RtlNtStatusToDosError(Status));
1798         return FALSE;
1799     }
1800 
1801     return TRUE;
1802 }
1803 
1804 /******************************************************************************
1805  * LookupAccountNameA [ADVAPI32.@]
1806  *
1807  * @implemented
1808  */
1809 BOOL
1810 WINAPI
1811 LookupAccountNameA(LPCSTR SystemName,
1812                    LPCSTR AccountName,
1813                    PSID Sid,
1814                    LPDWORD SidLength,
1815                    LPSTR ReferencedDomainName,
1816                    LPDWORD hReferencedDomainNameLength,
1817                    PSID_NAME_USE SidNameUse)
1818 {
1819     BOOL ret;
1820     UNICODE_STRING lpSystemW;
1821     UNICODE_STRING lpAccountW;
1822     LPWSTR lpReferencedDomainNameW = NULL;
1823 
1824     RtlCreateUnicodeStringFromAsciiz(&lpSystemW, SystemName);
1825     RtlCreateUnicodeStringFromAsciiz(&lpAccountW, AccountName);
1826 
1827     if (ReferencedDomainName)
1828         lpReferencedDomainNameW = HeapAlloc(GetProcessHeap(),
1829                                             0,
1830                                             *hReferencedDomainNameLength * sizeof(WCHAR));
1831 
1832     ret = LookupAccountNameW(lpSystemW.Buffer,
1833                              lpAccountW.Buffer,
1834                              Sid,
1835                              SidLength,
1836                              lpReferencedDomainNameW,
1837                              hReferencedDomainNameLength,
1838                              SidNameUse);
1839 
1840     if (ret && lpReferencedDomainNameW)
1841     {
1842         WideCharToMultiByte(CP_ACP,
1843                             0,
1844                             lpReferencedDomainNameW,
1845                             *hReferencedDomainNameLength + 1,
1846                             ReferencedDomainName,
1847                             *hReferencedDomainNameLength + 1,
1848                             NULL,
1849                             NULL);
1850     }
1851 
1852     RtlFreeUnicodeString(&lpSystemW);
1853     RtlFreeUnicodeString(&lpAccountW);
1854     HeapFree(GetProcessHeap(), 0, lpReferencedDomainNameW);
1855 
1856     return ret;
1857 }
1858 
1859 /**********************************************************************
1860  *	PrivilegeCheck					EXPORTED
1861  *
1862  * @implemented
1863  */
1864 BOOL WINAPI
1865 PrivilegeCheck(HANDLE ClientToken,
1866                PPRIVILEGE_SET RequiredPrivileges,
1867                LPBOOL pfResult)
1868 {
1869     BOOLEAN Result;
1870     NTSTATUS Status;
1871 
1872     Status = NtPrivilegeCheck(ClientToken,
1873                               RequiredPrivileges,
1874                               &Result);
1875     if (!NT_SUCCESS(Status))
1876     {
1877         SetLastError(RtlNtStatusToDosError(Status));
1878         return FALSE;
1879     }
1880 
1881     *pfResult = (BOOL)Result;
1882 
1883     return TRUE;
1884 }
1885 
1886 /******************************************************************************
1887  * GetSecurityInfoExW         EXPORTED
1888  */
1889 DWORD
1890 WINAPI
1891 GetSecurityInfoExA(HANDLE hObject,
1892                    SE_OBJECT_TYPE ObjectType,
1893                    SECURITY_INFORMATION SecurityInfo,
1894                    LPCSTR lpProvider,
1895                    LPCSTR lpProperty,
1896                    PACTRL_ACCESSA *ppAccessList,
1897                    PACTRL_AUDITA *ppAuditList,
1898                    LPSTR *lppOwner,
1899                    LPSTR *lppGroup)
1900 {
1901     FIXME("%s() not implemented!\n", __FUNCTION__);
1902     return ERROR_BAD_PROVIDER;
1903 }
1904 
1905 
1906 /******************************************************************************
1907  * GetSecurityInfoExW         EXPORTED
1908  */
1909 DWORD
1910 WINAPI
1911 GetSecurityInfoExW(HANDLE hObject,
1912                    SE_OBJECT_TYPE ObjectType,
1913                    SECURITY_INFORMATION SecurityInfo,
1914                    LPCWSTR lpProvider,
1915                    LPCWSTR lpProperty,
1916                    PACTRL_ACCESSW *ppAccessList,
1917                    PACTRL_AUDITW *ppAuditList,
1918                    LPWSTR *lppOwner,
1919                    LPWSTR *lppGroup)
1920 {
1921     FIXME("%s() not implemented!\n", __FUNCTION__);
1922     return ERROR_BAD_PROVIDER;
1923 }
1924 
1925 /******************************************************************************
1926  * BuildExplicitAccessWithNameA [ADVAPI32.@]
1927  */
1928 VOID WINAPI
1929 BuildExplicitAccessWithNameA(PEXPLICIT_ACCESSA pExplicitAccess,
1930                              LPSTR pTrusteeName,
1931                              DWORD AccessPermissions,
1932                              ACCESS_MODE AccessMode,
1933                              DWORD Inheritance)
1934 {
1935     pExplicitAccess->grfAccessPermissions = AccessPermissions;
1936     pExplicitAccess->grfAccessMode = AccessMode;
1937     pExplicitAccess->grfInheritance = Inheritance;
1938 
1939     pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1940     pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1941     pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1942     pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1943     pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1944 }
1945 
1946 
1947 /******************************************************************************
1948  * BuildExplicitAccessWithNameW [ADVAPI32.@]
1949  */
1950 VOID WINAPI
1951 BuildExplicitAccessWithNameW(PEXPLICIT_ACCESSW pExplicitAccess,
1952                              LPWSTR pTrusteeName,
1953                              DWORD AccessPermissions,
1954                              ACCESS_MODE AccessMode,
1955                              DWORD Inheritance)
1956 {
1957     pExplicitAccess->grfAccessPermissions = AccessPermissions;
1958     pExplicitAccess->grfAccessMode = AccessMode;
1959     pExplicitAccess->grfInheritance = Inheritance;
1960 
1961     pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1962     pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1963     pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1964     pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1965     pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1966 }
1967 
1968 /******************************************************************************
1969  * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
1970  */
1971 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
1972                                              SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
1973                                              LPSTR InheritedObjectTypeName, LPSTR Name )
1974 {
1975     DWORD ObjectsPresent = 0;
1976 
1977     TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1978           ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
1979 
1980     /* Fill the OBJECTS_AND_NAME structure */
1981     pObjName->ObjectType = ObjectType;
1982     if (ObjectTypeName != NULL)
1983     {
1984         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1985     }
1986 
1987     pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1988     if (InheritedObjectTypeName != NULL)
1989     {
1990         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1991     }
1992 
1993     pObjName->ObjectsPresent = ObjectsPresent;
1994     pObjName->ptstrName = Name;
1995 
1996     /* Fill the TRUSTEE structure */
1997     pTrustee->pMultipleTrustee = NULL;
1998     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1999     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
2000     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2001     pTrustee->ptstrName = (LPSTR)pObjName;
2002 }
2003 
2004 /******************************************************************************
2005  * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
2006  */
2007 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
2008                                              SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
2009                                              LPWSTR InheritedObjectTypeName, LPWSTR Name )
2010 {
2011     DWORD ObjectsPresent = 0;
2012 
2013     TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
2014           ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
2015 
2016     /* Fill the OBJECTS_AND_NAME structure */
2017     pObjName->ObjectType = ObjectType;
2018     if (ObjectTypeName != NULL)
2019     {
2020         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
2021     }
2022 
2023     pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
2024     if (InheritedObjectTypeName != NULL)
2025     {
2026         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
2027     }
2028 
2029     pObjName->ObjectsPresent = ObjectsPresent;
2030     pObjName->ptstrName = Name;
2031 
2032     /* Fill the TRUSTEE structure */
2033     pTrustee->pMultipleTrustee = NULL;
2034     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2035     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
2036     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2037     pTrustee->ptstrName = (LPWSTR)pObjName;
2038 }
2039 
2040 /******************************************************************************
2041  * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
2042  */
2043 VOID WINAPI
2044 BuildTrusteeWithObjectsAndSidA(PTRUSTEEA pTrustee,
2045                                POBJECTS_AND_SID pObjSid,
2046                                GUID *pObjectGuid,
2047                                GUID *pInheritedObjectGuid,
2048                                PSID pSid)
2049 {
2050     DWORD ObjectsPresent = 0;
2051 
2052     TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
2053 
2054     /* Fill the OBJECTS_AND_SID structure */
2055     if (pObjectGuid != NULL)
2056     {
2057         pObjSid->ObjectTypeGuid = *pObjectGuid;
2058         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
2059     }
2060     else
2061     {
2062         ZeroMemory(&pObjSid->ObjectTypeGuid,
2063                    sizeof(GUID));
2064     }
2065 
2066     if (pInheritedObjectGuid != NULL)
2067     {
2068         pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
2069         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
2070     }
2071     else
2072     {
2073         ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
2074                    sizeof(GUID));
2075     }
2076 
2077     pObjSid->ObjectsPresent = ObjectsPresent;
2078     pObjSid->pSid = pSid;
2079 
2080     /* Fill the TRUSTEE structure */
2081     pTrustee->pMultipleTrustee = NULL;
2082     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2083     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
2084     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2085     pTrustee->ptstrName = (LPSTR) pObjSid;
2086 }
2087 
2088 
2089 /******************************************************************************
2090  * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
2091  */
2092 VOID WINAPI
2093 BuildTrusteeWithObjectsAndSidW(PTRUSTEEW pTrustee,
2094                                POBJECTS_AND_SID pObjSid,
2095                                GUID *pObjectGuid,
2096                                GUID *pInheritedObjectGuid,
2097                                PSID pSid)
2098 {
2099     DWORD ObjectsPresent = 0;
2100 
2101     TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
2102 
2103     /* Fill the OBJECTS_AND_SID structure */
2104     if (pObjectGuid != NULL)
2105     {
2106         pObjSid->ObjectTypeGuid = *pObjectGuid;
2107         ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
2108     }
2109     else
2110     {
2111         ZeroMemory(&pObjSid->ObjectTypeGuid,
2112                    sizeof(GUID));
2113     }
2114 
2115     if (pInheritedObjectGuid != NULL)
2116     {
2117         pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
2118         ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
2119     }
2120     else
2121     {
2122         ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
2123                    sizeof(GUID));
2124     }
2125 
2126     pObjSid->ObjectsPresent = ObjectsPresent;
2127     pObjSid->pSid = pSid;
2128 
2129     /* Fill the TRUSTEE structure */
2130     pTrustee->pMultipleTrustee = NULL;
2131     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2132     pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
2133     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2134     pTrustee->ptstrName = (LPWSTR) pObjSid;
2135 }
2136 
2137 /******************************************************************************
2138  * BuildTrusteeWithSidA [ADVAPI32.@]
2139  */
2140 VOID WINAPI
2141 BuildTrusteeWithSidA(PTRUSTEE_A pTrustee,
2142                      PSID pSid)
2143 {
2144     TRACE("%p %p\n", pTrustee, pSid);
2145 
2146     pTrustee->pMultipleTrustee = NULL;
2147     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2148     pTrustee->TrusteeForm = TRUSTEE_IS_SID;
2149     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2150     pTrustee->ptstrName = (LPSTR) pSid;
2151 }
2152 
2153 
2154 /******************************************************************************
2155  * BuildTrusteeWithSidW [ADVAPI32.@]
2156  */
2157 VOID WINAPI
2158 BuildTrusteeWithSidW(PTRUSTEE_W pTrustee,
2159                      PSID pSid)
2160 {
2161     TRACE("%p %p\n", pTrustee, pSid);
2162 
2163     pTrustee->pMultipleTrustee = NULL;
2164     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2165     pTrustee->TrusteeForm = TRUSTEE_IS_SID;
2166     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2167     pTrustee->ptstrName = (LPWSTR) pSid;
2168 }
2169 
2170 /******************************************************************************
2171  * BuildTrusteeWithNameA [ADVAPI32.@]
2172  */
2173 VOID WINAPI
2174 BuildTrusteeWithNameA(PTRUSTEE_A pTrustee,
2175                       LPSTR name)
2176 {
2177     TRACE("%p %s\n", pTrustee, name);
2178 
2179     pTrustee->pMultipleTrustee = NULL;
2180     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2181     pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
2182     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2183     pTrustee->ptstrName = name;
2184 }
2185 
2186 /******************************************************************************
2187  * BuildTrusteeWithNameW [ADVAPI32.@]
2188  */
2189 VOID WINAPI
2190 BuildTrusteeWithNameW(PTRUSTEE_W pTrustee,
2191                       LPWSTR name)
2192 {
2193     TRACE("%p %s\n", pTrustee, name);
2194 
2195     pTrustee->pMultipleTrustee = NULL;
2196     pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2197     pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
2198     pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2199     pTrustee->ptstrName = name;
2200 }
2201 
2202 /******************************************************************************
2203  * GetTrusteeFormA [ADVAPI32.@]
2204  */
2205 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
2206 {
2207     TRACE("(%p)\n", pTrustee);
2208 
2209     if (!pTrustee)
2210         return TRUSTEE_BAD_FORM;
2211 
2212     return pTrustee->TrusteeForm;
2213 }
2214 
2215 /******************************************************************************
2216  * GetTrusteeFormW [ADVAPI32.@]
2217  */
2218 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
2219 {
2220     TRACE("(%p)\n", pTrustee);
2221 
2222     if (!pTrustee)
2223         return TRUSTEE_BAD_FORM;
2224 
2225     return pTrustee->TrusteeForm;
2226 }
2227 
2228 /******************************************************************************
2229  * GetTrusteeNameA [ADVAPI32.@]
2230  */
2231 LPSTR WINAPI
2232 GetTrusteeNameA(PTRUSTEE_A pTrustee)
2233 {
2234     return pTrustee->ptstrName;
2235 }
2236 
2237 
2238 /******************************************************************************
2239  * GetTrusteeNameW [ADVAPI32.@]
2240  */
2241 LPWSTR WINAPI
2242 GetTrusteeNameW(PTRUSTEE_W pTrustee)
2243 {
2244     return pTrustee->ptstrName;
2245 }
2246 
2247 /******************************************************************************
2248  * GetTrusteeTypeA [ADVAPI32.@]
2249  */
2250 TRUSTEE_TYPE WINAPI
2251 GetTrusteeTypeA(PTRUSTEE_A pTrustee)
2252 {
2253     return pTrustee->TrusteeType;
2254 }
2255 
2256 /******************************************************************************
2257  * GetTrusteeTypeW [ADVAPI32.@]
2258  */
2259 TRUSTEE_TYPE WINAPI
2260 GetTrusteeTypeW(PTRUSTEE_W pTrustee)
2261 {
2262     return pTrustee->TrusteeType;
2263 }
2264 
2265 /*
2266  * @implemented
2267  */
2268 BOOL
2269 WINAPI
2270 SetAclInformation(PACL pAcl,
2271                   LPVOID pAclInformation,
2272                   DWORD nAclInformationLength,
2273                   ACL_INFORMATION_CLASS dwAclInformationClass)
2274 {
2275     NTSTATUS Status;
2276 
2277     Status = RtlSetInformationAcl(pAcl,
2278                                   pAclInformation,
2279                                   nAclInformationLength,
2280                                   dwAclInformationClass);
2281     if (!NT_SUCCESS(Status))
2282     {
2283         SetLastError(RtlNtStatusToDosError(Status));
2284         return FALSE;
2285     }
2286 
2287     return TRUE;
2288 }
2289 
2290 /**********************************************************************
2291  * SetNamedSecurityInfoA			EXPORTED
2292  *
2293  * @implemented
2294  */
2295 DWORD
2296 WINAPI
2297 SetNamedSecurityInfoA(LPSTR pObjectName,
2298                       SE_OBJECT_TYPE ObjectType,
2299                       SECURITY_INFORMATION SecurityInfo,
2300                       PSID psidOwner,
2301                       PSID psidGroup,
2302                       PACL pDacl,
2303                       PACL pSacl)
2304 {
2305     UNICODE_STRING ObjectName;
2306     DWORD Ret;
2307 
2308     if (!RtlCreateUnicodeStringFromAsciiz(&ObjectName, pObjectName))
2309     {
2310         return ERROR_NOT_ENOUGH_MEMORY;
2311     }
2312 
2313     Ret = SetNamedSecurityInfoW(ObjectName.Buffer,
2314                                 ObjectType,
2315                                 SecurityInfo,
2316                                 psidOwner,
2317                                 psidGroup,
2318                                 pDacl,
2319                                 pSacl);
2320 
2321     RtlFreeUnicodeString(&ObjectName);
2322 
2323     return Ret;
2324 }
2325 
2326 /*
2327  * @implemented
2328  */
2329 BOOL
2330 WINAPI
2331 AreAllAccessesGranted(DWORD GrantedAccess,
2332                       DWORD DesiredAccess)
2333 {
2334     return (BOOL)RtlAreAllAccessesGranted(GrantedAccess,
2335                                           DesiredAccess);
2336 }
2337 
2338 /*
2339  * @implemented
2340  */
2341 BOOL
2342 WINAPI
2343 AreAnyAccessesGranted(DWORD GrantedAccess,
2344                       DWORD DesiredAccess)
2345 {
2346     return (BOOL)RtlAreAnyAccessesGranted(GrantedAccess,
2347                                           DesiredAccess);
2348 }
2349 
2350 /******************************************************************************
2351  * ParseAclStringFlags
2352  */
2353 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
2354 {
2355     DWORD flags = 0;
2356     LPCWSTR szAcl = *StringAcl;
2357 
2358     while (*szAcl && *szAcl != '(')
2359     {
2360         if (*szAcl == 'P')
2361         {
2362             flags |= SE_DACL_PROTECTED;
2363         }
2364         else if (*szAcl == 'A')
2365         {
2366             szAcl++;
2367             if (*szAcl == 'R')
2368                 flags |= SE_DACL_AUTO_INHERIT_REQ;
2369             else if (*szAcl == 'I')
2370                 flags |= SE_DACL_AUTO_INHERITED;
2371         }
2372         szAcl++;
2373     }
2374 
2375     *StringAcl = szAcl;
2376     return flags;
2377 }
2378 
2379 /******************************************************************************
2380  * ParseAceStringType
2381  */
2382 static const ACEFLAG AceType[] =
2383 {
2384     { SDDL_ALARM,          SYSTEM_ALARM_ACE_TYPE },
2385     { SDDL_AUDIT,          SYSTEM_AUDIT_ACE_TYPE },
2386     { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
2387     { SDDL_ACCESS_DENIED,  ACCESS_DENIED_ACE_TYPE },
2388     { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_ACE_TYPE },
2389     /*
2390     { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
2391     { SDDL_OBJECT_ACCESS_DENIED,  ACCESS_DENIED_OBJECT_ACE_TYPE },
2392     { SDDL_OBJECT_ALARM,          SYSTEM_ALARM_OBJECT_ACE_TYPE },
2393     { SDDL_OBJECT_AUDIT,          SYSTEM_AUDIT_OBJECT_ACE_TYPE },
2394     */
2395     { NULL, 0 },
2396 };
2397 
2398 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
2399 {
2400     UINT len = 0;
2401     LPCWSTR szAcl = *StringAcl;
2402     const ACEFLAG *lpaf = AceType;
2403 
2404     while (*szAcl == ' ')
2405         szAcl++;
2406 
2407     while (lpaf->wstr &&
2408         (len = strlenW(lpaf->wstr)) &&
2409         strncmpW(lpaf->wstr, szAcl, len))
2410         lpaf++;
2411 
2412     if (!lpaf->wstr)
2413         return 0;
2414 
2415     *StringAcl = szAcl + len;
2416     return lpaf->value;
2417 }
2418 
2419 
2420 /******************************************************************************
2421  * ParseAceStringFlags
2422  */
2423 static const ACEFLAG AceFlags[] =
2424 {
2425     { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
2426     { SDDL_AUDIT_FAILURE,     FAILED_ACCESS_ACE_FLAG },
2427     { SDDL_INHERITED,         INHERITED_ACE },
2428     { SDDL_INHERIT_ONLY,      INHERIT_ONLY_ACE },
2429     { SDDL_NO_PROPAGATE,      NO_PROPAGATE_INHERIT_ACE },
2430     { SDDL_OBJECT_INHERIT,    OBJECT_INHERIT_ACE },
2431     { SDDL_AUDIT_SUCCESS,     SUCCESSFUL_ACCESS_ACE_FLAG },
2432     { NULL, 0 },
2433 };
2434 
2435 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
2436 {
2437     UINT len = 0;
2438     BYTE flags = 0;
2439     LPCWSTR szAcl = *StringAcl;
2440 
2441     while (*szAcl == ' ')
2442         szAcl++;
2443 
2444     while (*szAcl != ';')
2445     {
2446         const ACEFLAG *lpaf = AceFlags;
2447 
2448         while (lpaf->wstr &&
2449                (len = strlenW(lpaf->wstr)) &&
2450                strncmpW(lpaf->wstr, szAcl, len))
2451             lpaf++;
2452 
2453         if (!lpaf->wstr)
2454             return 0;
2455 
2456 	flags |= lpaf->value;
2457         szAcl += len;
2458     }
2459 
2460     *StringAcl = szAcl;
2461     return flags;
2462 }
2463 
2464 
2465 /******************************************************************************
2466  * ParseAceStringRights
2467  */
2468 static const ACEFLAG AceRights[] =
2469 {
2470     { SDDL_GENERIC_ALL,     GENERIC_ALL },
2471     { SDDL_GENERIC_READ,    GENERIC_READ },
2472     { SDDL_GENERIC_WRITE,   GENERIC_WRITE },
2473     { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
2474 
2475     { SDDL_READ_CONTROL,    READ_CONTROL },
2476     { SDDL_STANDARD_DELETE, DELETE },
2477     { SDDL_WRITE_DAC,       WRITE_DAC },
2478     { SDDL_WRITE_OWNER,     WRITE_OWNER },
2479 
2480     { SDDL_READ_PROPERTY,   ADS_RIGHT_DS_READ_PROP},
2481     { SDDL_WRITE_PROPERTY,  ADS_RIGHT_DS_WRITE_PROP},
2482     { SDDL_CREATE_CHILD,    ADS_RIGHT_DS_CREATE_CHILD},
2483     { SDDL_DELETE_CHILD,    ADS_RIGHT_DS_DELETE_CHILD},
2484     { SDDL_LIST_CHILDREN,   ADS_RIGHT_ACTRL_DS_LIST},
2485     { SDDL_SELF_WRITE,      ADS_RIGHT_DS_SELF},
2486     { SDDL_LIST_OBJECT,     ADS_RIGHT_DS_LIST_OBJECT},
2487     { SDDL_DELETE_TREE,     ADS_RIGHT_DS_DELETE_TREE},
2488     { SDDL_CONTROL_ACCESS,  ADS_RIGHT_DS_CONTROL_ACCESS},
2489 
2490     { SDDL_FILE_ALL,        FILE_ALL_ACCESS },
2491     { SDDL_FILE_READ,       FILE_GENERIC_READ },
2492     { SDDL_FILE_WRITE,      FILE_GENERIC_WRITE },
2493     { SDDL_FILE_EXECUTE,    FILE_GENERIC_EXECUTE },
2494 
2495     { SDDL_KEY_ALL,         KEY_ALL_ACCESS },
2496     { SDDL_KEY_READ,        KEY_READ },
2497     { SDDL_KEY_WRITE,       KEY_WRITE },
2498     { SDDL_KEY_EXECUTE,     KEY_EXECUTE },
2499 
2500     { SDDL_NO_READ_UP,      SYSTEM_MANDATORY_LABEL_NO_READ_UP },
2501     { SDDL_NO_WRITE_UP,     SYSTEM_MANDATORY_LABEL_NO_WRITE_UP },
2502     { SDDL_NO_EXECUTE_UP,   SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP },
2503     { NULL, 0 },
2504 };
2505 
2506 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
2507 {
2508     UINT len = 0;
2509     DWORD rights = 0;
2510     LPCWSTR szAcl = *StringAcl;
2511 
2512     while (*szAcl == ' ')
2513         szAcl++;
2514 
2515     if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
2516     {
2517         LPCWSTR p = szAcl;
2518 
2519 	while (*p && *p != ';')
2520             p++;
2521 
2522 	if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
2523 	{
2524 	    rights = strtoulW(szAcl, NULL, 16);
2525 	    szAcl = p;
2526 	}
2527 	else
2528             WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
2529     }
2530     else
2531     {
2532         while (*szAcl != ';')
2533         {
2534             const ACEFLAG *lpaf = AceRights;
2535 
2536             while (lpaf->wstr &&
2537                (len = strlenW(lpaf->wstr)) &&
2538                strncmpW(lpaf->wstr, szAcl, len))
2539 	    {
2540                lpaf++;
2541 	    }
2542 
2543             if (!lpaf->wstr)
2544                 return 0;
2545 
2546 	    rights |= lpaf->value;
2547             szAcl += len;
2548         }
2549     }
2550 
2551     *StringAcl = szAcl;
2552     return rights;
2553 }
2554 
2555 
2556 /******************************************************************************
2557  * ParseStringAclToAcl
2558  *
2559  * dacl_flags(string_ace1)(string_ace2)... (string_acen)
2560  */
2561 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
2562     PACL pAcl, LPDWORD cBytes)
2563 {
2564     DWORD val;
2565     DWORD sidlen;
2566     DWORD length = sizeof(ACL);
2567     DWORD acesize = 0;
2568     DWORD acecount = 0;
2569     PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
2570     DWORD error = ERROR_INVALID_ACL;
2571 
2572     TRACE("%s\n", debugstr_w(StringAcl));
2573 
2574     if (!StringAcl)
2575 	return FALSE;
2576 
2577     if (pAcl) /* pAce is only useful if we're setting values */
2578         pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
2579 
2580     /* Parse ACL flags */
2581     *lpdwFlags = ParseAclStringFlags(&StringAcl);
2582 
2583     /* Parse ACE */
2584     while (*StringAcl == '(')
2585     {
2586         StringAcl++;
2587 
2588         /* Parse ACE type */
2589         val = ParseAceStringType(&StringAcl);
2590 	if (pAce)
2591             pAce->Header.AceType = (BYTE) val;
2592         if (*StringAcl != ';')
2593         {
2594             error = RPC_S_INVALID_STRING_UUID;
2595             goto lerr;
2596         }
2597         StringAcl++;
2598 
2599         /* Parse ACE flags */
2600 	val = ParseAceStringFlags(&StringAcl);
2601 	if (pAce)
2602             pAce->Header.AceFlags = (BYTE) val;
2603         if (*StringAcl != ';')
2604             goto lerr;
2605         StringAcl++;
2606 
2607         /* Parse ACE rights */
2608 	val = ParseAceStringRights(&StringAcl);
2609 	if (pAce)
2610             pAce->Mask = val;
2611         if (*StringAcl != ';')
2612             goto lerr;
2613         StringAcl++;
2614 
2615         /* Parse ACE object guid */
2616         while (*StringAcl == ' ')
2617             StringAcl++;
2618         if (*StringAcl != ';')
2619         {
2620             FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
2621             goto lerr;
2622         }
2623         StringAcl++;
2624 
2625         /* Parse ACE inherit object guid */
2626         while (*StringAcl == ' ')
2627             StringAcl++;
2628         if (*StringAcl != ';')
2629         {
2630             FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
2631             goto lerr;
2632         }
2633         StringAcl++;
2634 
2635         /* Parse ACE account sid */
2636         if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
2637 	{
2638             while (*StringAcl && *StringAcl != ')')
2639                 StringAcl++;
2640 	}
2641 
2642         if (*StringAcl != ')')
2643             goto lerr;
2644         StringAcl++;
2645 
2646         acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
2647         length += acesize;
2648         if (pAce)
2649         {
2650             pAce->Header.AceSize = acesize;
2651             pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
2652         }
2653         acecount++;
2654     }
2655 
2656     *cBytes = length;
2657 
2658     if (length > 0xffff)
2659     {
2660         ERR("ACL too large\n");
2661         goto lerr;
2662     }
2663 
2664     if (pAcl)
2665     {
2666         pAcl->AclRevision = ACL_REVISION;
2667         pAcl->Sbz1 = 0;
2668         pAcl->AclSize = length;
2669         pAcl->AceCount = acecount;
2670         pAcl->Sbz2 = 0;
2671     }
2672     return TRUE;
2673 
2674 lerr:
2675     SetLastError(error);
2676     WARN("Invalid ACE string format\n");
2677     return FALSE;
2678 }
2679 
2680 /******************************************************************************
2681  * ParseStringSecurityDescriptorToSecurityDescriptor
2682  */
2683 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
2684     LPCWSTR StringSecurityDescriptor,
2685     SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
2686     LPDWORD cBytes)
2687 {
2688     BOOL bret = FALSE;
2689     WCHAR toktype;
2690     WCHAR *tok;
2691     LPCWSTR lptoken;
2692     LPBYTE lpNext = NULL;
2693     DWORD len;
2694 
2695     *cBytes = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
2696 
2697     tok = heap_alloc( (lstrlenW(StringSecurityDescriptor) + 1) * sizeof(WCHAR));
2698 
2699     if (SecurityDescriptor)
2700         lpNext = (LPBYTE)(SecurityDescriptor + 1);
2701 
2702     while (*StringSecurityDescriptor == ' ')
2703         StringSecurityDescriptor++;
2704 
2705     while (*StringSecurityDescriptor)
2706     {
2707         toktype = *StringSecurityDescriptor;
2708 
2709 	/* Expect char identifier followed by ':' */
2710 	StringSecurityDescriptor++;
2711         if (*StringSecurityDescriptor != ':')
2712         {
2713             SetLastError(ERROR_INVALID_PARAMETER);
2714             goto lend;
2715         }
2716 	StringSecurityDescriptor++;
2717 
2718 	/* Extract token */
2719 	lptoken = StringSecurityDescriptor;
2720 	while (*lptoken && *lptoken != ':')
2721             lptoken++;
2722 
2723 	if (*lptoken)
2724             lptoken--;
2725 
2726         len = lptoken - StringSecurityDescriptor;
2727         memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
2728         tok[len] = 0;
2729 
2730         switch (toktype)
2731 	{
2732             case 'O':
2733             {
2734                 DWORD bytes;
2735 
2736                 if (!ParseStringSidToSid(tok, lpNext, &bytes))
2737                     goto lend;
2738 
2739                 if (SecurityDescriptor)
2740                 {
2741                     SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
2742                     lpNext += bytes; /* Advance to next token */
2743                 }
2744 
2745 		*cBytes += bytes;
2746 
2747                 break;
2748             }
2749 
2750             case 'G':
2751             {
2752                 DWORD bytes;
2753 
2754                 if (!ParseStringSidToSid(tok, lpNext, &bytes))
2755                     goto lend;
2756 
2757                 if (SecurityDescriptor)
2758                 {
2759                     SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
2760                     lpNext += bytes; /* Advance to next token */
2761                 }
2762 
2763 		*cBytes += bytes;
2764 
2765                 break;
2766             }
2767 
2768             case 'D':
2769 	    {
2770                 DWORD flags;
2771                 DWORD bytes;
2772 
2773                 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
2774                     goto lend;
2775 
2776                 if (SecurityDescriptor)
2777                 {
2778                     SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
2779                     SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
2780                     lpNext += bytes; /* Advance to next token */
2781 		}
2782 
2783 		*cBytes += bytes;
2784 
2785 		break;
2786             }
2787 
2788             case 'S':
2789             {
2790                 DWORD flags;
2791                 DWORD bytes;
2792 
2793                 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
2794                     goto lend;
2795 
2796                 if (SecurityDescriptor)
2797                 {
2798                     SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
2799                     SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
2800                     lpNext += bytes; /* Advance to next token */
2801 		}
2802 
2803 		*cBytes += bytes;
2804 
2805 		break;
2806             }
2807 
2808             default:
2809                 FIXME("Unknown token\n");
2810                 SetLastError(ERROR_INVALID_PARAMETER);
2811 		goto lend;
2812 	}
2813 
2814         StringSecurityDescriptor = lptoken;
2815     }
2816 
2817     bret = TRUE;
2818 
2819 lend:
2820     heap_free(tok);
2821     return bret;
2822 }
2823 
2824 /* Winehq cvs 20050916 */
2825 /******************************************************************************
2826  * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
2827  * @implemented
2828  */
2829 BOOL
2830 WINAPI
2831 ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor,
2832                                                      DWORD StringSDRevision,
2833                                                      PSECURITY_DESCRIPTOR* SecurityDescriptor,
2834                                                      PULONG SecurityDescriptorSize)
2835 {
2836     UINT len;
2837     BOOL ret = FALSE;
2838     LPWSTR StringSecurityDescriptorW;
2839 
2840     len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
2841     StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2842 
2843     if (StringSecurityDescriptorW)
2844     {
2845         MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
2846 
2847         ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
2848                                                                    StringSDRevision, SecurityDescriptor,
2849                                                                    SecurityDescriptorSize);
2850         HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
2851     }
2852 
2853     return ret;
2854 }
2855 
2856 /******************************************************************************
2857  * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
2858  * @implemented
2859  */
2860 BOOL WINAPI
2861 ConvertStringSecurityDescriptorToSecurityDescriptorW(LPCWSTR StringSecurityDescriptor,
2862                                                      DWORD StringSDRevision,
2863                                                      PSECURITY_DESCRIPTOR* SecurityDescriptor,
2864                                                      PULONG SecurityDescriptorSize)
2865 {
2866     DWORD cBytes;
2867     SECURITY_DESCRIPTOR* psd;
2868     BOOL bret = FALSE;
2869 
2870     TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
2871 
2872     if (GetVersion() & 0x80000000)
2873     {
2874         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2875         goto lend;
2876     }
2877     else if (!StringSecurityDescriptor || !SecurityDescriptor)
2878     {
2879         SetLastError(ERROR_INVALID_PARAMETER);
2880         goto lend;
2881     }
2882     else if (StringSDRevision != SID_REVISION)
2883     {
2884         SetLastError(ERROR_UNKNOWN_REVISION);
2885         goto lend;
2886     }
2887 
2888     /* Compute security descriptor length */
2889     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
2890         NULL, &cBytes))
2891         goto lend;
2892 
2893     psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
2894     if (!psd) goto lend;
2895 
2896     psd->Revision = SID_REVISION;
2897     psd->Control |= SE_SELF_RELATIVE;
2898 
2899     if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
2900              (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
2901     {
2902         LocalFree(psd);
2903         goto lend;
2904     }
2905 
2906     if (SecurityDescriptorSize)
2907         *SecurityDescriptorSize = cBytes;
2908 
2909     bret = TRUE;
2910 
2911 lend:
2912     TRACE(" ret=%d\n", bret);
2913     return bret;
2914 }
2915 
2916 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
2917 {
2918     if (cch == -1)
2919         cch = strlenW(string);
2920 
2921     if (plen)
2922         *plen += cch;
2923 
2924     if (pwptr)
2925     {
2926         memcpy(*pwptr, string, sizeof(WCHAR)*cch);
2927         *pwptr += cch;
2928     }
2929 }
2930 
2931 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
2932 {
2933     DWORD i;
2934     WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
2935     WCHAR subauthfmt[] = { '-','%','u',0 };
2936     WCHAR buf[26];
2937     SID *pisid = psid;
2938 
2939     if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
2940     {
2941         SetLastError(ERROR_INVALID_SID);
2942         return FALSE;
2943     }
2944 
2945     if (pisid->IdentifierAuthority.Value[0] ||
2946      pisid->IdentifierAuthority.Value[1])
2947     {
2948         FIXME("not matching MS' bugs\n");
2949         SetLastError(ERROR_INVALID_SID);
2950         return FALSE;
2951     }
2952 
2953     sprintfW( buf, fmt, pisid->Revision,
2954         MAKELONG(
2955             MAKEWORD( pisid->IdentifierAuthority.Value[5],
2956                     pisid->IdentifierAuthority.Value[4] ),
2957             MAKEWORD( pisid->IdentifierAuthority.Value[3],
2958                     pisid->IdentifierAuthority.Value[2] )
2959         ) );
2960     DumpString(buf, -1, pwptr, plen);
2961 
2962     for( i=0; i<pisid->SubAuthorityCount; i++ )
2963     {
2964         sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
2965         DumpString(buf, -1, pwptr, plen);
2966     }
2967     return TRUE;
2968 }
2969 
2970 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
2971 {
2972     size_t i;
2973     for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
2974     {
2975         if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
2976         {
2977             DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
2978             return TRUE;
2979         }
2980     }
2981 
2982     return DumpSidNumeric(psid, pwptr, plen);
2983 }
2984 
2985 static const LPCWSTR AceRightBitNames[32] = {
2986         SDDL_CREATE_CHILD,        /*  0 */
2987         SDDL_DELETE_CHILD,
2988         SDDL_LIST_CHILDREN,
2989         SDDL_SELF_WRITE,
2990         SDDL_READ_PROPERTY,       /*  4 */
2991         SDDL_WRITE_PROPERTY,
2992         SDDL_DELETE_TREE,
2993         SDDL_LIST_OBJECT,
2994         SDDL_CONTROL_ACCESS,      /*  8 */
2995         NULL,
2996         NULL,
2997         NULL,
2998         NULL,                     /* 12 */
2999         NULL,
3000         NULL,
3001         NULL,
3002         SDDL_STANDARD_DELETE,     /* 16 */
3003         SDDL_READ_CONTROL,
3004         SDDL_WRITE_DAC,
3005         SDDL_WRITE_OWNER,
3006         NULL,                     /* 20 */
3007         NULL,
3008         NULL,
3009         NULL,
3010         NULL,                     /* 24 */
3011         NULL,
3012         NULL,
3013         NULL,
3014         SDDL_GENERIC_ALL,         /* 28 */
3015         SDDL_GENERIC_EXECUTE,
3016         SDDL_GENERIC_WRITE,
3017         SDDL_GENERIC_READ
3018 };
3019 
3020 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
3021 {
3022     static const WCHAR fmtW[] = {'0','x','%','x',0};
3023     WCHAR buf[15];
3024     size_t i;
3025 
3026     if (mask == 0)
3027         return;
3028 
3029     /* first check if the right have name */
3030     for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
3031     {
3032         if (AceRights[i].wstr == NULL)
3033             break;
3034         if (mask == AceRights[i].value)
3035         {
3036             DumpString(AceRights[i].wstr, -1, pwptr, plen);
3037             return;
3038         }
3039     }
3040 
3041     /* then check if it can be built from bit names */
3042     for (i = 0; i < 32; i++)
3043     {
3044         if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
3045         {
3046             /* can't be built from bit names */
3047             sprintfW(buf, fmtW, mask);
3048             DumpString(buf, -1, pwptr, plen);
3049             return;
3050         }
3051     }
3052 
3053     /* build from bit names */
3054     for (i = 0; i < 32; i++)
3055         if (mask & (1 << i))
3056             DumpString(AceRightBitNames[i], -1, pwptr, plen);
3057 }
3058 
3059 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
3060 {
3061     ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
3062     static const WCHAR openbr = '(';
3063     static const WCHAR closebr = ')';
3064     static const WCHAR semicolon = ';';
3065 
3066     if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
3067     {
3068         SetLastError(ERROR_INVALID_ACL);
3069         return FALSE;
3070     }
3071 
3072     piace = pace;
3073     DumpString(&openbr, 1, pwptr, plen);
3074     switch (piace->Header.AceType)
3075     {
3076         case ACCESS_ALLOWED_ACE_TYPE:
3077             DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
3078             break;
3079         case ACCESS_DENIED_ACE_TYPE:
3080             DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
3081             break;
3082         case SYSTEM_AUDIT_ACE_TYPE:
3083             DumpString(SDDL_AUDIT, -1, pwptr, plen);
3084             break;
3085         case SYSTEM_ALARM_ACE_TYPE:
3086             DumpString(SDDL_ALARM, -1, pwptr, plen);
3087             break;
3088     }
3089     DumpString(&semicolon, 1, pwptr, plen);
3090 
3091     if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
3092         DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
3093     if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
3094         DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
3095     if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
3096         DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
3097     if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
3098         DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
3099     if (piace->Header.AceFlags & INHERITED_ACE)
3100         DumpString(SDDL_INHERITED, -1, pwptr, plen);
3101     if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
3102         DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
3103     if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
3104         DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
3105     DumpString(&semicolon, 1, pwptr, plen);
3106     DumpRights(piace->Mask, pwptr, plen);
3107     DumpString(&semicolon, 1, pwptr, plen);
3108     /* objects not supported */
3109     DumpString(&semicolon, 1, pwptr, plen);
3110     /* objects not supported */
3111     DumpString(&semicolon, 1, pwptr, plen);
3112     if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
3113         return FALSE;
3114     DumpString(&closebr, 1, pwptr, plen);
3115     return TRUE;
3116 }
3117 
3118 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
3119 {
3120     WORD count;
3121     int i;
3122 
3123     if (protected)
3124         DumpString(SDDL_PROTECTED, -1, pwptr, plen);
3125     if (autoInheritReq)
3126         DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
3127     if (autoInherited)
3128         DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
3129 
3130     if (pacl == NULL)
3131         return TRUE;
3132 
3133     if (!IsValidAcl(pacl))
3134         return FALSE;
3135 
3136     count = pacl->AceCount;
3137     for (i = 0; i < count; i++)
3138     {
3139         LPVOID ace;
3140         if (!GetAce(pacl, i, &ace))
3141             return FALSE;
3142         if (!DumpAce(ace, pwptr, plen))
3143             return FALSE;
3144     }
3145 
3146     return TRUE;
3147 }
3148 
3149 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3150 {
3151     static const WCHAR prefix[] = {'O',':',0};
3152     BOOL bDefaulted;
3153     PSID psid;
3154 
3155     if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
3156         return FALSE;
3157 
3158     if (psid == NULL)
3159         return TRUE;
3160 
3161     DumpString(prefix, -1, pwptr, plen);
3162     if (!DumpSid(psid, pwptr, plen))
3163         return FALSE;
3164     return TRUE;
3165 }
3166 
3167 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3168 {
3169     static const WCHAR prefix[] = {'G',':',0};
3170     BOOL bDefaulted;
3171     PSID psid;
3172 
3173     if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
3174         return FALSE;
3175 
3176     if (psid == NULL)
3177         return TRUE;
3178 
3179     DumpString(prefix, -1, pwptr, plen);
3180     if (!DumpSid(psid, pwptr, plen))
3181         return FALSE;
3182     return TRUE;
3183 }
3184 
3185 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3186 {
3187     static const WCHAR dacl[] = {'D',':',0};
3188     SECURITY_DESCRIPTOR_CONTROL control;
3189     BOOL present, defaulted;
3190     DWORD revision;
3191     PACL pacl;
3192 
3193     if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
3194         return FALSE;
3195 
3196     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
3197         return FALSE;
3198 
3199     if (!present)
3200         return TRUE;
3201 
3202     DumpString(dacl, 2, pwptr, plen);
3203     if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
3204         return FALSE;
3205     return TRUE;
3206 }
3207 
3208 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3209 {
3210     static const WCHAR sacl[] = {'S',':',0};
3211     SECURITY_DESCRIPTOR_CONTROL control;
3212     BOOL present, defaulted;
3213     DWORD revision;
3214     PACL pacl;
3215 
3216     if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
3217         return FALSE;
3218 
3219     if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
3220         return FALSE;
3221 
3222     if (!present)
3223         return TRUE;
3224 
3225     DumpString(sacl, 2, pwptr, plen);
3226     if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
3227         return FALSE;
3228     return TRUE;
3229 }
3230 
3231 /******************************************************************************
3232  * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
3233  */
3234 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
3235 {
3236     ULONG len;
3237     WCHAR *wptr, *wstr;
3238 
3239     if (SDRevision != SDDL_REVISION_1)
3240     {
3241         ERR("Program requested unknown SDDL revision %d\n", SDRevision);
3242         SetLastError(ERROR_UNKNOWN_REVISION);
3243         return FALSE;
3244     }
3245 
3246     len = 0;
3247     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
3248         if (!DumpOwner(SecurityDescriptor, NULL, &len))
3249             return FALSE;
3250     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
3251         if (!DumpGroup(SecurityDescriptor, NULL, &len))
3252             return FALSE;
3253     if (RequestedInformation & DACL_SECURITY_INFORMATION)
3254         if (!DumpDacl(SecurityDescriptor, NULL, &len))
3255             return FALSE;
3256     if (RequestedInformation & SACL_SECURITY_INFORMATION)
3257         if (!DumpSacl(SecurityDescriptor, NULL, &len))
3258             return FALSE;
3259 
3260     wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
3261 #ifdef __REACTOS__
3262     if (wstr == NULL)
3263         return FALSE;
3264 #endif
3265 
3266     if (RequestedInformation & OWNER_SECURITY_INFORMATION)
3267         if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) {
3268             LocalFree (wstr);
3269             return FALSE;
3270         }
3271     if (RequestedInformation & GROUP_SECURITY_INFORMATION)
3272         if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) {
3273             LocalFree (wstr);
3274             return FALSE;
3275         }
3276     if (RequestedInformation & DACL_SECURITY_INFORMATION)
3277         if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) {
3278             LocalFree (wstr);
3279             return FALSE;
3280         }
3281     if (RequestedInformation & SACL_SECURITY_INFORMATION)
3282         if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) {
3283             LocalFree (wstr);
3284             return FALSE;
3285         }
3286     *wptr = 0;
3287 
3288     TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
3289     *OutputString = wstr;
3290     if (OutputLen)
3291         *OutputLen = strlenW(*OutputString)+1;
3292     return TRUE;
3293 }
3294 
3295 /******************************************************************************
3296  * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
3297  */
3298 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
3299 {
3300     LPWSTR wstr;
3301     ULONG len;
3302     if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
3303     {
3304         int lenA;
3305 
3306         lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
3307         *OutputString = heap_alloc(lenA);
3308 #ifdef __REACTOS__
3309         if (*OutputString == NULL)
3310         {
3311             LocalFree(wstr);
3312             *OutputLen = 0;
3313             return FALSE;
3314         }
3315 #endif
3316         WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
3317         LocalFree(wstr);
3318 
3319         if (OutputLen != NULL)
3320             *OutputLen = lenA;
3321         return TRUE;
3322     }
3323     else
3324     {
3325         *OutputString = NULL;
3326         if (OutputLen)
3327             *OutputLen = 0;
3328         return FALSE;
3329     }
3330 }
3331 
3332 /******************************************************************************
3333  * ConvertStringSidToSidW [ADVAPI32.@]
3334  */
3335 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
3336 {
3337     BOOL bret = FALSE;
3338     DWORD cBytes;
3339 
3340     TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
3341     if (GetVersion() & 0x80000000)
3342         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3343     else if (!StringSid || !Sid)
3344         SetLastError(ERROR_INVALID_PARAMETER);
3345     else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
3346     {
3347         PSID pSid = *Sid = LocalAlloc(0, cBytes);
3348 
3349         bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
3350         if (!bret)
3351             LocalFree(*Sid);
3352     }
3353     return bret;
3354 }
3355 
3356 /******************************************************************************
3357  * ConvertStringSidToSidA [ADVAPI32.@]
3358  */
3359 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
3360 {
3361     BOOL bret = FALSE;
3362 
3363     TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
3364     if (GetVersion() & 0x80000000)
3365         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3366     else if (!StringSid || !Sid)
3367         SetLastError(ERROR_INVALID_PARAMETER);
3368     else
3369     {
3370         WCHAR *wStringSid = SERV_dup(StringSid);
3371         bret = ConvertStringSidToSidW(wStringSid, Sid);
3372         heap_free(wStringSid);
3373     }
3374     return bret;
3375 }
3376 
3377 /*
3378  * @implemented
3379  */
3380 BOOL
3381 WINAPI
3382 ConvertSidToStringSidW(PSID Sid,
3383                        LPWSTR *StringSid)
3384 {
3385     NTSTATUS Status;
3386     UNICODE_STRING UnicodeString;
3387     WCHAR FixedBuffer[64];
3388 
3389     if (!RtlValidSid(Sid))
3390     {
3391         SetLastError(ERROR_INVALID_SID);
3392         return FALSE;
3393     }
3394 
3395     UnicodeString.Length = 0;
3396     UnicodeString.MaximumLength = sizeof(FixedBuffer);
3397     UnicodeString.Buffer = FixedBuffer;
3398     Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
3399     if (STATUS_BUFFER_TOO_SMALL == Status)
3400     {
3401         Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
3402     }
3403 
3404     if (!NT_SUCCESS(Status))
3405     {
3406         SetLastError(RtlNtStatusToDosError(Status));
3407         return FALSE;
3408     }
3409 
3410     *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
3411     if (NULL == *StringSid)
3412     {
3413         if (UnicodeString.Buffer != FixedBuffer)
3414         {
3415             RtlFreeUnicodeString(&UnicodeString);
3416         }
3417       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3418       return FALSE;
3419     }
3420 
3421     MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
3422     ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
3423     if (UnicodeString.Buffer != FixedBuffer)
3424     {
3425         RtlFreeUnicodeString(&UnicodeString);
3426     }
3427 
3428     return TRUE;
3429 }
3430 
3431 /*
3432  * @implemented
3433  */
3434 BOOL
3435 WINAPI
3436 ConvertSidToStringSidA(PSID Sid,
3437                        LPSTR *StringSid)
3438 {
3439     LPWSTR StringSidW;
3440     int Len;
3441 
3442     if (!ConvertSidToStringSidW(Sid, &StringSidW))
3443     {
3444         return FALSE;
3445     }
3446 
3447     Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
3448     if (Len <= 0)
3449     {
3450         LocalFree(StringSidW);
3451         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3452         return FALSE;
3453     }
3454 
3455     *StringSid = LocalAlloc(LMEM_FIXED, Len);
3456     if (NULL == *StringSid)
3457     {
3458         LocalFree(StringSidW);
3459         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3460         return FALSE;
3461     }
3462 
3463     if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
3464     {
3465         LocalFree(StringSid);
3466         LocalFree(StringSidW);
3467         return FALSE;
3468     }
3469 
3470     LocalFree(StringSidW);
3471 
3472     return TRUE;
3473 }
3474 
3475 /*
3476  * @unimplemented
3477  */
3478 BOOL
3479 WINAPI
3480 CreateProcessWithLogonW(
3481     _In_ LPCWSTR lpUsername,
3482     _In_opt_ LPCWSTR lpDomain,
3483     _In_ LPCWSTR lpPassword,
3484     _In_ DWORD dwLogonFlags,
3485     _In_opt_ LPCWSTR lpApplicationName,
3486     _Inout_opt_ LPWSTR lpCommandLine,
3487     _In_ DWORD dwCreationFlags,
3488     _In_opt_ LPVOID lpEnvironment,
3489     _In_opt_ LPCWSTR lpCurrentDirectory,
3490     _In_ LPSTARTUPINFOW lpStartupInfo,
3491     _Out_ LPPROCESS_INFORMATION lpProcessInformation)
3492 {
3493     LPWSTR pszStringBinding = NULL;
3494     handle_t hBinding = NULL;
3495     SECL_REQUEST Request;
3496     SECL_RESPONSE Response;
3497     RPC_STATUS Status;
3498 
3499     TRACE("CreateProcessWithLogonW(%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p)\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
3500     debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
3501     debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
3502     lpStartupInfo, lpProcessInformation);
3503 
3504     Status = RpcStringBindingComposeW(NULL,
3505                                       L"ncacn_np",
3506                                       NULL,
3507                                       L"\\pipe\\seclogon",
3508                                       NULL,
3509                                       &pszStringBinding);
3510     if (Status != RPC_S_OK)
3511     {
3512         WARN("RpcStringBindingCompose returned 0x%x\n", Status);
3513         SetLastError(Status);
3514         return FALSE;
3515     }
3516 
3517     /* Set the binding handle that will be used to bind to the server. */
3518     Status = RpcBindingFromStringBindingW(pszStringBinding,
3519                                           &hBinding);
3520     if (Status != RPC_S_OK)
3521     {
3522         WARN("RpcBindingFromStringBinding returned 0x%x\n", Status);
3523     }
3524 
3525     Status = RpcStringFreeW(&pszStringBinding);
3526     if (Status != RPC_S_OK)
3527     {
3528         WARN("RpcStringFree returned 0x%x\n", Status);
3529     }
3530 
3531     Request.Username = (LPWSTR)lpUsername;
3532     Request.Domain = (LPWSTR)lpDomain;
3533     Request.Password = (LPWSTR)lpPassword;
3534     Request.ApplicationName = (LPWSTR)lpApplicationName;
3535     Request.CommandLine = (LPWSTR)lpCommandLine;
3536     Request.CurrentDirectory = (LPWSTR)lpCurrentDirectory;
3537 
3538     Request.dwLogonFlags = dwLogonFlags;
3539     Request.dwCreationFlags = dwCreationFlags;
3540 
3541     Request.dwProcessId = GetCurrentProcessId();
3542     TRACE("Request.dwProcessId %lu\n", Request.dwProcessId);
3543 
3544     Response.hProcess = 0;
3545     Response.hThread = 0;
3546     Response.dwProcessId = 0;
3547     Response.dwThreadId = 0;
3548     Response.dwError = ERROR_SUCCESS;
3549 
3550     RpcTryExcept
3551     {
3552         SeclCreateProcessWithLogonW(hBinding, &Request, &Response);
3553     }
3554     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
3555     {
3556         WARN("Exception: %lx\n", RpcExceptionCode());
3557     }
3558     RpcEndExcept;
3559 
3560     if (hBinding)
3561     {
3562         Status = RpcBindingFree(&hBinding);
3563         if (Status != RPC_S_OK)
3564         {
3565             WARN("RpcBindingFree returned 0x%x\n", Status);
3566         }
3567 
3568         hBinding = NULL;
3569     }
3570 
3571     TRACE("Response.hProcess %p\n", Response.hProcess);
3572     TRACE("Response.hThread %p\n", Response.hThread);
3573     TRACE("Response.dwProcessId %lu\n", Response.dwProcessId);
3574     TRACE("Response.dwThreadId %lu\n", Response.dwThreadId);
3575     TRACE("Response.dwError %lu\n", Response.dwError);
3576     if (Response.dwError != ERROR_SUCCESS)
3577         SetLastError(Response.dwError);
3578 
3579     TRACE("CreateProcessWithLogonW() done\n");
3580 
3581     return (Response.dwError == ERROR_SUCCESS);
3582 }
3583 
3584 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
3585         DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
3586         PROCESS_INFORMATION *process_information )
3587 {
3588     FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
3589           logon_flags, debugstr_w(application_name), debugstr_w(command_line),
3590           creation_flags, environment, debugstr_w(current_directory),
3591           startup_info, process_information);
3592 
3593     /* FIXME: check if handles should be inherited */
3594     return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
3595                            current_directory, startup_info, process_information );
3596 }
3597 
3598 /*
3599  * @implemented
3600  */
3601 BOOL WINAPI
3602 DuplicateTokenEx(IN HANDLE ExistingTokenHandle,
3603                  IN DWORD dwDesiredAccess,
3604                  IN LPSECURITY_ATTRIBUTES lpTokenAttributes  OPTIONAL,
3605                  IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
3606                  IN TOKEN_TYPE TokenType,
3607                  OUT PHANDLE DuplicateTokenHandle)
3608 {
3609     OBJECT_ATTRIBUTES ObjectAttributes;
3610     NTSTATUS Status;
3611     SECURITY_QUALITY_OF_SERVICE Sqos;
3612 
3613     TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
3614         ImpersonationLevel, TokenType, DuplicateTokenHandle);
3615 
3616     Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
3617     Sqos.ImpersonationLevel = ImpersonationLevel;
3618     Sqos.ContextTrackingMode = 0;
3619     Sqos.EffectiveOnly = FALSE;
3620 
3621     if (lpTokenAttributes != NULL)
3622     {
3623         InitializeObjectAttributes(&ObjectAttributes,
3624                                    NULL,
3625                                    lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
3626                                    NULL,
3627                                    lpTokenAttributes->lpSecurityDescriptor);
3628     }
3629     else
3630     {
3631         InitializeObjectAttributes(&ObjectAttributes,
3632                                    NULL,
3633                                    0,
3634                                    NULL,
3635                                    NULL);
3636     }
3637 
3638     ObjectAttributes.SecurityQualityOfService = &Sqos;
3639 
3640     Status = NtDuplicateToken(ExistingTokenHandle,
3641                               dwDesiredAccess,
3642                               &ObjectAttributes,
3643                               FALSE,
3644                               TokenType,
3645                               DuplicateTokenHandle);
3646     if (!NT_SUCCESS(Status))
3647     {
3648         ERR("NtDuplicateToken failed: Status %08x\n", Status);
3649         SetLastError(RtlNtStatusToDosError(Status));
3650         return FALSE;
3651     }
3652 
3653     TRACE("Returning token %p.\n", *DuplicateTokenHandle);
3654 
3655     return TRUE;
3656 }
3657 
3658 /*
3659  * @implemented
3660  */
3661 BOOL WINAPI
3662 DuplicateToken(IN HANDLE ExistingTokenHandle,
3663                IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
3664                OUT PHANDLE DuplicateTokenHandle)
3665 {
3666     return DuplicateTokenEx(ExistingTokenHandle,
3667                             TOKEN_IMPERSONATE | TOKEN_QUERY,
3668                             NULL,
3669                             ImpersonationLevel,
3670                             TokenImpersonation,
3671                             DuplicateTokenHandle);
3672 }
3673 
3674 /******************************************************************************
3675  * ComputeStringSidSize
3676  */
3677 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
3678 {
3679     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
3680     {
3681         int ctok = 0;
3682         while (*StringSid)
3683         {
3684             if (*StringSid == '-')
3685                 ctok++;
3686             StringSid++;
3687         }
3688 
3689         if (ctok >= 3)
3690             return GetSidLengthRequired(ctok - 2);
3691     }
3692     else /* String constant format  - Only available in winxp and above */
3693     {
3694         unsigned int i;
3695 
3696         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
3697             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
3698                 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
3699 
3700         for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
3701             if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
3702             {
3703                 MAX_SID local;
3704                 ADVAPI_GetComputerSid(&local);
3705                 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
3706             }
3707 
3708     }
3709 
3710     return GetSidLengthRequired(0);
3711 }
3712 
3713 /******************************************************************************
3714  * ParseStringSidToSid
3715  */
3716 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
3717 {
3718     BOOL bret = FALSE;
3719     SID* pisid=pSid;
3720 
3721     TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
3722     if (!StringSid)
3723     {
3724         SetLastError(ERROR_INVALID_PARAMETER);
3725         TRACE("StringSid is NULL, returning FALSE\n");
3726         return FALSE;
3727     }
3728 
3729     while (*StringSid == ' ')
3730         StringSid++;
3731 
3732     if (!*StringSid)
3733         goto lend; /* ERROR_INVALID_SID */
3734 
3735     *cBytes = ComputeStringSidSize(StringSid);
3736     if (!pisid) /* Simply compute the size */
3737     {
3738         TRACE("only size requested, returning TRUE with %d\n", *cBytes);
3739         return TRUE;
3740     }
3741 
3742     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
3743     {
3744         DWORD i = 0, identAuth;
3745         DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
3746 
3747         StringSid += 2; /* Advance to Revision */
3748         pisid->Revision = atoiW(StringSid);
3749 
3750         if (pisid->Revision != SDDL_REVISION)
3751         {
3752             TRACE("Revision %d is unknown\n", pisid->Revision);
3753             goto lend; /* ERROR_INVALID_SID */
3754         }
3755         if (csubauth == 0)
3756         {
3757             TRACE("SubAuthorityCount is 0\n");
3758             goto lend; /* ERROR_INVALID_SID */
3759         }
3760 
3761         pisid->SubAuthorityCount = csubauth;
3762 
3763         /* Advance to identifier authority */
3764         while (*StringSid && *StringSid != '-')
3765             StringSid++;
3766         if (*StringSid == '-')
3767             StringSid++;
3768 
3769         /* MS' implementation can't handle values greater than 2^32 - 1, so
3770          * we don't either; assume most significant bytes are always 0
3771          */
3772         pisid->IdentifierAuthority.Value[0] = 0;
3773         pisid->IdentifierAuthority.Value[1] = 0;
3774         identAuth = atoiW(StringSid);
3775         pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
3776         pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
3777         pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
3778         pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
3779 
3780         /* Advance to first sub authority */
3781         while (*StringSid && *StringSid != '-')
3782             StringSid++;
3783         if (*StringSid == '-')
3784             StringSid++;
3785 
3786         while (*StringSid)
3787         {
3788             pisid->SubAuthority[i++] = atoiW(StringSid);
3789 
3790             while (*StringSid && *StringSid != '-')
3791                 StringSid++;
3792             if (*StringSid == '-')
3793                 StringSid++;
3794         }
3795 
3796         if (i != pisid->SubAuthorityCount)
3797             goto lend; /* ERROR_INVALID_SID */
3798 
3799         bret = TRUE;
3800     }
3801     else /* String constant format  - Only available in winxp and above */
3802     {
3803         unsigned int i;
3804         pisid->Revision = SDDL_REVISION;
3805 
3806         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
3807             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
3808             {
3809                 DWORD j;
3810                 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
3811                 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
3812                 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
3813                     pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
3814                 bret = TRUE;
3815             }
3816 
3817         for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
3818             if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
3819             {
3820                 ADVAPI_GetComputerSid(pisid);
3821                 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
3822                 pisid->SubAuthorityCount++;
3823                 bret = TRUE;
3824             }
3825 
3826         if (!bret)
3827             FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
3828     }
3829 
3830 lend:
3831     if (!bret)
3832         SetLastError(ERROR_INVALID_SID);
3833 
3834     TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
3835     return bret;
3836 }
3837 
3838 /**********************************************************************
3839  * GetNamedSecurityInfoA			EXPORTED
3840  *
3841  * @implemented
3842  */
3843 DWORD
3844 WINAPI
3845 GetNamedSecurityInfoA(LPSTR pObjectName,
3846                       SE_OBJECT_TYPE ObjectType,
3847                       SECURITY_INFORMATION SecurityInfo,
3848                       PSID *ppsidOwner,
3849                       PSID *ppsidGroup,
3850                       PACL *ppDacl,
3851                       PACL *ppSacl,
3852                       PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
3853 {
3854     DWORD len;
3855     LPWSTR wstr = NULL;
3856     DWORD r;
3857 
3858     TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
3859         ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
3860 
3861     if( pObjectName )
3862     {
3863         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
3864         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
3865         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
3866     }
3867 
3868     r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
3869                            ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
3870 
3871     HeapFree( GetProcessHeap(), 0, wstr );
3872 
3873     return r;
3874 }
3875 
3876 /******************************************************************************
3877  * GetWindowsAccountDomainSid         [ADVAPI32.@]
3878  */
3879 BOOL WINAPI GetWindowsAccountDomainSid( PSID sid, PSID domain_sid, DWORD *size )
3880 {
3881     SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
3882     DWORD required_size;
3883     int i;
3884 
3885     FIXME( "(%p %p %p): semi-stub\n", sid, domain_sid, size );
3886 
3887     if (!sid || !IsValidSid( sid ))
3888     {
3889         SetLastError( ERROR_INVALID_SID );
3890         return FALSE;
3891     }
3892 
3893     if (!size)
3894     {
3895         SetLastError( ERROR_INVALID_PARAMETER );
3896         return FALSE;
3897     }
3898 
3899     if (*GetSidSubAuthorityCount( sid ) < 4)
3900     {
3901         SetLastError( ERROR_INVALID_SID );
3902         return FALSE;
3903     }
3904 
3905     required_size = GetSidLengthRequired( 4 );
3906     if (*size < required_size || !domain_sid)
3907     {
3908         *size = required_size;
3909         SetLastError( domain_sid ? ERROR_INSUFFICIENT_BUFFER :
3910                                    ERROR_INVALID_PARAMETER );
3911         return FALSE;
3912     }
3913 
3914     InitializeSid( domain_sid, &domain_ident, 4 );
3915     for (i = 0; i < 4; i++)
3916         *GetSidSubAuthority( domain_sid, i ) = *GetSidSubAuthority( sid, i );
3917 
3918     *size = required_size;
3919     return TRUE;
3920 }
3921 
3922 /*
3923  * @unimplemented
3924  */
3925 BOOL
3926 WINAPI
3927 EqualDomainSid(IN PSID pSid1,
3928                IN PSID pSid2,
3929                OUT BOOL* pfEqual)
3930 {
3931     UNIMPLEMENTED;
3932     return FALSE;
3933 }
3934 
3935 /* EOF */
3936