DevConをビルドして動かしてみて、ドライバ等々を取り扱うWindowsのAPIを勉強してみる

VS2022 Communityが入った状態からstart

devconのサンプルをMSのrepositoryからダウンロード

https://github.com/microsoft/Windows-driver-samples/tree/main/setup/devcon

VS2022で開いてビルドしようとすると、msg.hがないと怒られる。

なんで?なにかが足りてない?とりあえず思いつくものをinsutallしてみる。

WDKをインストール

https://learn.microsoft.com/ja-jp/windows-hardware/drivers/download-the-wdk

こんなんが出てきた

VS2022にC++デスクトップのワークロードがたりない、インストールせよ、と言っているが、VSinstaller見た限りでは、C++デスクトップはインストール済みのように見える。

→よくわからんので、そのまま進む。

こうなった。チェックは入れとく。

vsixでインストールが始まった

入れ終わった。

が、これでもVS2022でdevconビルドしようとすると、msg.hが無いと怒られた。

下記ページに、VS2019だとうまくビルドできるとある。やってみる。

https://github.com/microsoft/Windows-driver-samples/pull/991

vs2019だと、別のエラーになった。

下記のページに、「WDK.vsix」をインストールするとうまくいくとある。

https://qiita.com/skitoy4321/items/4e1cc3ab939aabf23fd6

これかな?インストールしてみる。

C:\Program Files (x86)\Windows Kits\10\Vsix\VS2022\10.0.22621.0\WDK.vsix

→すでに入ってると言われた。↑で入れたやつがこれなのか。

これをやってみる。

https://qiita.com/skitoy4321/items/4e1cc3ab939aabf23fd6#buildtools%E3%81%97%E3%81%8B%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AE%E8%A7%A3%E6%B1%BA%E6%96%B9%E6%B3%95

ここのx64フォルダを、

C:\Users\masa\Desktop\WDK\$MSBuild\Microsoft\VC\v170\Platforms\x64

ここに上書コピーする。

C:\Program Files\Microsoft Visual Studio\2022\Community\Msbuild\Microsoft\VC\v170\Platforms

だめだった。

これらをDL&インストールしてみた。

https://learn.microsoft.com/ja-jp/windows-hardware/drivers/other-wdk-downloads#step-2-install-the-wdk

WDK for Windows 10 バージョン 2004 をインストールしたら、VS2019で出てたtoolsetがないというエラーは出なくなった。が、VS2022とおなじ、msg.hがないエラーは同じ。

これを入れてみる。Windows 11 SDK (10.0.22621.0

https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/

要らないものをいれるのはいやだけど、どれがいらないかわからないので全チェック入れてインストールしてみる。

この図の、下の4つの「Windows SDK for Desktop C++ なんとか・・」が、上のINportant何とか画面ででてた、足りないヤツなのか?

下記に、本家のDevConからforkしたリポジトリに、msg.hがあった。

https://github.com/WOA-Project/DevCon/tree/main

これをもらってきてみる。

→もらってきて、文字コードSJISで保存しなおしてビルドしたら、エラーが変わった。

ここをみて、Spectre軽減設定をOFFにしてみる

https://learn.microsoft.com/ja-jp/visualstudio/msbuild/errors/msb8040?view=vs-2022

→ビルドできた!

出力先フォルダに移動して、VSの開発者用powershellで、./devcon.exe helpと打つと、devconのhelpを見れた。

./devcon.exe find *と打つと、ドライバの一覧っぽいのが見れた。どうやらうまく動いたっポイ。


ここまでやってみた感想

おそらく、途中でやってたWDKやそのオマケのVS用アドオンvsix、windowsSDKのインストールはいらなかったっぽい。最後にやった、forkのリポジトリからmsg.hを持ってきたのだけが、効果があった気がする。(検証はしてない)

本家のmsg.hがどこへ消えたのか?は分からずじまい。

だがともかく、DevConを動かせたので、とりあえず掲題の勉強はできそう。


ビルドしたDevConを動かしてみた。

試しに下記コマンドを打つと、

devcon classes

日本語が化ける。

ターミナルでchcp 65001とかしてもダメだった。

色々試した結果、devconのコード中で、setlocale(LC_ALL, "Japanese");をしてやれば化けなくなった。

参考:
https://oshiete.goo.ne.jp/qa/5388646.html

devcon.cppの冒頭に下記を書いて、

#include <locale.h>

devcon.cpp の _tmain() の開始直後に下記を入れた。

setlocale(LC_ALL, "Japanese");

これで、うまく日本語が出てくれた。


devcon、動かすとなんだかいろんな情報が取れてるっぽいが、それが何を示しているのかさっぱりわからない。

下記ページがなんかよさそう?見てみる。

https://sciencepark.co.jp/device_driver/dvdr_report/


ちょっと横道にそれるが、chatgptに、

Windowsのデバイスマネージャー画面に出てくる一覧は、なんの一覧でしょうか?メニューの「表示」は、「デバイス(種類別)」にチェックが入っています。

さらに

この一覧と同じ内容を、windowsのAPIで取得したい場合、どのようなAPIを使えばよいでしょうか?

と聞いて出てきたC++コードをちょっと直してやると、デバマネの最初に出てくる一覧と似た内容が取れた。たぶんdevconにも、似た内容があるんだろうと思う。とりあえずメモ。

#include <windows.h>
#include <Setupapi.h>
#include <devguid.h>
#include <stdio.h>

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

// 文字コードを、マルチバイト文字列、にすべし

void PrintDeviceProperty(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInfoData, DWORD property) {
    DWORD requiredSize = 0;
    SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, NULL, NULL, 0, &requiredSize);
    if (requiredSize == 0) {
        printf("Property not found.\n");
        return;
    }

    BYTE* buffer = (BYTE*)malloc(requiredSize);
    if (buffer == NULL) {
        printf("Memory allocation failed.\n");
        return;
    }

    if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, NULL, buffer, requiredSize, NULL)) {
        printf("Failed to retrieve property.\n");
        free(buffer);
        return;
    }

    printf("%s\n", (char*)buffer);
    free(buffer);
}

int main()
{
    HDEVINFO deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
    if (deviceInfoSet == INVALID_HANDLE_VALUE) {
        printf("Failed to get device information set.\n");
        return 1;
    }

    SP_DEVINFO_DATA deviceInfoData;
    ZeroMemory(&deviceInfoData, sizeof(deviceInfoData));
    deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

    for (DWORD i = 0; SetupDiEnumDeviceInfo(deviceInfoSet, i, &deviceInfoData); i++) {
        printf("Device %lu:\n", i + 1);
        PrintDeviceProperty(deviceInfoSet, &deviceInfoData, SPDRP_DEVICEDESC); // デバイスの説明
        PrintDeviceProperty(deviceInfoSet, &deviceInfoData, SPDRP_HARDWAREID); // ハードウェアID
        printf("\n");
    }

    SetupDiDestroyDeviceInfoList(deviceInfoSet);
}

出力結果の一部

Device 1:
WinDriver
*WINDRVR6

Device 2:
ローカル印刷キュー
PRINTENUM\{0f4130dd-19c7-7ab6-99a1-980f03b2ee4e}

Device 3:
Intel(R) Dynamic Application Loader Host Interface
SWC\3C4852D6-D47B-4F46-B05E-B5EDC1AA440E

Device 4:
Microsoft Bluetooth LE Enumerator
BTH\MS_BTHLE

Device 5:
マザーボード リソース
ACPI\VEN_PNP&DEV_0C02

Device 6:
マザーボード リソース
ACPI\VEN_PNP&DEV_0C02

DevConで、情報を取る部分で、どうかかれているかを見てみる。