[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 * @implemented
1077 */
1078 BOOL
1079 WINAPI
1080 DeleteAce(PACL pAcl,
1081 DWORD dwAceIndex)
1082 {
1083 NTSTATUS Status;
1084
1085 Status = RtlDeleteAce(pAcl,
1086 dwAceIndex);
1087 if (!NT_SUCCESS(Status))
1088 {
1089 SetLastError(RtlNtStatusToDosError(Status));
1090 return FALSE;
1091 }
1092
1093 return TRUE;
1094 }
1095
1096 /*
1097 * @implemented
1098 */
1099 BOOL
1100 WINAPI
1101 FindFirstFreeAce(PACL pAcl,
1102 LPVOID *pAce)
1103 {
1104 return RtlFirstFreeAce(pAcl,
1105 (PACE*)pAce);
1106 }
1107
1108
1109 /*
1110 * @implemented
1111 */
1112 BOOL
1113 WINAPI
1114 GetAce(PACL pAcl,
1115 DWORD dwAceIndex,
1116 LPVOID *pAce)
1117 {
1118 NTSTATUS Status;
1119
1120 Status = RtlGetAce(pAcl,
1121 dwAceIndex,
1122 pAce);
1123 if (!NT_SUCCESS(Status))
1124 {
1125 SetLastError(RtlNtStatusToDosError(Status));
1126 return FALSE;
1127 }
1128
1129 return TRUE;
1130 }
1131
1132 /*
1133 * @implemented
1134 */
1135 BOOL
1136 WINAPI
1137 GetAclInformation(PACL pAcl,
1138 LPVOID pAclInformation,
1139 DWORD nAclInformationLength,
1140 ACL_INFORMATION_CLASS dwAclInformationClass)
1141 {
1142 NTSTATUS Status;
1143
1144 Status = RtlQueryInformationAcl(pAcl,
1145 pAclInformation,
1146 nAclInformationLength,
1147 dwAclInformationClass);
1148 if (!NT_SUCCESS(Status))
1149 {
1150 SetLastError(RtlNtStatusToDosError(Status));
1151 return FALSE;
1152 }
1153
1154 return TRUE;
1155 }
1156
1157 /*
1158 * @implemented
1159 */
1160 BOOL
1161 WINAPI
1162 IsValidAcl(PACL pAcl)
1163 {
1164 return RtlValidAcl (pAcl);
1165 }
1166
1167 /*
1168 * @implemented
1169 */
1170 BOOL WINAPI
1171 AllocateLocallyUniqueId(PLUID Luid)
1172 {
1173 NTSTATUS Status;
1174
1175 Status = NtAllocateLocallyUniqueId (Luid);
1176 if (!NT_SUCCESS (Status))
1177 {
1178 SetLastError(RtlNtStatusToDosError(Status));
1179 return FALSE;
1180 }
1181
1182 return TRUE;
1183 }
1184
1185 /**********************************************************************
1186 * LookupPrivilegeDisplayNameA EXPORTED
1187 *
1188 * @unimplemented
1189 */
1190 BOOL
1191 WINAPI
1192 LookupPrivilegeDisplayNameA(LPCSTR lpSystemName,
1193 LPCSTR lpName,
1194 LPSTR lpDisplayName,
1195 LPDWORD cbDisplayName,
1196 LPDWORD lpLanguageId)
1197 {
1198 FIXME("%s() not implemented!\n", __FUNCTION__);
1199 SetLastError (ERROR_CALL_NOT_IMPLEMENTED);
1200 return FALSE;
1201 }
1202
1203
1204 /**********************************************************************
1205 * LookupPrivilegeDisplayNameW EXPORTED
1206 *
1207 * @unimplemented
1208 */
1209 BOOL
1210 WINAPI
1211 LookupPrivilegeDisplayNameW(LPCWSTR lpSystemName,
1212 LPCWSTR lpName,
1213 LPWSTR lpDisplayName,
1214 LPDWORD cbDisplayName,
1215 LPDWORD lpLanguageId)
1216 {
1217 FIXME("%s() not implemented!\n", __FUNCTION__);
1218 SetLastError (ERROR_CALL_NOT_IMPLEMENTED);
1219 return FALSE;
1220 }
1221
1222 /**********************************************************************
1223 * LookupPrivilegeNameA EXPORTED
1224 *
1225 * @implemented
1226 */
1227 BOOL
1228 WINAPI
1229 LookupPrivilegeNameA(LPCSTR lpSystemName,
1230 PLUID lpLuid,
1231 LPSTR lpName,
1232 LPDWORD cchName)
1233 {
1234 UNICODE_STRING lpSystemNameW;
1235 BOOL ret;
1236 DWORD wLen = 0;
1237
1238 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1239
1240 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1241 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1242 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1243 {
1244 LPWSTR lpNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR));
1245
1246 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1247 &wLen);
1248 if (ret)
1249 {
1250 /* Windows crashes if cchName is NULL, so will I */
1251 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1252 *cchName, NULL, NULL);
1253
1254 if (len == 0)
1255 {
1256 /* WideCharToMultiByte failed */
1257 ret = FALSE;
1258 }
1259 else if (len > *cchName)
1260 {
1261 *cchName = len;
1262 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1263 ret = FALSE;
1264 }
1265 else
1266 {
1267 /* WideCharToMultiByte succeeded, output length needs to be
1268 * length not including NULL terminator
1269 */
1270 *cchName = len - 1;
1271 }
1272 }
1273 HeapFree(GetProcessHeap(), 0, lpNameW);
1274 }
1275 RtlFreeUnicodeString(&lpSystemNameW);
1276 return ret;
1277 }
1278
1279 /******************************************************************************
1280 * GetFileSecurityA [ADVAPI32.@]
1281 *
1282 * Obtains Specified information about the security of a file or directory.
1283 *
1284 * PARAMS
1285 * lpFileName [I] Name of the file to get info for
1286 * RequestedInformation [I] SE_ flags from "winnt.h"
1287 * pSecurityDescriptor [O] Destination for security information
1288 * nLength [I] Length of pSecurityDescriptor
1289 * lpnLengthNeeded [O] Destination for length of returned security information
1290 *
1291 * RETURNS
1292 * Success: TRUE. pSecurityDescriptor contains the requested information.
1293 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
1294 *
1295 * NOTES
1296 * The information returned is constrained by the callers access rights and
1297 * privileges.
1298 *
1299 * @implemented
1300 */
1301 BOOL
1302 WINAPI
1303 GetFileSecurityA(LPCSTR lpFileName,
1304 SECURITY_INFORMATION RequestedInformation,
1305 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1306 DWORD nLength,
1307 LPDWORD lpnLengthNeeded)
1308 {
1309 UNICODE_STRING FileName;
1310 BOOL bResult;
1311
1312 if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName))
1313 {
1314 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1315 return FALSE;
1316 }
1317
1318 bResult = GetFileSecurityW(FileName.Buffer,
1319 RequestedInformation,
1320 pSecurityDescriptor,
1321 nLength,
1322 lpnLengthNeeded);
1323
1324 RtlFreeUnicodeString(&FileName);
1325
1326 return bResult;
1327 }
1328
1329 /*
1330 * @implemented
1331 */
1332 BOOL
1333 WINAPI
1334 GetFileSecurityW(LPCWSTR lpFileName,
1335 SECURITY_INFORMATION RequestedInformation,
1336 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1337 DWORD nLength,
1338 LPDWORD lpnLengthNeeded)
1339 {
1340 OBJECT_ATTRIBUTES ObjectAttributes;
1341 IO_STATUS_BLOCK StatusBlock;
1342 UNICODE_STRING FileName;
1343 ULONG AccessMask = 0;
1344 HANDLE FileHandle;
1345 NTSTATUS Status;
1346
1347 TRACE("GetFileSecurityW() called\n");
1348
1349 QuerySecurityAccessMask(RequestedInformation, &AccessMask);
1350
1351 if (!RtlDosPathNameToNtPathName_U(lpFileName,
1352 &FileName,
1353 NULL,
1354 NULL))
1355 {
1356 ERR("Invalid path\n");
1357 SetLastError(ERROR_INVALID_NAME);
1358 return FALSE;
1359 }
1360
1361 InitializeObjectAttributes(&ObjectAttributes,
1362 &FileName,
1363 OBJ_CASE_INSENSITIVE,
1364 NULL,
1365 NULL);
1366
1367 Status = NtOpenFile(&FileHandle,
1368 AccessMask,
1369 &ObjectAttributes,
1370 &StatusBlock,
1371 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1372 0);
1373
1374 RtlFreeHeap(RtlGetProcessHeap(),
1375 0,
1376 FileName.Buffer);
1377
1378 if (!NT_SUCCESS(Status))
1379 {
1380 ERR("NtOpenFile() failed (Status %lx)\n", Status);
1381 SetLastError(RtlNtStatusToDosError(Status));
1382 return FALSE;
1383 }
1384
1385 Status = NtQuerySecurityObject(FileHandle,
1386 RequestedInformation,
1387 pSecurityDescriptor,
1388 nLength,
1389 lpnLengthNeeded);
1390 NtClose(FileHandle);
1391 if (!NT_SUCCESS(Status))
1392 {
1393 ERR("NtQuerySecurityObject() failed (Status %lx)\n", Status);
1394 SetLastError(RtlNtStatusToDosError(Status));
1395 return FALSE;
1396 }
1397
1398 return TRUE;
1399 }
1400
1401 /******************************************************************************
1402 * SetFileSecurityA [ADVAPI32.@]
1403 * Sets the security of a file or directory
1404 *
1405 * @implemented
1406 */
1407 BOOL
1408 WINAPI
1409 SetFileSecurityA(LPCSTR lpFileName,
1410 SECURITY_INFORMATION SecurityInformation,
1411 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1412 {
1413 UNICODE_STRING FileName;
1414 BOOL bResult;
1415
1416 if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName))
1417 {
1418 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1419 return FALSE;
1420 }
1421
1422 bResult = SetFileSecurityW(FileName.Buffer,
1423 SecurityInformation,
1424 pSecurityDescriptor);
1425
1426 RtlFreeUnicodeString(&FileName);
1427
1428 return bResult;
1429 }
1430
1431 /******************************************************************************
1432 * SetFileSecurityW [ADVAPI32.@]
1433 * Sets the security of a file or directory
1434 *
1435 * @implemented
1436 */
1437 BOOL
1438 WINAPI
1439 SetFileSecurityW(LPCWSTR lpFileName,
1440 SECURITY_INFORMATION SecurityInformation,
1441 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1442 {
1443 OBJECT_ATTRIBUTES ObjectAttributes;
1444 IO_STATUS_BLOCK StatusBlock;
1445 UNICODE_STRING FileName;
1446 ULONG AccessMask = 0;
1447 HANDLE FileHandle;
1448 NTSTATUS Status;
1449
1450 TRACE("SetFileSecurityW() called\n");
1451
1452 SetSecurityAccessMask(SecurityInformation, &AccessMask);
1453
1454 if (!RtlDosPathNameToNtPathName_U(lpFileName,
1455 &FileName,
1456 NULL,
1457 NULL))
1458 {
1459 ERR("Invalid path\n");
1460 SetLastError(ERROR_INVALID_NAME);
1461 return FALSE;
1462 }
1463
1464 InitializeObjectAttributes(&ObjectAttributes,
1465 &FileName,
1466 OBJ_CASE_INSENSITIVE,
1467 NULL,
1468 NULL);
1469
1470 Status = NtOpenFile(&FileHandle,
1471 AccessMask,
1472 &ObjectAttributes,
1473 &StatusBlock,
1474 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1475 0);
1476
1477 RtlFreeHeap(RtlGetProcessHeap(),
1478 0,
1479 FileName.Buffer);
1480
1481 if (!NT_SUCCESS(Status))
1482 {
1483 ERR("NtOpenFile() failed (Status %lx)\n", Status);
1484 SetLastError(RtlNtStatusToDosError(Status));
1485 return FALSE;
1486 }
1487
1488 Status = NtSetSecurityObject(FileHandle,
1489 SecurityInformation,
1490 pSecurityDescriptor);
1491 NtClose(FileHandle);
1492
1493 if (!NT_SUCCESS(Status))
1494 {
1495 ERR("NtSetSecurityObject() failed (Status %lx)\n", Status);
1496 SetLastError(RtlNtStatusToDosError(Status));
1497 return FALSE;
1498 }
1499
1500 return TRUE;
1501 }
1502
1503 /******************************************************************************
1504 * QueryWindows31FilesMigration [ADVAPI32.@]
1505 *
1506 * PARAMS
1507 * x1 []
1508 */
1509 BOOL WINAPI
1510 QueryWindows31FilesMigration( DWORD x1 )
1511 {
1512 FIXME("(%d):stub\n",x1);
1513 return TRUE;
1514 }
1515
1516 /******************************************************************************
1517 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
1518 *
1519 * PARAMS
1520 * x1 []
1521 * x2 []
1522 * x3 []
1523 * x4 []
1524 */
1525 BOOL WINAPI
1526 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
1527 DWORD x4 )
1528 {
1529 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
1530 return TRUE;
1531 }
1532
1533 /*
1534 * @implemented
1535 */
1536 BOOL
1537 WINAPI
1538 RevertToSelf(VOID)
1539 {
1540 NTSTATUS Status;
1541 HANDLE Token = NULL;
1542
1543 Status = NtSetInformationThread(NtCurrentThread(),
1544 ThreadImpersonationToken,
1545 &Token,
1546 sizeof(HANDLE));
1547 if (!NT_SUCCESS(Status))
1548 {
1549 SetLastError(RtlNtStatusToDosError(Status));
1550 return FALSE;
1551 }
1552
1553 return TRUE;
1554 }
1555
1556 /*
1557 * @implemented
1558 */
1559 BOOL
1560 WINAPI
1561 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1562 {
1563 NTSTATUS Status;
1564
1565 Status = RtlImpersonateSelf(ImpersonationLevel);
1566 if (!NT_SUCCESS(Status))
1567 {
1568 SetLastError(RtlNtStatusToDosError(Status));
1569 return FALSE;
1570 }
1571
1572 return TRUE;
1573 }
1574
1575 /*
1576 * @implemented
1577 */
1578 BOOL
1579 WINAPI
1580 AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1581 IN HANDLE ClientToken,
1582 IN DWORD DesiredAccess,
1583 IN PGENERIC_MAPPING GenericMapping,
1584 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
1585 IN OUT LPDWORD PrivilegeSetLength,
1586 OUT LPDWORD GrantedAccess,
1587 OUT LPBOOL AccessStatus)
1588 {
1589 NTSTATUS Status;
1590 NTSTATUS NtAccessStatus;
1591
1592 /* Do the access check */
1593 Status = NtAccessCheck(pSecurityDescriptor,
1594 ClientToken,
1595 DesiredAccess,
1596 GenericMapping,
1597 PrivilegeSet,
1598 (PULONG)PrivilegeSetLength,
1599 (PACCESS_MASK)GrantedAccess,
1600 &NtAccessStatus);
1601
1602 /* See if the access check operation succeeded */
1603 if (!NT_SUCCESS(Status))
1604 {
1605 /* Check failed */
1606 SetLastError(RtlNtStatusToDosError(Status));
1607 return FALSE;
1608 }
1609
1610 /* Now check the access status */
1611 if (!NT_SUCCESS(NtAccessStatus))
1612 {
1613 /* Access denied */
1614 SetLastError(RtlNtStatusToDosError(NtAccessStatus));
1615 *AccessStatus = FALSE;
1616 }
1617 else
1618 {
1619 /* Access granted */
1620 *AccessStatus = TRUE;
1621 }
1622
1623 /* Check succeeded */
1624 return TRUE;
1625 }
1626
1627 /*
1628 * @unimplemented
1629 */
1630 BOOL WINAPI AccessCheckByType(
1631 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1632 PSID PrincipalSelfSid,
1633 HANDLE ClientToken,
1634 DWORD DesiredAccess,
1635 POBJECT_TYPE_LIST ObjectTypeList,
1636 DWORD ObjectTypeListLength,
1637 PGENERIC_MAPPING GenericMapping,
1638 PPRIVILEGE_SET PrivilegeSet,
1639 LPDWORD PrivilegeSetLength,
1640 LPDWORD GrantedAccess,
1641 LPBOOL AccessStatus)
1642 {
1643 FIXME("stub\n");
1644
1645 *AccessStatus = TRUE;
1646
1647 return !*AccessStatus;
1648 }
1649
1650 /*
1651 * @implemented
1652 */
1653 BOOL
1654 WINAPI
1655 SetKernelObjectSecurity(HANDLE Handle,
1656 SECURITY_INFORMATION SecurityInformation,
1657 PSECURITY_DESCRIPTOR SecurityDescriptor)
1658 {
1659 NTSTATUS Status;
1660
1661 Status = NtSetSecurityObject(Handle,
1662 SecurityInformation,
1663 SecurityDescriptor);
1664 if (!NT_SUCCESS(Status))
1665 {
1666 SetLastError(RtlNtStatusToDosError(Status));
1667 return FALSE;
1668 }
1669
1670 return TRUE;
1671 }
1672
1673 /*
1674 * @implemented
1675 */
1676 BOOL
1677 WINAPI
1678 AddAuditAccessAce(PACL pAcl,
1679 DWORD dwAceRevision,
1680 DWORD dwAccessMask,
1681 PSID pSid,
1682 BOOL bAuditSuccess,
1683 BOOL bAuditFailure)
1684 {
1685 NTSTATUS Status;
1686
1687 Status = RtlAddAuditAccessAce(pAcl,
1688 dwAceRevision,
1689 dwAccessMask,
1690 pSid,
1691 bAuditSuccess,
1692 bAuditFailure);
1693 if (!NT_SUCCESS(Status))
1694 {
1695 SetLastError(RtlNtStatusToDosError(Status));
1696 return FALSE;
1697 }
1698
1699 return TRUE;
1700 }
1701
1702 /*
1703 * @implemented
1704 */
1705 BOOL WINAPI
1706 AddAuditAccessAceEx(PACL pAcl,
1707 DWORD dwAceRevision,
1708 DWORD AceFlags,
1709 DWORD dwAccessMask,
1710 PSID pSid,
1711 BOOL bAuditSuccess,
1712 BOOL bAuditFailure)
1713 {
1714 NTSTATUS Status;
1715
1716 Status = RtlAddAuditAccessAceEx(pAcl,
1717 dwAceRevision,
1718 AceFlags,
1719 dwAccessMask,
1720 pSid,
1721 bAuditSuccess,
1722 bAuditFailure);
1723 if (!NT_SUCCESS(Status))
1724 {
1725 SetLastError(RtlNtStatusToDosError(Status));
1726 return FALSE;
1727 }
1728
1729 return TRUE;
1730 }
1731
1732 /******************************************************************************
1733 * LookupAccountNameA [ADVAPI32.@]
1734 *
1735 * @implemented
1736 */
1737 BOOL
1738 WINAPI
1739 LookupAccountNameA(LPCSTR SystemName,
1740 LPCSTR AccountName,
1741 PSID Sid,
1742 LPDWORD SidLength,
1743 LPSTR ReferencedDomainName,
1744 LPDWORD hReferencedDomainNameLength,
1745 PSID_NAME_USE SidNameUse)
1746 {
1747 BOOL ret;
1748 UNICODE_STRING lpSystemW;
1749 UNICODE_STRING lpAccountW;
1750 LPWSTR lpReferencedDomainNameW = NULL;
1751
1752 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, SystemName);
1753 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, AccountName);
1754
1755 if (ReferencedDomainName)
1756 lpReferencedDomainNameW = HeapAlloc(GetProcessHeap(),
1757 0,
1758 *hReferencedDomainNameLength * sizeof(WCHAR));
1759
1760 ret = LookupAccountNameW(lpSystemW.Buffer,
1761 lpAccountW.Buffer,
1762 Sid,
1763 SidLength,
1764 lpReferencedDomainNameW,
1765 hReferencedDomainNameLength,
1766 SidNameUse);
1767
1768 if (ret && lpReferencedDomainNameW)
1769 {
1770 WideCharToMultiByte(CP_ACP,
1771 0,
1772 lpReferencedDomainNameW,
1773 *hReferencedDomainNameLength + 1,
1774 ReferencedDomainName,
1775 *hReferencedDomainNameLength + 1,
1776 NULL,
1777 NULL);
1778 }
1779
1780 RtlFreeUnicodeString(&lpSystemW);
1781 RtlFreeUnicodeString(&lpAccountW);
1782 HeapFree(GetProcessHeap(), 0, lpReferencedDomainNameW);
1783
1784 return ret;
1785 }
1786
1787 /**********************************************************************
1788 * PrivilegeCheck EXPORTED
1789 *
1790 * @implemented
1791 */
1792 BOOL WINAPI
1793 PrivilegeCheck(HANDLE ClientToken,
1794 PPRIVILEGE_SET RequiredPrivileges,
1795 LPBOOL pfResult)
1796 {
1797 BOOLEAN Result;
1798 NTSTATUS Status;
1799
1800 Status = NtPrivilegeCheck(ClientToken,
1801 RequiredPrivileges,
1802 &Result);
1803 if (!NT_SUCCESS(Status))
1804 {
1805 SetLastError(RtlNtStatusToDosError(Status));
1806 return FALSE;
1807 }
1808
1809 *pfResult = (BOOL)Result;
1810
1811 return TRUE;
1812 }
1813
1814 /******************************************************************************
1815 * GetSecurityInfoExW EXPORTED
1816 */
1817 DWORD
1818 WINAPI
1819 GetSecurityInfoExA(HANDLE hObject,
1820 SE_OBJECT_TYPE ObjectType,
1821 SECURITY_INFORMATION SecurityInfo,
1822 LPCSTR lpProvider,
1823 LPCSTR lpProperty,
1824 PACTRL_ACCESSA *ppAccessList,
1825 PACTRL_AUDITA *ppAuditList,
1826 LPSTR *lppOwner,
1827 LPSTR *lppGroup)
1828 {
1829 FIXME("%s() not implemented!\n", __FUNCTION__);
1830 return ERROR_BAD_PROVIDER;
1831 }
1832
1833
1834 /******************************************************************************
1835 * GetSecurityInfoExW EXPORTED
1836 */
1837 DWORD
1838 WINAPI
1839 GetSecurityInfoExW(HANDLE hObject,
1840 SE_OBJECT_TYPE ObjectType,
1841 SECURITY_INFORMATION SecurityInfo,
1842 LPCWSTR lpProvider,
1843 LPCWSTR lpProperty,
1844 PACTRL_ACCESSW *ppAccessList,
1845 PACTRL_AUDITW *ppAuditList,
1846 LPWSTR *lppOwner,
1847 LPWSTR *lppGroup)
1848 {
1849 FIXME("%s() not implemented!\n", __FUNCTION__);
1850 return ERROR_BAD_PROVIDER;
1851 }
1852
1853 /******************************************************************************
1854 * BuildExplicitAccessWithNameA [ADVAPI32.@]
1855 */
1856 VOID WINAPI
1857 BuildExplicitAccessWithNameA(PEXPLICIT_ACCESSA pExplicitAccess,
1858 LPSTR pTrusteeName,
1859 DWORD AccessPermissions,
1860 ACCESS_MODE AccessMode,
1861 DWORD Inheritance)
1862 {
1863 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1864 pExplicitAccess->grfAccessMode = AccessMode;
1865 pExplicitAccess->grfInheritance = Inheritance;
1866
1867 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1868 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1869 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1870 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1871 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1872 }
1873
1874
1875 /******************************************************************************
1876 * BuildExplicitAccessWithNameW [ADVAPI32.@]
1877 */
1878 VOID WINAPI
1879 BuildExplicitAccessWithNameW(PEXPLICIT_ACCESSW pExplicitAccess,
1880 LPWSTR pTrusteeName,
1881 DWORD AccessPermissions,
1882 ACCESS_MODE AccessMode,
1883 DWORD Inheritance)
1884 {
1885 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1886 pExplicitAccess->grfAccessMode = AccessMode;
1887 pExplicitAccess->grfInheritance = Inheritance;
1888
1889 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1890 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1891 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1892 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1893 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1894 }
1895
1896 /******************************************************************************
1897 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
1898 */
1899 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
1900 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
1901 LPSTR InheritedObjectTypeName, LPSTR Name )
1902 {
1903 DWORD ObjectsPresent = 0;
1904
1905 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1906 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
1907
1908 /* Fill the OBJECTS_AND_NAME structure */
1909 pObjName->ObjectType = ObjectType;
1910 if (ObjectTypeName != NULL)
1911 {
1912 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1913 }
1914
1915 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1916 if (InheritedObjectTypeName != NULL)
1917 {
1918 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1919 }
1920
1921 pObjName->ObjectsPresent = ObjectsPresent;
1922 pObjName->ptstrName = Name;
1923
1924 /* Fill the TRUSTEE structure */
1925 pTrustee->pMultipleTrustee = NULL;
1926 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1927 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1928 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1929 pTrustee->ptstrName = (LPSTR)pObjName;
1930 }
1931
1932 /******************************************************************************
1933 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
1934 */
1935 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
1936 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
1937 LPWSTR InheritedObjectTypeName, LPWSTR Name )
1938 {
1939 DWORD ObjectsPresent = 0;
1940
1941 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1942 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
1943
1944 /* Fill the OBJECTS_AND_NAME structure */
1945 pObjName->ObjectType = ObjectType;
1946 if (ObjectTypeName != NULL)
1947 {
1948 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1949 }
1950
1951 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1952 if (InheritedObjectTypeName != NULL)
1953 {
1954 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1955 }
1956
1957 pObjName->ObjectsPresent = ObjectsPresent;
1958 pObjName->ptstrName = Name;
1959
1960 /* Fill the TRUSTEE structure */
1961 pTrustee->pMultipleTrustee = NULL;
1962 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1963 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1964 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1965 pTrustee->ptstrName = (LPWSTR)pObjName;
1966 }
1967
1968 /******************************************************************************
1969 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
1970 */
1971 VOID WINAPI
1972 BuildTrusteeWithObjectsAndSidA(PTRUSTEEA pTrustee,
1973 POBJECTS_AND_SID pObjSid,
1974 GUID *pObjectGuid,
1975 GUID *pInheritedObjectGuid,
1976 PSID pSid)
1977 {
1978 DWORD ObjectsPresent = 0;
1979
1980 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
1981
1982 /* Fill the OBJECTS_AND_SID structure */
1983 if (pObjectGuid != NULL)
1984 {
1985 pObjSid->ObjectTypeGuid = *pObjectGuid;
1986 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1987 }
1988 else
1989 {
1990 ZeroMemory(&pObjSid->ObjectTypeGuid,
1991 sizeof(GUID));
1992 }
1993
1994 if (pInheritedObjectGuid != NULL)
1995 {
1996 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
1997 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1998 }
1999 else
2000 {
2001 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
2002 sizeof(GUID));
2003 }
2004
2005 pObjSid->ObjectsPresent = ObjectsPresent;
2006 pObjSid->pSid = pSid;
2007
2008 /* Fill the TRUSTEE structure */
2009 pTrustee->pMultipleTrustee = NULL;
2010 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2011 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
2012 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2013 pTrustee->ptstrName = (LPSTR) pObjSid;
2014 }
2015
2016
2017 /******************************************************************************
2018 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
2019 */
2020 VOID WINAPI
2021 BuildTrusteeWithObjectsAndSidW(PTRUSTEEW pTrustee,
2022 POBJECTS_AND_SID pObjSid,
2023 GUID *pObjectGuid,
2024 GUID *pInheritedObjectGuid,
2025 PSID pSid)
2026 {
2027 DWORD ObjectsPresent = 0;
2028
2029 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
2030
2031 /* Fill the OBJECTS_AND_SID structure */
2032 if (pObjectGuid != NULL)
2033 {
2034 pObjSid->ObjectTypeGuid = *pObjectGuid;
2035 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
2036 }
2037 else
2038 {
2039 ZeroMemory(&pObjSid->ObjectTypeGuid,
2040 sizeof(GUID));
2041 }
2042
2043 if (pInheritedObjectGuid != NULL)
2044 {
2045 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
2046 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
2047 }
2048 else
2049 {
2050 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
2051 sizeof(GUID));
2052 }
2053
2054 pObjSid->ObjectsPresent = ObjectsPresent;
2055 pObjSid->pSid = pSid;
2056
2057 /* Fill the TRUSTEE structure */
2058 pTrustee->pMultipleTrustee = NULL;
2059 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2060 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
2061 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2062 pTrustee->ptstrName = (LPWSTR) pObjSid;
2063 }
2064
2065 /******************************************************************************
2066 * BuildTrusteeWithSidA [ADVAPI32.@]
2067 */
2068 VOID WINAPI
2069 BuildTrusteeWithSidA(PTRUSTEE_A pTrustee,
2070 PSID pSid)
2071 {
2072 TRACE("%p %p\n", pTrustee, pSid);
2073
2074 pTrustee->pMultipleTrustee = NULL;
2075 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2076 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
2077 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2078 pTrustee->ptstrName = (LPSTR) pSid;
2079 }
2080
2081
2082 /******************************************************************************
2083 * BuildTrusteeWithSidW [ADVAPI32.@]
2084 */
2085 VOID WINAPI
2086 BuildTrusteeWithSidW(PTRUSTEE_W pTrustee,
2087 PSID pSid)
2088 {
2089 TRACE("%p %p\n", pTrustee, pSid);
2090
2091 pTrustee->pMultipleTrustee = NULL;
2092 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2093 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
2094 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2095 pTrustee->ptstrName = (LPWSTR) pSid;
2096 }
2097
2098 /******************************************************************************
2099 * BuildTrusteeWithNameA [ADVAPI32.@]
2100 */
2101 VOID WINAPI
2102 BuildTrusteeWithNameA(PTRUSTEE_A pTrustee,
2103 LPSTR name)
2104 {
2105 TRACE("%p %s\n", pTrustee, name);
2106
2107 pTrustee->pMultipleTrustee = NULL;
2108 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2109 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
2110 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2111 pTrustee->ptstrName = name;
2112 }
2113
2114 /******************************************************************************
2115 * BuildTrusteeWithNameW [ADVAPI32.@]
2116 */
2117 VOID WINAPI
2118 BuildTrusteeWithNameW(PTRUSTEE_W pTrustee,
2119 LPWSTR name)
2120 {
2121 TRACE("%p %s\n", pTrustee, name);
2122
2123 pTrustee->pMultipleTrustee = NULL;
2124 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2125 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
2126 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2127 pTrustee->ptstrName = name;
2128 }
2129
2130 /******************************************************************************
2131 * GetTrusteeFormW [ADVAPI32.@]
2132 */
2133 TRUSTEE_FORM WINAPI
2134 GetTrusteeFormA(PTRUSTEE_A pTrustee)
2135 {
2136 return pTrustee->TrusteeForm;
2137 }
2138
2139
2140 /******************************************************************************
2141 * GetTrusteeFormW [ADVAPI32.@]
2142 */
2143 TRUSTEE_FORM WINAPI
2144 GetTrusteeFormW(PTRUSTEE_W pTrustee)
2145 {
2146 return pTrustee->TrusteeForm;
2147 }
2148
2149 /******************************************************************************
2150 * GetTrusteeNameA [ADVAPI32.@]
2151 */
2152 LPSTR WINAPI
2153 GetTrusteeNameA(PTRUSTEE_A pTrustee)
2154 {
2155 return pTrustee->ptstrName;
2156 }
2157
2158
2159 /******************************************************************************
2160 * GetTrusteeNameW [ADVAPI32.@]
2161 */
2162 LPWSTR WINAPI
2163 GetTrusteeNameW(PTRUSTEE_W pTrustee)
2164 {
2165 return pTrustee->ptstrName;
2166 }
2167
2168 /******************************************************************************
2169 * GetTrusteeTypeA [ADVAPI32.@]
2170 */
2171 TRUSTEE_TYPE WINAPI
2172 GetTrusteeTypeA(PTRUSTEE_A pTrustee)
2173 {
2174 return pTrustee->TrusteeType;
2175 }
2176
2177 /******************************************************************************
2178 * GetTrusteeTypeW [ADVAPI32.@]
2179 */
2180 TRUSTEE_TYPE WINAPI
2181 GetTrusteeTypeW(PTRUSTEE_W pTrustee)
2182 {
2183 return pTrustee->TrusteeType;
2184 }
2185
2186 /*
2187 * @implemented
2188 */
2189 BOOL
2190 WINAPI
2191 SetAclInformation(PACL pAcl,
2192 LPVOID pAclInformation,
2193 DWORD nAclInformationLength,
2194 ACL_INFORMATION_CLASS dwAclInformationClass)
2195 {
2196 NTSTATUS Status;
2197
2198 Status = RtlSetInformationAcl(pAcl,
2199 pAclInformation,
2200 nAclInformationLength,
2201 dwAclInformationClass);
2202 if (!NT_SUCCESS(Status))
2203 {
2204 SetLastError(RtlNtStatusToDosError(Status));
2205 return FALSE;
2206 }
2207
2208 return TRUE;
2209 }
2210
2211 /**********************************************************************
2212 * SetNamedSecurityInfoA EXPORTED
2213 *
2214 * @implemented
2215 */
2216 DWORD
2217 WINAPI
2218 SetNamedSecurityInfoA(LPSTR pObjectName,
2219 SE_OBJECT_TYPE ObjectType,
2220 SECURITY_INFORMATION SecurityInfo,
2221 PSID psidOwner,
2222 PSID psidGroup,
2223 PACL pDacl,
2224 PACL pSacl)
2225 {
2226 UNICODE_STRING ObjectName;
2227 DWORD Ret;
2228
2229 if (!RtlCreateUnicodeStringFromAsciiz(&ObjectName, pObjectName))
2230 {
2231 return ERROR_NOT_ENOUGH_MEMORY;
2232 }
2233
2234 Ret = SetNamedSecurityInfoW(ObjectName.Buffer,
2235 ObjectType,
2236 SecurityInfo,
2237 psidOwner,
2238 psidGroup,
2239 pDacl,
2240 pSacl);
2241
2242 RtlFreeUnicodeString(&ObjectName);
2243
2244 return Ret;
2245 }
2246
2247 /*
2248 * @implemented
2249 */
2250 BOOL
2251 WINAPI
2252 AreAllAccessesGranted(DWORD GrantedAccess,
2253 DWORD DesiredAccess)
2254 {
2255 return (BOOL)RtlAreAllAccessesGranted(GrantedAccess,
2256 DesiredAccess);
2257 }
2258
2259 /*
2260 * @implemented
2261 */
2262 BOOL
2263 WINAPI
2264 AreAnyAccessesGranted(DWORD GrantedAccess,
2265 DWORD DesiredAccess)
2266 {
2267 return (BOOL)RtlAreAnyAccessesGranted(GrantedAccess,
2268 DesiredAccess);
2269 }
2270
2271 /******************************************************************************
2272 * ParseAclStringFlags
2273 */
2274 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
2275 {
2276 DWORD flags = 0;
2277 LPCWSTR szAcl = *StringAcl;
2278
2279 while (*szAcl != '(')
2280 {
2281 if (*szAcl == 'P')
2282 {
2283 flags |= SE_DACL_PROTECTED;
2284 }
2285 else if (*szAcl == 'A')
2286 {
2287 szAcl++;
2288 if (*szAcl == 'R')
2289 flags |= SE_DACL_AUTO_INHERIT_REQ;
2290 else if (*szAcl == 'I')
2291 flags |= SE_DACL_AUTO_INHERITED;
2292 }
2293 szAcl++;
2294 }
2295
2296 *StringAcl = szAcl;
2297 return flags;
2298 }
2299
2300 /******************************************************************************
2301 * ParseAceStringType
2302 */
2303 static const ACEFLAG AceType[] =
2304 {
2305 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
2306 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
2307 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
2308 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
2309 /*
2310 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
2311 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
2312 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
2313 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
2314 */
2315 { NULL, 0 },
2316 };
2317
2318 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
2319 {
2320 UINT len = 0;
2321 LPCWSTR szAcl = *StringAcl;
2322 const ACEFLAG *lpaf = AceType;
2323
2324 while (*szAcl == ' ')
2325 szAcl++;
2326
2327 while (lpaf->wstr &&
2328 (len = strlenW(lpaf->wstr)) &&
2329 strncmpW(lpaf->wstr, szAcl, len))
2330 lpaf++;
2331
2332 if (!lpaf->wstr)
2333 return 0;
2334
2335 *StringAcl = szAcl + len;
2336 return lpaf->value;
2337 }
2338
2339
2340 /******************************************************************************
2341 * ParseAceStringFlags
2342 */
2343 static const ACEFLAG AceFlags[] =
2344 {
2345 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
2346 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
2347 { SDDL_INHERITED, INHERITED_ACE },
2348 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
2349 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
2350 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
2351 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
2352 { NULL, 0 },
2353 };
2354
2355 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
2356 {
2357 UINT len = 0;
2358 BYTE flags = 0;
2359 LPCWSTR szAcl = *StringAcl;
2360
2361 while (*szAcl == ' ')
2362 szAcl++;
2363
2364 while (*szAcl != ';')
2365 {
2366 const ACEFLAG *lpaf = AceFlags;
2367
2368 while (lpaf->wstr &&
2369 (len = strlenW(lpaf->wstr)) &&
2370 strncmpW(lpaf->wstr, szAcl, len))
2371 lpaf++;
2372
2373 if (!lpaf->wstr)
2374 return 0;
2375
2376 flags |= lpaf->value;
2377 szAcl += len;
2378 }
2379
2380 *StringAcl = szAcl;
2381 return flags;
2382 }
2383
2384
2385 /******************************************************************************
2386 * ParseAceStringRights
2387 */
2388 static const ACEFLAG AceRights[] =
2389 {
2390 { SDDL_GENERIC_ALL, GENERIC_ALL },
2391 { SDDL_GENERIC_READ, GENERIC_READ },
2392 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
2393 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
2394
2395 { SDDL_READ_CONTROL, READ_CONTROL },
2396 { SDDL_STANDARD_DELETE, DELETE },
2397 { SDDL_WRITE_DAC, WRITE_DAC },
2398 { SDDL_WRITE_OWNER, WRITE_OWNER },
2399
2400 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
2401 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
2402 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
2403 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
2404 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
2405 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
2406 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
2407 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
2408 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
2409
2410 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
2411 { SDDL_FILE_READ, FILE_GENERIC_READ },
2412 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
2413 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
2414
2415 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
2416 { SDDL_KEY_READ, KEY_READ },
2417 { SDDL_KEY_WRITE, KEY_WRITE },
2418 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
2419 { NULL, 0 },
2420 };
2421
2422 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
2423 {
2424 UINT len = 0;
2425 DWORD rights = 0;
2426 LPCWSTR szAcl = *StringAcl;
2427
2428 while (*szAcl == ' ')
2429 szAcl++;
2430
2431 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
2432 {
2433 LPCWSTR p = szAcl;
2434
2435 while (*p && *p != ';')
2436 p++;
2437
2438 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
2439 {
2440 rights = strtoulW(szAcl, NULL, 16);
2441 szAcl = p;
2442 }
2443 else
2444 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
2445 }
2446 else
2447 {
2448 while (*szAcl != ';')
2449 {
2450 const ACEFLAG *lpaf = AceRights;
2451
2452 while (lpaf->wstr &&
2453 (len = strlenW(lpaf->wstr)) &&
2454 strncmpW(lpaf->wstr, szAcl, len))
2455 {
2456 lpaf++;
2457 }
2458
2459 if (!lpaf->wstr)
2460 return 0;
2461
2462 rights |= lpaf->value;
2463 szAcl += len;
2464 }
2465 }
2466
2467 *StringAcl = szAcl;
2468 return rights;
2469 }
2470
2471
2472 /******************************************************************************
2473 * ParseStringAclToAcl
2474 *
2475 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
2476 */
2477 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
2478 PACL pAcl, LPDWORD cBytes)
2479 {
2480 DWORD val;
2481 DWORD sidlen;
2482 DWORD length = sizeof(ACL);
2483 DWORD acesize = 0;
2484 DWORD acecount = 0;
2485 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
2486 DWORD error = ERROR_INVALID_ACL;
2487
2488 TRACE("%s\n", debugstr_w(StringAcl));
2489
2490 if (!StringAcl)
2491 return FALSE;
2492
2493 if (pAcl) /* pAce is only useful if we're setting values */
2494 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
2495
2496 /* Parse ACL flags */
2497 *lpdwFlags = ParseAclStringFlags(&StringAcl);
2498
2499 /* Parse ACE */
2500 while (*StringAcl == '(')
2501 {
2502 StringAcl++;
2503
2504 /* Parse ACE type */
2505 val = ParseAceStringType(&StringAcl);
2506 if (pAce)
2507 pAce->Header.AceType = (BYTE) val;
2508 if (*StringAcl != ';')
2509 {
2510 error = RPC_S_INVALID_STRING_UUID;
2511 goto lerr;
2512 }
2513 StringAcl++;
2514
2515 /* Parse ACE flags */
2516 val = ParseAceStringFlags(&StringAcl);
2517 if (pAce)
2518 pAce->Header.AceFlags = (BYTE) val;
2519 if (*StringAcl != ';')
2520 goto lerr;
2521 StringAcl++;
2522
2523 /* Parse ACE rights */
2524 val = ParseAceStringRights(&StringAcl);
2525 if (pAce)
2526 pAce->Mask = val;
2527 if (*StringAcl != ';')
2528 goto lerr;
2529 StringAcl++;
2530
2531 /* Parse ACE object guid */
2532 while (*StringAcl == ' ')
2533 StringAcl++;
2534 if (*StringAcl != ';')
2535 {
2536 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
2537 goto lerr;
2538 }
2539 StringAcl++;
2540
2541 /* Parse ACE inherit object guid */
2542 while (*StringAcl == ' ')
2543 StringAcl++;
2544 if (*StringAcl != ';')
2545 {
2546 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
2547 goto lerr;
2548 }
2549 StringAcl++;
2550
2551 /* Parse ACE account sid */
2552 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
2553 {
2554 while (*StringAcl && *StringAcl != ')')
2555 StringAcl++;
2556 }
2557
2558 if (*StringAcl != ')')
2559 goto lerr;
2560 StringAcl++;
2561
2562 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
2563 length += acesize;
2564 if (pAce)
2565 {
2566 pAce->Header.AceSize = acesize;
2567 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
2568 }
2569 acecount++;
2570 }
2571
2572 *cBytes = length;
2573
2574 if (length > 0xffff)
2575 {
2576 ERR("ACL too large\n");
2577 goto lerr;
2578 }
2579
2580 if (pAcl)
2581 {
2582 pAcl->AclRevision = ACL_REVISION;
2583 pAcl->Sbz1 = 0;
2584 pAcl->AclSize = length;
2585 pAcl->AceCount = acecount++;
2586 pAcl->Sbz2 = 0;
2587 }
2588 return TRUE;
2589
2590 lerr:
2591 SetLastError(error);
2592 WARN("Invalid ACE string format\n");
2593 return FALSE;
2594 }
2595
2596
2597 /******************************************************************************
2598 * ParseStringSecurityDescriptorToSecurityDescriptor
2599 */
2600 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
2601 LPCWSTR StringSecurityDescriptor,
2602 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
2603 LPDWORD cBytes)
2604 {
2605 BOOL bret = FALSE;
2606 WCHAR toktype;
2607 WCHAR tok[MAX_PATH];
2608 LPCWSTR lptoken;
2609 LPBYTE lpNext = NULL;
2610 DWORD len;
2611
2612 *cBytes = sizeof(SECURITY_DESCRIPTOR);
2613
2614 if (SecurityDescriptor)
2615 lpNext = (LPBYTE)(SecurityDescriptor + 1);
2616
2617 while (*StringSecurityDescriptor == ' ')
2618 StringSecurityDescriptor++;
2619
2620 while (*StringSecurityDescriptor)
2621 {
2622 toktype = *StringSecurityDescriptor;
2623
2624 /* Expect char identifier followed by ':' */
2625 StringSecurityDescriptor++;
2626 if (*StringSecurityDescriptor != ':')
2627 {
2628 SetLastError(ERROR_INVALID_PARAMETER);
2629 goto lend;
2630 }
2631 StringSecurityDescriptor++;
2632
2633 /* Extract token */
2634 lptoken = StringSecurityDescriptor;
2635 while (*lptoken && *lptoken != ':')
2636 lptoken++;
2637
2638 if (*lptoken)
2639 lptoken--;
2640
2641 len = lptoken - StringSecurityDescriptor;
2642 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
2643 tok[len] = 0;
2644
2645 switch (toktype)
2646 {
2647 case 'O':
2648 {
2649 DWORD bytes;
2650
2651 if (!ParseStringSidToSid(tok, lpNext, &bytes))
2652 goto lend;
2653
2654 if (SecurityDescriptor)
2655 {
2656 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
2657 lpNext += bytes; /* Advance to next token */
2658 }
2659
2660 *cBytes += bytes;
2661
2662 break;
2663 }
2664
2665 case 'G':
2666 {
2667 DWORD bytes;
2668
2669 if (!ParseStringSidToSid(tok, lpNext, &bytes))
2670 goto lend;
2671
2672 if (SecurityDescriptor)
2673 {
2674 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
2675 lpNext += bytes; /* Advance to next token */
2676 }
2677
2678 *cBytes += bytes;
2679
2680 break;
2681 }
2682
2683 case 'D':
2684 {
2685 DWORD flags;
2686 DWORD bytes;
2687
2688 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
2689 goto lend;
2690
2691 if (SecurityDescriptor)
2692 {
2693 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
2694 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
2695 lpNext += bytes; /* Advance to next token */
2696 }
2697
2698 *cBytes += bytes;
2699
2700 break;
2701 }
2702
2703 case 'S':
2704 {
2705 DWORD flags;
2706 DWORD bytes;
2707
2708 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
2709 goto lend;
2710
2711 if (SecurityDescriptor)
2712 {
2713 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
2714 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
2715 lpNext += bytes; /* Advance to next token */
2716 }
2717
2718 *cBytes += bytes;
2719
2720 break;
2721 }
2722
2723 default:
2724 FIXME("Unknown token\n");
2725 SetLastError(ERROR_INVALID_PARAMETER);
2726 goto lend;
2727 }
2728
2729 StringSecurityDescriptor = lptoken;
2730 }
2731
2732 bret = TRUE;
2733
2734 lend:
2735 return bret;
2736 }
2737
2738 /* Winehq cvs 20050916 */
2739 /******************************************************************************
2740 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
2741 * @implemented
2742 */
2743 BOOL
2744 WINAPI
2745 ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor,
2746 DWORD StringSDRevision,
2747 PSECURITY_DESCRIPTOR* SecurityDescriptor,
2748 PULONG SecurityDescriptorSize)
2749 {
2750 UINT len;
2751 BOOL ret = FALSE;
2752 LPWSTR StringSecurityDescriptorW;
2753
2754 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
2755 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2756
2757 if (StringSecurityDescriptorW)
2758 {
2759 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
2760
2761 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
2762 StringSDRevision, SecurityDescriptor,
2763 SecurityDescriptorSize);
2764 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
2765 }
2766
2767 return ret;
2768 }
2769
2770 /******************************************************************************
2771 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
2772 * @implemented
2773 */
2774 BOOL WINAPI
2775 ConvertStringSecurityDescriptorToSecurityDescriptorW(LPCWSTR StringSecurityDescriptor,
2776 DWORD StringSDRevision,
2777 PSECURITY_DESCRIPTOR* SecurityDescriptor,
2778 PULONG SecurityDescriptorSize)
2779 {
2780 DWORD cBytes;
2781 SECURITY_DESCRIPTOR* psd;
2782 BOOL bret = FALSE;
2783
2784 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
2785
2786 if (GetVersion() & 0x80000000)
2787 {
2788 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2789 goto lend;
2790 }
2791 else if (!StringSecurityDescriptor || !SecurityDescriptor)
2792 {
2793 SetLastError(ERROR_INVALID_PARAMETER);
2794 goto lend;
2795 }
2796 else if (StringSDRevision != SID_REVISION)
2797 {
2798 SetLastError(ERROR_UNKNOWN_REVISION);
2799 goto lend;
2800 }
2801
2802 /* Compute security descriptor length */
2803 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
2804 NULL, &cBytes))
2805 goto lend;
2806
2807 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
2808 if (!psd) goto lend;
2809
2810 psd->Revision = SID_REVISION;
2811 psd->Control |= SE_SELF_RELATIVE;
2812
2813 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
2814 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
2815 {
2816 LocalFree(psd);
2817 goto lend;
2818 }
2819
2820 if (SecurityDescriptorSize)
2821 *SecurityDescriptorSize = cBytes;
2822
2823 bret = TRUE;
2824
2825 lend:
2826 TRACE(" ret=%d\n", bret);
2827 return bret;
2828 }
2829
2830 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
2831 {
2832 if (cch == -1)
2833 cch = strlenW(string);
2834
2835 if (plen)
2836 *plen += cch;
2837
2838 if (pwptr)
2839 {
2840 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
2841 *pwptr += cch;
2842 }
2843 }
2844
2845 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
2846 {
2847 DWORD i;
2848 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
2849 WCHAR subauthfmt[] = { '-','%','u',0 };
2850 WCHAR buf[26];
2851 SID *pisid = psid;
2852
2853 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
2854 {
2855 SetLastError(ERROR_INVALID_SID);
2856 return FALSE;
2857 }
2858
2859 if (pisid->IdentifierAuthority.Value[0] ||
2860 pisid->IdentifierAuthority.Value[1])
2861 {
2862 FIXME("not matching MS' bugs\n");
2863 SetLastError(ERROR_INVALID_SID);
2864 return FALSE;
2865 }
2866
2867 sprintfW( buf, fmt, pisid->Revision,
2868 MAKELONG(
2869 MAKEWORD( pisid->IdentifierAuthority.Value[5],
2870 pisid->IdentifierAuthority.Value[4] ),
2871 MAKEWORD( pisid->IdentifierAuthority.Value[3],
2872 pisid->IdentifierAuthority.Value[2] )
2873 ) );
2874 DumpString(buf, -1, pwptr, plen);
2875
2876 for( i=0; i<pisid->SubAuthorityCount; i++ )
2877 {
2878 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
2879 DumpString(buf, -1, pwptr, plen);
2880 }
2881 return TRUE;
2882 }
2883
2884 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
2885 {
2886 size_t i;
2887 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
2888 {
2889 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
2890 {
2891 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
2892 return TRUE;
2893 }
2894 }
2895
2896 return DumpSidNumeric(psid, pwptr, plen);
2897 }
2898
2899 static const LPCWSTR AceRightBitNames[32] = {
2900 SDDL_CREATE_CHILD, /* 0 */
2901 SDDL_DELETE_CHILD,
2902 SDDL_LIST_CHILDREN,
2903 SDDL_SELF_WRITE,
2904 SDDL_READ_PROPERTY, /* 4 */
2905 SDDL_WRITE_PROPERTY,
2906 SDDL_DELETE_TREE,
2907 SDDL_LIST_OBJECT,
2908 SDDL_CONTROL_ACCESS, /* 8 */
2909 NULL,
2910 NULL,
2911 NULL,
2912 NULL, /* 12 */
2913 NULL,
2914 NULL,
2915 NULL,
2916 SDDL_STANDARD_DELETE, /* 16 */
2917 SDDL_READ_CONTROL,
2918 SDDL_WRITE_DAC,
2919 SDDL_WRITE_OWNER,
2920 NULL, /* 20 */
2921 NULL,
2922 NULL,
2923 NULL,
2924 NULL, /* 24 */
2925 NULL,
2926 NULL,
2927 NULL,
2928 SDDL_GENERIC_ALL, /* 28 */
2929 SDDL_GENERIC_EXECUTE,
2930 SDDL_GENERIC_WRITE,
2931 SDDL_GENERIC_READ
2932 };
2933
2934 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
2935 {
2936 static const WCHAR fmtW[] = {'0','x','%','x',0};
2937 WCHAR buf[15];
2938 size_t i;
2939
2940 if (mask == 0)
2941 return;
2942
2943 /* first check if the right have name */
2944 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
2945 {
2946 if (AceRights[i].wstr == NULL)
2947 break;
2948 if (mask == AceRights[i].value)
2949 {
2950 DumpString(AceRights[i].wstr, -1, pwptr, plen);
2951 return;
2952 }
2953 }
2954
2955 /* then check if it can be built from bit names */
2956 for (i = 0; i < 32; i++)
2957 {
2958 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
2959 {
2960 /* can't be built from bit names */
2961 sprintfW(buf, fmtW, mask);
2962 DumpString(buf, -1, pwptr, plen);
2963 return;
2964 }
2965 }
2966
2967 /* build from bit names */
2968 for (i = 0; i < 32; i++)
2969 if (mask & (1 << i))
2970 DumpString(AceRightBitNames[i], -1, pwptr, plen);
2971 }
2972
2973 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
2974 {
2975 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
2976 static const WCHAR openbr = '(';
2977 static const WCHAR closebr = ')';
2978 static const WCHAR semicolon = ';';
2979
2980 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
2981 {
2982 SetLastError(ERROR_INVALID_ACL);
2983 return FALSE;
2984 }
2985
2986 piace = pace;
2987 DumpString(&openbr, 1, pwptr, plen);
2988 switch (piace->Header.AceType)
2989 {
2990 case ACCESS_ALLOWED_ACE_TYPE:
2991 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
2992 break;
2993 case ACCESS_DENIED_ACE_TYPE:
2994 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
2995 break;
2996 case SYSTEM_AUDIT_ACE_TYPE:
2997 DumpString(SDDL_AUDIT, -1, pwptr, plen);
2998 break;
2999 case SYSTEM_ALARM_ACE_TYPE:
3000 DumpString(SDDL_ALARM, -1, pwptr, plen);
3001 break;
3002 }
3003 DumpString(&semicolon, 1, pwptr, plen);
3004
3005 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
3006 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
3007 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
3008 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
3009 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
3010 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
3011 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
3012 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
3013 if (piace->Header.AceFlags & INHERITED_ACE)
3014 DumpString(SDDL_INHERITED, -1, pwptr, plen);
3015 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
3016 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
3017 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
3018 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
3019 DumpString(&semicolon, 1, pwptr, plen);
3020 DumpRights(piace->Mask, pwptr, plen);
3021 DumpString(&semicolon, 1, pwptr, plen);
3022 /* objects not supported */
3023 DumpString(&semicolon, 1, pwptr, plen);
3024 /* objects not supported */
3025 DumpString(&semicolon, 1, pwptr, plen);
3026 if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
3027 return FALSE;
3028 DumpString(&closebr, 1, pwptr, plen);
3029 return TRUE;
3030 }
3031
3032 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
3033 {
3034 WORD count;
3035 int i;
3036
3037 if (protected)
3038 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
3039 if (autoInheritReq)
3040 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
3041 if (autoInherited)
3042 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
3043
3044 if (pacl == NULL)
3045 return TRUE;
3046
3047 if (!IsValidAcl(pacl))
3048 return FALSE;
3049
3050 count = pacl->AceCount;
3051 for (i = 0; i < count; i++)
3052 {
3053 LPVOID ace;
3054 if (!GetAce(pacl, i, &ace))
3055 return FALSE;
3056 if (!DumpAce(ace, pwptr, plen))
3057 return FALSE;
3058 }
3059
3060 return TRUE;
3061 }
3062
3063 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3064 {
3065 static const WCHAR prefix[] = {'O',':',0};
3066 BOOL bDefaulted;
3067 PSID psid;
3068
3069 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
3070 return FALSE;
3071
3072 if (psid == NULL)
3073 return TRUE;
3074
3075 DumpString(prefix, -1, pwptr, plen);
3076 if (!DumpSid(psid, pwptr, plen))
3077 return FALSE;
3078 return TRUE;
3079 }
3080
3081 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3082 {
3083 static const WCHAR prefix[] = {'G',':',0};
3084 BOOL bDefaulted;
3085 PSID psid;
3086
3087 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
3088 return FALSE;
3089
3090 if (psid == NULL)
3091 return TRUE;
3092
3093 DumpString(prefix, -1, pwptr, plen);
3094 if (!DumpSid(psid, pwptr, plen))
3095 return FALSE;
3096 return TRUE;
3097 }
3098
3099 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3100 {
3101 static const WCHAR dacl[] = {'D',':',0};
3102 SECURITY_DESCRIPTOR_CONTROL control;
3103 BOOL present, defaulted;
3104 DWORD revision;
3105 PACL pacl;
3106
3107 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
3108 return FALSE;
3109
3110 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
3111 return FALSE;
3112
3113 if (!present)
3114 return TRUE;
3115
3116 DumpString(dacl, 2, pwptr, plen);
3117 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
3118 return FALSE;
3119 return TRUE;
3120 }
3121
3122 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3123 {
3124 static const WCHAR sacl[] = {'S',':',0};
3125 SECURITY_DESCRIPTOR_CONTROL control;
3126 BOOL present, defaulted;
3127 DWORD revision;
3128 PACL pacl;
3129
3130 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
3131 return FALSE;
3132
3133 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
3134 return FALSE;
3135
3136 if (!present)
3137 return TRUE;
3138
3139 DumpString(sacl, 2, pwptr, plen);
3140 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
3141 return FALSE;
3142 return TRUE;
3143 }
3144
3145 /******************************************************************************
3146 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
3147 * @implemented
3148 */
3149 BOOL WINAPI
3150 ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
3151 DWORD SDRevision,
3152 SECURITY_INFORMATION SecurityInformation,
3153 LPWSTR *OutputString,
3154 PULONG OutputLen)
3155 {
3156 ULONG len;
3157 WCHAR *wptr, *wstr;
3158
3159 if (SDRevision != SDDL_REVISION_1)
3160 {
3161 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
3162 SetLastError(ERROR_UNKNOWN_REVISION);
3163 return FALSE;
3164 }
3165
3166 len = 0;
3167 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
3168 if (!DumpOwner(SecurityDescriptor, NULL, &len))
3169 return FALSE;
3170 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
3171 if (!DumpGroup(SecurityDescriptor, NULL, &len))
3172 return FALSE;
3173 if (SecurityInformation & DACL_SECURITY_INFORMATION)
3174 if (!DumpDacl(SecurityDescriptor, NULL, &len))
3175 return FALSE;
3176 if (SecurityInformation & SACL_SECURITY_INFORMATION)
3177 if (!DumpSacl(SecurityDescriptor, NULL, &len))
3178 return FALSE;
3179
3180 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
3181 if (wstr == NULL)
3182 return FALSE;
3183
3184 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
3185 if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
3186 return FALSE;
3187 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
3188 if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
3189 return FALSE;
3190 if (SecurityInformation & DACL_SECURITY_INFORMATION)
3191 if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
3192 return FALSE;
3193 if (SecurityInformation & SACL_SECURITY_INFORMATION)
3194 if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
3195 return FALSE;
3196 *wptr = 0;
3197
3198 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
3199 *OutputString = wstr;
3200 if (OutputLen)
3201 *OutputLen = strlenW(*OutputString)+1;
3202 return TRUE;
3203 }
3204
3205 /******************************************************************************
3206 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
3207 * @implemented
3208 */
3209 BOOL WINAPI
3210 ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
3211 DWORD SDRevision,
3212 SECURITY_INFORMATION Information,
3213 LPSTR *OutputString,
3214 PULONG OutputLen)
3215 {
3216 LPWSTR wstr;
3217 ULONG len;
3218
3219 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
3220 {
3221 int lenA;
3222
3223 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
3224 *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
3225 if (*OutputString == NULL)
3226 {
3227 LocalFree(wstr);
3228 *OutputLen = 0;
3229 return FALSE;
3230 }
3231 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
3232 LocalFree(wstr);
3233
3234 if (OutputLen != NULL)
3235 *OutputLen = lenA;
3236 return TRUE;
3237 }
3238 else
3239 {
3240 *OutputString = NULL;
3241 if (OutputLen)