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