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