[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
806 WINAPI
807 AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
808 IN HANDLE ClientToken,
809 IN DWORD DesiredAccess,
810 IN PGENERIC_MAPPING GenericMapping,
811 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
812 IN OUT LPDWORD PrivilegeSetLength,
813 OUT LPDWORD GrantedAccess,
814 OUT LPBOOL AccessStatus)
815 {
816 NTSTATUS Status;
817 NTSTATUS NtAccessStatus;
818
819 /* Do the access check */
820 Status = NtAccessCheck(pSecurityDescriptor,
821 ClientToken,
822 DesiredAccess,
823 GenericMapping,
824 PrivilegeSet,
825 (PULONG)PrivilegeSetLength,
826 (PACCESS_MASK)GrantedAccess,
827 &NtAccessStatus);
828
829 /* See if the access check operation succeeded */
830 if (!NT_SUCCESS(Status))
831 {
832 /* Check failed */
833 SetLastError(RtlNtStatusToDosError(Status));
834 return FALSE;
835 }
836
837 /* Now check the access status */
838 if (!NT_SUCCESS(NtAccessStatus))
839 {
840 /* Access denied */
841 SetLastError(RtlNtStatusToDosError(NtAccessStatus));
842 *AccessStatus = FALSE;
843 }
844 else
845 {
846 /* Access granted */
847 *AccessStatus = TRUE;
848 }
849
850 /* Check succeeded */
851 return TRUE;
852 }
853
854 /*
855 * @unimplemented
856 */
857 BOOL WINAPI AccessCheckByType(
858 PSECURITY_DESCRIPTOR pSecurityDescriptor,
859 PSID PrincipalSelfSid,
860 HANDLE ClientToken,
861 DWORD DesiredAccess,
862 POBJECT_TYPE_LIST ObjectTypeList,
863 DWORD ObjectTypeListLength,
864 PGENERIC_MAPPING GenericMapping,
865 PPRIVILEGE_SET PrivilegeSet,
866 LPDWORD PrivilegeSetLength,
867 LPDWORD GrantedAccess,
868 LPBOOL AccessStatus)
869 {
870 FIXME("stub\n");
871
872 *AccessStatus = TRUE;
873
874 return !*AccessStatus;
875 }
876
877 /**********************************************************************
878 * PrivilegeCheck EXPORTED
879 *
880 * @implemented
881 */
882 BOOL WINAPI
883 PrivilegeCheck(HANDLE ClientToken,
884 PPRIVILEGE_SET RequiredPrivileges,
885 LPBOOL pfResult)
886 {
887 BOOLEAN Result;
888 NTSTATUS Status;
889
890 Status = NtPrivilegeCheck(ClientToken,
891 RequiredPrivileges,
892 &Result);
893 if (!NT_SUCCESS(Status))
894 {
895 SetLastError(RtlNtStatusToDosError(Status));
896 return FALSE;
897 }
898
899 *pfResult = (BOOL)Result;
900
901 return TRUE;
902 }
903
904 /******************************************************************************
905 * ParseAclStringFlags
906 */
907 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
908 {
909 DWORD flags = 0;
910 LPCWSTR szAcl = *StringAcl;
911
912 while (*szAcl != '(')
913 {
914 if (*szAcl == 'P')
915 {
916 flags |= SE_DACL_PROTECTED;
917 }
918 else if (*szAcl == 'A')
919 {
920 szAcl++;
921 if (*szAcl == 'R')
922 flags |= SE_DACL_AUTO_INHERIT_REQ;
923 else if (*szAcl == 'I')
924 flags |= SE_DACL_AUTO_INHERITED;
925 }
926 szAcl++;
927 }
928
929 *StringAcl = szAcl;
930 return flags;
931 }
932
933 /******************************************************************************
934 * ParseAceStringType
935 */
936 static const ACEFLAG AceType[] =
937 {
938 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
939 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
940 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
941 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
942 /*
943 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
944 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
945 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
946 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
947 */
948 { NULL, 0 },
949 };
950
951 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
952 {
953 UINT len = 0;
954 LPCWSTR szAcl = *StringAcl;
955 const ACEFLAG *lpaf = AceType;
956
957 while (lpaf->wstr &&
958 (len = strlenW(lpaf->wstr)) &&
959 strncmpW(lpaf->wstr, szAcl, len))
960 lpaf++;
961
962 if (!lpaf->wstr)
963 return 0;
964
965 *StringAcl += len;
966 return lpaf->value;
967 }
968
969
970 /******************************************************************************
971 * ParseAceStringFlags
972 */
973 static const ACEFLAG AceFlags[] =
974 {
975 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
976 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
977 { SDDL_INHERITED, INHERITED_ACE },
978 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
979 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
980 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
981 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
982 { NULL, 0 },
983 };
984
985 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
986 {
987 UINT len = 0;
988 BYTE flags = 0;
989 LPCWSTR szAcl = *StringAcl;
990
991 while (*szAcl != ';')
992 {
993 const ACEFLAG *lpaf = AceFlags;
994
995 while (lpaf->wstr &&
996 (len = strlenW(lpaf->wstr)) &&
997 strncmpW(lpaf->wstr, szAcl, len))
998 lpaf++;
999
1000 if (!lpaf->wstr)
1001 return 0;
1002
1003 flags |= lpaf->value;
1004 szAcl += len;
1005 }
1006
1007 *StringAcl = szAcl;
1008 return flags;
1009 }
1010
1011
1012 /******************************************************************************
1013 * ParseAceStringRights
1014 */
1015 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
1016 {
1017 UINT len = 0;
1018 DWORD rights = 0;
1019 LPCWSTR szAcl = *StringAcl;
1020
1021 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
1022 {
1023 LPCWSTR p = szAcl;
1024
1025 while (*p && *p != ';')
1026 p++;
1027
1028 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
1029 {
1030 rights = strtoulW(szAcl, NULL, 16);
1031 szAcl = p;
1032 }
1033 else
1034 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
1035 }
1036 else
1037 {
1038 while (*szAcl != ';')
1039 {
1040 const ACEFLAG *lpaf = AceRights;
1041
1042 while (lpaf->wstr &&
1043 (len = strlenW(lpaf->wstr)) &&
1044 strncmpW(lpaf->wstr, szAcl, len))
1045 {
1046 lpaf++;
1047 }
1048
1049 if (!lpaf->wstr)
1050 return 0;
1051
1052 rights |= lpaf->value;
1053 szAcl += len;
1054 }
1055 }
1056
1057 *StringAcl = szAcl;
1058 return rights;
1059 }
1060
1061
1062 /******************************************************************************
1063 * ParseStringAclToAcl
1064 *
1065 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
1066 */
1067 static BOOL
1068 ParseStringAclToAcl(LPCWSTR StringAcl,
1069 LPDWORD lpdwFlags,
1070 PACL pAcl,
1071 LPDWORD cBytes)
1072 {
1073 DWORD val;
1074 DWORD sidlen;
1075 DWORD length = sizeof(ACL);
1076 DWORD acesize = 0;
1077 DWORD acecount = 0;
1078 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
1079
1080 TRACE("%s\n", debugstr_w(StringAcl));
1081
1082 if (!StringAcl)
1083 return FALSE;
1084
1085 if (pAcl) /* pAce is only useful if we're setting values */
1086 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
1087
1088 /* Parse ACL flags */
1089 *lpdwFlags = ParseAclStringFlags(&StringAcl);
1090
1091 /* Parse ACE */
1092 while (*StringAcl == '(')
1093 {
1094 StringAcl++;
1095
1096 /* Parse ACE type */
1097 val = ParseAceStringType(&StringAcl);
1098 if (pAce)
1099 pAce->Header.AceType = (BYTE) val;
1100 if (*StringAcl != ';')
1101 goto lerr;
1102 StringAcl++;
1103
1104 /* Parse ACE flags */
1105 val = ParseAceStringFlags(&StringAcl);
1106 if (pAce)
1107 pAce->Header.AceFlags = (BYTE) val;
1108 if (*StringAcl != ';')
1109 goto lerr;
1110 StringAcl++;
1111
1112 /* Parse ACE rights */
1113 val = ParseAceStringRights(&StringAcl);
1114 if (pAce)
1115 pAce->Mask = val;
1116 if (*StringAcl != ';')
1117 goto lerr;
1118 StringAcl++;
1119
1120 /* Parse ACE object guid */
1121 if (*StringAcl != ';')
1122 {
1123 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1124 goto lerr;
1125 }
1126 StringAcl++;
1127
1128 /* Parse ACE inherit object guid */
1129 if (*StringAcl != ';')
1130 {
1131 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1132 goto lerr;
1133 }
1134 StringAcl++;
1135
1136 /* Parse ACE account sid */
1137 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
1138 {
1139 while (*StringAcl && *StringAcl != ')')
1140 StringAcl++;
1141 }
1142
1143 if (*StringAcl != ')')
1144 goto lerr;
1145 StringAcl++;
1146
1147 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
1148 length += acesize;
1149 if (pAce)
1150 {
1151 pAce->Header.AceSize = acesize;
1152 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
1153 }
1154 acecount++;
1155 }
1156
1157 *cBytes = length;
1158
1159 if (length > 0xffff)
1160 {
1161 ERR("ACL too large\n");
1162 goto lerr;
1163 }
1164
1165 if (pAcl)
1166 {
1167 pAcl->AclRevision = ACL_REVISION;
1168 pAcl->Sbz1 = 0;
1169 pAcl->AclSize = length;
1170 pAcl->AceCount = acecount++;
1171 pAcl->Sbz2 = 0;
1172 }
1173 return TRUE;
1174
1175 lerr:
1176 SetLastError(ERROR_INVALID_ACL);
1177 WARN("Invalid ACE string format\n");
1178 return FALSE;
1179 }
1180
1181
1182 /******************************************************************************
1183 * ParseStringSecurityDescriptorToSecurityDescriptor
1184 */
1185 static BOOL
1186 ParseStringSecurityDescriptorToSecurityDescriptor(LPCWSTR StringSecurityDescriptor,
1187 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
1188 LPDWORD cBytes)
1189 {
1190 BOOL bret = FALSE;
1191 WCHAR toktype;
1192 WCHAR tok[MAX_PATH];
1193 LPCWSTR lptoken;
1194 LPBYTE lpNext = NULL;
1195 DWORD len;
1196
1197 *cBytes = sizeof(SECURITY_DESCRIPTOR);
1198
1199 if (SecurityDescriptor)
1200 lpNext = (LPBYTE)(SecurityDescriptor + 1);
1201
1202 while (*StringSecurityDescriptor)
1203 {
1204 toktype = *StringSecurityDescriptor;
1205
1206 /* Expect char identifier followed by ':' */
1207 StringSecurityDescriptor++;
1208 if (*StringSecurityDescriptor != ':')
1209 {
1210 SetLastError(ERROR_INVALID_PARAMETER);
1211 goto lend;
1212 }
1213 StringSecurityDescriptor++;
1214
1215 /* Extract token */
1216 lptoken = StringSecurityDescriptor;
1217 while (*lptoken && *lptoken != ':')
1218 lptoken++;
1219
1220 if (*lptoken)
1221 lptoken--;
1222
1223 len = lptoken - StringSecurityDescriptor;
1224 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
1225 tok[len] = 0;
1226
1227 switch (toktype)
1228 {
1229 case 'O':
1230 {
1231 DWORD bytes;
1232
1233 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1234 goto lend;
1235
1236 if (SecurityDescriptor)
1237 {
1238 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
1239 lpNext += bytes; /* Advance to next token */
1240 }
1241
1242 *cBytes += bytes;
1243
1244 break;
1245 }
1246
1247 case 'G':
1248 {
1249 DWORD bytes;
1250
1251 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1252 goto lend;
1253
1254 if (SecurityDescriptor)
1255 {
1256 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
1257 lpNext += bytes; /* Advance to next token */
1258 }
1259
1260 *cBytes += bytes;
1261
1262 break;
1263 }
1264
1265 case 'D':
1266 {
1267 DWORD flags;
1268 DWORD bytes;
1269
1270 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1271 goto lend;
1272
1273 if (SecurityDescriptor)
1274 {
1275 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
1276 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
1277 lpNext += bytes; /* Advance to next token */
1278 }
1279
1280 *cBytes += bytes;
1281
1282 break;
1283 }
1284
1285 case 'S':
1286 {
1287 DWORD flags;
1288 DWORD bytes;
1289
1290 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1291 goto lend;
1292
1293 if (SecurityDescriptor)
1294 {
1295 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
1296 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
1297 lpNext += bytes; /* Advance to next token */
1298 }
1299
1300 *cBytes += bytes;
1301
1302 break;
1303 }
1304
1305 default:
1306 FIXME("Unknown token\n");
1307 SetLastError(ERROR_INVALID_PARAMETER);
1308 goto lend;
1309 }
1310
1311 StringSecurityDescriptor = lptoken;
1312 }
1313
1314 bret = TRUE;
1315
1316 lend:
1317 return bret;
1318 }
1319
1320 /* Winehq cvs 20050916 */
1321 /******************************************************************************
1322 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
1323 * @implemented
1324 */
1325 BOOL
1326 WINAPI
1327 ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor,
1328 DWORD StringSDRevision,
1329 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1330 PULONG SecurityDescriptorSize)
1331 {
1332 UINT len;
1333 BOOL ret = FALSE;
1334 LPWSTR StringSecurityDescriptorW;
1335
1336 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
1337 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1338
1339 if (StringSecurityDescriptorW)
1340 {
1341 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
1342
1343 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
1344 StringSDRevision, SecurityDescriptor,
1345 SecurityDescriptorSize);
1346 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
1347 }
1348
1349 return ret;
1350 }
1351
1352 /******************************************************************************
1353 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
1354 * @implemented
1355 */
1356 BOOL WINAPI
1357 ConvertStringSecurityDescriptorToSecurityDescriptorW(LPCWSTR StringSecurityDescriptor,
1358 DWORD StringSDRevision,
1359 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1360 PULONG SecurityDescriptorSize)
1361 {
1362 DWORD cBytes;
1363 SECURITY_DESCRIPTOR* psd;
1364 BOOL bret = FALSE;
1365
1366 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
1367
1368 if (GetVersion() & 0x80000000)
1369 {
1370 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1371 goto lend;
1372 }
1373 else if (!StringSecurityDescriptor || !SecurityDescriptor)
1374 {
1375 SetLastError(ERROR_INVALID_PARAMETER);
1376 goto lend;
1377 }
1378 else if (StringSDRevision != SID_REVISION)
1379 {
1380 SetLastError(ERROR_UNKNOWN_REVISION);
1381 goto lend;
1382 }
1383
1384 /* Compute security descriptor length */
1385 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1386 NULL, &cBytes))
1387 goto lend;
1388
1389 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
1390 if (!psd) goto lend;
1391
1392 psd->Revision = SID_REVISION;
1393 psd->Control |= SE_SELF_RELATIVE;
1394
1395 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1396 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
1397 {
1398 LocalFree(psd);
1399 goto lend;
1400 }
1401
1402 if (SecurityDescriptorSize)
1403 *SecurityDescriptorSize = cBytes;
1404
1405 bret = TRUE;
1406
1407 lend:
1408 TRACE(" ret=%d\n", bret);
1409 return bret;
1410 }
1411
1412 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
1413 {
1414 if (cch == -1)
1415 cch = strlenW(string);
1416
1417 if (plen)
1418 *plen += cch;
1419
1420 if (pwptr)
1421 {
1422 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
1423 *pwptr += cch;
1424 }
1425 }
1426
1427 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
1428 {
1429 DWORD i;
1430 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
1431 WCHAR subauthfmt[] = { '-','%','u',0 };
1432 WCHAR buf[26];
1433 SID *pisid = psid;
1434
1435 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
1436 {
1437 SetLastError(ERROR_INVALID_SID);
1438 return FALSE;
1439 }
1440
1441 if (pisid->IdentifierAuthority.Value[0] ||
1442 pisid->IdentifierAuthority.Value[1])
1443 {
1444 FIXME("not matching MS' bugs\n");
1445 SetLastError(ERROR_INVALID_SID);
1446 return FALSE;
1447 }
1448
1449 sprintfW( buf, fmt, pisid->Revision,
1450 MAKELONG(
1451 MAKEWORD( pisid->IdentifierAuthority.Value[5],
1452 pisid->IdentifierAuthority.Value[4] ),
1453 MAKEWORD( pisid->IdentifierAuthority.Value[3],
1454 pisid->IdentifierAuthority.Value[2] )
1455 ) );
1456 DumpString(buf, -1, pwptr, plen);
1457
1458 for( i=0; i<pisid->SubAuthorityCount; i++ )
1459 {
1460 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
1461 DumpString(buf, -1, pwptr, plen);
1462 }
1463 return TRUE;
1464 }
1465
1466 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
1467 {
1468 size_t i;
1469 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
1470 {
1471 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
1472 {
1473 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
1474 return TRUE;
1475 }
1476 }
1477
1478 return DumpSidNumeric(psid, pwptr, plen);
1479 }
1480
1481 static const LPCWSTR AceRightBitNames[32] = {
1482 SDDL_CREATE_CHILD, /* 0 */
1483 SDDL_DELETE_CHILD,
1484 SDDL_LIST_CHILDREN,
1485 SDDL_SELF_WRITE,
1486 SDDL_READ_PROPERTY, /* 4 */
1487 SDDL_WRITE_PROPERTY,
1488 SDDL_DELETE_TREE,
1489 SDDL_LIST_OBJECT,
1490 SDDL_CONTROL_ACCESS, /* 8 */
1491 NULL,
1492 NULL,
1493 NULL,
1494 NULL, /* 12 */
1495 NULL,
1496 NULL,
1497 NULL,
1498 SDDL_STANDARD_DELETE, /* 16 */
1499 SDDL_READ_CONTROL,
1500 SDDL_WRITE_DAC,
1501 SDDL_WRITE_OWNER,
1502 NULL, /* 20 */
1503 NULL,
1504 NULL,
1505 NULL,
1506 NULL, /* 24 */
1507 NULL,
1508 NULL,
1509 NULL,
1510 SDDL_GENERIC_ALL, /* 28 */
1511 SDDL_GENERIC_EXECUTE,
1512 SDDL_GENERIC_WRITE,
1513 SDDL_GENERIC_READ
1514 };
1515
1516 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
1517 {
1518 static const WCHAR fmtW[] = {'0','x','%','x',0};
1519 WCHAR buf[15];
1520 size_t i;
1521
1522 if (mask == 0)
1523 return;
1524
1525 /* first check if the right have name */
1526 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
1527 {
1528 if (AceRights[i].wstr == NULL)
1529 break;
1530 if (mask == AceRights[i].value)
1531 {
1532 DumpString(AceRights[i].wstr, -1, pwptr, plen);
1533 return;
1534 }
1535 }
1536
1537 /* then check if it can be built from bit names */
1538 for (i = 0; i < 32; i++)
1539 {
1540 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
1541 {
1542 /* can't be built from bit names */
1543 sprintfW(buf, fmtW, mask);
1544 DumpString(buf, -1, pwptr, plen);
1545 return;
1546 }
1547 }
1548
1549 /* build from bit names */
1550 for (i = 0; i < 32; i++)
1551 if (mask & (1 << i))
1552 DumpString(AceRightBitNames[i], -1, pwptr, plen);
1553 }
1554
1555 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
1556 {
1557 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
1558 static const WCHAR openbr = '(';
1559 static const WCHAR closebr = ')';
1560 static const WCHAR semicolon = ';';
1561
1562 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
1563 {
1564 SetLastError(ERROR_INVALID_ACL);
1565 return FALSE;
1566 }
1567
1568 piace = pace;
1569 DumpString(&openbr, 1, pwptr, plen);
1570 switch (piace->Header.AceType)
1571 {
1572 case ACCESS_ALLOWED_ACE_TYPE:
1573 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
1574 break;
1575 case ACCESS_DENIED_ACE_TYPE:
1576 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
1577 break;
1578 case SYSTEM_AUDIT_ACE_TYPE:
1579 DumpString(SDDL_AUDIT, -1, pwptr, plen);
1580 break;
1581 case SYSTEM_ALARM_ACE_TYPE:
1582 DumpString(SDDL_ALARM, -1, pwptr, plen);
1583 break;
1584 }
1585 DumpString(&semicolon, 1, pwptr, plen);
1586
1587 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
1588 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
1589 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
1590 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
1591 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
1592 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
1593 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
1594 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
1595 if (piace->Header.AceFlags & INHERITED_ACE)
1596 DumpString(SDDL_INHERITED, -1, pwptr, plen);
1597 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
1598 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
1599 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
1600 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
1601 DumpString(&semicolon, 1, pwptr, plen);
1602 DumpRights(piace->Mask, pwptr, plen);
1603 DumpString(&semicolon, 1, pwptr, plen);
1604 /* objects not supported */
1605 DumpString(&semicolon, 1, pwptr, plen);
1606 /* objects not supported */
1607 DumpString(&semicolon, 1, pwptr, plen);
1608 if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
1609 return FALSE;
1610 DumpString(&closebr, 1, pwptr, plen);
1611 return TRUE;
1612 }
1613
1614 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
1615 {
1616 WORD count;
1617 int i;
1618
1619 if (protected)
1620 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
1621 if (autoInheritReq)
1622 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
1623 if (autoInherited)
1624 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
1625
1626 if (pacl == NULL)
1627 return TRUE;
1628
1629 if (!IsValidAcl(pacl))
1630 return FALSE;
1631
1632 count = pacl->AceCount;
1633 for (i = 0; i < count; i++)
1634 {
1635 LPVOID ace;
1636 if (!GetAce(pacl, i, &ace))
1637 return FALSE;
1638 if (!DumpAce(ace, pwptr, plen))
1639 return FALSE;
1640 }
1641
1642 return TRUE;
1643 }
1644
1645 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
1646 {
1647 static const WCHAR prefix[] = {'O',':',0};
1648 BOOL bDefaulted;
1649 PSID psid;
1650
1651 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
1652 return FALSE;
1653
1654 if (psid == NULL)
1655 return TRUE;
1656
1657 DumpString(prefix, -1, pwptr, plen);
1658 if (!DumpSid(psid, pwptr, plen))
1659 return FALSE;
1660 return TRUE;
1661 }
1662
1663 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
1664 {
1665 static const WCHAR prefix[] = {'G',':',0};
1666 BOOL bDefaulted;
1667 PSID psid;
1668
1669 if (!GetSecurityDescriptorGroup(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 DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
1682 {
1683 static const WCHAR dacl[] = {'D',':',0};
1684 SECURITY_DESCRIPTOR_CONTROL control;
1685 BOOL present, defaulted;
1686 DWORD revision;
1687 PACL pacl;
1688
1689 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
1690 return FALSE;
1691
1692 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
1693 return FALSE;
1694
1695 if (!present)
1696 return TRUE;
1697
1698 DumpString(dacl, 2, pwptr, plen);
1699 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
1700 return FALSE;
1701 return TRUE;
1702 }
1703
1704 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
1705 {
1706 static const WCHAR sacl[] = {'S',':',0};
1707 SECURITY_DESCRIPTOR_CONTROL control;
1708 BOOL present, defaulted;
1709 DWORD revision;
1710 PACL pacl;
1711
1712 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
1713 return FALSE;
1714
1715 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
1716 return FALSE;
1717
1718 if (!present)
1719 return TRUE;
1720
1721 DumpString(sacl, 2, pwptr, plen);
1722 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
1723 return FALSE;
1724 return TRUE;
1725 }
1726
1727 /******************************************************************************
1728 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
1729 * @implemented
1730 */
1731 BOOL WINAPI
1732 ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
1733 DWORD SDRevision,
1734 SECURITY_INFORMATION SecurityInformation,
1735 LPWSTR *OutputString,
1736 PULONG OutputLen)
1737 {
1738 ULONG len;
1739 WCHAR *wptr, *wstr;
1740
1741 if (SDRevision != SDDL_REVISION_1)
1742 {
1743 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
1744 SetLastError(ERROR_UNKNOWN_REVISION);
1745 return FALSE;
1746 }
1747
1748 len = 0;
1749 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1750 if (!DumpOwner(SecurityDescriptor, NULL, &len))
1751 return FALSE;
1752 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1753 if (!DumpGroup(SecurityDescriptor, NULL, &len))
1754 return FALSE;
1755 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1756 if (!DumpDacl(SecurityDescriptor, NULL, &len))
1757 return FALSE;
1758 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1759 if (!DumpSacl(SecurityDescriptor, NULL, &len))
1760 return FALSE;
1761
1762 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
1763 if (wstr == NULL)
1764 return FALSE;
1765
1766 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1767 if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
1768 return FALSE;
1769 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1770 if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
1771 return FALSE;
1772 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1773 if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
1774 return FALSE;
1775 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1776 if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
1777 return FALSE;
1778 *wptr = 0;
1779
1780 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
1781 *OutputString = wstr;
1782 if (OutputLen)
1783 *OutputLen = strlenW(*OutputString)+1;
1784 return TRUE;
1785 }
1786
1787 /******************************************************************************
1788 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
1789 * @implemented
1790 */
1791 BOOL WINAPI
1792 ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
1793 DWORD SDRevision,
1794 SECURITY_INFORMATION Information,
1795 LPSTR *OutputString,
1796 PULONG OutputLen)
1797 {
1798 LPWSTR wstr;
1799 ULONG len;
1800
1801 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
1802 {
1803 int lenA;
1804
1805 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
1806 *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
1807 if (*OutputString == NULL)
1808 {
1809 LocalFree(wstr);
1810 *OutputLen = 0;
1811 return FALSE;
1812 }
1813 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
1814 LocalFree(wstr);
1815
1816 if (OutputLen != NULL)
1817 *OutputLen = lenA;
1818 return TRUE;
1819 }
1820 else
1821 {
1822 *OutputString = NULL;
1823 if (OutputLen)
1824 *OutputLen = 0;
1825 return FALSE;
1826 }
1827 }
1828
1829 /*
1830 * @implemented
1831 */
1832 BOOL
1833 WINAPI
1834 ConvertStringSidToSidW(IN LPCWSTR StringSid,
1835 OUT PSID* sid)
1836 {
1837 DWORD size;
1838 DWORD i, cBytes, identAuth, csubauth;
1839 BOOL ret;
1840 SID* pisid;
1841
1842 TRACE("%s %p\n", debugstr_w(StringSid), sid);
1843
1844 if (!StringSid)
1845 {
1846 SetLastError(ERROR_INVALID_SID);
1847 return FALSE;
1848 }
1849
1850 for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
1851 {
1852 if (wcscmp(StringSid, SidTable[i].key) == 0)
1853 {
1854 WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
1855 size = SECURITY_MAX_SID_SIZE;
1856 *sid = LocalAlloc(0, size);
1857 if (!*sid)
1858 {
1859 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1860 return FALSE;
1861 }
1862 ret = CreateWellKnownSid(knownSid,
1863 NULL,
1864 *sid,
1865 &size);
1866 if (!ret)
1867 {
1868 SetLastError(ERROR_INVALID_SID);
1869 LocalFree(*sid);
1870 }
1871 return ret;
1872 }
1873 }
1874
1875 /* That's probably a string S-R-I-S-S... */
1876 if (StringSid[0] != 'S' || StringSid[1] != '-')
1877 {
1878 SetLastError(ERROR_INVALID_SID);
1879 return FALSE;
1880 }
1881
1882 cBytes = ComputeStringSidSize(StringSid);
1883 pisid = (SID*)LocalAlloc( 0, cBytes );
1884 if (!pisid)
1885 {
1886 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1887 return FALSE;
1888 }
1889 i = 0;
1890 ret = FALSE;
1891 csubauth = ((cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
1892
1893 StringSid += 2; /* Advance to Revision */
1894 pisid->Revision = atoiW(StringSid);
1895
1896 if (pisid->Revision != SDDL_REVISION)
1897 {
1898 TRACE("Revision %d is unknown\n", pisid->Revision);
1899 goto lend; /* ERROR_INVALID_SID */
1900 }
1901 if (csubauth == 0)
1902 {
1903 TRACE("SubAuthorityCount is 0\n");
1904 goto lend; /* ERROR_INVALID_SID */
1905 }
1906
1907 pisid->SubAuthorityCount = csubauth;
1908
1909 /* Advance to identifier authority */
1910 while (*StringSid && *StringSid != '-')
1911 StringSid++;
1912 if (*StringSid == '-')
1913 StringSid++;
1914
1915 /* MS' implementation can't handle values greater than 2^32 - 1, so
1916 * we don't either; assume most significant bytes are always 0
1917 */
1918 pisid->IdentifierAuthority.Value[0] = 0;
1919 pisid->IdentifierAuthority.Value[1] = 0;
1920 identAuth = atoiW(StringSid);
1921 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
1922 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
1923 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
1924 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
1925
1926 /* Advance to first sub authority */
1927 while (*StringSid && *StringSid != '-')
1928 StringSid++;
1929 if (*StringSid == '-')
1930 StringSid++;
1931
1932 while (*StringSid)
1933 {
1934 pisid->SubAuthority[i++] = atoiW(StringSid);
1935
1936 while (*StringSid && *StringSid != '-')
1937 StringSid++;
1938 if (*StringSid == '-')
1939 StringSid++;
1940 }
1941
1942 if (i != pisid->SubAuthorityCount)
1943 goto lend; /* ERROR_INVALID_SID */
1944
1945 *sid = pisid;
1946 ret = TRUE;
1947
1948 lend:
1949 if (!ret)
1950 {
1951 LocalFree(pisid);
1952 SetLastError(ERROR_INVALID_SID);
1953 }
1954
1955 TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
1956 return ret;
1957 }
1958
1959 /*
1960 * @implemented
1961 */
1962 BOOL
1963 WINAPI
1964 ConvertStringSidToSidA(IN LPCSTR StringSid,
1965 OUT PSID* sid)
1966 {
1967 BOOL bRetVal = FALSE;
1968
1969 TRACE("%s, %p\n", debugstr_a(StringSid), sid);
1970 if (GetVersion() & 0x80000000)
1971 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1972 else if (!StringSid || !sid)
1973 SetLastError(ERROR_INVALID_PARAMETER);
1974 else
1975 {
1976 UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
1977 LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1978 if (wStringSid == NULL)
1979 return FALSE;
1980 MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
1981 bRetVal = ConvertStringSidToSidW(wStringSid, sid);
1982 HeapFree(GetProcessHeap(), 0, wStringSid);
1983 }
1984 return bRetVal;
1985 }
1986
1987 /*
1988 * @implemented
1989 */
1990 BOOL
1991 WINAPI
1992 ConvertSidToStringSidW(PSID Sid,
1993 LPWSTR *StringSid)
1994 {
1995 NTSTATUS Status;
1996 UNICODE_STRING UnicodeString;
1997 WCHAR FixedBuffer[64];
1998
1999 if (!RtlValidSid(Sid))
2000 {
2001 SetLastError(ERROR_INVALID_SID);
2002 return FALSE;
2003 }
2004
2005 UnicodeString.Length = 0;
2006 UnicodeString.MaximumLength = sizeof(FixedBuffer);
2007 UnicodeString.Buffer = FixedBuffer;
2008 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
2009 if (STATUS_BUFFER_TOO_SMALL == Status)
2010 {
2011 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
2012 }
2013
2014 if (!NT_SUCCESS(Status))
2015 {
2016 SetLastError(RtlNtStatusToDosError(Status));
2017 return FALSE;
2018 }
2019
2020 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
2021 if (NULL == *StringSid)
2022 {
2023 if (UnicodeString.Buffer != FixedBuffer)
2024 {
2025 RtlFreeUnicodeString(&UnicodeString);
2026 }
2027 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2028 return FALSE;
2029 }
2030
2031 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
2032 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
2033 if (UnicodeString.Buffer != FixedBuffer)
2034 {
2035 RtlFreeUnicodeString(&UnicodeString);
2036 }
2037
2038 return TRUE;
2039 }
2040
2041 /*
2042 * @implemented
2043 */
2044 BOOL
2045 WINAPI
2046 ConvertSidToStringSidA(PSID Sid,
2047 LPSTR *StringSid)
2048 {
2049 LPWSTR StringSidW;
2050 int Len;
2051
2052 if (!ConvertSidToStringSidW(Sid, &StringSidW))
2053 {
2054 return FALSE;
2055 }
2056
2057 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
2058 if (Len <= 0)
2059 {
2060 LocalFree(StringSidW);
2061 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2062 return FALSE;
2063 }
2064
2065 *StringSid = LocalAlloc(LMEM_FIXED, Len);
2066 if (NULL == *StringSid)
2067 {
2068 LocalFree(StringSidW);
2069 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2070 return FALSE;
2071 }
2072
2073 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
2074 {
2075 LocalFree(StringSid);
2076 LocalFree(StringSidW);
2077 return FALSE;
2078 }
2079
2080 LocalFree(StringSidW);
2081
2082 return TRUE;
2083 }
2084
2085 BOOL
2086 WINAPI
2087 CreateProcessWithTokenW(IN HANDLE hToken,
2088 IN DWORD dwLogonFlags,
2089 IN LPCWSTR lpApplicationName OPTIONAL,
2090 IN OUT LPWSTR lpCommandLine OPTIONAL,
2091 IN DWORD dwCreationFlags,
2092 IN LPVOID lpEnvironment OPTIONAL,
2093 IN LPCWSTR lpCurrentDirectory OPTIONAL,
2094 IN LPSTARTUPINFOW lpStartupInfo,
2095 OUT LPPROCESS_INFORMATION lpProcessInfo)
2096 {
2097 UNIMPLEMENTED;
2098 return FALSE;
2099 }
2100
2101 /*
2102 * @implemented
2103 */
2104 BOOL WINAPI
2105 DuplicateTokenEx(IN HANDLE ExistingTokenHandle,
2106 IN DWORD dwDesiredAccess,
2107 IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL,
2108 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
2109 IN TOKEN_TYPE TokenType,
2110 OUT PHANDLE DuplicateTokenHandle)
2111 {
2112 OBJECT_ATTRIBUTES ObjectAttributes;
2113 NTSTATUS Status;
2114 SECURITY_QUALITY_OF_SERVICE Sqos;
2115
2116 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
2117 ImpersonationLevel, TokenType, DuplicateTokenHandle);
2118
2119 Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
2120 Sqos.ImpersonationLevel = ImpersonationLevel;
2121 Sqos.ContextTrackingMode = 0;
2122 Sqos.EffectiveOnly = FALSE;
2123
2124 if (lpTokenAttributes != NULL)
2125 {
2126 InitializeObjectAttributes(&ObjectAttributes,
2127 NULL,
2128 lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
2129 NULL,
2130 lpTokenAttributes->lpSecurityDescriptor);
2131 }
2132 else
2133 {
2134 InitializeObjectAttributes(&ObjectAttributes,
2135 NULL,
2136 0,
2137 NULL,
2138 NULL);
2139 }
2140
2141 ObjectAttributes.SecurityQualityOfService = &Sqos;
2142
2143 Status = NtDuplicateToken(ExistingTokenHandle,
2144 dwDesiredAccess,
2145 &ObjectAttributes,
2146 FALSE,
2147 TokenType,
2148 DuplicateTokenHandle);
2149 if (!NT_SUCCESS(Status))
2150 {
2151 ERR("NtDuplicateToken failed: Status %08x\n", Status);
2152 SetLastError(RtlNtStatusToDosError(Status));
2153 return FALSE;
2154 }
2155
2156 TRACE("Returning token %p.\n", *DuplicateTokenHandle);
2157
2158 return TRUE;
2159 }
2160
2161 /*
2162 * @implemented
2163 */
2164 BOOL WINAPI
2165 DuplicateToken(IN HANDLE ExistingTokenHandle,
2166 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
2167 OUT PHANDLE DuplicateTokenHandle)
2168 {
2169 return DuplicateTokenEx(ExistingTokenHandle,
2170 TOKEN_IMPERSONATE | TOKEN_QUERY,
2171 NULL,
2172 ImpersonationLevel,
2173 TokenImpersonation,
2174 DuplicateTokenHandle);
2175 }
2176
2177 /*
2178 * @implemented
2179 */
2180 BOOL WINAPI
2181 AllocateLocallyUniqueId(PLUID Luid)
2182 {
2183 NTSTATUS Status;
2184
2185 Status = NtAllocateLocallyUniqueId (Luid);
2186 if (!NT_SUCCESS (Status))
2187 {
2188 SetLastError(RtlNtStatusToDosError(Status));
2189 return FALSE;
2190 }
2191
2192 return TRUE;
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 */