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