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