[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/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 OpenProcessToken(HANDLE ProcessHandle,
321 DWORD DesiredAccess,
322 PHANDLE TokenHandle)
323 {
324 NTSTATUS Status;
325
326 TRACE("%p, %x, %p.\n", ProcessHandle, DesiredAccess, TokenHandle);
327
328 Status = NtOpenProcessToken(ProcessHandle,
329 DesiredAccess,
330 TokenHandle);
331 if (!NT_SUCCESS(Status))
332 {
333 ERR("NtOpenProcessToken failed! Status %08x.\n", Status);
334 SetLastError(RtlNtStatusToDosError(Status));
335 return FALSE;
336 }
337
338 TRACE("Returning token %p.\n", *TokenHandle);
339
340 return TRUE;
341 }
342
343 /*
344 * @implemented
345 */
346 BOOL WINAPI
347 OpenThreadToken(HANDLE ThreadHandle,
348 DWORD DesiredAccess,
349 BOOL OpenAsSelf,
350 PHANDLE TokenHandle)
351 {
352 NTSTATUS Status;
353
354 Status = NtOpenThreadToken(ThreadHandle,
355 DesiredAccess,
356 OpenAsSelf,
357 TokenHandle);
358 if (!NT_SUCCESS(Status))
359 {
360 SetLastError(RtlNtStatusToDosError(Status));
361 return FALSE;
362 }
363
364 return TRUE;
365 }
366
367 /*
368 * @implemented
369 */
370 BOOL WINAPI
371 AdjustTokenGroups(HANDLE TokenHandle,
372 BOOL ResetToDefault,
373 PTOKEN_GROUPS NewState,
374 DWORD BufferLength,
375 PTOKEN_GROUPS PreviousState,
376 PDWORD ReturnLength)
377 {
378 NTSTATUS Status;
379
380 Status = NtAdjustGroupsToken(TokenHandle,
381 ResetToDefault,
382 NewState,
383 BufferLength,
384 PreviousState,
385 (PULONG)ReturnLength);
386 if (!NT_SUCCESS(Status))
387 {
388 SetLastError(RtlNtStatusToDosError(Status));
389 return FALSE;
390 }
391
392 return TRUE;
393 }
394
395 /*
396 * @implemented
397 */
398 BOOL WINAPI
399 AdjustTokenPrivileges(HANDLE TokenHandle,
400 BOOL DisableAllPrivileges,
401 PTOKEN_PRIVILEGES NewState,
402 DWORD BufferLength,
403 PTOKEN_PRIVILEGES PreviousState,
404 PDWORD ReturnLength)
405 {
406 NTSTATUS Status;
407
408 Status = NtAdjustPrivilegesToken(TokenHandle,
409 DisableAllPrivileges,
410 NewState,
411 BufferLength,
412 PreviousState,
413 (PULONG)ReturnLength);
414 if (STATUS_NOT_ALL_ASSIGNED == Status)
415 {
416 SetLastError(ERROR_NOT_ALL_ASSIGNED);
417 return TRUE;
418 }
419
420 if (!NT_SUCCESS(Status))
421 {
422 SetLastError(RtlNtStatusToDosError(Status));
423 return FALSE;
424 }
425
426 /* AdjustTokenPrivileges is documented to do this */
427 SetLastError(ERROR_SUCCESS);
428
429 return TRUE;
430 }
431
432 /*
433 * @implemented
434 */
435 BOOL WINAPI
436 GetTokenInformation(HANDLE TokenHandle,
437 TOKEN_INFORMATION_CLASS TokenInformationClass,
438 LPVOID TokenInformation,
439 DWORD TokenInformationLength,
440 PDWORD ReturnLength)
441 {
442 NTSTATUS Status;
443
444 Status = NtQueryInformationToken(TokenHandle,
445 TokenInformationClass,
446 TokenInformation,
447 TokenInformationLength,
448 (PULONG)ReturnLength);
449 if (!NT_SUCCESS(Status))
450 {
451 SetLastError(RtlNtStatusToDosError(Status));
452 return FALSE;
453 }
454
455 return TRUE;
456 }
457
458 /*
459 * @implemented
460 */
461 BOOL WINAPI
462 SetTokenInformation(HANDLE TokenHandle,
463 TOKEN_INFORMATION_CLASS TokenInformationClass,
464 LPVOID TokenInformation,
465 DWORD TokenInformationLength)
466 {
467 NTSTATUS Status;
468
469 Status = NtSetInformationToken(TokenHandle,
470 TokenInformationClass,
471 TokenInformation,
472 TokenInformationLength);
473 if (!NT_SUCCESS(Status))
474 {
475 SetLastError(RtlNtStatusToDosError(Status));
476 return FALSE;
477 }
478
479 return TRUE;
480 }
481
482 /*
483 * @implemented
484 */
485 BOOL WINAPI
486 SetThreadToken(IN PHANDLE ThreadHandle OPTIONAL,
487 IN HANDLE TokenHandle)
488 {
489 NTSTATUS Status;
490 HANDLE hThread;
491
492 hThread = (ThreadHandle != NULL) ? *ThreadHandle : NtCurrentThread();
493
494 Status = NtSetInformationThread(hThread,
495 ThreadImpersonationToken,
496 &TokenHandle,
497 sizeof(HANDLE));
498 if (!NT_SUCCESS(Status))
499 {
500 SetLastError(RtlNtStatusToDosError(Status));
501 return FALSE;
502 }
503
504 return TRUE;
505 }
506
507 BOOL WINAPI
508 CreateRestrictedToken(HANDLE TokenHandle,
509 DWORD Flags,
510 DWORD DisableSidCount,
511 PSID_AND_ATTRIBUTES pSidAndAttributes,
512 DWORD DeletePrivilegeCount,
513 PLUID_AND_ATTRIBUTES pLUIDAndAttributes,
514 DWORD RestrictedSidCount,
515 PSID_AND_ATTRIBUTES pSIDAndAttributes,
516 PHANDLE NewTokenHandle)
517 {
518 UNIMPLEMENTED;
519 return FALSE;
520 }
521
522 /*
523 * @implemented
524 */
525 BOOL WINAPI
526 AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
527 BYTE nSubAuthorityCount,
528 DWORD dwSubAuthority0,
529 DWORD dwSubAuthority1,
530 DWORD dwSubAuthority2,
531 DWORD dwSubAuthority3,
532 DWORD dwSubAuthority4,
533 DWORD dwSubAuthority5,
534 DWORD dwSubAuthority6,
535 DWORD dwSubAuthority7,
536 PSID *pSid)
537 {
538 NTSTATUS Status;
539
540 Status = RtlAllocateAndInitializeSid(pIdentifierAuthority,
541 nSubAuthorityCount,
542 dwSubAuthority0,
543 dwSubAuthority1,
544 dwSubAuthority2,
545 dwSubAuthority3,
546 dwSubAuthority4,
547 dwSubAuthority5,
548 dwSubAuthority6,
549 dwSubAuthority7,
550 pSid);
551 if (!NT_SUCCESS(Status))
552 {
553 SetLastError(RtlNtStatusToDosError(Status));
554 return FALSE;
555 }
556
557 return TRUE;
558 }
559
560 /*
561 * @implemented
562 *
563 * RETURNS
564 * Docs says this function does NOT return a value
565 * even thou it's defined to return a PVOID...
566 */
567 PVOID
568 WINAPI
569 FreeSid(PSID pSid)
570 {
571 return RtlFreeSid(pSid);
572 }
573
574 /*
575 * @implemented
576 */
577 BOOL WINAPI
578 CopySid(DWORD nDestinationSidLength,
579 PSID pDestinationSid,
580 PSID pSourceSid)
581 {
582 NTSTATUS Status;
583
584 Status = RtlCopySid(nDestinationSidLength,
585 pDestinationSid,
586 pSourceSid);
587 if (!NT_SUCCESS (Status))
588 {
589 SetLastError(RtlNtStatusToDosError(Status));
590 return FALSE;
591 }
592
593 return TRUE;
594 }
595
596 /*
597 * @unimplemented
598 */
599 BOOL
600 WINAPI
601 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
602 IN PSID DomainSid OPTIONAL,
603 OUT PSID pSid,
604 IN OUT DWORD* cbSid)
605 {
606 unsigned int i;
607 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
608
609 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
610 {
611 SetLastError(ERROR_INVALID_PARAMETER);
612 return FALSE;
613 }
614
615 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
616 if (WellKnownSids[i].Type == WellKnownSidType) {
617 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
618
619 if (*cbSid < length)
620 {
621 *cbSid = length;
622 SetLastError(ERROR_INSUFFICIENT_BUFFER);
623 return FALSE;
624 }
625 if (!pSid)
626 {
627 SetLastError(ERROR_INVALID_PARAMETER);
628 return FALSE;
629 }
630 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
631 *cbSid = length;
632 return TRUE;
633 }
634 }
635
636 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
637 {
638 SetLastError(ERROR_INVALID_PARAMETER);
639 return FALSE;
640 }
641
642 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
643 if (WellKnownRids[i].Type == WellKnownSidType) {
644 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
645 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
646 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
647
648 if (*cbSid < output_sid_length)
649 {
650 *cbSid = output_sid_length;
651 SetLastError(ERROR_INSUFFICIENT_BUFFER);
652 return FALSE;
653 }
654 if (!pSid)
655 {
656 SetLastError(ERROR_INVALID_PARAMETER);
657 return FALSE;
658 }
659 CopyMemory(pSid, DomainSid, domain_sid_length);
660 (*GetSidSubAuthorityCount(pSid))++;
661 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
662 *cbSid = output_sid_length;
663 return TRUE;
664 }
665
666 SetLastError(ERROR_INVALID_PARAMETER);
667 return FALSE;
668 }
669
670 /*
671 * @unimplemented
672 */
673 BOOL
674 WINAPI
675 IsWellKnownSid(IN PSID pSid,
676 IN WELL_KNOWN_SID_TYPE WellKnownSidType)
677 {
678 unsigned int i;
679 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
680
681 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
682 {
683 if (WellKnownSids[i].Type == WellKnownSidType)
684 {
685 if (EqualSid(pSid, (PSID)(&WellKnownSids[i].Sid.Revision)))
686 return TRUE;
687 }
688 }
689
690 return FALSE;
691 }
692
693 /*
694 * @implemented
695 */
696 BOOL
697 WINAPI
698 IsValidSid(PSID pSid)
699 {
700 return (BOOL)RtlValidSid(pSid);
701 }
702
703 /*
704 * @implemented
705 */
706 BOOL
707 WINAPI
708 EqualSid(PSID pSid1,
709 PSID pSid2)
710 {
711 SetLastError(ERROR_SUCCESS);
712 return RtlEqualSid (pSid1, pSid2);
713 }
714
715 /*
716 * @implemented
717 */
718 BOOL
719 WINAPI
720 EqualPrefixSid(PSID pSid1,
721 PSID pSid2)
722 {
723 return RtlEqualPrefixSid (pSid1, pSid2);
724 }
725
726 /*
727 * @implemented
728 */
729 DWORD
730 WINAPI
731 GetSidLengthRequired(UCHAR nSubAuthorityCount)
732 {
733 return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
734 }
735
736 /*
737 * @implemented
738 */
739 BOOL
740 WINAPI
741 InitializeSid(PSID Sid,
742 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
743 BYTE nSubAuthorityCount)
744 {
745 NTSTATUS Status;
746
747 Status = RtlInitializeSid(Sid,
748 pIdentifierAuthority,
749 nSubAuthorityCount);
750 if (!NT_SUCCESS(Status))
751 {
752 SetLastError(RtlNtStatusToDosError(Status));
753 return FALSE;
754 }
755
756 return TRUE;
757 }
758
759 /*
760 * @implemented
761 */
762 PSID_IDENTIFIER_AUTHORITY
763 WINAPI
764 GetSidIdentifierAuthority(PSID pSid)
765 {
766 return RtlIdentifierAuthoritySid(pSid);
767 }
768
769 /*
770 * @implemented
771 */
772 PDWORD
773 WINAPI
774 GetSidSubAuthority(PSID pSid,
775 DWORD nSubAuthority)
776 {
777 SetLastError(ERROR_SUCCESS);
778 return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority);
779 }
780
781 /*
782 * @implemented
783 */
784 PUCHAR
785 WINAPI
786 GetSidSubAuthorityCount(PSID pSid)
787 {
788 SetLastError(ERROR_SUCCESS);
789 return RtlSubAuthorityCountSid(pSid);
790 }
791
792 /*
793 * @implemented
794 */
795 DWORD
796 WINAPI
797 GetLengthSid(PSID pSid)
798 {
799 return (DWORD)RtlLengthSid(pSid);
800 }
801
802 /*
803 * @implemented
804 */
805 BOOL WINAPI
806 AllocateLocallyUniqueId(PLUID Luid)
807 {
808 NTSTATUS Status;
809
810 Status = NtAllocateLocallyUniqueId (Luid);
811 if (!NT_SUCCESS (Status))
812 {
813 SetLastError(RtlNtStatusToDosError(Status));
814 return FALSE;
815 }
816
817 return TRUE;
818 }
819
820 /*
821 * @implemented
822 */
823 BOOL
824 WINAPI
825 AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
826 IN HANDLE ClientToken,
827 IN DWORD DesiredAccess,
828 IN PGENERIC_MAPPING GenericMapping,
829 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
830 IN OUT LPDWORD PrivilegeSetLength,
831 OUT LPDWORD GrantedAccess,
832 OUT LPBOOL AccessStatus)
833 {
834 NTSTATUS Status;
835 NTSTATUS NtAccessStatus;
836
837 /* Do the access check */
838 Status = NtAccessCheck(pSecurityDescriptor,
839 ClientToken,
840 DesiredAccess,
841 GenericMapping,
842 PrivilegeSet,
843 (PULONG)PrivilegeSetLength,
844 (PACCESS_MASK)GrantedAccess,
845 &NtAccessStatus);
846
847 /* See if the access check operation succeeded */
848 if (!NT_SUCCESS(Status))
849 {
850 /* Check failed */
851 SetLastError(RtlNtStatusToDosError(Status));
852 return FALSE;
853 }
854
855 /* Now check the access status */
856 if (!NT_SUCCESS(NtAccessStatus))
857 {
858 /* Access denied */
859 SetLastError(RtlNtStatusToDosError(NtAccessStatus));
860 *AccessStatus = FALSE;
861 }
862 else
863 {
864 /* Access granted */
865 *AccessStatus = TRUE;
866 }
867
868 /* Check succeeded */
869 return TRUE;
870 }
871
872 /*
873 * @unimplemented
874 */
875 BOOL WINAPI AccessCheckByType(
876 PSECURITY_DESCRIPTOR pSecurityDescriptor,
877 PSID PrincipalSelfSid,
878 HANDLE ClientToken,
879 DWORD DesiredAccess,
880 POBJECT_TYPE_LIST ObjectTypeList,
881 DWORD ObjectTypeListLength,
882 PGENERIC_MAPPING GenericMapping,
883 PPRIVILEGE_SET PrivilegeSet,
884 LPDWORD PrivilegeSetLength,
885 LPDWORD GrantedAccess,
886 LPBOOL AccessStatus)
887 {
888 FIXME("stub\n");
889
890 *AccessStatus = TRUE;
891
892 return !*AccessStatus;
893 }
894
895 /**********************************************************************
896 * PrivilegeCheck EXPORTED
897 *
898 * @implemented
899 */
900 BOOL WINAPI
901 PrivilegeCheck(HANDLE ClientToken,
902 PPRIVILEGE_SET RequiredPrivileges,
903 LPBOOL pfResult)
904 {
905 BOOLEAN Result;
906 NTSTATUS Status;
907
908 Status = NtPrivilegeCheck(ClientToken,
909 RequiredPrivileges,
910 &Result);
911 if (!NT_SUCCESS(Status))
912 {
913 SetLastError(RtlNtStatusToDosError(Status));
914 return FALSE;
915 }
916
917 *pfResult = (BOOL)Result;
918
919 return TRUE;
920 }
921
922 /******************************************************************************
923 * ParseAclStringFlags
924 */
925 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
926 {
927 DWORD flags = 0;
928 LPCWSTR szAcl = *StringAcl;
929
930 while (*szAcl != '(')
931 {
932 if (*szAcl == 'P')
933 {
934 flags |= SE_DACL_PROTECTED;
935 }
936 else if (*szAcl == 'A')
937 {
938 szAcl++;
939 if (*szAcl == 'R')
940 flags |= SE_DACL_AUTO_INHERIT_REQ;
941 else if (*szAcl == 'I')
942 flags |= SE_DACL_AUTO_INHERITED;
943 }
944 szAcl++;
945 }
946
947 *StringAcl = szAcl;
948 return flags;
949 }
950
951 /******************************************************************************
952 * ParseAceStringType
953 */
954 static const ACEFLAG AceType[] =
955 {
956 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
957 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
958 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
959 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
960 /*
961 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
962 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
963 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
964 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
965 */
966 { NULL, 0 },
967 };
968
969 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
970 {
971 UINT len = 0;
972 LPCWSTR szAcl = *StringAcl;
973 const ACEFLAG *lpaf = AceType;
974
975 while (lpaf->wstr &&
976 (len = strlenW(lpaf->wstr)) &&
977 strncmpW(lpaf->wstr, szAcl, len))
978 lpaf++;
979
980 if (!lpaf->wstr)
981 return 0;
982
983 *StringAcl += len;
984 return lpaf->value;
985 }
986
987
988 /******************************************************************************
989 * ParseAceStringFlags
990 */
991 static const ACEFLAG AceFlags[] =
992 {
993 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
994 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
995 { SDDL_INHERITED, INHERITED_ACE },
996 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
997 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
998 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
999 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
1000 { NULL, 0 },
1001 };
1002
1003 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
1004 {
1005 UINT len = 0;
1006 BYTE flags = 0;
1007 LPCWSTR szAcl = *StringAcl;
1008
1009 while (*szAcl != ';')
1010 {
1011 const ACEFLAG *lpaf = AceFlags;
1012
1013 while (lpaf->wstr &&
1014 (len = strlenW(lpaf->wstr)) &&
1015 strncmpW(lpaf->wstr, szAcl, len))
1016 lpaf++;
1017
1018 if (!lpaf->wstr)
1019 return 0;
1020
1021 flags |= lpaf->value;
1022 szAcl += len;
1023 }
1024
1025 *StringAcl = szAcl;
1026 return flags;
1027 }
1028
1029
1030 /******************************************************************************
1031 * ParseAceStringRights
1032 */
1033 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
1034 {
1035 UINT len = 0;
1036 DWORD rights = 0;
1037 LPCWSTR szAcl = *StringAcl;
1038
1039 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
1040 {
1041 LPCWSTR p = szAcl;
1042
1043 while (*p && *p != ';')
1044 p++;
1045
1046 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
1047 {
1048 rights = strtoulW(szAcl, NULL, 16);
1049 szAcl = p;
1050 }
1051 else
1052 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
1053 }
1054 else
1055 {
1056 while (*szAcl != ';')
1057 {
1058 const ACEFLAG *lpaf = AceRights;
1059
1060 while (lpaf->wstr &&
1061 (len = strlenW(lpaf->wstr)) &&
1062 strncmpW(lpaf->wstr, szAcl, len))
1063 {
1064 lpaf++;
1065 }
1066
1067 if (!lpaf->wstr)
1068 return 0;
1069
1070 rights |= lpaf->value;
1071 szAcl += len;
1072 }
1073 }
1074
1075 *StringAcl = szAcl;
1076 return rights;
1077 }
1078
1079
1080 /******************************************************************************
1081 * ParseStringAclToAcl
1082 *
1083 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
1084 */
1085 static BOOL
1086 ParseStringAclToAcl(LPCWSTR StringAcl,
1087 LPDWORD lpdwFlags,
1088 PACL pAcl,
1089 LPDWORD cBytes)
1090 {
1091 DWORD val;
1092 DWORD sidlen;
1093 DWORD length = sizeof(ACL);
1094 DWORD acesize = 0;
1095 DWORD acecount = 0;
1096 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
1097
1098 TRACE("%s\n", debugstr_w(StringAcl));
1099
1100 if (!StringAcl)
1101 return FALSE;
1102
1103 if (pAcl) /* pAce is only useful if we're setting values */
1104 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
1105
1106 /* Parse ACL flags */
1107 *lpdwFlags = ParseAclStringFlags(&StringAcl);
1108
1109 /* Parse ACE */
1110 while (*StringAcl == '(')
1111 {
1112 StringAcl++;
1113
1114 /* Parse ACE type */
1115 val = ParseAceStringType(&StringAcl);
1116 if (pAce)
1117 pAce->Header.AceType = (BYTE) val;
1118 if (*StringAcl != ';')
1119 goto lerr;
1120 StringAcl++;
1121
1122 /* Parse ACE flags */
1123 val = ParseAceStringFlags(&StringAcl);
1124 if (pAce)
1125 pAce->Header.AceFlags = (BYTE) val;
1126 if (*StringAcl != ';')
1127 goto lerr;
1128 StringAcl++;
1129
1130 /* Parse ACE rights */
1131 val = ParseAceStringRights(&StringAcl);
1132 if (pAce)
1133 pAce->Mask = val;
1134 if (*StringAcl != ';')
1135 goto lerr;
1136 StringAcl++;
1137
1138 /* Parse ACE object guid */
1139 if (*StringAcl != ';')
1140 {
1141 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1142 goto lerr;
1143 }
1144 StringAcl++;
1145
1146 /* Parse ACE inherit object guid */
1147 if (*StringAcl != ';')
1148 {
1149 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1150 goto lerr;
1151 }
1152 StringAcl++;
1153
1154 /* Parse ACE account sid */
1155 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
1156 {
1157 while (*StringAcl && *StringAcl != ')')
1158 StringAcl++;
1159 }
1160
1161 if (*StringAcl != ')')
1162 goto lerr;
1163 StringAcl++;
1164
1165 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
1166 length += acesize;
1167 if (pAce)
1168 {
1169 pAce->Header.AceSize = acesize;
1170 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
1171 }
1172 acecount++;
1173 }
1174
1175 *cBytes = length;
1176
1177 if (length > 0xffff)
1178 {
1179 ERR("ACL too large\n");
1180 goto lerr;
1181 }
1182
1183 if (pAcl)
1184 {
1185 pAcl->AclRevision = ACL_REVISION;
1186 pAcl->Sbz1 = 0;
1187 pAcl->AclSize = length;
1188 pAcl->AceCount = acecount++;
1189 pAcl->Sbz2 = 0;
1190 }
1191 return TRUE;
1192
1193 lerr:
1194 SetLastError(ERROR_INVALID_ACL);
1195 WARN("Invalid ACE string format\n");
1196 return FALSE;
1197 }
1198
1199
1200 /******************************************************************************
1201 * ParseStringSecurityDescriptorToSecurityDescriptor
1202 */
1203 static BOOL
1204 ParseStringSecurityDescriptorToSecurityDescriptor(LPCWSTR StringSecurityDescriptor,
1205 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
1206 LPDWORD cBytes)
1207 {
1208 BOOL bret = FALSE;
1209 WCHAR toktype;
1210 WCHAR tok[MAX_PATH];
1211 LPCWSTR lptoken;
1212 LPBYTE lpNext = NULL;
1213 DWORD len;
1214
1215 *cBytes = sizeof(SECURITY_DESCRIPTOR);
1216
1217 if (SecurityDescriptor)
1218 lpNext = (LPBYTE)(SecurityDescriptor + 1);
1219
1220 while (*StringSecurityDescriptor)
1221 {
1222 toktype = *StringSecurityDescriptor;
1223
1224 /* Expect char identifier followed by ':' */
1225 StringSecurityDescriptor++;
1226 if (*StringSecurityDescriptor != ':')
1227 {
1228 SetLastError(ERROR_INVALID_PARAMETER);
1229 goto lend;
1230 }
1231 StringSecurityDescriptor++;
1232
1233 /* Extract token */
1234 lptoken = StringSecurityDescriptor;
1235 while (*lptoken && *lptoken != ':')
1236 lptoken++;
1237
1238 if (*lptoken)
1239 lptoken--;
1240
1241 len = lptoken - StringSecurityDescriptor;
1242 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
1243 tok[len] = 0;
1244
1245 switch (toktype)
1246 {
1247 case 'O':
1248 {
1249 DWORD bytes;
1250
1251 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1252 goto lend;
1253
1254 if (SecurityDescriptor)
1255 {
1256 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
1257 lpNext += bytes; /* Advance to next token */
1258 }
1259
1260 *cBytes += bytes;
1261
1262 break;
1263 }
1264
1265 case 'G':
1266 {
1267 DWORD bytes;
1268
1269 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1270 goto lend;
1271
1272 if (SecurityDescriptor)
1273 {
1274 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
1275 lpNext += bytes; /* Advance to next token */
1276 }
1277
1278 *cBytes += bytes;
1279
1280 break;
1281 }
1282
1283 case 'D':
1284 {
1285 DWORD flags;
1286 DWORD bytes;
1287
1288 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1289 goto lend;
1290
1291 if (SecurityDescriptor)
1292 {
1293 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
1294 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
1295 lpNext += bytes; /* Advance to next token */
1296 }
1297
1298 *cBytes += bytes;
1299
1300 break;
1301 }
1302
1303 case 'S':
1304 {
1305 DWORD flags;
1306 DWORD bytes;
1307
1308 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1309 goto lend;
1310
1311 if (SecurityDescriptor)
1312 {
1313 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
1314 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
1315 lpNext += bytes; /* Advance to next token */
1316 }
1317
1318 *cBytes += bytes;
1319
1320 break;
1321 }
1322
1323 default:
1324 FIXME("Unknown token\n");
1325 SetLastError(ERROR_INVALID_PARAMETER);
1326 goto lend;
1327 }
1328
1329 StringSecurityDescriptor = lptoken;
1330 }
1331
1332 bret = TRUE;
1333
1334 lend:
1335 return bret;
1336 }
1337
1338 /* Winehq cvs 20050916 */
1339 /******************************************************************************
1340 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
1341 * @implemented
1342 */
1343 BOOL
1344 WINAPI
1345 ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor,
1346 DWORD StringSDRevision,
1347 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1348 PULONG SecurityDescriptorSize)
1349 {
1350 UINT len;
1351 BOOL ret = FALSE;
1352 LPWSTR StringSecurityDescriptorW;
1353
1354 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
1355 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1356
1357 if (StringSecurityDescriptorW)
1358 {
1359 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
1360
1361 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
1362 StringSDRevision, SecurityDescriptor,
1363 SecurityDescriptorSize);
1364 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
1365 }
1366
1367 return ret;
1368 }
1369
1370 /******************************************************************************
1371 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
1372 * @implemented
1373 */
1374 BOOL WINAPI
1375 ConvertStringSecurityDescriptorToSecurityDescriptorW(LPCWSTR StringSecurityDescriptor,
1376 DWORD StringSDRevision,
1377 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1378 PULONG SecurityDescriptorSize)
1379 {
1380 DWORD cBytes;
1381 SECURITY_DESCRIPTOR* psd;
1382 BOOL bret = FALSE;
1383
1384 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
1385
1386 if (GetVersion() & 0x80000000)
1387 {
1388 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1389 goto lend;
1390 }
1391 else if (!StringSecurityDescriptor || !SecurityDescriptor)
1392 {
1393 SetLastError(ERROR_INVALID_PARAMETER);
1394 goto lend;
1395 }
1396 else if (StringSDRevision != SID_REVISION)
1397 {
1398 SetLastError(ERROR_UNKNOWN_REVISION);
1399 goto lend;
1400 }
1401
1402 /* Compute security descriptor length */
1403 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1404 NULL, &cBytes))
1405 goto lend;
1406
1407 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
1408 if (!psd) goto lend;
1409
1410 psd->Revision = SID_REVISION;
1411 psd->Control |= SE_SELF_RELATIVE;
1412
1413 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1414 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
1415 {
1416 LocalFree(psd);
1417 goto lend;
1418 }
1419
1420 if (SecurityDescriptorSize)
1421 *SecurityDescriptorSize = cBytes;
1422
1423 bret = TRUE;
1424
1425 lend:
1426 TRACE(" ret=%d\n", bret);
1427 return bret;
1428 }
1429
1430 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
1431 {
1432 if (cch == -1)
1433 cch = strlenW(string);
1434
1435 if (plen)
1436 *plen += cch;
1437
1438 if (pwptr)
1439 {
1440 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
1441 *pwptr += cch;
1442 }
1443 }
1444
1445 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
1446 {
1447 DWORD i;
1448 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
1449 WCHAR subauthfmt[] = { '-','%','u',0 };
1450 WCHAR buf[26];
1451 SID *pisid = psid;
1452
1453 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
1454 {
1455 SetLastError(ERROR_INVALID_SID);
1456 return FALSE;
1457 }
1458
1459 if (pisid->IdentifierAuthority.Value[0] ||
1460 pisid->IdentifierAuthority.Value[1])
1461 {
1462 FIXME("not matching MS' bugs\n");
1463 SetLastError(ERROR_INVALID_SID);
1464 return FALSE;
1465 }
1466
1467 sprintfW( buf, fmt, pisid->Revision,
1468 MAKELONG(
1469 MAKEWORD( pisid->IdentifierAuthority.Value[5],
1470 pisid->IdentifierAuthority.Value[4] ),
1471 MAKEWORD( pisid->IdentifierAuthority.Value[3],
1472 pisid->IdentifierAuthority.Value[2] )
1473 ) );
1474 DumpString(buf, -1, pwptr, plen);
1475
1476 for( i=0; i<pisid->SubAuthorityCount; i++ )
1477 {
1478 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
1479 DumpString(buf, -1, pwptr, plen);
1480 }
1481 return TRUE;
1482 }
1483
1484 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
1485 {
1486 size_t i;
1487 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
1488 {
1489 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
1490 {
1491 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
1492 return TRUE;
1493 }
1494 }
1495
1496 return DumpSidNumeric(psid, pwptr, plen);
1497 }
1498
1499 static const LPCWSTR AceRightBitNames[32] = {
1500 SDDL_CREATE_CHILD, /* 0 */
1501 SDDL_DELETE_CHILD,
1502 SDDL_LIST_CHILDREN,
1503 SDDL_SELF_WRITE,
1504 SDDL_READ_PROPERTY, /* 4 */
1505 SDDL_WRITE_PROPERTY,
1506 SDDL_DELETE_TREE,
1507 SDDL_LIST_OBJECT,
1508 SDDL_CONTROL_ACCESS, /* 8 */
1509 NULL,
1510 NULL,
1511 NULL,
1512 NULL, /* 12 */
1513 NULL,
1514 NULL,
1515 NULL,
1516 SDDL_STANDARD_DELETE, /* 16 */
1517 SDDL_READ_CONTROL,
1518 SDDL_WRITE_DAC,
1519 SDDL_WRITE_OWNER,
1520 NULL, /* 20 */
1521 NULL,
1522 NULL,
1523 NULL,
1524 NULL, /* 24 */
1525 NULL,
1526 NULL,
1527 NULL,
1528 SDDL_GENERIC_ALL, /* 28 */
1529 SDDL_GENERIC_EXECUTE,
1530 SDDL_GENERIC_WRITE,
1531 SDDL_GENERIC_READ
1532 };
1533
1534 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
1535 {
1536 static const WCHAR fmtW[] = {'0','x','%','x',0};
1537 WCHAR buf[15];
1538 size_t i;
1539
1540 if (mask == 0)
1541 return;
1542
1543 /* first check if the right have name */
1544 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
1545 {
1546 if (AceRights[i].wstr == NULL)
1547 break;
1548 if (mask == AceRights[i].value)
1549 {
1550 DumpString(AceRights[i].wstr, -1, pwptr, plen);
1551 return;
1552 }
1553 }
1554
1555 /* then check if it can be built from bit names */
1556 for (i = 0; i < 32; i++)
1557 {
1558 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
1559 {
1560 /* can't be built from bit names */
1561 sprintfW(buf, fmtW, mask);
1562 DumpString(buf, -1, pwptr, plen);
1563 return;
1564 }
1565 }
1566
1567 /* build from bit names */
1568 for (i = 0; i < 32; i++)
1569 if (mask & (1 << i))
1570 DumpString(AceRightBitNames[i], -1, pwptr, plen);
1571 }
1572
1573 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
1574 {
1575 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
1576 static const WCHAR openbr = '(';
1577 static const WCHAR closebr = ')';
1578 static const WCHAR semicolon = ';';
1579
1580 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
1581 {
1582 SetLastError(ERROR_INVALID_ACL);
1583 return FALSE;
1584 }
1585
1586 piace = pace;
1587 DumpString(&openbr, 1, pwptr, plen);
1588 switch (piace->Header.AceType)
1589 {
1590 case ACCESS_ALLOWED_ACE_TYPE:
1591 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
1592 break;
1593 case ACCESS_DENIED_ACE_TYPE:
1594 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
1595 break;
1596 case SYSTEM_AUDIT_ACE_TYPE:
1597 DumpString(SDDL_AUDIT, -1, pwptr, plen);
1598 break;
1599 case SYSTEM_ALARM_ACE_TYPE:
1600 DumpString(SDDL_ALARM, -1, pwptr, plen);
1601 break;
1602 }
1603 DumpString(&semicolon, 1, pwptr, plen);
1604
1605 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
1606 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
1607 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
1608 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
1609 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
1610 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
1611 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
1612 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
1613 if (piace->Header.AceFlags & INHERITED_ACE)
1614 DumpString(SDDL_INHERITED, -1, pwptr, plen);
1615 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
1616 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
1617 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
1618 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
1619 DumpString(&semicolon, 1, pwptr, plen);
1620 DumpRights(piace->Mask, pwptr, plen);
1621 DumpString(&semicolon, 1, pwptr, plen);
1622 /* objects not supported */
1623 DumpString(&semicolon, 1, pwptr, plen);
1624 /* objects not supported */
1625 DumpString(&semicolon, 1, pwptr, plen);
1626 if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
1627 return FALSE;
1628 DumpString(&closebr, 1, pwptr, plen);
1629 return TRUE;
1630 }
1631
1632 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
1633 {
1634 WORD count;
1635 int i;
1636
1637 if (protected)
1638 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
1639 if (autoInheritReq)
1640 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
1641 if (autoInherited)
1642 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
1643
1644 if (pacl == NULL)
1645 return TRUE;
1646
1647 if (!IsValidAcl(pacl))
1648 return FALSE;
1649
1650 count = pacl->AceCount;
1651 for (i = 0; i < count; i++)
1652 {
1653 LPVOID ace;
1654 if (!GetAce(pacl, i, &ace))
1655 return FALSE;
1656 if (!DumpAce(ace, pwptr, plen))
1657 return FALSE;
1658 }
1659
1660 return TRUE;
1661 }
1662
1663 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
1664 {
1665 static const WCHAR prefix[] = {'O',':',0};
1666 BOOL bDefaulted;
1667 PSID psid;
1668
1669 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
1670 return FALSE;
1671
1672 if (psid == NULL)
1673 return TRUE;
1674
1675 DumpString(prefix, -1, pwptr, plen);
1676 if (!DumpSid(psid, pwptr, plen))
1677 return FALSE;
1678 return TRUE;
1679 }
1680
1681 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
1682 {
1683 static const WCHAR prefix[] = {'G',':',0};
1684 BOOL bDefaulted;
1685 PSID psid;
1686
1687 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
1688 return FALSE;
1689
1690 if (psid == NULL)
1691 return TRUE;
1692
1693 DumpString(prefix, -1, pwptr, plen);
1694 if (!DumpSid(psid, pwptr, plen))
1695 return FALSE;
1696 return TRUE;
1697 }
1698
1699 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
1700 {
1701 static const WCHAR dacl[] = {'D',':',0};
1702 SECURITY_DESCRIPTOR_CONTROL control;
1703 BOOL present, defaulted;
1704 DWORD revision;
1705 PACL pacl;
1706
1707 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
1708 return FALSE;
1709
1710 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
1711 return FALSE;
1712
1713 if (!present)
1714 return TRUE;
1715
1716 DumpString(dacl, 2, pwptr, plen);
1717 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
1718 return FALSE;
1719 return TRUE;
1720 }
1721
1722 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
1723 {
1724 static const WCHAR sacl[] = {'S',':',0};
1725 SECURITY_DESCRIPTOR_CONTROL control;
1726 BOOL present, defaulted;
1727 DWORD revision;
1728 PACL pacl;
1729
1730 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
1731 return FALSE;
1732
1733 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
1734 return FALSE;
1735
1736 if (!present)
1737 return TRUE;
1738
1739 DumpString(sacl, 2, pwptr, plen);
1740 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
1741 return FALSE;
1742 return TRUE;
1743 }
1744
1745 /******************************************************************************
1746 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
1747 * @implemented
1748 */
1749 BOOL WINAPI
1750 ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
1751 DWORD SDRevision,
1752 SECURITY_INFORMATION SecurityInformation,
1753 LPWSTR *OutputString,
1754 PULONG OutputLen)
1755 {
1756 ULONG len;
1757 WCHAR *wptr, *wstr;
1758
1759 if (SDRevision != SDDL_REVISION_1)
1760 {
1761 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
1762 SetLastError(ERROR_UNKNOWN_REVISION);
1763 return FALSE;
1764 }
1765
1766 len = 0;
1767 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1768 if (!DumpOwner(SecurityDescriptor, NULL, &len))
1769 return FALSE;
1770 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1771 if (!DumpGroup(SecurityDescriptor, NULL, &len))
1772 return FALSE;
1773 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1774 if (!DumpDacl(SecurityDescriptor, NULL, &len))
1775 return FALSE;
1776 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1777 if (!DumpSacl(SecurityDescriptor, NULL, &len))
1778 return FALSE;
1779
1780 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
1781 if (wstr == NULL)
1782 return FALSE;
1783
1784 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1785 if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
1786 return FALSE;
1787 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1788 if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
1789 return FALSE;
1790 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1791 if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
1792 return FALSE;
1793 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1794 if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
1795 return FALSE;
1796 *wptr = 0;
1797
1798 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
1799 *OutputString = wstr;
1800 if (OutputLen)
1801 *OutputLen = strlenW(*OutputString)+1;
1802 return TRUE;
1803 }
1804
1805 /******************************************************************************
1806 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
1807 * @implemented
1808 */
1809 BOOL WINAPI
1810 ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
1811 DWORD SDRevision,
1812 SECURITY_INFORMATION Information,
1813 LPSTR *OutputString,
1814 PULONG OutputLen)
1815 {
1816 LPWSTR wstr;
1817 ULONG len;
1818
1819 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
1820 {
1821 int lenA;
1822
1823 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
1824 *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
1825 if (*OutputString == NULL)
1826 {
1827 LocalFree(wstr);
1828 *OutputLen = 0;
1829 return FALSE;
1830 }
1831 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
1832 LocalFree(wstr);
1833
1834 if (OutputLen != NULL)
1835 *OutputLen = lenA;
1836 return TRUE;
1837 }
1838 else
1839 {
1840 *OutputString = NULL;
1841 if (OutputLen)
1842 *OutputLen = 0;
1843 return FALSE;
1844 }
1845 }
1846
1847 /*
1848 * @implemented
1849 */
1850 BOOL
1851 WINAPI
1852 ConvertStringSidToSidW(IN LPCWSTR StringSid,
1853 OUT PSID* sid)
1854 {
1855 DWORD size;
1856 DWORD i, cBytes, identAuth, csubauth;
1857 BOOL ret;
1858 SID* pisid;
1859
1860 TRACE("%s %p\n", debugstr_w(StringSid), sid);
1861
1862 if (!StringSid)
1863 {
1864 SetLastError(ERROR_INVALID_SID);
1865 return FALSE;
1866 }
1867
1868 for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
1869 {
1870 if (wcscmp(StringSid, SidTable[i].key) == 0)
1871 {
1872 WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
1873 size = SECURITY_MAX_SID_SIZE;
1874 *sid = LocalAlloc(0, size);
1875 if (!*sid)
1876 {
1877 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1878 return FALSE;
1879 }
1880 ret = CreateWellKnownSid(knownSid,
1881 NULL,
1882 *sid,
1883 &size);
1884 if (!ret)
1885 {
1886 SetLastError(ERROR_INVALID_SID);
1887 LocalFree(*sid);
1888 }
1889 return ret;
1890 }
1891 }
1892
1893 /* That's probably a string S-R-I-S-S... */
1894 if (StringSid[0] != 'S' || StringSid[1] != '-')
1895 {
1896 SetLastError(ERROR_INVALID_SID);
1897 return FALSE;
1898 }
1899
1900 cBytes = ComputeStringSidSize(StringSid);
1901 pisid = (SID*)LocalAlloc( 0, cBytes );
1902 if (!pisid)
1903 {
1904 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1905 return FALSE;
1906 }
1907 i = 0;
1908 ret = FALSE;
1909 csubauth = ((cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
1910
1911 StringSid += 2; /* Advance to Revision */
1912 pisid->Revision = atoiW(StringSid);
1913
1914 if (pisid->Revision != SDDL_REVISION)
1915 {
1916 TRACE("Revision %d is unknown\n", pisid->Revision);
1917 goto lend; /* ERROR_INVALID_SID */
1918 }
1919 if (csubauth == 0)
1920 {
1921 TRACE("SubAuthorityCount is 0\n");
1922 goto lend; /* ERROR_INVALID_SID */
1923 }
1924
1925 pisid->SubAuthorityCount = csubauth;
1926
1927 /* Advance to identifier authority */
1928 while (*StringSid && *StringSid != '-')
1929 StringSid++;
1930 if (*StringSid == '-')
1931 StringSid++;
1932
1933 /* MS' implementation can't handle values greater than 2^32 - 1, so
1934 * we don't either; assume most significant bytes are always 0
1935 */
1936 pisid->IdentifierAuthority.Value[0] = 0;
1937 pisid->IdentifierAuthority.Value[1] = 0;
1938 identAuth = atoiW(StringSid);
1939 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
1940 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
1941 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
1942 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
1943
1944 /* Advance to first sub authority */
1945 while (*StringSid && *StringSid != '-')
1946 StringSid++;
1947 if (*StringSid == '-')
1948 StringSid++;
1949
1950 while (*StringSid)
1951 {
1952 pisid->SubAuthority[i++] = atoiW(StringSid);
1953
1954 while (*StringSid && *StringSid != '-')
1955 StringSid++;
1956 if (*StringSid == '-')
1957 StringSid++;
1958 }
1959
1960 if (i != pisid->SubAuthorityCount)
1961 goto lend; /* ERROR_INVALID_SID */
1962
1963 *sid = pisid;
1964 ret = TRUE;
1965
1966 lend:
1967 if (!ret)
1968 {
1969 LocalFree(pisid);
1970 SetLastError(ERROR_INVALID_SID);
1971 }
1972
1973 TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
1974 return ret;
1975 }
1976
1977 /*
1978 * @implemented
1979 */
1980 BOOL
1981 WINAPI
1982 ConvertStringSidToSidA(IN LPCSTR StringSid,
1983 OUT PSID* sid)
1984 {
1985 BOOL bRetVal = FALSE;
1986
1987 TRACE("%s, %p\n", debugstr_a(StringSid), sid);
1988 if (GetVersion() & 0x80000000)
1989 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1990 else if (!StringSid || !sid)
1991 SetLastError(ERROR_INVALID_PARAMETER);
1992 else
1993 {
1994 UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
1995 LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1996 if (wStringSid == NULL)
1997 return FALSE;
1998 MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
1999 bRetVal = ConvertStringSidToSidW(wStringSid, sid);
2000 HeapFree(GetProcessHeap(), 0, wStringSid);
2001 }
2002 return bRetVal;
2003 }
2004
2005 /*
2006 * @implemented
2007 */
2008 BOOL
2009 WINAPI
2010 ConvertSidToStringSidW(PSID Sid,
2011 LPWSTR *StringSid)
2012 {
2013 NTSTATUS Status;
2014 UNICODE_STRING UnicodeString;
2015 WCHAR FixedBuffer[64];
2016
2017 if (!RtlValidSid(Sid))
2018 {
2019 SetLastError(ERROR_INVALID_SID);
2020 return FALSE;
2021 }
2022
2023 UnicodeString.Length = 0;
2024 UnicodeString.MaximumLength = sizeof(FixedBuffer);
2025 UnicodeString.Buffer = FixedBuffer;
2026 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
2027 if (STATUS_BUFFER_TOO_SMALL == Status)
2028 {
2029 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
2030 }
2031
2032 if (!NT_SUCCESS(Status))
2033 {
2034 SetLastError(RtlNtStatusToDosError(Status));
2035 return FALSE;
2036 }
2037
2038 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
2039 if (NULL == *StringSid)
2040 {
2041 if (UnicodeString.Buffer != FixedBuffer)
2042 {
2043 RtlFreeUnicodeString(&UnicodeString);
2044 }
2045 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2046 return FALSE;
2047 }
2048
2049 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
2050 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
2051 if (UnicodeString.Buffer != FixedBuffer)
2052 {
2053 RtlFreeUnicodeString(&UnicodeString);
2054 }
2055
2056 return TRUE;
2057 }
2058
2059 /*
2060 * @implemented
2061 */
2062 BOOL
2063 WINAPI
2064 ConvertSidToStringSidA(PSID Sid,
2065 LPSTR *StringSid)
2066 {
2067 LPWSTR StringSidW;
2068 int Len;
2069
2070 if (!ConvertSidToStringSidW(Sid, &StringSidW))
2071 {
2072 return FALSE;
2073 }
2074
2075 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
2076 if (Len <= 0)
2077 {
2078 LocalFree(StringSidW);
2079 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2080 return FALSE;
2081 }
2082
2083 *StringSid = LocalAlloc(LMEM_FIXED, Len);
2084 if (NULL == *StringSid)
2085 {
2086 LocalFree(StringSidW);
2087 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2088 return FALSE;
2089 }
2090
2091 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
2092 {
2093 LocalFree(StringSid);
2094 LocalFree(StringSidW);
2095 return FALSE;
2096 }
2097
2098 LocalFree(StringSidW);
2099
2100 return TRUE;
2101 }
2102
2103 BOOL
2104 WINAPI
2105 CreateProcessWithTokenW(IN HANDLE hToken,
2106 IN DWORD dwLogonFlags,
2107 IN LPCWSTR lpApplicationName OPTIONAL,
2108 IN OUT LPWSTR lpCommandLine OPTIONAL,
2109 IN DWORD dwCreationFlags,
2110 IN LPVOID lpEnvironment OPTIONAL,
2111 IN LPCWSTR lpCurrentDirectory OPTIONAL,
2112 IN LPSTARTUPINFOW lpStartupInfo,
2113 OUT LPPROCESS_INFORMATION lpProcessInfo)
2114 {
2115 UNIMPLEMENTED;
2116 return FALSE;
2117 }
2118
2119 /*
2120 * @implemented
2121 */
2122 BOOL WINAPI
2123 DuplicateTokenEx(IN HANDLE ExistingTokenHandle,
2124 IN DWORD dwDesiredAccess,
2125 IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL,
2126 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
2127 IN TOKEN_TYPE TokenType,
2128 OUT PHANDLE DuplicateTokenHandle)
2129 {
2130 OBJECT_ATTRIBUTES ObjectAttributes;
2131 NTSTATUS Status;
2132 SECURITY_QUALITY_OF_SERVICE Sqos;
2133
2134 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
2135 ImpersonationLevel, TokenType, DuplicateTokenHandle);
2136
2137 Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
2138 Sqos.ImpersonationLevel = ImpersonationLevel;
2139 Sqos.ContextTrackingMode = 0;
2140 Sqos.EffectiveOnly = FALSE;
2141
2142 if (lpTokenAttributes != NULL)
2143 {
2144 InitializeObjectAttributes(&ObjectAttributes,
2145 NULL,
2146 lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
2147 NULL,
2148 lpTokenAttributes->lpSecurityDescriptor);
2149 }
2150 else
2151 {
2152 InitializeObjectAttributes(&ObjectAttributes,
2153 NULL,
2154 0,
2155 NULL,
2156 NULL);
2157 }
2158
2159 ObjectAttributes.SecurityQualityOfService = &Sqos;
2160
2161 Status = NtDuplicateToken(ExistingTokenHandle,
2162 dwDesiredAccess,
2163 &ObjectAttributes,
2164 FALSE,
2165 TokenType,
2166 DuplicateTokenHandle);
2167 if (!NT_SUCCESS(Status))
2168 {
2169 ERR("NtDuplicateToken failed: Status %08x\n", Status);
2170 SetLastError(RtlNtStatusToDosError(Status));
2171 return FALSE;
2172 }
2173
2174 TRACE("Returning token %p.\n", *DuplicateTokenHandle);
2175
2176 return TRUE;
2177 }
2178
2179 /*
2180 * @implemented
2181 */
2182 BOOL WINAPI
2183 DuplicateToken(IN HANDLE ExistingTokenHandle,
2184 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
2185 OUT PHANDLE DuplicateTokenHandle)
2186 {
2187 return DuplicateTokenEx(ExistingTokenHandle,
2188 TOKEN_IMPERSONATE | TOKEN_QUERY,
2189 NULL,
2190 ImpersonationLevel,
2191 TokenImpersonation,
2192 DuplicateTokenHandle);
2193 }
2194
2195 /******************************************************************************
2196 * ComputeStringSidSize
2197 */
2198 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
2199 {
2200 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
2201 {
2202 int ctok = 0;
2203 while (*StringSid)
2204 {
2205 if (*StringSid == '-')
2206 ctok++;
2207 StringSid++;
2208 }
2209
2210 if (ctok >= 3)
2211 return GetSidLengthRequired(ctok - 2);
2212 }
2213 else /* String constant format - Only available in winxp and above */
2214 {
2215 unsigned int i;
2216
2217 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
2218 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
2219 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
2220 }
2221
2222 return GetSidLengthRequired(0);
2223 }
2224
2225 /******************************************************************************
2226 * ParseStringSidToSid
2227 */
2228 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
2229 {
2230 BOOL bret = FALSE;
2231 SID* pisid=pSid;
2232
2233 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
2234 if (!StringSid)
2235 {
2236 SetLastError(ERROR_INVALID_PARAMETER);
2237 TRACE("StringSid is NULL, returning FALSE\n");
2238 return FALSE;
2239 }
2240
2241 while (*StringSid == ' ')
2242 StringSid++;
2243
2244 *cBytes = ComputeStringSidSize(StringSid);
2245 if (!pisid) /* Simply compute the size */
2246 {
2247 TRACE("only size requested, returning TRUE\n");
2248 return TRUE;
2249 }
2250
2251 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
2252 {
2253 DWORD i = 0, identAuth;
2254 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
2255
2256 StringSid += 2; /* Advance to Revision */
2257 pisid->Revision = atoiW(StringSid);
2258
2259 if (pisid->Revision != SDDL_REVISION)
2260 {
2261 TRACE("Revision %d is unknown\n", pisid->Revision);
2262 goto lend; /* ERROR_INVALID_SID */
2263 }
2264 if (csubauth == 0)
2265 {
2266 TRACE("SubAuthorityCount is 0\n");
2267 goto lend; /* ERROR_INVALID_SID */
2268 }
2269
2270 pisid->SubAuthorityCount = csubauth;
2271
2272 /* Advance to identifier authority */
2273 while (*StringSid && *StringSid != '-')
2274 StringSid++;
2275 if (*StringSid == '-')
2276 StringSid++;
2277
2278 /* MS' implementation can't handle values greater than 2^32 - 1, so
2279 * we don't either; assume most significant bytes are always 0
2280 */
2281 pisid->IdentifierAuthority.Value[0] = 0;
2282 pisid->IdentifierAuthority.Value[1] = 0;
2283 identAuth = atoiW(StringSid);
2284 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
2285 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
2286 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
2287 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
2288
2289 /* Advance to first sub authority */
2290 while (*StringSid && *StringSid != '-')
2291 StringSid++;
2292 if (*StringSid == '-')
2293 StringSid++;
2294
2295 while (*StringSid)
2296 {
2297 pisid->SubAuthority[i++] = atoiW(StringSid);
2298
2299 while (*StringSid && *StringSid != '-')
2300 StringSid++;
2301 if (*StringSid == '-')
2302 StringSid++;
2303 }
2304
2305 if (i != pisid->SubAuthorityCount)
2306 goto lend; /* ERROR_INVALID_SID */
2307
2308 bret = TRUE;
2309 }
2310 else /* String constant format - Only available in winxp and above */
2311 {
2312 unsigned int i;
2313 pisid->Revision = SDDL_REVISION;
2314
2315 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
2316 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
2317 {
2318 DWORD j;
2319 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
2320 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
2321 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
2322 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
2323 bret = TRUE;
2324 }
2325
2326 if (!bret)
2327 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
2328 }
2329
2330 lend:
2331 if (!bret)
2332 SetLastError(ERROR_INVALID_SID);
2333
2334 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
2335 return bret;
2336 }
2337
2338 /*
2339 * @unimplemented
2340 */
2341 BOOL
2342 WINAPI
2343 GetWindowsAccountDomainSid(IN PSID pSid,
2344 OUT PSID ppDomainSid,
2345 IN OUT DWORD* cbSid)
2346 {
2347 UNIMPLEMENTED;
2348 return FALSE;
2349 }
2350
2351 /*
2352 * @unimplemented
2353 */
2354 BOOL
2355 WINAPI
2356 EqualDomainSid(IN PSID pSid1,
2357 IN PSID pSid2,
2358 OUT BOOL* pfEqual)
2359 {
2360 UNIMPLEMENTED;
2361 return FALSE;
2362 }
2363
2364 /* EOF */