りぺんぎんの書きなぐり技術書

基本、ITの技術について書きます

c++で接続されているUSBのシリアル番号を取得するプログラム

仕事でUSBライセンス認証機能をつくった。

MicroSoftサンプルソースをいじった

javaしかやっていなかった私はとても苦労しました。

汚い部分や非効率な部分もあるでしょうが多めに見てください

関数名も英語のできなさがでてて恥ずかしい

#include <devguid.h>//ココらへんのインクルードはどれ使うか忘れました
#include <regstr.h>

#include "stdafx.h"
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#include <string>
#include <fstream>
#include <iterator>
#include <stdlib.h>//ココらへんのインクルードはどれ使うか忘れました


#pragma comment(lib, "wbemuuid.lib")



//hash
string EncodeSerial(string word)
{
    //Hash
}
/*BSTRをSTringに変換*/
string BstrConvertToString(BSTR bst){  // 関数の定義
    //BSTRをcharに変換
    char Char[255]="";
    WideCharToMultiByte(
        CP_ACP,         // コードページ ANSI コードページ
        0,          // 処理速度とマッピング方法を決定するフラグ
        (OLECHAR*)bst,      // ワイド文字列のアドレス
        -1,         // ワイド文字列の文字数
        Char,           // 新しい文字列を受け取るバッファのアドレス
        sizeof(Char) - 1,       // 新しい文字列を受け取るバッファのサイズ
        NULL,           // マップできない文字の既定値のアドレス
        NULL            // 既定の文字を使ったときにセットするフラグのアドレス
    );
    //charをstringに変換
    string Str = Char;
    return Str;
}
/*StringをBSTRに変換*/
BSTR StringConvertToBstr(string str){  // 関数の定義
    LPSTR lstr = (LPSTR)str.c_str();
    //BSTRに必要なバッファサイズを求める
    int bstrlen=(int)MultiByteToWideChar(
        CP_ACP,         // コードページ ANSI コードページ
        0,          // 文字の種類を指定するフラグ
        lstr,           // マップ元文字列のアドレス
        strlen(lstr),       // マップ元文字列のバイト数
        NULL,           // マップ先ワイド文字列を入れるバッファのアドレス
        0           // バッファのサイズ
        );

    //バッファを確保する
    BSTR bstr=SysAllocStringLen(NULL,bstrlen);

    //BSTRに複製
    MultiByteToWideChar(
        CP_ACP,
        0,
        lstr,
        strlen(lstr),
        bstr,
        bstrlen
        );
    return bstr;
}
//メイン
int CompareHash()
{
  //フラグ
    BOOL success=false;
    HRESULT hres = CoInitialize(NULL);
    /コンソールアプリだとStep1,Strp2をコメント化する必要はない。コメントにすると動かなくなる。windowsアプリケーションはコメントにしないと動かない。原因は不明。そもそもc++全くわからない/
    // Step 1: --------------------------------------------------
    // Initialize COM. ------------------------------------------

    /*hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
    if (FAILED(hres))
    {
        return 0;                  // Program has failed.
    }

    // Step 2: --------------------------------------------------
    // Set general COM security levels --------------------------

    hres =  CoInitializeSecurity(
        NULL, 
        -1,                          // COM authentication
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities 
        NULL                         // Reserved
        );

                      
    if (FAILED(hres))
    {
        CoUninitialize();
        return 0;                    // Program has failed.
    }*/
    
    // Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------

    IWbemLocator *pLoc = NULL;

    hres = CoCreateInstance(
        CLSID_WbemLocator,             
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc);
 
    if (FAILED(hres))
    {
        CoUninitialize();
        return 0;                 // Program has failed.
    }

    // Step 4: -----------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method

    IWbemServices *pSvc = NULL;
 
    // Connect to the root\cimv2 namespace with
    // the current user and obtain pointer pSvc
    // to make IWbemServices calls.
    hres = pLoc->ConnectServer(
         _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
         NULL,                    // User name. NULL = current user
         NULL,                    // User password. NULL = current
         0,                       // Locale. NULL indicates current
         NULL,                    // Security flags.
         0,                       // Authority (for example, Kerberos)
         0,                       // Context object 
         &pSvc                    // pointer to IWbemServices proxy
         );
    
    if (FAILED(hres))
    {
        pLoc->Release();     
        CoUninitialize();
        return 0;                // Program has failed.
    }



    // Step 5: --------------------------------------------------
    // Set security levels on the proxy -------------------------

    hres = CoSetProxyBlanket(
       pSvc,                        // Indicates the proxy to set
       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
       NULL,                        // Server principal name 
       RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
       RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
       NULL,                        // client identity
       EOAC_NONE                    // proxy capabilities 
    );

    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x" 
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 0;               // Program has failed.
    }

    // Step 6: --------------------------------------------------
    // Use the IWbemServices pointer to make requests of WMI ----

    // For example, get the name of the operating system
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(
        bstr_t("WQL"), 
        bstr_t("SELECT * FROM Win32_DiskDrive Where InterfaceType=\'USB\'"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator);
    
    if (FAILED(hres))
    {
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return 0;               // Program has failed.
    }

    // Step 7: -------------------------------------------------
    // Get the data from the query in step 6 -------------------
 
    IWbemClassObject *pclsObj = NULL;
    ULONG uReturn = 0;
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
            &pclsObj, &uReturn);
        if(0 == uReturn)
        {
            break;
        }
        VARIANT vtProp;
    char deviceID[]="";
        // Get the value of the Name property
    //デバイズID
        hr = pclsObj->Get(L"DeviceID", 0, &vtProp, 0, 0);
        wcout << " DeviceID : " << vtProp.bstrVal << endl;
    BSTR drvDevId=L"";
    drvDevId=vtProp.bstrVal;
    //usbList[i][255] = vtProp.bstrVal;
    //シリアル番号を取得
    hr = pclsObj->Get(L"PNPDeviceID", 0, &vtProp, 0, 0);
    BSTR pnpdeveiceID = vtProp.bstrVal;
        wcout << " PNPDeviceID : " << vtProp.bstrVal << endl;
    //シリアル番号を抽出する
    string strpnpCode = BstrConvertToString(vtProp.bstrVal);
    char key='\\';
    int position=0;
    //最後の\の位置を特定
    for(int s=0;s<strpnpCode.size();s++){
        char target = strpnpCode[s];
        if(key == target){
            position = s;
        }
    }
    strpnpCode = strpnpCode.substr(position+1,strpnpCode.length());
    //hashに変換
    string serialHash=EncodeSerial(strpnpCode);
    //利用可能判別フラグ
    hr = pclsObj->Get(L"ConfigManagerErrorCode", 0, &vtProp, 0, 0);
    int ableFlg=vtProp.intVal;
        VariantClear(&vtProp);
        pclsObj->Release();
    if(ableFlg != 0){
        //利用不可能だった場合
        continue;
    }
    //パーティションを取得
    IEnumWbemClassObject* pEnumerator2 = NULL;
    HRESULT hres2;
    string strDrvDevId=BstrConvertToString(drvDevId);
    string sql= "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=\'" + strDrvDevId + "\'} WHERE AssocClass = Win32_DiskDriveToDiskPartition";
    BSTR sql1Bstr=StringConvertToBstr(sql);
    hres2 = pSvc->ExecQuery(
        bstr_t("WQL"), 
        bstr_t(sql1Bstr),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator2);
    if (FAILED(hres2))
    {
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        continue;               // Program has failed.
        }
    IWbemClassObject *pclsObj = NULL;
    ULONG uReturn = 0;
     while (pEnumerator2)
    {
        HRESULT hr = pEnumerator2->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
        if(0 == uReturn)
        {
            break;
        }
        VARIANT vtProp;
        // Get the value of the Name property
        //デバイズID
        hr = pclsObj->Get(L"DeviceID", 0, &vtProp, 0, 0);
        BSTR patDevId = vtProp.bstrVal;
        VariantClear(&vtProp);
        //論理ディスクを取得
        IEnumWbemClassObject* pEnumerator2 = NULL;
        HRESULT hres2;
        string sql2= "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=\'" + BstrConvertToString(patDevId) + "\'} WHERE AssocClass = Win32_LogicalDiskToPartition";
        BSTR sql2Bstr=StringConvertToBstr(sql2);
        hres2 = pSvc->ExecQuery(
        bstr_t("WQL"), 
        bstr_t(sql2Bstr),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator2);
        if (FAILED(hres2))
        {
            pSvc->Release();
            pLoc->Release();
            CoUninitialize();
            continue;               // Program has failed.
        }
        IWbemClassObject *pclsObj = NULL;
        ULONG uReturn = 0;
         while (pEnumerator2)
        {
            HRESULT hr = pEnumerator2->Next(WBEM_INFINITE, 1, 
                    &pclsObj, &uReturn);
            if(0 == uReturn)
            {
                break;
            }
            VARIANT vtProp;
            // Get the value of the Name property
            //デバイズID
            hr = pclsObj->Get(L"DeviceID", 0, &vtProp, 0, 0);
            //シリアルファイルのhashを確認する
            string path= BstrConvertToString(vtProp.bstrVal) + "\\aaa.hash";
            std::ifstream ifs(path.c_str());
            //解放
            VariantClear(&vtProp);
            if (ifs.fail())
            {
                success= false;
            }else{
                std::string str((std::istreambuf_iterator<char>(ifs)),std::istreambuf_iterator<char>());
                //比較
                int len = strlen(serialHash.c_str());
                int len2=strlen(str.c_str());
                int i=0;
                for (i = 0;i < len;i++) {
                    if(i>len || i>len2){
                        break;
                    }
                    if (str[i] != serialHash[i]) break;
                }
                if (i == len) {
                    success= true;
                } else {
                    success= false;
                }
            }
        }
    }
    pclsObj->Release();
  }
    // Cleanup
    // ========
    
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();
    cout << success << endl;
    return success;   // Program successfully completed
}