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