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