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