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