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