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