📄 store.c
字号:
return ret;
}
/* If force is true or the registry store is dirty, writes the contents of the
* store to the registry.
*/
static BOOL CRYPT_RegFlushStore(PWINE_REGSTOREINFO store, BOOL force)
{
BOOL ret;
TRACE("(%p, %d)\n", store, force);
if (store->dirty || force)
ret = CRYPT_RegWriteToReg(store);
else
ret = TRUE;
return ret;
}
static void WINAPI CRYPT_RegCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
{
PWINE_REGSTOREINFO store = (PWINE_REGSTOREINFO)hCertStore;
TRACE("(%p, %08x)\n", store, dwFlags);
if (dwFlags)
FIXME("Unimplemented flags: %08x\n", dwFlags);
CRYPT_RegFlushStore(store, FALSE);
RegCloseKey(store->key);
store->cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&store->cs);
CryptMemFree(store);
}
static BOOL WINAPI CRYPT_RegWriteContext(PWINE_REGSTOREINFO store,
const void *context, DWORD dwFlags)
{
BOOL ret;
if (dwFlags & CERT_STORE_PROV_WRITE_ADD_FLAG)
{
store->dirty = TRUE;
ret = TRUE;
}
else
ret = FALSE;
return ret;
}
static BOOL CRYPT_RegDeleteContext(PWINE_REGSTOREINFO store,
struct list *deleteList, const void *context,
PCWINE_CONTEXT_INTERFACE contextInterface)
{
BOOL ret;
if (store->dwOpenFlags & CERT_STORE_READONLY_FLAG)
{
SetLastError(ERROR_ACCESS_DENIED);
ret = FALSE;
}
else
{
PWINE_HASH_TO_DELETE toDelete =
CryptMemAlloc(sizeof(WINE_HASH_TO_DELETE));
if (toDelete)
{
DWORD size = sizeof(toDelete->hash);
ret = contextInterface->getProp(context, CERT_HASH_PROP_ID,
toDelete->hash, &size);
if (ret)
{
EnterCriticalSection(&store->cs);
list_add_tail(deleteList, &toDelete->entry);
LeaveCriticalSection(&store->cs);
}
else
{
CryptMemFree(toDelete);
ret = FALSE;
}
}
else
ret = FALSE;
if (ret)
store->dirty = TRUE;
}
return ret;
}
static BOOL WINAPI CRYPT_RegWriteCert(HCERTSTORE hCertStore,
PCCERT_CONTEXT cert, DWORD dwFlags)
{
PWINE_REGSTOREINFO store = (PWINE_REGSTOREINFO)hCertStore;
TRACE("(%p, %p, %d)\n", hCertStore, cert, dwFlags);
return CRYPT_RegWriteContext(store, cert, dwFlags);
}
static BOOL WINAPI CRYPT_RegDeleteCert(HCERTSTORE hCertStore,
PCCERT_CONTEXT pCertContext, DWORD dwFlags)
{
PWINE_REGSTOREINFO store = (PWINE_REGSTOREINFO)hCertStore;
TRACE("(%p, %p, %08x)\n", store, pCertContext, dwFlags);
return CRYPT_RegDeleteContext(store, &store->certsToDelete, pCertContext,
pCertInterface);
}
static BOOL WINAPI CRYPT_RegWriteCRL(HCERTSTORE hCertStore,
PCCRL_CONTEXT crl, DWORD dwFlags)
{
PWINE_REGSTOREINFO store = (PWINE_REGSTOREINFO)hCertStore;
TRACE("(%p, %p, %d)\n", hCertStore, crl, dwFlags);
return CRYPT_RegWriteContext(store, crl, dwFlags);
}
static BOOL WINAPI CRYPT_RegDeleteCRL(HCERTSTORE hCertStore,
PCCRL_CONTEXT pCrlContext, DWORD dwFlags)
{
PWINE_REGSTOREINFO store = (PWINE_REGSTOREINFO)hCertStore;
TRACE("(%p, %p, %08x)\n", store, pCrlContext, dwFlags);
return CRYPT_RegDeleteContext(store, &store->crlsToDelete, pCrlContext,
pCRLInterface);
}
static BOOL WINAPI CRYPT_RegControl(HCERTSTORE hCertStore, DWORD dwFlags,
DWORD dwCtrlType, void const *pvCtrlPara)
{
PWINE_REGSTOREINFO store = (PWINE_REGSTOREINFO)hCertStore;
BOOL ret;
TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
pvCtrlPara);
switch (dwCtrlType)
{
case CERT_STORE_CTRL_RESYNC:
CRYPT_RegFlushStore(store, FALSE);
CRYPT_MemEmptyStore((PWINE_MEMSTORE)store->memStore);
CRYPT_RegReadFromReg(store);
ret = TRUE;
break;
case CERT_STORE_CTRL_COMMIT:
ret = CRYPT_RegFlushStore(store,
dwFlags & CERT_STORE_CTRL_COMMIT_FORCE_FLAG);
break;
default:
FIXME("%d: stub\n", dwCtrlType);
ret = FALSE;
}
return ret;
}
/* Copied from shlwapi's SHDeleteKeyW, and reformatted to match this file. */
static DWORD CRYPT_RecurseDeleteKey(HKEY hKey, LPCWSTR lpszSubKey)
{
DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
HKEY hSubKey = 0;
TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
if (!dwRet)
{
/* Find how many subkeys there are */
dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
&dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
if (!dwRet)
{
dwMaxSubkeyLen++;
if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
{
/* Name too big: alloc a buffer for it */
lpszName = CryptMemAlloc(dwMaxSubkeyLen*sizeof(WCHAR));
}
if (!lpszName)
dwRet = ERROR_NOT_ENOUGH_MEMORY;
else
{
/* Recursively delete all the subkeys */
for (i = 0; i < dwKeyCount && !dwRet; i++)
{
dwSize = dwMaxSubkeyLen;
dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL,
NULL, NULL, NULL);
if (!dwRet)
dwRet = CRYPT_RecurseDeleteKey(hSubKey, lpszName);
}
if (lpszName != szNameBuf)
{
/* Free buffer if allocated */
CryptMemFree(lpszName);
}
}
}
RegCloseKey(hSubKey);
if (!dwRet)
dwRet = RegDeleteKeyW(hKey, lpszSubKey);
}
return dwRet;
}
static void *regProvFuncs[] = {
CRYPT_RegCloseStore,
NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */
CRYPT_RegWriteCert,
CRYPT_RegDeleteCert,
NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */
CRYPT_RegWriteCRL,
CRYPT_RegDeleteCRL,
NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */
NULL, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
NULL, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
CRYPT_RegControl,
};
static WINECRYPT_CERTSTORE *CRYPT_RegOpenStore(HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara)
{
PWINECRYPT_CERTSTORE store = NULL;
TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
if (dwFlags & CERT_STORE_DELETE_FLAG)
{
DWORD rc = CRYPT_RecurseDeleteKey((HKEY)pvPara, CertsW);
if (rc == ERROR_SUCCESS || rc == ERROR_NO_MORE_ITEMS)
rc = CRYPT_RecurseDeleteKey((HKEY)pvPara, CRLsW);
if (rc == ERROR_SUCCESS || rc == ERROR_NO_MORE_ITEMS)
rc = CRYPT_RecurseDeleteKey((HKEY)pvPara, CTLsW);
if (rc == ERROR_NO_MORE_ITEMS)
rc = ERROR_SUCCESS;
SetLastError(rc);
}
else
{
HKEY key;
if (DuplicateHandle(GetCurrentProcess(), (HANDLE)pvPara,
GetCurrentProcess(), (LPHANDLE)&key,
dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ : KEY_ALL_ACCESS,
TRUE, 0))
{
PWINECRYPT_CERTSTORE memStore;
memStore = CRYPT_MemOpenStore(hCryptProv, dwFlags, NULL);
if (memStore)
{
PWINE_REGSTOREINFO regInfo = CryptMemAlloc(
sizeof(WINE_REGSTOREINFO));
if (regInfo)
{
CERT_STORE_PROV_INFO provInfo = { 0 };
regInfo->dwOpenFlags = dwFlags;
regInfo->cryptProv = hCryptProv;
regInfo->memStore = memStore;
regInfo->key = key;
InitializeCriticalSection(®Info->cs);
regInfo->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PWINE_REGSTOREINFO->cs");
list_init(®Info->certsToDelete);
list_init(®Info->crlsToDelete);
CRYPT_RegReadFromReg(regInfo);
regInfo->dirty = FALSE;
provInfo.cbSize = sizeof(provInfo);
provInfo.cStoreProvFunc = sizeof(regProvFuncs) /
sizeof(regProvFuncs[0]);
provInfo.rgpvStoreProvFunc = regProvFuncs;
provInfo.hStoreProv = regInfo;
store = CRYPT_ProvCreateStore(hCryptProv, dwFlags, memStore,
&provInfo);
}
}
}
}
TRACE("returning %p\n", store);
return 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 };
LPCWSTR storeName = (LPCWSTR)pvPara;
LPWSTR storePath;
PWINECRYPT_CERTSTORE store = NULL;
HKEY root;
LPCWSTR base;
BOOL ret;
TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
debugstr_w((LPCWSTR)pvPara));
if (!pvPara)
{
SetLastError(E_INVALIDARG);
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(E_INVALIDARG);
return NULL;
}
storePath = CryptMemAlloc((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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -