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