[PR]血液型で当たる無料占い:アナタと私の相性は?《無料診断》

USBデバイスの取り外し関連、etc...


QueryDosDevice を使ったデバイス名取得
USBデバイスの取り外し関連サンプルプログラム
デバイスの有効化・無効化

QueryDosDevice を使ったデバイス名取得
対象バージョン
最終更新日2006-01-01

解 説
USBデバイスの取り外しをする際、ドライブに割り当てられたデバイス名というものが必要になりました。
『ドライブ名から、デバイス名を取得し、USBデバイスのデバイス名と一致するものを取り外す』という処理が必要だったわけです。
そのときに作成したクラスを一個、そのまま掲載します。
TStringListを継承させているので、デバイス名で検索するとき、IndexOfメソッド一つで済みます。

また、通常 TStringList.Objects[**] は、TObject型ですが、SizeOf(TObject) = SizeOf(Pointer) = SizeOf(Integer) = 4 であることを利用し、TStringList.Objectsには、ドライブ名を格納しています。
正確には、『Ord(ドライブ名の'A'とか'C'とかの頭文字)』で得られる、文字列の順序型・・・ややこしいですが、Char($41) = 'A' というときの、$41 値を格納しています。
そのため、このクラスを他で使用したい場合、Objectsプロパティを使用できません。


サンプルプログラム

実行ファイルのみ

ソースコード
//宣言部//
type
  TDriveDevices =class(TStringList)
  public
    constructor Create; virtual;
    {DOSデバイス情報を読み込む}
    function LoadDevices: Boolean;

  public
    {DOSデバイス名からドライブ名を得る}
    function IndexOfDrive(aDevice: String): String; {ex) 'A:'}

  end;

//実装部//
constructor TDriveDevices.Create;
  begin
    inherited Create;
    LoadDevices;
  end;

{DOSデバイス情報を読み込む}
function TDriveDevices.LoadDevices: Boolean;
  {検索対象デバイスであるか}
  function isDriveDevice(aBuf: PChar): Boolean;
    begin
      Result := False;
      case aBuf[0] of
        'A'..'Z':begin
          Result := (aBuf[1] = ':') and (aBuf[2] = #0);
        end;
      end;
    end;
  const
    maxDevs     = $FFFF;
  var
    idx, gets   :Integer;
    dosDevices  :array[0..maxDevs -1] of Char;
    desDevName  :array[0..1024-1] of Char;
    firstPos    :PChar;
    counter     :Integer;
  begin
    {クリア}
    Clear;

    {デバイス名の一覧を取得}
    gets := QueryDosDevice(nil, @dosDevices, maxDevs);
    if gets > 0 then begin
      {ドライブに対応したデバイス名のみ抽出}
      counter := 0;
      while (counter < gets) do begin
        {DOSデバイス名ポインタ}
        firstPos := @dosDevices[counter];
        {ドライブ対応文字か判定(簡易)}
        if isDriveDevice(firstPos) then begin
          {デバイス名を取得}
          if QueryDosDevice(firstPos, @desDevName, 1024) > 0 then begin
            {Objects[xx]にドライブ名文字のAscii値を格納して追加}
            AddObject(PChar(@desDevName), Pointer(Ord(firstPos[0])));
          end;
        end;
        {Next}
        idx := 0;
        while (counter < gets) and (firstPos[idx] <> #0) do begin
          Inc(idx);
          Inc(counter);
        end;
        Inc(counter);
      end;{!While...}
    end;
    Result := Count > 0;
  end;

{デバイス名からドライブ名を得る}
function TDriveDevices.IndexOfDrive(aDevice: String): String;
  var
    idx :Integer;
  begin
    idx := IndexOf(aDevice);
    if idx < 0 then begin
      Result := '';
    end
    else begin
      Result := Char(Integer(Objects[idx])) + ':';
    end;
  end;

  


USBデバイスの取り外し関連サンプルプログラム
対象バージョン
最終更新日2006-05-17

解 説
USBデバイスの取り外しをする際に使用する、SetupApicfgmgr32関連のヘッダ定義及び、Tasktray Ejector II に実装した、USBデバイスの取り外し機能に関する俺様仕様クラス定義のユニットと、それを活用したサンプルプログラムです。
もう、解説ページ作る余裕も気力もありません。

SetupApicfgmgr32関連のヘッダ定義は、必要な部分のみ移植しているので、不完全です。
海外のコンポーネント配布サイトに行けば、完全なヘッダユニットを手に入れることができるかもしれません。

サンプルプログラム

サンプルプログラム&実行ファイルとAPI宣言
2008.11.09:圧縮ファイルの内容を更新しましたが、サンプルプログラム自身に変更はありません


ソースコード
気力がないので、検索キーワードっぽいものだけ列挙しておきます。

//ライブラリ
cfgmgr32.dll
SetupApi.dll

//ヘッダ
Cfg.h
CfgMgr32.h
SetupApi.h

//API
SetupDiEnumDeviceInfo
SetupDiDestroyDeviceInfoList
SetupDiGetClassDevs
SetupDiGetDeviceRegistryProperty

CM_Get_DevNode_Registry_Property
CM_Get_Child
CM_Get_DevNode_Status

CM_Request_Device_Eject

SetupDiEnumDeviceInfo
GetDeviceStatusName

  

デバイスの有効化・無効化
対象バージョン
最終更新日2007-08-03


解 説
デバイスマネージャーで、デバイスの有効・無効を設定できるものがあります。これをSetupApiあたりを利用して、有効化・無効化するサンプルです。
自分で使った関数を、ほぼそのまま使っているので、雰囲気だけを感じ取ってください。
なお、上記サンプルプログラム&実行ファイルとAPI宣言をダウンロードしたアーカイブファイルの中にあるUSBDev.pasを使っています。

サンプルプログラム

下記ソースコードを利用したサンプルプログラム&実行ファイルとAPI宣言です。
USBデバイスの取り外し関連サンプルプログラムと同じくUSBDev.pasを同梱しています。


ソースコード
{サンプル}
function deviceDisableAndEnabled(aDevNameString): Boolean;
var
  devInfohDevInfo;
  devInfoDataTSPDevInfoData;
  sppParamsTSPPropChangeParams;
  idxInteger;
  dataType,
  buffersizeDWORD;
  bufferLPTSTR;
  ustatus,
  ulProgNoULONG;
  devNameString;
  getOKBoolean;
begin
  Result := False;
  if not IsApiLoaded then begin
    MessageBeep(0);
    Exit;
  end;

  {デバイス取得ハンドルを得る}
  devInfo := SetupDiGetClassDevs(nilnil0DIGCF_ALLCLASSES or DIGCF_PRESENT);

  {無効ハンドルは終了}
  if DWORD(devInfo) = INVALID_HANDLE_VALUE then begin
    MessageBeep(0);
    Exit;
  end;

  {構造体初期化}
  FillChar(devInfoDataSizeOf(TSPDevInfoData), 0);
  devInfoData.cbSize := SizeOf(TSPDevInfoData);

  {初期化}
  idx := 0;
  buffersize := 0;
  buffer := nil;

  {デバイス名を順に取得する}
  while SetupDiEnumDeviceInfo(devInfoidxdevInfoDatado begin
    {デバイスノードのステータス取得}
    if (CM_Get_DevNode_Status(ustatusulProgNodevInfoData.DevInst0) = CR_SUCCESSthen begin
        getOK := False;
        {デバイス名の取得}
        while not SetupDiGetDeviceRegistryProperty(devInfodevInfoDataSPDRP_DEVICEDESC,
                                                   dataTypePByte(buffer),
                                                   buffersizebuffersizedo begin
          if (GetLastError = ERROR_INSUFFICIENT_BUFFERthen begin
          //受信バッファ不足
            // Change the buffer size.
            if buffer <> nil then LocalFree(Cardinal(buffer));
            // Double the size to avoid problems on
            // W2k MBCS systems per KB 888609.
            buffersize := buffersize * 2;
            buffer := Pointer(LocalAlloc(LPTRbuffersize));
          end
          else begin
            // Insert error handling here.
            break;
          end;
        end;
        if (buffer <> nilthen devName := buffer;

        if aDevName <> '' then begin
          getOK := AnsiPos(AnsiUpperCase(aDevName), AnsiUpperCase(devName)) > 0;
         end;

        if getOK then begin
          sppParams.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);
          sppParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
          sppParams.Scope := DICS_FLAG_GLOBAL ;
          sppParams.HwProfile := 0// current hardware profile

          {無効化}
          sppParams.StateChange := DICS_DISABLE;
          {有効・無効変更}
          SetupDiSetClassInstallParams(devInfo, @devInfoData, @sppParamsSizeOf(sppParams));
          {変更通知}
           SetupDiChangeState(devInfodevInfoData);

          {有効化}
          sppParams.StateChange := DICS_ENABLE;
          {有効・無効変更}
          SetupDiSetClassInstallParams(devInfo, @devInfoData, @sppParamsSizeOf(sppParams));
          {変更通知}
          SetupDiChangeState(devInfodevInfoData);

          Result := True;
        end;
    end;
    {Next}
    Inc(idx);
  end;
  {終了処理}
  if buffer <> nil then LocalFree(Cardinal(buffer));

  {Clean up}
  SetupDiDestroyDeviceInfoList(devInfo);
end;
このソースコードにに限り、KHE00221 さんの、pas2HTML ver.1.16を利用しました。
2007年08月03日現在、移転後の構築中のようで、pas2HTMLのダウンロード先はありません。



戻る

[PR]看護師の好条件な求人情報満載:年間50000人の看護師が転職に利用!