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