From: Ariel Darshan <abdaandroid(a)gmail.com>
Signed-off-by: Ariel Darshan <abdaandroid(a)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