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