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