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