advapi32/tests: Expand tests for performance keys.
[wine.git] / dlls / advapi32 / security.c
blob02787fc841cf84b9097ccd2a1f7ee9edddae8508
1 /*
2 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
3 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
4 * Copyright 2006 Robert Reif
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
23 #include <string.h>
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "winreg.h"
31 #include "winsafer.h"
32 #include "winternl.h"
33 #include "winioctl.h"
34 #include "accctrl.h"
35 #include "sddl.h"
36 #include "winsvc.h"
37 #include "aclapi.h"
38 #include "objbase.h"
39 #include "iads.h"
40 #include "advapi32_misc.h"
41 #include "lmcons.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
47 static DWORD trustee_to_sid(DWORD nDestinationSidLength, PSID pDestinationSid, PTRUSTEEW pTrustee);
49 typedef struct _MAX_SID
51 /* same fields as struct _SID */
52 BYTE Revision;
53 BYTE SubAuthorityCount;
54 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
55 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
56 } MAX_SID;
58 typedef struct _AccountSid {
59 WELL_KNOWN_SID_TYPE type;
60 LPCWSTR account;
61 LPCWSTR domain;
62 SID_NAME_USE name_use;
63 LPCWSTR alias;
64 } AccountSid;
66 static const AccountSid ACCOUNT_SIDS[] = {
67 { WinNullSid, L"NULL SID", L"", SidTypeWellKnownGroup },
68 { WinWorldSid, L"Everyone", L"", SidTypeWellKnownGroup },
69 { WinLocalSid, L"LOCAL", L"", SidTypeWellKnownGroup },
70 { WinCreatorOwnerSid, L"CREATOR OWNER", L"", SidTypeWellKnownGroup },
71 { WinCreatorGroupSid, L"CREATOR GROUP", L"", SidTypeWellKnownGroup },
72 { WinCreatorOwnerServerSid, L"CREATOR OWNER SERVER", L"", SidTypeWellKnownGroup },
73 { WinCreatorGroupServerSid, L"CREATOR GROUP SERVER", L"", SidTypeWellKnownGroup },
74 { WinNtAuthoritySid, L"NT Pseudo Domain", L"NT Pseudo Domain", SidTypeDomain },
75 { WinDialupSid, L"DIALUP", L"NT AUTHORITY", SidTypeWellKnownGroup },
76 { WinNetworkSid, L"NETWORK", L"NT AUTHORITY", SidTypeWellKnownGroup },
77 { WinBatchSid, L"BATCH", L"NT AUTHORITY", SidTypeWellKnownGroup },
78 { WinInteractiveSid, L"INTERACTIVE", L"NT AUTHORITY", SidTypeWellKnownGroup },
79 { WinServiceSid, L"SERVICE", L"NT AUTHORITY", SidTypeWellKnownGroup },
80 { WinAnonymousSid, L"ANONYMOUS LOGON", L"NT AUTHORITY", SidTypeWellKnownGroup },
81 { WinProxySid, L"PROXY", L"NT AUTHORITY", SidTypeWellKnownGroup },
82 { WinEnterpriseControllersSid, L"ENTERPRISE DOMAIN CONTROLLERS", L"NT AUTHORITY", SidTypeWellKnownGroup },
83 { WinSelfSid, L"SELF", L"NT AUTHORITY", SidTypeWellKnownGroup },
84 { WinAuthenticatedUserSid, L"Authenticated Users", L"NT AUTHORITY", SidTypeWellKnownGroup },
85 { WinRestrictedCodeSid, L"RESTRICTED", L"NT AUTHORITY", SidTypeWellKnownGroup },
86 { WinTerminalServerSid, L"TERMINAL SERVER USER", L"NT AUTHORITY", SidTypeWellKnownGroup },
87 { WinRemoteLogonIdSid, L"REMOTE INTERACTIVE LOGON", L"NT AUTHORITY", SidTypeWellKnownGroup },
88 { WinLocalSystemSid, L"SYSTEM", L"NT AUTHORITY", SidTypeWellKnownGroup },
89 { WinLocalServiceSid, L"LOCAL SERVICE", L"NT AUTHORITY", SidTypeWellKnownGroup, L"LOCALSERVICE" },
90 { WinNetworkServiceSid, L"NETWORK SERVICE", L"NT AUTHORITY", SidTypeWellKnownGroup , L"NETWORKSERVICE"},
91 { WinBuiltinDomainSid, L"BUILTIN", L"BUILTIN", SidTypeDomain },
92 { WinBuiltinAdministratorsSid, L"Administrators", L"BUILTIN", SidTypeAlias },
93 { WinBuiltinUsersSid, L"Users", L"BUILTIN", SidTypeAlias },
94 { WinBuiltinGuestsSid, L"Guests", L"BUILTIN", SidTypeAlias },
95 { WinBuiltinPowerUsersSid, L"Power Users", L"BUILTIN", SidTypeAlias },
96 { WinBuiltinAccountOperatorsSid, L"Account Operators", L"BUILTIN", SidTypeAlias },
97 { WinBuiltinSystemOperatorsSid, L"Server Operators", L"BUILTIN", SidTypeAlias },
98 { WinBuiltinPrintOperatorsSid, L"Print Operators", L"BUILTIN", SidTypeAlias },
99 { WinBuiltinBackupOperatorsSid, L"Backup Operators", L"BUILTIN", SidTypeAlias },
100 { WinBuiltinReplicatorSid, L"Replicators", L"BUILTIN", SidTypeAlias },
101 { WinBuiltinPreWindows2000CompatibleAccessSid, L"Pre-Windows 2000 Compatible Access", L"BUILTIN", SidTypeAlias },
102 { WinBuiltinRemoteDesktopUsersSid, L"Remote Desktop Users", L"BUILTIN", SidTypeAlias },
103 { WinBuiltinNetworkConfigurationOperatorsSid, L"Network Configuration Operators", L"BUILTIN", SidTypeAlias },
104 { WinNTLMAuthenticationSid, L"NTLM Authentication", L"NT AUTHORITY", SidTypeWellKnownGroup },
105 { WinDigestAuthenticationSid, L"Digest Authentication", L"NT AUTHORITY", SidTypeWellKnownGroup },
106 { WinSChannelAuthenticationSid, L"SChannel Authentication", L"NT AUTHORITY", SidTypeWellKnownGroup },
107 { WinThisOrganizationSid, L"This Organization", L"NT AUTHORITY", SidTypeWellKnownGroup },
108 { WinOtherOrganizationSid, L"Other Organization", L"NT AUTHORITY", SidTypeWellKnownGroup },
109 { WinBuiltinPerfMonitoringUsersSid, L"Performance Monitor Users", L"BUILTIN", SidTypeAlias },
110 { WinBuiltinPerfLoggingUsersSid, L"Performance Log Users", L"BUILTIN", SidTypeAlias },
111 { WinBuiltinAnyPackageSid, L"ALL APPLICATION PACKAGES", L"APPLICATION PACKAGE AUTHORITY", SidTypeWellKnownGroup },
114 const char * debugstr_sid(PSID sid)
116 int auth = 0;
117 SID * psid = sid;
119 if (psid == NULL)
120 return "(null)";
122 auth = psid->IdentifierAuthority.Value[5] +
123 (psid->IdentifierAuthority.Value[4] << 8) +
124 (psid->IdentifierAuthority.Value[3] << 16) +
125 (psid->IdentifierAuthority.Value[2] << 24);
127 switch (psid->SubAuthorityCount) {
128 case 0:
129 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
130 case 1:
131 return wine_dbg_sprintf("S-%d-%d-%u", psid->Revision, auth,
132 psid->SubAuthority[0]);
133 case 2:
134 return wine_dbg_sprintf("S-%d-%d-%u-%u", psid->Revision, auth,
135 psid->SubAuthority[0], psid->SubAuthority[1]);
136 case 3:
137 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u", psid->Revision, auth,
138 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
139 case 4:
140 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u", psid->Revision, auth,
141 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
142 psid->SubAuthority[3]);
143 case 5:
144 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u", psid->Revision, auth,
145 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
146 psid->SubAuthority[3], psid->SubAuthority[4]);
147 case 6:
148 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
149 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
150 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
151 case 7:
152 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
153 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
154 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
155 psid->SubAuthority[6]);
156 case 8:
157 return wine_dbg_sprintf("S-%d-%d-%u-%u-%u-%u-%u-%u-%u-%u", psid->Revision, auth,
158 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
159 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
160 psid->SubAuthority[6], psid->SubAuthority[7]);
162 return "(too-big)";
165 /* helper function for SE_FILE_OBJECT objects in [Get|Set]NamedSecurityInfo */
166 static inline DWORD get_security_file( LPCWSTR full_file_name, DWORD access, HANDLE *file )
168 UNICODE_STRING file_nameW;
169 OBJECT_ATTRIBUTES attr;
170 IO_STATUS_BLOCK io;
171 NTSTATUS status;
173 if (!RtlDosPathNameToNtPathName_U( full_file_name, &file_nameW, NULL, NULL ))
174 return ERROR_PATH_NOT_FOUND;
175 attr.Length = sizeof(attr);
176 attr.RootDirectory = 0;
177 attr.Attributes = OBJ_CASE_INSENSITIVE;
178 attr.ObjectName = &file_nameW;
179 attr.SecurityDescriptor = NULL;
180 status = NtCreateFile( file, access|SYNCHRONIZE, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS,
181 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
182 FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
183 RtlFreeUnicodeString( &file_nameW );
184 return RtlNtStatusToDosError( status );
187 /* helper function for SE_SERVICE objects in [Get|Set]NamedSecurityInfo */
188 static inline DWORD get_security_service( LPWSTR full_service_name, DWORD access, HANDLE *service )
190 SC_HANDLE manager = OpenSCManagerW( NULL, NULL, access );
191 if (manager)
193 *service = OpenServiceW( manager, full_service_name, access);
194 CloseServiceHandle( manager );
195 if (*service)
196 return ERROR_SUCCESS;
198 return GetLastError();
201 /* helper function for SE_REGISTRY_KEY objects in [Get|Set]NamedSecurityInfo */
202 static inline DWORD get_security_regkey( LPWSTR full_key_name, DWORD access, HANDLE *key )
204 LPWSTR p = wcschr(full_key_name, '\\');
205 int len = p-full_key_name;
206 HKEY hParent;
208 if (!p) return ERROR_INVALID_PARAMETER;
209 if (!wcsncmp( full_key_name, L"CLASSES_ROOT", len ))
210 hParent = HKEY_CLASSES_ROOT;
211 else if (!wcsncmp( full_key_name, L"CURRENT_USER", len ))
212 hParent = HKEY_CURRENT_USER;
213 else if (!wcsncmp( full_key_name, L"MACHINE", len ))
214 hParent = HKEY_LOCAL_MACHINE;
215 else if (!wcsncmp( full_key_name, L"USERS", len ))
216 hParent = HKEY_USERS;
217 else
218 return ERROR_INVALID_PARAMETER;
219 return RegOpenKeyExW( hParent, p+1, 0, access, (HKEY *)key );
223 /************************************************************
224 * ADVAPI_IsLocalComputer
226 * Checks whether the server name indicates local machine.
228 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName)
230 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
231 BOOL Result;
232 LPWSTR buf;
234 if (!ServerName || !ServerName[0])
235 return TRUE;
237 buf = heap_alloc(dwSize * sizeof(WCHAR));
238 Result = GetComputerNameW(buf, &dwSize);
239 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\'))
240 ServerName += 2;
241 Result = Result && !wcscmp(ServerName, buf);
242 heap_free(buf);
244 return Result;
247 /************************************************************
248 * ADVAPI_GetComputerSid
250 BOOL ADVAPI_GetComputerSid(PSID sid)
252 static const struct /* same fields as struct SID */
254 BYTE Revision;
255 BYTE SubAuthorityCount;
256 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
257 DWORD SubAuthority[4];
258 } computer_sid =
259 { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } };
261 memcpy( sid, &computer_sid, sizeof(computer_sid) );
262 return TRUE;
265 DWORD WINAPI
266 GetEffectiveRightsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pAccessRights )
268 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
270 *pAccessRights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
271 return 0;
274 DWORD WINAPI
275 GetEffectiveRightsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pAccessRights )
277 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
279 return 1;
282 /* ##############################################
283 ###### SECURITY DESCRIPTOR FUNCTIONS ######
284 ##############################################
287 /******************************************************************************
288 * BuildSecurityDescriptorA [ADVAPI32.@]
290 * Builds a SD from
292 * PARAMS
293 * pOwner [I]
294 * pGroup [I]
295 * cCountOfAccessEntries [I]
296 * pListOfAccessEntries [I]
297 * cCountOfAuditEntries [I]
298 * pListofAuditEntries [I]
299 * pOldSD [I]
300 * lpdwBufferLength [I/O]
301 * pNewSD [O]
303 * RETURNS
304 * Success: ERROR_SUCCESS
305 * Failure: nonzero error code from Winerror.h
307 DWORD WINAPI BuildSecurityDescriptorA(
308 IN PTRUSTEEA pOwner,
309 IN PTRUSTEEA pGroup,
310 IN ULONG cCountOfAccessEntries,
311 IN PEXPLICIT_ACCESSA pListOfAccessEntries,
312 IN ULONG cCountOfAuditEntries,
313 IN PEXPLICIT_ACCESSA pListofAuditEntries,
314 IN PSECURITY_DESCRIPTOR pOldSD,
315 IN OUT PULONG lpdwBufferLength,
316 OUT PSECURITY_DESCRIPTOR* pNewSD)
318 FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
319 cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
320 pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
322 return ERROR_CALL_NOT_IMPLEMENTED;
325 /******************************************************************************
326 * BuildSecurityDescriptorW [ADVAPI32.@]
328 * See BuildSecurityDescriptorA.
330 DWORD WINAPI BuildSecurityDescriptorW(
331 IN PTRUSTEEW pOwner,
332 IN PTRUSTEEW pGroup,
333 IN ULONG cCountOfAccessEntries,
334 IN PEXPLICIT_ACCESSW pListOfAccessEntries,
335 IN ULONG cCountOfAuditEntries,
336 IN PEXPLICIT_ACCESSW pListOfAuditEntries,
337 IN PSECURITY_DESCRIPTOR pOldSD,
338 IN OUT PULONG lpdwBufferLength,
339 OUT PSECURITY_DESCRIPTOR* pNewSD)
341 SECURITY_DESCRIPTOR desc;
342 NTSTATUS status;
343 DWORD ret = ERROR_SUCCESS;
345 TRACE("(%p,%p,%d,%p,%d,%p,%p,%p,%p)\n", pOwner, pGroup,
346 cCountOfAccessEntries, pListOfAccessEntries, cCountOfAuditEntries,
347 pListOfAuditEntries, pOldSD, lpdwBufferLength, pNewSD);
349 if (pOldSD)
351 SECURITY_DESCRIPTOR_CONTROL control;
352 DWORD desc_size, dacl_size = 0, sacl_size = 0, owner_size = 0, group_size = 0;
353 PACL dacl = NULL, sacl = NULL;
354 PSID owner = NULL, group = NULL;
355 DWORD revision;
357 if ((status = RtlGetControlSecurityDescriptor( pOldSD, &control, &revision )) != STATUS_SUCCESS)
358 return RtlNtStatusToDosError( status );
359 if (!(control & SE_SELF_RELATIVE))
360 return ERROR_INVALID_SECURITY_DESCR;
362 desc_size = sizeof(desc);
363 status = RtlSelfRelativeToAbsoluteSD( pOldSD, &desc, &desc_size, dacl, &dacl_size, sacl, &sacl_size,
364 owner, &owner_size, group, &group_size );
365 if (status == STATUS_BUFFER_TOO_SMALL)
367 if (dacl_size)
368 dacl = LocalAlloc( LMEM_FIXED, dacl_size );
369 if (sacl_size)
370 sacl = LocalAlloc( LMEM_FIXED, sacl_size );
371 if (owner_size)
372 owner = LocalAlloc( LMEM_FIXED, owner_size );
373 if (group_size)
374 group = LocalAlloc( LMEM_FIXED, group_size );
376 desc_size = sizeof(desc);
377 status = RtlSelfRelativeToAbsoluteSD( pOldSD, &desc, &desc_size, dacl, &dacl_size, sacl, &sacl_size,
378 owner, &owner_size, group, &group_size );
380 if (status != STATUS_SUCCESS)
382 LocalFree( dacl );
383 LocalFree( sacl );
384 LocalFree( owner );
385 LocalFree( group );
386 return RtlNtStatusToDosError( status );
389 else
391 if ((status = RtlCreateSecurityDescriptor( &desc, SECURITY_DESCRIPTOR_REVISION )) != STATUS_SUCCESS)
392 return RtlNtStatusToDosError( status );
395 if (pOwner)
397 LocalFree( desc.Owner );
398 desc.Owner = LocalAlloc( LMEM_FIXED, sizeof(MAX_SID) );
399 if ((ret = trustee_to_sid( sizeof(MAX_SID), desc.Owner, pOwner )))
400 goto done;
403 if (pGroup)
405 LocalFree( desc.Group );
406 desc.Group = LocalAlloc( LMEM_FIXED, sizeof(MAX_SID) );
407 if ((ret = trustee_to_sid( sizeof(MAX_SID), desc.Group, pGroup )))
408 goto done;
411 if (pListOfAccessEntries)
413 PACL new_dacl;
415 if ((ret = SetEntriesInAclW( cCountOfAccessEntries, pListOfAccessEntries, desc.Dacl, &new_dacl )))
416 goto done;
418 LocalFree( desc.Dacl );
419 desc.Dacl = new_dacl;
420 desc.Control |= SE_DACL_PRESENT;
423 if (pListOfAuditEntries)
425 PACL new_sacl;
427 if ((ret = SetEntriesInAclW( cCountOfAuditEntries, pListOfAuditEntries, desc.Sacl, &new_sacl )))
428 goto done;
430 LocalFree( desc.Sacl );
431 desc.Sacl = new_sacl;
432 desc.Control |= SE_SACL_PRESENT;
435 *lpdwBufferLength = RtlLengthSecurityDescriptor( &desc );
436 *pNewSD = LocalAlloc( LMEM_FIXED, *lpdwBufferLength );
438 if ((status = RtlMakeSelfRelativeSD( &desc, *pNewSD, lpdwBufferLength )) != STATUS_SUCCESS)
440 ret = RtlNtStatusToDosError( status );
441 LocalFree( *pNewSD );
442 *pNewSD = NULL;
445 done:
446 /* free absolute descriptor */
447 LocalFree( desc.Owner );
448 LocalFree( desc.Group );
449 LocalFree( desc.Sacl );
450 LocalFree( desc.Dacl );
451 return ret;
454 static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] =
456 NULL,
457 NULL,
458 L"SeCreateTokenPrivilege",
459 L"SeAssignPrimaryTokenPrivilege",
460 L"SeLockMemoryPrivilege",
461 L"SeIncreaseQuotaPrivilege",
462 L"SeMachineAccountPrivilege",
463 L"SeTcbPrivilege",
464 L"SeSecurityPrivilege",
465 L"SeTakeOwnershipPrivilege",
466 L"SeLoadDriverPrivilege",
467 L"SeSystemProfilePrivilege",
468 L"SeSystemtimePrivilege",
469 L"SeProfileSingleProcessPrivilege",
470 L"SeIncreaseBasePriorityPrivilege",
471 L"SeCreatePagefilePrivilege",
472 L"SeCreatePermanentPrivilege",
473 L"SeBackupPrivilege",
474 L"SeRestorePrivilege",
475 L"SeShutdownPrivilege",
476 L"SeDebugPrivilege",
477 L"SeAuditPrivilege",
478 L"SeSystemEnvironmentPrivilege",
479 L"SeChangeNotifyPrivilege",
480 L"SeRemoteShutdownPrivilege",
481 L"SeUndockPrivilege",
482 L"SeSyncAgentPrivilege",
483 L"SeEnableDelegationPrivilege",
484 L"SeManageVolumePrivilege",
485 L"SeImpersonatePrivilege",
486 L"SeCreateGlobalPrivilege",
489 const WCHAR *get_wellknown_privilege_name(const LUID *luid)
491 if (luid->HighPart || luid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
492 luid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE || !WellKnownPrivNames[luid->LowPart])
493 return NULL;
495 return WellKnownPrivNames[luid->LowPart];
498 /******************************************************************************
499 * LookupPrivilegeValueW [ADVAPI32.@]
501 * See LookupPrivilegeValueA.
503 BOOL WINAPI
504 LookupPrivilegeValueW( LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid )
506 UINT i;
508 TRACE("%s,%s,%p\n",debugstr_w(lpSystemName), debugstr_w(lpName), lpLuid);
510 if (!ADVAPI_IsLocalComputer(lpSystemName))
512 SetLastError(RPC_S_SERVER_UNAVAILABLE);
513 return FALSE;
515 if (!lpName)
517 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
518 return FALSE;
520 for( i=SE_MIN_WELL_KNOWN_PRIVILEGE; i<=SE_MAX_WELL_KNOWN_PRIVILEGE; i++ )
522 if( !WellKnownPrivNames[i] )
523 continue;
524 if( wcsicmp( WellKnownPrivNames[i], lpName) )
525 continue;
526 lpLuid->LowPart = i;
527 lpLuid->HighPart = 0;
528 TRACE( "%s -> %08x-%08x\n",debugstr_w( lpSystemName ),
529 lpLuid->HighPart, lpLuid->LowPart );
530 return TRUE;
532 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
533 return FALSE;
536 /******************************************************************************
537 * LookupPrivilegeValueA [ADVAPI32.@]
539 * Retrieves LUID used on a system to represent the privilege name.
541 * PARAMS
542 * lpSystemName [I] Name of the system
543 * lpName [I] Name of the privilege
544 * lpLuid [O] Destination for the resulting LUID
546 * RETURNS
547 * Success: TRUE. lpLuid contains the requested LUID.
548 * Failure: FALSE.
550 BOOL WINAPI
551 LookupPrivilegeValueA( LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid )
553 UNICODE_STRING lpSystemNameW;
554 UNICODE_STRING lpNameW;
555 BOOL ret;
557 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
558 RtlCreateUnicodeStringFromAsciiz(&lpNameW,lpName);
559 ret = LookupPrivilegeValueW(lpSystemNameW.Buffer, lpNameW.Buffer, lpLuid);
560 RtlFreeUnicodeString(&lpNameW);
561 RtlFreeUnicodeString(&lpSystemNameW);
562 return ret;
565 BOOL WINAPI LookupPrivilegeDisplayNameA( LPCSTR lpSystemName, LPCSTR lpName, LPSTR lpDisplayName,
566 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
568 FIXME("%s %s %s %p %p - stub\n", debugstr_a(lpSystemName), debugstr_a(lpName),
569 debugstr_a(lpDisplayName), cchDisplayName, lpLanguageId);
571 return FALSE;
574 BOOL WINAPI LookupPrivilegeDisplayNameW( LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName,
575 LPDWORD cchDisplayName, LPDWORD lpLanguageId )
577 FIXME("%s %s %s %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
578 debugstr_w(lpDisplayName), cchDisplayName, lpLanguageId);
580 return FALSE;
583 /******************************************************************************
584 * LookupPrivilegeNameA [ADVAPI32.@]
586 * See LookupPrivilegeNameW.
588 BOOL WINAPI
589 LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName,
590 LPDWORD cchName)
592 UNICODE_STRING lpSystemNameW;
593 BOOL ret;
594 DWORD wLen = 0;
596 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName);
598 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName);
599 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen);
600 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
602 LPWSTR lpNameW = heap_alloc(wLen * sizeof(WCHAR));
604 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW,
605 &wLen);
606 if (ret)
608 /* Windows crashes if cchName is NULL, so will I */
609 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName,
610 *cchName, NULL, NULL);
612 if (len == 0)
614 /* WideCharToMultiByte failed */
615 ret = FALSE;
617 else if (len > *cchName)
619 *cchName = len;
620 SetLastError(ERROR_INSUFFICIENT_BUFFER);
621 ret = FALSE;
623 else
625 /* WideCharToMultiByte succeeded, output length needs to be
626 * length not including NULL terminator
628 *cchName = len - 1;
631 heap_free(lpNameW);
633 RtlFreeUnicodeString(&lpSystemNameW);
634 return ret;
637 /******************************************************************************
638 * LookupPrivilegeNameW [ADVAPI32.@]
640 * Retrieves the privilege name referred to by the LUID lpLuid.
642 * PARAMS
643 * lpSystemName [I] Name of the system
644 * lpLuid [I] Privilege value
645 * lpName [O] Name of the privilege
646 * cchName [I/O] Number of characters in lpName.
648 * RETURNS
649 * Success: TRUE. lpName contains the name of the privilege whose value is
650 * *lpLuid.
651 * Failure: FALSE.
653 * REMARKS
654 * Only well-known privilege names (those defined in winnt.h) can be retrieved
655 * using this function.
656 * If the length of lpName is too small, on return *cchName will contain the
657 * number of WCHARs needed to contain the privilege, including the NULL
658 * terminator, and GetLastError will return ERROR_INSUFFICIENT_BUFFER.
659 * On success, *cchName will contain the number of characters stored in
660 * lpName, NOT including the NULL terminator.
662 BOOL WINAPI
663 LookupPrivilegeNameW( LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName,
664 LPDWORD cchName)
666 size_t privNameLen;
668 TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName);
670 if (!ADVAPI_IsLocalComputer(lpSystemName))
672 SetLastError(RPC_S_SERVER_UNAVAILABLE);
673 return FALSE;
675 if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
676 lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
678 SetLastError(ERROR_NO_SUCH_PRIVILEGE);
679 return FALSE;
681 privNameLen = lstrlenW(WellKnownPrivNames[lpLuid->LowPart]);
682 /* Windows crashes if cchName is NULL, so will I */
683 if (*cchName <= privNameLen)
685 *cchName = privNameLen + 1;
686 SetLastError(ERROR_INSUFFICIENT_BUFFER);
687 return FALSE;
689 else
691 lstrcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]);
692 *cchName = privNameLen;
693 return TRUE;
697 /******************************************************************************
698 * GetFileSecurityA [ADVAPI32.@]
700 * Obtains Specified information about the security of a file or directory.
702 * PARAMS
703 * lpFileName [I] Name of the file to get info for
704 * RequestedInformation [I] SE_ flags from "winnt.h"
705 * pSecurityDescriptor [O] Destination for security information
706 * nLength [I] Length of pSecurityDescriptor
707 * lpnLengthNeeded [O] Destination for length of returned security information
709 * RETURNS
710 * Success: TRUE. pSecurityDescriptor contains the requested information.
711 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info.
713 * NOTES
714 * The information returned is constrained by the callers access rights and
715 * privileges.
717 BOOL WINAPI
718 GetFileSecurityA( LPCSTR lpFileName,
719 SECURITY_INFORMATION RequestedInformation,
720 PSECURITY_DESCRIPTOR pSecurityDescriptor,
721 DWORD nLength, LPDWORD lpnLengthNeeded )
723 BOOL r;
724 LPWSTR name;
726 name = strdupAW(lpFileName);
727 r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor,
728 nLength, lpnLengthNeeded );
729 heap_free( name );
731 return r;
734 /******************************************************************************
735 * LookupAccountSidA [ADVAPI32.@]
737 BOOL WINAPI
738 LookupAccountSidA(
739 IN LPCSTR system,
740 IN PSID sid,
741 OUT LPSTR account,
742 IN OUT LPDWORD accountSize,
743 OUT LPSTR domain,
744 IN OUT LPDWORD domainSize,
745 OUT PSID_NAME_USE name_use )
747 DWORD len;
748 BOOL r;
749 LPWSTR systemW;
750 LPWSTR accountW = NULL;
751 LPWSTR domainW = NULL;
752 DWORD accountSizeW = *accountSize;
753 DWORD domainSizeW = *domainSize;
755 systemW = strdupAW(system);
756 if (account)
757 accountW = heap_alloc( accountSizeW * sizeof(WCHAR) );
758 if (domain)
759 domainW = heap_alloc( domainSizeW * sizeof(WCHAR) );
761 r = LookupAccountSidW( systemW, sid, accountW, &accountSizeW, domainW, &domainSizeW, name_use );
763 if (r) {
764 if (accountW && *accountSize) {
765 len = WideCharToMultiByte( CP_ACP, 0, accountW, -1, NULL, 0, NULL, NULL );
766 WideCharToMultiByte( CP_ACP, 0, accountW, -1, account, len, NULL, NULL );
767 *accountSize = len;
768 } else
769 *accountSize = accountSizeW + 1;
771 if (domainW && *domainSize) {
772 len = WideCharToMultiByte( CP_ACP, 0, domainW, -1, NULL, 0, NULL, NULL );
773 WideCharToMultiByte( CP_ACP, 0, domainW, -1, domain, len, NULL, NULL );
774 *domainSize = len;
775 } else
776 *domainSize = domainSizeW + 1;
778 else
780 *accountSize = accountSizeW + 1;
781 *domainSize = domainSizeW + 1;
784 heap_free( systemW );
785 heap_free( accountW );
786 heap_free( domainW );
788 return r;
791 /******************************************************************************
792 * LookupAccountSidLocalA [ADVAPI32.@]
794 BOOL WINAPI
795 LookupAccountSidLocalA(
796 PSID sid,
797 LPSTR account,
798 LPDWORD accountSize,
799 LPSTR domain,
800 LPDWORD domainSize,
801 PSID_NAME_USE name_use )
803 return LookupAccountSidA(NULL, sid, account, accountSize, domain, domainSize, name_use);
806 /******************************************************************************
807 * LookupAccountSidW [ADVAPI32.@]
809 * PARAMS
810 * system []
811 * sid []
812 * account []
813 * accountSize []
814 * domain []
815 * domainSize []
816 * name_use []
819 BOOL WINAPI
820 LookupAccountSidW(
821 IN LPCWSTR system,
822 IN PSID sid,
823 OUT LPWSTR account,
824 IN OUT LPDWORD accountSize,
825 OUT LPWSTR domain,
826 IN OUT LPDWORD domainSize,
827 OUT PSID_NAME_USE name_use )
829 unsigned int i, j;
830 const WCHAR * ac = NULL;
831 const WCHAR * dm = NULL;
832 SID_NAME_USE use = 0;
833 LPWSTR computer_name = NULL;
834 LPWSTR account_name = NULL;
836 TRACE("(%s,sid=%s,%p,%p(%u),%p,%p(%u),%p)\n",
837 debugstr_w(system),debugstr_sid(sid),
838 account,accountSize,accountSize?*accountSize:0,
839 domain,domainSize,domainSize?*domainSize:0,
840 name_use);
842 if (!ADVAPI_IsLocalComputer(system)) {
843 FIXME("Only local computer supported!\n");
844 SetLastError(RPC_S_SERVER_UNAVAILABLE);
845 return FALSE;
848 /* check the well known SIDs first */
849 for (i = 0; i <= WinAccountProtectedUsersSid; i++) {
850 if (IsWellKnownSid(sid, i)) {
851 for (j = 0; j < ARRAY_SIZE(ACCOUNT_SIDS); j++) {
852 if (ACCOUNT_SIDS[j].type == i) {
853 ac = ACCOUNT_SIDS[j].account;
854 dm = ACCOUNT_SIDS[j].domain;
855 use = ACCOUNT_SIDS[j].name_use;
858 break;
862 if (dm == NULL) {
863 MAX_SID local;
865 /* check for the local computer next */
866 if (ADVAPI_GetComputerSid(&local)) {
867 DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
868 BOOL result;
870 computer_name = heap_alloc(size * sizeof(WCHAR));
871 result = GetComputerNameW(computer_name, &size);
873 if (result) {
874 if (EqualSid(sid, &local)) {
875 dm = computer_name;
876 ac = L"";
877 use = 3;
878 } else {
879 local.SubAuthorityCount++;
881 if (EqualPrefixSid(sid, &local)) {
882 dm = computer_name;
883 use = 1;
884 switch (((MAX_SID *)sid)->SubAuthority[4]) {
885 case DOMAIN_USER_RID_ADMIN:
886 ac = L"Administrator";
887 break;
888 case DOMAIN_USER_RID_GUEST:
889 ac = L"Guest";
890 break;
891 case DOMAIN_GROUP_RID_ADMINS:
892 ac = L"Domain Admins";
893 break;
894 case DOMAIN_GROUP_RID_USERS:
895 ac = L"None";
896 use = SidTypeGroup;
897 break;
898 case DOMAIN_GROUP_RID_GUESTS:
899 ac = L"Domain Guests";
900 break;
901 case DOMAIN_GROUP_RID_COMPUTERS:
902 ac = L"Domain Computers";
903 break;
904 case DOMAIN_GROUP_RID_CONTROLLERS:
905 ac = L"Domain Controllers";
906 break;
907 case DOMAIN_GROUP_RID_CERT_ADMINS:
908 ac = L"Cert Publishers";
909 break;
910 case DOMAIN_GROUP_RID_SCHEMA_ADMINS:
911 ac = L"Schema Admins";
912 break;
913 case DOMAIN_GROUP_RID_ENTERPRISE_ADMINS:
914 ac = L"Enterprise Admins";
915 break;
916 case DOMAIN_GROUP_RID_POLICY_ADMINS:
917 ac = L"Group Policy Creator Owners";
918 break;
919 case DOMAIN_ALIAS_RID_RAS_SERVERS:
920 ac = L"RAS and IAS Servers";
921 break;
922 case 1000: /* first user account */
923 size = UNLEN + 1;
924 account_name = heap_alloc(size * sizeof(WCHAR));
925 if (GetUserNameW(account_name, &size))
926 ac = account_name;
927 else
928 dm = NULL;
930 break;
931 default:
932 dm = NULL;
933 break;
941 if (dm) {
942 DWORD ac_len = lstrlenW(ac);
943 DWORD dm_len = lstrlenW(dm);
944 BOOL status = TRUE;
946 if (*accountSize > ac_len) {
947 if (account)
948 lstrcpyW(account, ac);
950 if (*domainSize > dm_len) {
951 if (domain)
952 lstrcpyW(domain, dm);
954 if ((*accountSize && *accountSize < ac_len) ||
955 (!account && !*accountSize && ac_len) ||
956 (*domainSize && *domainSize < dm_len) ||
957 (!domain && !*domainSize && dm_len))
959 SetLastError(ERROR_INSUFFICIENT_BUFFER);
960 status = FALSE;
962 if (*domainSize)
963 *domainSize = dm_len;
964 else
965 *domainSize = dm_len + 1;
966 if (*accountSize)
967 *accountSize = ac_len;
968 else
969 *accountSize = ac_len + 1;
971 heap_free(account_name);
972 heap_free(computer_name);
973 if (status) *name_use = use;
974 return status;
977 heap_free(account_name);
978 heap_free(computer_name);
979 SetLastError(ERROR_NONE_MAPPED);
980 return FALSE;
983 /******************************************************************************
984 * LookupAccountSidLocalW [ADVAPI32.@]
986 BOOL WINAPI
987 LookupAccountSidLocalW(
988 PSID sid,
989 LPWSTR account,
990 LPDWORD accountSize,
991 LPWSTR domain,
992 LPDWORD domainSize,
993 PSID_NAME_USE name_use )
995 return LookupAccountSidW(NULL, sid, account, accountSize, domain, domainSize, name_use);
998 /******************************************************************************
999 * SetFileSecurityA [ADVAPI32.@]
1001 * See SetFileSecurityW.
1003 BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName,
1004 SECURITY_INFORMATION RequestedInformation,
1005 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1007 BOOL r;
1008 LPWSTR name;
1010 name = strdupAW(lpFileName);
1011 r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor );
1012 heap_free( name );
1014 return r;
1017 /******************************************************************************
1018 * QueryWindows31FilesMigration [ADVAPI32.@]
1020 * PARAMS
1021 * x1 []
1023 BOOL WINAPI
1024 QueryWindows31FilesMigration( DWORD x1 )
1026 FIXME("(%d):stub\n",x1);
1027 return TRUE;
1030 /******************************************************************************
1031 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@]
1033 * PARAMS
1034 * x1 []
1035 * x2 []
1036 * x3 []
1037 * x4 []
1039 BOOL WINAPI
1040 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3,
1041 DWORD x4 )
1043 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4);
1044 return TRUE;
1047 /******************************************************************************
1048 * NotifyBootConfigStatus [ADVAPI32.@]
1050 * PARAMS
1051 * x1 []
1053 BOOL WINAPI
1054 NotifyBootConfigStatus( BOOL x1 )
1056 FIXME("(0x%08d):stub\n",x1);
1057 return TRUE;
1060 /******************************************************************************
1061 * LookupAccountNameA [ADVAPI32.@]
1063 BOOL WINAPI
1064 LookupAccountNameA(
1065 IN LPCSTR system,
1066 IN LPCSTR account,
1067 OUT PSID sid,
1068 OUT LPDWORD cbSid,
1069 LPSTR ReferencedDomainName,
1070 IN OUT LPDWORD cbReferencedDomainName,
1071 OUT PSID_NAME_USE name_use )
1073 BOOL ret;
1074 UNICODE_STRING lpSystemW;
1075 UNICODE_STRING lpAccountW;
1076 LPWSTR lpReferencedDomainNameW = NULL;
1078 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, system);
1079 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, account);
1081 if (ReferencedDomainName)
1082 lpReferencedDomainNameW = heap_alloc(*cbReferencedDomainName * sizeof(WCHAR));
1084 ret = LookupAccountNameW(lpSystemW.Buffer, lpAccountW.Buffer, sid, cbSid, lpReferencedDomainNameW,
1085 cbReferencedDomainName, name_use);
1087 if (ret && lpReferencedDomainNameW)
1089 WideCharToMultiByte(CP_ACP, 0, lpReferencedDomainNameW, -1,
1090 ReferencedDomainName, *cbReferencedDomainName+1, NULL, NULL);
1093 RtlFreeUnicodeString(&lpSystemW);
1094 RtlFreeUnicodeString(&lpAccountW);
1095 heap_free(lpReferencedDomainNameW);
1097 return ret;
1100 /******************************************************************************
1101 * lookup_user_account_name
1103 static BOOL lookup_user_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
1104 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
1106 char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
1107 DWORD len = sizeof(buffer);
1108 HANDLE token;
1109 BOOL ret;
1110 PSID pSid;
1111 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
1112 DWORD nameLen;
1114 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
1116 if (GetLastError() != ERROR_NO_TOKEN) return FALSE;
1117 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) return FALSE;
1120 ret = GetTokenInformation(token, TokenUser, buffer, len, &len);
1121 CloseHandle( token );
1123 if (!ret) return FALSE;
1125 pSid = ((TOKEN_USER *)buffer)->User.Sid;
1127 if (Sid != NULL && (*cbSid >= GetLengthSid(pSid)))
1128 CopySid(*cbSid, Sid, pSid);
1129 if (*cbSid < GetLengthSid(pSid))
1131 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1132 ret = FALSE;
1134 *cbSid = GetLengthSid(pSid);
1136 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
1137 if (!GetComputerNameW(domainName, &nameLen))
1139 domainName[0] = 0;
1140 nameLen = 0;
1142 if (*cchReferencedDomainName <= nameLen || !ret)
1144 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1145 nameLen += 1;
1146 ret = FALSE;
1148 else if (ReferencedDomainName)
1149 lstrcpyW(ReferencedDomainName, domainName);
1151 *cchReferencedDomainName = nameLen;
1153 if (ret)
1154 *peUse = SidTypeUser;
1156 return ret;
1159 /******************************************************************************
1160 * lookup_computer_account_name
1162 static BOOL lookup_computer_account_name(PSID Sid, PDWORD cbSid, LPWSTR ReferencedDomainName,
1163 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
1165 MAX_SID local;
1166 BOOL ret;
1167 WCHAR domainName[MAX_COMPUTERNAME_LENGTH + 1];
1168 DWORD nameLen;
1170 if ((ret = ADVAPI_GetComputerSid(&local)))
1172 if (Sid != NULL && (*cbSid >= GetLengthSid(&local)))
1173 CopySid(*cbSid, Sid, &local);
1174 if (*cbSid < GetLengthSid(&local))
1176 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1177 ret = FALSE;
1179 *cbSid = GetLengthSid(&local);
1182 nameLen = MAX_COMPUTERNAME_LENGTH + 1;
1183 if (!GetComputerNameW(domainName, &nameLen))
1185 domainName[0] = 0;
1186 nameLen = 0;
1188 if (*cchReferencedDomainName <= nameLen || !ret)
1190 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1191 nameLen += 1;
1192 ret = FALSE;
1194 else if (ReferencedDomainName)
1195 lstrcpyW(ReferencedDomainName, domainName);
1197 *cchReferencedDomainName = nameLen;
1199 if (ret)
1200 *peUse = SidTypeDomain;
1202 return ret;
1205 static void split_domain_account( const LSA_UNICODE_STRING *str, LSA_UNICODE_STRING *account,
1206 LSA_UNICODE_STRING *domain )
1208 WCHAR *p = str->Buffer + str->Length / sizeof(WCHAR) - 1;
1210 while (p > str->Buffer && *p != '\\') p--;
1212 if (*p == '\\')
1214 domain->Buffer = str->Buffer;
1215 domain->Length = (p - str->Buffer) * sizeof(WCHAR);
1217 account->Buffer = p + 1;
1218 account->Length = str->Length - ((p - str->Buffer + 1) * sizeof(WCHAR));
1220 else
1222 domain->Buffer = NULL;
1223 domain->Length = 0;
1225 account->Buffer = str->Buffer;
1226 account->Length = str->Length;
1230 static BOOL match_domain( ULONG idx, const LSA_UNICODE_STRING *domain )
1232 ULONG len = lstrlenW( ACCOUNT_SIDS[idx].domain );
1234 if (len == domain->Length / sizeof(WCHAR) && !wcsnicmp( domain->Buffer, ACCOUNT_SIDS[idx].domain, len ))
1235 return TRUE;
1237 return FALSE;
1240 static BOOL match_account( ULONG idx, const LSA_UNICODE_STRING *account )
1242 ULONG len = lstrlenW( ACCOUNT_SIDS[idx].account );
1244 if (len == account->Length / sizeof(WCHAR) && !wcsnicmp( account->Buffer, ACCOUNT_SIDS[idx].account, len ))
1245 return TRUE;
1247 if (ACCOUNT_SIDS[idx].alias)
1249 len = lstrlenW( ACCOUNT_SIDS[idx].alias );
1250 if (len == account->Length / sizeof(WCHAR) && !wcsnicmp( account->Buffer, ACCOUNT_SIDS[idx].alias, len ))
1251 return TRUE;
1253 return FALSE;
1257 * Helper function for LookupAccountNameW
1259 BOOL lookup_local_wellknown_name( const LSA_UNICODE_STRING *account_and_domain,
1260 PSID Sid, LPDWORD cbSid,
1261 LPWSTR ReferencedDomainName,
1262 LPDWORD cchReferencedDomainName,
1263 PSID_NAME_USE peUse, BOOL *handled )
1265 PSID pSid;
1266 LSA_UNICODE_STRING account, domain;
1267 BOOL ret = TRUE;
1268 ULONG i;
1270 *handled = FALSE;
1271 split_domain_account( account_and_domain, &account, &domain );
1273 for (i = 0; i < ARRAY_SIZE(ACCOUNT_SIDS); i++)
1275 /* check domain first */
1276 if (domain.Buffer && !match_domain( i, &domain )) continue;
1278 if (match_account( i, &account ))
1280 DWORD len, sidLen = SECURITY_MAX_SID_SIZE;
1282 if (!(pSid = heap_alloc( sidLen ))) return FALSE;
1284 if ((ret = CreateWellKnownSid( ACCOUNT_SIDS[i].type, NULL, pSid, &sidLen )))
1286 if (*cbSid < sidLen)
1288 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1289 ret = FALSE;
1291 else if (Sid)
1293 CopySid(*cbSid, Sid, pSid);
1295 *cbSid = sidLen;
1298 len = lstrlenW( ACCOUNT_SIDS[i].domain );
1299 if (*cchReferencedDomainName <= len || !ret)
1301 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1302 len++;
1303 ret = FALSE;
1305 else if (ReferencedDomainName)
1307 lstrcpyW( ReferencedDomainName, ACCOUNT_SIDS[i].domain );
1310 *cchReferencedDomainName = len;
1311 if (ret)
1312 *peUse = ACCOUNT_SIDS[i].name_use;
1314 heap_free(pSid);
1315 *handled = TRUE;
1316 return ret;
1319 return ret;
1322 BOOL lookup_local_user_name( const LSA_UNICODE_STRING *account_and_domain,
1323 PSID Sid, LPDWORD cbSid,
1324 LPWSTR ReferencedDomainName,
1325 LPDWORD cchReferencedDomainName,
1326 PSID_NAME_USE peUse, BOOL *handled )
1328 DWORD nameLen;
1329 LPWSTR userName = NULL;
1330 LSA_UNICODE_STRING account, domain;
1331 BOOL ret = TRUE;
1333 *handled = FALSE;
1334 split_domain_account( account_and_domain, &account, &domain );
1336 /* Let the current Unix user id masquerade as first Windows user account */
1338 nameLen = UNLEN + 1;
1339 if (!(userName = heap_alloc( nameLen * sizeof(WCHAR) ))) return FALSE;
1341 if (domain.Buffer)
1343 /* check to make sure this account is on this computer */
1344 if (GetComputerNameW( userName, &nameLen ) &&
1345 (domain.Length / sizeof(WCHAR) != nameLen || wcsncmp( domain.Buffer, userName, nameLen )))
1347 SetLastError(ERROR_NONE_MAPPED);
1348 ret = FALSE;
1350 nameLen = UNLEN + 1;
1353 if (GetUserNameW( userName, &nameLen ) &&
1354 account.Length / sizeof(WCHAR) == nameLen - 1 && !wcsncmp( account.Buffer, userName, nameLen - 1 ))
1356 ret = lookup_user_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
1357 *handled = TRUE;
1359 else
1361 nameLen = UNLEN + 1;
1362 if (GetComputerNameW( userName, &nameLen ) &&
1363 account.Length / sizeof(WCHAR) == nameLen && !wcsncmp( account.Buffer, userName , nameLen ))
1365 ret = lookup_computer_account_name( Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse );
1366 *handled = TRUE;
1370 heap_free(userName);
1371 return ret;
1374 /******************************************************************************
1375 * LookupAccountNameW [ADVAPI32.@]
1377 BOOL WINAPI LookupAccountNameW( LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid,
1378 LPDWORD cbSid, LPWSTR ReferencedDomainName,
1379 LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse )
1381 BOOL ret, handled;
1382 LSA_UNICODE_STRING account;
1384 TRACE("%s %s %p %p %p %p %p\n", debugstr_w(lpSystemName), debugstr_w(lpAccountName),
1385 Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse);
1387 if (!ADVAPI_IsLocalComputer( lpSystemName ))
1389 FIXME("remote computer not supported\n");
1390 SetLastError( RPC_S_SERVER_UNAVAILABLE );
1391 return FALSE;
1394 if (!lpAccountName || !wcscmp( lpAccountName, L"" ))
1396 lpAccountName = L"BUILTIN";
1399 RtlInitUnicodeString( &account, lpAccountName );
1401 /* Check well known SIDs first */
1402 ret = lookup_local_wellknown_name( &account, Sid, cbSid, ReferencedDomainName,
1403 cchReferencedDomainName, peUse, &handled );
1404 if (handled)
1405 return ret;
1407 /* Check user names */
1408 ret = lookup_local_user_name( &account, Sid, cbSid, ReferencedDomainName,
1409 cchReferencedDomainName, peUse, &handled);
1410 if (handled)
1411 return ret;
1413 SetLastError( ERROR_NONE_MAPPED );
1414 return FALSE;
1417 /******************************************************************************
1418 * AccessCheckAndAuditAlarmA [ADVAPI32.@]
1420 BOOL WINAPI AccessCheckAndAuditAlarmA(LPCSTR Subsystem, LPVOID HandleId, LPSTR ObjectTypeName,
1421 LPSTR ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD DesiredAccess,
1422 PGENERIC_MAPPING GenericMapping, BOOL ObjectCreation, LPDWORD GrantedAccess,
1423 LPBOOL AccessStatus, LPBOOL pfGenerateOnClose)
1425 FIXME("stub (%s,%p,%s,%s,%p,%08x,%p,%x,%p,%p,%p)\n", debugstr_a(Subsystem),
1426 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName),
1427 SecurityDescriptor, DesiredAccess, GenericMapping,
1428 ObjectCreation, GrantedAccess, AccessStatus, pfGenerateOnClose);
1429 return TRUE;
1432 BOOL WINAPI ObjectCloseAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, BOOL GenerateOnClose)
1434 FIXME("stub (%s,%p,%x)\n", debugstr_a(SubsystemName), HandleId, GenerateOnClose);
1436 return TRUE;
1439 BOOL WINAPI ObjectOpenAuditAlarmA(LPCSTR SubsystemName, LPVOID HandleId, LPSTR ObjectTypeName,
1440 LPSTR ObjectName, PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess,
1441 DWORD GrantedAccess, PPRIVILEGE_SET Privileges, BOOL ObjectCreation, BOOL AccessGranted,
1442 LPBOOL GenerateOnClose)
1444 FIXME("stub (%s,%p,%s,%s,%p,%p,0x%08x,0x%08x,%p,%x,%x,%p)\n", debugstr_a(SubsystemName),
1445 HandleId, debugstr_a(ObjectTypeName), debugstr_a(ObjectName), pSecurityDescriptor,
1446 ClientToken, DesiredAccess, GrantedAccess, Privileges, ObjectCreation, AccessGranted,
1447 GenerateOnClose);
1449 return TRUE;
1452 BOOL WINAPI ObjectPrivilegeAuditAlarmA( LPCSTR SubsystemName, LPVOID HandleId, HANDLE ClientToken,
1453 DWORD DesiredAccess, PPRIVILEGE_SET Privileges, BOOL AccessGranted)
1455 FIXME("stub (%s,%p,%p,0x%08x,%p,%x)\n", debugstr_a(SubsystemName), HandleId, ClientToken,
1456 DesiredAccess, Privileges, AccessGranted);
1458 return TRUE;
1461 BOOL WINAPI PrivilegedServiceAuditAlarmA( LPCSTR SubsystemName, LPCSTR ServiceName, HANDLE ClientToken,
1462 PPRIVILEGE_SET Privileges, BOOL AccessGranted)
1464 FIXME("stub (%s,%s,%p,%p,%x)\n", debugstr_a(SubsystemName), debugstr_a(ServiceName),
1465 ClientToken, Privileges, AccessGranted);
1467 return TRUE;
1470 #define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT
1471 #define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA
1473 /******************************************************************************
1474 * GetSecurityInfo [ADVAPI32.@]
1476 * Retrieves a copy of the security descriptor associated with an object.
1478 * PARAMS
1479 * hObject [I] A handle for the object.
1480 * ObjectType [I] The type of object.
1481 * SecurityInfo [I] A bitmask indicating what info to retrieve.
1482 * ppsidOwner [O] If non-null, receives a pointer to the owner SID.
1483 * ppsidGroup [O] If non-null, receives a pointer to the group SID.
1484 * ppDacl [O] If non-null, receives a pointer to the DACL.
1485 * ppSacl [O] If non-null, receives a pointer to the SACL.
1486 * ppSecurityDescriptor [O] Receives a pointer to the security descriptor,
1487 * which must be freed with LocalFree.
1489 * RETURNS
1490 * ERROR_SUCCESS if all's well, and a WIN32 error code otherwise.
1492 DWORD WINAPI GetSecurityInfo( HANDLE handle, SE_OBJECT_TYPE type, SECURITY_INFORMATION SecurityInfo,
1493 PSID *ppsidOwner, PSID *ppsidGroup, PACL *ppDacl, PACL *ppSacl,
1494 PSECURITY_DESCRIPTOR *ppSecurityDescriptor )
1496 PSECURITY_DESCRIPTOR sd;
1497 NTSTATUS status;
1498 ULONG size;
1499 BOOL present, defaulted;
1501 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
1502 if (!(ppsidOwner||ppsidGroup||ppDacl||ppSacl||ppSecurityDescriptor)) return ERROR_INVALID_PARAMETER;
1504 /* If no descriptor, we have to check that there's a pointer for the requested information */
1505 if( !ppSecurityDescriptor && (
1506 ((SecurityInfo & OWNER_SECURITY_INFORMATION) && !ppsidOwner)
1507 || ((SecurityInfo & GROUP_SECURITY_INFORMATION) && !ppsidGroup)
1508 || ((SecurityInfo & DACL_SECURITY_INFORMATION) && !ppDacl)
1509 || ((SecurityInfo & SACL_SECURITY_INFORMATION) && !ppSacl) ))
1510 return ERROR_INVALID_PARAMETER;
1512 if (type == SE_SERVICE)
1514 if (!QueryServiceObjectSecurity( handle, SecurityInfo, NULL, 0, &size )
1515 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1516 return GetLastError();
1518 if (!(sd = LocalAlloc( 0, size ))) return ERROR_NOT_ENOUGH_MEMORY;
1520 if (!QueryServiceObjectSecurity( handle, SecurityInfo, sd, size, &size ))
1522 LocalFree(sd);
1523 return GetLastError();
1526 else
1528 HKEY key = NULL;
1530 if (type == SE_REGISTRY_KEY && (HandleToUlong(handle) >= HandleToUlong(HKEY_SPECIAL_ROOT_FIRST))
1531 && (HandleToUlong(handle) <= HandleToUlong(HKEY_SPECIAL_ROOT_LAST)))
1533 REGSAM access = READ_CONTROL;
1534 DWORD ret;
1536 if (SecurityInfo & SACL_SECURITY_INFORMATION)
1537 access |= ACCESS_SYSTEM_SECURITY;
1539 if ((ret = RegCreateKeyExW( handle, NULL, 0, NULL, 0, access, NULL, &key, NULL )))
1540 return ret;
1542 handle = key;
1545 status = NtQuerySecurityObject( handle, SecurityInfo, NULL, 0, &size );
1546 if (status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
1548 RegCloseKey( key );
1549 return RtlNtStatusToDosError( status );
1552 if (!(sd = LocalAlloc( 0, size )))
1554 RegCloseKey( key );
1555 return ERROR_NOT_ENOUGH_MEMORY;
1558 if ((status = NtQuerySecurityObject( handle, SecurityInfo, sd, size, &size )))
1560 RegCloseKey( key );
1561 LocalFree(sd);
1562 return RtlNtStatusToDosError( status );
1564 RegCloseKey( key );
1567 if (ppsidOwner)
1569 *ppsidOwner = NULL;
1570 GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
1572 if (ppsidGroup)
1574 *ppsidGroup = NULL;
1575 GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
1577 if (ppDacl)
1579 *ppDacl = NULL;
1580 GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
1582 if (ppSacl)
1584 *ppSacl = NULL;
1585 GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
1587 if (ppSecurityDescriptor)
1588 *ppSecurityDescriptor = sd;
1590 /* The security descriptor (sd) cannot be freed if ppSecurityDescriptor is
1591 * NULL, because native happily returns the SIDs and ACLs that are requested
1592 * in this case.
1595 return ERROR_SUCCESS;
1598 /******************************************************************************
1599 * GetSecurityInfoExA [ADVAPI32.@]
1601 DWORD WINAPI GetSecurityInfoExA(
1602 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
1603 SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
1604 LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
1605 PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
1608 FIXME("stub!\n");
1609 return ERROR_BAD_PROVIDER;
1612 /******************************************************************************
1613 * GetSecurityInfoExW [ADVAPI32.@]
1615 DWORD WINAPI GetSecurityInfoExW(
1616 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
1617 SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
1618 LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList,
1619 PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
1622 FIXME("stub!\n");
1623 return ERROR_BAD_PROVIDER;
1626 /******************************************************************************
1627 * BuildExplicitAccessWithNameA [ADVAPI32.@]
1629 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
1630 LPSTR pTrusteeName, DWORD AccessPermissions,
1631 ACCESS_MODE AccessMode, DWORD Inheritance )
1633 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_a(pTrusteeName),
1634 AccessPermissions, AccessMode, Inheritance);
1636 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1637 pExplicitAccess->grfAccessMode = AccessMode;
1638 pExplicitAccess->grfInheritance = Inheritance;
1640 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1641 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1642 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1643 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1644 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1647 /******************************************************************************
1648 * BuildExplicitAccessWithNameW [ADVAPI32.@]
1650 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
1651 LPWSTR pTrusteeName, DWORD AccessPermissions,
1652 ACCESS_MODE AccessMode, DWORD Inheritance )
1654 TRACE("%p %s 0x%08x 0x%08x 0x%08x\n", pExplicitAccess, debugstr_w(pTrusteeName),
1655 AccessPermissions, AccessMode, Inheritance);
1657 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1658 pExplicitAccess->grfAccessMode = AccessMode;
1659 pExplicitAccess->grfInheritance = Inheritance;
1661 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1662 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1663 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1664 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1665 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1668 /******************************************************************************
1669 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
1671 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
1672 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
1673 LPSTR InheritedObjectTypeName, LPSTR Name )
1675 DWORD ObjectsPresent = 0;
1677 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1678 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
1680 /* Fill the OBJECTS_AND_NAME structure */
1681 pObjName->ObjectType = ObjectType;
1682 if (ObjectTypeName != NULL)
1684 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1687 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1688 if (InheritedObjectTypeName != NULL)
1690 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1693 pObjName->ObjectsPresent = ObjectsPresent;
1694 pObjName->ptstrName = Name;
1696 /* Fill the TRUSTEE structure */
1697 pTrustee->pMultipleTrustee = NULL;
1698 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1699 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1700 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1701 pTrustee->ptstrName = (LPSTR)pObjName;
1704 /******************************************************************************
1705 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
1707 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
1708 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
1709 LPWSTR InheritedObjectTypeName, LPWSTR Name )
1711 DWORD ObjectsPresent = 0;
1713 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1714 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
1716 /* Fill the OBJECTS_AND_NAME structure */
1717 pObjName->ObjectType = ObjectType;
1718 if (ObjectTypeName != NULL)
1720 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1723 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1724 if (InheritedObjectTypeName != NULL)
1726 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1729 pObjName->ObjectsPresent = ObjectsPresent;
1730 pObjName->ptstrName = Name;
1732 /* Fill the TRUSTEE structure */
1733 pTrustee->pMultipleTrustee = NULL;
1734 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1735 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1736 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1737 pTrustee->ptstrName = (LPWSTR)pObjName;
1740 /******************************************************************************
1741 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
1743 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
1744 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
1746 DWORD ObjectsPresent = 0;
1748 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
1750 /* Fill the OBJECTS_AND_SID structure */
1751 if (pObjectGuid != NULL)
1753 pObjSid->ObjectTypeGuid = *pObjectGuid;
1754 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1756 else
1758 ZeroMemory(&pObjSid->ObjectTypeGuid,
1759 sizeof(GUID));
1762 if (pInheritedObjectGuid != NULL)
1764 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
1765 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1767 else
1769 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
1770 sizeof(GUID));
1773 pObjSid->ObjectsPresent = ObjectsPresent;
1774 pObjSid->pSid = pSid;
1776 /* Fill the TRUSTEE structure */
1777 pTrustee->pMultipleTrustee = NULL;
1778 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1779 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
1780 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1781 pTrustee->ptstrName = (LPSTR) pObjSid;
1784 /******************************************************************************
1785 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
1787 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
1788 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
1790 DWORD ObjectsPresent = 0;
1792 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
1794 /* Fill the OBJECTS_AND_SID structure */
1795 if (pObjectGuid != NULL)
1797 pObjSid->ObjectTypeGuid = *pObjectGuid;
1798 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1800 else
1802 ZeroMemory(&pObjSid->ObjectTypeGuid,
1803 sizeof(GUID));
1806 if (pInheritedObjectGuid != NULL)
1808 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
1809 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1811 else
1813 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
1814 sizeof(GUID));
1817 pObjSid->ObjectsPresent = ObjectsPresent;
1818 pObjSid->pSid = pSid;
1820 /* Fill the TRUSTEE structure */
1821 pTrustee->pMultipleTrustee = NULL;
1822 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1823 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
1824 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1825 pTrustee->ptstrName = (LPWSTR) pObjSid;
1828 /******************************************************************************
1829 * BuildTrusteeWithSidA [ADVAPI32.@]
1831 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
1833 TRACE("%p %p\n", pTrustee, pSid);
1835 pTrustee->pMultipleTrustee = NULL;
1836 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1837 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
1838 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1839 pTrustee->ptstrName = pSid;
1842 /******************************************************************************
1843 * BuildTrusteeWithSidW [ADVAPI32.@]
1845 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
1847 TRACE("%p %p\n", pTrustee, pSid);
1849 pTrustee->pMultipleTrustee = NULL;
1850 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1851 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
1852 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1853 pTrustee->ptstrName = pSid;
1856 /******************************************************************************
1857 * BuildTrusteeWithNameA [ADVAPI32.@]
1859 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
1861 TRACE("%p %s\n", pTrustee, debugstr_a(name) );
1863 pTrustee->pMultipleTrustee = NULL;
1864 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1865 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
1866 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1867 pTrustee->ptstrName = name;
1870 /******************************************************************************
1871 * BuildTrusteeWithNameW [ADVAPI32.@]
1873 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
1875 TRACE("%p %s\n", pTrustee, debugstr_w(name) );
1877 pTrustee->pMultipleTrustee = NULL;
1878 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1879 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
1880 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1881 pTrustee->ptstrName = name;
1884 /******************************************************************************
1885 * GetTrusteeFormA [ADVAPI32.@]
1887 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
1889 TRACE("(%p)\n", pTrustee);
1891 if (!pTrustee)
1892 return TRUSTEE_BAD_FORM;
1894 return pTrustee->TrusteeForm;
1897 /******************************************************************************
1898 * GetTrusteeFormW [ADVAPI32.@]
1900 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
1902 TRACE("(%p)\n", pTrustee);
1904 if (!pTrustee)
1905 return TRUSTEE_BAD_FORM;
1907 return pTrustee->TrusteeForm;
1910 /******************************************************************************
1911 * GetTrusteeNameA [ADVAPI32.@]
1913 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee)
1915 TRACE("(%p)\n", pTrustee);
1917 if (!pTrustee)
1918 return NULL;
1920 return pTrustee->ptstrName;
1923 /******************************************************************************
1924 * GetTrusteeNameW [ADVAPI32.@]
1926 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee)
1928 TRACE("(%p)\n", pTrustee);
1930 if (!pTrustee)
1931 return NULL;
1933 return pTrustee->ptstrName;
1936 /******************************************************************************
1937 * GetTrusteeTypeA [ADVAPI32.@]
1939 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee)
1941 TRACE("(%p)\n", pTrustee);
1943 if (!pTrustee)
1944 return TRUSTEE_IS_UNKNOWN;
1946 return pTrustee->TrusteeType;
1949 /******************************************************************************
1950 * GetTrusteeTypeW [ADVAPI32.@]
1952 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee)
1954 TRACE("(%p)\n", pTrustee);
1956 if (!pTrustee)
1957 return TRUSTEE_IS_UNKNOWN;
1959 return pTrustee->TrusteeType;
1962 static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR **ptrustee_nameW)
1964 switch (form)
1966 case TRUSTEE_IS_NAME:
1968 *ptrustee_nameW = strdupAW(trustee_nameA);
1969 return ERROR_SUCCESS;
1971 case TRUSTEE_IS_OBJECTS_AND_NAME:
1973 OBJECTS_AND_NAME_A *objA = (OBJECTS_AND_NAME_A *)trustee_nameA;
1974 OBJECTS_AND_NAME_W *objW = NULL;
1976 if (objA)
1978 if (!(objW = heap_alloc( sizeof(OBJECTS_AND_NAME_W) )))
1979 return ERROR_NOT_ENOUGH_MEMORY;
1981 objW->ObjectsPresent = objA->ObjectsPresent;
1982 objW->ObjectType = objA->ObjectType;
1983 objW->ObjectTypeName = strdupAW(objA->ObjectTypeName);
1984 objW->InheritedObjectTypeName = strdupAW(objA->InheritedObjectTypeName);
1985 objW->ptstrName = strdupAW(objA->ptstrName);
1988 *ptrustee_nameW = (WCHAR *)objW;
1989 return ERROR_SUCCESS;
1991 /* These forms do not require conversion. */
1992 case TRUSTEE_IS_SID:
1993 case TRUSTEE_IS_OBJECTS_AND_SID:
1994 *ptrustee_nameW = (WCHAR *)trustee_nameA;
1995 return ERROR_SUCCESS;
1996 default:
1997 return ERROR_INVALID_PARAMETER;
2001 static void free_trustee_name(TRUSTEE_FORM form, WCHAR *trustee_nameW)
2003 switch (form)
2005 case TRUSTEE_IS_NAME:
2006 heap_free( trustee_nameW );
2007 break;
2008 case TRUSTEE_IS_OBJECTS_AND_NAME:
2010 OBJECTS_AND_NAME_W *objW = (OBJECTS_AND_NAME_W *)trustee_nameW;
2012 if (objW)
2014 heap_free( objW->ptstrName );
2015 heap_free( objW->InheritedObjectTypeName );
2016 heap_free( objW->ObjectTypeName );
2017 heap_free( objW );
2020 break;
2022 /* Other forms did not require allocation, so no freeing is necessary. */
2023 default:
2024 break;
2028 static DWORD trustee_to_sid( DWORD nDestinationSidLength, PSID pDestinationSid, PTRUSTEEW pTrustee )
2030 if (pTrustee->MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
2032 WARN("bad multiple trustee operation %d\n", pTrustee->MultipleTrusteeOperation);
2033 return ERROR_INVALID_PARAMETER;
2036 switch (pTrustee->TrusteeForm)
2038 case TRUSTEE_IS_SID:
2039 if (!CopySid(nDestinationSidLength, pDestinationSid, pTrustee->ptstrName))
2041 WARN("bad sid %p\n", pTrustee->ptstrName);
2042 return ERROR_INVALID_PARAMETER;
2044 break;
2045 case TRUSTEE_IS_NAME:
2047 DWORD sid_size = nDestinationSidLength;
2048 DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
2049 SID_NAME_USE use;
2050 if (!wcscmp( pTrustee->ptstrName, L"CURRENT_USER" ))
2052 if (!lookup_user_account_name( pDestinationSid, &sid_size, NULL, &domain_size, &use ))
2054 return GetLastError();
2057 else if (!LookupAccountNameW(NULL, pTrustee->ptstrName, pDestinationSid, &sid_size, NULL, &domain_size, &use))
2059 WARN("bad user name %s\n", debugstr_w(pTrustee->ptstrName));
2060 return ERROR_INVALID_PARAMETER;
2062 break;
2064 case TRUSTEE_IS_OBJECTS_AND_SID:
2065 FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
2066 break;
2067 case TRUSTEE_IS_OBJECTS_AND_NAME:
2068 FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
2069 break;
2070 default:
2071 WARN("bad trustee form %d\n", pTrustee->TrusteeForm);
2072 return ERROR_INVALID_PARAMETER;
2075 return ERROR_SUCCESS;
2078 /******************************************************************************
2079 * SetEntriesInAclA [ADVAPI32.@]
2081 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
2082 PACL OldAcl, PACL* NewAcl )
2084 DWORD err = ERROR_SUCCESS;
2085 EXPLICIT_ACCESSW *pEntriesW;
2086 UINT alloc_index, free_index;
2088 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
2090 if (NewAcl)
2091 *NewAcl = NULL;
2093 if (!count && !OldAcl)
2094 return ERROR_SUCCESS;
2096 pEntriesW = heap_alloc( count * sizeof(EXPLICIT_ACCESSW) );
2097 if (!pEntriesW)
2098 return ERROR_NOT_ENOUGH_MEMORY;
2100 for (alloc_index = 0; alloc_index < count; ++alloc_index)
2102 pEntriesW[alloc_index].grfAccessPermissions = pEntries[alloc_index].grfAccessPermissions;
2103 pEntriesW[alloc_index].grfAccessMode = pEntries[alloc_index].grfAccessMode;
2104 pEntriesW[alloc_index].grfInheritance = pEntries[alloc_index].grfInheritance;
2105 pEntriesW[alloc_index].Trustee.pMultipleTrustee = NULL; /* currently not supported */
2106 pEntriesW[alloc_index].Trustee.MultipleTrusteeOperation = pEntries[alloc_index].Trustee.MultipleTrusteeOperation;
2107 pEntriesW[alloc_index].Trustee.TrusteeForm = pEntries[alloc_index].Trustee.TrusteeForm;
2108 pEntriesW[alloc_index].Trustee.TrusteeType = pEntries[alloc_index].Trustee.TrusteeType;
2110 err = trustee_name_A_to_W( pEntries[alloc_index].Trustee.TrusteeForm,
2111 pEntries[alloc_index].Trustee.ptstrName,
2112 &pEntriesW[alloc_index].Trustee.ptstrName );
2113 if (err != ERROR_SUCCESS)
2115 if (err == ERROR_INVALID_PARAMETER)
2116 WARN("bad trustee form %d for trustee %d\n",
2117 pEntries[alloc_index].Trustee.TrusteeForm, alloc_index);
2119 goto cleanup;
2123 err = SetEntriesInAclW( count, pEntriesW, OldAcl, NewAcl );
2125 cleanup:
2126 /* Free any previously allocated trustee name buffers, taking into account
2127 * a possible out-of-memory condition while building the EXPLICIT_ACCESSW
2128 * list. */
2129 for (free_index = 0; free_index < alloc_index; ++free_index)
2130 free_trustee_name( pEntriesW[free_index].Trustee.TrusteeForm, pEntriesW[free_index].Trustee.ptstrName );
2132 heap_free( pEntriesW );
2133 return err;
2136 /******************************************************************************
2137 * SetEntriesInAclW [ADVAPI32.@]
2139 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
2140 PACL OldAcl, PACL* NewAcl )
2142 ULONG i;
2143 PSID *ppsid;
2144 DWORD ret = ERROR_SUCCESS;
2145 DWORD acl_size = sizeof(ACL);
2146 NTSTATUS status;
2148 TRACE("%d %p %p %p\n", count, pEntries, OldAcl, NewAcl);
2150 if (NewAcl)
2151 *NewAcl = NULL;
2153 if (!count && !OldAcl)
2154 return ERROR_SUCCESS;
2156 /* allocate array of maximum sized sids allowed */
2157 ppsid = heap_alloc(count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
2158 if (!ppsid)
2159 return ERROR_OUTOFMEMORY;
2161 for (i = 0; i < count; i++)
2163 ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
2165 TRACE("[%d]:\n\tgrfAccessPermissions = 0x%x\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%x\n\t"
2166 "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
2167 "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
2168 pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
2169 pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
2170 pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
2171 pEntries[i].Trustee.ptstrName);
2173 ret = trustee_to_sid( FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]), ppsid[i], &pEntries[i].Trustee);
2174 if (ret)
2175 goto exit;
2177 /* Note: we overestimate the ACL size here as a tradeoff between
2178 * instructions (simplicity) and memory */
2179 switch (pEntries[i].grfAccessMode)
2181 case GRANT_ACCESS:
2182 case SET_ACCESS:
2183 acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
2184 break;
2185 case DENY_ACCESS:
2186 acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
2187 break;
2188 case SET_AUDIT_SUCCESS:
2189 case SET_AUDIT_FAILURE:
2190 acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
2191 break;
2192 case REVOKE_ACCESS:
2193 break;
2194 default:
2195 WARN("bad access mode %d for trustee %d\n", pEntries[i].grfAccessMode, i);
2196 ret = ERROR_INVALID_PARAMETER;
2197 goto exit;
2201 if (OldAcl)
2203 ACL_SIZE_INFORMATION size_info;
2205 status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
2206 if (status != STATUS_SUCCESS)
2208 ret = RtlNtStatusToDosError(status);
2209 goto exit;
2211 acl_size += size_info.AclBytesInUse - sizeof(ACL);
2214 *NewAcl = LocalAlloc(0, acl_size);
2215 if (!*NewAcl)
2217 ret = ERROR_OUTOFMEMORY;
2218 goto exit;
2221 status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
2222 if (status != STATUS_SUCCESS)
2224 ret = RtlNtStatusToDosError(status);
2225 goto exit;
2228 for (i = 0; i < count; i++)
2230 switch (pEntries[i].grfAccessMode)
2232 case GRANT_ACCESS:
2233 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
2234 pEntries[i].grfInheritance,
2235 pEntries[i].grfAccessPermissions,
2236 ppsid[i]);
2237 break;
2238 case SET_ACCESS:
2240 ULONG j;
2241 BOOL add = TRUE;
2242 if (OldAcl)
2244 for (j = 0; ; j++)
2246 const ACE_HEADER *existing_ace_header;
2247 status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
2248 if (status != STATUS_SUCCESS)
2249 break;
2250 if (pEntries[i].grfAccessMode == SET_ACCESS &&
2251 existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
2252 EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
2254 add = FALSE;
2255 break;
2259 if (add)
2260 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
2261 pEntries[i].grfInheritance,
2262 pEntries[i].grfAccessPermissions,
2263 ppsid[i]);
2264 break;
2266 case DENY_ACCESS:
2267 status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
2268 pEntries[i].grfInheritance,
2269 pEntries[i].grfAccessPermissions,
2270 ppsid[i]);
2271 break;
2272 case SET_AUDIT_SUCCESS:
2273 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
2274 pEntries[i].grfInheritance,
2275 pEntries[i].grfAccessPermissions,
2276 ppsid[i], TRUE, FALSE);
2277 break;
2278 case SET_AUDIT_FAILURE:
2279 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
2280 pEntries[i].grfInheritance,
2281 pEntries[i].grfAccessPermissions,
2282 ppsid[i], FALSE, TRUE);
2283 break;
2284 default:
2285 FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
2289 if (OldAcl)
2291 for (i = 0; ; i++)
2293 BOOL add = TRUE;
2294 ULONG j;
2295 const ACE_HEADER *old_ace_header;
2296 status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
2297 if (status != STATUS_SUCCESS) break;
2298 for (j = 0; j < count; j++)
2300 if (pEntries[j].grfAccessMode == SET_ACCESS &&
2301 old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
2302 EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
2304 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
2305 add = FALSE;
2306 break;
2308 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
2310 switch (old_ace_header->AceType)
2312 case ACCESS_ALLOWED_ACE_TYPE:
2313 if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
2314 add = FALSE;
2315 break;
2316 case ACCESS_DENIED_ACE_TYPE:
2317 /* REVOKE_ACCESS does not affect ACCESS_DENIED_ACE. */
2318 break;
2319 case SYSTEM_AUDIT_ACE_TYPE:
2320 if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
2321 add = FALSE;
2322 break;
2323 case SYSTEM_ALARM_ACE_TYPE:
2324 if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
2325 add = FALSE;
2326 break;
2327 default:
2328 FIXME("unhandled ace type %d\n", old_ace_header->AceType);
2331 if (!add)
2332 break;
2335 if (add)
2336 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
2337 if (status != STATUS_SUCCESS)
2339 WARN("RtlAddAce failed with error 0x%08x\n", status);
2340 ret = RtlNtStatusToDosError(status);
2341 break;
2346 exit:
2347 heap_free(ppsid);
2348 return ret;
2351 /******************************************************************************
2352 * SetNamedSecurityInfoA [ADVAPI32.@]
2354 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
2355 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
2356 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
2358 LPWSTR wstr;
2359 DWORD r;
2361 TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
2362 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
2364 wstr = strdupAW(pObjectName);
2365 r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
2366 psidGroup, pDacl, pSacl );
2368 heap_free( wstr );
2370 return r;
2373 /******************************************************************************
2374 * SetNamedSecurityInfoW [ADVAPI32.@]
2376 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
2377 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
2378 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
2380 DWORD access = 0;
2381 HANDLE handle;
2382 DWORD err;
2384 TRACE( "%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
2385 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
2387 if (!pObjectName) return ERROR_INVALID_PARAMETER;
2389 if (SecurityInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION))
2390 access |= WRITE_OWNER;
2391 if (SecurityInfo & DACL_SECURITY_INFORMATION)
2392 access |= WRITE_DAC;
2393 if (SecurityInfo & SACL_SECURITY_INFORMATION)
2394 access |= ACCESS_SYSTEM_SECURITY;
2396 switch (ObjectType)
2398 case SE_SERVICE:
2399 if (!(err = get_security_service( pObjectName, access, &handle )))
2401 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
2402 CloseServiceHandle( handle );
2404 break;
2405 case SE_REGISTRY_KEY:
2406 if (!(err = get_security_regkey( pObjectName, access, &handle )))
2408 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
2409 RegCloseKey( handle );
2411 break;
2412 case SE_FILE_OBJECT:
2413 if (SecurityInfo & DACL_SECURITY_INFORMATION)
2414 access |= READ_CONTROL;
2415 if (!(err = get_security_file( pObjectName, access, &handle )))
2417 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
2418 CloseHandle( handle );
2420 break;
2421 default:
2422 FIXME( "Object type %d is not currently supported.\n", ObjectType );
2423 return ERROR_SUCCESS;
2425 return err;
2428 /******************************************************************************
2429 * GetExplicitEntriesFromAclA [ADVAPI32.@]
2431 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
2432 PEXPLICIT_ACCESSA* pListOfExplicitEntries)
2434 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
2435 return ERROR_CALL_NOT_IMPLEMENTED;
2438 /******************************************************************************
2439 * GetExplicitEntriesFromAclW [ADVAPI32.@]
2441 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG count, PEXPLICIT_ACCESSW *list )
2443 ACL_SIZE_INFORMATION sizeinfo;
2444 EXPLICIT_ACCESSW *entries;
2445 MAX_SID *sid_entries;
2446 ACE_HEADER *ace;
2447 NTSTATUS status;
2448 int i;
2450 TRACE("%p %p %p\n",pacl, count, list);
2452 if (!count || !list)
2453 return ERROR_INVALID_PARAMETER;
2455 status = RtlQueryInformationAcl(pacl, &sizeinfo, sizeof(sizeinfo), AclSizeInformation);
2456 if (status) return RtlNtStatusToDosError(status);
2458 if (!sizeinfo.AceCount)
2460 *count = 0;
2461 *list = NULL;
2462 return ERROR_SUCCESS;
2465 entries = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, (sizeof(EXPLICIT_ACCESSW) + sizeof(MAX_SID)) * sizeinfo.AceCount);
2466 if (!entries) return ERROR_OUTOFMEMORY;
2467 sid_entries = (MAX_SID *)(entries + sizeinfo.AceCount);
2469 for (i = 0; i < sizeinfo.AceCount; i++)
2471 status = RtlGetAce(pacl, i, (void**)&ace);
2472 if (status) goto error;
2474 switch (ace->AceType)
2476 case ACCESS_ALLOWED_ACE_TYPE:
2478 ACCESS_ALLOWED_ACE *allow = (ACCESS_ALLOWED_ACE *)ace;
2479 entries[i].grfAccessMode = GRANT_ACCESS;
2480 entries[i].grfInheritance = ace->AceFlags;
2481 entries[i].grfAccessPermissions = allow->Mask;
2483 CopySid(sizeof(MAX_SID), (PSID)&sid_entries[i], (PSID)&allow->SidStart);
2484 entries[i].Trustee.pMultipleTrustee = NULL;
2485 entries[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2486 entries[i].Trustee.TrusteeForm = TRUSTEE_IS_SID;
2487 entries[i].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2488 entries[i].Trustee.ptstrName = (WCHAR *)&sid_entries[i];
2489 break;
2492 case ACCESS_DENIED_ACE_TYPE:
2494 ACCESS_DENIED_ACE *deny = (ACCESS_DENIED_ACE *)ace;
2495 entries[i].grfAccessMode = DENY_ACCESS;
2496 entries[i].grfInheritance = ace->AceFlags;
2497 entries[i].grfAccessPermissions = deny->Mask;
2499 CopySid(sizeof(MAX_SID), (PSID)&sid_entries[i], (PSID)&deny->SidStart);
2500 entries[i].Trustee.pMultipleTrustee = NULL;
2501 entries[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2502 entries[i].Trustee.TrusteeForm = TRUSTEE_IS_SID;
2503 entries[i].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2504 entries[i].Trustee.ptstrName = (WCHAR *)&sid_entries[i];
2505 break;
2508 default:
2509 FIXME("Unhandled ace type %d\n", ace->AceType);
2510 entries[i].grfAccessMode = NOT_USED_ACCESS;
2511 continue;
2515 *count = sizeinfo.AceCount;
2516 *list = entries;
2517 return ERROR_SUCCESS;
2519 error:
2520 LocalFree(entries);
2521 return RtlNtStatusToDosError(status);
2524 /******************************************************************************
2525 * GetAuditedPermissionsFromAclA [ADVAPI32.@]
2527 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
2528 PACCESS_MASK pFailedAuditRights)
2530 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
2531 return ERROR_CALL_NOT_IMPLEMENTED;
2535 /******************************************************************************
2536 * GetAuditedPermissionsFromAclW [ADVAPI32.@]
2538 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
2539 PACCESS_MASK pFailedAuditRights)
2541 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
2542 return ERROR_CALL_NOT_IMPLEMENTED;
2546 /******************************************************************************
2547 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
2549 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
2550 LPCSTR StringSecurityDescriptor,
2551 DWORD StringSDRevision,
2552 PSECURITY_DESCRIPTOR* SecurityDescriptor,
2553 PULONG SecurityDescriptorSize)
2555 BOOL ret;
2556 LPWSTR StringSecurityDescriptorW;
2558 TRACE("%s, %u, %p, %p\n", debugstr_a(StringSecurityDescriptor), StringSDRevision,
2559 SecurityDescriptor, SecurityDescriptorSize);
2561 if(!StringSecurityDescriptor)
2562 return FALSE;
2564 StringSecurityDescriptorW = strdupAW(StringSecurityDescriptor);
2565 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
2566 StringSDRevision, SecurityDescriptor,
2567 SecurityDescriptorSize);
2568 heap_free(StringSecurityDescriptorW);
2570 return ret;
2573 /******************************************************************************
2574 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
2576 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
2578 LPWSTR wstr;
2579 ULONG len;
2580 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
2582 int lenA;
2584 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
2585 *OutputString = heap_alloc(lenA);
2586 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
2587 LocalFree(wstr);
2589 if (OutputLen != NULL)
2590 *OutputLen = lenA;
2591 return TRUE;
2593 else
2595 *OutputString = NULL;
2596 if (OutputLen)
2597 *OutputLen = 0;
2598 return FALSE;
2602 /******************************************************************************
2603 * ConvertStringSidToSidA [ADVAPI32.@]
2605 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
2607 BOOL bret = FALSE;
2609 TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
2610 if (GetVersion() & 0x80000000)
2611 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2612 else if (!StringSid || !Sid)
2613 SetLastError(ERROR_INVALID_PARAMETER);
2614 else
2616 WCHAR *wStringSid = strdupAW(StringSid);
2617 bret = ConvertStringSidToSidW(wStringSid, Sid);
2618 heap_free(wStringSid);
2620 return bret;
2623 /******************************************************************************
2624 * ConvertSidToStringSidA [ADVAPI32.@]
2626 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
2628 LPWSTR wstr = NULL;
2629 LPSTR str;
2630 UINT len;
2632 TRACE("%p %p\n", pSid, pstr );
2634 if( !ConvertSidToStringSidW( pSid, &wstr ) )
2635 return FALSE;
2637 len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
2638 str = LocalAlloc( 0, len );
2639 WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
2640 LocalFree( wstr );
2642 *pstr = str;
2644 return TRUE;
2647 /******************************************************************************
2648 * CreateProcessWithLogonW
2650 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
2651 LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
2652 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
2654 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
2655 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
2656 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
2657 lpStartupInfo, lpProcessInformation);
2659 return FALSE;
2662 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
2663 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
2664 PROCESS_INFORMATION *process_information )
2666 FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token,
2667 logon_flags, debugstr_w(application_name), debugstr_w(command_line),
2668 creation_flags, environment, debugstr_w(current_directory),
2669 startup_info, process_information);
2671 /* FIXME: check if handles should be inherited */
2672 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
2673 current_directory, startup_info, process_information );
2676 /******************************************************************************
2677 * GetNamedSecurityInfoA [ADVAPI32.@]
2679 DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName,
2680 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
2681 PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
2682 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
2684 LPWSTR wstr;
2685 DWORD r;
2687 TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo,
2688 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
2690 wstr = strdupAW(pObjectName);
2691 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
2692 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
2694 heap_free( wstr );
2696 return r;
2699 /******************************************************************************
2700 * GetNamedSecurityInfoW [ADVAPI32.@]
2702 DWORD WINAPI GetNamedSecurityInfoW( LPWSTR name, SE_OBJECT_TYPE type,
2703 SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
2704 PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
2706 DWORD access = 0;
2707 HANDLE handle;
2708 DWORD err;
2710 TRACE( "%s %d %d %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
2711 group, dacl, sacl, descriptor );
2713 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
2714 if (!name || !(owner||group||dacl||sacl||descriptor) ) return ERROR_INVALID_PARAMETER;
2716 /* If no descriptor, we have to check that there's a pointer for the requested information */
2717 if( !descriptor && (
2718 ((info & OWNER_SECURITY_INFORMATION) && !owner)
2719 || ((info & GROUP_SECURITY_INFORMATION) && !group)
2720 || ((info & DACL_SECURITY_INFORMATION) && !dacl)
2721 || ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
2722 return ERROR_INVALID_PARAMETER;
2724 if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION))
2725 access |= READ_CONTROL;
2726 if (info & SACL_SECURITY_INFORMATION)
2727 access |= ACCESS_SYSTEM_SECURITY;
2729 switch (type)
2731 case SE_SERVICE:
2732 if (!(err = get_security_service( name, access, &handle )))
2734 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
2735 CloseServiceHandle( handle );
2737 break;
2738 case SE_REGISTRY_KEY:
2739 if (!(err = get_security_regkey( name, access, &handle )))
2741 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
2742 RegCloseKey( handle );
2744 break;
2745 case SE_FILE_OBJECT:
2746 if (!(err = get_security_file( name, access, &handle )))
2748 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
2749 CloseHandle( handle );
2751 break;
2752 default:
2753 FIXME( "Object type %d is not currently supported.\n", type );
2754 if (owner) *owner = NULL;
2755 if (group) *group = NULL;
2756 if (dacl) *dacl = NULL;
2757 if (sacl) *sacl = NULL;
2758 if (descriptor) *descriptor = NULL;
2759 return ERROR_SUCCESS;
2761 return err;
2764 /******************************************************************************
2765 * GetNamedSecurityInfoExW [ADVAPI32.@]
2767 DWORD WINAPI GetNamedSecurityInfoExW( LPCWSTR object, SE_OBJECT_TYPE type,
2768 SECURITY_INFORMATION info, LPCWSTR provider, LPCWSTR property,
2769 PACTRL_ACCESSW* access_list, PACTRL_AUDITW* audit_list, LPWSTR* owner, LPWSTR* group )
2771 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_w(object), type, info,
2772 debugstr_w(provider), debugstr_w(property), access_list, audit_list, owner, group);
2773 return ERROR_CALL_NOT_IMPLEMENTED;
2776 /******************************************************************************
2777 * GetNamedSecurityInfoExA [ADVAPI32.@]
2779 DWORD WINAPI GetNamedSecurityInfoExA( LPCSTR object, SE_OBJECT_TYPE type,
2780 SECURITY_INFORMATION info, LPCSTR provider, LPCSTR property,
2781 PACTRL_ACCESSA* access_list, PACTRL_AUDITA* audit_list, LPSTR* owner, LPSTR* group )
2783 FIXME("(%s, %d, %d, %s, %s, %p, %p, %p, %p) stub\n", debugstr_a(object), type, info,
2784 debugstr_a(provider), debugstr_a(property), access_list, audit_list, owner, group);
2785 return ERROR_CALL_NOT_IMPLEMENTED;
2788 /******************************************************************************
2789 * DecryptFileW [ADVAPI32.@]
2791 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
2793 FIXME("(%s, %08x): stub\n", debugstr_w(lpFileName), dwReserved);
2794 return TRUE;
2797 /******************************************************************************
2798 * DecryptFileA [ADVAPI32.@]
2800 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
2802 FIXME("(%s, %08x): stub\n", debugstr_a(lpFileName), dwReserved);
2803 return TRUE;
2806 /******************************************************************************
2807 * EncryptFileW [ADVAPI32.@]
2809 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
2811 FIXME("(%s): stub\n", debugstr_w(lpFileName));
2812 return TRUE;
2815 /******************************************************************************
2816 * EncryptFileA [ADVAPI32.@]
2818 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
2820 FIXME("(%s): stub\n", debugstr_a(lpFileName));
2821 return TRUE;
2824 /******************************************************************************
2825 * FileEncryptionStatusW [ADVAPI32.@]
2827 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
2829 FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
2830 if (!lpStatus)
2831 return FALSE;
2832 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
2833 return TRUE;
2836 /******************************************************************************
2837 * FileEncryptionStatusA [ADVAPI32.@]
2839 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
2841 FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
2842 if (!lpStatus)
2843 return FALSE;
2844 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
2845 return TRUE;
2848 static NTSTATUS combine_dacls(ACL *parent, ACL *child, ACL **result)
2850 NTSTATUS status;
2851 ACL *combined;
2852 int i;
2854 /* initialize a combined DACL containing both inherited and new ACEs */
2855 combined = heap_alloc_zero(child->AclSize+parent->AclSize);
2856 if (!combined)
2857 return STATUS_NO_MEMORY;
2859 status = RtlCreateAcl(combined, parent->AclSize+child->AclSize, ACL_REVISION);
2860 if (status != STATUS_SUCCESS)
2862 heap_free(combined);
2863 return status;
2866 /* copy the new ACEs */
2867 for (i=0; i<child->AceCount; i++)
2869 ACE_HEADER *ace;
2871 if (!GetAce(child, i, (void*)&ace))
2872 continue;
2873 if (!AddAce(combined, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
2874 WARN("error adding new ACE\n");
2877 /* copy the inherited ACEs */
2878 for (i=0; i<parent->AceCount; i++)
2880 ACE_HEADER *ace;
2882 if (!GetAce(parent, i, (void*)&ace))
2883 continue;
2884 if (!(ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)))
2885 continue;
2886 if ((ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) !=
2887 (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE))
2889 FIXME("unsupported flags: %x\n", ace->AceFlags);
2890 continue;
2893 if (ace->AceFlags & NO_PROPAGATE_INHERIT_ACE)
2894 ace->AceFlags &= ~(OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE|NO_PROPAGATE_INHERIT_ACE);
2895 ace->AceFlags &= ~INHERIT_ONLY_ACE;
2896 ace->AceFlags |= INHERITED_ACE;
2898 if (!AddAce(combined, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
2899 WARN("error adding inherited ACE\n");
2902 *result = combined;
2903 return STATUS_SUCCESS;
2906 /******************************************************************************
2907 * SetSecurityInfo [ADVAPI32.@]
2909 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
2910 SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
2911 PSID psidGroup, PACL pDacl, PACL pSacl)
2913 SECURITY_DESCRIPTOR sd;
2914 PACL dacl = pDacl;
2915 NTSTATUS status;
2917 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
2918 return ERROR_INVALID_SECURITY_DESCR;
2920 if (SecurityInfo & OWNER_SECURITY_INFORMATION)
2921 SetSecurityDescriptorOwner(&sd, psidOwner, FALSE);
2922 if (SecurityInfo & GROUP_SECURITY_INFORMATION)
2923 SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
2924 if (SecurityInfo & DACL_SECURITY_INFORMATION)
2926 if (ObjectType == SE_FILE_OBJECT && pDacl)
2928 SECURITY_DESCRIPTOR_CONTROL control;
2929 PSECURITY_DESCRIPTOR psd;
2930 OBJECT_NAME_INFORMATION *name_info;
2931 DWORD size, rev;
2933 status = NtQuerySecurityObject(handle, SecurityInfo, NULL, 0, &size);
2934 if (status != STATUS_BUFFER_TOO_SMALL)
2935 return RtlNtStatusToDosError(status);
2937 psd = heap_alloc(size);
2938 if (!psd)
2939 return ERROR_NOT_ENOUGH_MEMORY;
2941 status = NtQuerySecurityObject(handle, SecurityInfo, psd, size, &size);
2942 if (status)
2944 heap_free(psd);
2945 return RtlNtStatusToDosError(status);
2948 status = RtlGetControlSecurityDescriptor(psd, &control, &rev);
2949 heap_free(psd);
2950 if (status)
2951 return RtlNtStatusToDosError(status);
2952 /* TODO: copy some control flags to new sd */
2954 /* inherit parent directory DACL */
2955 if (!(control & SE_DACL_PROTECTED))
2957 status = NtQueryObject(handle, ObjectNameInformation, NULL, 0, &size);
2958 if (status != STATUS_INFO_LENGTH_MISMATCH)
2959 return RtlNtStatusToDosError(status);
2961 name_info = heap_alloc(size);
2962 if (!name_info)
2963 return ERROR_NOT_ENOUGH_MEMORY;
2965 status = NtQueryObject(handle, ObjectNameInformation, name_info, size, NULL);
2966 if (status)
2968 heap_free(name_info);
2969 return RtlNtStatusToDosError(status);
2972 for (name_info->Name.Length-=2; name_info->Name.Length>0; name_info->Name.Length-=2)
2973 if (name_info->Name.Buffer[name_info->Name.Length/2-1]=='\\' ||
2974 name_info->Name.Buffer[name_info->Name.Length/2-1]=='/')
2975 break;
2976 if (name_info->Name.Length)
2978 OBJECT_ATTRIBUTES attr;
2979 IO_STATUS_BLOCK io;
2980 HANDLE parent;
2981 PSECURITY_DESCRIPTOR parent_sd;
2982 ACL *parent_dacl;
2983 DWORD err = ERROR_ACCESS_DENIED;
2985 name_info->Name.Buffer[name_info->Name.Length/2] = 0;
2987 attr.Length = sizeof(attr);
2988 attr.RootDirectory = 0;
2989 attr.Attributes = 0;
2990 attr.ObjectName = &name_info->Name;
2991 attr.SecurityDescriptor = NULL;
2992 status = NtOpenFile(&parent, READ_CONTROL|SYNCHRONIZE, &attr, &io,
2993 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
2994 FILE_OPEN_FOR_BACKUP_INTENT);
2995 heap_free(name_info);
2996 if (!status)
2998 err = GetSecurityInfo(parent, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
2999 NULL, NULL, &parent_dacl, NULL, &parent_sd);
3000 CloseHandle(parent);
3003 if (!err)
3005 status = combine_dacls(parent_dacl, pDacl, &dacl);
3006 LocalFree(parent_sd);
3007 if (status != STATUS_SUCCESS)
3008 return RtlNtStatusToDosError(status);
3011 else
3012 heap_free(name_info);
3016 SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE);
3018 if (SecurityInfo & SACL_SECURITY_INFORMATION)
3019 SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
3021 switch (ObjectType)
3023 case SE_SERVICE:
3024 FIXME("stub: Service objects are not supported at this time.\n");
3025 status = STATUS_SUCCESS; /* Implement SetServiceObjectSecurity */
3026 break;
3027 default:
3028 status = NtSetSecurityObject(handle, SecurityInfo, &sd);
3029 break;
3031 if (dacl != pDacl)
3032 heap_free(dacl);
3033 return RtlNtStatusToDosError(status);
3036 /******************************************************************************
3037 * SaferCreateLevel [ADVAPI32.@]
3039 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
3040 SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
3042 FIXME("(%u, %x, %u, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
3044 *LevelHandle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
3045 return TRUE;
3048 /******************************************************************************
3049 * SaferComputeTokenFromLevel [ADVAPI32.@]
3051 BOOL WINAPI SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE handle, HANDLE token, PHANDLE access_token,
3052 DWORD flags, LPVOID reserved)
3054 FIXME("(%p, %p, %p, %x, %p) stub\n", handle, token, access_token, flags, reserved);
3056 *access_token = (flags & SAFER_TOKEN_NULL_IF_EQUAL) ? NULL : (HANDLE)0xdeadbeef;
3057 return TRUE;
3060 /******************************************************************************
3061 * SaferCloseLevel [ADVAPI32.@]
3063 BOOL WINAPI SaferCloseLevel(SAFER_LEVEL_HANDLE handle)
3065 FIXME("(%p) stub\n", handle);
3066 return TRUE;
3069 /******************************************************************************
3070 * TreeResetNamedSecurityInfoW [ADVAPI32.@]
3072 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
3073 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3074 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
3075 BOOL KeepExplicit, FN_PROGRESS fnProgress,
3076 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
3078 FIXME("(%s, %i, %i, %p, %p, %p, %p, %i, %p, %i, %p) stub\n",
3079 debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
3080 pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
3082 return ERROR_SUCCESS;
3085 /******************************************************************************
3086 * SaferGetPolicyInformation [ADVAPI32.@]
3088 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
3089 PVOID buffer, PDWORD required, LPVOID lpReserved)
3091 FIXME("(%u %u %u %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
3092 return FALSE;
3095 /******************************************************************************
3096 * SaferIdentifyLevel [ADVAPI32.@]
3098 BOOL WINAPI SaferIdentifyLevel(DWORD count, SAFER_CODE_PROPERTIES *properties, SAFER_LEVEL_HANDLE *handle,
3099 void *reserved)
3101 FIXME("(%u %p %p %p) stub\n", count, properties, handle, reserved);
3102 *handle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
3103 return TRUE;
3106 /******************************************************************************
3107 * SaferSetLevelInformation [ADVAPI32.@]
3109 BOOL WINAPI SaferSetLevelInformation(SAFER_LEVEL_HANDLE handle, SAFER_OBJECT_INFO_CLASS infotype,
3110 LPVOID buffer, DWORD size)
3112 FIXME("(%p %u %p %u) stub\n", handle, infotype, buffer, size);
3113 return FALSE;
3116 /******************************************************************************
3117 * LookupSecurityDescriptorPartsA [ADVAPI32.@]
3119 DWORD WINAPI LookupSecurityDescriptorPartsA(TRUSTEEA *owner, TRUSTEEA *group, ULONG *access_count,
3120 EXPLICIT_ACCESSA *access_list, ULONG *audit_count,
3121 EXPLICIT_ACCESSA *audit_list, SECURITY_DESCRIPTOR *descriptor)
3123 FIXME("(%p %p %p %p %p %p %p) stub\n", owner, group, access_count,
3124 access_list, audit_count, audit_list, descriptor);
3125 return ERROR_CALL_NOT_IMPLEMENTED;
3128 /******************************************************************************
3129 * LookupSecurityDescriptorPartsW [ADVAPI32.@]
3131 DWORD WINAPI LookupSecurityDescriptorPartsW(TRUSTEEW *owner, TRUSTEEW *group, ULONG *access_count,
3132 EXPLICIT_ACCESSW *access_list, ULONG *audit_count,
3133 EXPLICIT_ACCESSW *audit_list, SECURITY_DESCRIPTOR *descriptor)
3135 FIXME("(%p %p %p %p %p %p %p) stub\n", owner, group, access_count,
3136 access_list, audit_count, audit_list, descriptor);
3137 return ERROR_CALL_NOT_IMPLEMENTED;