[PATCH 01/16] ncrypt: Implement NCryptEnumStorageProviders

Hans Leidekker hans at codeweavers.com
Mon Oct 12 06:50:23 CDT 2020


Hi Ariel,

Thanks for your contribution.

> 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;

We try to avoid Hungarian notation. Please use names like out_count, num_keys, etc.

> +    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);

This should be a WARN or TRACE at most.

> +        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");

I don't think this is worth an error message.

> +                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);
> +        }

The reallocated buffer may have moved. You don't need these casts if
you make allocBuffer a BYTE *.

> +
> +
> +
> +        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)

Some tests would be nice.





More information about the wine-devel mailing list