7148647e42567645262341ca721fafe1ae53e498
[reactos.git] / reactos / dll / win32 / advapi32 / sec / sid.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/sec/sid.c
11 * PURPOSE: Security ID functions
12 */
13
14 #include <advapi32.h>
15 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
16
17 #define MAX_GUID_STRING_LEN 39
18
19 BOOL WINAPI
20 AddAuditAccessAceEx(PACL pAcl,
21 DWORD dwAceRevision,
22 DWORD AceFlags,
23 DWORD dwAccessMask,
24 PSID pSid,
25 BOOL bAuditSuccess,
26 BOOL bAuditFailure);
27
28 typedef struct RECORD
29 {
30 LPCWSTR key;
31 DWORD value;
32 } RECORD;
33
34
35 typedef struct _MAX_SID
36 {
37 /* same fields as struct _SID */
38 BYTE Revision;
39 BYTE SubAuthorityCount;
40 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
41 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
42 } MAX_SID;
43
44 typedef struct WELLKNOWNSID
45 {
46 WCHAR wstr[2];
47 WELL_KNOWN_SID_TYPE Type;
48 MAX_SID Sid;
49 } WELLKNOWNSID;
50
51 typedef struct _ACEFLAG
52 {
53 LPCWSTR wstr;
54 DWORD value;
55 } ACEFLAG, *LPACEFLAG;
56
57 static const WELLKNOWNSID WellKnownSids[] =
58 {
59 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
60 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } },
61 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } },
62 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } },
63 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } },
64 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } },
65 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } },
66 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } },
67 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } },
68 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } },
69 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } },
70 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } },
71 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } },
72 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } },
73 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } },
74 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } },
75 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } },
76 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } },
77 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } },
78 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } },
79 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } },
80 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } },
81 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } },
82 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } },
83 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } },
84 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } },
85 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } },
86 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } },
87 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } },
88 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } },
89 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } },
90 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } },
91 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } },
92 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } },
93 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } },
94 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } },
95 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } },
96 { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } },
97 { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } },
98 { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } },
99 { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } },
100 { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } },
101 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } },
102 { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } },
103 { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } },
104 { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } },
105 { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } },
106 { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } },
107 { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } },
108 { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } },
109 { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } },
110 { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } },
111 };
112
113 typedef struct WELLKNOWNRID
114 {
115 WELL_KNOWN_SID_TYPE Type;
116 DWORD Rid;
117 } WELLKNOWNRID;
118
119 static const WELLKNOWNRID WellKnownRids[] = {
120 { WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN },
121 { WinAccountGuestSid, DOMAIN_USER_RID_GUEST },
122 { WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT },
123 { WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS },
124 { WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS },
125 { WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS },
126 { WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS },
127 { WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS },
128 { WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS },
129 { WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS },
130 { WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
131 { WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS },
132 { WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
133 };
134
135 static const SID sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
136
137 /*
138 * ACE types
139 */
140 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
141 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
142 static const WCHAR SDDL_OBJECT_ACCESS_ALLOWED[] = {'O','A',0};
143 static const WCHAR SDDL_OBJECT_ACCESS_DENIED[] = {'O','D',0};
144 static const WCHAR SDDL_AUDIT[] = {'A','U',0};
145 static const WCHAR SDDL_ALARM[] = {'A','L',0};
146 static const WCHAR SDDL_OBJECT_AUDIT[] = {'O','U',0};
147 static const WCHAR SDDL_OBJECT_ALARM[] = {'O','L',0};
148
149 /*
150 * SDDL ADS Rights
151 */
152 #define ADS_RIGHT_DS_CREATE_CHILD 0x0001
153 #define ADS_RIGHT_DS_DELETE_CHILD 0x0002
154 #define ADS_RIGHT_ACTRL_DS_LIST 0x0004
155 #define ADS_RIGHT_DS_SELF 0x0008
156 #define ADS_RIGHT_DS_READ_PROP 0x0010
157 #define ADS_RIGHT_DS_WRITE_PROP 0x0020
158 #define ADS_RIGHT_DS_DELETE_TREE 0x0040
159 #define ADS_RIGHT_DS_LIST_OBJECT 0x0080
160 #define ADS_RIGHT_DS_CONTROL_ACCESS 0x0100
161
162 /*
163 * ACE flags
164 */
165 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0};
166 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0};
167 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0};
168 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0};
169 static const WCHAR SDDL_INHERITED[] = {'I','D',0};
170 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0};
171 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0};
172
173 static const char * debugstr_sid(PSID sid)
174 {
175 int auth = 0;
176 SID * psid = (SID *)sid;
177
178 if (psid == NULL)
179 return "(null)";
180
181 auth = psid->IdentifierAuthority.Value[5] +
182 (psid->IdentifierAuthority.Value[4] << 8) +
183 (psid->IdentifierAuthority.Value[3] << 16) +
184 (psid->IdentifierAuthority.Value[2] << 24);
185
186 switch (psid->SubAuthorityCount) {
187 case 0:
188 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
189 case 1:
190 return wine_dbg_sprintf("S-%d-%d-%lu", psid->Revision, auth,
191 psid->SubAuthority[0]);
192 case 2:
193 return wine_dbg_sprintf("S-%d-%d-%lu-%lu", psid->Revision, auth,
194 psid->SubAuthority[0], psid->SubAuthority[1]);
195 case 3:
196 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu", psid->Revision, auth,
197 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
198 case 4:
199 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu", psid->Revision, auth,
200 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
201 psid->SubAuthority[3]);
202 case 5:
203 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
204 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
205 psid->SubAuthority[3], psid->SubAuthority[4]);
206 case 6:
207 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
208 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
209 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
210 case 7:
211 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
212 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
213 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
214 psid->SubAuthority[6]);
215 case 8:
216 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
217 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
218 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
219 psid->SubAuthority[6], psid->SubAuthority[7]);
220 }
221 return "(too-big)";
222 }
223
224 static const ACEFLAG AceRights[] =
225 {
226 { SDDL_GENERIC_ALL, GENERIC_ALL },
227 { SDDL_GENERIC_READ, GENERIC_READ },
228 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
229 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
230
231 { SDDL_READ_CONTROL, READ_CONTROL },
232 { SDDL_STANDARD_DELETE, DELETE },
233 { SDDL_WRITE_DAC, WRITE_DAC },
234 { SDDL_WRITE_OWNER, WRITE_OWNER },
235
236 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
237 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
238 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
239 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
240 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
241 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
242 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
243 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
244 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
245
246 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
247 { SDDL_FILE_READ, FILE_GENERIC_READ },
248 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
249 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
250
251 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
252 { SDDL_KEY_READ, KEY_READ },
253 { SDDL_KEY_WRITE, KEY_WRITE },
254 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
255 { NULL, 0 },
256 };
257
258 static const LPCWSTR AceRightBitNames[32] = {
259 SDDL_CREATE_CHILD, /* 0 */
260 SDDL_DELETE_CHILD,
261 SDDL_LIST_CHILDREN,
262 SDDL_SELF_WRITE,
263 SDDL_READ_PROPERTY, /* 4 */
264 SDDL_WRITE_PROPERTY,
265 SDDL_DELETE_TREE,
266 SDDL_LIST_OBJECT,
267 SDDL_CONTROL_ACCESS, /* 8 */
268 NULL,
269 NULL,
270 NULL,
271 NULL, /* 12 */
272 NULL,
273 NULL,
274 NULL,
275 SDDL_STANDARD_DELETE, /* 16 */
276 SDDL_READ_CONTROL,
277 SDDL_WRITE_DAC,
278 SDDL_WRITE_OWNER,
279 NULL, /* 20 */
280 NULL,
281 NULL,
282 NULL,
283 NULL, /* 24 */
284 NULL,
285 NULL,
286 NULL,
287 SDDL_GENERIC_ALL, /* 28 */
288 SDDL_GENERIC_EXECUTE,
289 SDDL_GENERIC_WRITE,
290 SDDL_GENERIC_READ
291 };
292
293
294 /* set last error code from NT status and get the proper boolean return value */
295 /* used for functions that are a simple wrapper around the corresponding ntdll API */
296 static __inline BOOL set_ntstatus( NTSTATUS status )
297 {
298 if (status) SetLastError( RtlNtStatusToDosError( status ));
299 return !status;
300 }
301
302
303 /* Exported functions */
304
305 /*
306 * @implemented
307 */
308 BOOL WINAPI
309 AllocateLocallyUniqueId(PLUID Luid)
310 {
311 NTSTATUS Status;
312
313 Status = NtAllocateLocallyUniqueId (Luid);
314 if (!NT_SUCCESS (Status))
315 {
316 SetLastError(RtlNtStatusToDosError(Status));
317 return FALSE;
318 }
319
320 return TRUE;
321 }
322
323
324 /*
325 * @implemented
326 */
327 BOOL WINAPI
328 AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
329 BYTE nSubAuthorityCount,
330 DWORD dwSubAuthority0,
331 DWORD dwSubAuthority1,
332 DWORD dwSubAuthority2,
333 DWORD dwSubAuthority3,
334 DWORD dwSubAuthority4,
335 DWORD dwSubAuthority5,
336 DWORD dwSubAuthority6,
337 DWORD dwSubAuthority7,
338 PSID *pSid)
339 {
340 NTSTATUS Status;
341
342 Status = RtlAllocateAndInitializeSid(pIdentifierAuthority,
343 nSubAuthorityCount,
344 dwSubAuthority0,
345 dwSubAuthority1,
346 dwSubAuthority2,
347 dwSubAuthority3,
348 dwSubAuthority4,
349 dwSubAuthority5,
350 dwSubAuthority6,
351 dwSubAuthority7,
352 pSid);
353 if (!NT_SUCCESS(Status))
354 {
355 SetLastError(RtlNtStatusToDosError(Status));
356 return FALSE;
357 }
358
359 return TRUE;
360 }
361
362
363 /*
364 * @implemented
365 */
366 BOOL WINAPI
367 CopySid(DWORD nDestinationSidLength,
368 PSID pDestinationSid,
369 PSID pSourceSid)
370 {
371 NTSTATUS Status;
372
373 Status = RtlCopySid(nDestinationSidLength,
374 pDestinationSid,
375 pSourceSid);
376 if (!NT_SUCCESS (Status))
377 {
378 SetLastError(RtlNtStatusToDosError(Status));
379 return FALSE;
380 }
381
382 return TRUE;
383 }
384
385 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
386 {
387 if (cch == -1)
388 cch = strlenW(string);
389
390 if (plen)
391 *plen += cch;
392
393 if (pwptr)
394 {
395 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
396 *pwptr += cch;
397 }
398 }
399
400 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
401 {
402 DWORD i;
403 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
404 WCHAR subauthfmt[] = { '-','%','u',0 };
405 WCHAR buf[26];
406 SID *pisid = psid;
407
408 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
409 {
410 SetLastError(ERROR_INVALID_SID);
411 return FALSE;
412 }
413
414 if (pisid->IdentifierAuthority.Value[0] ||
415 pisid->IdentifierAuthority.Value[1])
416 {
417 FIXME("not matching MS' bugs\n");
418 SetLastError(ERROR_INVALID_SID);
419 return FALSE;
420 }
421
422 sprintfW( buf, fmt, pisid->Revision,
423 MAKELONG(
424 MAKEWORD( pisid->IdentifierAuthority.Value[5],
425 pisid->IdentifierAuthority.Value[4] ),
426 MAKEWORD( pisid->IdentifierAuthority.Value[3],
427 pisid->IdentifierAuthority.Value[2] )
428 ) );
429 DumpString(buf, -1, pwptr, plen);
430
431 for( i=0; i<pisid->SubAuthorityCount; i++ )
432 {
433 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
434 DumpString(buf, -1, pwptr, plen);
435 }
436 return TRUE;
437 }
438
439 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
440 {
441 size_t i;
442 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
443 {
444 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
445 {
446 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
447 return TRUE;
448 }
449 }
450
451 return DumpSidNumeric(psid, pwptr, plen);
452 }
453
454 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
455 {
456 static const WCHAR fmtW[] = {'0','x','%','x',0};
457 WCHAR buf[15];
458 size_t i;
459
460 if (mask == 0)
461 return;
462
463 /* first check if the right have name */
464 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
465 {
466 if (AceRights[i].wstr == NULL)
467 break;
468 if (mask == AceRights[i].value)
469 {
470 DumpString(AceRights[i].wstr, -1, pwptr, plen);
471 return;
472 }
473 }
474
475 /* then check if it can be built from bit names */
476 for (i = 0; i < 32; i++)
477 {
478 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
479 {
480 /* can't be built from bit names */
481 sprintfW(buf, fmtW, mask);
482 DumpString(buf, -1, pwptr, plen);
483 return;
484 }
485 }
486
487 /* build from bit names */
488 for (i = 0; i < 32; i++)
489 if (mask & (1 << i))
490 DumpString(AceRightBitNames[i], -1, pwptr, plen);
491 }
492
493 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
494 {
495 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
496 static const WCHAR openbr = '(';
497 static const WCHAR closebr = ')';
498 static const WCHAR semicolon = ';';
499
500 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
501 {
502 SetLastError(ERROR_INVALID_ACL);
503 return FALSE;
504 }
505
506 piace = pace;
507 DumpString(&openbr, 1, pwptr, plen);
508 switch (piace->Header.AceType)
509 {
510 case ACCESS_ALLOWED_ACE_TYPE:
511 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
512 break;
513 case ACCESS_DENIED_ACE_TYPE:
514 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
515 break;
516 case SYSTEM_AUDIT_ACE_TYPE:
517 DumpString(SDDL_AUDIT, -1, pwptr, plen);
518 break;
519 case SYSTEM_ALARM_ACE_TYPE:
520 DumpString(SDDL_ALARM, -1, pwptr, plen);
521 break;
522 }
523 DumpString(&semicolon, 1, pwptr, plen);
524
525 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
526 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
527 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
528 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
529 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
530 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
531 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
532 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
533 if (piace->Header.AceFlags & INHERITED_ACE)
534 DumpString(SDDL_INHERITED, -1, pwptr, plen);
535 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
536 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
537 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
538 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
539 DumpString(&semicolon, 1, pwptr, plen);
540 DumpRights(piace->Mask, pwptr, plen);
541 DumpString(&semicolon, 1, pwptr, plen);
542 /* objects not supported */
543 DumpString(&semicolon, 1, pwptr, plen);
544 /* objects not supported */
545 DumpString(&semicolon, 1, pwptr, plen);
546 if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
547 return FALSE;
548 DumpString(&closebr, 1, pwptr, plen);
549 return TRUE;
550 }
551
552 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
553 {
554 WORD count;
555 int i;
556
557 if (protected)
558 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
559 if (autoInheritReq)
560 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
561 if (autoInherited)
562 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
563
564 if (pacl == NULL)
565 return TRUE;
566
567 if (!IsValidAcl(pacl))
568 return FALSE;
569
570 count = pacl->AceCount;
571 for (i = 0; i < count; i++)
572 {
573 LPVOID ace;
574 if (!GetAce(pacl, i, &ace))
575 return FALSE;
576 if (!DumpAce(ace, pwptr, plen))
577 return FALSE;
578 }
579
580 return TRUE;
581 }
582
583 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
584 {
585 static const WCHAR prefix[] = {'O',':',0};
586 BOOL bDefaulted;
587 PSID psid;
588
589 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
590 return FALSE;
591
592 if (psid == NULL)
593 return TRUE;
594
595 DumpString(prefix, -1, pwptr, plen);
596 if (!DumpSid(psid, pwptr, plen))
597 return FALSE;
598 return TRUE;
599 }
600
601 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
602 {
603 static const WCHAR prefix[] = {'G',':',0};
604 BOOL bDefaulted;
605 PSID psid;
606
607 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
608 return FALSE;
609
610 if (psid == NULL)
611 return TRUE;
612
613 DumpString(prefix, -1, pwptr, plen);
614 if (!DumpSid(psid, pwptr, plen))
615 return FALSE;
616 return TRUE;
617 }
618
619 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
620 {
621 static const WCHAR dacl[] = {'D',':',0};
622 SECURITY_DESCRIPTOR_CONTROL control;
623 BOOL present, defaulted;
624 DWORD revision;
625 PACL pacl;
626
627 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
628 return FALSE;
629
630 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
631 return FALSE;
632
633 if (!present)
634 return TRUE;
635
636 DumpString(dacl, 2, pwptr, plen);
637 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
638 return FALSE;
639 return TRUE;
640 }
641
642 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
643 {
644 static const WCHAR sacl[] = {'S',':',0};
645 SECURITY_DESCRIPTOR_CONTROL control;
646 BOOL present, defaulted;
647 DWORD revision;
648 PACL pacl;
649
650 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
651 return FALSE;
652
653 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
654 return FALSE;
655
656 if (!present)
657 return TRUE;
658
659 DumpString(sacl, 2, pwptr, plen);
660 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
661 return FALSE;
662 return TRUE;
663 }
664
665 /******************************************************************************
666 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
667 * @implemented
668 */
669 BOOL WINAPI
670 ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
671 DWORD SDRevision,
672 SECURITY_INFORMATION SecurityInformation,
673 LPWSTR *OutputString,
674 PULONG OutputLen)
675 {
676 ULONG len;
677 WCHAR *wptr, *wstr;
678
679 if (SDRevision != SDDL_REVISION_1)
680 {
681 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
682 SetLastError(ERROR_UNKNOWN_REVISION);
683 return FALSE;
684 }
685
686 len = 0;
687 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
688 if (!DumpOwner(SecurityDescriptor, NULL, &len))
689 return FALSE;
690 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
691 if (!DumpGroup(SecurityDescriptor, NULL, &len))
692 return FALSE;
693 if (SecurityInformation & DACL_SECURITY_INFORMATION)
694 if (!DumpDacl(SecurityDescriptor, NULL, &len))
695 return FALSE;
696 if (SecurityInformation & SACL_SECURITY_INFORMATION)
697 if (!DumpSacl(SecurityDescriptor, NULL, &len))
698 return FALSE;
699
700 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
701 if (wstr == NULL)
702 return FALSE;
703
704 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
705 if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
706 return FALSE;
707 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
708 if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
709 return FALSE;
710 if (SecurityInformation & DACL_SECURITY_INFORMATION)
711 if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
712 return FALSE;
713 if (SecurityInformation & SACL_SECURITY_INFORMATION)
714 if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
715 return FALSE;
716 *wptr = 0;
717
718 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
719 *OutputString = wstr;
720 if (OutputLen)
721 *OutputLen = strlenW(*OutputString)+1;
722 return TRUE;
723 }
724
725
726 /******************************************************************************
727 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
728 * @implemented
729 */
730 BOOL WINAPI
731 ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
732 DWORD SDRevision,
733 SECURITY_INFORMATION Information,
734 LPSTR *OutputString,
735 PULONG OutputLen)
736 {
737 LPWSTR wstr;
738 ULONG len;
739
740 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
741 {
742 int lenA;
743
744 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
745 *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
746 if (*OutputString == NULL)
747 {
748 LocalFree(wstr);
749 *OutputLen = 0;
750 return FALSE;
751 }
752 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
753 LocalFree(wstr);
754
755 if (OutputLen != NULL)
756 *OutputLen = lenA;
757 return TRUE;
758 }
759 else
760 {
761 *OutputString = NULL;
762 if (OutputLen)
763 *OutputLen = 0;
764 return FALSE;
765 }
766 }
767
768
769 /******************************************************************************
770 * ComputeStringSidSize
771 */
772 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
773 {
774 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
775 {
776 int ctok = 0;
777 while (*StringSid)
778 {
779 if (*StringSid == '-')
780 ctok++;
781 StringSid++;
782 }
783
784 if (ctok >= 3)
785 return GetSidLengthRequired(ctok - 2);
786 }
787 else /* String constant format - Only available in winxp and above */
788 {
789 unsigned int i;
790
791 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
792 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
793 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
794 }
795
796 return GetSidLengthRequired(0);
797 }
798
799 /******************************************************************************
800 * ParseStringSidToSid
801 */
802 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
803 {
804 BOOL bret = FALSE;
805 SID* pisid=pSid;
806
807 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
808 if (!StringSid)
809 {
810 SetLastError(ERROR_INVALID_PARAMETER);
811 TRACE("StringSid is NULL, returning FALSE\n");
812 return FALSE;
813 }
814
815 while (*StringSid == ' ')
816 StringSid++;
817
818 *cBytes = ComputeStringSidSize(StringSid);
819 if (!pisid) /* Simply compute the size */
820 {
821 TRACE("only size requested, returning TRUE\n");
822 return TRUE;
823 }
824
825 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
826 {
827 DWORD i = 0, identAuth;
828 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
829
830 StringSid += 2; /* Advance to Revision */
831 pisid->Revision = atoiW(StringSid);
832
833 if (pisid->Revision != SDDL_REVISION)
834 {
835 TRACE("Revision %d is unknown\n", pisid->Revision);
836 goto lend; /* ERROR_INVALID_SID */
837 }
838 if (csubauth == 0)
839 {
840 TRACE("SubAuthorityCount is 0\n");
841 goto lend; /* ERROR_INVALID_SID */
842 }
843
844 pisid->SubAuthorityCount = csubauth;
845
846 /* Advance to identifier authority */
847 while (*StringSid && *StringSid != '-')
848 StringSid++;
849 if (*StringSid == '-')
850 StringSid++;
851
852 /* MS' implementation can't handle values greater than 2^32 - 1, so
853 * we don't either; assume most significant bytes are always 0
854 */
855 pisid->IdentifierAuthority.Value[0] = 0;
856 pisid->IdentifierAuthority.Value[1] = 0;
857 identAuth = atoiW(StringSid);
858 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
859 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
860 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
861 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
862
863 /* Advance to first sub authority */
864 while (*StringSid && *StringSid != '-')
865 StringSid++;
866 if (*StringSid == '-')
867 StringSid++;
868
869 while (*StringSid)
870 {
871 pisid->SubAuthority[i++] = atoiW(StringSid);
872
873 while (*StringSid && *StringSid != '-')
874 StringSid++;
875 if (*StringSid == '-')
876 StringSid++;
877 }
878
879 if (i != pisid->SubAuthorityCount)
880 goto lend; /* ERROR_INVALID_SID */
881
882 bret = TRUE;
883 }
884 else /* String constant format - Only available in winxp and above */
885 {
886 unsigned int i;
887 pisid->Revision = SDDL_REVISION;
888
889 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
890 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
891 {
892 DWORD j;
893 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
894 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
895 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
896 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
897 bret = TRUE;
898 }
899
900 if (!bret)
901 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
902 }
903
904 lend:
905 if (!bret)
906 SetLastError(ERROR_INVALID_SID);
907
908 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
909 return bret;
910 }
911
912 /******************************************************************************
913 * ParseAclStringFlags
914 */
915 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
916 {
917 DWORD flags = 0;
918 LPCWSTR szAcl = *StringAcl;
919
920 while (*szAcl != '(')
921 {
922 if (*szAcl == 'P')
923 {
924 flags |= SE_DACL_PROTECTED;
925 }
926 else if (*szAcl == 'A')
927 {
928 szAcl++;
929 if (*szAcl == 'R')
930 flags |= SE_DACL_AUTO_INHERIT_REQ;
931 else if (*szAcl == 'I')
932 flags |= SE_DACL_AUTO_INHERITED;
933 }
934 szAcl++;
935 }
936
937 *StringAcl = szAcl;
938 return flags;
939 }
940
941 /******************************************************************************
942 * ParseAceStringType
943 */
944 static const ACEFLAG AceType[] =
945 {
946 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
947 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
948 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
949 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
950 /*
951 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
952 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
953 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
954 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
955 */
956 { NULL, 0 },
957 };
958
959 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
960 {
961 UINT len = 0;
962 LPCWSTR szAcl = *StringAcl;
963 const ACEFLAG *lpaf = AceType;
964
965 while (lpaf->wstr &&
966 (len = strlenW(lpaf->wstr)) &&
967 strncmpW(lpaf->wstr, szAcl, len))
968 lpaf++;
969
970 if (!lpaf->wstr)
971 return 0;
972
973 *StringAcl += len;
974 return lpaf->value;
975 }
976
977
978 /******************************************************************************
979 * ParseAceStringFlags
980 */
981 static const ACEFLAG AceFlags[] =
982 {
983 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
984 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
985 { SDDL_INHERITED, INHERITED_ACE },
986 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
987 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
988 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
989 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
990 { NULL, 0 },
991 };
992
993 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
994 {
995 UINT len = 0;
996 BYTE flags = 0;
997 LPCWSTR szAcl = *StringAcl;
998
999 while (*szAcl != ';')
1000 {
1001 const ACEFLAG *lpaf = AceFlags;
1002
1003 while (lpaf->wstr &&
1004 (len = strlenW(lpaf->wstr)) &&
1005 strncmpW(lpaf->wstr, szAcl, len))
1006 lpaf++;
1007
1008 if (!lpaf->wstr)
1009 return 0;
1010
1011 flags |= lpaf->value;
1012 szAcl += len;
1013 }
1014
1015 *StringAcl = szAcl;
1016 return flags;
1017 }
1018
1019
1020 /******************************************************************************
1021 * ParseAceStringRights
1022 */
1023 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
1024 {
1025 UINT len = 0;
1026 DWORD rights = 0;
1027 LPCWSTR szAcl = *StringAcl;
1028
1029 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
1030 {
1031 LPCWSTR p = szAcl;
1032
1033 while (*p && *p != ';')
1034 p++;
1035
1036 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
1037 {
1038 rights = strtoulW(szAcl, NULL, 16);
1039 szAcl = p;
1040 }
1041 else
1042 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
1043 }
1044 else
1045 {
1046 while (*szAcl != ';')
1047 {
1048 const ACEFLAG *lpaf = AceRights;
1049
1050 while (lpaf->wstr &&
1051 (len = strlenW(lpaf->wstr)) &&
1052 strncmpW(lpaf->wstr, szAcl, len))
1053 {
1054 lpaf++;
1055 }
1056
1057 if (!lpaf->wstr)
1058 return 0;
1059
1060 rights |= lpaf->value;
1061 szAcl += len;
1062 }
1063 }
1064
1065 *StringAcl = szAcl;
1066 return rights;
1067 }
1068
1069
1070 /******************************************************************************
1071 * ParseStringAclToAcl
1072 *
1073 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
1074 */
1075 static BOOL
1076 ParseStringAclToAcl(LPCWSTR StringAcl,
1077 LPDWORD lpdwFlags,
1078 PACL pAcl,
1079 LPDWORD cBytes)
1080 {
1081 DWORD val;
1082 DWORD sidlen;
1083 DWORD length = sizeof(ACL);
1084 DWORD acesize = 0;
1085 DWORD acecount = 0;
1086 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
1087
1088 TRACE("%s\n", debugstr_w(StringAcl));
1089
1090 if (!StringAcl)
1091 return FALSE;
1092
1093 if (pAcl) /* pAce is only useful if we're setting values */
1094 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
1095
1096 /* Parse ACL flags */
1097 *lpdwFlags = ParseAclStringFlags(&StringAcl);
1098
1099 /* Parse ACE */
1100 while (*StringAcl == '(')
1101 {
1102 StringAcl++;
1103
1104 /* Parse ACE type */
1105 val = ParseAceStringType(&StringAcl);
1106 if (pAce)
1107 pAce->Header.AceType = (BYTE) val;
1108 if (*StringAcl != ';')
1109 goto lerr;
1110 StringAcl++;
1111
1112 /* Parse ACE flags */
1113 val = ParseAceStringFlags(&StringAcl);
1114 if (pAce)
1115 pAce->Header.AceFlags = (BYTE) val;
1116 if (*StringAcl != ';')
1117 goto lerr;
1118 StringAcl++;
1119
1120 /* Parse ACE rights */
1121 val = ParseAceStringRights(&StringAcl);
1122 if (pAce)
1123 pAce->Mask = val;
1124 if (*StringAcl != ';')
1125 goto lerr;
1126 StringAcl++;
1127
1128 /* Parse ACE object guid */
1129 if (*StringAcl != ';')
1130 {
1131 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1132 goto lerr;
1133 }
1134 StringAcl++;
1135
1136 /* Parse ACE inherit object guid */
1137 if (*StringAcl != ';')
1138 {
1139 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1140 goto lerr;
1141 }
1142 StringAcl++;
1143
1144 /* Parse ACE account sid */
1145 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
1146 {
1147 while (*StringAcl && *StringAcl != ')')
1148 StringAcl++;
1149 }
1150
1151 if (*StringAcl != ')')
1152 goto lerr;
1153 StringAcl++;
1154
1155 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
1156 length += acesize;
1157 if (pAce)
1158 {
1159 pAce->Header.AceSize = acesize;
1160 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
1161 }
1162 acecount++;
1163 }
1164
1165 *cBytes = length;
1166
1167 if (length > 0xffff)
1168 {
1169 ERR("ACL too large\n");
1170 goto lerr;
1171 }
1172
1173 if (pAcl)
1174 {
1175 pAcl->AclRevision = ACL_REVISION;
1176 pAcl->Sbz1 = 0;
1177 pAcl->AclSize = length;
1178 pAcl->AceCount = acecount++;
1179 pAcl->Sbz2 = 0;
1180 }
1181 return TRUE;
1182
1183 lerr:
1184 SetLastError(ERROR_INVALID_ACL);
1185 WARN("Invalid ACE string format\n");
1186 return FALSE;
1187 }
1188
1189
1190 /******************************************************************************
1191 * ParseStringSecurityDescriptorToSecurityDescriptor
1192 */
1193 static BOOL
1194 ParseStringSecurityDescriptorToSecurityDescriptor(LPCWSTR StringSecurityDescriptor,
1195 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
1196 LPDWORD cBytes)
1197 {
1198 BOOL bret = FALSE;
1199 WCHAR toktype;
1200 WCHAR tok[MAX_PATH];
1201 LPCWSTR lptoken;
1202 LPBYTE lpNext = NULL;
1203 DWORD len;
1204
1205 *cBytes = sizeof(SECURITY_DESCRIPTOR);
1206
1207 if (SecurityDescriptor)
1208 lpNext = (LPBYTE)(SecurityDescriptor + 1);
1209
1210 while (*StringSecurityDescriptor)
1211 {
1212 toktype = *StringSecurityDescriptor;
1213
1214 /* Expect char identifier followed by ':' */
1215 StringSecurityDescriptor++;
1216 if (*StringSecurityDescriptor != ':')
1217 {
1218 SetLastError(ERROR_INVALID_PARAMETER);
1219 goto lend;
1220 }
1221 StringSecurityDescriptor++;
1222
1223 /* Extract token */
1224 lptoken = StringSecurityDescriptor;
1225 while (*lptoken && *lptoken != ':')
1226 lptoken++;
1227
1228 if (*lptoken)
1229 lptoken--;
1230
1231 len = lptoken - StringSecurityDescriptor;
1232 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
1233 tok[len] = 0;
1234
1235 switch (toktype)
1236 {
1237 case 'O':
1238 {
1239 DWORD bytes;
1240
1241 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1242 goto lend;
1243
1244 if (SecurityDescriptor)
1245 {
1246 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
1247 lpNext += bytes; /* Advance to next token */
1248 }
1249
1250 *cBytes += bytes;
1251
1252 break;
1253 }
1254
1255 case 'G':
1256 {
1257 DWORD bytes;
1258
1259 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1260 goto lend;
1261
1262 if (SecurityDescriptor)
1263 {
1264 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
1265 lpNext += bytes; /* Advance to next token */
1266 }
1267
1268 *cBytes += bytes;
1269
1270 break;
1271 }
1272
1273 case 'D':
1274 {
1275 DWORD flags;
1276 DWORD bytes;
1277
1278 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1279 goto lend;
1280
1281 if (SecurityDescriptor)
1282 {
1283 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
1284 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
1285 lpNext += bytes; /* Advance to next token */
1286 }
1287
1288 *cBytes += bytes;
1289
1290 break;
1291 }
1292
1293 case 'S':
1294 {
1295 DWORD flags;
1296 DWORD bytes;
1297
1298 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1299 goto lend;
1300
1301 if (SecurityDescriptor)
1302 {
1303 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
1304 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
1305 lpNext += bytes; /* Advance to next token */
1306 }
1307
1308 *cBytes += bytes;
1309
1310 break;
1311 }
1312
1313 default:
1314 FIXME("Unknown token\n");
1315 SetLastError(ERROR_INVALID_PARAMETER);
1316 goto lend;
1317 }
1318
1319 StringSecurityDescriptor = lptoken;
1320 }
1321
1322 bret = TRUE;
1323
1324 lend:
1325 return bret;
1326 }
1327
1328
1329 /******************************************************************************
1330 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
1331 * @implemented
1332 */
1333 BOOL WINAPI
1334 ConvertStringSecurityDescriptorToSecurityDescriptorW(LPCWSTR StringSecurityDescriptor,
1335 DWORD StringSDRevision,
1336 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1337 PULONG SecurityDescriptorSize)
1338 {
1339 DWORD cBytes;
1340 SECURITY_DESCRIPTOR* psd;
1341 BOOL bret = FALSE;
1342
1343 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
1344
1345 if (GetVersion() & 0x80000000)
1346 {
1347 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1348 goto lend;
1349 }
1350 else if (!StringSecurityDescriptor || !SecurityDescriptor)
1351 {
1352 SetLastError(ERROR_INVALID_PARAMETER);
1353 goto lend;
1354 }
1355 else if (StringSDRevision != SID_REVISION)
1356 {
1357 SetLastError(ERROR_UNKNOWN_REVISION);
1358 goto lend;
1359 }
1360
1361 /* Compute security descriptor length */
1362 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1363 NULL, &cBytes))
1364 goto lend;
1365
1366 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
1367 if (!psd) goto lend;
1368
1369 psd->Revision = SID_REVISION;
1370 psd->Control |= SE_SELF_RELATIVE;
1371
1372 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1373 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
1374 {
1375 LocalFree(psd);
1376 goto lend;
1377 }
1378
1379 if (SecurityDescriptorSize)
1380 *SecurityDescriptorSize = cBytes;
1381
1382 bret = TRUE;
1383
1384 lend:
1385 TRACE(" ret=%d\n", bret);
1386 return bret;
1387 }
1388
1389
1390 /* Winehq cvs 20050916 */
1391 /******************************************************************************
1392 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
1393 * @implemented
1394 */
1395 BOOL
1396 WINAPI
1397 ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor,
1398 DWORD StringSDRevision,
1399 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1400 PULONG SecurityDescriptorSize)
1401 {
1402 UINT len;
1403 BOOL ret = FALSE;
1404 LPWSTR StringSecurityDescriptorW;
1405
1406 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
1407 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1408
1409 if (StringSecurityDescriptorW)
1410 {
1411 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
1412
1413 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
1414 StringSDRevision, SecurityDescriptor,
1415 SecurityDescriptorSize);
1416 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
1417 }
1418
1419 return ret;
1420 }
1421
1422 /*
1423 * @implemented
1424 */
1425 BOOL
1426 WINAPI
1427 EqualPrefixSid(PSID pSid1,
1428 PSID pSid2)
1429 {
1430 return RtlEqualPrefixSid (pSid1, pSid2);
1431 }
1432
1433
1434 /*
1435 * @implemented
1436 */
1437 BOOL
1438 WINAPI
1439 EqualSid(PSID pSid1,
1440 PSID pSid2)
1441 {
1442 return RtlEqualSid (pSid1, pSid2);
1443 }
1444
1445
1446 /*
1447 * @implemented
1448 *
1449 * RETURNS
1450 * Docs says this function does NOT return a value
1451 * even thou it's defined to return a PVOID...
1452 */
1453 PVOID
1454 WINAPI
1455 FreeSid(PSID pSid)
1456 {
1457 return RtlFreeSid(pSid);
1458 }
1459
1460
1461 /*
1462 * @implemented
1463 */
1464 DWORD
1465 WINAPI
1466 GetLengthSid(PSID pSid)
1467 {
1468 return (DWORD)RtlLengthSid(pSid);
1469 }
1470
1471
1472 /*
1473 * @implemented
1474 */
1475 PSID_IDENTIFIER_AUTHORITY
1476 WINAPI
1477 GetSidIdentifierAuthority(PSID pSid)
1478 {
1479 return RtlIdentifierAuthoritySid(pSid);
1480 }
1481
1482
1483 /*
1484 * @implemented
1485 */
1486 DWORD
1487 WINAPI
1488 GetSidLengthRequired(UCHAR nSubAuthorityCount)
1489 {
1490 return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
1491 }
1492
1493
1494 /*
1495 * @implemented
1496 */
1497 PDWORD
1498 WINAPI
1499 GetSidSubAuthority(PSID pSid,
1500 DWORD nSubAuthority)
1501 {
1502 SetLastError(ERROR_SUCCESS);
1503 return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority);
1504 }
1505
1506
1507 /*
1508 * @implemented
1509 */
1510 PUCHAR
1511 WINAPI
1512 GetSidSubAuthorityCount(PSID pSid)
1513 {
1514 SetLastError(ERROR_SUCCESS);
1515 return RtlSubAuthorityCountSid(pSid);
1516 }
1517
1518
1519 /*
1520 * @implemented
1521 */
1522 BOOL
1523 WINAPI
1524 InitializeSid(PSID Sid,
1525 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
1526 BYTE nSubAuthorityCount)
1527 {
1528 NTSTATUS Status;
1529
1530 Status = RtlInitializeSid(Sid,
1531 pIdentifierAuthority,
1532 nSubAuthorityCount);
1533 if (!NT_SUCCESS(Status))
1534 {
1535 SetLastError(RtlNtStatusToDosError(Status));
1536 return FALSE;
1537 }
1538
1539 return TRUE;
1540 }
1541
1542
1543 /*
1544 * @implemented
1545 */
1546 BOOL
1547 WINAPI
1548 IsValidSid(PSID pSid)
1549 {
1550 return (BOOL)RtlValidSid(pSid);
1551 }
1552
1553
1554 /*
1555 * @implemented
1556 */
1557 BOOL
1558 WINAPI
1559 ConvertSidToStringSidW(PSID Sid,
1560 LPWSTR *StringSid)
1561 {
1562 NTSTATUS Status;
1563 UNICODE_STRING UnicodeString;
1564 WCHAR FixedBuffer[64];
1565
1566 if (!RtlValidSid(Sid))
1567 {
1568 SetLastError(ERROR_INVALID_SID);
1569 return FALSE;
1570 }
1571
1572 UnicodeString.Length = 0;
1573 UnicodeString.MaximumLength = sizeof(FixedBuffer);
1574 UnicodeString.Buffer = FixedBuffer;
1575 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
1576 if (STATUS_BUFFER_TOO_SMALL == Status)
1577 {
1578 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
1579 }
1580
1581 if (!NT_SUCCESS(Status))
1582 {
1583 SetLastError(RtlNtStatusToDosError(Status));
1584 return FALSE;
1585 }
1586
1587 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
1588 if (NULL == *StringSid)
1589 {
1590 if (UnicodeString.Buffer != FixedBuffer)
1591 {
1592 RtlFreeUnicodeString(&UnicodeString);
1593 }
1594 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1595 return FALSE;
1596 }
1597
1598 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
1599 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
1600 if (UnicodeString.Buffer != FixedBuffer)
1601 {
1602 RtlFreeUnicodeString(&UnicodeString);
1603 }
1604
1605 return TRUE;
1606 }
1607
1608
1609 /*
1610 * @implemented
1611 */
1612 BOOL
1613 WINAPI
1614 ConvertSidToStringSidA(PSID Sid,
1615 LPSTR *StringSid)
1616 {
1617 LPWSTR StringSidW;
1618 int Len;
1619
1620 if (!ConvertSidToStringSidW(Sid, &StringSidW))
1621 {
1622 return FALSE;
1623 }
1624
1625 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
1626 if (Len <= 0)
1627 {
1628 LocalFree(StringSidW);
1629 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1630 return FALSE;
1631 }
1632
1633 *StringSid = LocalAlloc(LMEM_FIXED, Len);
1634 if (NULL == *StringSid)
1635 {
1636 LocalFree(StringSidW);
1637 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1638 return FALSE;
1639 }
1640
1641 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
1642 {
1643 LocalFree(StringSid);
1644 LocalFree(StringSidW);
1645 return FALSE;
1646 }
1647
1648 LocalFree(StringSidW);
1649
1650 return TRUE;
1651 }
1652
1653
1654 /*
1655 * @unimplemented
1656 */
1657 BOOL
1658 WINAPI
1659 EqualDomainSid(IN PSID pSid1,
1660 IN PSID pSid2,
1661 OUT BOOL* pfEqual)
1662 {
1663 UNIMPLEMENTED;
1664 return FALSE;
1665 }
1666
1667
1668 /*
1669 * @unimplemented
1670 */
1671 BOOL
1672 WINAPI
1673 GetWindowsAccountDomainSid(IN PSID pSid,
1674 OUT PSID ppDomainSid,
1675 IN OUT DWORD* cbSid)
1676 {
1677 UNIMPLEMENTED;
1678 return FALSE;
1679 }
1680
1681
1682 /*
1683 * @unimplemented
1684 */
1685 BOOL
1686 WINAPI
1687 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
1688 IN PSID DomainSid OPTIONAL,
1689 OUT PSID pSid,
1690 IN OUT DWORD* cbSid)
1691 {
1692 unsigned int i;
1693 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
1694
1695 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
1696 {
1697 SetLastError(ERROR_INVALID_PARAMETER);
1698 return FALSE;
1699 }
1700
1701 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
1702 if (WellKnownSids[i].Type == WellKnownSidType) {
1703 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
1704
1705 if (*cbSid < length)
1706 {
1707 *cbSid = length;
1708 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1709 return FALSE;
1710 }
1711 if (!pSid)
1712 {
1713 SetLastError(ERROR_INVALID_PARAMETER);
1714 return FALSE;
1715 }
1716 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
1717 *cbSid = length;
1718 return TRUE;
1719 }
1720 }
1721
1722 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
1723 {
1724 SetLastError(ERROR_INVALID_PARAMETER);
1725 return FALSE;
1726 }
1727
1728 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
1729 if (WellKnownRids[i].Type == WellKnownSidType) {
1730 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
1731 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
1732 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
1733
1734 if (*cbSid < output_sid_length)
1735 {
1736 *cbSid = output_sid_length;
1737 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1738 return FALSE;
1739 }
1740 if (!pSid)
1741 {
1742 SetLastError(ERROR_INVALID_PARAMETER);
1743 return FALSE;
1744 }
1745 CopyMemory(pSid, DomainSid, domain_sid_length);
1746 (*GetSidSubAuthorityCount(pSid))++;
1747 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
1748 *cbSid = output_sid_length;
1749 return TRUE;
1750 }
1751
1752 SetLastError(ERROR_INVALID_PARAMETER);
1753 return FALSE;
1754 }
1755
1756
1757 /*
1758 * @unimplemented
1759 */
1760 BOOL
1761 WINAPI
1762 IsWellKnownSid(IN PSID pSid,
1763 IN WELL_KNOWN_SID_TYPE WellKnownSidType)
1764 {
1765 unsigned int i;
1766 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
1767
1768 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
1769 {
1770 if (WellKnownSids[i].Type == WellKnownSidType)
1771 {
1772 if (EqualSid(pSid, (PSID)(&WellKnownSids[i].Sid.Revision)))
1773 return TRUE;
1774 }
1775 }
1776
1777 return FALSE;
1778 }
1779
1780
1781 /*
1782 * @implemented
1783 */
1784 BOOL
1785 WINAPI
1786 ConvertStringSidToSidA(IN LPCSTR StringSid,
1787 OUT PSID* sid)
1788 {
1789 BOOL bRetVal = FALSE;
1790
1791 TRACE("%s, %p\n", debugstr_a(StringSid), sid);
1792 if (GetVersion() & 0x80000000)
1793 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1794 else if (!StringSid || !sid)
1795 SetLastError(ERROR_INVALID_PARAMETER);
1796 else
1797 {
1798 UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
1799 LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1800 if (wStringSid == NULL)
1801 return FALSE;
1802 MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
1803 bRetVal = ConvertStringSidToSidW(wStringSid, sid);
1804 HeapFree(GetProcessHeap(), 0, wStringSid);
1805 }
1806 return bRetVal;
1807 }
1808
1809
1810 static const RECORD SidTable[] =
1811 {
1812 { SDDL_ACCOUNT_OPERATORS, WinBuiltinAccountOperatorsSid },
1813 { SDDL_ALIAS_PREW2KCOMPACC, WinBuiltinPreWindows2000CompatibleAccessSid },
1814 { SDDL_ANONYMOUS, WinAnonymousSid },
1815 { SDDL_AUTHENTICATED_USERS, WinAuthenticatedUserSid },
1816 { SDDL_BUILTIN_ADMINISTRATORS, WinBuiltinAdministratorsSid },
1817 { SDDL_BUILTIN_GUESTS, WinBuiltinGuestsSid },
1818 { SDDL_BACKUP_OPERATORS, WinBuiltinBackupOperatorsSid },
1819 { SDDL_BUILTIN_USERS, WinBuiltinUsersSid },
1820 { SDDL_CERT_SERV_ADMINISTRATORS, WinAccountCertAdminsSid /* FIXME: DOMAIN_GROUP_RID_CERT_ADMINS */ },
1821 { SDDL_CREATOR_GROUP, WinCreatorGroupSid },
1822 { SDDL_CREATOR_OWNER, WinCreatorOwnerSid },
1823 { SDDL_DOMAIN_ADMINISTRATORS, WinAccountDomainAdminsSid /* FIXME: DOMAIN_GROUP_RID_ADMINS */ },
1824 { SDDL_DOMAIN_COMPUTERS, WinAccountComputersSid /* FIXME: DOMAIN_GROUP_RID_COMPUTERS */ },
1825 { SDDL_DOMAIN_DOMAIN_CONTROLLERS, WinAccountControllersSid /* FIXME: DOMAIN_GROUP_RID_CONTROLLERS */ },
1826 { SDDL_DOMAIN_GUESTS, WinAccountDomainGuestsSid /* FIXME: DOMAIN_GROUP_RID_GUESTS */ },
1827 { SDDL_DOMAIN_USERS, WinAccountDomainUsersSid /* FIXME: DOMAIN_GROUP_RID_USERS */ },
1828 { SDDL_ENTERPRISE_ADMINS, WinAccountEnterpriseAdminsSid /* FIXME: DOMAIN_GROUP_RID_ENTERPRISE_ADMINS */ },
1829 { SDDL_ENTERPRISE_DOMAIN_CONTROLLERS, WinLogonIdsSid /* FIXME: SECURITY_SERVER_LOGON_RID */ },
1830 { SDDL_EVERYONE, WinWorldSid },
1831 { SDDL_GROUP_POLICY_ADMINS, WinAccountPolicyAdminsSid /* FIXME: DOMAIN_GROUP_RID_POLICY_ADMINS */ },
1832 { SDDL_INTERACTIVE, WinInteractiveSid },
1833 { SDDL_LOCAL_ADMIN, WinAccountAdministratorSid /* FIXME: DOMAIN_USER_RID_ADMIN */ },
1834 { SDDL_LOCAL_GUEST, WinAccountGuestSid /* FIXME: DOMAIN_USER_RID_GUEST */ },
1835 { SDDL_LOCAL_SERVICE, WinLocalServiceSid },
1836 { SDDL_LOCAL_SYSTEM, WinLocalSystemSid },
1837 { SDDL_NETWORK, WinNetworkSid },
1838 { SDDL_NETWORK_CONFIGURATION_OPS, WinBuiltinNetworkConfigurationOperatorsSid },
1839 { SDDL_NETWORK_SERVICE, WinNetworkServiceSid },
1840 { SDDL_PRINTER_OPERATORS, WinBuiltinPrintOperatorsSid },
1841 { SDDL_PERSONAL_SELF, WinSelfSid },
1842 { SDDL_POWER_USERS, WinBuiltinPowerUsersSid },
1843 { SDDL_RAS_SERVERS, WinAccountRasAndIasServersSid /* FIXME: DOMAIN_ALIAS_RID_RAS_SERVERS */ },
1844 { SDDL_REMOTE_DESKTOP, WinBuiltinRemoteDesktopUsersSid },
1845 { SDDL_REPLICATOR, WinBuiltinReplicatorSid },
1846 { SDDL_RESTRICTED_CODE, WinRestrictedCodeSid },
1847 { SDDL_SCHEMA_ADMINISTRATORS, WinAccountSchemaAdminsSid /* FIXME: DOMAIN_GROUP_RID_SCHEMA_ADMINS */ },
1848 { SDDL_SERVER_OPERATORS, WinBuiltinSystemOperatorsSid },
1849 { SDDL_SERVICE, WinServiceSid },
1850 { NULL, 0 },
1851 };
1852
1853 /*
1854 * @implemented
1855 */
1856 BOOL
1857 WINAPI
1858 ConvertStringSidToSidW(IN LPCWSTR StringSid,
1859 OUT PSID* sid)
1860 {
1861 DWORD size;
1862 DWORD i, cBytes, identAuth, csubauth;
1863 BOOL ret;
1864 SID* pisid;
1865
1866 TRACE("%s %p\n", debugstr_w(StringSid), sid);
1867
1868 if (!StringSid)
1869 {
1870 SetLastError(ERROR_INVALID_SID);
1871 return FALSE;
1872 }
1873
1874 for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
1875 {
1876 if (wcscmp(StringSid, SidTable[i].key) == 0)
1877 {
1878 WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
1879 size = SECURITY_MAX_SID_SIZE;
1880 *sid = LocalAlloc(0, size);
1881 if (!*sid)
1882 {
1883 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1884 return FALSE;
1885 }
1886 ret = CreateWellKnownSid(knownSid,
1887 NULL,
1888 *sid,
1889 &size);
1890 if (!ret)
1891 {
1892 SetLastError(ERROR_INVALID_SID);
1893 LocalFree(*sid);
1894 }
1895 return ret;
1896 }
1897 }
1898
1899 /* That's probably a string S-R-I-S-S... */
1900 if (StringSid[0] != 'S' || StringSid[1] != '-')
1901 {
1902 SetLastError(ERROR_INVALID_SID);
1903 return FALSE;
1904 }
1905
1906 cBytes = ComputeStringSidSize(StringSid);
1907 pisid = (SID*)LocalAlloc( 0, cBytes );
1908 if (!pisid)
1909 {
1910 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1911 return FALSE;
1912 }
1913 i = 0;
1914 ret = FALSE;
1915 csubauth = ((cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
1916
1917 StringSid += 2; /* Advance to Revision */
1918 pisid->Revision = atoiW(StringSid);
1919
1920 if (pisid->Revision != SDDL_REVISION)
1921 {
1922 TRACE("Revision %d is unknown\n", pisid->Revision);
1923 goto lend; /* ERROR_INVALID_SID */
1924 }
1925 if (csubauth == 0)
1926 {
1927 TRACE("SubAuthorityCount is 0\n");
1928 goto lend; /* ERROR_INVALID_SID */
1929 }
1930
1931 pisid->SubAuthorityCount = csubauth;
1932
1933 /* Advance to identifier authority */
1934 while (*StringSid && *StringSid != '-')
1935 StringSid++;
1936 if (*StringSid == '-')
1937 StringSid++;
1938
1939 /* MS' implementation can't handle values greater than 2^32 - 1, so
1940 * we don't either; assume most significant bytes are always 0
1941 */
1942 pisid->IdentifierAuthority.Value[0] = 0;
1943 pisid->IdentifierAuthority.Value[1] = 0;
1944 identAuth = atoiW(StringSid);
1945 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
1946 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
1947 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
1948 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
1949
1950 /* Advance to first sub authority */
1951 while (*StringSid && *StringSid != '-')
1952 StringSid++;
1953 if (*StringSid == '-')
1954 StringSid++;
1955
1956 while (*StringSid)
1957 {
1958 pisid->SubAuthority[i++] = atoiW(StringSid);
1959
1960 while (*StringSid && *StringSid != '-')
1961 StringSid++;
1962 if (*StringSid == '-')
1963 StringSid++;
1964 }
1965
1966 if (i != pisid->SubAuthorityCount)
1967 goto lend; /* ERROR_INVALID_SID */
1968
1969 *sid = pisid;
1970 ret = TRUE;
1971
1972 lend:
1973 if (!ret)
1974 {
1975 LocalFree(pisid);
1976 SetLastError(ERROR_INVALID_SID);
1977 }
1978
1979 TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
1980 return ret;
1981 }
1982
1983 /* EOF */