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