Commit 1cf56599 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

Implement system registry stores.

parent e385fc5c
......@@ -31,6 +31,7 @@
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winreg.h"
#include "winuser.h"
#include "wincrypt.h"
......@@ -1395,6 +1396,145 @@ static WINECRYPT_CERTSTORE *CRYPT_RegOpenStore(HCRYPTPROV hCryptProv,
return (WINECRYPT_CERTSTORE *)store;
}
/* FIXME: this isn't complete for the Root store, in which the top-level
* self-signed CA certs reside. Adding a cert to the Root store should present
* the user with a dialog indicating the consequences of doing so, and asking
* the user to confirm whether the cert should be added.
*/
static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara)
{
static const WCHAR fmt[] = { '%','s','\\','%','s',0 };
LPWSTR storeName = (LPWSTR)pvPara;
LPWSTR storePath;
PWINECRYPT_CERTSTORE store = NULL;
HKEY root;
LPCWSTR base;
BOOL ret;
TRACE("(%ld, %08lx, %s)\n", hCryptProv, dwFlags,
debugstr_w((LPCWSTR)pvPara));
if (!pvPara)
{
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
return NULL;
}
ret = TRUE;
switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
{
case CERT_SYSTEM_STORE_LOCAL_MACHINE:
root = HKEY_LOCAL_MACHINE;
base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
break;
case CERT_SYSTEM_STORE_CURRENT_USER:
root = HKEY_CURRENT_USER;
base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
break;
case CERT_SYSTEM_STORE_CURRENT_SERVICE:
/* hklm\Software\Microsoft\Cryptography\Services\servicename\
* SystemCertificates
*/
FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
debugstr_w(storeName));
return NULL;
case CERT_SYSTEM_STORE_SERVICES:
/* hklm\Software\Microsoft\Cryptography\Services\servicename\
* SystemCertificates
*/
FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
debugstr_w(storeName));
return NULL;
case CERT_SYSTEM_STORE_USERS:
/* hku\user sid\Software\Microsoft\SystemCertificates */
FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
debugstr_w(storeName));
return NULL;
case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
root = HKEY_CURRENT_USER;
base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
break;
case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
root = HKEY_LOCAL_MACHINE;
base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
break;
case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
/* hklm\Software\Microsoft\EnterpriseCertificates */
FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
debugstr_w(storeName));
return NULL;
default:
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
return NULL;
}
storePath = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(base) +
lstrlenW(storeName) + 2) * sizeof(WCHAR));
if (storePath)
{
LONG rc;
HKEY key;
REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
KEY_ALL_ACCESS;
wsprintfW(storePath, fmt, base, storeName);
if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
else
{
DWORD disp;
rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
&key, &disp);
if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
disp == REG_OPENED_EXISTING_KEY)
{
RegCloseKey(key);
rc = ERROR_FILE_EXISTS;
}
}
if (!rc)
{
store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
RegCloseKey(key);
}
else
SetLastError(rc);
HeapFree(GetProcessHeap(), 0, storePath);
}
return store;
}
static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara)
{
int len;
PWINECRYPT_CERTSTORE ret = NULL;
TRACE("(%ld, %08lx, %s)\n", hCryptProv, dwFlags,
debugstr_a((LPCSTR)pvPara));
if (!pvPara)
{
SetLastError(ERROR_FILE_NOT_FOUND);
return NULL;
}
len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
if (len)
{
LPWSTR storeName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (storeName)
{
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
HeapFree(GetProcessHeap(), 0, storeName);
}
}
return ret;
}
static void WINAPI CRYPT_DummyCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
{
HeapFree(GetProcessHeap(), 0, (PWINECRYPT_CERTSTORE)hCertStore);
......@@ -1476,6 +1616,12 @@ HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
case (int)CERT_STORE_PROV_SYSTEM_W:
openFunc = CRYPT_DummyOpenStore;
break;
case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_A:
openFunc = CRYPT_SysRegOpenStoreA;
break;
case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_W:
openFunc = CRYPT_SysRegOpenStoreW;
break;
default:
if (LOWORD(lpszStoreProvider))
FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
......@@ -1487,6 +1633,8 @@ HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
openFunc = CRYPT_DummyOpenStore;
else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
openFunc = CRYPT_CollectionOpenStore;
else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
openFunc = CRYPT_SysRegOpenStoreW;
else
{
FIXME("unimplemented type %s\n", lpszStoreProvider);
......
......@@ -883,11 +883,7 @@ static void testRegStore(void)
{
RegCloseKey(key);
rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
/* There seems to be a bug in the registry code, not sure if it's a
* race condition in the recurse delete key implementation here, or if
* it's elsewhere in wine. Marking todo_wine for now.
*/
todo_wine ok(!rc, "RegDeleteKeyA failed: %ld\n", rc);
ok(!rc, "RegDeleteKeyA failed: %ld\n", rc);
if (rc)
{
HMODULE shlwapi = LoadLibraryA("shlwapi");
......@@ -908,6 +904,77 @@ static void testRegStore(void)
}
}
static const char MyA[] = { 'M','y',0,0 };
static const WCHAR MyW[] = { 'M','y',0 };
static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
static void testSystemRegStore(void)
{
HCERTSTORE store, memStore;
/* Check with a UNICODE name */
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
/* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
* testing if they don't.
*/
if (!store)
return;
/* Check that it isn't a collection store */
memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
CERT_STORE_CREATE_NEW_FLAG, NULL);
if (memStore)
{
BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
ok(!ret && GetLastError() ==
HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
CertCloseStore(memStore, 0);
}
CertCloseStore(store, 0);
/* Check opening a bogus store */
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
"Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
if (store)
CertCloseStore(store, 0);
/* Now check whether deleting is allowed */
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
/* The name is expected to be UNICODE, check with an ASCII name */
store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
"Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
}
static void testCertProperties(void)
{
PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
......@@ -1186,6 +1253,7 @@ START_TEST(cert)
testMemStore();
testCollectionStore();
testRegStore();
testSystemRegStore();
testCertProperties();
testAddSerialized();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment