[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 InitializeAcl(PACL pAcl,
808 DWORD nAclLength,
809 DWORD dwAclRevision)
810 {
811 NTSTATUS Status;
812
813 Status = RtlCreateAcl(pAcl,
814 nAclLength,
815 dwAclRevision);
816 if (!NT_SUCCESS(Status))
817 {
818 SetLastError(RtlNtStatusToDosError(Status));
819 return FALSE;
820 }
821
822 return TRUE;
823 }
824
825 /*
826 * @implemented
827 */
828 BOOL
829 WINAPI
830 AddAccessAllowedAce(PACL pAcl,
831 DWORD dwAceRevision,
832 DWORD AccessMask,
833 PSID pSid)
834 {
835 NTSTATUS Status;
836
837 Status = RtlAddAccessAllowedAce(pAcl,
838 dwAceRevision,
839 AccessMask,
840 pSid);
841 if (!NT_SUCCESS(Status))
842 {
843 SetLastError(RtlNtStatusToDosError(Status));
844 return FALSE;
845 }
846
847 return TRUE;
848 }
849
850 /*
851 * @implemented
852 */
853 BOOL WINAPI
854 AddAccessAllowedAceEx(PACL pAcl,
855 DWORD dwAceRevision,
856 DWORD AceFlags,
857 DWORD AccessMask,
858 PSID pSid)
859 {
860 NTSTATUS Status;
861
862 Status = RtlAddAccessAllowedAceEx(pAcl,
863 dwAceRevision,
864 AceFlags,
865 AccessMask,
866 pSid);
867 if (!NT_SUCCESS(Status))
868 {
869 SetLastError(RtlNtStatusToDosError(Status));
870 return FALSE;
871 }
872
873 return TRUE;
874 }
875
876 /*
877 * @implemented
878 */
879 BOOL
880 WINAPI
881 AddAccessDeniedAce(PACL pAcl,
882 DWORD dwAceRevision,
883 DWORD AccessMask,
884 PSID pSid)
885 {
886 NTSTATUS Status;
887
888 Status = RtlAddAccessDeniedAce(pAcl,
889 dwAceRevision,
890 AccessMask,
891 pSid);
892 if (!NT_SUCCESS(Status))
893 {
894 SetLastError(RtlNtStatusToDosError(Status));
895 return FALSE;
896 }
897
898 return TRUE;
899 }
900
901 /*
902 * @implemented
903 */
904 BOOL WINAPI
905 AddAccessDeniedAceEx(PACL pAcl,
906 DWORD dwAceRevision,
907 DWORD AceFlags,
908 DWORD AccessMask,
909 PSID pSid)
910 {
911 NTSTATUS Status;
912
913 Status = RtlAddAccessDeniedAceEx(pAcl,
914 dwAceRevision,
915 AceFlags,
916 AccessMask,
917 pSid);
918 if (!NT_SUCCESS(Status))
919 {
920 SetLastError(RtlNtStatusToDosError(Status));
921 return FALSE;
922 }
923
924 return TRUE;
925 }
926
927 /*
928 * @implemented
929 */
930 BOOL
931 WINAPI
932 AddAce(PACL pAcl,
933 DWORD dwAceRevision,
934 DWORD dwStartingAceIndex,
935 LPVOID pAceList,
936 DWORD nAceListLength)
937 {
938 NTSTATUS Status;
939
940 Status = RtlAddAce(pAcl,
941 dwAceRevision,
942 dwStartingAceIndex,
943 pAceList,
944 nAceListLength);
945 if (!NT_SUCCESS(Status))
946 {
947 SetLastError(RtlNtStatusToDosError(Status));
948 return FALSE;
949 }
950
951 return TRUE;
952 }
953
954 /*
955 * @implemented
956 */
957 BOOL
958 WINAPI
959 DeleteAce(PACL pAcl,
960 DWORD dwAceIndex)
961 {
962 NTSTATUS Status;
963
964 Status = RtlDeleteAce(pAcl,
965 dwAceIndex);
966 if (!NT_SUCCESS(Status))
967 {
968 SetLastError(RtlNtStatusToDosError(Status));
969 return FALSE;
970 }
971
972 return TRUE;
973 }
974
975 /*
976 * @implemented
977 */
978 BOOL
979 WINAPI
980 FindFirstFreeAce(PACL pAcl,
981 LPVOID *pAce)
982 {
983 return RtlFirstFreeAce(pAcl,
984 (PACE*)pAce);
985 }
986
987
988 /*
989 * @implemented
990 */
991 BOOL
992 WINAPI
993 GetAce(PACL pAcl,
994 DWORD dwAceIndex,
995 LPVOID *pAce)
996 {
997 NTSTATUS Status;
998
999 Status = RtlGetAce(pAcl,
1000 dwAceIndex,
1001 pAce);
1002 if (!NT_SUCCESS(Status))
1003 {
1004 SetLastError(RtlNtStatusToDosError(Status));
1005 return FALSE;
1006 }
1007
1008 return TRUE;
1009 }
1010
1011 /*
1012 * @implemented
1013 */
1014 BOOL
1015 WINAPI
1016 GetAclInformation(PACL pAcl,
1017 LPVOID pAclInformation,
1018 DWORD nAclInformationLength,
1019 ACL_INFORMATION_CLASS dwAclInformationClass)
1020 {
1021 NTSTATUS Status;
1022
1023 Status = RtlQueryInformationAcl(pAcl,
1024 pAclInformation,
1025 nAclInformationLength,
1026 dwAclInformationClass);
1027 if (!NT_SUCCESS(Status))
1028 {
1029 SetLastError(RtlNtStatusToDosError(Status));
1030 return FALSE;
1031 }
1032
1033 return TRUE;
1034 }
1035
1036 /*
1037 * @implemented
1038 */
1039 BOOL
1040 WINAPI
1041 IsValidAcl(PACL pAcl)
1042 {
1043 return RtlValidAcl (pAcl);
1044 }
1045
1046 /*
1047 * @implemented
1048 */
1049 BOOL WINAPI
1050 AllocateLocallyUniqueId(PLUID Luid)
1051 {
1052 NTSTATUS Status;
1053
1054 Status = NtAllocateLocallyUniqueId (Luid);
1055 if (!NT_SUCCESS (Status))
1056 {
1057 SetLastError(RtlNtStatusToDosError(Status));
1058 return FALSE;
1059 }
1060
1061 return TRUE;
1062 }
1063
1064 /*
1065 * @implemented
1066 */
1067 BOOL
1068 WINAPI
1069 AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1070 IN HANDLE ClientToken,
1071 IN DWORD DesiredAccess,
1072 IN PGENERIC_MAPPING GenericMapping,
1073 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
1074 IN OUT LPDWORD PrivilegeSetLength,
1075 OUT LPDWORD GrantedAccess,
1076 OUT LPBOOL AccessStatus)
1077 {
1078 NTSTATUS Status;
1079 NTSTATUS NtAccessStatus;
1080
1081 /* Do the access check */
1082 Status = NtAccessCheck(pSecurityDescriptor,
1083 ClientToken,
1084 DesiredAccess,
1085 GenericMapping,
1086 PrivilegeSet,
1087 (PULONG)PrivilegeSetLength,
1088 (PACCESS_MASK)GrantedAccess,
1089 &NtAccessStatus);
1090
1091 /* See if the access check operation succeeded */
1092 if (!NT_SUCCESS(Status))
1093 {
1094 /* Check failed */
1095 SetLastError(RtlNtStatusToDosError(Status));
1096 return FALSE;
1097 }
1098
1099 /* Now check the access status */
1100 if (!NT_SUCCESS(NtAccessStatus))
1101 {
1102 /* Access denied */
1103 SetLastError(RtlNtStatusToDosError(NtAccessStatus));
1104 *AccessStatus = FALSE;
1105 }
1106 else
1107 {
1108 /* Access granted */
1109 *AccessStatus = TRUE;
1110 }
1111
1112 /* Check succeeded */
1113 return TRUE;
1114 }
1115
1116 /*
1117 * @unimplemented
1118 */
1119 BOOL WINAPI AccessCheckByType(
1120 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1121 PSID PrincipalSelfSid,
1122 HANDLE ClientToken,
1123 DWORD DesiredAccess,
1124 POBJECT_TYPE_LIST ObjectTypeList,
1125 DWORD ObjectTypeListLength,
1126 PGENERIC_MAPPING GenericMapping,
1127 PPRIVILEGE_SET PrivilegeSet,
1128 LPDWORD PrivilegeSetLength,
1129 LPDWORD GrantedAccess,
1130 LPBOOL AccessStatus)
1131 {
1132 FIXME("stub\n");
1133
1134 *AccessStatus = TRUE;
1135
1136 return !*AccessStatus;
1137 }
1138
1139 /*
1140 * @implemented
1141 */
1142 BOOL
1143 WINAPI
1144 AddAuditAccessAce(PACL pAcl,
1145 DWORD dwAceRevision,
1146 DWORD dwAccessMask,
1147 PSID pSid,
1148 BOOL bAuditSuccess,
1149 BOOL bAuditFailure)
1150 {
1151 NTSTATUS Status;
1152
1153 Status = RtlAddAuditAccessAce(pAcl,
1154 dwAceRevision,
1155 dwAccessMask,
1156 pSid,
1157 bAuditSuccess,
1158 bAuditFailure);
1159 if (!NT_SUCCESS(Status))
1160 {
1161 SetLastError(RtlNtStatusToDosError(Status));
1162 return FALSE;
1163 }
1164
1165 return TRUE;
1166 }
1167
1168 /*
1169 * @implemented
1170 */
1171 BOOL WINAPI
1172 AddAuditAccessAceEx(PACL pAcl,
1173 DWORD dwAceRevision,
1174 DWORD AceFlags,
1175 DWORD dwAccessMask,
1176 PSID pSid,
1177 BOOL bAuditSuccess,
1178 BOOL bAuditFailure)
1179 {
1180 NTSTATUS Status;
1181
1182 Status = RtlAddAuditAccessAceEx(pAcl,
1183 dwAceRevision,
1184 AceFlags,
1185 dwAccessMask,
1186 pSid,
1187 bAuditSuccess,
1188 bAuditFailure);
1189 if (!NT_SUCCESS(Status))
1190 {
1191 SetLastError(RtlNtStatusToDosError(Status));
1192 return FALSE;
1193 }
1194
1195 return TRUE;
1196 }
1197
1198 /**********************************************************************
1199 * PrivilegeCheck EXPORTED
1200 *
1201 * @implemented
1202 */
1203 BOOL WINAPI
1204 PrivilegeCheck(HANDLE ClientToken,
1205 PPRIVILEGE_SET RequiredPrivileges,
1206 LPBOOL pfResult)
1207 {
1208 BOOLEAN Result;
1209 NTSTATUS Status;
1210
1211 Status = NtPrivilegeCheck(ClientToken,
1212 RequiredPrivileges,
1213 &Result);
1214 if (!NT_SUCCESS(Status))
1215 {
1216 SetLastError(RtlNtStatusToDosError(Status));
1217 return FALSE;
1218 }
1219
1220 *pfResult = (BOOL)Result;
1221
1222 return TRUE;
1223 }
1224
1225 /*
1226 * @implemented
1227 */
1228 BOOL
1229 WINAPI
1230 SetAclInformation(PACL pAcl,
1231 LPVOID pAclInformation,
1232 DWORD nAclInformationLength,
1233 ACL_INFORMATION_CLASS dwAclInformationClass)
1234 {
1235 NTSTATUS Status;
1236
1237 Status = RtlSetInformationAcl(pAcl,
1238 pAclInformation,
1239 nAclInformationLength,
1240 dwAclInformationClass);
1241 if (!NT_SUCCESS(Status))
1242 {
1243 SetLastError(RtlNtStatusToDosError(Status));
1244 return FALSE;
1245 }
1246
1247 return TRUE;
1248 }
1249
1250 /******************************************************************************
1251 * ParseAclStringFlags
1252 */
1253 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
1254 {
1255 DWORD flags = 0;
1256 LPCWSTR szAcl = *StringAcl;
1257
1258 while (*szAcl != '(')
1259 {
1260 if (*szAcl == 'P')
1261 {
1262 flags |= SE_DACL_PROTECTED;
1263 }
1264 else if (*szAcl == 'A')
1265 {
1266 szAcl++;
1267 if (*szAcl == 'R')
1268 flags |= SE_DACL_AUTO_INHERIT_REQ;
1269 else if (*szAcl == 'I')
1270 flags |= SE_DACL_AUTO_INHERITED;
1271 }
1272 szAcl++;
1273 }
1274
1275 *StringAcl = szAcl;
1276 return flags;
1277 }
1278
1279 /******************************************************************************
1280 * ParseAceStringType
1281 */
1282 static const ACEFLAG AceType[] =
1283 {
1284 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
1285 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
1286 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
1287 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
1288 /*
1289 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
1290 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
1291 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
1292 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
1293 */
1294 { NULL, 0 },
1295 };
1296
1297 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
1298 {
1299 UINT len = 0;
1300 LPCWSTR szAcl = *StringAcl;
1301 const ACEFLAG *lpaf = AceType;
1302
1303 while (lpaf->wstr &&
1304 (len = strlenW(lpaf->wstr)) &&
1305 strncmpW(lpaf->wstr, szAcl, len))
1306 lpaf++;
1307
1308 if (!lpaf->wstr)
1309 return 0;
1310
1311 *StringAcl += len;
1312 return lpaf->value;
1313 }
1314
1315
1316 /******************************************************************************
1317 * ParseAceStringFlags
1318 */
1319 static const ACEFLAG AceFlags[] =
1320 {
1321 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
1322 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
1323 { SDDL_INHERITED, INHERITED_ACE },
1324 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
1325 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
1326 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
1327 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
1328 { NULL, 0 },
1329 };
1330
1331 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
1332 {
1333 UINT len = 0;
1334 BYTE flags = 0;
1335 LPCWSTR szAcl = *StringAcl;
1336
1337 while (*szAcl != ';')
1338 {
1339 const ACEFLAG *lpaf = AceFlags;
1340
1341 while (lpaf->wstr &&
1342 (len = strlenW(lpaf->wstr)) &&
1343 strncmpW(lpaf->wstr, szAcl, len))
1344 lpaf++;
1345
1346 if (!lpaf->wstr)
1347 return 0;
1348
1349 flags |= lpaf->value;
1350 szAcl += len;
1351 }
1352
1353 *StringAcl = szAcl;
1354 return flags;
1355 }
1356
1357
1358 /******************************************************************************
1359 * ParseAceStringRights
1360 */
1361 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
1362 {
1363 UINT len = 0;
1364 DWORD rights = 0;
1365 LPCWSTR szAcl = *StringAcl;
1366
1367 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
1368 {
1369 LPCWSTR p = szAcl;
1370
1371 while (*p && *p != ';')
1372 p++;
1373
1374 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
1375 {
1376 rights = strtoulW(szAcl, NULL, 16);
1377 szAcl = p;
1378 }
1379 else
1380 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
1381 }
1382 else
1383 {
1384 while (*szAcl != ';')
1385 {
1386 const ACEFLAG *lpaf = AceRights;
1387
1388 while (lpaf->wstr &&
1389 (len = strlenW(lpaf->wstr)) &&
1390 strncmpW(lpaf->wstr, szAcl, len))
1391 {
1392 lpaf++;
1393 }
1394
1395 if (!lpaf->wstr)
1396 return 0;
1397
1398 rights |= lpaf->value;
1399 szAcl += len;
1400 }
1401 }
1402
1403 *StringAcl = szAcl;
1404 return rights;
1405 }
1406
1407
1408 /******************************************************************************
1409 * ParseStringAclToAcl
1410 *
1411 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
1412 */
1413 static BOOL
1414 ParseStringAclToAcl(LPCWSTR StringAcl,
1415 LPDWORD lpdwFlags,
1416 PACL pAcl,
1417 LPDWORD cBytes)
1418 {
1419 DWORD val;
1420 DWORD sidlen;
1421 DWORD length = sizeof(ACL);
1422 DWORD acesize = 0;
1423 DWORD acecount = 0;
1424 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
1425
1426 TRACE("%s\n", debugstr_w(StringAcl));
1427
1428 if (!StringAcl)
1429 return FALSE;
1430
1431 if (pAcl) /* pAce is only useful if we're setting values */
1432 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
1433
1434 /* Parse ACL flags */
1435 *lpdwFlags = ParseAclStringFlags(&StringAcl);
1436
1437 /* Parse ACE */
1438 while (*StringAcl == '(')
1439 {
1440 StringAcl++;
1441
1442 /* Parse ACE type */
1443 val = ParseAceStringType(&StringAcl);
1444 if (pAce)
1445 pAce->Header.AceType = (BYTE) val;
1446 if (*StringAcl != ';')
1447 goto lerr;
1448 StringAcl++;
1449
1450 /* Parse ACE flags */
1451 val = ParseAceStringFlags(&StringAcl);
1452 if (pAce)
1453 pAce->Header.AceFlags = (BYTE) val;
1454 if (*StringAcl != ';')
1455 goto lerr;
1456 StringAcl++;
1457
1458 /* Parse ACE rights */
1459 val = ParseAceStringRights(&StringAcl);
1460 if (pAce)
1461 pAce->Mask = val;
1462 if (*StringAcl != ';')
1463 goto lerr;
1464 StringAcl++;
1465
1466 /* Parse ACE object guid */
1467 if (*StringAcl != ';')
1468 {
1469 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1470 goto lerr;
1471 }
1472 StringAcl++;
1473
1474 /* Parse ACE inherit object guid */
1475 if (*StringAcl != ';')
1476 {
1477 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
1478 goto lerr;
1479 }
1480 StringAcl++;
1481
1482 /* Parse ACE account sid */
1483 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
1484 {
1485 while (*StringAcl && *StringAcl != ')')
1486 StringAcl++;
1487 }
1488
1489 if (*StringAcl != ')')
1490 goto lerr;
1491 StringAcl++;
1492
1493 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
1494 length += acesize;
1495 if (pAce)
1496 {
1497 pAce->Header.AceSize = acesize;
1498 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
1499 }
1500 acecount++;
1501 }
1502
1503 *cBytes = length;
1504
1505 if (length > 0xffff)
1506 {
1507 ERR("ACL too large\n");
1508 goto lerr;
1509 }
1510
1511 if (pAcl)
1512 {
1513 pAcl->AclRevision = ACL_REVISION;
1514 pAcl->Sbz1 = 0;
1515 pAcl->AclSize = length;
1516 pAcl->AceCount = acecount++;
1517 pAcl->Sbz2 = 0;
1518 }
1519 return TRUE;
1520
1521 lerr:
1522 SetLastError(ERROR_INVALID_ACL);
1523 WARN("Invalid ACE string format\n");
1524 return FALSE;
1525 }
1526
1527
1528 /******************************************************************************
1529 * ParseStringSecurityDescriptorToSecurityDescriptor
1530 */
1531 static BOOL
1532 ParseStringSecurityDescriptorToSecurityDescriptor(LPCWSTR StringSecurityDescriptor,
1533 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
1534 LPDWORD cBytes)
1535 {
1536 BOOL bret = FALSE;
1537 WCHAR toktype;
1538 WCHAR tok[MAX_PATH];
1539 LPCWSTR lptoken;
1540 LPBYTE lpNext = NULL;
1541 DWORD len;
1542
1543 *cBytes = sizeof(SECURITY_DESCRIPTOR);
1544
1545 if (SecurityDescriptor)
1546 lpNext = (LPBYTE)(SecurityDescriptor + 1);
1547
1548 while (*StringSecurityDescriptor)
1549 {
1550 toktype = *StringSecurityDescriptor;
1551
1552 /* Expect char identifier followed by ':' */
1553 StringSecurityDescriptor++;
1554 if (*StringSecurityDescriptor != ':')
1555 {
1556 SetLastError(ERROR_INVALID_PARAMETER);
1557 goto lend;
1558 }
1559 StringSecurityDescriptor++;
1560
1561 /* Extract token */
1562 lptoken = StringSecurityDescriptor;
1563 while (*lptoken && *lptoken != ':')
1564 lptoken++;
1565
1566 if (*lptoken)
1567 lptoken--;
1568
1569 len = lptoken - StringSecurityDescriptor;
1570 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
1571 tok[len] = 0;
1572
1573 switch (toktype)
1574 {
1575 case 'O':
1576 {
1577 DWORD bytes;
1578
1579 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1580 goto lend;
1581
1582 if (SecurityDescriptor)
1583 {
1584 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
1585 lpNext += bytes; /* Advance to next token */
1586 }
1587
1588 *cBytes += bytes;
1589
1590 break;
1591 }
1592
1593 case 'G':
1594 {
1595 DWORD bytes;
1596
1597 if (!ParseStringSidToSid(tok, lpNext, &bytes))
1598 goto lend;
1599
1600 if (SecurityDescriptor)
1601 {
1602 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
1603 lpNext += bytes; /* Advance to next token */
1604 }
1605
1606 *cBytes += bytes;
1607
1608 break;
1609 }
1610
1611 case 'D':
1612 {
1613 DWORD flags;
1614 DWORD bytes;
1615
1616 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1617 goto lend;
1618
1619 if (SecurityDescriptor)
1620 {
1621 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
1622 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
1623 lpNext += bytes; /* Advance to next token */
1624 }
1625
1626 *cBytes += bytes;
1627
1628 break;
1629 }
1630
1631 case 'S':
1632 {
1633 DWORD flags;
1634 DWORD bytes;
1635
1636 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
1637 goto lend;
1638
1639 if (SecurityDescriptor)
1640 {
1641 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
1642 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
1643 lpNext += bytes; /* Advance to next token */
1644 }
1645
1646 *cBytes += bytes;
1647
1648 break;
1649 }
1650
1651 default:
1652 FIXME("Unknown token\n");
1653 SetLastError(ERROR_INVALID_PARAMETER);
1654 goto lend;
1655 }
1656
1657 StringSecurityDescriptor = lptoken;
1658 }
1659
1660 bret = TRUE;
1661
1662 lend:
1663 return bret;
1664 }
1665
1666 /* Winehq cvs 20050916 */
1667 /******************************************************************************
1668 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
1669 * @implemented
1670 */
1671 BOOL
1672 WINAPI
1673 ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor,
1674 DWORD StringSDRevision,
1675 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1676 PULONG SecurityDescriptorSize)
1677 {
1678 UINT len;
1679 BOOL ret = FALSE;
1680 LPWSTR StringSecurityDescriptorW;
1681
1682 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
1683 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1684
1685 if (StringSecurityDescriptorW)
1686 {
1687 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
1688
1689 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
1690 StringSDRevision, SecurityDescriptor,
1691 SecurityDescriptorSize);
1692 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
1693 }
1694
1695 return ret;
1696 }
1697
1698 /******************************************************************************
1699 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
1700 * @implemented
1701 */
1702 BOOL WINAPI
1703 ConvertStringSecurityDescriptorToSecurityDescriptorW(LPCWSTR StringSecurityDescriptor,
1704 DWORD StringSDRevision,
1705 PSECURITY_DESCRIPTOR* SecurityDescriptor,
1706 PULONG SecurityDescriptorSize)
1707 {
1708 DWORD cBytes;
1709 SECURITY_DESCRIPTOR* psd;
1710 BOOL bret = FALSE;
1711
1712 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
1713
1714 if (GetVersion() & 0x80000000)
1715 {
1716 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1717 goto lend;
1718 }
1719 else if (!StringSecurityDescriptor || !SecurityDescriptor)
1720 {
1721 SetLastError(ERROR_INVALID_PARAMETER);
1722 goto lend;
1723 }
1724 else if (StringSDRevision != SID_REVISION)
1725 {
1726 SetLastError(ERROR_UNKNOWN_REVISION);
1727 goto lend;
1728 }
1729
1730 /* Compute security descriptor length */
1731 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1732 NULL, &cBytes))
1733 goto lend;
1734
1735 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
1736 if (!psd) goto lend;
1737
1738 psd->Revision = SID_REVISION;
1739 psd->Control |= SE_SELF_RELATIVE;
1740
1741 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
1742 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
1743 {
1744 LocalFree(psd);
1745 goto lend;
1746 }
1747
1748 if (SecurityDescriptorSize)
1749 *SecurityDescriptorSize = cBytes;
1750
1751 bret = TRUE;
1752
1753 lend:
1754 TRACE(" ret=%d\n", bret);
1755 return bret;
1756 }
1757
1758 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
1759 {
1760 if (cch == -1)
1761 cch = strlenW(string);
1762
1763 if (plen)
1764 *plen += cch;
1765
1766 if (pwptr)
1767 {
1768 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
1769 *pwptr += cch;
1770 }
1771 }
1772
1773 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
1774 {
1775 DWORD i;
1776 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
1777 WCHAR subauthfmt[] = { '-','%','u',0 };
1778 WCHAR buf[26];
1779 SID *pisid = psid;
1780
1781 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
1782 {
1783 SetLastError(ERROR_INVALID_SID);
1784 return FALSE;
1785 }
1786
1787 if (pisid->IdentifierAuthority.Value[0] ||
1788 pisid->IdentifierAuthority.Value[1])
1789 {
1790 FIXME("not matching MS' bugs\n");
1791 SetLastError(ERROR_INVALID_SID);
1792 return FALSE;
1793 }
1794
1795 sprintfW( buf, fmt, pisid->Revision,
1796 MAKELONG(
1797 MAKEWORD( pisid->IdentifierAuthority.Value[5],
1798 pisid->IdentifierAuthority.Value[4] ),
1799 MAKEWORD( pisid->IdentifierAuthority.Value[3],
1800 pisid->IdentifierAuthority.Value[2] )
1801 ) );
1802 DumpString(buf, -1, pwptr, plen);
1803
1804 for( i=0; i<pisid->SubAuthorityCount; i++ )
1805 {
1806 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
1807 DumpString(buf, -1, pwptr, plen);
1808 }
1809 return TRUE;
1810 }
1811
1812 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
1813 {
1814 size_t i;
1815 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
1816 {
1817 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
1818 {
1819 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
1820 return TRUE;
1821 }
1822 }
1823
1824 return DumpSidNumeric(psid, pwptr, plen);
1825 }
1826
1827 static const LPCWSTR AceRightBitNames[32] = {
1828 SDDL_CREATE_CHILD, /* 0 */
1829 SDDL_DELETE_CHILD,
1830 SDDL_LIST_CHILDREN,
1831 SDDL_SELF_WRITE,
1832 SDDL_READ_PROPERTY, /* 4 */
1833 SDDL_WRITE_PROPERTY,
1834 SDDL_DELETE_TREE,
1835 SDDL_LIST_OBJECT,
1836 SDDL_CONTROL_ACCESS, /* 8 */
1837 NULL,
1838 NULL,
1839 NULL,
1840 NULL, /* 12 */
1841 NULL,
1842 NULL,
1843 NULL,
1844 SDDL_STANDARD_DELETE, /* 16 */
1845 SDDL_READ_CONTROL,
1846 SDDL_WRITE_DAC,
1847 SDDL_WRITE_OWNER,
1848 NULL, /* 20 */
1849 NULL,
1850 NULL,
1851 NULL,
1852 NULL, /* 24 */
1853 NULL,
1854 NULL,
1855 NULL,
1856 SDDL_GENERIC_ALL, /* 28 */
1857 SDDL_GENERIC_EXECUTE,
1858 SDDL_GENERIC_WRITE,
1859 SDDL_GENERIC_READ
1860 };
1861
1862 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
1863 {
1864 static const WCHAR fmtW[] = {'0','x','%','x',0};
1865 WCHAR buf[15];
1866 size_t i;
1867
1868 if (mask == 0)
1869 return;
1870
1871 /* first check if the right have name */
1872 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
1873 {
1874 if (AceRights[i].wstr == NULL)
1875 break;
1876 if (mask == AceRights[i].value)
1877 {
1878 DumpString(AceRights[i].wstr, -1, pwptr, plen);
1879 return;
1880 }
1881 }
1882
1883 /* then check if it can be built from bit names */
1884 for (i = 0; i < 32; i++)
1885 {
1886 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
1887 {
1888 /* can't be built from bit names */
1889 sprintfW(buf, fmtW, mask);
1890 DumpString(buf, -1, pwptr, plen);
1891 return;
1892 }
1893 }
1894
1895 /* build from bit names */
1896 for (i = 0; i < 32; i++)
1897 if (mask & (1 << i))
1898 DumpString(AceRightBitNames[i], -1, pwptr, plen);
1899 }
1900
1901 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
1902 {
1903 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
1904 static const WCHAR openbr = '(';
1905 static const WCHAR closebr = ')';
1906 static const WCHAR semicolon = ';';
1907
1908 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
1909 {
1910 SetLastError(ERROR_INVALID_ACL);
1911 return FALSE;
1912 }
1913
1914 piace = pace;
1915 DumpString(&openbr, 1, pwptr, plen);
1916 switch (piace->Header.AceType)
1917 {
1918 case ACCESS_ALLOWED_ACE_TYPE:
1919 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
1920 break;
1921 case ACCESS_DENIED_ACE_TYPE:
1922 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
1923 break;
1924 case SYSTEM_AUDIT_ACE_TYPE:
1925 DumpString(SDDL_AUDIT, -1, pwptr, plen);
1926 break;
1927 case SYSTEM_ALARM_ACE_TYPE:
1928 DumpString(SDDL_ALARM, -1, pwptr, plen);
1929 break;
1930 }
1931 DumpString(&semicolon, 1, pwptr, plen);
1932
1933 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
1934 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
1935 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
1936 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
1937 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
1938 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
1939 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
1940 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
1941 if (piace->Header.AceFlags & INHERITED_ACE)
1942 DumpString(SDDL_INHERITED, -1, pwptr, plen);
1943 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
1944 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
1945 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
1946 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
1947 DumpString(&semicolon, 1, pwptr, plen);
1948 DumpRights(piace->Mask, pwptr, plen);
1949 DumpString(&semicolon, 1, pwptr, plen);
1950 /* objects not supported */
1951 DumpString(&semicolon, 1, pwptr, plen);
1952 /* objects not supported */
1953 DumpString(&semicolon, 1, pwptr, plen);
1954 if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
1955 return FALSE;
1956 DumpString(&closebr, 1, pwptr, plen);
1957 return TRUE;
1958 }
1959
1960 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
1961 {
1962 WORD count;
1963 int i;
1964
1965 if (protected)
1966 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
1967 if (autoInheritReq)
1968 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
1969 if (autoInherited)
1970 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
1971
1972 if (pacl == NULL)
1973 return TRUE;
1974
1975 if (!IsValidAcl(pacl))
1976 return FALSE;
1977
1978 count = pacl->AceCount;
1979 for (i = 0; i < count; i++)
1980 {
1981 LPVOID ace;
1982 if (!GetAce(pacl, i, &ace))
1983 return FALSE;
1984 if (!DumpAce(ace, pwptr, plen))
1985 return FALSE;
1986 }
1987
1988 return TRUE;
1989 }
1990
1991 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
1992 {
1993 static const WCHAR prefix[] = {'O',':',0};
1994 BOOL bDefaulted;
1995 PSID psid;
1996
1997 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
1998 return FALSE;
1999
2000 if (psid == NULL)
2001 return TRUE;
2002
2003 DumpString(prefix, -1, pwptr, plen);
2004 if (!DumpSid(psid, pwptr, plen))
2005 return FALSE;
2006 return TRUE;
2007 }
2008
2009 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
2010 {
2011 static const WCHAR prefix[] = {'G',':',0};
2012 BOOL bDefaulted;
2013 PSID psid;
2014
2015 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
2016 return FALSE;
2017
2018 if (psid == NULL)
2019 return TRUE;
2020
2021 DumpString(prefix, -1, pwptr, plen);
2022 if (!DumpSid(psid, pwptr, plen))
2023 return FALSE;
2024 return TRUE;
2025 }
2026
2027 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
2028 {
2029 static const WCHAR dacl[] = {'D',':',0};
2030 SECURITY_DESCRIPTOR_CONTROL control;
2031 BOOL present, defaulted;
2032 DWORD revision;
2033 PACL pacl;
2034
2035 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
2036 return FALSE;
2037
2038 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
2039 return FALSE;
2040
2041 if (!present)
2042 return TRUE;
2043
2044 DumpString(dacl, 2, pwptr, plen);
2045 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
2046 return FALSE;
2047 return TRUE;
2048 }
2049
2050 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
2051 {
2052 static const WCHAR sacl[] = {'S',':',0};
2053 SECURITY_DESCRIPTOR_CONTROL control;
2054 BOOL present, defaulted;
2055 DWORD revision;
2056 PACL pacl;
2057
2058 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
2059 return FALSE;
2060
2061 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
2062 return FALSE;
2063
2064 if (!present)
2065 return TRUE;
2066
2067 DumpString(sacl, 2, pwptr, plen);
2068 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
2069 return FALSE;
2070 return TRUE;
2071 }
2072
2073 /******************************************************************************
2074 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
2075 * @implemented
2076 */
2077 BOOL WINAPI
2078 ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
2079 DWORD SDRevision,
2080 SECURITY_INFORMATION SecurityInformation,
2081 LPWSTR *OutputString,
2082 PULONG OutputLen)
2083 {
2084 ULONG len;
2085 WCHAR *wptr, *wstr;
2086
2087 if (SDRevision != SDDL_REVISION_1)
2088 {
2089 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
2090 SetLastError(ERROR_UNKNOWN_REVISION);
2091 return FALSE;
2092 }
2093
2094 len = 0;
2095 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
2096 if (!DumpOwner(SecurityDescriptor, NULL, &len))
2097 return FALSE;
2098 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
2099 if (!DumpGroup(SecurityDescriptor, NULL, &len))
2100 return FALSE;
2101 if (SecurityInformation & DACL_SECURITY_INFORMATION)
2102 if (!DumpDacl(SecurityDescriptor, NULL, &len))
2103 return FALSE;
2104 if (SecurityInformation & SACL_SECURITY_INFORMATION)
2105 if (!DumpSacl(SecurityDescriptor, NULL, &len))
2106 return FALSE;
2107
2108 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
2109 if (wstr == NULL)
2110 return FALSE;
2111
2112 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
2113 if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
2114 return FALSE;
2115 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
2116 if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
2117 return FALSE;
2118 if (SecurityInformation & DACL_SECURITY_INFORMATION)
2119 if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
2120 return FALSE;
2121 if (SecurityInformation & SACL_SECURITY_INFORMATION)
2122 if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
2123 return FALSE;
2124 *wptr = 0;
2125
2126 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
2127 *OutputString = wstr;
2128 if (OutputLen)
2129 *OutputLen = strlenW(*OutputString)+1;
2130 return TRUE;
2131 }
2132
2133 /******************************************************************************
2134 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
2135 * @implemented
2136 */
2137 BOOL WINAPI
2138 ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
2139 DWORD SDRevision,
2140 SECURITY_INFORMATION Information,
2141 LPSTR *OutputString,
2142 PULONG OutputLen)
2143 {
2144 LPWSTR wstr;
2145 ULONG len;
2146
2147 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
2148 {
2149 int lenA;
2150
2151 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
2152 *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
2153 if (*OutputString == NULL)
2154 {
2155 LocalFree(wstr);
2156 *OutputLen = 0;
2157 return FALSE;
2158 }
2159 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
2160 LocalFree(wstr);
2161
2162 if (OutputLen != NULL)
2163 *OutputLen = lenA;
2164 return TRUE;
2165 }
2166 else
2167 {
2168 *OutputString = NULL;
2169 if (OutputLen)
2170 *OutputLen = 0;
2171 return FALSE;
2172 }
2173 }
2174
2175 /*
2176 * @implemented
2177 */
2178 BOOL
2179 WINAPI
2180 ConvertStringSidToSidW(IN LPCWSTR StringSid,
2181 OUT PSID* sid)
2182 {
2183 DWORD size;
2184 DWORD i, cBytes, identAuth, csubauth;
2185 BOOL ret;
2186 SID* pisid;
2187
2188 TRACE("%s %p\n", debugstr_w(StringSid), sid);
2189
2190 if (!StringSid)
2191 {
2192 SetLastError(ERROR_INVALID_SID);
2193 return FALSE;
2194 }
2195
2196 for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
2197 {
2198 if (wcscmp(StringSid, SidTable[i].key) == 0)
2199 {
2200 WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
2201 size = SECURITY_MAX_SID_SIZE;
2202 *sid = LocalAlloc(0, size);
2203 if (!*sid)
2204 {
2205 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2206 return FALSE;
2207 }
2208 ret = CreateWellKnownSid(knownSid,
2209 NULL,
2210 *sid,
2211 &size);
2212 if (!ret)
2213 {
2214 SetLastError(ERROR_INVALID_SID);
2215 LocalFree(*sid);
2216 }
2217 return ret;
2218 }
2219 }
2220
2221 /* That's probably a string S-R-I-S-S... */
2222 if (StringSid[0] != 'S' || StringSid[1] != '-')
2223 {
2224 SetLastError(ERROR_INVALID_SID);
2225 return FALSE;
2226 }
2227
2228 cBytes = ComputeStringSidSize(StringSid);
2229 pisid = (SID*)LocalAlloc( 0, cBytes );
2230 if (!pisid)
2231 {
2232 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2233 return FALSE;
2234 }
2235 i = 0;
2236 ret = FALSE;
2237 csubauth = ((cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
2238
2239 StringSid += 2; /* Advance to Revision */
2240 pisid->Revision = atoiW(StringSid);
2241
2242 if (pisid->Revision != SDDL_REVISION)
2243 {
2244 TRACE("Revision %d is unknown\n", pisid->Revision);
2245 goto lend; /* ERROR_INVALID_SID */
2246 }
2247 if (csubauth == 0)
2248 {
2249 TRACE("SubAuthorityCount is 0\n");
2250 goto lend; /* ERROR_INVALID_SID */
2251 }
2252
2253 pisid->SubAuthorityCount = csubauth;
2254
2255 /* Advance to identifier authority */
2256 while (*StringSid && *StringSid != '-')
2257 StringSid++;
2258 if (*StringSid == '-')
2259 StringSid++;
2260
2261 /* MS' implementation can't handle values greater than 2^32 - 1, so
2262 * we don't either; assume most significant bytes are always 0
2263 */
2264 pisid->IdentifierAuthority.Value[0] = 0;
2265 pisid->IdentifierAuthority.Value[1] = 0;
2266 identAuth = atoiW(StringSid);
2267 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
2268 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
2269 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
2270 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
2271
2272 /* Advance to first sub authority */
2273 while (*StringSid && *StringSid != '-')
2274 StringSid++;
2275 if (*StringSid == '-')
2276 StringSid++;
2277
2278 while (*StringSid)
2279 {
2280 pisid->SubAuthority[i++] = atoiW(StringSid);
2281
2282 while (*StringSid && *StringSid != '-')
2283 StringSid++;
2284 if (*StringSid == '-')
2285 StringSid++;
2286 }
2287
2288 if (i != pisid->SubAuthorityCount)
2289 goto lend; /* ERROR_INVALID_SID */
2290
2291 *sid = pisid;
2292 ret = TRUE;
2293
2294 lend:
2295 if (!ret)
2296 {
2297 LocalFree(pisid);
2298 SetLastError(ERROR_INVALID_SID);
2299 }
2300
2301 TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
2302 return ret;
2303 }
2304
2305 /*
2306 * @implemented
2307 */
2308 BOOL
2309 WINAPI
2310 ConvertStringSidToSidA(IN LPCSTR StringSid,
2311 OUT PSID* sid)
2312 {
2313 BOOL bRetVal = FALSE;
2314
2315 TRACE("%s, %p\n", debugstr_a(StringSid), sid);
2316 if (GetVersion() & 0x80000000)
2317 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2318 else if (!StringSid || !sid)
2319 SetLastError(ERROR_INVALID_PARAMETER);
2320 else
2321 {
2322 UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
2323 LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2324 if (wStringSid == NULL)
2325 return FALSE;
2326 MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
2327 bRetVal = ConvertStringSidToSidW(wStringSid, sid);
2328 HeapFree(GetProcessHeap(), 0, wStringSid);
2329 }
2330 return bRetVal;
2331 }
2332
2333 /*
2334 * @implemented
2335 */
2336 BOOL
2337 WINAPI
2338 ConvertSidToStringSidW(PSID Sid,
2339 LPWSTR *StringSid)
2340 {
2341 NTSTATUS Status;
2342 UNICODE_STRING UnicodeString;
2343 WCHAR FixedBuffer[64];
2344
2345 if (!RtlValidSid(Sid))
2346 {
2347 SetLastError(ERROR_INVALID_SID);
2348 return FALSE;
2349 }
2350
2351 UnicodeString.Length = 0;
2352 UnicodeString.MaximumLength = sizeof(FixedBuffer);
2353 UnicodeString.Buffer = FixedBuffer;
2354 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
2355 if (STATUS_BUFFER_TOO_SMALL == Status)
2356 {
2357 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
2358 }
2359
2360 if (!NT_SUCCESS(Status))
2361 {
2362 SetLastError(RtlNtStatusToDosError(Status));
2363 return FALSE;
2364 }
2365
2366 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
2367 if (NULL == *StringSid)
2368 {
2369 if (UnicodeString.Buffer != FixedBuffer)
2370 {
2371 RtlFreeUnicodeString(&UnicodeString);
2372 }
2373 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2374 return FALSE;
2375 }
2376
2377 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
2378 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
2379 if (UnicodeString.Buffer != FixedBuffer)
2380 {
2381 RtlFreeUnicodeString(&UnicodeString);
2382 }
2383
2384 return TRUE;
2385 }
2386
2387 /*
2388 * @implemented
2389 */
2390 BOOL
2391 WINAPI
2392 ConvertSidToStringSidA(PSID Sid,
2393 LPSTR *StringSid)
2394 {
2395 LPWSTR StringSidW;
2396 int Len;
2397
2398 if (!ConvertSidToStringSidW(Sid, &StringSidW))
2399 {
2400 return FALSE;
2401 }
2402
2403 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
2404 if (Len <= 0)
2405 {
2406 LocalFree(StringSidW);
2407 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2408 return FALSE;
2409 }
2410
2411 *StringSid = LocalAlloc(LMEM_FIXED, Len);
2412 if (NULL == *StringSid)
2413 {
2414 LocalFree(StringSidW);
2415 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2416 return FALSE;
2417 }
2418
2419 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
2420 {
2421 LocalFree(StringSid);
2422 LocalFree(StringSidW);
2423 return FALSE;
2424 }
2425
2426 LocalFree(StringSidW);
2427
2428 return TRUE;
2429 }
2430
2431 /*
2432 * @unimplemented
2433 */
2434 BOOL WINAPI
2435 CreateProcessWithLogonW(LPCWSTR lpUsername,
2436 LPCWSTR lpDomain,
2437 LPCWSTR lpPassword,
2438 DWORD dwLogonFlags,
2439 LPCWSTR lpApplicationName,
2440 LPWSTR lpCommandLine,
2441 DWORD dwCreationFlags,
2442 LPVOID lpEnvironment,
2443 LPCWSTR lpCurrentDirectory,
2444 LPSTARTUPINFOW lpStartupInfo,
2445 LPPROCESS_INFORMATION lpProcessInformation)
2446 {
2447 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
2448 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
2449 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
2450 lpStartupInfo, lpProcessInformation);
2451
2452 return FALSE;
2453 }
2454
2455 BOOL
2456 WINAPI
2457 CreateProcessWithTokenW(IN HANDLE hToken,
2458 IN DWORD dwLogonFlags,
2459 IN LPCWSTR lpApplicationName OPTIONAL,
2460 IN OUT LPWSTR lpCommandLine OPTIONAL,
2461 IN DWORD dwCreationFlags,
2462 IN LPVOID lpEnvironment OPTIONAL,
2463 IN LPCWSTR lpCurrentDirectory OPTIONAL,
2464 IN LPSTARTUPINFOW lpStartupInfo,
2465 OUT LPPROCESS_INFORMATION lpProcessInfo)
2466 {
2467 UNIMPLEMENTED;
2468 return FALSE;
2469 }
2470
2471 /*
2472 * @implemented
2473 */
2474 BOOL WINAPI
2475 DuplicateTokenEx(IN HANDLE ExistingTokenHandle,
2476 IN DWORD dwDesiredAccess,
2477 IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL,
2478 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
2479 IN TOKEN_TYPE TokenType,
2480 OUT PHANDLE DuplicateTokenHandle)
2481 {
2482 OBJECT_ATTRIBUTES ObjectAttributes;
2483 NTSTATUS Status;
2484 SECURITY_QUALITY_OF_SERVICE Sqos;
2485
2486 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
2487 ImpersonationLevel, TokenType, DuplicateTokenHandle);
2488
2489 Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
2490 Sqos.ImpersonationLevel = ImpersonationLevel;
2491 Sqos.ContextTrackingMode = 0;
2492 Sqos.EffectiveOnly = FALSE;
2493
2494 if (lpTokenAttributes != NULL)
2495 {
2496 InitializeObjectAttributes(&ObjectAttributes,
2497 NULL,
2498 lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
2499 NULL,
2500 lpTokenAttributes->lpSecurityDescriptor);
2501 }
2502 else
2503 {
2504 InitializeObjectAttributes(&ObjectAttributes,
2505 NULL,
2506 0,
2507 NULL,
2508 NULL);
2509 }
2510
2511 ObjectAttributes.SecurityQualityOfService = &Sqos;
2512
2513 Status = NtDuplicateToken(ExistingTokenHandle,
2514 dwDesiredAccess,
2515 &ObjectAttributes,
2516 FALSE,
2517 TokenType,
2518 DuplicateTokenHandle);
2519 if (!NT_SUCCESS(Status))
2520 {
2521 ERR("NtDuplicateToken failed: Status %08x\n", Status);
2522 SetLastError(RtlNtStatusToDosError(Status));
2523 return FALSE;
2524 }
2525
2526 TRACE("Returning token %p.\n", *DuplicateTokenHandle);
2527
2528 return TRUE;
2529 }
2530
2531 /*
2532 * @implemented
2533 */
2534 BOOL WINAPI
2535 DuplicateToken(IN HANDLE ExistingTokenHandle,
2536 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
2537 OUT PHANDLE DuplicateTokenHandle)
2538 {
2539 return DuplicateTokenEx(ExistingTokenHandle,
2540 TOKEN_IMPERSONATE | TOKEN_QUERY,
2541 NULL,
2542 ImpersonationLevel,
2543 TokenImpersonation,
2544 DuplicateTokenHandle);
2545 }
2546
2547 /******************************************************************************
2548 * ComputeStringSidSize
2549 */
2550 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
2551 {
2552 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
2553 {
2554 int ctok = 0;
2555 while (*StringSid)
2556 {
2557 if (*StringSid == '-')
2558 ctok++;
2559 StringSid++;
2560 }
2561
2562 if (ctok >= 3)
2563 return GetSidLengthRequired(ctok - 2);
2564 }
2565 else /* String constant format - Only available in winxp and above */
2566 {
2567 unsigned int i;
2568
2569 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
2570 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
2571 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
2572 }
2573
2574 return GetSidLengthRequired(0);
2575 }
2576
2577 /******************************************************************************
2578 * ParseStringSidToSid
2579 */
2580 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
2581 {
2582 BOOL bret = FALSE;
2583 SID* pisid=pSid;
2584
2585 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
2586 if (!StringSid)
2587 {
2588 SetLastError(ERROR_INVALID_PARAMETER);
2589 TRACE("StringSid is NULL, returning FALSE\n");
2590 return FALSE;
2591 }
2592
2593 while (*StringSid == ' ')
2594 StringSid++;
2595
2596 *cBytes = ComputeStringSidSize(StringSid);
2597 if (!pisid) /* Simply compute the size */
2598 {
2599 TRACE("only size requested, returning TRUE\n");
2600 return TRUE;
2601 }
2602
2603 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
2604 {
2605 DWORD i = 0, identAuth;
2606 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
2607
2608 StringSid += 2; /* Advance to Revision */
2609 pisid->Revision = atoiW(StringSid);
2610
2611 if (pisid->Revision != SDDL_REVISION)
2612 {
2613 TRACE("Revision %d is unknown\n", pisid->Revision);
2614 goto lend; /* ERROR_INVALID_SID */
2615 }
2616 if (csubauth == 0)
2617 {
2618 TRACE("SubAuthorityCount is 0\n");
2619 goto lend; /* ERROR_INVALID_SID */
2620 }
2621
2622 pisid->SubAuthorityCount = csubauth;
2623
2624 /* Advance to identifier authority */
2625 while (*StringSid && *StringSid != '-')
2626 StringSid++;
2627 if (*StringSid == '-')
2628 StringSid++;
2629
2630 /* MS' implementation can't handle values greater than 2^32 - 1, so
2631 * we don't either; assume most significant bytes are always 0
2632 */
2633 pisid->IdentifierAuthority.Value[0] = 0;
2634 pisid->IdentifierAuthority.Value[1] = 0;
2635 identAuth = atoiW(StringSid);
2636 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
2637 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
2638 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
2639 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
2640
2641 /* Advance to first sub authority */
2642 while (*StringSid && *StringSid != '-')
2643 StringSid++;
2644 if (*StringSid == '-')
2645 StringSid++;
2646
2647 while (*StringSid)
2648 {
2649 pisid->SubAuthority[i++] = atoiW(StringSid);
2650
2651 while (*StringSid && *StringSid != '-')
2652 StringSid++;
2653 if (*StringSid == '-')
2654 StringSid++;
2655 }
2656
2657 if (i != pisid->SubAuthorityCount)
2658 goto lend; /* ERROR_INVALID_SID */
2659
2660 bret = TRUE;
2661 }
2662 else /* String constant format - Only available in winxp and above */
2663 {
2664 unsigned int i;
2665 pisid->Revision = SDDL_REVISION;
2666
2667 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
2668 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
2669 {
2670 DWORD j;
2671 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
2672 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
2673 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
2674 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
2675 bret = TRUE;
2676 }
2677
2678 if (!bret)
2679 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
2680 }
2681
2682 lend:
2683 if (!bret)
2684 SetLastError(ERROR_INVALID_SID);
2685
2686 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
2687 return bret;
2688 }
2689
2690 /*
2691 * @unimplemented
2692 */
2693 BOOL
2694 WINAPI
2695 GetWindowsAccountDomainSid(IN PSID pSid,
2696 OUT PSID ppDomainSid,
2697 IN OUT DWORD* cbSid)
2698 {
2699 UNIMPLEMENTED;
2700 return FALSE;
2701 }
2702
2703 /*
2704 * @unimplemented
2705 */
2706 BOOL
2707 WINAPI
2708 EqualDomainSid(IN PSID pSid1,
2709 IN PSID pSid2,
2710 OUT BOOL* pfEqual)
2711 {
2712 UNIMPLEMENTED;
2713 return FALSE;
2714 }
2715
2716 /* EOF */