Sync to trunk r65566.
[reactos.git] / dll / win32 / advapi32 / wine / security.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * WINE COPYRIGHT:
4 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6 * Copyright 2006 Robert Reif
7 * Copyright 2006 Hervé Poussineau
8 *
9 * PROJECT: ReactOS system libraries
10 * FILE: dll/win32/advapi32/wine/security.c
11 */
12
13 #include <advapi32.h>
14
15 #include <sddl.h>
16
17 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
18
19 static 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 { {0,0}, WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS },
112 { {0,0}, WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS },
113 { {0,0}, WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS },
114 { {0,0}, WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS },
115 { {0,0}, WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS },
116 { {0,0}, WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS },
117 { {0,0}, WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS },
118 { {0,0}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
119 { {0,0}, WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS },
120 { {0,0}, 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 cbDisplayName,
1106 LPDWORD lpLanguageId)
1107 {
1108 FIXME("%s() not implemented!\n", __FUNCTION__);
1109 SetLastError (ERROR_CALL_NOT_IMPLEMENTED);
1110 return FALSE;
1111 }
1112
1113
1114 /**********************************************************************
1115 * LookupPrivilegeDisplayNameW EXPORTED
1116 *
1117 * @unimplemented
1118 */
1119 BOOL
1120 WINAPI
1121 LookupPrivilegeDisplayNameW(LPCWSTR lpSystemName,
1122 LPCWSTR lpName,
1123 LPWSTR lpDisplayName,
1124 LPDWORD cbDisplayName,
1125 LPDWORD lpLanguageId)
1126 {
1127 FIXME("%s() not implemented!\n", __FUNCTION__);
1128 SetLastError (ERROR_CALL_NOT_IMPLEMENTED);
1129 return FALSE;
1130 }
1131
1132 /**********************************************************************
1133 * LookupPrivilegeNameA EXPORTED
1134 *
1135 * @implemented
1136 */
1137 BOOL
1138 WINAPI
1139 LookupPrivilegeNameA(LPCSTR lpSystemName,
1140 PLUID lpLuid,
1141 LPSTR lpName,
1142 LPDWORD cchName)
1143 {
1144 UNICODE_STRING lpSystemNameW;
1145 BOOL ret;
1146 DWORD wLen = 0;
1147
1148 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
1149
1150 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
1151 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
1152 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1153 {
1154 LPWSTR lpNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR));
1155
1156 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
1157 &wLen);
1158 if (ret)
1159 {
1160 /* Windows crashes if cchName is NULL, so will I */
1161 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
1162 *cchName, NULL, NULL);
1163
1164 if (len == 0)
1165 {
1166 /* WideCharToMultiByte failed */
1167 ret = FALSE;
1168 }
1169 else if (len > *cchName)
1170 {
1171 *cchName = len;
1172 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1173 ret = FALSE;
1174 }
1175 else
1176 {
1177 /* WideCharToMultiByte succeeded, output length needs to be
1178 * length not including NULL terminator
1179 */
1180 *cchName = len - 1;
1181 }
1182 }
1183 HeapFree(GetProcessHeap(), 0, lpNameW);
1184 }
1185 RtlFreeUnicodeString(&lpSystemNameW);
1186 return ret;
1187 }
1188
1189 /******************************************************************************
1190 * GetFileSecurityA [ADVAPI32.@]
1191 *
1192 * Obtains Specified information about the security of a file or directory.
1193 *
1194 * PARAMS
1195 * lpFileName [I] Name of the file to get info for
1196 * RequestedInformation [I] SE_ flags from "winnt.h"
1197 * pSecurityDescriptor [O] Destination for security information
1198 * nLength [I] Length of pSecurityDescriptor
1199 * lpnLengthNeeded [O] Destination for length of returned security information
1200 *
1201 * RETURNS
1202 * Success: TRUE. pSecurityDescriptor contains the requested information.
1203 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
1204 *
1205 * NOTES
1206 * The information returned is constrained by the callers access rights and
1207 * privileges.
1208 *
1209 * @implemented
1210 */
1211 BOOL
1212 WINAPI
1213 GetFileSecurityA(LPCSTR lpFileName,
1214 SECURITY_INFORMATION RequestedInformation,
1215 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1216 DWORD nLength,
1217 LPDWORD lpnLengthNeeded)
1218 {
1219 UNICODE_STRING FileName;
1220 BOOL bResult;
1221
1222 if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName))
1223 {
1224 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1225 return FALSE;
1226 }
1227
1228 bResult = GetFileSecurityW(FileName.Buffer,
1229 RequestedInformation,
1230 pSecurityDescriptor,
1231 nLength,
1232 lpnLengthNeeded);
1233
1234 RtlFreeUnicodeString(&FileName);
1235
1236 return bResult;
1237 }
1238
1239 /*
1240 * @implemented
1241 */
1242 BOOL
1243 WINAPI
1244 GetFileSecurityW(LPCWSTR lpFileName,
1245 SECURITY_INFORMATION RequestedInformation,
1246 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1247 DWORD nLength,
1248 LPDWORD lpnLengthNeeded)
1249 {
1250 OBJECT_ATTRIBUTES ObjectAttributes;
1251 IO_STATUS_BLOCK StatusBlock;
1252 UNICODE_STRING FileName;
1253 ULONG AccessMask = 0;
1254 HANDLE FileHandle;
1255 NTSTATUS Status;
1256
1257 TRACE("GetFileSecurityW() called\n");
1258
1259 QuerySecurityAccessMask(RequestedInformation, &AccessMask);
1260
1261 if (!RtlDosPathNameToNtPathName_U(lpFileName,
1262 &FileName,
1263 NULL,
1264 NULL))
1265 {
1266 ERR("Invalid path\n");
1267 SetLastError(ERROR_INVALID_NAME);
1268 return FALSE;
1269 }
1270
1271 InitializeObjectAttributes(&ObjectAttributes,
1272 &FileName,
1273 OBJ_CASE_INSENSITIVE,
1274 NULL,
1275 NULL);
1276
1277 Status = NtOpenFile(&FileHandle,
1278 AccessMask,
1279 &ObjectAttributes,
1280 &StatusBlock,
1281 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1282 0);
1283
1284 RtlFreeHeap(RtlGetProcessHeap(),
1285 0,
1286 FileName.Buffer);
1287
1288 if (!NT_SUCCESS(Status))
1289 {
1290 ERR("NtOpenFile() failed (Status %lx)\n", Status);
1291 SetLastError(RtlNtStatusToDosError(Status));
1292 return FALSE;
1293 }
1294
1295 Status = NtQuerySecurityObject(FileHandle,
1296 RequestedInformation,
1297 pSecurityDescriptor,
1298 nLength,
1299 lpnLengthNeeded);
1300 NtClose(FileHandle);
1301 if (!NT_SUCCESS(Status))
1302 {
1303 ERR("NtQuerySecurityObject() failed (Status %lx)\n", Status);
1304 SetLastError(RtlNtStatusToDosError(Status));
1305 return FALSE;
1306 }
1307
1308 return TRUE;
1309 }
1310
1311 /******************************************************************************
1312 * SetFileSecurityA [ADVAPI32.@]
1313 * Sets the security of a file or directory
1314 *
1315 * @implemented
1316 */
1317 BOOL
1318 WINAPI
1319 SetFileSecurityA(LPCSTR lpFileName,
1320 SECURITY_INFORMATION SecurityInformation,
1321 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1322 {
1323 UNICODE_STRING FileName;
1324 BOOL bResult;
1325
1326 if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName))
1327 {
1328 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1329 return FALSE;
1330 }
1331
1332 bResult = SetFileSecurityW(FileName.Buffer,
1333 SecurityInformation,
1334 pSecurityDescriptor);
1335
1336 RtlFreeUnicodeString(&FileName);
1337
1338 return bResult;
1339 }
1340
1341 /******************************************************************************
1342 * SetFileSecurityW [ADVAPI32.@]
1343 * Sets the security of a file or directory
1344 *
1345 * @implemented
1346 */
1347 BOOL
1348 WINAPI
1349 SetFileSecurityW(LPCWSTR lpFileName,
1350 SECURITY_INFORMATION SecurityInformation,
1351 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1352 {
1353 OBJECT_ATTRIBUTES ObjectAttributes;
1354 IO_STATUS_BLOCK StatusBlock;
1355 UNICODE_STRING FileName;
1356 ULONG AccessMask = 0;
1357 HANDLE FileHandle;
1358 NTSTATUS Status;
1359
1360 TRACE("SetFileSecurityW() called\n");
1361
1362 SetSecurityAccessMask(SecurityInformation, &AccessMask);
1363
1364 if (!RtlDosPathNameToNtPathName_U(lpFileName,
1365 &FileName,
1366 NULL,
1367 NULL))
1368 {
1369 ERR("Invalid path\n");
1370 SetLastError(ERROR_INVALID_NAME);
1371 return FALSE;
1372 }
1373
1374 InitializeObjectAttributes(&ObjectAttributes,
1375 &FileName,
1376 OBJ_CASE_INSENSITIVE,
1377 NULL,
1378 NULL);
1379
1380 Status = NtOpenFile(&FileHandle,
1381 AccessMask,
1382 &ObjectAttributes,
1383 &StatusBlock,
1384 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1385 0);
1386
1387 RtlFreeHeap(RtlGetProcessHeap(),
1388 0,
1389 FileName.Buffer);
1390
1391 if (!NT_SUCCESS(Status))
1392 {
1393 ERR("NtOpenFile() failed (Status %lx)\n", Status);
1394 SetLastError(RtlNtStatusToDosError(Status));
1395 return FALSE;
1396 }
1397
1398 Status = NtSetSecurityObject(FileHandle,
1399 SecurityInformation,
1400 pSecurityDescriptor);
1401 NtClose(FileHandle);
1402
1403 if (!NT_SUCCESS(Status))
1404 {
1405 ERR("NtSetSecurityObject() failed (Status %lx)\n", Status);
1406 SetLastError(RtlNtStatusToDosError(Status));
1407 return FALSE;
1408 }
1409
1410 return TRUE;
1411 }
1412
1413 /******************************************************************************
1414 * QueryWindows31FilesMigration [ADVAPI32.@]
1415 *
1416 * PARAMS
1417 * x1 []
1418 */
1419 BOOL WINAPI
1420 QueryWindows31FilesMigration( DWORD x1 )
1421 {
1422 FIXME("(%d):stub\n",x1);
1423 return TRUE;
1424 }
1425
1426 /******************************************************************************
1427 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
1428 *
1429 * PARAMS
1430 * x1 []
1431 * x2 []
1432 * x3 []
1433 * x4 []
1434 */
1435 BOOL WINAPI
1436 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
1437 DWORD x4 )
1438 {
1439 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
1440 return TRUE;
1441 }
1442
1443 /*
1444 * @implemented
1445 */
1446 BOOL
1447 WINAPI
1448 RevertToSelf(VOID)
1449 {
1450 NTSTATUS Status;
1451 HANDLE Token = NULL;
1452
1453 Status = NtSetInformationThread(NtCurrentThread(),
1454 ThreadImpersonationToken,
1455 &Token,
1456 sizeof(HANDLE));
1457 if (!NT_SUCCESS(Status))
1458 {
1459 SetLastError(RtlNtStatusToDosError(Status));
1460 return FALSE;
1461 }
1462
1463 return TRUE;
1464 }
1465
1466 /*
1467 * @implemented
1468 */
1469 BOOL
1470 WINAPI
1471 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1472 {
1473 NTSTATUS Status;
1474
1475 Status = RtlImpersonateSelf(ImpersonationLevel);
1476 if (!NT_SUCCESS(Status))
1477 {
1478 SetLastError(RtlNtStatusToDosError(Status));
1479 return FALSE;
1480 }
1481
1482 return TRUE;
1483 }
1484
1485 /*
1486 * @implemented
1487 */
1488 BOOL
1489 WINAPI
1490 AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
1491 IN HANDLE ClientToken,
1492 IN DWORD DesiredAccess,
1493 IN PGENERIC_MAPPING GenericMapping,
1494 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
1495 IN OUT LPDWORD PrivilegeSetLength,
1496 OUT LPDWORD GrantedAccess,
1497 OUT LPBOOL AccessStatus)
1498 {
1499 NTSTATUS Status;
1500 NTSTATUS NtAccessStatus;
1501
1502 /* Do the access check */
1503 Status = NtAccessCheck(pSecurityDescriptor,
1504 ClientToken,
1505 DesiredAccess,
1506 GenericMapping,
1507 PrivilegeSet,
1508 (PULONG)PrivilegeSetLength,
1509 (PACCESS_MASK)GrantedAccess,
1510 &NtAccessStatus);
1511
1512 /* See if the access check operation succeeded */
1513 if (!NT_SUCCESS(Status))
1514 {
1515 /* Check failed */
1516 SetLastError(RtlNtStatusToDosError(Status));
1517 return FALSE;
1518 }
1519
1520 /* Now check the access status */
1521 if (!NT_SUCCESS(NtAccessStatus))
1522 {
1523 /* Access denied */
1524 SetLastError(RtlNtStatusToDosError(NtAccessStatus));
1525 *AccessStatus = FALSE;
1526 }
1527 else
1528 {
1529 /* Access granted */
1530 *AccessStatus = TRUE;
1531 }
1532
1533 /* Check succeeded */
1534 return TRUE;
1535 }
1536
1537 /*
1538 * @unimplemented
1539 */
1540 BOOL WINAPI AccessCheckByType(
1541 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1542 PSID PrincipalSelfSid,
1543 HANDLE ClientToken,
1544 DWORD DesiredAccess,
1545 POBJECT_TYPE_LIST ObjectTypeList,
1546 DWORD ObjectTypeListLength,
1547 PGENERIC_MAPPING GenericMapping,
1548 PPRIVILEGE_SET PrivilegeSet,
1549 LPDWORD PrivilegeSetLength,
1550 LPDWORD GrantedAccess,
1551 LPBOOL AccessStatus)
1552 {
1553 FIXME("stub\n");
1554
1555 *AccessStatus = TRUE;
1556
1557 return !*AccessStatus;
1558 }
1559
1560 /*
1561 * @implemented
1562 */
1563 BOOL
1564 WINAPI
1565 SetKernelObjectSecurity(HANDLE Handle,
1566 SECURITY_INFORMATION SecurityInformation,
1567 PSECURITY_DESCRIPTOR SecurityDescriptor)
1568 {
1569 NTSTATUS Status;
1570
1571 Status = NtSetSecurityObject(Handle,
1572 SecurityInformation,
1573 SecurityDescriptor);
1574 if (!NT_SUCCESS(Status))
1575 {
1576 SetLastError(RtlNtStatusToDosError(Status));
1577 return FALSE;
1578 }
1579
1580 return TRUE;
1581 }
1582
1583 /*
1584 * @implemented
1585 */
1586 BOOL
1587 WINAPI
1588 AddAuditAccessAce(PACL pAcl,
1589 DWORD dwAceRevision,
1590 DWORD dwAccessMask,
1591 PSID pSid,
1592 BOOL bAuditSuccess,
1593 BOOL bAuditFailure)
1594 {
1595 NTSTATUS Status;
1596
1597 Status = RtlAddAuditAccessAce(pAcl,
1598 dwAceRevision,
1599 dwAccessMask,
1600 pSid,
1601 bAuditSuccess,
1602 bAuditFailure);
1603 if (!NT_SUCCESS(Status))
1604 {
1605 SetLastError(RtlNtStatusToDosError(Status));
1606 return FALSE;
1607 }
1608
1609 return TRUE;
1610 }
1611
1612 /*
1613 * @implemented
1614 */
1615 BOOL WINAPI
1616 AddAuditAccessAceEx(PACL pAcl,
1617 DWORD dwAceRevision,
1618 DWORD AceFlags,
1619 DWORD dwAccessMask,
1620 PSID pSid,
1621 BOOL bAuditSuccess,
1622 BOOL bAuditFailure)
1623 {
1624 NTSTATUS Status;
1625
1626 Status = RtlAddAuditAccessAceEx(pAcl,
1627 dwAceRevision,
1628 AceFlags,
1629 dwAccessMask,
1630 pSid,
1631 bAuditSuccess,
1632 bAuditFailure);
1633 if (!NT_SUCCESS(Status))
1634 {
1635 SetLastError(RtlNtStatusToDosError(Status));
1636 return FALSE;
1637 }
1638
1639 return TRUE;
1640 }
1641
1642 /******************************************************************************
1643 * LookupAccountNameA [ADVAPI32.@]
1644 *
1645 * @implemented
1646 */
1647 BOOL
1648 WINAPI
1649 LookupAccountNameA(LPCSTR SystemName,
1650 LPCSTR AccountName,
1651 PSID Sid,
1652 LPDWORD SidLength,
1653 LPSTR ReferencedDomainName,
1654 LPDWORD hReferencedDomainNameLength,
1655 PSID_NAME_USE SidNameUse)
1656 {
1657 BOOL ret;
1658 UNICODE_STRING lpSystemW;
1659 UNICODE_STRING lpAccountW;
1660 LPWSTR lpReferencedDomainNameW = NULL;
1661
1662 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, SystemName);
1663 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, AccountName);
1664
1665 if (ReferencedDomainName)
1666 lpReferencedDomainNameW = HeapAlloc(GetProcessHeap(),
1667 0,
1668 *hReferencedDomainNameLength * sizeof(WCHAR));
1669
1670 ret = LookupAccountNameW(lpSystemW.Buffer,
1671 lpAccountW.Buffer,
1672 Sid,
1673 SidLength,
1674 lpReferencedDomainNameW,
1675 hReferencedDomainNameLength,
1676 SidNameUse);
1677
1678 if (ret && lpReferencedDomainNameW)
1679 {
1680 WideCharToMultiByte(CP_ACP,
1681 0,
1682 lpReferencedDomainNameW,
1683 *hReferencedDomainNameLength + 1,
1684 ReferencedDomainName,
1685 *hReferencedDomainNameLength + 1,
1686 NULL,
1687 NULL);
1688 }
1689
1690 RtlFreeUnicodeString(&lpSystemW);
1691 RtlFreeUnicodeString(&lpAccountW);
1692 HeapFree(GetProcessHeap(), 0, lpReferencedDomainNameW);
1693
1694 return ret;
1695 }
1696
1697 /**********************************************************************
1698 * PrivilegeCheck EXPORTED
1699 *
1700 * @implemented
1701 */
1702 BOOL WINAPI
1703 PrivilegeCheck(HANDLE ClientToken,
1704 PPRIVILEGE_SET RequiredPrivileges,
1705 LPBOOL pfResult)
1706 {
1707 BOOLEAN Result;
1708 NTSTATUS Status;
1709
1710 Status = NtPrivilegeCheck(ClientToken,
1711 RequiredPrivileges,
1712 &Result);
1713 if (!NT_SUCCESS(Status))
1714 {
1715 SetLastError(RtlNtStatusToDosError(Status));
1716 return FALSE;
1717 }
1718
1719 *pfResult = (BOOL)Result;
1720
1721 return TRUE;
1722 }
1723
1724 /******************************************************************************
1725 * GetSecurityInfoExW EXPORTED
1726 */
1727 DWORD
1728 WINAPI
1729 GetSecurityInfoExA(HANDLE hObject,
1730 SE_OBJECT_TYPE ObjectType,
1731 SECURITY_INFORMATION SecurityInfo,
1732 LPCSTR lpProvider,
1733 LPCSTR lpProperty,
1734 PACTRL_ACCESSA *ppAccessList,
1735 PACTRL_AUDITA *ppAuditList,
1736 LPSTR *lppOwner,
1737 LPSTR *lppGroup)
1738 {
1739 FIXME("%s() not implemented!\n", __FUNCTION__);
1740 return ERROR_BAD_PROVIDER;
1741 }
1742
1743
1744 /******************************************************************************
1745 * GetSecurityInfoExW EXPORTED
1746 */
1747 DWORD
1748 WINAPI
1749 GetSecurityInfoExW(HANDLE hObject,
1750 SE_OBJECT_TYPE ObjectType,
1751 SECURITY_INFORMATION SecurityInfo,
1752 LPCWSTR lpProvider,
1753 LPCWSTR lpProperty,
1754 PACTRL_ACCESSW *ppAccessList,
1755 PACTRL_AUDITW *ppAuditList,
1756 LPWSTR *lppOwner,
1757 LPWSTR *lppGroup)
1758 {
1759 FIXME("%s() not implemented!\n", __FUNCTION__);
1760 return ERROR_BAD_PROVIDER;
1761 }
1762
1763 /******************************************************************************
1764 * BuildExplicitAccessWithNameA [ADVAPI32.@]
1765 */
1766 VOID WINAPI
1767 BuildExplicitAccessWithNameA(PEXPLICIT_ACCESSA pExplicitAccess,
1768 LPSTR pTrusteeName,
1769 DWORD AccessPermissions,
1770 ACCESS_MODE AccessMode,
1771 DWORD Inheritance)
1772 {
1773 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1774 pExplicitAccess->grfAccessMode = AccessMode;
1775 pExplicitAccess->grfInheritance = Inheritance;
1776
1777 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1778 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1779 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1780 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1781 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1782 }
1783
1784
1785 /******************************************************************************
1786 * BuildExplicitAccessWithNameW [ADVAPI32.@]
1787 */
1788 VOID WINAPI
1789 BuildExplicitAccessWithNameW(PEXPLICIT_ACCESSW pExplicitAccess,
1790 LPWSTR pTrusteeName,
1791 DWORD AccessPermissions,
1792 ACCESS_MODE AccessMode,
1793 DWORD Inheritance)
1794 {
1795 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1796 pExplicitAccess->grfAccessMode = AccessMode;
1797 pExplicitAccess->grfInheritance = Inheritance;
1798
1799 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1800 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1801 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1802 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1803 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1804 }
1805
1806 /******************************************************************************
1807 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
1808 */
1809 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
1810 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
1811 LPSTR InheritedObjectTypeName, LPSTR Name )
1812 {
1813 DWORD ObjectsPresent = 0;
1814
1815 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1816 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
1817
1818 /* Fill the OBJECTS_AND_NAME structure */
1819 pObjName->ObjectType = ObjectType;
1820 if (ObjectTypeName != NULL)
1821 {
1822 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1823 }
1824
1825 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1826 if (InheritedObjectTypeName != NULL)
1827 {
1828 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1829 }
1830
1831 pObjName->ObjectsPresent = ObjectsPresent;
1832 pObjName->ptstrName = Name;
1833
1834 /* Fill the TRUSTEE structure */
1835 pTrustee->pMultipleTrustee = NULL;
1836 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1837 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1838 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1839 pTrustee->ptstrName = (LPSTR)pObjName;
1840 }
1841
1842 /******************************************************************************
1843 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
1844 */
1845 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
1846 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
1847 LPWSTR InheritedObjectTypeName, LPWSTR Name )
1848 {
1849 DWORD ObjectsPresent = 0;
1850
1851 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1852 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
1853
1854 /* Fill the OBJECTS_AND_NAME structure */
1855 pObjName->ObjectType = ObjectType;
1856 if (ObjectTypeName != NULL)
1857 {
1858 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1859 }
1860
1861 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1862 if (InheritedObjectTypeName != NULL)
1863 {
1864 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1865 }
1866
1867 pObjName->ObjectsPresent = ObjectsPresent;
1868 pObjName->ptstrName = Name;
1869
1870 /* Fill the TRUSTEE structure */
1871 pTrustee->pMultipleTrustee = NULL;
1872 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1873 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1874 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1875 pTrustee->ptstrName = (LPWSTR)pObjName;
1876 }
1877
1878 /******************************************************************************
1879 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
1880 */
1881 VOID WINAPI
1882 BuildTrusteeWithObjectsAndSidA(PTRUSTEEA pTrustee,
1883 POBJECTS_AND_SID pObjSid,
1884 GUID *pObjectGuid,
1885 GUID *pInheritedObjectGuid,
1886 PSID pSid)
1887 {
1888 DWORD ObjectsPresent = 0;
1889
1890 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
1891
1892 /* Fill the OBJECTS_AND_SID structure */
1893 if (pObjectGuid != NULL)
1894 {
1895 pObjSid->ObjectTypeGuid = *pObjectGuid;
1896 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1897 }
1898 else
1899 {
1900 ZeroMemory(&pObjSid->ObjectTypeGuid,
1901 sizeof(GUID));
1902 }
1903
1904 if (pInheritedObjectGuid != NULL)
1905 {
1906 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
1907 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1908 }
1909 else
1910 {
1911 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
1912 sizeof(GUID));
1913 }
1914
1915 pObjSid->ObjectsPresent = ObjectsPresent;
1916 pObjSid->pSid = pSid;
1917
1918 /* Fill the TRUSTEE structure */
1919 pTrustee->pMultipleTrustee = NULL;
1920 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1921 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
1922 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1923 pTrustee->ptstrName = (LPSTR) pObjSid;
1924 }
1925
1926
1927 /******************************************************************************
1928 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
1929 */
1930 VOID WINAPI
1931 BuildTrusteeWithObjectsAndSidW(PTRUSTEEW pTrustee,
1932 POBJECTS_AND_SID pObjSid,
1933 GUID *pObjectGuid,
1934 GUID *pInheritedObjectGuid,
1935 PSID pSid)
1936 {
1937 DWORD ObjectsPresent = 0;
1938
1939 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
1940
1941 /* Fill the OBJECTS_AND_SID structure */
1942 if (pObjectGuid != NULL)
1943 {
1944 pObjSid->ObjectTypeGuid = *pObjectGuid;
1945 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1946 }
1947 else
1948 {
1949 ZeroMemory(&pObjSid->ObjectTypeGuid,
1950 sizeof(GUID));
1951 }
1952
1953 if (pInheritedObjectGuid != NULL)
1954 {
1955 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
1956 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1957 }
1958 else
1959 {
1960 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
1961 sizeof(GUID));
1962 }
1963
1964 pObjSid->ObjectsPresent = ObjectsPresent;
1965 pObjSid->pSid = pSid;
1966
1967 /* Fill the TRUSTEE structure */
1968 pTrustee->pMultipleTrustee = NULL;
1969 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1970 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
1971 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1972 pTrustee->ptstrName = (LPWSTR) pObjSid;
1973 }
1974
1975 /******************************************************************************
1976 * BuildTrusteeWithSidA [ADVAPI32.@]
1977 */
1978 VOID WINAPI
1979 BuildTrusteeWithSidA(PTRUSTEE_A pTrustee,
1980 PSID pSid)
1981 {
1982 TRACE("%p %p\n", pTrustee, pSid);
1983
1984 pTrustee->pMultipleTrustee = NULL;
1985 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1986 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
1987 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1988 pTrustee->ptstrName = (LPSTR) pSid;
1989 }
1990
1991
1992 /******************************************************************************
1993 * BuildTrusteeWithSidW [ADVAPI32.@]
1994 */
1995 VOID WINAPI
1996 BuildTrusteeWithSidW(PTRUSTEE_W pTrustee,
1997 PSID pSid)
1998 {
1999 TRACE("%p %p\n", pTrustee, pSid);
2000
2001 pTrustee->pMultipleTrustee = NULL;
2002 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2003 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
2004 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2005 pTrustee->ptstrName = (LPWSTR) pSid;
2006 }
2007
2008 /******************************************************************************
2009 * BuildTrusteeWithNameA [ADVAPI32.@]
2010 */
2011 VOID WINAPI
2012 BuildTrusteeWithNameA(PTRUSTEE_A pTrustee,
2013 LPSTR name)
2014 {
2015 TRACE("%p %s\n", pTrustee, name);
2016
2017 pTrustee->pMultipleTrustee = NULL;
2018 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2019 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
2020 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2021 pTrustee->ptstrName = name;
2022 }
2023
2024 /******************************************************************************
2025 * BuildTrusteeWithNameW [ADVAPI32.@]
2026 */
2027 VOID WINAPI
2028 BuildTrusteeWithNameW(PTRUSTEE_W pTrustee,
2029 LPWSTR name)
2030 {
2031 TRACE("%p %s\n", pTrustee, name);
2032
2033 pTrustee->pMultipleTrustee = NULL;
2034 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2035 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
2036 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
2037 pTrustee->ptstrName = name;
2038 }
2039
2040 /******************************************************************************
2041 * GetTrusteeFormA [ADVAPI32.@]
2042 */
2043 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
2044 {
2045 TRACE("(%p)\n", pTrustee);
2046
2047 if (!pTrustee)
2048 return TRUSTEE_BAD_FORM;
2049
2050 return pTrustee->TrusteeForm;
2051 }
2052
2053 /******************************************************************************
2054 * GetTrusteeFormW [ADVAPI32.@]
2055 */
2056 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
2057 {
2058 TRACE("(%p)\n", pTrustee);
2059
2060 if (!pTrustee)
2061 return TRUSTEE_BAD_FORM;
2062
2063 return pTrustee->TrusteeForm;
2064 }
2065
2066 /******************************************************************************
2067 * GetTrusteeNameA [ADVAPI32.@]
2068 */
2069 LPSTR WINAPI
2070 GetTrusteeNameA(PTRUSTEE_A pTrustee)
2071 {
2072 return pTrustee->ptstrName;
2073 }
2074
2075
2076 /******************************************************************************
2077 * GetTrusteeNameW [ADVAPI32.@]
2078 */
2079 LPWSTR WINAPI
2080 GetTrusteeNameW(PTRUSTEE_W pTrustee)
2081 {
2082 return pTrustee->ptstrName;
2083 }
2084
2085 /******************************************************************************
2086 * GetTrusteeTypeA [ADVAPI32.@]
2087 */
2088 TRUSTEE_TYPE WINAPI
2089 GetTrusteeTypeA(PTRUSTEE_A pTrustee)
2090 {
2091 return pTrustee->TrusteeType;
2092 }
2093
2094 /******************************************************************************
2095 * GetTrusteeTypeW [ADVAPI32.@]
2096 */
2097 TRUSTEE_TYPE WINAPI
2098 GetTrusteeTypeW(PTRUSTEE_W pTrustee)
2099 {
2100 return pTrustee->TrusteeType;
2101 }
2102
2103 /*
2104 * @implemented
2105 */
2106 BOOL
2107 WINAPI
2108 SetAclInformation(PACL pAcl,
2109 LPVOID pAclInformation,
2110 DWORD nAclInformationLength,
2111 ACL_INFORMATION_CLASS dwAclInformationClass)
2112 {
2113 NTSTATUS Status;
2114
2115 Status = RtlSetInformationAcl(pAcl,
2116 pAclInformation,
2117 nAclInformationLength,
2118 dwAclInformationClass);
2119 if (!NT_SUCCESS(Status))
2120 {
2121 SetLastError(RtlNtStatusToDosError(Status));
2122 return FALSE;
2123 }
2124
2125 return TRUE;
2126 }
2127
2128 /**********************************************************************
2129 * SetNamedSecurityInfoA EXPORTED
2130 *
2131 * @implemented
2132 */
2133 DWORD
2134 WINAPI
2135 SetNamedSecurityInfoA(LPSTR pObjectName,
2136 SE_OBJECT_TYPE ObjectType,
2137 SECURITY_INFORMATION SecurityInfo,
2138 PSID psidOwner,
2139 PSID psidGroup,
2140 PACL pDacl,
2141 PACL pSacl)
2142 {
2143 UNICODE_STRING ObjectName;
2144 DWORD Ret;
2145
2146 if (!RtlCreateUnicodeStringFromAsciiz(&ObjectName, pObjectName))
2147 {
2148 return ERROR_NOT_ENOUGH_MEMORY;
2149 }
2150
2151 Ret = SetNamedSecurityInfoW(ObjectName.Buffer,
2152 ObjectType,
2153 SecurityInfo,
2154 psidOwner,
2155 psidGroup,
2156 pDacl,
2157 pSacl);
2158
2159 RtlFreeUnicodeString(&ObjectName);
2160
2161 return Ret;
2162 }
2163
2164 /*
2165 * @implemented
2166 */
2167 BOOL
2168 WINAPI
2169 AreAllAccessesGranted(DWORD GrantedAccess,
2170 DWORD DesiredAccess)
2171 {
2172 return (BOOL)RtlAreAllAccessesGranted(GrantedAccess,
2173 DesiredAccess);
2174 }
2175
2176 /*
2177 * @implemented
2178 */
2179 BOOL
2180 WINAPI
2181 AreAnyAccessesGranted(DWORD GrantedAccess,
2182 DWORD DesiredAccess)
2183 {
2184 return (BOOL)RtlAreAnyAccessesGranted(GrantedAccess,
2185 DesiredAccess);
2186 }
2187
2188 /******************************************************************************
2189 * ParseAclStringFlags
2190 */
2191 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
2192 {
2193 DWORD flags = 0;
2194 LPCWSTR szAcl = *StringAcl;
2195
2196 while (*szAcl != '(')
2197 {
2198 if (*szAcl == 'P')
2199 {
2200 flags |= SE_DACL_PROTECTED;
2201 }
2202 else if (*szAcl == 'A')
2203 {
2204 szAcl++;
2205 if (*szAcl == 'R')
2206 flags |= SE_DACL_AUTO_INHERIT_REQ;
2207 else if (*szAcl == 'I')
2208 flags |= SE_DACL_AUTO_INHERITED;
2209 }
2210 szAcl++;
2211 }
2212
2213 *StringAcl = szAcl;
2214 return flags;
2215 }
2216
2217 /******************************************************************************
2218 * ParseAceStringType
2219 */
2220 static const ACEFLAG AceType[] =
2221 {
2222 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE },
2223 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE },
2224 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE },
2225 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE },
2226 /*
2227 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE },
2228 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE },
2229 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE },
2230 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE },
2231 */
2232 { NULL, 0 },
2233 };
2234
2235 static BYTE ParseAceStringType(LPCWSTR* StringAcl)
2236 {
2237 UINT len = 0;
2238 LPCWSTR szAcl = *StringAcl;
2239 const ACEFLAG *lpaf = AceType;
2240
2241 while (*szAcl == ' ')
2242 szAcl++;
2243
2244 while (lpaf->wstr &&
2245 (len = strlenW(lpaf->wstr)) &&
2246 strncmpW(lpaf->wstr, szAcl, len))
2247 lpaf++;
2248
2249 if (!lpaf->wstr)
2250 return 0;
2251
2252 *StringAcl = szAcl + len;
2253 return lpaf->value;
2254 }
2255
2256
2257 /******************************************************************************
2258 * ParseAceStringFlags
2259 */
2260 static const ACEFLAG AceFlags[] =
2261 {
2262 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE },
2263 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG },
2264 { SDDL_INHERITED, INHERITED_ACE },
2265 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE },
2266 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE },
2267 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE },
2268 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG },
2269 { NULL, 0 },
2270 };
2271
2272 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl)
2273 {
2274 UINT len = 0;
2275 BYTE flags = 0;
2276 LPCWSTR szAcl = *StringAcl;
2277
2278 while (*szAcl == ' ')
2279 szAcl++;
2280
2281 while (*szAcl != ';')
2282 {
2283 const ACEFLAG *lpaf = AceFlags;
2284
2285 while (lpaf->wstr &&
2286 (len = strlenW(lpaf->wstr)) &&
2287 strncmpW(lpaf->wstr, szAcl, len))
2288 lpaf++;
2289
2290 if (!lpaf->wstr)
2291 return 0;
2292
2293 flags |= lpaf->value;
2294 szAcl += len;
2295 }
2296
2297 *StringAcl = szAcl;
2298 return flags;
2299 }
2300
2301
2302 /******************************************************************************
2303 * ParseAceStringRights
2304 */
2305 static const ACEFLAG AceRights[] =
2306 {
2307 { SDDL_GENERIC_ALL, GENERIC_ALL },
2308 { SDDL_GENERIC_READ, GENERIC_READ },
2309 { SDDL_GENERIC_WRITE, GENERIC_WRITE },
2310 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
2311
2312 { SDDL_READ_CONTROL, READ_CONTROL },
2313 { SDDL_STANDARD_DELETE, DELETE },
2314 { SDDL_WRITE_DAC, WRITE_DAC },
2315 { SDDL_WRITE_OWNER, WRITE_OWNER },
2316
2317 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
2318 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
2319 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
2320 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
2321 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
2322 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
2323 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
2324 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
2325 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
2326
2327 { SDDL_FILE_ALL, FILE_ALL_ACCESS },
2328 { SDDL_FILE_READ, FILE_GENERIC_READ },
2329 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
2330 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
2331
2332 { SDDL_KEY_ALL, KEY_ALL_ACCESS },
2333 { SDDL_KEY_READ, KEY_READ },
2334 { SDDL_KEY_WRITE, KEY_WRITE },
2335 { SDDL_KEY_EXECUTE, KEY_EXECUTE },
2336 { NULL, 0 },
2337 };
2338
2339 static DWORD ParseAceStringRights(LPCWSTR* StringAcl)
2340 {
2341 UINT len = 0;
2342 DWORD rights = 0;
2343 LPCWSTR szAcl = *StringAcl;
2344
2345 while (*szAcl == ' ')
2346 szAcl++;
2347
2348 if ((*szAcl == '0') && (*(szAcl + 1) == 'x'))
2349 {
2350 LPCWSTR p = szAcl;
2351
2352 while (*p && *p != ';')
2353 p++;
2354
2355 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ )
2356 {
2357 rights = strtoulW(szAcl, NULL, 16);
2358 szAcl = p;
2359 }
2360 else
2361 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl));
2362 }
2363 else
2364 {
2365 while (*szAcl != ';')
2366 {
2367 const ACEFLAG *lpaf = AceRights;
2368
2369 while (lpaf->wstr &&
2370 (len = strlenW(lpaf->wstr)) &&
2371 strncmpW(lpaf->wstr, szAcl, len))
2372 {
2373 lpaf++;
2374 }
2375
2376 if (!lpaf->wstr)
2377 return 0;
2378
2379 rights |= lpaf->value;
2380 szAcl += len;
2381 }
2382 }
2383
2384 *StringAcl = szAcl;
2385 return rights;
2386 }
2387
2388
2389 /******************************************************************************
2390 * ParseStringAclToAcl
2391 *
2392 * dacl_flags(string_ace1)(string_ace2)... (string_acen)
2393 */
2394 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags,
2395 PACL pAcl, LPDWORD cBytes)
2396 {
2397 DWORD val;
2398 DWORD sidlen;
2399 DWORD length = sizeof(ACL);
2400 DWORD acesize = 0;
2401 DWORD acecount = 0;
2402 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */
2403 DWORD error = ERROR_INVALID_ACL;
2404
2405 TRACE("%s\n", debugstr_w(StringAcl));
2406
2407 if (!StringAcl)
2408 return FALSE;
2409
2410 if (pAcl) /* pAce is only useful if we're setting values */
2411 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1);
2412
2413 /* Parse ACL flags */
2414 *lpdwFlags = ParseAclStringFlags(&StringAcl);
2415
2416 /* Parse ACE */
2417 while (*StringAcl == '(')
2418 {
2419 StringAcl++;
2420
2421 /* Parse ACE type */
2422 val = ParseAceStringType(&StringAcl);
2423 if (pAce)
2424 pAce->Header.AceType = (BYTE) val;
2425 if (*StringAcl != ';')
2426 {
2427 error = RPC_S_INVALID_STRING_UUID;
2428 goto lerr;
2429 }
2430 StringAcl++;
2431
2432 /* Parse ACE flags */
2433 val = ParseAceStringFlags(&StringAcl);
2434 if (pAce)
2435 pAce->Header.AceFlags = (BYTE) val;
2436 if (*StringAcl != ';')
2437 goto lerr;
2438 StringAcl++;
2439
2440 /* Parse ACE rights */
2441 val = ParseAceStringRights(&StringAcl);
2442 if (pAce)
2443 pAce->Mask = val;
2444 if (*StringAcl != ';')
2445 goto lerr;
2446 StringAcl++;
2447
2448 /* Parse ACE object guid */
2449 while (*StringAcl == ' ')
2450 StringAcl++;
2451 if (*StringAcl != ';')
2452 {
2453 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
2454 goto lerr;
2455 }
2456 StringAcl++;
2457
2458 /* Parse ACE inherit object guid */
2459 while (*StringAcl == ' ')
2460 StringAcl++;
2461 if (*StringAcl != ';')
2462 {
2463 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
2464 goto lerr;
2465 }
2466 StringAcl++;
2467
2468 /* Parse ACE account sid */
2469 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen))
2470 {
2471 while (*StringAcl && *StringAcl != ')')
2472 StringAcl++;
2473 }
2474
2475 if (*StringAcl != ')')
2476 goto lerr;
2477 StringAcl++;
2478
2479 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen;
2480 length += acesize;
2481 if (pAce)
2482 {
2483 pAce->Header.AceSize = acesize;
2484 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize);
2485 }
2486 acecount++;
2487 }
2488
2489 *cBytes = length;
2490
2491 if (length > 0xffff)
2492 {
2493 ERR("ACL too large\n");
2494 goto lerr;
2495 }
2496
2497 if (pAcl)
2498 {
2499 pAcl->AclRevision = ACL_REVISION;
2500 pAcl->Sbz1 = 0;
2501 pAcl->AclSize = length;
2502 pAcl->AceCount = acecount++;
2503 pAcl->Sbz2 = 0;
2504 }
2505 return TRUE;
2506
2507 lerr:
2508 SetLastError(error);
2509 WARN("Invalid ACE string format\n");
2510 return FALSE;
2511 }
2512
2513
2514 /******************************************************************************
2515 * ParseStringSecurityDescriptorToSecurityDescriptor
2516 */
2517 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor(
2518 LPCWSTR StringSecurityDescriptor,
2519 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor,
2520 LPDWORD cBytes)
2521 {
2522 BOOL bret = FALSE;
2523 WCHAR toktype;
2524 WCHAR tok[MAX_PATH];
2525 LPCWSTR lptoken;
2526 LPBYTE lpNext = NULL;
2527 DWORD len;
2528
2529 *cBytes = sizeof(SECURITY_DESCRIPTOR);
2530
2531 if (SecurityDescriptor)
2532 lpNext = (LPBYTE)(SecurityDescriptor + 1);
2533
2534 while (*StringSecurityDescriptor == ' ')
2535 StringSecurityDescriptor++;
2536
2537 while (*StringSecurityDescriptor)
2538 {
2539 toktype = *StringSecurityDescriptor;
2540
2541 /* Expect char identifier followed by ':' */
2542 StringSecurityDescriptor++;
2543 if (*StringSecurityDescriptor != ':')
2544 {
2545 SetLastError(ERROR_INVALID_PARAMETER);
2546 goto lend;
2547 }
2548 StringSecurityDescriptor++;
2549
2550 /* Extract token */
2551 lptoken = StringSecurityDescriptor;
2552 while (*lptoken && *lptoken != ':')
2553 lptoken++;
2554
2555 if (*lptoken)
2556 lptoken--;
2557
2558 len = lptoken - StringSecurityDescriptor;
2559 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) );
2560 tok[len] = 0;
2561
2562 switch (toktype)
2563 {
2564 case 'O':
2565 {
2566 DWORD bytes;
2567
2568 if (!ParseStringSidToSid(tok, lpNext, &bytes))
2569 goto lend;
2570
2571 if (SecurityDescriptor)
2572 {
2573 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor;
2574 lpNext += bytes; /* Advance to next token */
2575 }
2576
2577 *cBytes += bytes;
2578
2579 break;
2580 }
2581
2582 case 'G':
2583 {
2584 DWORD bytes;
2585
2586 if (!ParseStringSidToSid(tok, lpNext, &bytes))
2587 goto lend;
2588
2589 if (SecurityDescriptor)
2590 {
2591 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor;
2592 lpNext += bytes; /* Advance to next token */
2593 }
2594
2595 *cBytes += bytes;
2596
2597 break;
2598 }
2599
2600 case 'D':
2601 {
2602 DWORD flags;
2603 DWORD bytes;
2604
2605 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
2606 goto lend;
2607
2608 if (SecurityDescriptor)
2609 {
2610 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags;
2611 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor;
2612 lpNext += bytes; /* Advance to next token */
2613 }
2614
2615 *cBytes += bytes;
2616
2617 break;
2618 }
2619
2620 case 'S':
2621 {
2622 DWORD flags;
2623 DWORD bytes;
2624
2625 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes))
2626 goto lend;
2627
2628 if (SecurityDescriptor)
2629 {
2630 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags;
2631 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor;
2632 lpNext += bytes; /* Advance to next token */
2633 }
2634
2635 *cBytes += bytes;
2636
2637 break;
2638 }
2639
2640 default:
2641 FIXME("Unknown token\n");
2642 SetLastError(ERROR_INVALID_PARAMETER);
2643 goto lend;
2644 }
2645
2646 StringSecurityDescriptor = lptoken;
2647 }
2648
2649 bret = TRUE;
2650
2651 lend:
2652 return bret;
2653 }
2654
2655 /* Winehq cvs 20050916 */
2656 /******************************************************************************
2657 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
2658 * @implemented
2659 */
2660 BOOL
2661 WINAPI
2662 ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor,
2663 DWORD StringSDRevision,
2664 PSECURITY_DESCRIPTOR* SecurityDescriptor,
2665 PULONG SecurityDescriptorSize)
2666 {
2667 UINT len;
2668 BOOL ret = FALSE;
2669 LPWSTR StringSecurityDescriptorW;
2670
2671 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
2672 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2673
2674 if (StringSecurityDescriptorW)
2675 {
2676 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
2677
2678 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
2679 StringSDRevision, SecurityDescriptor,
2680 SecurityDescriptorSize);
2681 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
2682 }
2683
2684 return ret;
2685 }
2686
2687 /******************************************************************************
2688 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
2689 * @implemented
2690 */
2691 BOOL WINAPI
2692 ConvertStringSecurityDescriptorToSecurityDescriptorW(LPCWSTR StringSecurityDescriptor,
2693 DWORD StringSDRevision,
2694 PSECURITY_DESCRIPTOR* SecurityDescriptor,
2695 PULONG SecurityDescriptorSize)
2696 {
2697 DWORD cBytes;
2698 SECURITY_DESCRIPTOR* psd;
2699 BOOL bret = FALSE;
2700
2701 TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
2702
2703 if (GetVersion() & 0x80000000)
2704 {
2705 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2706 goto lend;
2707 }
2708 else if (!StringSecurityDescriptor || !SecurityDescriptor)
2709 {
2710 SetLastError(ERROR_INVALID_PARAMETER);
2711 goto lend;
2712 }
2713 else if (StringSDRevision != SID_REVISION)
2714 {
2715 SetLastError(ERROR_UNKNOWN_REVISION);
2716 goto lend;
2717 }
2718
2719 /* Compute security descriptor length */
2720 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
2721 NULL, &cBytes))
2722 goto lend;
2723
2724 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes);
2725 if (!psd) goto lend;
2726
2727 psd->Revision = SID_REVISION;
2728 psd->Control |= SE_SELF_RELATIVE;
2729
2730 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor,
2731 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes))
2732 {
2733 LocalFree(psd);
2734 goto lend;
2735 }
2736
2737 if (SecurityDescriptorSize)
2738 *SecurityDescriptorSize = cBytes;
2739
2740 bret = TRUE;
2741
2742 lend:
2743 TRACE(" ret=%d\n", bret);
2744 return bret;
2745 }
2746
2747 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
2748 {
2749 if (cch == -1)
2750 cch = strlenW(string);
2751
2752 if (plen)
2753 *plen += cch;
2754
2755 if (pwptr)
2756 {
2757 memcpy(*pwptr, string, sizeof(WCHAR)*cch);
2758 *pwptr += cch;
2759 }
2760 }
2761
2762 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
2763 {
2764 DWORD i;
2765 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
2766 WCHAR subauthfmt[] = { '-','%','u',0 };
2767 WCHAR buf[26];
2768 SID *pisid = psid;
2769
2770 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
2771 {
2772 SetLastError(ERROR_INVALID_SID);
2773 return FALSE;
2774 }
2775
2776 if (pisid->IdentifierAuthority.Value[0] ||
2777 pisid->IdentifierAuthority.Value[1])
2778 {
2779 FIXME("not matching MS' bugs\n");
2780 SetLastError(ERROR_INVALID_SID);
2781 return FALSE;
2782 }
2783
2784 sprintfW( buf, fmt, pisid->Revision,
2785 MAKELONG(
2786 MAKEWORD( pisid->IdentifierAuthority.Value[5],
2787 pisid->IdentifierAuthority.Value[4] ),
2788 MAKEWORD( pisid->IdentifierAuthority.Value[3],
2789 pisid->IdentifierAuthority.Value[2] )
2790 ) );
2791 DumpString(buf, -1, pwptr, plen);
2792
2793 for( i=0; i<pisid->SubAuthorityCount; i++ )
2794 {
2795 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
2796 DumpString(buf, -1, pwptr, plen);
2797 }
2798 return TRUE;
2799 }
2800
2801 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
2802 {
2803 size_t i;
2804 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
2805 {
2806 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
2807 {
2808 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
2809 return TRUE;
2810 }
2811 }
2812
2813 return DumpSidNumeric(psid, pwptr, plen);
2814 }
2815
2816 static const LPCWSTR AceRightBitNames[32] = {
2817 SDDL_CREATE_CHILD, /* 0 */
2818 SDDL_DELETE_CHILD,
2819 SDDL_LIST_CHILDREN,
2820 SDDL_SELF_WRITE,
2821 SDDL_READ_PROPERTY, /* 4 */
2822 SDDL_WRITE_PROPERTY,
2823 SDDL_DELETE_TREE,
2824 SDDL_LIST_OBJECT,
2825 SDDL_CONTROL_ACCESS, /* 8 */
2826 NULL,
2827 NULL,
2828 NULL,
2829 NULL, /* 12 */
2830 NULL,
2831 NULL,
2832 NULL,
2833 SDDL_STANDARD_DELETE, /* 16 */
2834 SDDL_READ_CONTROL,
2835 SDDL_WRITE_DAC,
2836 SDDL_WRITE_OWNER,
2837 NULL, /* 20 */
2838 NULL,
2839 NULL,
2840 NULL,
2841 NULL, /* 24 */
2842 NULL,
2843 NULL,
2844 NULL,
2845 SDDL_GENERIC_ALL, /* 28 */
2846 SDDL_GENERIC_EXECUTE,
2847 SDDL_GENERIC_WRITE,
2848 SDDL_GENERIC_READ
2849 };
2850
2851 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
2852 {
2853 static const WCHAR fmtW[] = {'0','x','%','x',0};
2854 WCHAR buf[15];
2855 size_t i;
2856
2857 if (mask == 0)
2858 return;
2859
2860 /* first check if the right have name */
2861 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
2862 {
2863 if (AceRights[i].wstr == NULL)
2864 break;
2865 if (mask == AceRights[i].value)
2866 {
2867 DumpString(AceRights[i].wstr, -1, pwptr, plen);
2868 return;
2869 }
2870 }
2871
2872 /* then check if it can be built from bit names */
2873 for (i = 0; i < 32; i++)
2874 {
2875 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
2876 {
2877 /* can't be built from bit names */
2878 sprintfW(buf, fmtW, mask);
2879 DumpString(buf, -1, pwptr, plen);
2880 return;
2881 }
2882 }
2883
2884 /* build from bit names */
2885 for (i = 0; i < 32; i++)
2886 if (mask & (1 << i))
2887 DumpString(AceRightBitNames[i], -1, pwptr, plen);
2888 }
2889
2890 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
2891 {
2892 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
2893 static const WCHAR openbr = '(';
2894 static const WCHAR closebr = ')';
2895 static const WCHAR semicolon = ';';
2896
2897 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
2898 {
2899 SetLastError(ERROR_INVALID_ACL);
2900 return FALSE;
2901 }
2902
2903 piace = pace;
2904 DumpString(&openbr, 1, pwptr, plen);
2905 switch (piace->Header.AceType)
2906 {
2907 case ACCESS_ALLOWED_ACE_TYPE:
2908 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
2909 break;
2910 case ACCESS_DENIED_ACE_TYPE:
2911 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
2912 break;
2913 case SYSTEM_AUDIT_ACE_TYPE:
2914 DumpString(SDDL_AUDIT, -1, pwptr, plen);
2915 break;
2916 case SYSTEM_ALARM_ACE_TYPE:
2917 DumpString(SDDL_ALARM, -1, pwptr, plen);
2918 break;
2919 }
2920 DumpString(&semicolon, 1, pwptr, plen);
2921
2922 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
2923 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
2924 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
2925 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
2926 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
2927 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
2928 if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
2929 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
2930 if (piace->Header.AceFlags & INHERITED_ACE)
2931 DumpString(SDDL_INHERITED, -1, pwptr, plen);
2932 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
2933 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
2934 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
2935 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
2936 DumpString(&semicolon, 1, pwptr, plen);
2937 DumpRights(piace->Mask, pwptr, plen);
2938 DumpString(&semicolon, 1, pwptr, plen);
2939 /* objects not supported */
2940 DumpString(&semicolon, 1, pwptr, plen);
2941 /* objects not supported */
2942 DumpString(&semicolon, 1, pwptr, plen);
2943 if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
2944 return FALSE;
2945 DumpString(&closebr, 1, pwptr, plen);
2946 return TRUE;
2947 }
2948
2949 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
2950 {
2951 WORD count;
2952 int i;
2953
2954 if (protected)
2955 DumpString(SDDL_PROTECTED, -1, pwptr, plen);
2956 if (autoInheritReq)
2957 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
2958 if (autoInherited)
2959 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
2960
2961 if (pacl == NULL)
2962 return TRUE;
2963
2964 if (!IsValidAcl(pacl))
2965 return FALSE;
2966
2967 count = pacl->AceCount;
2968 for (i = 0; i < count; i++)
2969 {
2970 LPVOID ace;
2971 if (!GetAce(pacl, i, &ace))
2972 return FALSE;
2973 if (!DumpAce(ace, pwptr, plen))
2974 return FALSE;
2975 }
2976
2977 return TRUE;
2978 }
2979
2980 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
2981 {
2982 static const WCHAR prefix[] = {'O',':',0};
2983 BOOL bDefaulted;
2984 PSID psid;
2985
2986 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
2987 return FALSE;
2988
2989 if (psid == NULL)
2990 return TRUE;
2991
2992 DumpString(prefix, -1, pwptr, plen);
2993 if (!DumpSid(psid, pwptr, plen))
2994 return FALSE;
2995 return TRUE;
2996 }
2997
2998 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
2999 {
3000 static const WCHAR prefix[] = {'G',':',0};
3001 BOOL bDefaulted;
3002 PSID psid;
3003
3004 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
3005 return FALSE;
3006
3007 if (psid == NULL)
3008 return TRUE;
3009
3010 DumpString(prefix, -1, pwptr, plen);
3011 if (!DumpSid(psid, pwptr, plen))
3012 return FALSE;
3013 return TRUE;
3014 }
3015
3016 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3017 {
3018 static const WCHAR dacl[] = {'D',':',0};
3019 SECURITY_DESCRIPTOR_CONTROL control;
3020 BOOL present, defaulted;
3021 DWORD revision;
3022 PACL pacl;
3023
3024 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
3025 return FALSE;
3026
3027 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
3028 return FALSE;
3029
3030 if (!present)
3031 return TRUE;
3032
3033 DumpString(dacl, 2, pwptr, plen);
3034 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
3035 return FALSE;
3036 return TRUE;
3037 }
3038
3039 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
3040 {
3041 static const WCHAR sacl[] = {'S',':',0};
3042 SECURITY_DESCRIPTOR_CONTROL control;
3043 BOOL present, defaulted;
3044 DWORD revision;
3045 PACL pacl;
3046
3047 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
3048 return FALSE;
3049
3050 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
3051 return FALSE;
3052
3053 if (!present)
3054 return TRUE;
3055
3056 DumpString(sacl, 2, pwptr, plen);
3057 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
3058 return FALSE;
3059 return TRUE;
3060 }
3061
3062 /******************************************************************************
3063 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
3064 */
3065 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen)
3066 {
3067 ULONG len;
3068 WCHAR *wptr, *wstr;
3069
3070 if (SDRevision != SDDL_REVISION_1)
3071 {
3072 ERR("Program requested unknown SDDL revision %d\n", SDRevision);
3073 SetLastError(ERROR_UNKNOWN_REVISION);
3074 return FALSE;
3075 }
3076
3077 len = 0;
3078 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
3079 if (!DumpOwner(SecurityDescriptor, NULL, &len))
3080 return FALSE;
3081 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
3082 if (!DumpGroup(SecurityDescriptor, NULL, &len))
3083 return FALSE;
3084 if (RequestedInformation & DACL_SECURITY_INFORMATION)
3085 if (!DumpDacl(SecurityDescriptor, NULL, &len))
3086 return FALSE;
3087 if (RequestedInformation & SACL_SECURITY_INFORMATION)
3088 if (!DumpSacl(SecurityDescriptor, NULL, &len))
3089 return FALSE;
3090
3091 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
3092 #ifdef __REACTOS__
3093 if (wstr == NULL)
3094 return FALSE;
3095 #endif
3096
3097 if (RequestedInformation & OWNER_SECURITY_INFORMATION)
3098 if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) {
3099 LocalFree (wstr);
3100 return FALSE;
3101 }
3102 if (RequestedInformation & GROUP_SECURITY_INFORMATION)
3103 if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) {
3104 LocalFree (wstr);
3105 return FALSE;
3106 }
3107 if (RequestedInformation & DACL_SECURITY_INFORMATION)
3108 if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) {
3109 LocalFree (wstr);
3110 return FALSE;
3111 }
3112 if (RequestedInformation & SACL_SECURITY_INFORMATION)
3113 if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) {
3114 LocalFree (wstr);
3115 return FALSE;
3116 }
3117 *wptr = 0;
3118
3119 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
3120 *OutputString = wstr;
3121 if (OutputLen)
3122 *OutputLen = strlenW(*OutputString)+1;
3123 return TRUE;
3124 }
3125
3126 /******************************************************************************
3127 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
3128 */
3129 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
3130 {
3131 LPWSTR wstr;
3132 ULONG len;
3133 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
3134 {
3135 int lenA;
3136
3137 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
3138 *OutputString = heap_alloc(lenA);
3139 #ifdef __REACTOS__
3140 if (*OutputString == NULL)
3141 {
3142 LocalFree(wstr);
3143 *OutputLen = 0;
3144 return FALSE;
3145 }
3146 #endif
3147 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
3148 LocalFree(wstr);
3149
3150 if (OutputLen != NULL)
3151 *OutputLen = lenA;
3152 return TRUE;
3153 }
3154 else
3155 {
3156 *OutputString = NULL;
3157 if (OutputLen)
3158 *OutputLen = 0;
3159 return FALSE;
3160 }
3161 }
3162
3163 /******************************************************************************
3164 * ConvertStringSidToSidW [ADVAPI32.@]
3165 */
3166 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid)
3167 {
3168 BOOL bret = FALSE;
3169 DWORD cBytes;
3170
3171 TRACE("%s, %p\n", debugstr_w(StringSid), Sid);
3172 if (GetVersion() & 0x80000000)
3173 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3174 else if (!StringSid || !Sid)
3175 SetLastError(ERROR_INVALID_PARAMETER);
3176 else if (ParseStringSidToSid(StringSid, NULL, &cBytes))
3177 {
3178 PSID pSid = *Sid = LocalAlloc(0, cBytes);
3179
3180 bret = ParseStringSidToSid(StringSid, pSid, &cBytes);
3181 if (!bret)
3182 LocalFree(*Sid);
3183 }
3184 return bret;
3185 }
3186
3187 /******************************************************************************
3188 * ConvertStringSidToSidA [ADVAPI32.@]
3189 */
3190 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
3191 {
3192 BOOL bret = FALSE;
3193
3194 TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
3195 if (GetVersion() & 0x80000000)
3196 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3197 else if (!StringSid || !Sid)
3198 SetLastError(ERROR_INVALID_PARAMETER);
3199 else
3200 {
3201 WCHAR *wStringSid = SERV_dup(StringSid);
3202 bret = ConvertStringSidToSidW(wStringSid, Sid);
3203 heap_free(wStringSid);
3204 }
3205 return bret;
3206 }
3207
3208 /*
3209 * @implemented
3210 */
3211 BOOL
3212 WINAPI
3213 ConvertSidToStringSidW(PSID Sid,
3214 LPWSTR *StringSid)
3215 {
3216 NTSTATUS Status;
3217 UNICODE_STRING UnicodeString;
3218 WCHAR FixedBuffer[64];
3219
3220 if (!RtlValidSid(Sid))
3221 {
3222 SetLastError(ERROR_INVALID_SID);
3223 return FALSE;
3224 }
3225
3226 UnicodeString.Length = 0;
3227 UnicodeString.MaximumLength = sizeof(FixedBuffer);
3228 UnicodeString.Buffer = FixedBuffer;
3229 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
3230 if (STATUS_BUFFER_TOO_SMALL == Status)
3231 {
3232 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
3233 }
3234
3235 if (!NT_SUCCESS(Status))
3236 {
3237 SetLastError(RtlNtStatusToDosError(Status));
3238 return FALSE;
3239 }
3240
3241 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
3242 if (NULL == *StringSid)
3243 {
3244 if (UnicodeString.Buffer != FixedBuffer)
3245 {
3246 RtlFreeUnicodeString(&UnicodeString);
3247 }
3248 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3249 return FALSE;
3250 }
3251
3252 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
3253 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
3254 if (UnicodeString.Buffer != FixedBuffer)
3255 {
3256 RtlFreeUnicodeString(&UnicodeString);
3257 }
3258
3259 return TRUE;
3260 }
3261
3262 /*
3263 * @implemented
3264 */
3265 BOOL
3266 WINAPI
3267 ConvertSidToStringSidA(PSID Sid,
3268 LPSTR *StringSid)
3269 {
3270 LPWSTR StringSidW;
3271 int Len;
3272
3273 if (!ConvertSidToStringSidW(Sid, &StringSidW))
3274 {
3275 return FALSE;
3276 }
3277
3278 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
3279 if (Len <= 0)
3280 {
3281 LocalFree(StringSidW);
3282 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3283 return FALSE;
3284 }
3285
3286 *StringSid = LocalAlloc(LMEM_FIXED, Len);
3287 if (NULL == *StringSid)
3288 {
3289 LocalFree(StringSidW);
3290 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3291 return FALSE;
3292 }
3293
3294 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
3295 {
3296 LocalFree(StringSid);
3297 LocalFree(StringSidW);
3298 return FALSE;
3299 }
3300
3301 LocalFree(StringSidW);
3302
3303 return TRUE;
3304 }
3305
3306 /*
3307 * @unimplemented
3308 */
3309 BOOL WINAPI
3310 CreateProcessWithLogonW(LPCWSTR lpUsername,
3311 LPCWSTR lpDomain,
3312 LPCWSTR lpPassword,
3313 DWORD dwLogonFlags,
3314 LPCWSTR lpApplicationName,
3315 LPWSTR lpCommandLine,
3316 DWORD dwCreationFlags,
3317 LPVOID lpEnvironment,
3318 LPCWSTR lpCurrentDirectory,
3319 LPSTARTUPINFOW lpStartupInfo,
3320 LPPROCESS_INFORMATION lpProcessInformation)
3321 {
3322 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
3323 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
3324 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
3325 lpStartupInfo, lpProcessInformation);
3326
3327 return FALSE;
3328 }
3329
3330 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
3331 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
3332 PROCESS_INFORMATION *process_information )
3333 {
3334 FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
3335 logon_flags, debugstr_w(application_name), debugstr_w(command_line),
3336 creation_flags, environment, debugstr_w(current_directory),
3337 startup_info, process_information);
3338
3339 /* FIXME: check if handles should be inherited */
3340 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
3341 current_directory, startup_info, process_information );
3342 }
3343
3344 /*
3345 * @implemented
3346 */
3347 BOOL WINAPI
3348 DuplicateTokenEx(IN HANDLE ExistingTokenHandle,
3349 IN DWORD dwDesiredAccess,
3350 IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL,
3351 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
3352 IN TOKEN_TYPE TokenType,
3353 OUT PHANDLE DuplicateTokenHandle)
3354 {
3355 OBJECT_ATTRIBUTES ObjectAttributes;
3356 NTSTATUS Status;
3357 SECURITY_QUALITY_OF_SERVICE Sqos;
3358
3359 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess,
3360 ImpersonationLevel, TokenType, DuplicateTokenHandle);
3361
3362 Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
3363 Sqos.ImpersonationLevel = ImpersonationLevel;
3364 Sqos.ContextTrackingMode = 0;
3365 Sqos.EffectiveOnly = FALSE;
3366
3367 if (lpTokenAttributes != NULL)
3368 {
3369 InitializeObjectAttributes(&ObjectAttributes,
3370 NULL,
3371 lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0,
3372 NULL,
3373 lpTokenAttributes->lpSecurityDescriptor);
3374 }
3375 else
3376 {
3377 InitializeObjectAttributes(&ObjectAttributes,
3378 NULL,
3379 0,
3380 NULL,
3381 NULL);
3382 }
3383
3384 ObjectAttributes.SecurityQualityOfService = &Sqos;
3385
3386 Status = NtDuplicateToken(ExistingTokenHandle,
3387 dwDesiredAccess,
3388 &ObjectAttributes,
3389 FALSE,
3390 TokenType,
3391 DuplicateTokenHandle);
3392 if (!NT_SUCCESS(Status))
3393 {
3394 ERR("NtDuplicateToken failed: Status %08x\n", Status);
3395 SetLastError(RtlNtStatusToDosError(Status));
3396 return FALSE;
3397 }
3398
3399 TRACE("Returning token %p.\n", *DuplicateTokenHandle);
3400
3401 return TRUE;
3402 }
3403
3404 /*
3405 * @implemented
3406 */
3407 BOOL WINAPI
3408 DuplicateToken(IN HANDLE ExistingTokenHandle,
3409 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
3410 OUT PHANDLE DuplicateTokenHandle)
3411 {
3412 return DuplicateTokenEx(ExistingTokenHandle,
3413 TOKEN_IMPERSONATE | TOKEN_QUERY,
3414 NULL,
3415 ImpersonationLevel,
3416 TokenImpersonation,
3417 DuplicateTokenHandle);
3418 }
3419
3420 /******************************************************************************
3421 * ComputeStringSidSize
3422 */
3423 static DWORD ComputeStringSidSize(LPCWSTR StringSid)
3424 {
3425 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */
3426 {
3427 int ctok = 0;
3428 while (*StringSid)
3429 {
3430 if (*StringSid == '-')
3431 ctok++;
3432 StringSid++;
3433 }
3434
3435 if (ctok >= 3)
3436 return GetSidLengthRequired(ctok - 2);
3437 }
3438 else /* String constant format - Only available in winxp and above */
3439 {
3440 unsigned int i;
3441
3442 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
3443 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
3444 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
3445
3446 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
3447 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
3448 {
3449 MAX_SID local;
3450 ADVAPI_GetComputerSid(&local);
3451 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1);
3452 }
3453
3454 }
3455
3456 return GetSidLengthRequired(0);
3457 }
3458
3459 /******************************************************************************
3460 * ParseStringSidToSid
3461 */
3462 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes)
3463 {
3464 BOOL bret = FALSE;
3465 SID* pisid=pSid;
3466
3467 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes);
3468 if (!StringSid)
3469 {
3470 SetLastError(ERROR_INVALID_PARAMETER);
3471 TRACE("StringSid is NULL, returning FALSE\n");
3472 return FALSE;
3473 }
3474
3475 while (*StringSid == ' ')
3476 StringSid++;
3477
3478 if (!*StringSid)
3479 goto lend; /* ERROR_INVALID_SID */
3480
3481 *cBytes = ComputeStringSidSize(StringSid);
3482 if (!pisid) /* Simply compute the size */
3483 {
3484 TRACE("only size requested, returning TRUE with %d\n", *cBytes);
3485 return TRUE;
3486 }
3487
3488 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */
3489 {
3490 DWORD i = 0, identAuth;
3491 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD));
3492
3493 StringSid += 2; /* Advance to Revision */
3494 pisid->Revision = atoiW(StringSid);
3495
3496 if (pisid->Revision != SDDL_REVISION)
3497 {
3498 TRACE("Revision %d is unknown\n", pisid->Revision);
3499 goto lend; /* ERROR_INVALID_SID */
3500 }
3501 if (csubauth == 0)
3502 {
3503 TRACE("SubAuthorityCount is 0\n");
3504 goto lend; /* ERROR_INVALID_SID */
3505 }
3506
3507 pisid->SubAuthorityCount = csubauth;
3508
3509 /* Advance to identifier authority */
3510 while (*StringSid && *StringSid != '-')
3511 StringSid++;
3512 if (*StringSid == '-')
3513 StringSid++;
3514
3515 /* MS' implementation can't handle values greater than 2^32 - 1, so
3516 * we don't either; assume most significant bytes are always 0
3517 */
3518 pisid->IdentifierAuthority.Value[0] = 0;
3519 pisid->IdentifierAuthority.Value[1] = 0;
3520 identAuth = atoiW(StringSid);
3521 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff;
3522 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8;
3523 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16;
3524 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24;
3525
3526 /* Advance to first sub authority */
3527 while (*StringSid && *StringSid != '-')
3528 StringSid++;
3529 if (*StringSid == '-')
3530 StringSid++;
3531
3532 while (*StringSid)
3533 {
3534 pisid->SubAuthority[i++] = atoiW(StringSid);
3535
3536 while (*StringSid && *StringSid != '-')
3537 StringSid++;
3538 if (*StringSid == '-')
3539 StringSid++;
3540 }
3541
3542 if (i != pisid->SubAuthorityCount)
3543 goto lend; /* ERROR_INVALID_SID */
3544
3545 bret = TRUE;
3546 }
3547 else /* String constant format - Only available in winxp and above */
3548 {
3549 unsigned int i;
3550 pisid->Revision = SDDL_REVISION;
3551
3552 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
3553 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
3554 {
3555 DWORD j;
3556 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount;
3557 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority;
3558 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++)
3559 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j];
3560 bret = TRUE;
3561 }
3562
3563 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
3564 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2))
3565 {
3566 ADVAPI_GetComputerSid(pisid);
3567 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid;
3568 pisid->SubAuthorityCount++;
3569 bret = TRUE;
3570 }
3571
3572 if (!bret)
3573 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2));
3574 }
3575
3576 lend:
3577 if (!bret)
3578 SetLastError(ERROR_INVALID_SID);
3579
3580 TRACE("returning %s\n", bret ? "TRUE" : "FALSE");
3581 return bret;
3582 }
3583
3584 /**********************************************************************
3585 * GetNamedSecurityInfoA EXPORTED
3586 *
3587 * @implemented
3588 */
3589 DWORD
3590 WINAPI
3591 GetNamedSecurityInfoA(LPSTR pObjectName,
3592 SE_OBJECT_TYPE ObjectType,
3593 SECURITY_INFORMATION SecurityInfo,
3594 PSID *ppsidOwner,
3595 PSID *ppsidGroup,
3596 PACL *ppDacl,
3597 PACL *ppSacl,
3598 PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
3599 {
3600 DWORD len;
3601 LPWSTR wstr = NULL;
3602 DWORD r;
3603
3604 TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
3605 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
3606
3607 if( pObjectName )
3608 {
3609 len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 );
3610 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR));
3611 MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len );
3612 }
3613
3614 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
3615 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
3616
3617 HeapFree( GetProcessHeap(), 0, wstr );
3618
3619 return r;
3620 }
3621
3622 /*
3623 * @unimplemented
3624 */
3625 BOOL
3626 WINAPI
3627 GetWindowsAccountDomainSid(IN PSID pSid,
3628 OUT PSID ppDomainSid,
3629 IN OUT DWORD* cbSid)
3630 {
3631 UNIMPLEMENTED;
3632 return FALSE;
3633 }
3634
3635 /*
3636 * @unimplemented
3637 */
3638 BOOL
3639 WINAPI
3640 EqualDomainSid(IN PSID pSid1,
3641 IN PSID pSid2,
3642 OUT BOOL* pfEqual)
3643 {
3644 UNIMPLEMENTED;
3645 return FALSE;
3646 }
3647
3648 /* EOF */