From d9e47e90394ceb0afb761e74315037304274f9bf Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 4 Jul 2010 12:51:39 +0000 Subject: [PATCH] [ADVAPI32/LSASRV] - Implement LookupPrivilegeNameW and LsaLookupPrivilegeName. - Move lookup code from LookupPrivilegeNameW and LsarLookupPrivilegeValue into a separate file. svn path=/trunk/; revision=47936 --- reactos/dll/win32/advapi32/sec/lsa.c | 61 +++++++- reactos/dll/win32/advapi32/sec/misc.c | 71 ++++++--- reactos/dll/win32/lsasrv/lsarpc.c | 69 +++------ reactos/dll/win32/lsasrv/lsasrv.h | 9 ++ reactos/dll/win32/lsasrv/lsasrv.rbuild | 1 + reactos/dll/win32/lsasrv/privileges.c | 197 +++++++++++++++++++++++++ reactos/include/psdk/ntsecapi.h | 1 + 7 files changed, 339 insertions(+), 70 deletions(-) create mode 100644 reactos/dll/win32/lsasrv/privileges.c diff --git a/reactos/dll/win32/advapi32/sec/lsa.c b/reactos/dll/win32/advapi32/sec/lsa.c index 6c34400e498..10bb1e65077 100644 --- a/reactos/dll/win32/advapi32/sec/lsa.c +++ b/reactos/dll/win32/advapi32/sec/lsa.c @@ -69,6 +69,27 @@ static void* ADVAPI_GetDomainName(unsigned sz, unsigned ofs) return ptr; } + +static BOOL LsapIsLocalComputer(PLSA_UNICODE_STRING ServerName) +{ + DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; + BOOL Result; + LPWSTR buf; + + if (ServerName == NULL || ServerName->Length == 0 || ServerName->Buffer == NULL) + return TRUE; + + buf = HeapAlloc(GetProcessHeap(), 0, dwSize * sizeof(WCHAR)); + Result = GetComputerNameW(buf, &dwSize); + if (Result && (ServerName->Buffer[0] == '\\') && (ServerName->Buffer[1] == '\\')) + ServerName += 2; + Result = Result && !lstrcmpW(ServerName->Buffer, buf); + HeapFree(GetProcessHeap(), 0, buf); + + return Result; +} + + handle_t __RPC_USER PLSAPR_SERVER_NAME_bind(PLSAPR_SERVER_NAME pszSystemName) { @@ -396,6 +417,40 @@ LsaLookupNames2( return STATUS_NONE_MAPPED; } +/* + * @unmplemented + */ +NTSTATUS +WINAPI +LsaLookupPrivilegeName(IN LSA_HANDLE PolicyHandle, + IN PLUID Value, + OUT PUNICODE_STRING *Name) +{ + PRPC_UNICODE_STRING NameBuffer = NULL; + NTSTATUS Status; + + TRACE("(%p,%p,%p) stub\n", PolicyHandle, Value, Name); + + RpcTryExcept + { + Status = LsarLookupPrivilegeName(PolicyHandle, + Value, + &NameBuffer); + + *Name = (PUNICODE_STRING)NameBuffer; + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + if (NameBuffer != NULL) + MIDL_user_free(NameBuffer); + + Status = I_RpcMapWin32Status(RpcExceptionCode()); + } + RpcEndExcept; + + return Status; +} + /* * @implemented */ @@ -408,7 +463,7 @@ LsaLookupPrivilegeValue(IN LSA_HANDLE PolicyHandle, LUID Luid; NTSTATUS Status; - FIXME("(%p,%p,%p) stub\n", PolicyHandle, Name, Value); + TRACE("(%p,%p,%p) stub\n", PolicyHandle, Name, Value); RpcTryExcept { @@ -511,6 +566,10 @@ LsaOpenPolicy( SystemName ? debugstr_w(SystemName->Buffer) : "(null)", ObjectAttributes, DesiredAccess, PolicyHandle); + /* FIXME: RPC should take care of this */ + if (!LsapIsLocalComputer(SystemName)) + return RPC_NT_SERVER_UNAVAILABLE; + RpcTryExcept { *PolicyHandle = NULL; diff --git a/reactos/dll/win32/advapi32/sec/misc.c b/reactos/dll/win32/advapi32/sec/misc.c index f8fb3832f2e..b92fbec9bbe 100644 --- a/reactos/dll/win32/advapi32/sec/misc.c +++ b/reactos/dll/win32/advapi32/sec/misc.c @@ -1419,12 +1419,14 @@ LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpPrivilegeName, PLUID lpLuid) { - LSA_OBJECT_ATTRIBUTES ObjectAttributes = {0}; - LSA_UNICODE_STRING SystemName; - LSA_UNICODE_STRING PrivilegeName; + OBJECT_ATTRIBUTES ObjectAttributes = {0}; + UNICODE_STRING SystemName; + UNICODE_STRING PrivilegeName; LSA_HANDLE PolicyHandle = NULL; NTSTATUS Status; + TRACE("%S,%S,%p\n", lpSystemName, lpPrivilegeName, lpLuid); + RtlInitUnicodeString(&SystemName, lpSystemName); @@ -1565,36 +1567,61 @@ LookupPrivilegeNameW(LPCWSTR lpSystemName, LPWSTR lpName, LPDWORD cchName) { - size_t privNameLen; + OBJECT_ATTRIBUTES ObjectAttributes = {0}; + UNICODE_STRING SystemName; + PUNICODE_STRING PrivilegeName = NULL; + LSA_HANDLE PolicyHandle = NULL; + NTSTATUS Status; - TRACE("%s,%p,%p,%p\n",debugstr_w(lpSystemName), lpLuid, lpName, cchName); + TRACE("%S,%p,%p,%p\n", lpSystemName, lpLuid, lpName, cchName); - if (!ADVAPI_IsLocalComputer(lpSystemName)) + RtlInitUnicodeString(&SystemName, + lpSystemName); + + Status = LsaOpenPolicy(lpSystemName ? &SystemName : NULL, + &ObjectAttributes, + POLICY_LOOKUP_NAMES, + &PolicyHandle); + if (!NT_SUCCESS(Status)) { - SetLastError(RPC_S_SERVER_UNAVAILABLE); + SetLastError(LsaNtStatusToWinError(Status)); return FALSE; } - if (lpLuid->HighPart || (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE || - lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE)) + Status = LsaLookupPrivilegeName(PolicyHandle, + lpLuid, + &PrivilegeName); + if (NT_SUCCESS(Status)) { - SetLastError(ERROR_NO_SUCH_PRIVILEGE); - return FALSE; + if (PrivilegeName->Length + sizeof(WCHAR) > (*cchName) * sizeof(WCHAR)) + { + Status = STATUS_BUFFER_TOO_SMALL; + + (*cchName) = (PrivilegeName->Length + sizeof(WCHAR)) / sizeof(WCHAR); + } + else + { + RtlMoveMemory(lpName, + PrivilegeName->Buffer, + PrivilegeName->Length); + lpName[PrivilegeName->Length / sizeof(WCHAR)] = 0; + + (*cchName) = PrivilegeName->Length / sizeof(WCHAR); + } + + LsaFreeMemory(PrivilegeName->Buffer); + LsaFreeMemory(PrivilegeName); } - privNameLen = strlenW(WellKnownPrivNames[lpLuid->LowPart]); - /* Windows crashes if cchName is NULL, so will I */ - if (*cchName <= privNameLen) + + LsaClose(PolicyHandle); + + if (!NT_SUCCESS(Status)) { - *cchName = privNameLen + 1; - SetLastError(ERROR_INSUFFICIENT_BUFFER); + SetLastError(LsaNtStatusToWinError(Status)); return FALSE; } - else - { - strcpyW(lpName, WellKnownPrivNames[lpLuid->LowPart]); - *cchName = privNameLen; - return TRUE; - } + + return TRUE; } diff --git a/reactos/dll/win32/lsasrv/lsarpc.c b/reactos/dll/win32/lsasrv/lsarpc.c index e7e4c1763f8..57f802b541d 100644 --- a/reactos/dll/win32/lsasrv/lsarpc.c +++ b/reactos/dll/win32/lsasrv/lsarpc.c @@ -6,6 +6,9 @@ #define NTOS_MODE_USER #include +#include + +#include "lsasrv.h" #include "lsa_s.h" #include @@ -520,40 +523,7 @@ NTSTATUS LsarLookupPrivilegeValue( PRPC_UNICODE_STRING Name, PLUID Value) { - static const WCHAR * const DefaultPrivNames[] = - { - L"SeCreateTokenPrivilege", - L"SeAssignPrimaryTokenPrivilege", - L"SeLockMemoryPrivilege", - L"SeIncreaseQuotaPrivilege", - L"SeMachineAccountPrivilege", - L"SeTcbPrivilege", - L"SeSecurityPrivilege", - L"SeTakeOwnershipPrivilege", - L"SeLoadDriverPrivilege", - L"SeSystemProfilePrivilege", - L"SeSystemtimePrivilege", - L"SeProfileSingleProcessPrivilege", - L"SeIncreaseBasePriorityPrivilege", - L"SeCreatePagefilePrivilege", - L"SeCreatePermanentPrivilege", - L"SeBackupPrivilege", - L"SeRestorePrivilege", - L"SeShutdownPrivilege", - L"SeDebugPrivilege", - L"SeAuditPrivilege", - L"SeSystemEnvironmentPrivilege", - L"SeChangeNotifyPrivilege", - L"SeRemoteShutdownPrivilege", - L"SeUndockPrivilege", - L"SeSyncAgentPrivilege", - L"SeEnableDelegationPrivilege", - L"SeManageVolumePrivilege", - L"SeImpersonatePrivilege", - L"SeCreateGlobalPrivilege" - }; - ULONG Priv; - + NTSTATUS Status; TRACE("LsarLookupPrivilegeValue(%p, %wZ, %p)\n", PolicyHandle, Name, Value); @@ -564,19 +534,12 @@ NTSTATUS LsarLookupPrivilegeValue( return STATUS_INVALID_HANDLE; } - for (Priv = 0; Priv < sizeof(DefaultPrivNames) / sizeof(DefaultPrivNames[0]); Priv++) - { - if (0 == _wcsicmp(Name->Buffer, DefaultPrivNames[Priv])) - { - Value->LowPart = Priv + SE_MIN_WELL_KNOWN_PRIVILEGE; - Value->HighPart = 0; - return STATUS_SUCCESS; - } - } + TRACE("Privilege: %wZ\n", Name); - WARN("LsarLookupPrivilegeValue: no such privilege %wZ\n", Name); + Status = LsarpLookupPrivilegeValue((PUNICODE_STRING)Name, + Value); - return STATUS_NO_SUCH_PRIVILEGE; + return Status; } @@ -586,8 +549,20 @@ NTSTATUS LsarLookupPrivilegeName( PLUID Value, PRPC_UNICODE_STRING *Name) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + + TRACE("LsarLookupPrivilegeName(%p, %p, %p)\n", + PolicyHandle, Value, Name); + + if (!LsapValidateDbHandle(PolicyHandle, LsaDbPolicyHandle)) + { + ERR("Invalid handle\n"); + return STATUS_INVALID_HANDLE; + } + + Status = LsarpLookupPrivilegeName(Value, (PUNICODE_STRING*)Name); + + return Status; } diff --git a/reactos/dll/win32/lsasrv/lsasrv.h b/reactos/dll/win32/lsasrv/lsasrv.h index 159950880df..00b1a77f1ed 100644 --- a/reactos/dll/win32/lsasrv/lsasrv.h +++ b/reactos/dll/win32/lsasrv/lsasrv.h @@ -12,3 +12,12 @@ NTSTATUS StartAuthenticationPort(VOID); /* lsarpc.c */ VOID LsarStartRpcServer(VOID); + +/* privileges.c */ +NTSTATUS +LsarpLookupPrivilegeName(PLUID Value, + PUNICODE_STRING *Name); + +NTSTATUS +LsarpLookupPrivilegeValue(PUNICODE_STRING Name, + PLUID Value); \ No newline at end of file diff --git a/reactos/dll/win32/lsasrv/lsasrv.rbuild b/reactos/dll/win32/lsasrv/lsasrv.rbuild index 840599c554c..d1d122e9ed6 100644 --- a/reactos/dll/win32/lsasrv/lsasrv.rbuild +++ b/reactos/dll/win32/lsasrv/lsasrv.rbuild @@ -11,5 +11,6 @@ authport.c lsarpc.c lsasrv.c + privileges.c lsasrv.rc diff --git a/reactos/dll/win32/lsasrv/privileges.c b/reactos/dll/win32/lsasrv/privileges.c new file mode 100644 index 00000000000..0154161b174 --- /dev/null +++ b/reactos/dll/win32/lsasrv/privileges.c @@ -0,0 +1,197 @@ +#define WIN32_NO_STATUS +#include +#include +#define NTOS_MODE_USER +#include + +#include +#include + + +#include + + +static const WCHAR SE_CREATE_TOKEN_NAME_W[] = + { 'S','e','C','r','e','a','t','e','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_ASSIGNPRIMARYTOKEN_NAME_W[] = + { 'S','e','A','s','s','i','g','n','P','r','i','m','a','r','y','T','o','k','e','n','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_LOCK_MEMORY_NAME_W[] = + { 'S','e','L','o','c','k','M','e','m','o','r','y','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_INCREASE_QUOTA_NAME_W[] = + { 'S','e','I','n','c','r','e','a','s','e','Q','u','o','t','a','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_MACHINE_ACCOUNT_NAME_W[] = + { 'S','e','M','a','c','h','i','n','e','A','c','c','o','u','n','t','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_TCB_NAME_W[] = + { 'S','e','T','c','b','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_SECURITY_NAME_W[] = + { 'S','e','S','e','c','u','r','i','t','y','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_TAKE_OWNERSHIP_NAME_W[] = + { 'S','e','T','a','k','e','O','w','n','e','r','s','h','i','p','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_LOAD_DRIVER_NAME_W[] = + { 'S','e','L','o','a','d','D','r','i','v','e','r','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_SYSTEM_PROFILE_NAME_W[] = + { 'S','e','S','y','s','t','e','m','P','r','o','f','i','l','e','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_SYSTEMTIME_NAME_W[] = + { 'S','e','S','y','s','t','e','m','t','i','m','e','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_PROF_SINGLE_PROCESS_NAME_W[] = + { 'S','e','P','r','o','f','i','l','e','S','i','n','g','l','e','P','r','o','c','e','s','s','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_INC_BASE_PRIORITY_NAME_W[] = + { 'S','e','I','n','c','r','e','a','s','e','B','a','s','e','P','r','i','o','r','i','t','y','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_CREATE_PAGEFILE_NAME_W[] = + { 'S','e','C','r','e','a','t','e','P','a','g','e','f','i','l','e','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_CREATE_PERMANENT_NAME_W[] = + { 'S','e','C','r','e','a','t','e','P','e','r','m','a','n','e','n','t','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_BACKUP_NAME_W[] = + { 'S','e','B','a','c','k','u','p','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_RESTORE_NAME_W[] = + { 'S','e','R','e','s','t','o','r','e','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_SHUTDOWN_NAME_W[] = + { 'S','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_DEBUG_NAME_W[] = + { 'S','e','D','e','b','u','g','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_AUDIT_NAME_W[] = + { 'S','e','A','u','d','i','t','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_SYSTEM_ENVIRONMENT_NAME_W[] = + { 'S','e','S','y','s','t','e','m','E','n','v','i','r','o','n','m','e','n','t','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_CHANGE_NOTIFY_NAME_W[] = + { 'S','e','C','h','a','n','g','e','N','o','t','i','f','y','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_REMOTE_SHUTDOWN_NAME_W[] = + { 'S','e','R','e','m','o','t','e','S','h','u','t','d','o','w','n','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_UNDOCK_NAME_W[] = + { 'S','e','U','n','d','o','c','k','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_SYNC_AGENT_NAME_W[] = + { 'S','e','S','y','n','c','A','g','e','n','t','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_ENABLE_DELEGATION_NAME_W[] = + { 'S','e','E','n','a','b','l','e','D','e','l','e','g','a','t','i','o','n','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_MANAGE_VOLUME_NAME_W[] = + { 'S','e','M','a','n','a','g','e','V','o','l','u','m','e','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_IMPERSONATE_NAME_W[] = + { 'S','e','I','m','p','e','r','s','o','n','a','t','e','P','r','i','v','i','l','e','g','e',0 }; +static const WCHAR SE_CREATE_GLOBAL_NAME_W[] = + { 'S','e','C','r','e','a','t','e','G','l','o','b','a','l','P','r','i','v','i','l','e','g','e',0 }; + +static const WCHAR * const WellKnownPrivNames[SE_MAX_WELL_KNOWN_PRIVILEGE + 1] = +{ + NULL, + NULL, + SE_CREATE_TOKEN_NAME_W, + SE_ASSIGNPRIMARYTOKEN_NAME_W, + SE_LOCK_MEMORY_NAME_W, + SE_INCREASE_QUOTA_NAME_W, + SE_MACHINE_ACCOUNT_NAME_W, + SE_TCB_NAME_W, + SE_SECURITY_NAME_W, + SE_TAKE_OWNERSHIP_NAME_W, + SE_LOAD_DRIVER_NAME_W, + SE_SYSTEM_PROFILE_NAME_W, + SE_SYSTEMTIME_NAME_W, + SE_PROF_SINGLE_PROCESS_NAME_W, + SE_INC_BASE_PRIORITY_NAME_W, + SE_CREATE_PAGEFILE_NAME_W, + SE_CREATE_PERMANENT_NAME_W, + SE_BACKUP_NAME_W, + SE_RESTORE_NAME_W, + SE_SHUTDOWN_NAME_W, + SE_DEBUG_NAME_W, + SE_AUDIT_NAME_W, + SE_SYSTEM_ENVIRONMENT_NAME_W, + SE_CHANGE_NOTIFY_NAME_W, + SE_REMOTE_SHUTDOWN_NAME_W, + SE_UNDOCK_NAME_W, + SE_SYNC_AGENT_NAME_W, + SE_ENABLE_DELEGATION_NAME_W, + SE_MANAGE_VOLUME_NAME_W, + SE_IMPERSONATE_NAME_W, + SE_CREATE_GLOBAL_NAME_W, +}; + +static const WCHAR * const DefaultPrivNames[] = +{ + L"SeCreateTokenPrivilege", + L"SeAssignPrimaryTokenPrivilege", + L"SeLockMemoryPrivilege", + L"SeIncreaseQuotaPrivilege", + L"SeMachineAccountPrivilege", + L"SeTcbPrivilege", + L"SeSecurityPrivilege", + L"SeTakeOwnershipPrivilege", + L"SeLoadDriverPrivilege", + L"SeSystemProfilePrivilege", + L"SeSystemtimePrivilege", + L"SeProfileSingleProcessPrivilege", + L"SeIncreaseBasePriorityPrivilege", + L"SeCreatePagefilePrivilege", + L"SeCreatePermanentPrivilege", + L"SeBackupPrivilege", + L"SeRestorePrivilege", + L"SeShutdownPrivilege", + L"SeDebugPrivilege", + L"SeAuditPrivilege", + L"SeSystemEnvironmentPrivilege", + L"SeChangeNotifyPrivilege", + L"SeRemoteShutdownPrivilege", + L"SeUndockPrivilege", + L"SeSyncAgentPrivilege", + L"SeEnableDelegationPrivilege", + L"SeManageVolumePrivilege", + L"SeImpersonatePrivilege", + L"SeCreateGlobalPrivilege" +}; + + +NTSTATUS +LsarpLookupPrivilegeName(PLUID Value, + PUNICODE_STRING *Name) +{ + PUNICODE_STRING NameBuffer; + + if (Value->HighPart || + (Value->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE || + Value->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE)) + { + return STATUS_NO_SUCH_PRIVILEGE; + } + + NameBuffer = MIDL_user_allocate(sizeof(UNICODE_STRING)); + if (NameBuffer == NULL) + return STATUS_NO_MEMORY; + + NameBuffer->Length = wcslen(WellKnownPrivNames[Value->LowPart]) * sizeof(WCHAR); + NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR); + + NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength); + if (NameBuffer == NULL) + { + MIDL_user_free(NameBuffer); + return STATUS_NO_MEMORY; + } + + wcscpy(NameBuffer->Buffer, WellKnownPrivNames[Value->LowPart]); + + *Name = NameBuffer; + + return STATUS_SUCCESS; +} + + +NTSTATUS +LsarpLookupPrivilegeValue(PUNICODE_STRING Name, + PLUID Value) +{ + ULONG Priv; + + if (Name->Length == 0 || Name->Buffer == NULL) + return STATUS_NO_SUCH_PRIVILEGE; + + for (Priv = 0; Priv < sizeof(DefaultPrivNames) / sizeof(DefaultPrivNames[0]); Priv++) + { + if (0 == _wcsicmp(Name->Buffer, DefaultPrivNames[Priv])) + { + Value->LowPart = Priv + SE_MIN_WELL_KNOWN_PRIVILEGE; + Value->HighPart = 0; + return STATUS_SUCCESS; + } + } + + return STATUS_NO_SUCH_PRIVILEGE; +} diff --git a/reactos/include/psdk/ntsecapi.h b/reactos/include/psdk/ntsecapi.h index 2aed58d277b..885315385b9 100644 --- a/reactos/include/psdk/ntsecapi.h +++ b/reactos/include/psdk/ntsecapi.h @@ -698,6 +698,7 @@ NTSTATUS NTAPI LsaLookupNames(LSA_HANDLE,ULONG,PLSA_UNICODE_STRING, PLSA_REFERENCED_DOMAIN_LIST*,PLSA_TRANSLATED_SID*); NTSTATUS NTAPI LsaLookupNames2(LSA_HANDLE,ULONG,ULONG,PLSA_UNICODE_STRING, PLSA_REFERENCED_DOMAIN_LIST*,PLSA_TRANSLATED_SID2*); +NTSTATUS NTAPI LsaLookupPrivilegeName(LSA_HANDLE, PLUID, PLSA_UNICODE_STRING*); NTSTATUS NTAPI LsaLookupPrivilegeValue(LSA_HANDLE, PLSA_UNICODE_STRING, PLUID); NTSTATUS NTAPI LsaLookupSids(LSA_HANDLE,ULONG,PSID*, PLSA_REFERENCED_DOMAIN_LIST*,PLSA_TRANSLATED_NAME*); -- 2.17.1