[[20200805153149]] 『windowsAPI の引数へヌルポインタの与え方』(素人のおっさん) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『windowsAPI の引数へヌルポインタの与え方』(素人のおっさん)

Excel でUSBデバイスからデータ通信を考えています。
PCのセキュリティ関係で専用ドライバをインストールできないので
WIndowsのHID標準デバイスとして扱いたいのです。

HidD_GetHidGuid()
SetupDiGetClassDevs()
SetupDiEnumDeviceInterfaces()
まではたどり着けたのですが、
SetupDiGetDeviceInterfaceDetail()で躓いています。

SetupDiGetDeviceInterfaceDetail funcitonの引数DeviceInterfaceDetailDataへ
ヌルポインタを与えてinterfaceのサイズを取得したのち、
デバイスパスを得るために構造体ポインタを与える処理を
ご教授いただけるようお願いいたします。

使用環境
windows10 64bit
excel365 or excel2019

C#のintptr.zeroの文献は見かけますが、VBAは以前の古いものしか見当たりません。
思いついて変数宣言しただけの構造体をnullとして与えればいけるかなと思ったのですが、だめでした。
Nullptrのダンプではaddrss、文字長ともに00が入っているのですが…
根本的に違っているかもしれないので、定番があればお願いします。


Private Type SP_DEVICE_INTERFACE_DETAIL_DATA
    cbSize As Long
    DevicePath As String
End Type

Private Declare PtrSafe Function SetupDiGetDeviceInterfaceDetail Lib "setupapi.dll" Alias _

    "SetupDiGetDeviceInterfaceDetailA" ( _
    ByVal DeviceInfoSet As LongPtr, _
    ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA, _
    ByRef DeviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA, _
    ByVal DeviceInterfaceDetailDataSize As Long, _
    ByRef RequiredSize As Long, _
    ByVal DeviceInfoData As String _
) As Long


Dim Nullptr As SP_DEVICE_INTERFACE_DETAIL_DATA

If (SetupDiGetDeviceInterfaceDetail(Hdev, sDeviceInterfaceData, Nullptr, 0, Needed, vbNullString) = False) Then

Call dumpMemory(VarPtr(Nullptr), 12, "dec")

end if


Nullptrのメモリダンプ
2952984382968 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00

< 使用 Excel:Office365、使用 OS:Windows10 >


dumpMemoryって、APIではないので、このコードも載せて欲しいです。 引数が2つのものと、3つのものを見たことがありますが、中身はAPIのRtlMoveMemoryを使って、型変換を実現しているだけでしたが。 まぁ、そこは結果表示に使っているだけであり、本題ではないようですね。

APIにヌルポインタを指定するということは、アドレスとして0を指定すれば良いので、0& とでも直接書けば良いかと思います。(普通に0と書くと16bitになるけど、これだと32bitの0という意味になる)
(???) 2020/08/05(水) 16:15


あと、うまくいかないのは、構造体のデータサイズが違うためと思われます。

C言語は、文字列は宣言したバイト数分領域が確保されますが、VBAではサイズを明示しない場合、先頭に文字長、その後ろに実体が入ります。 大きさを宣言しない場合、サイズ情報のみです。 大きめに用意して良い構造体ならば、String * 長さ のように指定しましょう。(Unicodeなので、1文字=2byte分確保されますが)

そして、返った文字列を取り出す際は、VBAに必要な文字長が判らないので、先頭から vbNullChar を探し、Left関数等で切り出して使いましょう。

また、VBAのLong型はSignedであり、Unsignedではない事が問題になる場合もあるので、覚えておいてください。
(???) 2020/08/05(水) 16:32


ちょっと検索して出てきた、参考になりそうなページなぞ。
https://www.dinop.com/elec/psoc_usb_txrx_by_excel.html

うーん、返る文字列は可変長っぽいですね。 byte型で対応しているみたいです。
(???) 2020/08/05(水) 16:48


早々の回答ありがとうございます
dumpMemoryは「エクセルの神髄」にあるコードをほぼそのまま使用しています。
https://excel-ubara.com/excelvba4/EXCEL_VBA_422.html

アドレスに0&を入れるとの事ですが、VBAでアドレスをいじれないので
これもAPIを使って直接書き込むということでしょうか?
ちなみに、0&はlongですよね。win64のアドレスはlonglongと思うのですが問題はないのでしょうか
とりあえずやってみます。

エラー出力を追加してみると
Debug.Print Hex(Err.LastDllError)
「0x6f8:要求された操作に対して与えられたバッファーが無効です」が吐き出されました。
根本的に構造体の与え方がよくないようです。

ご紹介いただいたページは元ネタです。
このコードにPtrsafeをつけただけでは動かなかったので苦慮しています。
また何かわかりましたら書き込みますのでよろしくお願いいたします.

(素人のおっさん) 2020/08/06(木) 09:49


PtrSafeを使っていたので、Excelも64bitだったのですね。 見落としました。

64bitでは、SP_DEVICE_INTERFACE_DETAIL_DATA の方は同じで良いようですが、SP_DEVICE_INTERFACE_DATA の要素が幾つか64bitに変わっているので、Long型を2つ並べるとか、構造体のサイズを合わせないと駄目かと思います。

(???) 2020/08/06(木) 10:57


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.