xref: /reactos/dll/win32/advapi32/wine/security.c (revision 2196a06f)
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 WINAPI
3479 CreateProcessWithLogonW(LPCWSTR lpUsername,
3480                         LPCWSTR lpDomain,
3481                         LPCWSTR lpPassword,
3482                         DWORD dwLogonFlags,
3483                         LPCWSTR lpApplicationName,
3484                         LPWSTR lpCommandLine,
3485                         DWORD dwCreationFlags,
3486                         LPVOID lpEnvironment,
3487                         LPCWSTR lpCurrentDirectory,
3488                         LPSTARTUPINFOW lpStartupInfo,
3489                         LPPROCESS_INFORMATION lpProcessInformation)
3490 {
3491     FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
3492     debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
3493     debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
3494     lpStartupInfo, lpProcessInformation);
3495 
3496     return FALSE;
3497 }
3498 
3499 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
3500         DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
3501         PROCESS_INFORMATION *process_information )
3502 {
3503     FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
3504           logon_flags, debugstr_w(application_name), debugstr_w(command_line),
3505           creation_flags, environment, debugstr_w(current_directory),
3506           startup_info, process_information);
3507 
3508     /* FIXME: check if handles should be inherited */
3509     return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
3510                            current_directory, startup_info, process_information );
3511 }
3512 
3513 /*
3514  * @implemented
3515  */
3516 BOOL WINAPI
3517 DuplicateTokenEx(IN HANDLE ExistingTokenHandle,
3518                  IN DWORD dwDesiredAccess,
3519                  IN LPSECURITY_ATTRIBUTES lpTokenAttributes  OPTIONAL,
3520                  IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
3521                  IN TOKEN_TYPE TokenType,
3522                  OUT PHANDLE DuplicateTokenHandle)
3523 {
3524     OBJECT_ATTRIBUTES ObjectAttributes;
3525     NTSTATUS Status;
3526     SECURITY_QUALITY_OF_SERVICE Sqos;
3527 
3528     TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
3529         ImpersonationLevel, TokenType, DuplicateTokenHandle);
3530 
3531     Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
3532     Sqos.ImpersonationLevel = ImpersonationLevel;
3533     Sqos.ContextTrackingMode = 0;
3534     Sqos.EffectiveOnly = FALSE;
3535 
3536     if (lpTokenAttributes != NULL)
3537     {
3538         InitializeObjectAttributes(&ObjectAttributes,
3539                                    NULL,
3540                                    lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
3541                                    NULL,
3542                                    lpTokenAttributes->lpSecurityDescriptor);
3543     }
3544     else
3545     {
3546         InitializeObjectAttributes(&ObjectAttributes,
3547                                    NULL,
3548                                    0,
3549                                    NULL,
3550                                    NULL);
3551     }
3552 
3553     ObjectAttributes.SecurityQualityOfService = &Sqos;
3554 
3555     Status = NtDuplicateToken(ExistingTokenHandle,
3556                               dwDesiredAccess,
3557                               &ObjectAttributes,
3558                               FALSE,
3559                               TokenType,
3560                               DuplicateTokenHandle);
3561     if (!NT_SUCCESS(Status))
3562     {
3563         ERR("NtDuplicateToken failed: Status %08x\n", Status);
3564         SetLastError(RtlNtStatusToDosError(Status));
3565         return FALSE;
3566     }
3567 
3568     TRACE("Returning token %p.\n", *DuplicateTokenHandle);
3569 
3570     return TRUE;
3571 }
3572 
3573 /*
3574  * @implemented
3575  */
3576 BOOL WINAPI
3577 DuplicateToken(IN HANDLE ExistingTokenHandle,
3578                IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
3579                OUT PHANDLE DuplicateTokenHandle)
3580 {
3581     return DuplicateTokenEx(ExistingTokenHandle,
3582                             TOKEN_IMPERSONATE | TOKEN_QUERY,
3583                             NULL,
3584                             ImpersonationLevel,
3585                             TokenImpersonation,
3586                             DuplicateTokenHandle);
3587 }
3588 
3589 /******************************************************************************
3590  * ComputeStringSidSize
3591  */
3592 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
3593 {
3594     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
3595     {
3596         int ctok = 0;
3597         while (*StringSid)
3598         {
3599             if (*StringSid == '-')
3600                 ctok++;
3601             StringSid++;
3602         }
3603 
3604         if (ctok >= 3)
3605             return GetSidLengthRequired(ctok - 2);
3606     }
3607     else /* String constant format  - Only available in winxp and above */
3608     {
3609         unsigned int i;
3610 
3611         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
3612             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
3613                 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
3614 
3615         for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
3616             if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
3617             {
3618                 MAX_SID local;
3619                 ADVAPI_GetComputerSid(&local);
3620                 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
3621             }
3622 
3623     }
3624 
3625     return GetSidLengthRequired(0);
3626 }
3627 
3628 /******************************************************************************
3629  * ParseStringSidToSid
3630  */
3631 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
3632 {
3633     BOOL bret = FALSE;
3634     SID* pisid=pSid;
3635 
3636     TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
3637     if (!StringSid)
3638     {
3639         SetLastError(ERROR_INVALID_PARAMETER);
3640         TRACE("StringSid is NULL, returning FALSE\n");
3641         return FALSE;
3642     }
3643 
3644     while (*StringSid == ' ')
3645         StringSid++;
3646 
3647     if (!*StringSid)
3648         goto lend; /* ERROR_INVALID_SID */
3649 
3650     *cBytes = ComputeStringSidSize(StringSid);
3651     if (!pisid) /* Simply compute the size */
3652     {
3653         TRACE("only size requested, returning TRUE with %d\n", *cBytes);
3654         return TRUE;
3655     }
3656 
3657     if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
3658     {
3659         DWORD i = 0, identAuth;
3660         DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
3661 
3662         StringSid += 2; /* Advance to Revision */
3663         pisid->Revision = atoiW(StringSid);
3664 
3665         if (pisid->Revision != SDDL_REVISION)
3666         {
3667             TRACE("Revision %d is unknown\n", pisid->Revision);
3668             goto lend; /* ERROR_INVALID_SID */
3669         }
3670         if (csubauth == 0)
3671         {
3672             TRACE("SubAuthorityCount is 0\n");
3673             goto lend; /* ERROR_INVALID_SID */
3674         }
3675 
3676         pisid->SubAuthorityCount = csubauth;
3677 
3678         /* Advance to identifier authority */
3679         while (*StringSid && *StringSid != '-')
3680             StringSid++;
3681         if (*StringSid == '-')
3682             StringSid++;
3683 
3684         /* MS' implementation can't handle values greater than 2^32 - 1, so
3685          * we don't either; assume most significant bytes are always 0
3686          */
3687         pisid->IdentifierAuthority.Value[0] = 0;
3688         pisid->IdentifierAuthority.Value[1] = 0;
3689         identAuth = atoiW(StringSid);
3690         pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
3691         pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
3692         pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
3693         pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
3694 
3695         /* Advance to first sub authority */
3696         while (*StringSid && *StringSid != '-')
3697             StringSid++;
3698         if (*StringSid == '-')
3699             StringSid++;
3700 
3701         while (*StringSid)
3702         {
3703             pisid->SubAuthority[i++] = atoiW(StringSid);
3704 
3705             while (*StringSid && *StringSid != '-')
3706                 StringSid++;
3707             if (*StringSid == '-')
3708                 StringSid++;
3709         }
3710 
3711         if (i != pisid->SubAuthorityCount)
3712             goto lend; /* ERROR_INVALID_SID */
3713 
3714         bret = TRUE;
3715     }
3716     else /* String constant format  - Only available in winxp and above */
3717     {
3718         unsigned int i;
3719         pisid->Revision = SDDL_REVISION;
3720 
3721         for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
3722             if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
3723             {
3724                 DWORD j;
3725                 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
3726                 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
3727                 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
3728                     pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
3729                 bret = TRUE;
3730             }
3731 
3732         for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
3733             if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
3734             {
3735                 ADVAPI_GetComputerSid(pisid);
3736                 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
3737                 pisid->SubAuthorityCount++;
3738                 bret = TRUE;
3739             }
3740 
3741         if (!bret)
3742             FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
3743     }
3744 
3745 lend:
3746     if (!bret)
3747         SetLastError(ERROR_INVALID_SID);
3748 
3749     TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
3750     return bret;
3751 }
3752 
3753 /**********************************************************************
3754  * GetNamedSecurityInfoA			EXPORTED
3755  *
3756  * @implemented
3757  */
3758 DWORD
3759 WINAPI
3760 GetNamedSecurityInfoA(LPSTR pObjectName,
3761                       SE_OBJECT_TYPE ObjectType,
3762                       SECURITY_INFORMATION SecurityInfo,
3763                       PSID *ppsidOwner,
3764                       PSID *ppsidGroup,
3765                       PACL *ppDacl,
3766                       PACL *ppSacl,
3767                       PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
3768 {
3769     DWORD len;
3770     LPWSTR wstr = NULL;
3771     DWORD r;
3772 
3773     TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
3774         ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
3775 
3776     if( pObjectName )
3777     {
3778         len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
3779         wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
3780         MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
3781     }
3782 
3783     r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
3784                            ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
3785 
3786     HeapFree( GetProcessHeap(), 0, wstr );
3787 
3788     return r;
3789 }
3790 
3791 /******************************************************************************
3792  * GetWindowsAccountDomainSid         [ADVAPI32.@]
3793  */
3794 BOOL WINAPI GetWindowsAccountDomainSid( PSID sid, PSID domain_sid, DWORD *size )
3795 {
3796     SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY };
3797     DWORD required_size;
3798     int i;
3799 
3800     FIXME( "(%p %p %p): semi-stub\n", sid, domain_sid, size );
3801 
3802     if (!sid || !IsValidSid( sid ))
3803     {
3804         SetLastError( ERROR_INVALID_SID );
3805         return FALSE;
3806     }
3807 
3808     if (!size)
3809     {
3810         SetLastError( ERROR_INVALID_PARAMETER );
3811         return FALSE;
3812     }
3813 
3814     if (*GetSidSubAuthorityCount( sid ) < 4)
3815     {
3816         SetLastError( ERROR_INVALID_SID );
3817         return FALSE;
3818     }
3819 
3820     required_size = GetSidLengthRequired( 4 );
3821     if (*size < required_size || !domain_sid)
3822     {
3823         *size = required_size;
3824         SetLastError( domain_sid ? ERROR_INSUFFICIENT_BUFFER :
3825                                    ERROR_INVALID_PARAMETER );
3826         return FALSE;
3827     }
3828 
3829     InitializeSid( domain_sid, &domain_ident, 4 );
3830     for (i = 0; i < 4; i++)
3831         *GetSidSubAuthority( domain_sid, i ) = *GetSidSubAuthority( sid, i );
3832 
3833     *size = required_size;
3834     return TRUE;
3835 }
3836 
3837 /*
3838  * @unimplemented
3839  */
3840 BOOL
3841 WINAPI
3842 EqualDomainSid(IN PSID pSid1,
3843                IN PSID pSid2,
3844                OUT BOOL* pfEqual)
3845 {
3846     UNIMPLEMENTED;
3847     return FALSE;
3848 }
3849 
3850 /* EOF */
3851