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