[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 /* set last error code from NT status and get the proper boolean return value */
230 /* used for functions that are a simple wrapper around the corresponding ntdll API */
231 static __inline BOOL set_ntstatus( NTSTATUS status )
232 {
233 if (!NT_SUCCESS(status)) SetLastError( RtlNtStatusToDosError( status ));
234 return NT_SUCCESS(status);
235 }
236
237 static const RECORD SidTable[] =
238 {
239 { SDDL_ACCOUNT_OPERATORS, WinBuiltinAccountOperatorsSid },
240 { SDDL_ALIAS_PREW2KCOMPACC, WinBuiltinPreWindows2000CompatibleAccessSid },
241 { SDDL_ANONYMOUS, WinAnonymousSid },
242 { SDDL_AUTHENTICATED_USERS, WinAuthenticatedUserSid },
243 { SDDL_BUILTIN_ADMINISTRATORS, WinBuiltinAdministratorsSid },
244 { SDDL_BUILTIN_GUESTS, WinBuiltinGuestsSid },
245 { SDDL_BACKUP_OPERATORS, WinBuiltinBackupOperatorsSid },
246 { SDDL_BUILTIN_USERS, WinBuiltinUsersSid },
247 { SDDL_CERT_SERV_ADMINISTRATORS, WinAccountCertAdminsSid /* FIXME: DOMAIN_GROUP_RID_CERT_ADMINS */ },
248 { SDDL_CREATOR_GROUP, WinCreatorGroupSid },
249 { SDDL_CREATOR_OWNER, WinCreatorOwnerSid },
250 { SDDL_DOMAIN_ADMINISTRATORS, WinAccountDomainAdminsSid /* FIXME: DOMAIN_GROUP_RID_ADMINS */ },
251 { SDDL_DOMAIN_COMPUTERS, WinAccountComputersSid /* FIXME: DOMAIN_GROUP_RID_COMPUTERS */ },
252 { SDDL_DOMAIN_DOMAIN_CONTROLLERS, WinAccountControllersSid /* FIXME: DOMAIN_GROUP_RID_CONTROLLERS */ },
253 { SDDL_DOMAIN_GUESTS, WinAccountDomainGuestsSid /* FIXME: DOMAIN_GROUP_RID_GUESTS */ },
254 { SDDL_DOMAIN_USERS, WinAccountDomainUsersSid /* FIXME: DOMAIN_GROUP_RID_USERS */ },
255 { SDDL_ENTERPRISE_ADMINS, WinAccountEnterpriseAdminsSid /* FIXME: DOMAIN_GROUP_RID_ENTERPRISE_ADMINS */ },
256 { SDDL_ENTERPRISE_DOMAIN_CONTROLLERS, WinEnterpriseControllersSid },
257 { SDDL_EVERYONE, WinWorldSid },
258 { SDDL_GROUP_POLICY_ADMINS, WinAccountPolicyAdminsSid /* FIXME: DOMAIN_GROUP_RID_POLICY_ADMINS */ },
259 { SDDL_INTERACTIVE, WinInteractiveSid },
260 { SDDL_LOCAL_ADMIN, WinAccountAdministratorSid /* FIXME: DOMAIN_USER_RID_ADMIN */ },
261 { SDDL_LOCAL_GUEST, WinAccountGuestSid /* FIXME: DOMAIN_USER_RID_GUEST */ },
262 { SDDL_LOCAL_SERVICE, WinLocalServiceSid },
263 { SDDL_LOCAL_SYSTEM, WinLocalSystemSid },
264 { SDDL_NETWORK, WinNetworkSid },
265 { SDDL_NETWORK_CONFIGURATION_OPS, WinBuiltinNetworkConfigurationOperatorsSid },
266 { SDDL_NETWORK_SERVICE, WinNetworkServiceSid },
267 { SDDL_PRINTER_OPERATORS, WinBuiltinPrintOperatorsSid },
268 { SDDL_PERSONAL_SELF, WinSelfSid },
269 { SDDL_POWER_USERS, WinBuiltinPowerUsersSid },
270 { SDDL_RAS_SERVERS, WinAccountRasAndIasServersSid /* FIXME: DOMAIN_ALIAS_RID_RAS_SERVERS */ },
271 { SDDL_REMOTE_DESKTOP, WinBuiltinRemoteDesktopUsersSid },
272 { SDDL_REPLICATOR, WinBuiltinReplicatorSid },
273 { SDDL_RESTRICTED_CODE, WinRestrictedCodeSid },
274 { SDDL_SCHEMA_ADMINISTRATORS, WinAccountSchemaAdminsSid /* FIXME: DOMAIN_GROUP_RID_SCHEMA_ADMINS */ },
275 { SDDL_SERVER_OPERATORS, WinBuiltinSystemOperatorsSid },
276 { SDDL_SERVICE, WinServiceSid },
277 { NULL, 0 },
278 };
279
280 /************************************************************
281 * ADVAPI_IsLocalComputer
282 *
283 * Checks whether the server name indicates local machine.
284 */
285 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
286 {
287 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
288 BOOL Result;
289 LPWSTR buf;
290
291 if (!ServerName || !ServerName[0])
292 return TRUE;
293
294 buf = heap_alloc(dwSize * sizeof(WCHAR));
295 Result = GetComputerNameW(buf, &dwSize);
296 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
297 ServerName += 2;
298 Result = Result && !lstrcmpW(ServerName, buf);
299 heap_free(buf);
300
301 return Result;
302 }
303
304 /* Exported functions */
305
306 /*
307 * @implemented
308 */
309 BOOL WINAPI
310 OpenProcessToken(HANDLE ProcessHandle,
311 DWORD DesiredAccess,
312 PHANDLE TokenHandle)
313 {
314 NTSTATUS Status;
315
316 TRACE("%p, %x, %p.\n", ProcessHandle, DesiredAccess, TokenHandle);
317
318 Status = NtOpenProcessToken(ProcessHandle,
319 DesiredAccess,
320 TokenHandle);
321 if (!NT_SUCCESS(Status))
322 {
323 ERR("NtOpenProcessToken failed! Status %08x.\n", Status);
324 SetLastError(RtlNtStatusToDosError(Status));
325 return FALSE;
326 }
327
328 TRACE("Returning token %p.\n", *TokenHandle);
329
330 return TRUE;
331 }
332
333 /******************************************************************************
334 * OpenThreadToken [ADVAPI32.@]
335 *
336 * Opens the access token associated with a thread handle.
337 *
338 * PARAMS
339 * ThreadHandle [I] Handle to process
340 * DesiredAccess [I] Desired access to the thread
341 * OpenAsSelf [I] ???
342 * TokenHandle [O] Destination for the token handle
343 *
344 * RETURNS
345 * Success: TRUE. TokenHandle contains the access token.
346 * Failure: FALSE.
347 *
348 * NOTES
349 * See NtOpenThreadToken.
350 */
351 BOOL WINAPI
352 OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess,
353 BOOL OpenAsSelf, HANDLE *TokenHandle)
354 {
355 return set_ntstatus( NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle));
356 }
357
358 /*
359 * @implemented
360 */
361 BOOL WINAPI
362 AdjustTokenGroups(HANDLE TokenHandle,
363 BOOL ResetToDefault,
364 PTOKEN_GROUPS NewState,
365 DWORD BufferLength,
366 PTOKEN_GROUPS PreviousState,
367 PDWORD ReturnLength)
368 {
369 NTSTATUS Status;
370
371 Status = NtAdjustGroupsToken(TokenHandle,
372 ResetToDefault,
373 NewState,
374 BufferLength,
375 PreviousState,
376 (PULONG)ReturnLength);
377 if (!NT_SUCCESS(Status))
378 {
379 SetLastError(RtlNtStatusToDosError(Status));
380 return FALSE;
381 }
382
383 return TRUE;
384 }
385
386 /*
387 * @implemented
388 */
389 BOOL WINAPI
390 AdjustTokenPrivileges(HANDLE TokenHandle,
391 BOOL DisableAllPrivileges,
392 PTOKEN_PRIVILEGES NewState,
393 DWORD BufferLength,
394 PTOKEN_PRIVILEGES PreviousState,
395 PDWORD ReturnLength)
396 {
397 NTSTATUS Status;
398
399 Status = NtAdjustPrivilegesToken(TokenHandle,
400 DisableAllPrivileges,
401 NewState,
402 BufferLength,
403 PreviousState,
404 (PULONG)ReturnLength);
405 if (STATUS_NOT_ALL_ASSIGNED == Status)
406 {
407 SetLastError(ERROR_NOT_ALL_ASSIGNED);
408 return TRUE;
409 }
410
411 if (!NT_SUCCESS(Status))
412 {
413 SetLastError(RtlNtStatusToDosError(Status));
414 return FALSE;
415 }
416
417 /* AdjustTokenPrivileges is documented to do this */
418 SetLastError(ERROR_SUCCESS);
419
420 return TRUE;
421 }
422
423 /*
424 * @implemented
425 */
426 BOOL WINAPI
427 GetTokenInformation(HANDLE TokenHandle,
428 TOKEN_INFORMATION_CLASS TokenInformationClass,
429 LPVOID TokenInformation,
430 DWORD TokenInformationLength,
431 PDWORD ReturnLength)
432 {
433 NTSTATUS Status;
434
435 Status = NtQueryInformationToken(TokenHandle,
436 TokenInformationClass,
437 TokenInformation,
438 TokenInformationLength,
439 (PULONG)ReturnLength);
440 if (!NT_SUCCESS(Status))
441 {
442 SetLastError(RtlNtStatusToDosError(Status));
443 return FALSE;
444 }
445
446 return TRUE;
447 }
448
449 /*
450 * @implemented
451 */
452 BOOL WINAPI
453 SetTokenInformation(HANDLE TokenHandle,
454 TOKEN_INFORMATION_CLASS TokenInformationClass,
455 LPVOID TokenInformation,
456 DWORD TokenInformationLength)
457 {
458 NTSTATUS Status;
459
460 Status = NtSetInformationToken(TokenHandle,
461 TokenInformationClass,
462 TokenInformation,
463 TokenInformationLength);
464 if (!NT_SUCCESS(Status))
465 {
466 SetLastError(RtlNtStatusToDosError(Status));
467 return FALSE;
468 }
469
470 return TRUE;
471 }
472
473 /*
474 * @implemented
475 */
476 BOOL WINAPI
477 SetThreadToken(IN PHANDLE ThreadHandle OPTIONAL,
478 IN HANDLE TokenHandle)
479 {
480 NTSTATUS Status;
481 HANDLE hThread;
482
483 hThread = (ThreadHandle != NULL) ? *ThreadHandle : NtCurrentThread();
484
485 Status = NtSetInformationThread(hThread,
486 ThreadImpersonationToken,
487 &TokenHandle,
488 sizeof(HANDLE));
489 if (!NT_SUCCESS(Status))
490 {
491 SetLastError(RtlNtStatusToDosError(Status));
492 return FALSE;
493 }
494
495 return TRUE;
496 }
497
498 /*************************************************************************
499 * CreateRestrictedToken [ADVAPI32.@]
500 *
501 * Create a new more restricted token from an existing token.
502 *
503 * PARAMS
504 * baseToken [I] Token to base the new restricted token on
505 * flags [I] Options
506 * nDisableSids [I] Length of disableSids array
507 * disableSids [I] Array of SIDs to disable in the new token
508 * nDeletePrivs [I] Length of deletePrivs array
509 * deletePrivs [I] Array of privileges to delete in the new token
510 * nRestrictSids [I] Length of restrictSids array
511 * restrictSids [I] Array of SIDs to restrict in the new token
512 * newToken [O] Address where the new token is stored
513 *
514 * RETURNS
515 * Success: TRUE
516 * Failure: FALSE
517 */
518 BOOL WINAPI CreateRestrictedToken(
519 HANDLE baseToken,
520 DWORD flags,
521 DWORD nDisableSids,
522 PSID_AND_ATTRIBUTES disableSids,
523 DWORD nDeletePrivs,
524 PLUID_AND_ATTRIBUTES deletePrivs,
525 DWORD nRestrictSids,
526 PSID_AND_ATTRIBUTES restrictSids,
527 PHANDLE newToken)
528 {
529 TOKEN_TYPE type;
530 SECURITY_IMPERSONATION_LEVEL level = TokenImpersonationLevel;
531 DWORD size;
532
533 FIXME("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p): stub\n",
534 baseToken, flags, nDisableSids, disableSids,
535 nDeletePrivs, deletePrivs,
536 nRestrictSids, restrictSids,
537 newToken);
538
539 size = sizeof(type);
540 if (!GetTokenInformation( baseToken, TokenType, &type, size, &size )) return FALSE;
541 if (type == TokenImpersonation)
542 {
543 size = sizeof(level);
544 if (!GetTokenInformation( baseToken, TokenImpersonationLevel, &level, size, &size ))
545 return FALSE;
546 }
547 return DuplicateTokenEx( baseToken, MAXIMUM_ALLOWED, NULL, level, type, newToken );
548 }
549
550 /******************************************************************************
551 * AllocateAndInitializeSid [ADVAPI32.@]
552 *
553 * PARAMS
554 * pIdentifierAuthority []
555 * nSubAuthorityCount []
556 * nSubAuthority0 []
557 * nSubAuthority1 []
558 * nSubAuthority2 []
559 * nSubAuthority3 []
560 * nSubAuthority4 []
561 * nSubAuthority5 []
562 * nSubAuthority6 []
563 * nSubAuthority7 []
564 * pSid []
565 */
566 BOOL WINAPI
567 AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
568 BYTE nSubAuthorityCount,
569 DWORD nSubAuthority0, DWORD nSubAuthority1,
570 DWORD nSubAuthority2, DWORD nSubAuthority3,
571 DWORD nSubAuthority4, DWORD nSubAuthority5,
572 DWORD nSubAuthority6, DWORD nSubAuthority7,
573 PSID *pSid )
574 {
575 return set_ntstatus( RtlAllocateAndInitializeSid(
576 pIdentifierAuthority, nSubAuthorityCount,
577 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
578 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7,
579 pSid ));
580 }
581
582 /*
583 * @implemented
584 *
585 * RETURNS
586 * Docs says this function does NOT return a value
587 * even thou it's defined to return a PVOID...
588 */
589 PVOID
590 WINAPI
591 FreeSid(PSID pSid)
592 {
593 return RtlFreeSid(pSid);
594 }
595
596 /******************************************************************************
597 * CopySid [ADVAPI32.@]
598 *
599 * PARAMS
600 * nDestinationSidLength []
601 * pDestinationSid []
602 * pSourceSid []
603 */
604 BOOL WINAPI
605 CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
606 {
607 return set_ntstatus(RtlCopySid(nDestinationSidLength, pDestinationSid, pSourceSid));
608 }
609
610 /*
611 * @unimplemented
612 */
613 BOOL
614 WINAPI
615 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
616 IN PSID DomainSid OPTIONAL,
617 OUT PSID pSid,
618 IN OUT DWORD* cbSid)
619 {
620 unsigned int i;
621 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
622
623 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
624 {
625 SetLastError(ERROR_INVALID_PARAMETER);
626 return FALSE;
627 }
628
629 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
630 if (WellKnownSids[i].Type == WellKnownSidType) {
631 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
632
633 if (*cbSid < length)
634 {
635 *cbSid = length;
636 SetLastError(ERROR_INSUFFICIENT_BUFFER);
637 return FALSE;
638 }
639 if (!pSid)
640 {
641 SetLastError(ERROR_INVALID_PARAMETER);
642 return FALSE;
643 }
644 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
645 *cbSid = length;
646 return TRUE;
647 }
648 }
649
650 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
651 {
652 SetLastError(ERROR_INVALID_PARAMETER);
653 return FALSE;
654 }
655
656 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
657 if (WellKnownRids[i].Type == WellKnownSidType) {
658 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
659 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
660 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
661
662 if (*cbSid < output_sid_length)
663 {
664 *cbSid = output_sid_length;
665 SetLastError(ERROR_INSUFFICIENT_BUFFER);
666 return FALSE;
667 }
668 if (!pSid)
669 {
670 SetLastError(ERROR_INVALID_PARAMETER);
671 return FALSE;
672 }
673 CopyMemory(pSid, DomainSid, domain_sid_length);
674 (*GetSidSubAuthorityCount(pSid))++;
675 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
676 *cbSid = output_sid_length;
677 return TRUE;
678 }
679
680 SetLastError(ERROR_INVALID_PARAMETER);
681 return FALSE;
682 }
683
684 /*
685 * @unimplemented
686 */
687 BOOL
688 WINAPI
689 IsWellKnownSid(IN PSID pSid,
690 IN WELL_KNOWN_SID_TYPE WellKnownSidType)
691 {
692 unsigned int i;
693 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
694
695 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
696 {
697 if (WellKnownSids[i].Type == WellKnownSidType)
698 {
699 if (EqualSid(pSid, (PSID)(&WellKnownSids[i].Sid.Revision)))
700 return TRUE;
701 }
702 }
703
704 return FALSE;
705 }
706
707 /*
708 * @implemented
709 */
710 BOOL
711 WINAPI
712 IsValidSid(PSID pSid)
713 {
714 return (BOOL)RtlValidSid(pSid);
715 }
716
717 /*
718 * @implemented
719 */
720 BOOL
721 WINAPI
722 EqualSid(PSID pSid1,
723 PSID pSid2)
724 {
725 SetLastError(ERROR_SUCCESS);
726 return RtlEqualSid (pSid1, pSid2);
727 }
728
729 /*
730 * @implemented
731 */
732 BOOL
733 WINAPI
734 EqualPrefixSid(PSID pSid1,
735 PSID pSid2)
736 {
737 return RtlEqualPrefixSid (pSid1, pSid2);
738 }
739
740 /*
741 * @implemented
742 */
743 DWORD
744 WINAPI
745 GetSidLengthRequired(UCHAR nSubAuthorityCount)
746 {
747 return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
748 }
749
750 /*
751 * @implemented
752 */
753 BOOL
754 WINAPI
755 InitializeSid(PSID Sid,
756 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
757 BYTE nSubAuthorityCount)
758 {
759 NTSTATUS Status;
760
761 Status = RtlInitializeSid(Sid,
762 pIdentifierAuthority,
763 nSubAuthorityCount);
764 if (!NT_SUCCESS(Status))
765 {
766 SetLastError(RtlNtStatusToDosError(Status));
767 return FALSE;
768 }
769
770 return TRUE;
771 }
772
773 /*
774 * @implemented
775 */
776 PSID_IDENTIFIER_AUTHORITY
777 WINAPI
778 GetSidIdentifierAuthority(PSID pSid)
779 {
780 return RtlIdentifierAuthoritySid(pSid);
781 }
782
783 /*
784 * @implemented
785 */
786 PDWORD
787 WINAPI
788 GetSidSubAuthority(PSID pSid,
789 DWORD nSubAuthority)
790 {
791 SetLastError(ERROR_SUCCESS);
792 return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority);
793 }
794
795 /*
796 * @implemented
797 */
798 PUCHAR
799 WINAPI
800 GetSidSubAuthorityCount(PSID pSid)
801 {
802 SetLastError(ERROR_SUCCESS);
803 return RtlSubAuthorityCountSid(pSid);
804 }
805
806 /*
807 * @implemented
808 */
809 DWORD
810 WINAPI
811 GetLengthSid(PSID pSid)
812 {
813 return (DWORD)RtlLengthSid(pSid);
814 }
815
816 /*
817 * @implemented
818 */
819 BOOL
820 WINAPI
821 InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor,
822 DWORD dwRevision)
823 {
824 NTSTATUS Status;
825
826 Status = RtlCreateSecurityDescriptor(pSecurityDescriptor,
827 dwRevision);
828 if (!NT_SUCCESS(Status))
829 {
830 SetLastError(RtlNtStatusToDosError(Status));
831 return FALSE;
832 }
833
834 return TRUE;
835 }
836
837 /*
838 * @implemented
839 */
840 BOOL
841 WINAPI
842 MakeAbsoluteSD(PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
843 PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
844 LPDWORD lpdwAbsoluteSecurityDescriptorSize,
845 PACL pDacl,
846 LPDWORD lpdwDaclSize,
847 PACL pSacl,
848 LPDWORD lpdwSaclSize,
849 PSID pOwner,
850 LPDWORD lpdwOwnerSize,
851 PSID pPrimaryGroup,
852 LPDWORD lpdwPrimaryGroupSize)
853 {
854 NTSTATUS Status;
855
856 Status = RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor,
857 pAbsoluteSecurityDescriptor,
858 lpdwAbsoluteSecurityDescriptorSize,
859 pDacl,
860 lpdwDaclSize,
861 pSacl,
862 lpdwSaclSize,
863 pOwner,
864 lpdwOwnerSize,
865 pPrimaryGroup,
866 lpdwPrimaryGroupSize);
867 if (!NT_SUCCESS(Status))
868 {
869 SetLastError(RtlNtStatusToDosError(Status));
870 return FALSE;
871 }
872
873 return TRUE;
874 }
875
876 /******************************************************************************
877 * GetKernelObjectSecurity [ADVAPI32.@]
878 */
879 BOOL WINAPI GetKernelObjectSecurity(
880 HANDLE Handle,
881 SECURITY_INFORMATION RequestedInformation,
882 PSECURITY_DESCRIPTOR pSecurityDescriptor,
883 DWORD nLength,
884 LPDWORD lpnLengthNeeded )
885 {
886 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation,
887 pSecurityDescriptor, nLength, lpnLengthNeeded);
888
889 return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor,
890 nLength, lpnLengthNeeded ));
891 }
892
893 /*
894 * @implemented
895 */
896 BOOL
897 WINAPI
898 InitializeAcl(PACL pAcl,
899 DWORD nAclLength,
900 DWORD dwAclRevision)
901 {
902 NTSTATUS Status;
903
904 Status = RtlCreateAcl(pAcl,
905 nAclLength,
906 dwAclRevision);
907 if (!NT_SUCCESS(Status))
908 {
909 SetLastError(RtlNtStatusToDosError(Status));
910 return FALSE;
911 }
912
913 return TRUE;
914 }
915
916 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe )
917 {
918 IO_STATUS_BLOCK io_block;
919
920 TRACE("(%p)\n", hNamedPipe);
921
922 return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL,
923 &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) );
924 }
925
926 /*
927 * @implemented
928 */
929 BOOL
930 WINAPI
931 AddAccessAllowedAce(PACL pAcl,
932 DWORD dwAceRevision,
933 DWORD AccessMask,
934 PSID pSid)
935 {
936 NTSTATUS Status;
937
938 Status = RtlAddAccessAllowedAce(pAcl,
939 dwAceRevision,
940 AccessMask,
941 pSid);
942 if (!NT_SUCCESS(Status))
943 {
944 SetLastError(RtlNtStatusToDosError(Status));
945 return FALSE;
946 }
947
948 return TRUE;
949 }
950
951 /*
952 * @implemented
953 */
954 BOOL WINAPI
955 AddAccessAllowedAceEx(PACL pAcl,
956 DWORD dwAceRevision,
957 DWORD AceFlags,
958 DWORD AccessMask,
959 PSID pSid)
960 {
961 NTSTATUS Status;
962
963 Status = RtlAddAccessAllowedAceEx(pAcl,
964 dwAceRevision,
965 AceFlags,
966 AccessMask,
967 pSid);
968 if (!NT_SUCCESS(Status))
969 {
970 SetLastError(RtlNtStatusToDosError(Status));
971 return FALSE;
972 }
973
974 return TRUE;
975 }
976
977 /*
978 * @implemented
979 */
980 BOOL
981 WINAPI
982 AddAccessDeniedAce(PACL pAcl,
983 DWORD dwAceRevision,
984 DWORD AccessMask,
985 PSID pSid)
986 {
987 NTSTATUS Status;
988
989 Status = RtlAddAccessDeniedAce(pAcl,
990 dwAceRevision,
991 AccessMask,
992 pSid);
993 if (!NT_SUCCESS(Status))
994 {
995 SetLastError(RtlNtStatusToDosError(Status));
996 return FALSE;
997 }
998
999 return TRUE;
1000 }
1001
1002 /*
1003 * @implemented
1004 */
1005 BOOL WINAPI
1006 AddAccessDeniedAceEx(PACL pAcl,
1007 DWORD dwAceRevision,
1008 DWORD AceFlags,
1009 DWORD AccessMask,
1010 PSID pSid)
1011 {
1012 NTSTATUS Status;
1013
1014 Status = RtlAddAccessDeniedAceEx(pAcl,
1015 dwAceRevision,
1016 AceFlags,
1017 AccessMask,
1018 pSid);
1019 if (!NT_SUCCESS(Status))
1020 {
1021 SetLastError(RtlNtStatusToDosError(Status));
1022 return FALSE;
1023 }
1024
1025 return TRUE;
1026 }
1027
1028 /*
1029 * @implemented
1030 */
1031 BOOL
1032 WINAPI
1033 AddAce(PACL pAcl,
1034 DWORD dwAceRevision,
1035 DWORD dwStartingAceIndex,
1036 LPVOID pAceList,
1037 DWORD nAceListLength)
1038 {
1039 NTSTATUS Status;
1040
1041 Status = RtlAddAce(pAcl,
1042 dwAceRevision,
1043 dwStartingAceIndex,
1044 pAceList,
1045 nAceListLength);
1046 if (!NT_SUCCESS(Status))
1047 {
1048 SetLastError(RtlNtStatusToDosError(Status));
1049 return FALSE;
1050 }
1051
1052 return TRUE;
1053 }
1054
1055 /*
1056 * @implemented
1057 */
1058 BOOL
1059 WINAPI
1060 DeleteAce(PACL pAcl,
1061 DWORD dwAceIndex)
1062 {
1063 NTSTATUS Status;
1064
1065 Status = RtlDeleteAce(pAcl,
1066 dwAceIndex);
1067 if (!NT_SUCCESS(Status))
1068 {
1069 SetLastError(RtlNtStatusToDosError(Status));
1070 return FALSE;
1071 }
1072
1073 return TRUE;
1074 }
1075
1076 /*
1077 * @implemented
1078 */
1079 BOOL
1080 WINAPI
1081 FindFirstFreeAce(PACL pAcl,
1082 LPVOID *pAce)
1083 {
1084 return RtlFirstFreeAce(pAcl,
1085 (PACE*)pAce);
1086 }
1087
1088
1089 /*
1090 * @implemented
1091 */
1092 BOOL
1093 WINAPI
1094 GetAce(PACL pAcl,
1095 DWORD dwAceIndex,
1096 LPVOID *pAce)
1097 {
1098 NTSTATUS Status;
1099
1100 Status = RtlGetAce(pAcl,
1101 dwAceIndex,
1102 pAce);
1103 if (!NT_SUCCESS(Status))
1104 {
1105 SetLastError(RtlNtStatusToDosError(Status));
1106 return FALSE;
1107 }
1108
1109 return TRUE;
1110 }
1111
1112 /*
1113 * @implemented
1114 */
1115 BOOL
1116 WINAPI
1117 GetAclInformation(PACL pAcl,
1118 LPVOID pAclInformation,
1119 DWORD nAclInformationLength,
1120 ACL_INFORMATION_CLASS dwAclInformationClass)
1121 {
1122 NTSTATUS Status;
1123
1124 Status = RtlQueryInformationAcl(pAcl,
1125 pAclInformation,
1126 nAclInformationLength,
1127 dwAclInformationClass);
1128 if (!NT_SUCCESS(Status))
1129 {
1130 SetLastError(RtlNtStatusToDosError(Status));
1131 return FALSE;
1132 }
1133
1134 return TRUE;
1135 }
1136
1137 /*
1138 * @implemented
1139 */
1140 BOOL
1141 WINAPI
1142 IsValidAcl(PACL pAcl)
1143 {
1144 return RtlValidAcl (pAcl);
1145 }
1146
1147 /*
1148 * @implemented
1149 */
1150 BOOL WINAPI
1151 AllocateLocallyUniqueId(PLUID Luid)
1152 {
1153 NTSTATUS Status;
1154
1155 Status = NtAllocateLocallyUniqueId (Luid);
1156 if (!NT_SUCCESS (Status))
1157 {
1158 SetLastError(RtlNtStatusToDosError(Status));
1159 return FALSE;
1160 }
1161
1162 return TRUE;
1163 }
1164
1165 /**********************************************************************
1166 * LookupPrivilegeDisplayNameA EXPORTED
1167 *
1168 * @unimplemented
1169 */
1170 BOOL
1171 WINAPI
1172 LookupPrivilegeDisplayNameA(LPCSTR lpSystemName,
1173 LPCSTR lpName,
1174 LPSTR lpDisplayName,
1175 LPDWORD cbDisplayName,
1176 LPDWORD lpLanguageId)
1177 {
1178 FIXME("%s() not implemented!\n", __FUNCTION__);
1179 SetLastError (ERROR_CALL_NOT_IMPLEMENTED);
1180 return FALSE;
1181 }
1182
1183
1184 /**********************************************************************
1185 * LookupPrivilegeDisplayNameW EXPORTED
1186 *
1187 * @unimplemented
1188 */
1189 BOOL
1190 WINAPI
1191 LookupPrivilegeDisplayNameW(LPCWSTR lpSystemName,
1192 LPCWSTR lpName,
1193 LPWSTR lpDisplayName,
1194 LPDWORD cbDisplayName,
1195 LPDWORD lpLanguageId)
1196 {
1197 FIXME("%s() not implemented!\n", __FUNCTION__);
1198 SetLastError (ERROR_CALL_NOT_IMPLEMENTED);
1199 return FALSE;
1200 }
1201
1202 /**********************************************************************
1203 * LookupPrivilegeNameA EXPORTED
1204 *
1205 * @implemented
1206 */
1207 BOOL
1208 WINAPI
1209 LookupPrivilegeNameA(LPCSTR lpSystemName,
1210 PLUID lpLuid,
1211 LPSTR lpName,
1212 LPDWORD cchName)
1213 {
1214 UNICODE_STRING lpSystemNameW;
1215 BOOL ret;
1216 DWORD wLen = 0;
1217
1218 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1219
1220 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1221 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1222 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1223 {
1224 LPWSTR lpNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR));
1225
1226 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1227 &wLen);
1228 if (ret)
1229 {
1230 /* Windows crashes if cchName is NULL, so will I */
1231 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1232 *cchName, NULL, NULL);
1233
1234 if (len == 0)
1235 {
1236 /* WideCharToMultiByte failed */
1237 ret = FALSE;
1238 }
1239 else if (len > *cchName)
1240 {
1241 *cchName = len;
1242 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1243 ret = FALSE;
1244 }
1245 else
1246 {
1247 /* WideCharToMultiByte succeeded, output length needs to be
1248 * length not including NULL terminator
1249 */
1250 *cchName = len - 1;
1251 }
1252 }
1253 HeapFree(GetProcessHeap(), 0, lpNameW);
1254 }
1255 RtlFreeUnicodeString(&lpSystemNameW);
1256 return ret;
1257 }
1258
1259 /******************************************************************************
1260 * GetFileSecurityA [ADVAPI32.@]
1261 *
1262 * Obtains Specified information about the security of a file or directory.
1263 *
1264 * PARAMS
1265 * lpFileName [I] Name of the file to get info for
1266 * RequestedInformation [I] SE_ flags from "winnt.h"
1267 * pSecurityDescriptor [O] Destination for security information
1268 * nLength [I] Length of pSecurityDescriptor
1269 * lpnLengthNeeded [O] Destination for length of returned security information
1270 *
1271 * RETURNS
1272 * Success: TRUE. pSecurityDescriptor contains the requested information.
1273 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
1274 *
1275 * NOTES
1276 * The information returned is constrained by the callers access rights and
1277 * privileges.
1278 *
1279 * @implemented
1280 */
1281 BOOL
1282 WINAPI
1283 GetFileSecurityA(LPCSTR lpFileName,
1284 SECURITY_INFORMATION RequestedInformation,
1285 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1286 DWORD nLength,
1287 LPDWORD lpnLengthNeeded)
1288 {
1289 UNICODE_STRING FileName;
1290 BOOL bResult;
1291
1292 if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName))
1293 {
1294 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1295 return FALSE;
1296 }
1297
1298 bResult = GetFileSecurityW(FileName.Buffer,
1299 RequestedInformation,
1300 pSecurityDescriptor,
1301 nLength,
1302 lpnLengthNeeded);
1303
1304 RtlFreeUnicodeString(&FileName);
1305
1306 return bResult;
1307 }
1308
1309 /*
1310 * @implemented
1311 */
1312 BOOL
1313 WINAPI
1314 GetFileSecurityW(LPCWSTR lpFileName,
1315 SECURITY_INFORMATION RequestedInformation,
1316 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1317 DWORD nLength,
1318 LPDWORD lpnLengthNeeded)
1319 {
1320 OBJECT_ATTRIBUTES ObjectAttributes;
1321 IO_STATUS_BLOCK StatusBlock;
1322 UNICODE_STRING FileName;
1323 ULONG AccessMask = 0;
1324 HANDLE FileHandle;
1325 NTSTATUS Status;
1326
1327 TRACE("GetFileSecurityW() called\n");
1328
1329 QuerySecurityAccessMask(RequestedInformation, &AccessMask);
1330
1331 if (!RtlDosPathNameToNtPathName_U(lpFileName,
1332 &FileName,
1333 NULL,
1334 NULL))
1335 {
1336 ERR("Invalid path\n");
1337 SetLastError(ERROR_INVALID_NAME);
1338 return FALSE;
1339 }
1340
1341 InitializeObjectAttributes(&ObjectAttributes,
1342 &FileName,
1343 OBJ_CASE_INSENSITIVE,
1344 NULL,
1345 NULL);
1346
1347 Status = NtOpenFile(&FileHandle,
1348 AccessMask,
1349 &ObjectAttributes,
1350 &StatusBlock,
1351 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1352 0);
1353
1354 RtlFreeHeap(RtlGetProcessHeap(),
1355 0,
1356 FileName.Buffer);
1357
1358 if (!NT_SUCCESS(Status))
1359 {
1360 ERR("NtOpenFile() failed (Status %lx)\n", Status);
1361 SetLastError(RtlNtStatusToDosError(Status));
1362 return FALSE;
1363 }
1364
1365 Status = NtQuerySecurityObject(FileHandle,
1366 RequestedInformation,
1367 pSecurityDescriptor,
1368 nLength,
1369 lpnLengthNeeded);
1370 NtClose(FileHandle);
1371 if (!NT_SUCCESS(Status))
1372 {
1373 ERR("NtQuerySecurityObject() failed (Status %lx)\n", Status);
1374 SetLastError(RtlNtStatusToDosError(Status));
1375 return FALSE;
1376 }
1377
1378 return TRUE;
1379 }
1380
1381 /******************************************************************************
1382 * SetFileSecurityA [ADVAPI32.@]
1383 * Sets the security of a file or directory
1384 *
1385 * @implemented
1386 */
1387 BOOL
1388 WINAPI
1389 SetFileSecurityA(LPCSTR lpFileName,
1390 SECURITY_INFORMATION SecurityInformation,
1391 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1392 {
1393 UNICODE_STRING FileName;
1394 BOOL bResult;
1395
1396 if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName))
1397 {
1398 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1399 return FALSE;
1400 }
1401
1402 bResult = SetFileSecurityW(FileName.Buffer,
1403 SecurityInformation,
1404 pSecurityDescriptor);
1405
1406 RtlFreeUnicodeString(&FileName);
1407
1408 return bResult;
1409 }
1410
1411 /******************************************************************************
1412 * SetFileSecurityW [ADVAPI32.@]
1413 * Sets the security of a file or directory
1414 *
1415 * @implemented
1416 */
1417 BOOL
1418 WINAPI
1419 SetFileSecurityW(LPCWSTR lpFileName,
1420 SECURITY_INFORMATION SecurityInformation,
1421 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1422 {
1423 OBJECT_ATTRIBUTES ObjectAttributes;
1424 IO_STATUS_BLOCK StatusBlock;
1425 UNICODE_STRING FileName;
1426 ULONG AccessMask = 0;
1427 HANDLE FileHandle;
1428 NTSTATUS Status;
1429
1430 TRACE("SetFileSecurityW() called\n");
1431
1432 SetSecurityAccessMask(SecurityInformation, &AccessMask);
1433
1434 if (!RtlDosPathNameToNtPathName_U(lpFileName,
1435 &FileName,
1436 NULL,
1437 NULL))
1438 {
1439 ERR("Invalid path\n");
1440 SetLastError(ERROR_INVALID_NAME);
1441 return FALSE;
1442 }
1443
1444 InitializeObjectAttributes(&ObjectAttributes,
1445 &FileName,
1446 OBJ_CASE_INSENSITIVE,
1447 NULL,
1448 NULL);
1449
1450 Status = NtOpenFile(&FileHandle,
1451 AccessMask,
1452 &ObjectAttributes,
1453 &StatusBlock,
1454 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1455 0);
1456
1457 RtlFreeHeap(RtlGetProcessHeap(),
1458 0,
1459 FileName.Buffer);
1460
1461 if (!NT_SUCCESS(Status))
1462 {
1463 ERR("NtOpenFile() failed (Status %lx)\n", Status);
1464 SetLastError(RtlNtStatusToDosError(Status));
1465 return FALSE;
1466 }
1467
1468 Status = NtSetSecurityObject(FileHandle,
1469 SecurityInformation,
1470 pSecurityDescriptor);
1471 NtClose(FileHandle);
1472
1473 if (!NT_SUCCESS(Status))
1474 {
1475 ERR("NtSetSecurityObject() failed (Status %lx)\n", Status);
1476 SetLastError(RtlNtStatusToDosError(Status));
1477 return FALSE;
1478 }
1479
1480 return TRUE;
1481 }
1482
1483 /******************************************************************************
1484 * QueryWindows31FilesMigration [ADVAPI32.@]
1485 *
1486 * PARAMS
1487 * x1 []
1488 */
1489 BOOL WINAPI
1490 QueryWindows31FilesMigration( DWORD x1 )
1491 {
1492 FIXME("(%d):stub\n",x1);
1493 return TRUE;
1494 }
1495
1496 /******************************************************************************
1497 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
1498 *
1499 * PARAMS
1500 * x1 []
1501 * x2 []
1502 * x3 []
1503 * x4 []
1504 */
1505 BOOL WINAPI
1506 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
1507 DWORD x4 )
1508 {
1509 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
1510 return TRUE;
1511 }
1512
1513 /*
1514 * @implemented
1515 */
1516 BOOL
1517 WINAPI
1518 RevertToSelf(VOID)
1519 {
1520 NTSTATUS Status;
1521 HANDLE Token = NULL;
1522
1523 Status = NtSetInformationThread(NtCurrentThread(),
1524 ThreadImpersonationToken,
1525 &Token,
1526 sizeof(HANDLE));
1527 if (!NT_SUCCESS(Status))
1528 {
1529 SetLastError(RtlNtStatusToDosError(Status));
1530 return FALSE;
1531 }
1532
1533 return TRUE;
1534 }
1535
1536 /*
1537 * @implemented
1538 */
1539 BOOL
1540 WINAPI
1541 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1542 {
1543 NTSTATUS Status;
1544
1545 Status = RtlImpersonateSelf(ImpersonationLevel);
1546 if (!NT_SUCCESS(Status))
1547 {
1548 SetLastError(RtlNtStatusToDosError(Status));
1549 return FALSE;
1550 }
1551
1552 return TRUE;
1553 }
1554
1555 /*
1556 * @implemented
1557 */
1558 BOOL
1559 WINAPI
1560 AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1561 IN HANDLE ClientToken,
1562 IN DWORD DesiredAccess,
1563 IN PGENERIC_MAPPING GenericMapping,
1564 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
1565 IN OUT LPDWORD PrivilegeSetLength,
1566 OUT LPDWORD GrantedAccess,
1567 OUT LPBOOL AccessStatus)
1568 {
1569 NTSTATUS Status;
1570 NTSTATUS NtAccessStatus;
1571
1572 /* Do the access check */
1573 Status = NtAccessCheck(pSecurityDescriptor,
1574 ClientToken,
1575 DesiredAccess,
1576 GenericMapping,
1577 PrivilegeSet,
1578 (PULONG)PrivilegeSetLength,
1579 (PACCESS_MASK)GrantedAccess,
1580 &NtAccessStatus);
1581
1582 /* See if the access check operation succeeded */
1583 if (!NT_SUCCESS(Status))
1584 {
1585 /* Check failed */
1586 SetLastError(RtlNtStatusToDosError(Status));
1587 return FALSE;
1588 }
1589
1590 /* Now check the access status */
1591 if (!NT_SUCCESS(NtAccessStatus))
1592 {
1593 /* Access denied */
1594 SetLastError(RtlNtStatusToDosError(NtAccessStatus));
1595 *AccessStatus = FALSE;
1596 }
1597 else
1598 {
1599 /* Access granted */
1600 *AccessStatus = TRUE;
1601 }
1602
1603 /* Check succeeded */
1604 return TRUE;
1605 }
1606
1607 /*
1608 * @unimplemented
1609 */
1610 BOOL WINAPI AccessCheckByType(
1611 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1612 PSID PrincipalSelfSid,
1613 HANDLE ClientToken,
1614 DWORD DesiredAccess,
1615 POBJECT_TYPE_LIST ObjectTypeList,
1616 DWORD ObjectTypeListLength,
1617 PGENERIC_MAPPING GenericMapping,
1618 PPRIVILEGE_SET PrivilegeSet,
1619 LPDWORD PrivilegeSetLength,
1620 LPDWORD GrantedAccess,
1621 LPBOOL AccessStatus)
1622 {
1623 FIXME("stub\n");
1624
1625 *AccessStatus = TRUE;
1626
1627 return !*AccessStatus;
1628 }
1629
1630 /*
1631 * @implemented
1632 */
1633 BOOL
1634 WINAPI
1635 SetKernelObjectSecurity(HANDLE Handle,
1636 SECURITY_INFORMATION SecurityInformation,
1637 PSECURITY_DESCRIPTOR SecurityDescriptor)
1638 {
1639 NTSTATUS Status;
1640
1641 Status = NtSetSecurityObject(Handle,
1642 SecurityInformation,
1643 SecurityDescriptor);
1644 if (!NT_SUCCESS(Status))
1645 {
1646 SetLastError(RtlNtStatusToDosError(Status));
1647 return FALSE;
1648 }
1649
1650 return TRUE;
1651 }
1652
1653 /*
1654 * @implemented
1655 */
1656 BOOL
1657 WINAPI
1658 AddAuditAccessAce(PACL pAcl,
1659 DWORD dwAceRevision,
1660 DWORD dwAccessMask,
1661 PSID pSid,
1662 BOOL bAuditSuccess,
1663 BOOL bAuditFailure)
1664 {
1665 NTSTATUS Status;
1666
1667 Status = RtlAddAuditAccessAce(pAcl,
1668 dwAceRevision,
1669 dwAccessMask,
1670 pSid,
1671 bAuditSuccess,
1672 bAuditFailure);
1673 if (!NT_SUCCESS(Status))
1674 {
1675 SetLastError(RtlNtStatusToDosError(Status));
1676 return FALSE;
1677 }
1678
1679 return TRUE;
1680 }
1681
1682 /*
1683 * @implemented
1684 */
1685 BOOL WINAPI
1686 AddAuditAccessAceEx(PACL pAcl,
1687 DWORD dwAceRevision,
1688 DWORD AceFlags,
1689 DWORD dwAccessMask,
1690 PSID pSid,
1691 BOOL bAuditSuccess,
1692 BOOL bAuditFailure)
1693 {
1694 NTSTATUS Status;
1695
1696 Status = RtlAddAuditAccessAceEx(pAcl,
1697 dwAceRevision,
1698 AceFlags,
1699 dwAccessMask,
1700 pSid,
1701 bAuditSuccess,
1702 bAuditFailure);
1703 if (!NT_SUCCESS(Status))
1704 {
1705 SetLastError(RtlNtStatusToDosError(Status));
1706 return FALSE;
1707 }
1708
1709 return TRUE;
1710 }
1711
1712 /******************************************************************************
1713 * LookupAccountNameA [ADVAPI32.@]
1714 *
1715 * @implemented
1716 */
1717 BOOL
1718 WINAPI
1719 LookupAccountNameA(LPCSTR SystemName,
1720 LPCSTR AccountName,
1721 PSID Sid,
1722 LPDWORD SidLength,
1723 LPSTR ReferencedDomainName,
1724 LPDWORD hReferencedDomainNameLength,
1725 PSID_NAME_USE SidNameUse)
1726 {
1727 BOOL ret;
1728 UNICODE_STRING lpSystemW;
1729 UNICODE_STRING lpAccountW;
1730 LPWSTR lpReferencedDomainNameW = NULL;
1731
1732 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, SystemName);
1733 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, AccountName);
1734
1735 if (ReferencedDomainName)
1736 lpReferencedDomainNameW = HeapAlloc(GetProcessHeap(),
1737 0,
1738 *hReferencedDomainNameLength * sizeof(WCHAR));
1739
1740 ret = LookupAccountNameW(lpSystemW.Buffer,
1741 lpAccountW.Buffer,
1742 Sid,
1743 SidLength,
1744 lpReferencedDomainNameW,
1745 hReferencedDomainNameLength,
1746 SidNameUse);
1747
1748 if (ret && lpReferencedDomainNameW)
1749 {
1750 WideCharToMultiByte(CP_ACP,
1751 0,
1752 lpReferencedDomainNameW,
1753 *hReferencedDomainNameLength + 1,
1754 ReferencedDomainName,
1755 *hReferencedDomainNameLength + 1,
1756 NULL,
1757 NULL);
1758 }
1759
1760 RtlFreeUnicodeString(&lpSystemW);
1761 RtlFreeUnicodeString(&lpAccountW);
1762 HeapFree(GetProcessHeap(), 0, lpReferencedDomainNameW);
1763
1764 return ret;
1765 }
1766
1767 /**********************************************************************
1768 * PrivilegeCheck EXPORTED
1769 *
1770 * @implemented
1771 */
1772 BOOL WINAPI
1773 PrivilegeCheck(HANDLE ClientToken,
1774 PPRIVILEGE_SET RequiredPrivileges,
1775 LPBOOL pfResult)
1776 {
1777 BOOLEAN Result;
1778 NTSTATUS Status;
1779
1780 Status = NtPrivilegeCheck(ClientToken,
1781 RequiredPrivileges,
1782 &Result);
1783 if (!NT_SUCCESS(Status))
1784 {
1785 SetLastError(RtlNtStatusToDosError(Status));
1786 return FALSE;
1787 }
1788
1789 *pfResult = (BOOL)Result;
1790
1791 return TRUE;
1792 }
1793
1794 /******************************************************************************
1795 * GetSecurityInfoExW EXPORTED
1796 */
1797 DWORD
1798 WINAPI
1799 GetSecurityInfoExA(HANDLE hObject,
1800 SE_OBJECT_TYPE ObjectType,
1801 SECURITY_INFORMATION SecurityInfo,
1802 LPCSTR lpProvider,
1803 LPCSTR lpProperty,
1804 PACTRL_ACCESSA *ppAccessList,
1805 PACTRL_AUDITA *ppAuditList,
1806 LPSTR *lppOwner,
1807 LPSTR *lppGroup)
1808 {
1809 FIXME("%s() not implemented!\n", __FUNCTION__);
1810 return ERROR_BAD_PROVIDER;
1811 }
1812
1813
1814 /******************************************************************************
1815 * GetSecurityInfoExW EXPORTED
1816 */
1817 DWORD
1818 WINAPI
1819 GetSecurityInfoExW(HANDLE hObject,
1820 SE_OBJECT_TYPE ObjectType,
1821 SECURITY_INFORMATION SecurityInfo,
1822 LPCWSTR lpProvider,
1823 LPCWSTR lpProperty,
1824 PACTRL_ACCESSW *ppAccessList,
1825 PACTRL_AUDITW *ppAuditList,
1826 LPWSTR *lppOwner,
1827 LPWSTR *lppGroup)
1828 {
1829 FIXME("%s() not implemented!\n", __FUNCTION__);
1830 return ERROR_BAD_PROVIDER;
1831 }
1832
1833 /******************************************************************************
1834 * BuildExplicitAccessWithNameA [ADVAPI32.@]
1835 */
1836 VOID WINAPI
1837 BuildExplicitAccessWithNameA(PEXPLICIT_ACCESSA pExplicitAccess,
1838 LPSTR pTrusteeName,
1839 DWORD AccessPermissions,
1840 ACCESS_MODE AccessMode,
1841 DWORD Inheritance)
1842 {
1843 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1844 pExplicitAccess->grfAccessMode = AccessMode;
1845 pExplicitAccess->grfInheritance = Inheritance;
1846
1847 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1848 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1849 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1850 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1851 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1852 }
1853
1854
1855 /******************************************************************************
1856 * BuildExplicitAccessWithNameW [ADVAPI32.@]
1857 */
1858 VOID WINAPI
1859 BuildExplicitAccessWithNameW(PEXPLICIT_ACCESSW pExplicitAccess,
1860 LPWSTR pTrusteeName,
1861 DWORD AccessPermissions,
1862 ACCESS_MODE AccessMode,
1863 DWORD Inheritance)
1864 {
1865 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1866 pExplicitAccess->grfAccessMode = AccessMode;
1867 pExplicitAccess->grfInheritance = Inheritance;
1868
1869 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1870 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1871 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1872 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1873 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1874 }
1875
1876 /******************************************************************************
1877 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
1878 */
1879 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
1880 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
1881 LPSTR InheritedObjectTypeName, LPSTR Name )
1882 {
1883 DWORD ObjectsPresent = 0;
1884
1885 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1886 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
1887
1888 /* Fill the OBJECTS_AND_NAME structure */
1889 pObjName->ObjectType = ObjectType;
1890 if (ObjectTypeName != NULL)
1891 {
1892 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1893 }
1894
1895 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1896 if (InheritedObjectTypeName != NULL)
1897 {
1898 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1899 }
1900
1901 pObjName->ObjectsPresent = ObjectsPresent;
1902 pObjName->ptstrName = Name;
1903
1904 /* Fill the TRUSTEE structure */
1905 pTrustee->pMultipleTrustee = NULL;
1906 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1907 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1908 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1909 pTrustee->ptstrName = (LPSTR)pObjName;
1910 }
1911
1912 /******************************************************************************
1913 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
1914 */
1915 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
1916 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
1917 LPWSTR InheritedObjectTypeName, LPWSTR Name )
1918 {
1919 DWORD ObjectsPresent = 0;
1920
1921 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1922 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
1923
1924 /* Fill the OBJECTS_AND_NAME structure */
1925 pObjName->ObjectType = ObjectType;
1926 if (ObjectTypeName != NULL)
1927 {
1928 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1929 }
1930
1931 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1932 if (InheritedObjectTypeName != NULL)
1933 {
1934 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1935 }
1936
1937 pObjName->ObjectsPresent = ObjectsPresent;
1938 pObjName->ptstrName = Name;
1939
1940 /* Fill the TRUSTEE structure */
1941 pTrustee->pMultipleTrustee = NULL;
1942 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1943 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1944 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1945 pTrustee->ptstrName = (LPWSTR)pObjName;
1946 }
1947
1948 /******************************************************************************
1949 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
1950 */
1951 VOID WINAPI
1952 BuildTrusteeWithObjectsAndSidA(PTRUSTEEA pTrustee,
1953 POBJECTS_AND_SID pObjSid,
1954 GUID *pObjectGuid,
1955 GUID *pInheritedObjectGuid,
1956 PSID pSid)
1957 {
1958 DWORD ObjectsPresent = 0;
1959
1960 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
1961
1962 /* Fill the OBJECTS_AND_SID structure */
1963 if (pObjectGuid != NULL)
1964 {
1965 pObjSid->ObjectTypeGuid = *pObjectGuid;
1966 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1967 }
1968 else
1969 {
1970 ZeroMemory(&pObjSid->ObjectTypeGuid,
1971 sizeof(GUID));
1972 }
1973
1974 if (pInheritedObjectGuid != NULL)
1975 {
1976 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
1977 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1978 }
1979 else
1980 {
1981 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
1982 sizeof(GUID));
1983 }
1984
1985 pObjSid->ObjectsPresent = ObjectsPresent;
1986 pObjSid->pSid = pSid;
1987
1988 /* Fill the TRUSTEE structure */
1989 pTrustee->pMultipleTrustee = NULL;
1990 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1991 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
1992 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1993 pTrustee->ptstrName = (LPSTR) pObjSid;
1994 }
1995
1996
1997 /******************************************************************************
1998 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
1999 */
2000 VOID WINAPI
2001 BuildTrusteeWithObjectsAndSidW(PTRUSTEEW pTrustee,
2002 POBJECTS_AND_SID pObjSid,
2003 GUID *pObjectGuid,
2004 GUID *pInheritedObjectGuid,
2005 PSID pSid)
2006 {
2007 DWORD ObjectsPresent = 0;
2008
2009 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
2010
2011 /* Fill the OBJECTS_AND_SID structure */
2012 if (pObjectGuid != NULL)
2013 {
2014 pObjSid->ObjectTypeGuid = *pObjectGuid;
2015 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
2016 }
2017 else
2018 {
2019 ZeroMemory(&pObjSid->ObjectTypeGuid,
2020 sizeof(GUID));
2021 }
2022
2023 if (pInheritedObjectGuid != NULL)
2024 {
2025 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
2026 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
2027 }
2028 else
2029 {
2030 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
2031 sizeof(GUID));
2032 }
2033
2034 pObjSid->ObjectsPresent = ObjectsPresent;
2035 pObjSid->pSid = pSid;
2036
2037 /* Fill the TRUSTEE structure */
2038 pTrustee->pMultipleTrustee = NULL;
2039 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2040 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
2041 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2042 pTrustee->ptstrName = (LPWSTR) pObjSid;
2043 }
2044
2045 /******************************************************************************
2046 * BuildTrusteeWithSidA [ADVAPI32.@]
2047 */
2048 VOID WINAPI
2049 BuildTrusteeWithSidA(PTRUSTEE_A pTrustee,
2050 PSID pSid)
2051 {
2052 TRACE("%p %p\n", pTrustee, pSid);
2053
2054 pTrustee->pMultipleTrustee = NULL;
2055 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2056 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
2057 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2058 pTrustee->ptstrName = (LPSTR) pSid;
2059 }
2060
2061
2062 /******************************************************************************
2063 * BuildTrusteeWithSidW [ADVAPI32.@]
2064 */
2065 VOID WINAPI
2066 BuildTrusteeWithSidW(PTRUSTEE_W pTrustee,
2067 PSID pSid)
2068 {
2069 TRACE("%p %p\n", pTrustee, pSid);
2070
2071 pTrustee->pMultipleTrustee = NULL;
2072 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2073 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
2074 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2075 pTrustee->ptstrName = (LPWSTR) pSid;
2076 }
2077
2078 /******************************************************************************
2079 * BuildTrusteeWithNameA [ADVAPI32.@]
2080 */
2081 VOID WINAPI
2082 BuildTrusteeWithNameA(PTRUSTEE_A pTrustee,
2083 LPSTR name)
2084 {
2085 TRACE("%p %s\n", pTrustee, name);
2086
2087 pTrustee->pMultipleTrustee = NULL;
2088 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2089 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
2090 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2091 pTrustee->ptstrName = name;
2092 }
2093
2094 /******************************************************************************
2095 * BuildTrusteeWithNameW [ADVAPI32.@]
2096 */
2097 VOID WINAPI
2098 BuildTrusteeWithNameW(PTRUSTEE_W pTrustee,
2099 LPWSTR name)
2100 {
2101 TRACE("%p %s\n", pTrustee, name);
2102
2103 pTrustee->pMultipleTrustee = NULL;
2104 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2105 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
2106 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2107 pTrustee->ptstrName = name;
2108 }
2109
2110 /******************************************************************************
2111 * GetTrusteeFormW [ADVAPI32.@]
2112 */
2113 TRUSTEE_FORM WINAPI
2114 GetTrusteeFormA(PTRUSTEE_A pTrustee)
2115 {
2116 return pTrustee->TrusteeForm;
2117 }
2118
2119
2120 /******************************************************************************
2121 * GetTrusteeFormW [ADVAPI32.@]
2122 */
2123 TRUSTEE_FORM WINAPI
2124 GetTrusteeFormW(PTRUSTEE_W pTrustee)
2125 {
2126 return pTrustee->TrusteeForm;
2127 }
2128
2129 /******************************************************************************
2130 * GetTrusteeNameA [ADVAPI32.@]
2131 */
2132 LPSTR WINAPI
2133 GetTrusteeNameA(PTRUSTEE_A pTrustee)
2134 {
2135 return pTrustee->ptstrName;
2136 }
2137
2138
2139 /******************************************************************************
2140 * GetTrusteeNameW [ADVAPI32.@]
2141 */
2142 LPWSTR WINAPI
2143 GetTrusteeNameW(PTRUSTEE_W pTrustee)
2144 {
2145 return pTrustee->ptstrName;
2146 }
2147
2148 /******************************************************************************
2149 * GetTrusteeTypeA [ADVAPI32.@]
2150 */
2151 TRUSTEE_TYPE WINAPI
2152 GetTrusteeTypeA(PTRUSTEE_A pTrustee)
2153 {
2154 return pTrustee->TrusteeType;
2155 }
2156
2157 /******************************************************************************
2158 * GetTrusteeTypeW [ADVAPI32.@]
2159 */
2160 TRUSTEE_TYPE WINAPI
2161 GetTrusteeTypeW(PTRUSTEE_W pTrustee)
2162 {
2163 return pTrustee->TrusteeType;
2164 }
2165
2166 /*
2167 * @implemented
2168 */
2169 BOOL
2170 WINAPI
2171 SetAclInformation(PACL pAcl,
2172 LPVOID pAclInformation,
2173 DWORD nAclInformationLength,
2174 ACL_INFORMATION_CLASS dwAclInformationClass)
2175 {
2176 NTSTATUS Status;
2177
2178 Status = RtlSetInformationAcl(pAcl,
2179 pAclInformation,
2180 nAclInformationLength,
2181 dwAclInformationClass);
2182 if (!NT_SUCCESS(Status))
2183 {
2184 SetLastError(RtlNtStatusToDosError(Status));
2185 return FALSE;
2186 }
2187
2188 return TRUE;
2189 }
2190
2191 /**********************************************************************
2192 * SetNamedSecurityInfoA EXPORTED
2193 *
2194 * @implemented
2195 */
2196 DWORD
2197 WINAPI
2198 SetNamedSecurityInfoA(LPSTR pObjectName,
2199 SE_OBJECT_TYPE ObjectType,
2200 SECURITY_INFORMATION SecurityInfo,
2201 PSID psidOwner,
2202 PSID psidGroup,
2203 PACL pDacl,
2204 PACL pSacl)
2205 {
2206 UNICODE_STRING ObjectName;
2207 DWORD Ret;
2208
2209 if (!RtlCreateUnicodeStringFromAsciiz(&ObjectName, pObjectName))
2210 {
2211 return ERROR_NOT_ENOUGH_MEMORY;
2212 }
2213
2214 Ret = SetNamedSecurityInfoW(ObjectName.Buffer,
2215 ObjectType,
2216 SecurityInfo,
2217 psidOwner,
2218 psidGroup,
2219 pDacl,
2220 pSacl);
2221
2222 RtlFreeUnicodeString(&ObjectName);
2223
2224 return Ret;
2225 }
2226
2227 /*
2228 * @implemented
2229 */
2230 BOOL
2231 WINAPI
2232 AreAllAccessesGranted(DWORD GrantedAccess,
2233 DWORD DesiredAccess)
2234 {
2235 return (BOOL)RtlAreAllAccessesGranted(GrantedAccess,
2236 DesiredAccess);
2237 }
2238
2239 /*
2240 * @implemented
2241 */
2242 BOOL
2243 WINAPI
2244 AreAnyAccessesGranted(DWORD GrantedAccess,
2245 DWORD DesiredAccess)
2246 {
2247 return (BOOL)RtlAreAnyAccessesGranted(GrantedAccess,
2248 DesiredAccess);
2249 }
2250
2251 /******************************************************************************
2252 * ParseAclStringFlags
2253 */
2254 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
2255 {
2256 DWORD flags = 0;
2257 LPCWSTR szAcl = *StringAcl;
2258
2259 while (*szAcl != '(')
2260 {
2261 if (*szAcl == 'P')
2262 {
2263 flags |= SE_DACL_PROTECTED;
2264 }
2265 else if (*szAcl == 'A')
2266 {
2267 szAcl++;
2268 if (*szAcl == 'R')
2269 flags |= SE_DACL_AUTO_INHERIT_REQ;
2270 else if (*szAcl == 'I')
2271 flags |= SE_DACL_AUTO_INHERITED;
2272 }
2273 szAcl++;
2274 }
2275
2276 *StringAcl = szAcl;
2277 return flags;
2278 }
2279
2280 /******************************************************************************
2281 * ParseAceStringType
2282 */
2283 static const ACEFLAG AceType[] =
2284 {
2285 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
2286 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
2287 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
2288 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
2289 /*
2290 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
2291 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
2292 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
2293 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
2294 */
2295 { NULL, 0 },
2296 };
2297
2298 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
2299 {
2300 UINT len = 0;
2301 LPCWSTR szAcl = *StringAcl;
2302 const ACEFLAG *lpaf = AceType;
2303
2304 while (*szAcl == ' ')
2305 szAcl++;
2306
2307 while (lpaf->wstr &&
2308 (len = strlenW(lpaf->wstr)) &&
2309 strncmpW(lpaf->wstr, szAcl, len))
2310 lpaf++;
2311
2312 if (!lpaf->wstr)
2313 return 0;
2314
2315 *StringAcl = szAcl + len;
2316 return lpaf->value;
2317 }
2318
2319
2320 /******************************************************************************
2321 * ParseAceStringFlags
2322 */
2323 static const ACEFLAG AceFlags[] =
2324 {
2325 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
2326 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
2327 { SDDL_INHERITED, INHERITED_ACE },
2328 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
2329 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
2330 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
2331 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
2332 { NULL, 0 },
2333 };
2334
2335 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
2336 {
2337 UINT len = 0;
2338 BYTE flags = 0;
2339 LPCWSTR szAcl = *StringAcl;
2340
2341 while (*szAcl == ' ')
2342 szAcl++;
2343
2344 while (*szAcl != ';')
2345 {
2346 const ACEFLAG *lpaf = AceFlags;
2347
2348 while (lpaf->wstr &&
2349 (len = strlenW(lpaf->wstr)) &&
2350 strncmpW(lpaf->wstr, szAcl, len))
2351 lpaf++;
2352
2353 if (!lpaf->wstr)
2354 return 0;
2355
2356 flags |= lpaf->value;
2357 szAcl += len;
2358 }
2359
2360 *StringAcl = szAcl;
2361 return flags;
2362 }
2363
2364
2365 /******************************************************************************
2366 * ParseAceStringRights
2367 */
2368 static const ACEFLAG AceRights[] =
2369 {
2370 { SDDL_GENERIC_ALL, GENERIC_ALL },
2371 { SDDL_GENERIC_READ, GENERIC_READ },
2372 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
2373 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
2374
2375 { SDDL_READ_CONTROL, READ_CONTROL },
2376 { SDDL_STANDARD_DELETE, DELETE },
2377 { SDDL_WRITE_DAC, WRITE_DAC },
2378 { SDDL_WRITE_OWNER, WRITE_OWNER },
2379
2380 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
2381 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
2382 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
2383 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
2384 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
2385 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
2386 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
2387 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
2388 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
2389
2390 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
2391 { SDDL_FILE_READ, FILE_GENERIC_READ },
2392 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
2393 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
2394
2395 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
2396 { SDDL_KEY_READ, KEY_READ },
2397 { SDDL_KEY_WRITE, KEY_WRITE },
2398 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
2399 { NULL, 0 },
2400 };
2401
2402 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
2403 {
2404 UINT len = 0;
2405 DWORD rights = 0;
2406 LPCWSTR szAcl = *StringAcl;
2407
2408 while (*szAcl == ' ')
2409 szAcl++;
2410
2411 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
2412 {
2413 LPCWSTR p = szAcl;
2414
2415 while (*p && *p != ';')
2416 p++;
2417
2418 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
2419 {
2420 rights = strtoulW(szAcl, NULL, 16);
2421 szAcl = p;
2422 }
2423 else
2424 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
2425 }
2426 else
2427 {
2428 while (*szAcl != ';')
2429 {
2430 const ACEFLAG *lpaf = AceRights;
2431
2432 while (lpaf->wstr &&
2433 (len = strlenW(lpaf->wstr)) &&
2434 strncmpW(lpaf->wstr, szAcl, len))
2435 {
2436 lpaf++;
2437 }
2438
2439 if (!lpaf->wstr)
2440 return 0;
2441
2442 rights |= lpaf->value;
2443 szAcl += len;
2444 }
2445 }
2446
2447 *StringAcl = szAcl;
2448 return rights;
2449 }
2450
2451
2452 /******************************************************************************
2453 * ParseStringAclToAcl
2454 *
2455 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
2456 */
2457 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
2458 PACL pAcl, LPDWORD cBytes)
2459 {
2460 DWORD val;
2461 DWORD sidlen;
2462 DWORD length = sizeof(ACL);
2463 DWORD acesize = 0;
2464 DWORD acecount = 0;
2465 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
2466 DWORD error = ERROR_INVALID_ACL;
2467
2468 TRACE("%s\n", debugstr_w(StringAcl));
2469
2470 if (!StringAcl)
2471 return FALSE;
2472
2473 if (pAcl) /* pAce is only useful if we're setting values */
2474 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
2475
2476 /* Parse ACL flags */
2477 *lpdwFlags = ParseAclStringFlags(&StringAcl);
2478
2479 /* Parse ACE */
2480 while (*StringAcl == '(')
2481 {
2482 StringAcl++;
2483
2484 /* Parse ACE type */
2485 val = ParseAceStringType(&StringAcl);
2486 if (pAce)
2487 pAce->Header.AceType = (BYTE) val;
2488 if (*StringAcl != ';')
2489 {
2490 error = RPC_S_INVALID_STRING_UUID;
2491 goto lerr;
2492 }
2493 StringAcl++;
2494
2495 /* Parse ACE flags */
2496 val = ParseAceStringFlags(&StringAcl);
2497 if (pAce)
2498 pAce->Header.AceFlags = (BYTE) val;
2499 if (*StringAcl != ';')
2500 goto lerr;
2501 StringAcl++;
2502
2503 /* Parse ACE rights */
2504 val = ParseAceStringRights(&StringAcl);
2505 if (pAce)
2506 pAce->Mask = val;
2507 if (*StringAcl != ';')
2508 goto lerr;
2509 StringAcl++;
2510
2511 /* Parse ACE object guid */
2512 while (*StringAcl == ' ')
2513 StringAcl++;
2514 if (*StringAcl != ';')
2515 {
2516 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
2517 goto lerr;
2518 }
2519 StringAcl++;
2520
2521 /* Parse ACE inherit object guid */
2522 while (*StringAcl == ' ')
2523 StringAcl++;
2524 if (*StringAcl != ';')
2525 {
2526 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
2527 goto lerr;
2528 }
2529 StringAcl++;
2530
2531 /* Parse ACE account sid */
2532 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
2533 {
2534 while (*StringAcl && *StringAcl != ')')
2535 StringAcl++;
2536 }
2537
2538 if (*StringAcl != ')')
2539 goto lerr;
2540 StringAcl++;
2541
2542 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
2543 length += acesize;
2544 if (pAce)
2545 {
2546 pAce->Header.AceSize = acesize;
2547 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
2548 }
2549 acecount++;
2550 }
2551
2552 *cBytes = length;
2553
2554 if (length > 0xffff)
2555 {
2556 ERR("ACL too large\n");
2557 goto lerr;
2558 }
2559
2560 if (pAcl)
2561 {
2562 pAcl->AclRevision = ACL_REVISION;
2563 pAcl->Sbz1 = 0;
2564 pAcl->AclSize = length;
2565 pAcl->AceCount = acecount++;
2566 pAcl->Sbz2 = 0;
2567 }
2568 return TRUE;
2569
2570 lerr:
2571 SetLastError(error);
2572 WARN("Invalid ACE string format\n");
2573 return FALSE;
2574 }
2575
2576
2577 /******************************************************************************
2578 * ParseStringSecurityDescriptorToSecurityDescriptor
2579 */
2580 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
2581 LPCWSTR StringSecurityDescriptor,
2582 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
2583 LPDWORD cBytes)
2584 {
2585 BOOL bret = FALSE;
2586 WCHAR toktype;
2587 WCHAR tok[MAX_PATH];
2588 LPCWSTR lptoken;
2589 LPBYTE lpNext = NULL;
2590 DWORD len;
2591
2592 *cBytes = sizeof(SECURITY_DESCRIPTOR);
2593
2594 if (SecurityDescriptor)
2595 lpNext = (LPBYTE)(SecurityDescriptor + 1);
2596
2597 while (*StringSecurityDescriptor == ' ')
2598 StringSecurityDescriptor++;
2599
2600 while (*StringSecurityDescriptor)
2601 {
2602 toktype = *StringSecurityDescriptor;
2603
2604 /* Expect char identifier followed by ':' */
2605 StringSecurityDescriptor++;
2606 if (*StringSecurityDescriptor != ':')
2607 {
2608 SetLastError(ERROR_INVALID_PARAMETER);
2609 goto lend;
2610 }
2611 StringSecurityDescriptor++;
2612
2613 /* Extract token */
2614 lptoken = StringSecurityDescriptor;
2615 while (*lptoken && *lptoken != ':')
2616 lptoken++;
2617
2618 if (*lptoken)
2619 lptoken--;
2620
2621 len = lptoken - StringSecurityDescriptor;
2622 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
2623 tok[len] = 0;
2624
2625 switch (toktype)
2626 {
2627 case 'O':
2628 {
2629 DWORD bytes;
2630
2631 if (!ParseStringSidToSid(tok, lpNext, &bytes))
2632 goto lend;
2633
2634 if (SecurityDescriptor)
2635 {
2636 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
2637 lpNext += bytes; /* Advance to next token */
2638 }
2639
2640 *cBytes += bytes;
2641
2642 break;
2643 }
2644
2645 case 'G':
2646 {
2647 DWORD bytes;
2648
2649 if (!ParseStringSidToSid(tok, lpNext, &bytes))
2650 goto lend;
2651
2652 if (SecurityDescriptor)
2653 {
2654 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
2655 lpNext += bytes; /* Advance to next token */
2656 }
2657
2658 *cBytes += bytes;
2659
2660 break;
2661 }
2662
2663 case 'D':
2664 {
2665 DWORD flags;
2666 DWORD bytes;
2667
2668 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
2669 goto lend;
2670
2671 if (SecurityDescriptor)
2672 {
2673 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
2674 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
2675 lpNext += bytes; /* Advance to next token */
2676 }
2677
2678 *cBytes += bytes;
2679
2680 break;
2681 }
2682
2683 case 'S':
2684 {
2685 DWORD flags;
2686 DWORD bytes;
2687
2688 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
2689 goto lend;
2690
2691 if (SecurityDescriptor)
2692 {
2693 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
2694 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
2695 lpNext += bytes; /* Advance to next token */
2696 }
2697
2698 *cBytes += bytes;
2699
2700 break;
2701 }
2702
2703 default:
2704 FIXME("Unknown token\n");
2705 SetLastError(ERROR_INVALID_PARAMETER);
2706 goto lend;
2707 }
2708
2709 StringSecurityDescriptor = lptoken;
2710 }
2711
2712 bret = TRUE;
2713
2714 lend:
2715 return bret;
2716 }
2717
2718 /* Winehq cvs 20050916 */
2719 /******************************************************************************
2720 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
2721 * @implemented
2722 */
2723 BOOL
2724 WINAPI
2725 ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor,
2726 DWORD StringSDRevision,
2727 PSECURITY_DESCRIPTOR* SecurityDescriptor,
2728 PULONG SecurityDescriptorSize)
2729 {
2730 UINT len;
2731 BOOL ret = FALSE;
2732 LPWSTR StringSecurityDescriptorW;
2733
2734 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
2735 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2736
2737 if (StringSecurityDescriptorW)
2738 {
2739 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
2740
2741 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
2742 StringSDRevision, SecurityDescriptor,
2743 SecurityDescriptorSize);
2744 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
2745 }
2746
2747 return ret;
2748 }
2749
2750 /******************************************************************************
2751 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
2752 * @implemented
2753 */
2754 BOOL WINAPI
2755 ConvertStringSecurityDescriptorToSecurityDescriptorW(LPCWSTR StringSecurityDescriptor,
2756 DWORD StringSDRevision,
2757 PSECURITY_DESCRIPTOR* SecurityDescriptor,
2758 PULONG SecurityDescriptorSize)
2759 {
2760 DWORD cBytes;
2761 SECURITY_DESCRIPTOR* psd;
2762 BOOL bret = FALSE;
2763
2764 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
2765
2766 if (GetVersion() & 0x80000000)
2767 {
2768 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2769 goto lend;
2770 }
2771 else if (!StringSecurityDescriptor || !SecurityDescriptor)
2772 {
2773 SetLastError(ERROR_INVALID_PARAMETER);
2774 goto lend;
2775 }
2776 else if (StringSDRevision != SID_REVISION)
2777 {
2778 SetLastError(ERROR_UNKNOWN_REVISION);
2779 goto lend;
2780 }
2781
2782 /* Compute security descriptor length */
2783 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
2784 NULL, &cBytes))
2785 goto lend;
2786
2787 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
2788 if (!psd) goto lend;
2789
2790 psd->Revision = SID_REVISION;
2791 psd->Control |= SE_SELF_RELATIVE;
2792
2793 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
2794 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
2795 {
2796 LocalFree(psd);
2797 goto lend;
2798 }
2799
2800 if (SecurityDescriptorSize)
2801 *SecurityDescriptorSize = cBytes;
2802
2803 bret = TRUE;
2804
2805 lend:
2806 TRACE(" ret=%d\n", bret);
2807 return bret;
2808 }
2809
2810 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
2811 {
2812 if (cch == -1)
2813 cch = strlenW(string);
2814
2815 if (plen)
2816 *plen += cch;
2817
2818 if (pwptr)
2819 {
2820 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
2821 *pwptr += cch;
2822 }
2823 }
2824
2825 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
2826 {
2827 DWORD i;
2828 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
2829 WCHAR subauthfmt[] = { '-','%','u',0 };
2830 WCHAR buf[26];
2831 SID *pisid = psid;
2832
2833 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
2834 {
2835 SetLastError(ERROR_INVALID_SID);
2836 return FALSE;
2837 }
2838
2839 if (pisid->IdentifierAuthority.Value[0] ||
2840 pisid->IdentifierAuthority.Value[1])
2841 {
2842 FIXME("not matching MS' bugs\n");
2843 SetLastError(ERROR_INVALID_SID);
2844 return FALSE;
2845 }
2846
2847 sprintfW( buf, fmt, pisid->Revision,
2848 MAKELONG(
2849 MAKEWORD( pisid->IdentifierAuthority.Value[5],
2850 pisid->IdentifierAuthority.Value[4] ),
2851 MAKEWORD( pisid->IdentifierAuthority.Value[3],
2852 pisid->IdentifierAuthority.Value[2] )
2853 ) );
2854 DumpString(buf, -1, pwptr, plen);
2855
2856 for( i=0; i<pisid->SubAuthorityCount; i++ )
2857 {
2858 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
2859 DumpString(buf, -1, pwptr, plen);
2860 }
2861 return TRUE;
2862 }
2863
2864 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
2865 {
2866 size_t i;
2867 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
2868 {
2869 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
2870 {
2871 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
2872 return TRUE;
2873 }
2874 }
2875
2876 return DumpSidNumeric(psid, pwptr, plen);
2877 }
2878
2879 static const LPCWSTR AceRightBitNames[32] = {
2880 SDDL_CREATE_CHILD, /* 0 */
2881 SDDL_DELETE_CHILD,
2882 SDDL_LIST_CHILDREN,
2883 SDDL_SELF_WRITE,
2884 SDDL_READ_PROPERTY, /* 4 */
2885 SDDL_WRITE_PROPERTY,
2886 SDDL_DELETE_TREE,
2887 SDDL_LIST_OBJECT,
2888 SDDL_CONTROL_ACCESS, /* 8 */
2889 NULL,
2890 NULL,
2891 NULL,
2892 NULL, /* 12 */
2893 NULL,
2894 NULL,
2895 NULL,
2896 SDDL_STANDARD_DELETE, /* 16 */
2897 SDDL_READ_CONTROL,
2898 SDDL_WRITE_DAC,
2899 SDDL_WRITE_OWNER,
2900 NULL, /* 20 */
2901 NULL,
2902 NULL,
2903 NULL,
2904 NULL, /* 24 */
2905 NULL,
2906 NULL,
2907 NULL,
2908 SDDL_GENERIC_ALL, /* 28 */
2909 SDDL_GENERIC_EXECUTE,
2910 SDDL_GENERIC_WRITE,
2911 SDDL_GENERIC_READ
2912 };
2913
2914 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
2915 {
2916 static const WCHAR fmtW[] = {'0','x','%','x',0};
2917 WCHAR buf[15];
2918 size_t i;
2919
2920 if (mask == 0)
2921 return;
2922
2923 /* first check if the right have name */
2924 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
2925 {
2926 if (AceRights[i].wstr == NULL)
2927 break;
2928 if (mask == AceRights[i].value)
2929 {
2930 DumpString(AceRights[i].wstr, -1, pwptr, plen);
2931 return;
2932 }
2933 }
2934
2935 /* then check if it can be built from bit names */
2936 for (i = 0; i < 32; i++)
2937 {
2938 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
2939 {
2940 /* can't be built from bit names */
2941 sprintfW(buf, fmtW, mask);
2942 DumpString(buf, -1, pwptr, plen);
2943 return;
2944 }
2945 }
2946
2947 /* build from bit names */
2948 for (i = 0; i < 32; i++)
2949 if (mask & (1 << i))
2950 DumpString(AceRightBitNames[i], -1, pwptr, plen);
2951 }
2952
2953 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
2954 {
2955 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
2956 static const WCHAR openbr = '(';
2957 static const WCHAR closebr = ')';
2958 static const WCHAR semicolon = ';';
2959
2960 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
2961 {
2962 SetLastError(ERROR_INVALID_ACL);
2963 return FALSE;
2964 }
2965
2966 piace = pace;
2967 DumpString(&openbr, 1, pwptr, plen);
2968 switch (piace->Header.AceType)
2969 {
2970 case ACCESS_ALLOWED_ACE_TYPE:
2971 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
2972 break;
2973 case ACCESS_DENIED_ACE_TYPE:
2974 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
2975 break;
2976 case SYSTEM_AUDIT_ACE_TYPE:
2977 DumpString(SDDL_AUDIT, -1, pwptr, plen);
2978 break;
2979 case SYSTEM_ALARM_ACE_TYPE:
2980 DumpString(SDDL_ALARM, -1, pwptr, plen);
2981 break;
2982 }
2983 DumpString(&semicolon, 1, pwptr, plen);
2984
2985 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
2986 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
2987 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
2988 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
2989 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
2990 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
2991 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
2992 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
2993 if (piace->Header.AceFlags & INHERITED_ACE)
2994 DumpString(SDDL_INHERITED, -1, pwptr, plen);
2995 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
2996 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
2997 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
2998 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
2999 DumpString(&semicolon, 1, pwptr, plen);
3000 DumpRights(piace->Mask, pwptr, plen);
3001 DumpString(&semicolon, 1, pwptr, plen);
3002 /* objects not supported */
3003 DumpString(&semicolon, 1, pwptr, plen);
3004 /* objects not supported */
3005 DumpString(&semicolon, 1, pwptr, plen);
3006 if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
3007 return FALSE;
3008 DumpString(&closebr, 1, pwptr, plen);
3009 return TRUE;
3010 }
3011
3012 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
3013 {
3014 WORD count;
3015 int i;
3016
3017 if (protected)
3018 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
3019 if (autoInheritReq)
3020 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
3021 if (autoInherited)
3022 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
3023
3024 if (pacl == NULL)
3025 return TRUE;
3026
3027 if (!IsValidAcl(pacl))
3028 return FALSE;
3029
3030 count = pacl->AceCount;
3031 for (i = 0; i < count; i++)
3032 {
3033 LPVOID ace;
3034 if (!GetAce(pacl, i, &ace))
3035 return FALSE;
3036 if (!DumpAce(ace, pwptr, plen))
3037 return FALSE;
3038 }
3039
3040 return TRUE;
3041 }
3042
3043 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3044 {
3045 static const WCHAR prefix[] = {'O',':',0};
3046 BOOL bDefaulted;
3047 PSID psid;
3048
3049 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
3050 return FALSE;
3051
3052 if (psid == NULL)
3053 return TRUE;
3054
3055 DumpString(prefix, -1, pwptr, plen);
3056 if (!DumpSid(psid, pwptr, plen))
3057 return FALSE;
3058 return TRUE;
3059 }
3060
3061 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3062 {
3063 static const WCHAR prefix[] = {'G',':',0};
3064 BOOL bDefaulted;
3065 PSID psid;
3066
3067 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
3068 return FALSE;
3069
3070 if (psid == NULL)
3071 return TRUE;
3072
3073 DumpString(prefix, -1, pwptr, plen);
3074 if (!DumpSid(psid, pwptr, plen))
3075 return FALSE;
3076 return TRUE;
3077 }
3078
3079 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3080 {
3081 static const WCHAR dacl[] = {'D',':',0};
3082 SECURITY_DESCRIPTOR_CONTROL control;
3083 BOOL present, defaulted;
3084 DWORD revision;
3085 PACL pacl;
3086
3087 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
3088 return FALSE;
3089
3090 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
3091 return FALSE;
3092
3093 if (!present)
3094 return TRUE;
3095
3096 DumpString(dacl, 2, pwptr, plen);
3097 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
3098 return FALSE;
3099 return TRUE;
3100 }
3101
3102 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3103 {
3104 static const WCHAR sacl[] = {'S',':',0};
3105 SECURITY_DESCRIPTOR_CONTROL control;
3106 BOOL present, defaulted;
3107 DWORD revision;
3108 PACL pacl;
3109
3110 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
3111 return FALSE;
3112
3113 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
3114 return FALSE;
3115
3116 if (!present)
3117 return TRUE;
3118
3119 DumpString(sacl, 2, pwptr, plen);
3120 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
3121 return FALSE;
3122 return TRUE;
3123 }
3124
3125 /******************************************************************************
3126 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
3127 * @implemented
3128 */
3129 BOOL WINAPI
3130 ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
3131 DWORD SDRevision,
3132 SECURITY_INFORMATION SecurityInformation,
3133 LPWSTR *OutputString,
3134 PULONG OutputLen)
3135 {
3136 ULONG len;
3137 WCHAR *wptr, *wstr;
3138
3139 if (SDRevision != SDDL_REVISION_1)
3140 {
3141 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
3142 SetLastError(ERROR_UNKNOWN_REVISION);
3143 return FALSE;
3144 }
3145
3146 len = 0;
3147 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
3148 if (!DumpOwner(SecurityDescriptor, NULL, &len))
3149 return FALSE;
3150 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
3151 if (!DumpGroup(SecurityDescriptor, NULL, &len))
3152 return FALSE;
3153 if (SecurityInformation & DACL_SECURITY_INFORMATION)
3154 if (!DumpDacl(SecurityDescriptor, NULL, &len))
3155 return FALSE;
3156 if (SecurityInformation & SACL_SECURITY_INFORMATION)
3157 if (!DumpSacl(SecurityDescriptor, NULL, &len))
3158 return FALSE;
3159
3160 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
3161 if (wstr == NULL)
3162 return FALSE;
3163
3164 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
3165 if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
3166 return FALSE;
3167 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
3168 if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
3169 return FALSE;
3170 if (SecurityInformation & DACL_SECURITY_INFORMATION)
3171 if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
3172 return FALSE;
3173 if (SecurityInformation & SACL_SECURITY_INFORMATION)
3174 if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
3175 return FALSE;
3176 *wptr = 0;
3177
3178 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
3179 *OutputString = wstr;
3180 if (OutputLen)
3181 *OutputLen = strlenW(*OutputString)+1;
3182 return TRUE;
3183 }
3184
3185 /******************************************************************************
3186 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
3187 * @implemented
3188 */
3189 BOOL WINAPI
3190 ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
3191 DWORD SDRevision,
3192 SECURITY_INFORMATION Information,
3193 LPSTR *OutputString,
3194 PULONG OutputLen)
3195 {
3196 LPWSTR wstr;
3197 ULONG len;
3198
3199 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
3200 {
3201 int lenA;
3202
3203 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
3204 *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
3205 if (*OutputString == NULL)
3206 {
3207 LocalFree(wstr);
3208 *OutputLen = 0;
3209 return FALSE;
3210 }
3211 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
3212 LocalFree(wstr);
3213
3214 if (OutputLen != NULL)
3215 *OutputLen = lenA;
3216 return TRUE;
3217 }
3218 else
3219 {
3220 *OutputString = NULL;
3221 if (OutputLen)
3222 *OutputLen = 0;
3223 return FALSE;
3224 }
3225 }
3226
3227 /*
3228 * @implemented
3229 */
3230 BOOL
3231 WINAPI
3232 ConvertStringSidToSidW(IN LPCWSTR StringSid,
3233 OUT PSID* sid)
3234 {
3235 DWORD size;
3236 DWORD i, cBytes, identAuth, csubauth;
3237 BOOL ret;
3238 SID* pisid;
3239
3240 TRACE("%s %p\n", debugstr_w(StringSid), sid);
3241
3242 if (!StringSid)
3243 {
3244 SetLastError(ERROR_INVALID_SID);
3245 return FALSE;
3246 }
3247
3248 for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
3249 {
3250 if (wcscmp(StringSid, SidTable[i].key) == 0)
3251 {
3252 WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
3253 size = SECURITY_MAX_SID_SIZE;
3254 *sid = LocalAlloc(0, size);
3255 if (!*sid)
3256 {
3257 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3258 return FALSE;
3259 }
3260 ret = CreateWellKnownSid(knownSid,
3261 NULL,
3262 *sid,
3263 &size);
3264 if (!ret)
3265 {
3266 SetLastError(ERROR_INVALID_SID);
3267 LocalFree(*sid);
3268 }
3269 return ret;
3270 }
3271 }
3272
3273 /* That's probably a string S-R-I-S-S... */
3274 if (StringSid[0] != 'S' || StringSid[1] != '-')
3275 {
3276 SetLastError(ERROR_INVALID_SID);
3277 return FALSE;
3278 }
3279
3280 cBytes = ComputeStringSidSize(StringSid);
3281 pisid = (SID*)LocalAlloc( 0, cBytes );
3282 if (!pisid)
3283 {
3284 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3285 return FALSE;
3286 }
3287 i = 0;
3288 ret = FALSE;
3289 csubauth = ((cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
3290
3291 StringSid += 2; /* Advance to Revision */
3292 pisid->Revision = atoiW(StringSid);
3293
3294 if (pisid->Revision != SDDL_REVISION)
3295 {
3296 TRACE("Revision %d is unknown\n", pisid->Revision);
3297 goto lend; /* ERROR_INVALID_SID */
3298 }
3299 if (csubauth == 0)
3300 {
3301 TRACE("SubAuthorityCount is 0\n");
3302 goto lend; /* ERROR_INVALID_SID */
3303 }
3304
3305 pisid->SubAuthorityCount = csubauth;
3306
3307 /* Advance to identifier authority */
3308 while (*StringSid && *StringSid != '-')
3309 StringSid++;
3310 if (*StringSid == '-')
3311 StringSid++;
3312
3313 /* MS' implementation can't handle values greater than 2^32 - 1, so
3314 * we don't either; assume most significant bytes are always 0
3315 */
3316 pisid->IdentifierAuthority.Value[0] = 0;
3317 pisid->IdentifierAuthority.Value[1] = 0;
3318 identAuth = atoiW(StringSid);
3319 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
3320 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
3321 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
3322 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
3323
3324 /* Advance to first sub authority */
3325 while (*StringSid && *StringSid != '-')
3326 StringSid++;
3327 if (*StringSid == '-')
3328 StringSid++;
3329
3330 while (*StringSid)
3331 {
3332 pisid->SubAuthority[i++] = atoiW(StringSid);
3333
3334 while (*StringSid && *StringSid != '-')
3335 StringSid++;
3336 if (*StringSid == '-')
3337 StringSid++;
3338 }
3339
3340 if (i != pisid->SubAuthorityCount)
3341 goto lend; /* ERROR_INVALID_SID */
3342
3343 *sid = pisid;
3344 ret = TRUE;
3345
3346 lend:
3347 if (!ret)
3348 {
3349 LocalFree(pisid);
3350 SetLastError(ERROR_INVALID_SID);
3351 }
3352
3353 TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
3354 return ret;
3355 }
3356
3357 /*
3358 * @implemented
3359 */
3360 BOOL
3361 WINAPI
3362 ConvertStringSidToSidA(IN LPCSTR StringSid,
3363 OUT PSID* sid)
3364 {
3365 BOOL bRetVal = FALSE;
3366
3367 TRACE("%s, %p\n", debugstr_a(StringSid), sid);
3368 if (GetVersion() & 0x80000000)
3369 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3370 else if (!StringSid || !sid)
3371 SetLastError(ERROR_INVALID_PARAMETER);
3372 else
3373 {
3374 UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
3375 LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3376 if (wStringSid == NULL)
3377 return FALSE;
3378 MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
3379 bRetVal = ConvertStringSidToSidW(wStringSid, sid);
3380 HeapFree(GetProcessHeap(), 0, wStringSid);
3381 }
3382 return bRetVal;
3383 }
3384
3385 /*
3386 * @implemented
3387 */
3388 BOOL
3389 WINAPI
3390 ConvertSidToStringSidW(PSID Sid,
3391 LPWSTR *StringSid)
3392 {
3393 NTSTATUS Status;
3394 UNICODE_STRING UnicodeString;
3395 WCHAR FixedBuffer[64];
3396
3397 if (!RtlValidSid(Sid))
3398 {
3399 SetLastError(ERROR_INVALID_SID);
3400 return FALSE;
3401 }
3402
3403 UnicodeString.Length = 0;
3404 UnicodeString.MaximumLength = sizeof(FixedBuffer);
3405 UnicodeString.Buffer = FixedBuffer;
3406 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
3407 if (STATUS_BUFFER_TOO_SMALL == Status)
3408 {
3409 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
3410 }
3411
3412 if (!NT_SUCCESS(Status))
3413 {
3414 SetLastError(RtlNtStatusToDosError(Status));
3415 return FALSE;
3416 }
3417
3418 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
3419 if (NULL == *StringSid)
3420 {
3421 if (UnicodeString.Buffer != FixedBuffer)
3422 {
3423 RtlFreeUnicodeString(&UnicodeString);
3424 }
3425 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3426 return FALSE;
3427 }
3428
3429 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
3430 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
3431 if (UnicodeString.Buffer != FixedBuffer)
3432 {
3433 RtlFreeUnicodeString(&UnicodeString);
3434 }
3435
3436 return TRUE;
3437 }
3438
3439 /*
3440 * @implemented
3441 */
3442 BOOL
3443 WINAPI
3444 ConvertSidToStringSidA(PSID Sid,
3445 LPSTR *StringSid)
3446 {
3447 LPWSTR StringSidW;
3448 int Len;
3449
3450 if (!ConvertSidToStringSidW(Sid, &StringSidW))
3451 {
3452 return FALSE;
3453 }
3454
3455 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
3456 if (Len <= 0)
3457 {
3458 LocalFree(StringSidW);
3459 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3460 return FALSE;
3461 }
3462
3463 *StringSid = LocalAlloc(LMEM_FIXED, Len);
3464 if (NULL == *StringSid)
3465 {
3466 LocalFree(StringSidW);
3467 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3468 return FALSE;
3469 }
3470
3471 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
3472 {
3473 LocalFree(StringSid);
3474 LocalFree(StringSidW);
3475 return FALSE;
3476 }
3477
3478 LocalFree(StringSidW);
3479
3480 return TRUE;
3481 }
3482
3483 /*
3484 * @unimplemented
3485 */
3486 BOOL WINAPI
3487 CreateProcessWithLogonW(LPCWSTR lpUsername,
3488 LPCWSTR lpDomain,
3489 LPCWSTR lpPassword,
3490 DWORD dwLogonFlags,
3491 LPCWSTR lpApplicationName,
3492 LPWSTR lpCommandLine,
3493 DWORD dwCreationFlags,
3494 LPVOID lpEnvironment,
3495 LPCWSTR lpCurrentDirectory,
3496 LPSTARTUPINFOW lpStartupInfo,
3497 LPPROCESS_INFORMATION lpProcessInformation)
3498 {
3499 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
3500 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
3501 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
3502 lpStartupInfo, lpProcessInformation);
3503
3504 return FALSE;
3505 }
3506
3507 BOOL
3508 WINAPI
3509 CreateProcessWithTokenW(IN HANDLE hToken,
3510 IN DWORD dwLogonFlags,
3511 IN LPCWSTR lpApplicationName OPTIONAL,
3512 IN OUT LPWSTR lpCommandLine OPTIONAL,
3513 IN DWORD dwCreationFlags,
3514 IN LPVOID lpEnvironment OPTIONAL,
3515 IN LPCWSTR lpCurrentDirectory OPTIONAL,
3516 IN LPSTARTUPINFOW lpStartupInfo,
3517 OUT LPPROCESS_INFORMATION lpProcessInfo)
3518 {
3519 UNIMPLEMENTED;
3520 return FALSE;
3521 }
3522
3523 /*
3524 * @implemented
3525 */
3526 BOOL WINAPI
3527 DuplicateTokenEx(IN HANDLE ExistingTokenHandle,
3528 IN DWORD dwDesiredAccess,
3529 IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL,
3530 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
3531 IN TOKEN_TYPE TokenType,
3532 OUT PHANDLE DuplicateTokenHandle)
3533 {
3534 OBJECT_ATTRIBUTES ObjectAttributes;
3535 NTSTATUS Status;
3536 SECURITY_QUALITY_OF_SERVICE Sqos;
3537
3538 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
3539 ImpersonationLevel, TokenType, DuplicateTokenHandle);
3540
3541 Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
3542 Sqos.ImpersonationLevel = ImpersonationLevel;
3543 Sqos.ContextTrackingMode = 0;
3544 Sqos.EffectiveOnly = FALSE;
3545
3546 if (lpTokenAttributes != NULL)
3547 {
3548 InitializeObjectAttributes(&ObjectAttributes,
3549 NULL,
3550 lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
3551 NULL,
3552 lpTokenAttributes->lpSecurityDescriptor);
3553 }
3554 else
3555 {
3556 InitializeObjectAttributes(&ObjectAttributes,
3557 NULL,
3558 0,
3559 NULL,
3560 NULL);
3561 }
3562
3563 ObjectAttributes.SecurityQualityOfService = &Sqos;
3564
3565 Status = NtDuplicateToken(ExistingTokenHandle,
3566 dwDesiredAccess,
3567 &ObjectAttributes,
3568 FALSE,
3569 TokenType,
3570 DuplicateTokenHandle);
3571 if (!NT_SUCCESS(Status))
3572 {
3573 ERR("NtDuplicateToken failed: Status %08x\n", Status);
3574 SetLastError(RtlNtStatusToDosError(Status));
3575 return FALSE;
3576 }
3577
3578 TRACE("Returning token %p.\n", *DuplicateTokenHandle);
3579
3580 return TRUE;
3581 }
3582
3583 /*
3584 * @implemented
3585 */
3586 BOOL WINAPI
3587 DuplicateToken(IN HANDLE ExistingTokenHandle,
3588 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
3589 OUT PHANDLE DuplicateTokenHandle)
3590 {
3591 return DuplicateTokenEx(ExistingTokenHandle,
3592 TOKEN_IMPERSONATE | TOKEN_QUERY,
3593 NULL,
3594 ImpersonationLevel,
3595 TokenImpersonation,
3596 DuplicateTokenHandle);
3597 }
3598
3599 /******************************************************************************
3600 * ComputeStringSidSize
3601 */
3602 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
3603 {
3604 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
3605 {
3606 int ctok = 0;
3607 while (*StringSid)
3608 {
3609 if (*StringSid == '-')
3610 ctok++;
3611 StringSid++;
3612 }
3613
3614 if (ctok >= 3)
3615 return GetSidLengthRequired(ctok - 2);
3616 }
3617 else /* String constant format - Only available in winxp and above */
3618 {
3619 unsigned int i;
3620
3621 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
3622 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
3623 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
3624 }
3625
3626 return GetSidLengthRequired(0);
3627 }
3628
3629 /******************************************************************************
3630 * ParseStringSidToSid
3631 */
3632 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
3633 {
3634 BOOL bret = FALSE;
3635 SID* pisid=pSid;
3636
3637 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
3638 if (!StringSid)
3639 {
3640 SetLastError(ERROR_INVALID_PARAMETER);
3641 TRACE("StringSid is NULL, returning FALSE\n");
3642 return FALSE;
3643 }
3644
3645 while (*StringSid == ' ')
3646 StringSid++;
3647
3648 *cBytes = ComputeStringSidSize(StringSid);
3649 if (!pisid) /* Simply compute the size */
3650 {
3651 TRACE("only size requested, returning TRUE\n");
3652 return TRUE;
3653 }
3654
3655 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
3656 {
3657 DWORD i = 0, identAuth;
3658 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
3659
3660 StringSid += 2; /* Advance to Revision */
3661 pisid->Revision = atoiW(StringSid);
3662
3663 if (pisid->Revision != SDDL_REVISION)
3664 {
3665 TRACE("Revision %d is unknown\n", pisid->Revision);
3666 goto lend; /* ERROR_INVALID_SID */
3667 }
3668 if (csubauth == 0)
3669 {
3670 TRACE("SubAuthorityCount is 0\n");
3671 goto lend; /* ERROR_INVALID_SID */
3672 }
3673
3674 pisid->SubAuthorityCount = csubauth;
3675
3676 /* Advance to identifier authority */
3677 while (*StringSid && *StringSid != '-')
3678 StringSid++;
3679 if (*StringSid == '-')
3680 StringSid++;
3681
3682 /* MS' implementation can't handle values greater than 2^32 - 1, so
3683 * we don't either; assume most significant bytes are always 0
3684 */
3685 pisid->IdentifierAuthority.Value[0] = 0;
3686 pisid->IdentifierAuthority.Value[1] = 0;
3687 identAuth = atoiW(StringSid);
3688 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
3689 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
3690 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
3691 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
3692
3693 /* Advance to first sub authority */
3694 while (*StringSid && *StringSid != '-')
3695 StringSid++;
3696 if (*StringSid == '-')
3697 StringSid++;
3698
3699 while (*StringSid)
3700 {
3701 pisid->SubAuthority[i++] = atoiW(StringSid);
3702
3703 while (*StringSid && *StringSid != '-')
3704 StringSid++;
3705 if (*StringSid == '-')
3706 StringSid++;
3707 }
3708
3709 if (i != pisid->SubAuthorityCount)
3710 goto lend; /* ERROR_INVALID_SID */
3711
3712 bret = TRUE;
3713 }
3714 else /* String constant format - Only available in winxp and above */
3715 {
3716 unsigned int i;
3717 pisid->Revision = SDDL_REVISION;
3718
3719 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
3720 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
3721 {
3722 DWORD j;
3723 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
3724 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
3725 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
3726 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
3727 bret = TRUE;
3728 }