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