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