[PATCH 01/16] ncrypt: Implement NCryptEnumStorageProviders

abdaandroid at gmail.com abdaandroid at gmail.com
Sun Oct 11 10:45:20 CDT 2020


From: Ariel Darshan <abdaandroid at gmail.com>

Signed-off-by: Ariel Darshan <abdaandroid at gmail.com>
---
 dlls/ncrypt/Makefile.in |   2 +
 dlls/ncrypt/main.c      | 127 +++++++++++++++++++++++++++++++++++++++-
 dlls/ncrypt/ncrypt.spec |   2 +-
 include/ncrypt.h        |   7 +++
 4 files changed, 135 insertions(+), 3 deletions(-)

diff --git a/dlls/ncrypt/Makefile.in b/dlls/ncrypt/Makefile.in
index c387c35d854..dc9d3fbdc28 100644
--- a/dlls/ncrypt/Makefile.in
+++ b/dlls/ncrypt/Makefile.in
@@ -1,5 +1,7 @@
 MODULE    = ncrypt.dll
 
+IMPORTS = advapi32
+
 EXTRADLLFLAGS = -mno-cygwin
 
 C_SRCS = \
diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c
index c0cc05c43ca..86bc9190717 100644
--- a/dlls/ncrypt/main.c
+++ b/dlls/ncrypt/main.c
@@ -23,7 +23,9 @@
 #include "windef.h"
 #include "winbase.h"
 #include "ncrypt.h"
+#include "winreg.h"
 #include "wine/debug.h"
+#include "wine/heap.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ncrypt);
 
@@ -89,6 +91,123 @@ SECURITY_STATUS WINAPI NCryptEnumKeys(NCRYPT_PROV_HANDLE provider, const WCHAR *
     return NTE_NOT_SUPPORTED;
 }
 
+SECURITY_STATUS WINAPI NCryptEnumStorageProviders(DWORD *providerCount, NCryptProviderName **providerList, DWORD flags)
+{
+    HKEY hKey;
+    HKEY hSubKey;
+    SECURITY_STATUS ret;
+    LSTATUS status;
+    DWORD maxKeyLen;
+    DWORD i;
+    WCHAR providerName[MAX_PATH];
+    WCHAR providerKSReg[MAX_PATH];
+    DWORD providerNameLength;
+    NCryptProviderName *outList;
+    DWORD outCount;
+    DWORD numKeys;
+    void *allocBuffer;
+    void *reAllocBuffer;
+    DWORD allocSize;
+    DWORD totalNamesSize;
+
+    TRACE("(%p, %p, 0x%08x)\n", providerCount, providerList, flags);
+
+    if (flags)
+    {
+        FIXME("Ignoring flags: 0x%08x - Not implemented\n", flags);
+    }
+
+    ret = ERROR_SUCCESS;
+    outList = NULL;
+    outCount = 0;
+    allocSize = 0;
+
+    status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Cryptography\\Providers", 0, KEY_READ, &hKey);
+    if (status != ERROR_SUCCESS)
+    {
+        ERR("Failed to open 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\Cryptography\\Providers' error code: 0x%08x\n", status);
+        return NTE_NOT_SUPPORTED; /* FIXME: what should be returned here? */
+    }
+
+    status = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &numKeys, &maxKeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
+    if (status != ERROR_SUCCESS)
+    {
+        ERR("Failed to query info on 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\Cryptography\\Providers' error code: 0x%08x\n", status);
+        ret = NTE_NOT_SUPPORTED; /* FIXME: what should be returned here? */
+        goto cleanup;
+    }
+
+
+    for (i = 0; i < numKeys; ++i)
+    {
+        providerNameLength = MAX_PATH;
+        status = RegEnumKeyExW(hKey, i, providerName, &providerNameLength, NULL, NULL, NULL, NULL);
+        if (status != ERROR_SUCCESS)
+        {
+            ERR("Failed to enumerate sub keys of 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\Cryptography\\Providers' error code: 0x%08x\n", status);
+            ret = NTE_NOT_SUPPORTED; /* FIXME: what should be returned here? */
+            goto cleanup;
+        }
+
+
+        /* This registry key should exist if the provider supports key storage */
+        swprintf(providerKSReg, MAX_PATH - 1, L"%s\\UM\\00010001", providerName);
+        status = RegOpenKeyExW(hKey, providerKSReg, 0, KEY_READ, &hSubKey);
+        if (status != ERROR_SUCCESS)
+        {
+            /* Provider doesn't support key storage, skip it */
+            continue;
+        }
+        RegCloseKey(hSubKey);
+
+        allocSize += sizeof(NCryptProviderName) + (providerNameLength + 1) * sizeof(WCHAR);
+        if (!outCount++)
+        {
+            allocBuffer = heap_alloc(allocSize);
+            if (!allocBuffer)
+            {
+                ERR("Out of memory!\n");
+                ret = NTE_NO_MEMORY;
+                goto cleanup;
+            }
+            totalNamesSize = 0;
+        }
+        else
+        {
+            reAllocBuffer = heap_realloc(allocBuffer, allocSize);
+            if (!reAllocBuffer)
+            {
+                ERR("Out of memory during realloc!\n");
+                heap_free(allocBuffer);
+                ret = NTE_NO_MEMORY;
+                goto cleanup;
+            }
+            /* Shift the wstrings that contain the names over by the size of one struct */
+            memmove((BYTE*)allocBuffer + outCount * sizeof(NCryptProviderName), (BYTE*)allocBuffer + (outCount - 1) * sizeof(NCryptProviderName), totalNamesSize);
+        }
+
+
+
+        outList = allocBuffer;
+        outList[outCount - 1].pszName = (WCHAR*)((BYTE*)allocBuffer + outCount * sizeof(NCryptProviderName) + totalNamesSize);
+        outList[outCount - 1].pszComment = NULL;
+
+        wcscpy(outList[outCount - 1].pszName, providerName);
+        totalNamesSize += (providerNameLength + 1) * sizeof(WCHAR);
+    }
+
+
+cleanup:
+    if (ret == ERROR_SUCCESS)
+    {
+        *providerCount = outCount;
+        *providerList = outList;
+    }
+
+    RegCloseKey(hKey);
+    return ret;
+}
+
 SECURITY_STATUS WINAPI NCryptFinalizeKey(NCRYPT_KEY_HANDLE key, DWORD flags)
 {
     FIXME("(0x%lx, 0x%08x): stub\n", key, flags);
@@ -97,8 +216,12 @@ SECURITY_STATUS WINAPI NCryptFinalizeKey(NCRYPT_KEY_HANDLE key, DWORD flags)
 
 SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID buf)
 {
-    FIXME("(%p): stub\n", buf);
-    return NTE_NOT_SUPPORTED;
+    /* FIXME: How do we tell which provider should be called?
+                How do we update refCounts of referenced objects? */
+    FIXME("(%p): semi-stub\n", buf);
+
+    heap_free(buf);
+    return ERROR_SUCCESS;
 }
 
 SECURITY_STATUS WINAPI NCryptFreeObject(NCRYPT_HANDLE object)
diff --git a/dlls/ncrypt/ncrypt.spec b/dlls/ncrypt/ncrypt.spec
index 2b5a4fca420..2e6765c91ff 100644
--- a/dlls/ncrypt/ncrypt.spec
+++ b/dlls/ncrypt/ncrypt.spec
@@ -69,7 +69,7 @@
 @ stdcall NCryptEncrypt(long ptr long ptr ptr long ptr long)
 @ stdcall NCryptEnumAlgorithms(long long ptr ptr long)
 @ stdcall NCryptEnumKeys(long wstr ptr ptr long)
-@ stub NCryptEnumStorageProviders
+@ stdcall NCryptEnumStorageProviders(ptr ptr long)
 @ stub NCryptExportKey
 @ stdcall NCryptFinalizeKey(long long)
 @ stdcall NCryptFreeBuffer(ptr)
diff --git a/include/ncrypt.h b/include/ncrypt.h
index 111693f1d49..9110c1ef6a4 100644
--- a/include/ncrypt.h
+++ b/include/ncrypt.h
@@ -58,6 +58,11 @@ typedef struct NCryptKeyName {
     DWORD dwFlags;
 } NCryptKeyName;
 
+typedef struct _NCryptProviderName {
+    LPWSTR pszName;
+    LPWSTR pszComment;
+} NCryptProviderName;
+
 typedef ULONG_PTR NCRYPT_HANDLE;
 typedef ULONG_PTR NCRYPT_PROV_HANDLE;
 typedef ULONG_PTR NCRYPT_KEY_HANDLE;
@@ -72,7 +77,9 @@ typedef ULONG_PTR NCRYPT_SECRET_HANDLE;
 SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE, NCRYPT_KEY_HANDLE *, const WCHAR *, const WCHAR *, DWORD, DWORD);
 SECURITY_STATUS WINAPI NCryptDecrypt(NCRYPT_KEY_HANDLE, BYTE *, DWORD, void *, BYTE *, DWORD, DWORD *, DWORD);
 SECURITY_STATUS WINAPI NCryptEncrypt(NCRYPT_KEY_HANDLE, BYTE *, DWORD, void *, BYTE *, DWORD, DWORD *, DWORD);
+SECURITY_STATUS WINAPI NCryptEnumStorageProviders(DWORD *, NCryptProviderName **, DWORD);
 SECURITY_STATUS WINAPI NCryptFinalizeKey(NCRYPT_KEY_HANDLE, DWORD);
+SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID);
 SECURITY_STATUS WINAPI NCryptFreeObject(NCRYPT_HANDLE);
 SECURITY_STATUS WINAPI NCryptOpenKey(NCRYPT_PROV_HANDLE, NCRYPT_KEY_HANDLE *, const WCHAR *, DWORD, DWORD);
 SECURITY_STATUS WINAPI NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE *, const WCHAR *, DWORD);
-- 
2.28.0




More information about the wine-devel mailing list