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