2015-08-21 3 views
0

Мой вопрос касается интерфейса cryptoAPI.Шаг от CertEnumSystemStoreLocation() до CertEnumSystemStore()

Look, CertEnumSystemStoreLocation() - это функция, позволяющая перечислять все хранилища сертификатов, доступные в системе. Он возвращает (используя обратный вызов) нумеруемое местоположение в виде широкой строки (LPCWSTR).

CertEnumSystemStore() перечисляет магазины по данному местоположению. Он принимает целочисленную константу для определения местоположения (DWORD) в качестве аргумента.

Я попытался перечислить местоположения, и результатом был список строк, который семантически равен списку констант местоположения DWORD из модуля импорта CryptoAPI.

И мой вопрос: что я должен сделать, чтобы перевести широкое строковое представление местоположения магазина на постоянную DWORD? Есть ли функция cryptoAPI (или, по крайней мере, обычно используемый метод) для нее?

ответ

0

Аргумент dwFlags, переданный в CertEnumSystemStoreLocationCallback callback function, содержит местоположение магазина, закодированное в битах CERT_SYSTEM_STORE_LOCATION_MASK. Смещение их вправо на CERT_SYSTEM_STORE_LOCATION_SHIFT превращает его в числовой идентификатор магазина.

Следующий код возвращает список мест хранения наряду с идентификаторами цифровых магазинов:

Структура для связи:

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

Callback:

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

спасибо! Как я мог упустить из виду dwFlags в обратном вызове! – MrCat

1

Похоже, что dwFlags, переданный вашей функции обратного вызова CertEnumSystemStoreLocationCallback, фактически дает вам постоянную позицию магазина, хотя это невероятно плохо документировано.

Пример, показанный здесь Listing System and Physical Stores обрабатывает значение dwFlags в его обратном вызове, как это:

dwFlags &= CERT_SYSTEM_STORE_MASK; 
dwFlags |= pEnumArg->dwFlags & ~CERT_SYSTEM_STORE_LOCATION_MASK; 
CertEnumSystemStore(dwFlags, ...); 

Так что я думаю, что если вы сделаете это маскировка вас останетесь с константой местоположения в dwFlags эквивалентна строке передается в параметре pvszStoreLocation.

+0

Спасибо, этот ответ является правильным too.Unfortunatly, невозможно отметить более одного ответа – MrCat