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