{*******************************************************} { } { Tocsg.MTP } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit Tocsg.MTP; interface uses System.SysUtils, System.Classes, Tocsg.Obj, Winapi.Windows, System.Generics.Collections; type PMtpEnt = ^TMtpEnt; TMtpEnt = record sName, sDesc, sMfg, sDevId: String; end; TMtpEntList = TList; TManagerMtpDev = class(TTgObject) private MtpEntList_: TMtpEntList; procedure OnMptEntNotify(Sender: TObject; const Item: PMtpEnt; Action: TCollectionNotification); public Constructor Create; Destructor Destroy; override; procedure RefreshMptDev; function GetMtpEntByDevId(sDevId: String): PMtpEnt; property MtpEntList: TMtpEntList read MtpEntList_; end; implementation uses Tocsg.Driver, Tocsg.Exception, Tocsg.Safe; Constructor TManagerMtpDev.Create; begin Inherited Create; MtpEntList_ := TMtpEntList.Create; MtpEntList_.OnNotify := OnMptEntNotify; end; Destructor TManagerMtpDev.Destroy; begin FreeAndNil(MtpEntList_); Inherited; end; procedure TManagerMtpDev.OnMptEntNotify(Sender: TObject; const Item: PMtpEnt; Action: TCollectionNotification); begin if Action = cnRemoved then Dispose(Item); end; procedure TManagerMtpDev.RefreshMptDev; var hDev: HDEVINFO; sdd: TSPDevInfoData; i, c: Integer; dwBufSize, dwStatus, dwProblem, dwPropertyRegDataType: DWORD; pBuf: Pointer; sInfo1, sInfo2: String; InfoList: TStringList; pEnt: PMtpEnt; function GetPropStr(dwProp: DWORD): String; begin Result := ''; dwBufSize := 0; if pBuf <> nil then begin FreeMem(pBuf); pBuf := nil; end; while not SetupDiGetDeviceRegistryProperty(hDev, sdd, dwProp, dwPropertyRegDataType, pBuf, dwBufSize, dwBufSize) do begin if GetLastError = ERROR_INSUFFICIENT_BUFFER then begin if pBuf <> nil then FreeMem(pBuf); pBuf := AllocMem(dwBufSize); end else break; end; if pBuf <> nil then Result := PChar(pBuf); // 값 여러줄 있는거 무시하고 첫번째만 가져옴 end; begin try hDev := SetupDiGetClassDevs(@GUID_DEVCLASS_WPD, nil, 0, DIGCF_PRESENT); if hDev = INVALID_HANDLE_VALUE then exit; pBuf := nil; try ZeroMemory(@sdd, SizeOf(sdd)); sdd.cbSize := SizeOf(sdd); Guard(InfoList, TStringList.Create); i := 0; while SetupDiEnumDeviceInfo(hDev, i, sdd) do begin sInfo1 := UpperCase(Trim(GetPropStr(SPDRP_COMPATIBLEIDS))); sInfo2 := UpperCase(Trim(GetPropStr(SPDRP_SERVICE))); // if GetPropStr(SPDRP_DEVTYPE) = 'MTP' then // todo : "버스에서 보고된 장치 설명" 값을 가져오는 방법을 모름.. 22_0630 15:18:12 kku if (sInfo1 = 'USB\MS_COMP_MTP') or (sInfo2 = 'WUDFWPDMTP') then begin New(pEnt); // _Trace(GetPropStr(SPDRP_COMPATIBLEIDS)); // USB\MS_COMP_MTP // _Trace(GetPropStr(SPDRP_SERVICE)); // WUDFWpdMtp // _Trace(GetPropStr(SPDRP_CLASS)); // _Trace(GetPropStr(SPDRP_CLASSGUID)); // _Trace(GetPropStr(SPDRP_DRIVER)); // _Trace(GetPropStr(SPDRP_CONFIGFLAGS)); // _Trace(GetPropStr(SPDRP_LOCATION_INFORMATION)); // _Trace(GetPropStr(SPDRP_PHYSICAL_DEVICE_OBJECT_NAME)); // _Trace(GetPropStr(SPDRP_CAPABILITIES)); // _Trace(GetPropStr(SPDRP_UI_NUMBER)); // _Trace(GetPropStr(SPDRP_UPPERFILTERS)); // _Trace(GetPropStr(SPDRP_LOWERFILTERS)); // _Trace(GetPropStr(SPDRP_BUSTYPEGUID)); // _Trace(GetPropStr(SPDRP_LEGACYBUSTYPE)); // _Trace(GetPropStr(SPDRP_BUSNUMBER)); // _Trace(GetPropStr(SPDRP_UI_NUMBER)); // _Trace(GetPropStr(SPDRP_ENUMERATOR_NAME)); // _Trace(GetPropStr(SPDRP_SECURITY)); // _Trace(GetPropStr(SPDRP_SECURITY_SDS)); // _Trace(GetPropStr(SPDRP_DEVTYPE)); // _Trace(GetPropStr(SPDRP_EXCLUSIVE)); // _Trace(GetPropStr(SPDRP_CHARACTERISTICS)); // _Trace(GetPropStr(SPDRP_ADDRESS)); // _Trace(GetPropStr(SPDRP_UI_NUMBER_DESC_FORMAT)); // _Trace(GetPropStr(SPDRP_DEVICE_POWER_DATA)); // _Trace(GetPropStr(SPDRP_REMOVAL_POLICY)); // _Trace(GetPropStr(SPDRP_LOCATION_PATHS)); pEnt.sName := GetPropStr(SPDRP_FRIENDLYNAME); pEnt.sDesc := GetPropStr(SPDRP_DEVICEDESC); pEnt.sMfg := GetPropStr(SPDRP_MFG); pEnt.sDevId := GetPropStr(SPDRP_HARDWAREID); MtpEntList_.Add(pEnt); end; Inc(i); end; finally SetupDiDestroyDeviceInfoList(hDev); if pBuf <> nil then FreeMem(pBuf); end; except on E: Exception do ETgException.TraceException(E, 'Fail .. RefreshMptDev()'); end; end; function TManagerMtpDev.GetMtpEntByDevId(sDevId: String): PMtpEnt; var i: Integer; begin Result := nil; for i := 0 to MtpEntList_.Count - 1 do if MtpEntList_[i].sDevId = sDevId then begin Result := MtpEntList_[i]; exit; end; end; end.