ntdll: Add ACTCTX field limit checks to RtlCreateActivationContext().
[wine.git] / dlls / advapi32 / security.c
blob8d0c6977d72a0f040ae07732c9124e8d3eda2f4d
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-%lu", psid->Revision, auth,
132 psid->SubAuthority[0]);
133 case 2:
134 return wine_dbg_sprintf("S-%d-%d-%lu-%lu", psid->Revision, auth,
135 psid->SubAuthority[0], psid->SubAuthority[1]);
136 case 3:
137 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu", psid->Revision, auth,
138 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
139 case 4:
140 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu", 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-%lu-%lu-%lu-%lu-%lu", 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-%lu-%lu-%lu-%lu-%lu-%lu", 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-%lu-%lu-%lu-%lu-%lu-%lu-%lu", 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-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu", 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 DWORD get_security_service( const WCHAR *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 DWORD get_security_regkey( const WCHAR *full_key_name, DWORD access, HANDLE *key )
204 const WCHAR *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 = malloc(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 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,%ld,%p,%ld,%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,%ld,%p,%ld,%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 -> %08lx-%08lx\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 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 %p %p %p - stub\n", debugstr_w(lpSystemName), debugstr_w(lpName),
578 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 = malloc(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 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 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 = malloc( accountSizeW * sizeof(WCHAR) );
758 if (domain)
759 domainW = malloc( 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 free( systemW );
785 free( accountW );
786 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(%lu),%p,%p(%lu),%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 = malloc(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 = malloc(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 free(account_name);
972 free(computer_name);
973 if (status) *name_use = use;
974 return status;
977 free(account_name);
978 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 free( name );
1014 return r;
1017 /******************************************************************************
1018 * QueryWindows31FilesMigration [ADVAPI32.@]
1020 * PARAMS
1021 * x1 []
1023 BOOL WINAPI
1024 QueryWindows31FilesMigration( DWORD x1 )
1026 FIXME("(%ld):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%08lx,0x%08lx,0x%08lx,0x%08lx):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 = malloc(*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 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 = malloc( 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 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 = malloc( 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 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,%08lx,%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%08lx,0x%08lx,%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%08lx,%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;
1500 HKEY key = NULL;
1502 if (!handle)
1503 return ERROR_INVALID_HANDLE;
1505 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
1506 if (!(ppsidOwner||ppsidGroup||ppDacl||ppSacl||ppSecurityDescriptor)) return ERROR_INVALID_PARAMETER;
1508 /* If no descriptor, we have to check that there's a pointer for the requested information */
1509 if( !ppSecurityDescriptor && (
1510 ((SecurityInfo & OWNER_SECURITY_INFORMATION) && !ppsidOwner)
1511 || ((SecurityInfo & GROUP_SECURITY_INFORMATION) && !ppsidGroup)
1512 || ((SecurityInfo & DACL_SECURITY_INFORMATION) && !ppDacl)
1513 || ((SecurityInfo & SACL_SECURITY_INFORMATION) && !ppSacl) ))
1514 return ERROR_INVALID_PARAMETER;
1516 switch (type)
1518 case SE_SERVICE:
1519 if (!QueryServiceObjectSecurity( handle, SecurityInfo, NULL, 0, &size )
1520 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1521 return GetLastError();
1523 if (!(sd = LocalAlloc( 0, size ))) return ERROR_NOT_ENOUGH_MEMORY;
1525 if (!QueryServiceObjectSecurity( handle, SecurityInfo, sd, size, &size ))
1527 LocalFree(sd);
1528 return GetLastError();
1530 break;
1532 case SE_WINDOW_OBJECT:
1533 if (!GetUserObjectSecurity( handle, &SecurityInfo, NULL, 0, &size )
1534 && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1535 return GetLastError();
1537 if (!(sd = LocalAlloc( 0, size )))
1538 return ERROR_NOT_ENOUGH_MEMORY;
1540 if (!GetUserObjectSecurity( handle, &SecurityInfo, sd, size, &size ))
1542 LocalFree( sd );
1543 return GetLastError();
1545 break;
1547 case SE_KERNEL_OBJECT:
1548 case SE_FILE_OBJECT:
1549 case SE_WMIGUID_OBJECT:
1550 case SE_REGISTRY_KEY:
1551 if (type == SE_REGISTRY_KEY && (HandleToUlong(handle) >= HandleToUlong(HKEY_SPECIAL_ROOT_FIRST))
1552 && (HandleToUlong(handle) <= HandleToUlong(HKEY_SPECIAL_ROOT_LAST)))
1554 REGSAM access = READ_CONTROL;
1555 DWORD ret;
1557 if (SecurityInfo & SACL_SECURITY_INFORMATION)
1558 access |= ACCESS_SYSTEM_SECURITY;
1560 if ((ret = RegCreateKeyExW( handle, NULL, 0, NULL, 0, access, NULL, &key, NULL )))
1561 return ret;
1563 handle = key;
1566 status = NtQuerySecurityObject( handle, SecurityInfo, NULL, 0, &size );
1567 if (status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
1569 RegCloseKey( key );
1570 return RtlNtStatusToDosError( status );
1573 if (!(sd = LocalAlloc( 0, size )))
1575 RegCloseKey( key );
1576 return ERROR_NOT_ENOUGH_MEMORY;
1579 if ((status = NtQuerySecurityObject( handle, SecurityInfo, sd, size, &size )))
1581 RegCloseKey( key );
1582 LocalFree(sd);
1583 return RtlNtStatusToDosError( status );
1585 RegCloseKey( key );
1586 break;
1588 default:
1589 FIXME("unimplemented type %u\n", type);
1590 return ERROR_CALL_NOT_IMPLEMENTED;
1593 if (ppsidOwner)
1595 *ppsidOwner = NULL;
1596 GetSecurityDescriptorOwner(sd, ppsidOwner, &defaulted);
1598 if (ppsidGroup)
1600 *ppsidGroup = NULL;
1601 GetSecurityDescriptorGroup(sd, ppsidGroup, &defaulted);
1603 if (ppDacl)
1605 *ppDacl = NULL;
1606 GetSecurityDescriptorDacl(sd, &present, ppDacl, &defaulted);
1608 if (ppSacl)
1610 *ppSacl = NULL;
1611 GetSecurityDescriptorSacl(sd, &present, ppSacl, &defaulted);
1613 if (ppSecurityDescriptor)
1614 *ppSecurityDescriptor = sd;
1616 /* The security descriptor (sd) cannot be freed if ppSecurityDescriptor is
1617 * NULL, because native happily returns the SIDs and ACLs that are requested
1618 * in this case.
1621 return ERROR_SUCCESS;
1624 /******************************************************************************
1625 * GetSecurityInfoExA [ADVAPI32.@]
1627 DWORD WINAPI GetSecurityInfoExA(
1628 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
1629 SECURITY_INFORMATION SecurityInfo, LPCSTR lpProvider,
1630 LPCSTR lpProperty, PACTRL_ACCESSA *ppAccessList,
1631 PACTRL_AUDITA *ppAuditList, LPSTR *lppOwner, LPSTR *lppGroup
1634 FIXME("stub!\n");
1635 return ERROR_BAD_PROVIDER;
1638 /******************************************************************************
1639 * GetSecurityInfoExW [ADVAPI32.@]
1641 DWORD WINAPI GetSecurityInfoExW(
1642 HANDLE hObject, SE_OBJECT_TYPE ObjectType,
1643 SECURITY_INFORMATION SecurityInfo, LPCWSTR lpProvider,
1644 LPCWSTR lpProperty, PACTRL_ACCESSW *ppAccessList,
1645 PACTRL_AUDITW *ppAuditList, LPWSTR *lppOwner, LPWSTR *lppGroup
1648 FIXME("stub!\n");
1649 return ERROR_BAD_PROVIDER;
1652 /******************************************************************************
1653 * BuildExplicitAccessWithNameA [ADVAPI32.@]
1655 VOID WINAPI BuildExplicitAccessWithNameA( PEXPLICIT_ACCESSA pExplicitAccess,
1656 LPSTR pTrusteeName, DWORD AccessPermissions,
1657 ACCESS_MODE AccessMode, DWORD Inheritance )
1659 TRACE("%p %s 0x%08lx 0x%08x 0x%08lx\n", pExplicitAccess, debugstr_a(pTrusteeName),
1660 AccessPermissions, AccessMode, Inheritance);
1662 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1663 pExplicitAccess->grfAccessMode = AccessMode;
1664 pExplicitAccess->grfInheritance = Inheritance;
1666 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1667 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1668 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1669 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1670 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1673 /******************************************************************************
1674 * BuildExplicitAccessWithNameW [ADVAPI32.@]
1676 VOID WINAPI BuildExplicitAccessWithNameW( PEXPLICIT_ACCESSW pExplicitAccess,
1677 LPWSTR pTrusteeName, DWORD AccessPermissions,
1678 ACCESS_MODE AccessMode, DWORD Inheritance )
1680 TRACE("%p %s 0x%08lx 0x%08x 0x%08lx\n", pExplicitAccess, debugstr_w(pTrusteeName),
1681 AccessPermissions, AccessMode, Inheritance);
1683 pExplicitAccess->grfAccessPermissions = AccessPermissions;
1684 pExplicitAccess->grfAccessMode = AccessMode;
1685 pExplicitAccess->grfInheritance = Inheritance;
1687 pExplicitAccess->Trustee.pMultipleTrustee = NULL;
1688 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1689 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME;
1690 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1691 pExplicitAccess->Trustee.ptstrName = pTrusteeName;
1694 /******************************************************************************
1695 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@]
1697 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName,
1698 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName,
1699 LPSTR InheritedObjectTypeName, LPSTR Name )
1701 DWORD ObjectsPresent = 0;
1703 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1704 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name));
1706 /* Fill the OBJECTS_AND_NAME structure */
1707 pObjName->ObjectType = ObjectType;
1708 if (ObjectTypeName != NULL)
1710 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1713 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1714 if (InheritedObjectTypeName != NULL)
1716 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1719 pObjName->ObjectsPresent = ObjectsPresent;
1720 pObjName->ptstrName = Name;
1722 /* Fill the TRUSTEE structure */
1723 pTrustee->pMultipleTrustee = NULL;
1724 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1725 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1726 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1727 pTrustee->ptstrName = (LPSTR)pObjName;
1730 /******************************************************************************
1731 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@]
1733 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName,
1734 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName,
1735 LPWSTR InheritedObjectTypeName, LPWSTR Name )
1737 DWORD ObjectsPresent = 0;
1739 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName,
1740 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name));
1742 /* Fill the OBJECTS_AND_NAME structure */
1743 pObjName->ObjectType = ObjectType;
1744 if (ObjectTypeName != NULL)
1746 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1749 pObjName->InheritedObjectTypeName = InheritedObjectTypeName;
1750 if (InheritedObjectTypeName != NULL)
1752 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1755 pObjName->ObjectsPresent = ObjectsPresent;
1756 pObjName->ptstrName = Name;
1758 /* Fill the TRUSTEE structure */
1759 pTrustee->pMultipleTrustee = NULL;
1760 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1761 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME;
1762 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1763 pTrustee->ptstrName = (LPWSTR)pObjName;
1766 /******************************************************************************
1767 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@]
1769 VOID WINAPI BuildTrusteeWithObjectsAndSidA( PTRUSTEEA pTrustee, POBJECTS_AND_SID pObjSid,
1770 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
1772 DWORD ObjectsPresent = 0;
1774 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
1776 /* Fill the OBJECTS_AND_SID structure */
1777 if (pObjectGuid != NULL)
1779 pObjSid->ObjectTypeGuid = *pObjectGuid;
1780 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1782 else
1784 ZeroMemory(&pObjSid->ObjectTypeGuid,
1785 sizeof(GUID));
1788 if (pInheritedObjectGuid != NULL)
1790 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
1791 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1793 else
1795 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
1796 sizeof(GUID));
1799 pObjSid->ObjectsPresent = ObjectsPresent;
1800 pObjSid->pSid = pSid;
1802 /* Fill the TRUSTEE structure */
1803 pTrustee->pMultipleTrustee = NULL;
1804 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1805 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
1806 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1807 pTrustee->ptstrName = (LPSTR) pObjSid;
1810 /******************************************************************************
1811 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@]
1813 VOID WINAPI BuildTrusteeWithObjectsAndSidW( PTRUSTEEW pTrustee, POBJECTS_AND_SID pObjSid,
1814 GUID* pObjectGuid, GUID* pInheritedObjectGuid, PSID pSid )
1816 DWORD ObjectsPresent = 0;
1818 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid);
1820 /* Fill the OBJECTS_AND_SID structure */
1821 if (pObjectGuid != NULL)
1823 pObjSid->ObjectTypeGuid = *pObjectGuid;
1824 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT;
1826 else
1828 ZeroMemory(&pObjSid->ObjectTypeGuid,
1829 sizeof(GUID));
1832 if (pInheritedObjectGuid != NULL)
1834 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid;
1835 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
1837 else
1839 ZeroMemory(&pObjSid->InheritedObjectTypeGuid,
1840 sizeof(GUID));
1843 pObjSid->ObjectsPresent = ObjectsPresent;
1844 pObjSid->pSid = pSid;
1846 /* Fill the TRUSTEE structure */
1847 pTrustee->pMultipleTrustee = NULL;
1848 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1849 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID;
1850 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1851 pTrustee->ptstrName = (LPWSTR) pObjSid;
1854 /******************************************************************************
1855 * BuildTrusteeWithSidA [ADVAPI32.@]
1857 VOID WINAPI BuildTrusteeWithSidA(PTRUSTEEA pTrustee, PSID pSid)
1859 TRACE("%p %p\n", pTrustee, pSid);
1861 pTrustee->pMultipleTrustee = NULL;
1862 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1863 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
1864 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1865 pTrustee->ptstrName = pSid;
1868 /******************************************************************************
1869 * BuildTrusteeWithSidW [ADVAPI32.@]
1871 VOID WINAPI BuildTrusteeWithSidW(PTRUSTEEW pTrustee, PSID pSid)
1873 TRACE("%p %p\n", pTrustee, pSid);
1875 pTrustee->pMultipleTrustee = NULL;
1876 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1877 pTrustee->TrusteeForm = TRUSTEE_IS_SID;
1878 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1879 pTrustee->ptstrName = pSid;
1882 /******************************************************************************
1883 * BuildTrusteeWithNameA [ADVAPI32.@]
1885 VOID WINAPI BuildTrusteeWithNameA(PTRUSTEEA pTrustee, LPSTR name)
1887 TRACE("%p %s\n", pTrustee, debugstr_a(name) );
1889 pTrustee->pMultipleTrustee = NULL;
1890 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1891 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
1892 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1893 pTrustee->ptstrName = name;
1896 /******************************************************************************
1897 * BuildTrusteeWithNameW [ADVAPI32.@]
1899 VOID WINAPI BuildTrusteeWithNameW(PTRUSTEEW pTrustee, LPWSTR name)
1901 TRACE("%p %s\n", pTrustee, debugstr_w(name) );
1903 pTrustee->pMultipleTrustee = NULL;
1904 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
1905 pTrustee->TrusteeForm = TRUSTEE_IS_NAME;
1906 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN;
1907 pTrustee->ptstrName = name;
1910 /******************************************************************************
1911 * GetTrusteeFormA [ADVAPI32.@]
1913 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee)
1915 TRACE("(%p)\n", pTrustee);
1917 if (!pTrustee)
1918 return TRUSTEE_BAD_FORM;
1920 return pTrustee->TrusteeForm;
1923 /******************************************************************************
1924 * GetTrusteeFormW [ADVAPI32.@]
1926 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee)
1928 TRACE("(%p)\n", pTrustee);
1930 if (!pTrustee)
1931 return TRUSTEE_BAD_FORM;
1933 return pTrustee->TrusteeForm;
1936 /******************************************************************************
1937 * GetTrusteeNameA [ADVAPI32.@]
1939 LPSTR WINAPI GetTrusteeNameA(PTRUSTEEA pTrustee)
1941 TRACE("(%p)\n", pTrustee);
1943 if (!pTrustee)
1944 return NULL;
1946 return pTrustee->ptstrName;
1949 /******************************************************************************
1950 * GetTrusteeNameW [ADVAPI32.@]
1952 LPWSTR WINAPI GetTrusteeNameW(PTRUSTEEW pTrustee)
1954 TRACE("(%p)\n", pTrustee);
1956 if (!pTrustee)
1957 return NULL;
1959 return pTrustee->ptstrName;
1962 /******************************************************************************
1963 * GetTrusteeTypeA [ADVAPI32.@]
1965 TRUSTEE_TYPE WINAPI GetTrusteeTypeA(PTRUSTEEA pTrustee)
1967 TRACE("(%p)\n", pTrustee);
1969 if (!pTrustee)
1970 return TRUSTEE_IS_UNKNOWN;
1972 return pTrustee->TrusteeType;
1975 /******************************************************************************
1976 * GetTrusteeTypeW [ADVAPI32.@]
1978 TRUSTEE_TYPE WINAPI GetTrusteeTypeW(PTRUSTEEW pTrustee)
1980 TRACE("(%p)\n", pTrustee);
1982 if (!pTrustee)
1983 return TRUSTEE_IS_UNKNOWN;
1985 return pTrustee->TrusteeType;
1988 static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR **ptrustee_nameW)
1990 switch (form)
1992 case TRUSTEE_IS_NAME:
1994 *ptrustee_nameW = strdupAW(trustee_nameA);
1995 return ERROR_SUCCESS;
1997 case TRUSTEE_IS_OBJECTS_AND_NAME:
1999 OBJECTS_AND_NAME_A *objA = (OBJECTS_AND_NAME_A *)trustee_nameA;
2000 OBJECTS_AND_NAME_W *objW = NULL;
2002 if (objA)
2004 if (!(objW = malloc( sizeof(OBJECTS_AND_NAME_W) )))
2005 return ERROR_NOT_ENOUGH_MEMORY;
2007 objW->ObjectsPresent = objA->ObjectsPresent;
2008 objW->ObjectType = objA->ObjectType;
2009 objW->ObjectTypeName = strdupAW(objA->ObjectTypeName);
2010 objW->InheritedObjectTypeName = strdupAW(objA->InheritedObjectTypeName);
2011 objW->ptstrName = strdupAW(objA->ptstrName);
2014 *ptrustee_nameW = (WCHAR *)objW;
2015 return ERROR_SUCCESS;
2017 /* These forms do not require conversion. */
2018 case TRUSTEE_IS_SID:
2019 case TRUSTEE_IS_OBJECTS_AND_SID:
2020 *ptrustee_nameW = (WCHAR *)trustee_nameA;
2021 return ERROR_SUCCESS;
2022 default:
2023 return ERROR_INVALID_PARAMETER;
2027 static void free_trustee_name(TRUSTEE_FORM form, WCHAR *trustee_nameW)
2029 switch (form)
2031 case TRUSTEE_IS_NAME:
2032 free( trustee_nameW );
2033 break;
2034 case TRUSTEE_IS_OBJECTS_AND_NAME:
2036 OBJECTS_AND_NAME_W *objW = (OBJECTS_AND_NAME_W *)trustee_nameW;
2038 if (objW)
2040 free( objW->ptstrName );
2041 free( objW->InheritedObjectTypeName );
2042 free( objW->ObjectTypeName );
2043 free( objW );
2046 break;
2048 /* Other forms did not require allocation, so no freeing is necessary. */
2049 default:
2050 break;
2054 static DWORD trustee_to_sid( DWORD nDestinationSidLength, PSID pDestinationSid, PTRUSTEEW pTrustee )
2056 if (pTrustee->MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
2058 WARN("bad multiple trustee operation %d\n", pTrustee->MultipleTrusteeOperation);
2059 return ERROR_INVALID_PARAMETER;
2062 switch (pTrustee->TrusteeForm)
2064 case TRUSTEE_IS_SID:
2065 if (!CopySid(nDestinationSidLength, pDestinationSid, pTrustee->ptstrName))
2067 WARN("bad sid %p\n", pTrustee->ptstrName);
2068 return ERROR_INVALID_PARAMETER;
2070 break;
2071 case TRUSTEE_IS_NAME:
2073 DWORD sid_size = nDestinationSidLength;
2074 DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
2075 SID_NAME_USE use;
2076 if (!wcscmp( pTrustee->ptstrName, L"CURRENT_USER" ))
2078 if (!lookup_user_account_name( pDestinationSid, &sid_size, NULL, &domain_size, &use ))
2080 return GetLastError();
2083 else if (!LookupAccountNameW(NULL, pTrustee->ptstrName, pDestinationSid, &sid_size, NULL, &domain_size, &use))
2085 WARN("bad user name %s\n", debugstr_w(pTrustee->ptstrName));
2086 return ERROR_INVALID_PARAMETER;
2088 break;
2090 case TRUSTEE_IS_OBJECTS_AND_SID:
2091 FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
2092 break;
2093 case TRUSTEE_IS_OBJECTS_AND_NAME:
2094 FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
2095 break;
2096 default:
2097 WARN("bad trustee form %d\n", pTrustee->TrusteeForm);
2098 return ERROR_INVALID_PARAMETER;
2101 return ERROR_SUCCESS;
2104 /******************************************************************************
2105 * SetEntriesInAclA [ADVAPI32.@]
2107 DWORD WINAPI SetEntriesInAclA( ULONG count, PEXPLICIT_ACCESSA pEntries,
2108 PACL OldAcl, PACL* NewAcl )
2110 DWORD err = ERROR_SUCCESS;
2111 EXPLICIT_ACCESSW *pEntriesW;
2112 UINT alloc_index, free_index;
2114 TRACE("%ld %p %p %p\n", count, pEntries, OldAcl, NewAcl);
2116 if (NewAcl)
2117 *NewAcl = NULL;
2119 if (!count && !OldAcl)
2120 return ERROR_SUCCESS;
2122 pEntriesW = malloc( count * sizeof(EXPLICIT_ACCESSW) );
2123 if (!pEntriesW)
2124 return ERROR_NOT_ENOUGH_MEMORY;
2126 for (alloc_index = 0; alloc_index < count; ++alloc_index)
2128 pEntriesW[alloc_index].grfAccessPermissions = pEntries[alloc_index].grfAccessPermissions;
2129 pEntriesW[alloc_index].grfAccessMode = pEntries[alloc_index].grfAccessMode;
2130 pEntriesW[alloc_index].grfInheritance = pEntries[alloc_index].grfInheritance;
2131 pEntriesW[alloc_index].Trustee.pMultipleTrustee = NULL; /* currently not supported */
2132 pEntriesW[alloc_index].Trustee.MultipleTrusteeOperation = pEntries[alloc_index].Trustee.MultipleTrusteeOperation;
2133 pEntriesW[alloc_index].Trustee.TrusteeForm = pEntries[alloc_index].Trustee.TrusteeForm;
2134 pEntriesW[alloc_index].Trustee.TrusteeType = pEntries[alloc_index].Trustee.TrusteeType;
2136 err = trustee_name_A_to_W( pEntries[alloc_index].Trustee.TrusteeForm,
2137 pEntries[alloc_index].Trustee.ptstrName,
2138 &pEntriesW[alloc_index].Trustee.ptstrName );
2139 if (err != ERROR_SUCCESS)
2141 if (err == ERROR_INVALID_PARAMETER)
2142 WARN("bad trustee form %d for trustee %d\n",
2143 pEntries[alloc_index].Trustee.TrusteeForm, alloc_index);
2145 goto cleanup;
2149 err = SetEntriesInAclW( count, pEntriesW, OldAcl, NewAcl );
2151 cleanup:
2152 /* Free any previously allocated trustee name buffers, taking into account
2153 * a possible out-of-memory condition while building the EXPLICIT_ACCESSW
2154 * list. */
2155 for (free_index = 0; free_index < alloc_index; ++free_index)
2156 free_trustee_name( pEntriesW[free_index].Trustee.TrusteeForm, pEntriesW[free_index].Trustee.ptstrName );
2158 free( pEntriesW );
2159 return err;
2162 /******************************************************************************
2163 * SetEntriesInAclW [ADVAPI32.@]
2165 DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
2166 PACL OldAcl, PACL* NewAcl )
2168 ULONG i;
2169 PSID *ppsid;
2170 DWORD ret = ERROR_SUCCESS;
2171 DWORD acl_size = sizeof(ACL);
2172 NTSTATUS status;
2174 TRACE("%ld %p %p %p\n", count, pEntries, OldAcl, NewAcl);
2176 if (NewAcl)
2177 *NewAcl = NULL;
2179 if (!count && !OldAcl)
2180 return ERROR_SUCCESS;
2182 /* allocate array of maximum sized sids allowed */
2183 ppsid = malloc(count * (sizeof(SID *) + FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES])));
2184 if (!ppsid)
2185 return ERROR_OUTOFMEMORY;
2187 for (i = 0; i < count; i++)
2189 ppsid[i] = (char *)&ppsid[count] + i * FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
2191 TRACE("[%ld]:\n\tgrfAccessPermissions = 0x%lx\n\tgrfAccessMode = %d\n\tgrfInheritance = 0x%lx\n\t"
2192 "Trustee.pMultipleTrustee = %p\n\tMultipleTrusteeOperation = %d\n\tTrusteeForm = %d\n\t"
2193 "Trustee.TrusteeType = %d\n\tptstrName = %p\n", i,
2194 pEntries[i].grfAccessPermissions, pEntries[i].grfAccessMode, pEntries[i].grfInheritance,
2195 pEntries[i].Trustee.pMultipleTrustee, pEntries[i].Trustee.MultipleTrusteeOperation,
2196 pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
2197 pEntries[i].Trustee.ptstrName);
2199 ret = trustee_to_sid( FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]), ppsid[i], &pEntries[i].Trustee);
2200 if (ret)
2201 goto exit;
2203 /* Note: we overestimate the ACL size here as a tradeoff between
2204 * instructions (simplicity) and memory */
2205 switch (pEntries[i].grfAccessMode)
2207 case GRANT_ACCESS:
2208 case SET_ACCESS:
2209 acl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(ppsid[i]);
2210 break;
2211 case DENY_ACCESS:
2212 acl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) + GetLengthSid(ppsid[i]);
2213 break;
2214 case SET_AUDIT_SUCCESS:
2215 case SET_AUDIT_FAILURE:
2216 acl_size += FIELD_OFFSET(SYSTEM_AUDIT_ACE, SidStart) + GetLengthSid(ppsid[i]);
2217 break;
2218 case REVOKE_ACCESS:
2219 break;
2220 default:
2221 WARN("bad access mode %d for trustee %ld\n", pEntries[i].grfAccessMode, i);
2222 ret = ERROR_INVALID_PARAMETER;
2223 goto exit;
2227 if (OldAcl)
2229 ACL_SIZE_INFORMATION size_info;
2231 status = RtlQueryInformationAcl(OldAcl, &size_info, sizeof(size_info), AclSizeInformation);
2232 if (status != STATUS_SUCCESS)
2234 ret = RtlNtStatusToDosError(status);
2235 goto exit;
2237 acl_size += size_info.AclBytesInUse - sizeof(ACL);
2240 *NewAcl = LocalAlloc(0, acl_size);
2241 if (!*NewAcl)
2243 ret = ERROR_OUTOFMEMORY;
2244 goto exit;
2247 status = RtlCreateAcl( *NewAcl, acl_size, ACL_REVISION );
2248 if (status != STATUS_SUCCESS)
2250 ret = RtlNtStatusToDosError(status);
2251 goto exit;
2254 for (i = 0; i < count; i++)
2256 switch (pEntries[i].grfAccessMode)
2258 case GRANT_ACCESS:
2259 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
2260 pEntries[i].grfInheritance,
2261 pEntries[i].grfAccessPermissions,
2262 ppsid[i]);
2263 break;
2264 case SET_ACCESS:
2266 ULONG j;
2267 BOOL add = TRUE;
2268 if (OldAcl)
2270 for (j = 0; ; j++)
2272 const ACE_HEADER *existing_ace_header;
2273 status = RtlGetAce(OldAcl, j, (LPVOID *)&existing_ace_header);
2274 if (status != STATUS_SUCCESS)
2275 break;
2276 if (pEntries[i].grfAccessMode == SET_ACCESS &&
2277 existing_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
2278 EqualSid(ppsid[i], &((ACCESS_ALLOWED_ACE *)existing_ace_header)->SidStart))
2280 add = FALSE;
2281 break;
2285 if (add)
2286 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION,
2287 pEntries[i].grfInheritance,
2288 pEntries[i].grfAccessPermissions,
2289 ppsid[i]);
2290 break;
2292 case DENY_ACCESS:
2293 status = RtlAddAccessDeniedAceEx(*NewAcl, ACL_REVISION,
2294 pEntries[i].grfInheritance,
2295 pEntries[i].grfAccessPermissions,
2296 ppsid[i]);
2297 break;
2298 case SET_AUDIT_SUCCESS:
2299 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
2300 pEntries[i].grfInheritance,
2301 pEntries[i].grfAccessPermissions,
2302 ppsid[i], TRUE, FALSE);
2303 break;
2304 case SET_AUDIT_FAILURE:
2305 status = RtlAddAuditAccessAceEx(*NewAcl, ACL_REVISION,
2306 pEntries[i].grfInheritance,
2307 pEntries[i].grfAccessPermissions,
2308 ppsid[i], FALSE, TRUE);
2309 break;
2310 default:
2311 FIXME("unhandled access mode %d\n", pEntries[i].grfAccessMode);
2315 if (OldAcl)
2317 for (i = 0; ; i++)
2319 BOOL add = TRUE;
2320 ULONG j;
2321 const ACE_HEADER *old_ace_header;
2322 status = RtlGetAce(OldAcl, i, (LPVOID *)&old_ace_header);
2323 if (status != STATUS_SUCCESS) break;
2324 for (j = 0; j < count; j++)
2326 if (pEntries[j].grfAccessMode == SET_ACCESS &&
2327 old_ace_header->AceType == ACCESS_ALLOWED_ACE_TYPE &&
2328 EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
2330 status = RtlAddAccessAllowedAceEx(*NewAcl, ACL_REVISION, pEntries[j].grfInheritance, pEntries[j].grfAccessPermissions, ppsid[j]);
2331 add = FALSE;
2332 break;
2334 else if (pEntries[j].grfAccessMode == REVOKE_ACCESS)
2336 switch (old_ace_header->AceType)
2338 case ACCESS_ALLOWED_ACE_TYPE:
2339 if (EqualSid(ppsid[j], &((ACCESS_ALLOWED_ACE *)old_ace_header)->SidStart))
2340 add = FALSE;
2341 break;
2342 case ACCESS_DENIED_ACE_TYPE:
2343 /* REVOKE_ACCESS does not affect ACCESS_DENIED_ACE. */
2344 break;
2345 case SYSTEM_AUDIT_ACE_TYPE:
2346 if (EqualSid(ppsid[j], &((SYSTEM_AUDIT_ACE *)old_ace_header)->SidStart))
2347 add = FALSE;
2348 break;
2349 case SYSTEM_ALARM_ACE_TYPE:
2350 if (EqualSid(ppsid[j], &((SYSTEM_ALARM_ACE *)old_ace_header)->SidStart))
2351 add = FALSE;
2352 break;
2353 default:
2354 FIXME("unhandled ace type %d\n", old_ace_header->AceType);
2357 if (!add)
2358 break;
2361 if (add)
2362 status = RtlAddAce(*NewAcl, ACL_REVISION, 1, (PACE_HEADER)old_ace_header, old_ace_header->AceSize);
2363 if (status != STATUS_SUCCESS)
2365 WARN("RtlAddAce failed with error 0x%08lx\n", status);
2366 ret = RtlNtStatusToDosError(status);
2367 break;
2372 exit:
2373 free(ppsid);
2374 return ret;
2377 /******************************************************************************
2378 * SetNamedSecurityInfoA [ADVAPI32.@]
2380 DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName,
2381 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
2382 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
2384 LPWSTR wstr;
2385 DWORD r;
2387 TRACE("%s %d %ld %p %p %p %p\n", debugstr_a(pObjectName), ObjectType,
2388 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
2390 wstr = strdupAW(pObjectName);
2391 r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner,
2392 psidGroup, pDacl, pSacl );
2394 free( wstr );
2396 return r;
2399 /******************************************************************************
2400 * SetNamedSecurityInfoW [ADVAPI32.@]
2402 DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName,
2403 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
2404 PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl)
2406 DWORD access = 0;
2407 HANDLE handle;
2408 DWORD err;
2410 TRACE( "%s %d %ld %p %p %p %p\n", debugstr_w(pObjectName), ObjectType,
2411 SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
2413 if (!pObjectName) return ERROR_INVALID_PARAMETER;
2415 if (SecurityInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION))
2416 access |= WRITE_OWNER;
2417 if (SecurityInfo & DACL_SECURITY_INFORMATION)
2418 access |= WRITE_DAC;
2419 if (SecurityInfo & SACL_SECURITY_INFORMATION)
2420 access |= ACCESS_SYSTEM_SECURITY;
2422 switch (ObjectType)
2424 case SE_SERVICE:
2425 if (!(err = get_security_service( pObjectName, access, &handle )))
2427 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
2428 CloseServiceHandle( handle );
2430 break;
2431 case SE_REGISTRY_KEY:
2432 if (!(err = get_security_regkey( pObjectName, access, &handle )))
2434 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
2435 RegCloseKey( handle );
2437 break;
2438 case SE_FILE_OBJECT:
2439 if (SecurityInfo & DACL_SECURITY_INFORMATION)
2440 access |= READ_CONTROL;
2441 if (!(err = get_security_file( pObjectName, access, &handle )))
2443 err = SetSecurityInfo( handle, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
2444 CloseHandle( handle );
2446 break;
2447 default:
2448 FIXME( "Object type %d is not currently supported.\n", ObjectType );
2449 return ERROR_SUCCESS;
2451 return err;
2454 /******************************************************************************
2455 * GetExplicitEntriesFromAclA [ADVAPI32.@]
2457 DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntries,
2458 PEXPLICIT_ACCESSA* pListOfExplicitEntries)
2460 FIXME("%p %p %p\n",pacl, pcCountOfExplicitEntries, pListOfExplicitEntries);
2461 return ERROR_CALL_NOT_IMPLEMENTED;
2464 /******************************************************************************
2465 * GetExplicitEntriesFromAclW [ADVAPI32.@]
2467 DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG count, PEXPLICIT_ACCESSW *list )
2469 ACL_SIZE_INFORMATION sizeinfo;
2470 EXPLICIT_ACCESSW *entries;
2471 MAX_SID *sid_entries;
2472 ACE_HEADER *ace;
2473 NTSTATUS status;
2474 int i;
2476 TRACE("%p %p %p\n",pacl, count, list);
2478 if (!count || !list)
2479 return ERROR_INVALID_PARAMETER;
2481 status = RtlQueryInformationAcl(pacl, &sizeinfo, sizeof(sizeinfo), AclSizeInformation);
2482 if (status) return RtlNtStatusToDosError(status);
2484 if (!sizeinfo.AceCount)
2486 *count = 0;
2487 *list = NULL;
2488 return ERROR_SUCCESS;
2491 entries = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, (sizeof(EXPLICIT_ACCESSW) + sizeof(MAX_SID)) * sizeinfo.AceCount);
2492 if (!entries) return ERROR_OUTOFMEMORY;
2493 sid_entries = (MAX_SID *)(entries + sizeinfo.AceCount);
2495 for (i = 0; i < sizeinfo.AceCount; i++)
2497 status = RtlGetAce(pacl, i, (void**)&ace);
2498 if (status) goto error;
2500 switch (ace->AceType)
2502 case ACCESS_ALLOWED_ACE_TYPE:
2504 ACCESS_ALLOWED_ACE *allow = (ACCESS_ALLOWED_ACE *)ace;
2505 entries[i].grfAccessMode = GRANT_ACCESS;
2506 entries[i].grfInheritance = ace->AceFlags;
2507 entries[i].grfAccessPermissions = allow->Mask;
2509 CopySid(sizeof(MAX_SID), (PSID)&sid_entries[i], (PSID)&allow->SidStart);
2510 entries[i].Trustee.pMultipleTrustee = NULL;
2511 entries[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2512 entries[i].Trustee.TrusteeForm = TRUSTEE_IS_SID;
2513 entries[i].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2514 entries[i].Trustee.ptstrName = (WCHAR *)&sid_entries[i];
2515 break;
2518 case ACCESS_DENIED_ACE_TYPE:
2520 ACCESS_DENIED_ACE *deny = (ACCESS_DENIED_ACE *)ace;
2521 entries[i].grfAccessMode = DENY_ACCESS;
2522 entries[i].grfInheritance = ace->AceFlags;
2523 entries[i].grfAccessPermissions = deny->Mask;
2525 CopySid(sizeof(MAX_SID), (PSID)&sid_entries[i], (PSID)&deny->SidStart);
2526 entries[i].Trustee.pMultipleTrustee = NULL;
2527 entries[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2528 entries[i].Trustee.TrusteeForm = TRUSTEE_IS_SID;
2529 entries[i].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2530 entries[i].Trustee.ptstrName = (WCHAR *)&sid_entries[i];
2531 break;
2534 default:
2535 FIXME("Unhandled ace type %d\n", ace->AceType);
2536 entries[i].grfAccessMode = NOT_USED_ACCESS;
2537 continue;
2541 *count = sizeinfo.AceCount;
2542 *list = entries;
2543 return ERROR_SUCCESS;
2545 error:
2546 LocalFree(entries);
2547 return RtlNtStatusToDosError(status);
2550 /******************************************************************************
2551 * GetAuditedPermissionsFromAclA [ADVAPI32.@]
2553 DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
2554 PACCESS_MASK pFailedAuditRights)
2556 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
2557 return ERROR_CALL_NOT_IMPLEMENTED;
2561 /******************************************************************************
2562 * GetAuditedPermissionsFromAclW [ADVAPI32.@]
2564 DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights,
2565 PACCESS_MASK pFailedAuditRights)
2567 FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights);
2568 return ERROR_CALL_NOT_IMPLEMENTED;
2572 /******************************************************************************
2573 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
2575 BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
2576 LPCSTR StringSecurityDescriptor,
2577 DWORD StringSDRevision,
2578 PSECURITY_DESCRIPTOR* SecurityDescriptor,
2579 PULONG SecurityDescriptorSize)
2581 BOOL ret;
2582 LPWSTR StringSecurityDescriptorW;
2584 TRACE("%s, %lu, %p, %p\n", debugstr_a(StringSecurityDescriptor), StringSDRevision,
2585 SecurityDescriptor, SecurityDescriptorSize);
2587 if(!StringSecurityDescriptor)
2588 return FALSE;
2590 StringSecurityDescriptorW = strdupAW(StringSecurityDescriptor);
2591 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
2592 StringSDRevision, SecurityDescriptor,
2593 SecurityDescriptorSize);
2594 free(StringSecurityDescriptorW);
2596 return ret;
2599 /******************************************************************************
2600 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
2602 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen)
2604 LPWSTR wstr;
2605 ULONG len;
2606 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
2608 int lenA;
2610 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
2611 *OutputString = malloc(lenA);
2612 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
2613 LocalFree(wstr);
2615 if (OutputLen != NULL)
2616 *OutputLen = lenA;
2617 return TRUE;
2619 else
2621 *OutputString = NULL;
2622 if (OutputLen)
2623 *OutputLen = 0;
2624 return FALSE;
2628 /******************************************************************************
2629 * ConvertStringSidToSidA [ADVAPI32.@]
2631 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid)
2633 BOOL bret = FALSE;
2635 TRACE("%s, %p\n", debugstr_a(StringSid), Sid);
2636 if (GetVersion() & 0x80000000)
2637 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2638 else if (!StringSid || !Sid)
2639 SetLastError(ERROR_INVALID_PARAMETER);
2640 else
2642 WCHAR *wStringSid = strdupAW(StringSid);
2643 bret = ConvertStringSidToSidW(wStringSid, Sid);
2644 free(wStringSid);
2646 return bret;
2649 /******************************************************************************
2650 * ConvertSidToStringSidA [ADVAPI32.@]
2652 BOOL WINAPI ConvertSidToStringSidA(PSID pSid, LPSTR *pstr)
2654 LPWSTR wstr = NULL;
2655 LPSTR str;
2656 UINT len;
2658 TRACE("%p %p\n", pSid, pstr );
2660 if( !ConvertSidToStringSidW( pSid, &wstr ) )
2661 return FALSE;
2663 len = WideCharToMultiByte( CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL );
2664 str = LocalAlloc( 0, len );
2665 WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, len, NULL, NULL );
2666 LocalFree( wstr );
2668 *pstr = str;
2670 return TRUE;
2673 /******************************************************************************
2674 * CreateProcessWithLogonW
2676 BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags,
2677 LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment,
2678 LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation )
2680 FIXME("%s %s %s 0x%08lx %s %s 0x%08lx %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
2681 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
2682 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
2683 lpStartupInfo, lpProcessInformation);
2685 return FALSE;
2688 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line,
2689 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info,
2690 PROCESS_INFORMATION *process_information )
2692 FIXME("%p 0x%08lx %s %s 0x%08lx %p %s %p %p - semi-stub\n", token,
2693 logon_flags, debugstr_w(application_name), debugstr_w(command_line),
2694 creation_flags, environment, debugstr_w(current_directory),
2695 startup_info, process_information);
2697 /* FIXME: check if handles should be inherited */
2698 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment,
2699 current_directory, startup_info, process_information );
2702 /******************************************************************************
2703 * GetNamedSecurityInfoA [ADVAPI32.@]
2705 DWORD WINAPI GetNamedSecurityInfoA(const char *pObjectName,
2706 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
2707 PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl,
2708 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
2710 LPWSTR wstr;
2711 DWORD r;
2713 TRACE("%s %d %ld %p %p %p %p %p\n", debugstr_a(pObjectName), ObjectType, SecurityInfo,
2714 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
2716 wstr = strdupAW(pObjectName);
2717 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner,
2718 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
2720 free( wstr );
2722 return r;
2725 /******************************************************************************
2726 * GetNamedSecurityInfoW [ADVAPI32.@]
2728 DWORD WINAPI GetNamedSecurityInfoW( const WCHAR *name, SE_OBJECT_TYPE type,
2729 SECURITY_INFORMATION info, PSID* owner, PSID* group, PACL* dacl,
2730 PACL* sacl, PSECURITY_DESCRIPTOR* descriptor )
2732 DWORD access = 0;
2733 HANDLE handle;
2734 DWORD err;
2736 TRACE( "%s %d %ld %p %p %p %p %p\n", debugstr_w(name), type, info, owner,
2737 group, dacl, sacl, descriptor );
2739 /* A NULL descriptor is allowed if any one of the other pointers is not NULL */
2740 if (!name || !(owner||group||dacl||sacl||descriptor) ) return ERROR_INVALID_PARAMETER;
2742 /* If no descriptor, we have to check that there's a pointer for the requested information */
2743 if( !descriptor && (
2744 ((info & OWNER_SECURITY_INFORMATION) && !owner)
2745 || ((info & GROUP_SECURITY_INFORMATION) && !group)
2746 || ((info & DACL_SECURITY_INFORMATION) && !dacl)
2747 || ((info & SACL_SECURITY_INFORMATION) && !sacl) ))
2748 return ERROR_INVALID_PARAMETER;
2750 if (info & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION))
2751 access |= READ_CONTROL;
2752 if (info & SACL_SECURITY_INFORMATION)
2753 access |= ACCESS_SYSTEM_SECURITY;
2755 switch (type)
2757 case SE_SERVICE:
2758 if (!(err = get_security_service( name, access, &handle )))
2760 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
2761 CloseServiceHandle( handle );
2763 break;
2764 case SE_REGISTRY_KEY:
2765 if (!(err = get_security_regkey( name, access, &handle )))
2767 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
2768 RegCloseKey( handle );
2770 break;
2771 case SE_FILE_OBJECT:
2772 if (!(err = get_security_file( name, access, &handle )))
2774 err = GetSecurityInfo( handle, type, info, owner, group, dacl, sacl, descriptor );
2775 CloseHandle( handle );
2777 break;
2778 default:
2779 FIXME( "Object type %d is not currently supported.\n", type );
2780 if (owner) *owner = NULL;
2781 if (group) *group = NULL;
2782 if (dacl) *dacl = NULL;
2783 if (sacl) *sacl = NULL;
2784 if (descriptor) *descriptor = NULL;
2785 return ERROR_SUCCESS;
2787 return err;
2790 /******************************************************************************
2791 * GetNamedSecurityInfoExW [ADVAPI32.@]
2793 DWORD WINAPI GetNamedSecurityInfoExW( LPCWSTR object, SE_OBJECT_TYPE type,
2794 SECURITY_INFORMATION info, LPCWSTR provider, LPCWSTR property,
2795 PACTRL_ACCESSW* access_list, PACTRL_AUDITW* audit_list, LPWSTR* owner, LPWSTR* group )
2797 FIXME("(%s, %d, %ld, %s, %s, %p, %p, %p, %p) stub\n", debugstr_w(object), type, info,
2798 debugstr_w(provider), debugstr_w(property), access_list, audit_list, owner, group);
2799 return ERROR_CALL_NOT_IMPLEMENTED;
2802 /******************************************************************************
2803 * GetNamedSecurityInfoExA [ADVAPI32.@]
2805 DWORD WINAPI GetNamedSecurityInfoExA( LPCSTR object, SE_OBJECT_TYPE type,
2806 SECURITY_INFORMATION info, LPCSTR provider, LPCSTR property,
2807 PACTRL_ACCESSA* access_list, PACTRL_AUDITA* audit_list, LPSTR* owner, LPSTR* group )
2809 FIXME("(%s, %d, %ld, %s, %s, %p, %p, %p, %p) stub\n", debugstr_a(object), type, info,
2810 debugstr_a(provider), debugstr_a(property), access_list, audit_list, owner, group);
2811 return ERROR_CALL_NOT_IMPLEMENTED;
2814 /******************************************************************************
2815 * DecryptFileW [ADVAPI32.@]
2817 BOOL WINAPI DecryptFileW(LPCWSTR lpFileName, DWORD dwReserved)
2819 FIXME("(%s, %08lx): stub\n", debugstr_w(lpFileName), dwReserved);
2820 return TRUE;
2823 /******************************************************************************
2824 * DecryptFileA [ADVAPI32.@]
2826 BOOL WINAPI DecryptFileA(LPCSTR lpFileName, DWORD dwReserved)
2828 FIXME("(%s, %08lx): stub\n", debugstr_a(lpFileName), dwReserved);
2829 return TRUE;
2832 /******************************************************************************
2833 * EncryptFileW [ADVAPI32.@]
2835 BOOL WINAPI EncryptFileW(LPCWSTR lpFileName)
2837 FIXME("(%s): stub\n", debugstr_w(lpFileName));
2838 return TRUE;
2841 /******************************************************************************
2842 * EncryptFileA [ADVAPI32.@]
2844 BOOL WINAPI EncryptFileA(LPCSTR lpFileName)
2846 FIXME("(%s): stub\n", debugstr_a(lpFileName));
2847 return TRUE;
2850 /******************************************************************************
2851 * FileEncryptionStatusW [ADVAPI32.@]
2853 BOOL WINAPI FileEncryptionStatusW(LPCWSTR lpFileName, LPDWORD lpStatus)
2855 FIXME("(%s %p): stub\n", debugstr_w(lpFileName), lpStatus);
2856 if (!lpStatus)
2857 return FALSE;
2858 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
2859 return TRUE;
2862 /******************************************************************************
2863 * FileEncryptionStatusA [ADVAPI32.@]
2865 BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
2867 FIXME("(%s %p): stub\n", debugstr_a(lpFileName), lpStatus);
2868 if (!lpStatus)
2869 return FALSE;
2870 *lpStatus = FILE_SYSTEM_NOT_SUPPORT;
2871 return TRUE;
2874 static NTSTATUS combine_dacls(ACL *parent, ACL *child, ACL **result)
2876 NTSTATUS status;
2877 ACL *combined;
2878 int i;
2880 /* initialize a combined DACL containing both inherited and new ACEs */
2881 combined = calloc(1, child->AclSize + parent->AclSize);
2882 if (!combined)
2883 return STATUS_NO_MEMORY;
2885 status = RtlCreateAcl(combined, parent->AclSize+child->AclSize, ACL_REVISION);
2886 if (status != STATUS_SUCCESS)
2888 free(combined);
2889 return status;
2892 /* copy the new ACEs */
2893 for (i=0; i<child->AceCount; i++)
2895 ACE_HEADER *ace;
2897 if (!GetAce(child, i, (void*)&ace))
2898 continue;
2899 if (!AddAce(combined, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
2900 WARN("error adding new ACE\n");
2903 /* copy the inherited ACEs */
2904 for (i=0; i<parent->AceCount; i++)
2906 ACE_HEADER *ace;
2908 if (!GetAce(parent, i, (void*)&ace))
2909 continue;
2910 if (!(ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)))
2911 continue;
2912 if ((ace->AceFlags & (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE)) !=
2913 (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE))
2915 FIXME("unsupported flags: %x\n", ace->AceFlags);
2916 continue;
2919 if (ace->AceFlags & NO_PROPAGATE_INHERIT_ACE)
2920 ace->AceFlags &= ~(OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE|NO_PROPAGATE_INHERIT_ACE);
2921 ace->AceFlags &= ~INHERIT_ONLY_ACE;
2922 ace->AceFlags |= INHERITED_ACE;
2924 if (!AddAce(combined, ACL_REVISION, MAXDWORD, ace, ace->AceSize))
2925 WARN("error adding inherited ACE\n");
2928 *result = combined;
2929 return STATUS_SUCCESS;
2932 /******************************************************************************
2933 * SetSecurityInfo [ADVAPI32.@]
2935 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType,
2936 SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
2937 PSID psidGroup, PACL pDacl, PACL pSacl)
2939 SECURITY_DESCRIPTOR sd;
2940 PACL dacl = pDacl;
2941 NTSTATUS status;
2943 if (!handle)
2944 return ERROR_INVALID_HANDLE;
2946 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
2947 return ERROR_INVALID_SECURITY_DESCR;
2949 if (SecurityInfo & OWNER_SECURITY_INFORMATION)
2950 SetSecurityDescriptorOwner(&sd, psidOwner, FALSE);
2951 if (SecurityInfo & GROUP_SECURITY_INFORMATION)
2952 SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
2953 if (SecurityInfo & DACL_SECURITY_INFORMATION)
2955 if (ObjectType == SE_FILE_OBJECT && pDacl)
2957 SECURITY_DESCRIPTOR_CONTROL control;
2958 PSECURITY_DESCRIPTOR psd;
2959 OBJECT_NAME_INFORMATION *name_info;
2960 DWORD size, rev;
2962 status = NtQuerySecurityObject(handle, SecurityInfo, NULL, 0, &size);
2963 if (status != STATUS_BUFFER_TOO_SMALL)
2964 return RtlNtStatusToDosError(status);
2966 psd = malloc(size);
2967 if (!psd)
2968 return ERROR_NOT_ENOUGH_MEMORY;
2970 status = NtQuerySecurityObject(handle, SecurityInfo, psd, size, &size);
2971 if (status)
2973 free(psd);
2974 return RtlNtStatusToDosError(status);
2977 status = RtlGetControlSecurityDescriptor(psd, &control, &rev);
2978 free(psd);
2979 if (status)
2980 return RtlNtStatusToDosError(status);
2981 /* TODO: copy some control flags to new sd */
2983 /* inherit parent directory DACL */
2984 if (!(control & SE_DACL_PROTECTED))
2986 status = NtQueryObject(handle, ObjectNameInformation, NULL, 0, &size);
2987 if (status != STATUS_INFO_LENGTH_MISMATCH)
2988 return RtlNtStatusToDosError(status);
2990 name_info = malloc(size);
2991 if (!name_info)
2992 return ERROR_NOT_ENOUGH_MEMORY;
2994 status = NtQueryObject(handle, ObjectNameInformation, name_info, size, NULL);
2995 if (status)
2997 free(name_info);
2998 return RtlNtStatusToDosError(status);
3001 if (name_info->Name.Length && name_info->Name.Buffer[(name_info->Name.Length / 2) - 1] == '\\')
3002 name_info->Name.Length -= 2;
3003 while (name_info->Name.Length && name_info->Name.Buffer[(name_info->Name.Length / 2) - 1] != '\\')
3004 name_info->Name.Length -= 2;
3006 if (name_info->Name.Length)
3008 OBJECT_ATTRIBUTES attr;
3009 IO_STATUS_BLOCK io;
3010 HANDLE parent;
3011 PSECURITY_DESCRIPTOR parent_sd;
3012 ACL *parent_dacl;
3013 DWORD err = ERROR_ACCESS_DENIED;
3015 name_info->Name.Buffer[name_info->Name.Length/2] = 0;
3017 attr.Length = sizeof(attr);
3018 attr.RootDirectory = 0;
3019 attr.Attributes = 0;
3020 attr.ObjectName = &name_info->Name;
3021 attr.SecurityDescriptor = NULL;
3022 status = NtOpenFile(&parent, READ_CONTROL|SYNCHRONIZE, &attr, &io,
3023 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3024 FILE_OPEN_FOR_BACKUP_INTENT);
3025 free(name_info);
3026 if (!status)
3028 err = GetSecurityInfo(parent, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
3029 NULL, NULL, &parent_dacl, NULL, &parent_sd);
3030 CloseHandle(parent);
3033 if (!err)
3035 status = combine_dacls(parent_dacl, pDacl, &dacl);
3036 LocalFree(parent_sd);
3037 if (status != STATUS_SUCCESS)
3038 return RtlNtStatusToDosError(status);
3041 else
3042 free(name_info);
3046 SetSecurityDescriptorDacl(&sd, TRUE, dacl, FALSE);
3048 if (SecurityInfo & SACL_SECURITY_INFORMATION)
3049 SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
3051 switch (ObjectType)
3053 case SE_FILE_OBJECT:
3054 case SE_KERNEL_OBJECT:
3055 case SE_WMIGUID_OBJECT:
3056 case SE_REGISTRY_KEY:
3057 status = NtSetSecurityObject(handle, SecurityInfo, &sd);
3058 break;
3060 default:
3061 FIXME("unimplemented type %u, returning success\n", ObjectType);
3062 status = STATUS_SUCCESS;
3063 break;
3066 if (dacl != pDacl)
3067 free(dacl);
3068 return RtlNtStatusToDosError(status);
3071 /******************************************************************************
3072 * SaferCreateLevel [ADVAPI32.@]
3074 BOOL WINAPI SaferCreateLevel(DWORD ScopeId, DWORD LevelId, DWORD OpenFlags,
3075 SAFER_LEVEL_HANDLE* LevelHandle, LPVOID lpReserved)
3077 FIXME("(%lu, %lx, %lu, %p, %p) stub\n", ScopeId, LevelId, OpenFlags, LevelHandle, lpReserved);
3079 *LevelHandle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
3080 return TRUE;
3083 /******************************************************************************
3084 * SaferComputeTokenFromLevel [ADVAPI32.@]
3086 BOOL WINAPI SaferComputeTokenFromLevel(SAFER_LEVEL_HANDLE handle, HANDLE token, PHANDLE access_token,
3087 DWORD flags, LPVOID reserved)
3089 FIXME("(%p, %p, %p, %lx, %p) stub\n", handle, token, access_token, flags, reserved);
3091 *access_token = (flags & SAFER_TOKEN_NULL_IF_EQUAL) ? NULL : (HANDLE)0xdeadbeef;
3092 return TRUE;
3095 /******************************************************************************
3096 * SaferCloseLevel [ADVAPI32.@]
3098 BOOL WINAPI SaferCloseLevel(SAFER_LEVEL_HANDLE handle)
3100 FIXME("(%p) stub\n", handle);
3101 return TRUE;
3104 /******************************************************************************
3105 * TreeResetNamedSecurityInfoW [ADVAPI32.@]
3107 DWORD WINAPI TreeResetNamedSecurityInfoW( LPWSTR pObjectName,
3108 SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo,
3109 PSID pOwner, PSID pGroup, PACL pDacl, PACL pSacl,
3110 BOOL KeepExplicit, FN_PROGRESS fnProgress,
3111 PROG_INVOKE_SETTING ProgressInvokeSetting, PVOID Args)
3113 FIXME("(%s, %i, %li, %p, %p, %p, %p, %i, %p, %i, %p) stub\n",
3114 debugstr_w(pObjectName), ObjectType, SecurityInfo, pOwner, pGroup,
3115 pDacl, pSacl, KeepExplicit, fnProgress, ProgressInvokeSetting, Args);
3117 return ERROR_SUCCESS;
3120 /******************************************************************************
3121 * SaferGetPolicyInformation [ADVAPI32.@]
3123 BOOL WINAPI SaferGetPolicyInformation(DWORD scope, SAFER_POLICY_INFO_CLASS class, DWORD size,
3124 PVOID buffer, PDWORD required, LPVOID lpReserved)
3126 FIXME("(%lu %u %lu %p %p %p) stub\n", scope, class, size, buffer, required, lpReserved);
3127 return FALSE;
3130 /******************************************************************************
3131 * SaferIdentifyLevel [ADVAPI32.@]
3133 BOOL WINAPI SaferIdentifyLevel(DWORD count, SAFER_CODE_PROPERTIES *properties, SAFER_LEVEL_HANDLE *handle,
3134 void *reserved)
3136 FIXME("(%lu %p %p %p) stub\n", count, properties, handle, reserved);
3137 *handle = (SAFER_LEVEL_HANDLE)0xdeadbeef;
3138 return TRUE;
3141 /******************************************************************************
3142 * SaferSetLevelInformation [ADVAPI32.@]
3144 BOOL WINAPI SaferSetLevelInformation(SAFER_LEVEL_HANDLE handle, SAFER_OBJECT_INFO_CLASS infotype,
3145 LPVOID buffer, DWORD size)
3147 FIXME("(%p %u %p %lu) stub\n", handle, infotype, buffer, size);
3148 return FALSE;
3151 /******************************************************************************
3152 * LookupSecurityDescriptorPartsA [ADVAPI32.@]
3154 DWORD WINAPI LookupSecurityDescriptorPartsA(TRUSTEEA *owner, TRUSTEEA *group, ULONG *access_count,
3155 EXPLICIT_ACCESSA *access_list, ULONG *audit_count,
3156 EXPLICIT_ACCESSA *audit_list, SECURITY_DESCRIPTOR *descriptor)
3158 FIXME("(%p %p %p %p %p %p %p) stub\n", owner, group, access_count,
3159 access_list, audit_count, audit_list, descriptor);
3160 return ERROR_CALL_NOT_IMPLEMENTED;
3163 /******************************************************************************
3164 * LookupSecurityDescriptorPartsW [ADVAPI32.@]
3166 DWORD WINAPI LookupSecurityDescriptorPartsW(TRUSTEEW *owner, TRUSTEEW *group, ULONG *access_count,
3167 EXPLICIT_ACCESSW *access_list, ULONG *audit_count,
3168 EXPLICIT_ACCESSW *audit_list, SECURITY_DESCRIPTOR *descriptor)
3170 FIXME("(%p %p %p %p %p %p %p) stub\n", owner, group, access_count,
3171 access_list, audit_count, audit_list, descriptor);
3172 return ERROR_CALL_NOT_IMPLEMENTED;