从 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 functiondwFlags 参数包含以位 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;
}