[ADVAPI32/LSASRV]
authorEric Kohl <eric.kohl@reactos.org>
Sun, 4 Jul 2010 12:51:39 +0000 (12:51 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 4 Jul 2010 12:51:39 +0000 (12:51 +0000)
- 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
reactos/dll/win32/advapi32/sec/misc.c
reactos/dll/win32/lsasrv/lsarpc.c
reactos/dll/win32/lsasrv/lsasrv.h
reactos/dll/win32/lsasrv/lsasrv.rbuild
reactos/dll/win32/lsasrv/privileges.c [new file with mode: 0644]
reactos/include/psdk/ntsecapi.h

index 6c34400..10bb1e6 100644 (file)
@@ -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;
index f8fb383..b92fbec 100644 (file)
@@ -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;
 }
 
 
index e7e4c17..57f802b 100644 (file)
@@ -6,6 +6,9 @@
 #define NTOS_MODE_USER
 #include <ndk/ntndk.h>
 
+#include <string.h>
+
+#include "lsasrv.h"
 #include "lsa_s.h"
 
 #include <wine/debug.h>
@@ -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;
 }
 
 
index 1599508..00b1a77 100644 (file)
@@ -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
index 840599c..d1d122e 100644 (file)
@@ -11,5 +11,6 @@
        <file>authport.c</file>
        <file>lsarpc.c</file>
        <file>lsasrv.c</file>
+       <file>privileges.c</file>
        <file>lsasrv.rc</file>
 </module>
diff --git a/reactos/dll/win32/lsasrv/privileges.c b/reactos/dll/win32/lsasrv/privileges.c
new file mode 100644 (file)
index 0000000..0154161
--- /dev/null
@@ -0,0 +1,197 @@
+#define WIN32_NO_STATUS
+#include <windows.h>
+#include <ntsecapi.h>
+#define NTOS_MODE_USER
+#include <ndk/ntndk.h>
+
+#include <wchar.h>
+#include <string.h>
+
+
+#include <wine/debug.h>
+
+
+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;
+}
index 2aed58d..8853153 100644 (file)
@@ -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*);