从 CertEnumSystemStoreLocation() 到 CertEnumSystemStore()
Step from CertEnumSystemStoreLocation() to CertEnumSystemStore()
我的问题是关于 cryptoAPI 接口。
看,CertEnumSystemStoreLocation() 是一个函数,用于枚举系统中所有可用的证书存储位置。它 returns(使用回调)将位置枚举为宽字符串 (LPCWSTR)。
CertEnumSystemStore() 按给定位置枚举商店。它以位置整数常量 (DWORD) 作为参数。
我尝试枚举位置,结果是一个字符串列表,在语义上等于来自 CryptoAPI 导入模块的 DWORD 位置常量列表。
我的问题是:我应该如何将存储位置的宽字符串表示形式转换为 DWORD 常量?是否有针对它的 cryptoAPI 函数(或者,至少,常用方法)?
看起来传递给您的 CertEnumSystemStoreLocationCallback
回调函数的 dwFlags
实际上为您提供了商店位置常量,尽管这被记录得非常糟糕。
此处显示的 Listing System and Physical Stores 示例在其回调中处理 dwFlags
值,如下所示:
dwFlags &= CERT_SYSTEM_STORE_MASK;
dwFlags |= pEnumArg->dwFlags & ~CERT_SYSTEM_STORE_LOCATION_MASK;
CertEnumSystemStore(dwFlags, ...);
所以我认为,如果您执行该屏蔽操作,您将在 dwFlags
中留下位置常量,相当于 pvszStoreLocation
参数中传递的字符串。
传递给 CertEnumSystemStoreLocationCallback callback function 的 dwFlags
参数包含以位 CERT_SYSTEM_STORE_LOCATION_MASK
编码的存储位置。将它们向右移动 CERT_SYSTEM_STORE_LOCATION_SHIFT
将其变成数字商店 ID。
以下代码检索商店位置列表以及数字商店 ID:
通信结构:
#include <SDKDDKVer.h>
#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "Crypt32.lib")
#include <vector>
#include <string>
#include <iostream>
struct Location {
DWORD StoreId;
std::wstring Name;
};
typedef std::vector<Location> StoreLocationsContainer;
回调:
BOOL WINAPI CertEnumSystemStoreLocationCallback( LPCWSTR pvszStoreLocations,
DWORD dwFlags,
void* pvReserved,
void* pvArg
) {
StoreLocationsContainer& locations = *reinterpret_cast<StoreLocationsContainer*>( pvArg );
DWORD StoreId = ( dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK )
>> CERT_SYSTEM_STORE_LOCATION_SHIFT;
Location location = { StoreId, std::wstring( pvszStoreLocations ) };
locations.push_back( location );
return TRUE;
}
实施:
StoreLocationsContainer GetStoreLocations() {
StoreLocationsContainer locations;
if ( !::CertEnumSystemStoreLocation( 0x0,
&locations,
CertEnumSystemStoreLocationCallback ) ) {
throw std::runtime_error( "CertEnumSystemStoreLocation" );
}
return locations;
}
为了完整起见,这里是转储所有位置的所有商店的剩余代码:
BOOL WINAPI CertEnumSystemStoreCallback( const void* pvSystemStore,
DWORD dwFlags,
PCERT_SYSTEM_STORE_INFO pStoreInfo,
void* pvReserved,
void* pvArg ) {
std::wcout << L" " << static_cast<const wchar_t*>( pvSystemStore ) << std::endl;
return TRUE;
}
void PrintStores( const StoreLocationsContainer& locations ) {
for ( const Location& loc : locations ) {
std::wcout << loc.Name << std::endl;
DWORD dwFlags = ( loc.StoreId << CERT_SYSTEM_STORE_LOCATION_SHIFT )
& CERT_SYSTEM_STORE_LOCATION_MASK;
::CertEnumSystemStore( dwFlags, nullptr, nullptr, CertEnumSystemStoreCallback );
}
}
int main() {
StoreLocationsContainer locations = GetStoreLocations();
PrintStores( locations );
return 0;
}
我的问题是关于 cryptoAPI 接口。
看,CertEnumSystemStoreLocation() 是一个函数,用于枚举系统中所有可用的证书存储位置。它 returns(使用回调)将位置枚举为宽字符串 (LPCWSTR)。
CertEnumSystemStore() 按给定位置枚举商店。它以位置整数常量 (DWORD) 作为参数。
我尝试枚举位置,结果是一个字符串列表,在语义上等于来自 CryptoAPI 导入模块的 DWORD 位置常量列表。
我的问题是:我应该如何将存储位置的宽字符串表示形式转换为 DWORD 常量?是否有针对它的 cryptoAPI 函数(或者,至少,常用方法)?
看起来传递给您的 CertEnumSystemStoreLocationCallback
回调函数的 dwFlags
实际上为您提供了商店位置常量,尽管这被记录得非常糟糕。
此处显示的 Listing System and Physical Stores 示例在其回调中处理 dwFlags
值,如下所示:
dwFlags &= CERT_SYSTEM_STORE_MASK;
dwFlags |= pEnumArg->dwFlags & ~CERT_SYSTEM_STORE_LOCATION_MASK;
CertEnumSystemStore(dwFlags, ...);
所以我认为,如果您执行该屏蔽操作,您将在 dwFlags
中留下位置常量,相当于 pvszStoreLocation
参数中传递的字符串。
传递给 CertEnumSystemStoreLocationCallback callback function 的 dwFlags
参数包含以位 CERT_SYSTEM_STORE_LOCATION_MASK
编码的存储位置。将它们向右移动 CERT_SYSTEM_STORE_LOCATION_SHIFT
将其变成数字商店 ID。
以下代码检索商店位置列表以及数字商店 ID:
通信结构:
#include <SDKDDKVer.h>
#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "Crypt32.lib")
#include <vector>
#include <string>
#include <iostream>
struct Location {
DWORD StoreId;
std::wstring Name;
};
typedef std::vector<Location> StoreLocationsContainer;
回调:
BOOL WINAPI CertEnumSystemStoreLocationCallback( LPCWSTR pvszStoreLocations,
DWORD dwFlags,
void* pvReserved,
void* pvArg
) {
StoreLocationsContainer& locations = *reinterpret_cast<StoreLocationsContainer*>( pvArg );
DWORD StoreId = ( dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK )
>> CERT_SYSTEM_STORE_LOCATION_SHIFT;
Location location = { StoreId, std::wstring( pvszStoreLocations ) };
locations.push_back( location );
return TRUE;
}
实施:
StoreLocationsContainer GetStoreLocations() {
StoreLocationsContainer locations;
if ( !::CertEnumSystemStoreLocation( 0x0,
&locations,
CertEnumSystemStoreLocationCallback ) ) {
throw std::runtime_error( "CertEnumSystemStoreLocation" );
}
return locations;
}
为了完整起见,这里是转储所有位置的所有商店的剩余代码:
BOOL WINAPI CertEnumSystemStoreCallback( const void* pvSystemStore,
DWORD dwFlags,
PCERT_SYSTEM_STORE_INFO pStoreInfo,
void* pvReserved,
void* pvArg ) {
std::wcout << L" " << static_cast<const wchar_t*>( pvSystemStore ) << std::endl;
return TRUE;
}
void PrintStores( const StoreLocationsContainer& locations ) {
for ( const Location& loc : locations ) {
std::wcout << loc.Name << std::endl;
DWORD dwFlags = ( loc.StoreId << CERT_SYSTEM_STORE_LOCATION_SHIFT )
& CERT_SYSTEM_STORE_LOCATION_MASK;
::CertEnumSystemStore( dwFlags, nullptr, nullptr, CertEnumSystemStoreCallback );
}
}
int main() {
StoreLocationsContainer locations = GetStoreLocations();
PrintStores( locations );
return 0;
}