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