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