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