function
MySetThreadTokenOnProcess(
const
dwPID : DWORD;
const
Thread : PHANDLE;
const
bSetThreadToken :
Boolean
;
var
StrErrorInfo :
String
) :
Boolean
;
var
process_handle: THandle;
token_handle: THandle;
dup_token_handle: THandle;
token_attributes: SECURITY_ATTRIBUTES;
begin
Result:=
False
;
StrErrorInfo:=
''
;
if
not
bSetThreadToken
then
begin
Result:=windows
.
SetThreadToken(Thread,
0
);
Exit;
end
;
process_handle := MyOpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, dwPID,
True
);
if
(process_handle =
0
)
then
begin
StrErrorInfo:=
'OpenProcess 失败:'
+ MyGetErrorToText;
Exit;
end
;
if
(
not
OpenProcessToken(
process_handle,
TOKEN_DUPLICATE,
token_handle))
then
begin
windows
.
CloseHandle(process_handle);
StrErrorInfo:=
'OpenProcessToken 失败: '
+ MyGetErrorToText;
Exit;
end
;
windows
.
CloseHandle(process_handle);
token_attributes
.
nLength := sizeof(SECURITY_ATTRIBUTES);
token_attributes
.
lpSecurityDescriptor :=
nil
;
token_attributes
.
bInheritHandle :=
FALSE
;
if
(
not
DuplicateTokenEx(
token_handle,
TOKEN_IMPERSONATE,
@token_attributes,
SecurityImpersonation,
TokenImpersonation,
dup_token_handle)
)
then
begin
windows
.
CloseHandle(token_handle);
StrErrorInfo:=
'DuplicateTokenEx 失败:'
+ MyGetErrorToText;
Exit;
end
;
windows
.
CloseHandle(token_handle);
if
windows
.
SetThreadToken(Thread,
dup_token_handle
)
then
begin
Result:=
True
;
end
else
begin
StrErrorInfo:=
'SetThreadToken 失败:'
+ MyGetErrorToText;
end
;
windows
.
CloseHandle(dup_token_handle);
end
;
function
MyRegOpenKeyEx(
const
RootKey : HKEY;
const
lpSubKey :
PChar
;
const
KEYsamDesired : REGSAM;
const
isKEY_WOW64_64KEY :
Boolean
;
var
phkResult : HKEY) :
Boolean
;
var
samDesired : REGSAM;
begin
samDesired:=KEYsamDesired;
if
isKEY_WOW64_64KEY
and
G_IsWin64
then
begin
samDesired:=samDesired
or
KEY_WOW64_64KEY;
end
;
Result:= ERROR_SUCCESS = RegOpenKeyEx(RootKey, lpSubKey,
0
, samDesired, phkResult);
end
;
function
MyRegEnumKeyNameToList(
const
phkResult: HKEY;
var
KeyNamesList: TStringList) :
Boolean
;
var
I :
Integer
;
dwDataSize, dwLen : DWORD;
status : DWORD;
buffer :
array
[
0..255
]
of
AnsiChar
;
begin
Result:=
False
;
if
not
Assigned(KeyNamesList)
then
exit;
dwLen:=Length(buffer);
I:=
0
;
repeat
ZeroMemory(@buffer[
0
], dwLen);
dwDataSize:=dwLen;
status:=RegEnumKeyEx(phkResult,
I,
buffer,
dwDataSize,
nil
,
nil
,
nil
,
nil
);
if
ERROR_SUCCESS = status
then
begin
KeyNamesList
.
Add(buffer);
Inc(I);
end
;
until
status <> ERROR_SUCCESS;
Result:=I >
0
;
end
;
function
MyRegGetPropertiesDateTime(
const
RootKey : HKEY;
const
lpSubKey :
PChar
;
const
isKEY_WOW64_64KEY :
Boolean
;
var
DTTime : TDateTime) :
Boolean
;
var
samDesired : REGSAM;
phkResult : HKEY;
AData: TMyArrayOfBytes;
dwOutBufSize : DWORD;
begin
Result:=
False
;
DTTime:=
0
;
samDesired:=KEY_READ
or
KEY_QUERY_VALUE;
if
isKEY_WOW64_64KEY
and
G_IsWin64
then
begin
samDesired:=samDesired
or
KEY_WOW64_64KEY;
end
;
if
ERROR_SUCCESS = RegOpenKeyEx(RootKey, lpSubKey,
0
, samDesired, phkResult)
then
begin
if
MyRegQueryBinaryValueEx(phkResult,
''
, AData, dwOutBufSize)
then
begin
DTTime:=MyRegBinaryValueToDateTime(AData,
0
, dwOutBufSize);
Result:=
True
;
SetLength(AData,
0
);
end
else
begin
Result:=MyRegGetKeyLastWriteTime(phkResult, DTTime);
end
;
RegCloseKey(phkResult);
end
;
end
;
function
MyGetUSBDeviceUserInfo(
var
MyUSBDeviceInfo : TMyUSBDeviceInfoArray) :
Boolean
;
var
I, J, iLen, iTtemCount :
Integer
;
phkResult, phkResult2, phkResult3, hkKeyLastUesrDateTime : HKEY;
KeyNamesList1, KeyNamesList2, KeyNamesList3: TStringList;
StrKeyName, StrKey_WPDBUSENUM :
PAnsiChar
;
StrFriendlyName, StrClassGUID, StrSerialNumber, StrLastUesrDateTime, StrMfg, StrVolumeName,
StrSetupDateTime, StrConnectTime, StrKeyName2, StrKeyName3, StrProperties, StrContainerID, StrService, StrErrorInfo :
string
;
DTLastWriteTime, DTConnectTime, DTSetupDateTime : TDateTime;
begin
Result:=
False
;
KeyNamesList1:=TStringList
.
Create;
KeyNamesList2:=TStringList
.
Create;
KeyNamesList3:=TStringList
.
Create;
iLen:=
0
;
iTtemCount:=
0
;
StrKeyName:='SYSTEM\CurrentControlSet\Enum\USB\';
if
MyRegOpenKeyEx(HKEY_LOCAL_MACHINE, StrKeyName, KEY_READ
or
KEY_QUERY_VALUE,
True
, phkResult)
then
begin
if
MyRegEnumKeyNameToList(phkResult, KeyNamesList1)
then
begin
for
I:=
0
to
KeyNamesList1
.
Count-
1
do
begin
StrKeyName2:=StrKeyName + KeyNamesList1[I];
if
MyRegOpenKeyEx(HKEY_LOCAL_MACHINE,
PAnsiChar
(StrKeyName2), KEY_READ
or
KEY_QUERY_VALUE,
True
, phkResult2)
then
begin
KeyNamesList2
.
Clear;
if
MyRegEnumKeyNameToList(phkResult2, KeyNamesList2)
then
begin
for
J:=
0
to
KeyNamesList2
.
Count-
1
do
begin
StrKeyName3:= StrKeyName2 + '\' + KeyNamesList2[J];
if
MyRegOpenKeyEx(HKEY_LOCAL_MACHINE,
PAnsiChar
(StrKeyName3), KEY_READ
or
KEY_QUERY_VALUE,
True
, phkResult3)
then
begin
if
MyRegQueryStringValueEx(phkResult3,
'Service'
, StrService)
and
(SameText(StrService,
'USBSTOR'
))
then
begin
if
MyRegQueryStringValueEx(phkResult3,
'ContainerID'
, StrContainerID)
then
begin
MyRegQueryStringValueEx(phkResult3,
'LocationInformation'
, StrMfg);
Inc(iLen);
SetLength(MyUSBDeviceInfo, iLen);
with
MyUSBDeviceInfo[iLen -
1
]
do
begin
StringCbCopyA(@USBDI_RegKeyPath[
0
], SizeOf(USBDI_RegKeyPath),
PAnsiChar
(StrKeyName3));
StringCbCopyA(@USBDI_ContainerID[
0
], SizeOf(USBDI_ContainerID),
PAnsiChar
(StrContainerID));
StringCbCopyA(@USBDI_LocationInformation[
0
], SizeOf(USBDI_LocationInformation),
PAnsiChar
(StrMfg));
end
;
end
;
end
;
RegCloseKey(phkResult3);
end
;
end
;
end
;
RegCloseKey(phkResult2);
end
;
end
;
end
;
RegCloseKey(phkResult);
end
;
if
(iLen >
0
)
and
MyRegOpenKeyEx(HKEY_LOCAL_MACHINE,
'SYSTEM\CurrentControlSet\Enum\USBSTOR'
, KEY_READ
or
KEY_QUERY_VALUE,
True
, phkResult)
then
begin
if
MyRegEnumKeyNameToList(phkResult, KeyNamesList1)
then
begin
if
MySetThreadTokenOnProcess(MyGetProcessPIDByNameEx(
'winlogon.exe'
,
3
),
nil
,
True
, StrErrorInfo)
then
begin
for
I:=
0
to
KeyNamesList1
.
Count -
1
do
begin
StrKeyName:=
PAnsiChar
(
'SYSTEM\CurrentControlSet\Enum\USBSTOR'
+ '\' + KeyNamesList1[I]);
if
MyRegOpenKeyEx(HKEY_LOCAL_MACHINE, StrKeyName, KEY_READ
or
KEY_QUERY_VALUE,
True
, phkResult2)
then
begin
KeyNamesList2
.
Clear;
if
MyRegEnumKeyNameToList(phkResult2, KeyNamesList2)
then
begin
StrSerialNumber:=KeyNamesList2[
0
];
StrKeyName2:=StrKeyName + '\' + StrSerialNumber;
StrConnectTime:=
''
;
StrLastUesrDateTime:=
''
;
StrSetupDateTime:=
''
;
if
MyRegOpenKeyEx(HKEY_LOCAL_MACHINE,
PAnsiChar
(StrKeyName2), KEY_READ
or
KEY_QUERY_VALUE,
True
, phkResult3)
then
begin
if
MyRegQueryStringValueEx(phkResult3,
'ContainerID'
, StrContainerID)
then
begin
for
J:=Low(MyUSBDeviceInfo)
to
High(MyUSBDeviceInfo)
do
begin
if
SameText(StrContainerID, MyUSBDeviceInfo[J].USBDI_ContainerID)
then
begin
StrProperties:=MyUSBDeviceInfo[J].USBDI_RegKeyPath + '\Properties\
\';
if
MyRegGetPropertiesDateTime(HKEY_LOCAL_MACHINE,
PAnsiChar
(StrProperties +
'0065'
),
True
, DTSetupDateTime)
then
begin
end
else
if
MyRegGetPropertiesDateTime(HKEY_LOCAL_MACHINE,
PAnsiChar
(StrProperties +
'0064'
),
True
, DTSetupDateTime)
then
begin
end
;
MyRegGetPropertiesDateTime(HKEY_LOCAL_MACHINE,
PAnsiChar
(StrProperties +
'0066'
),
True
, DTConnectTime);
MyRegGetPropertiesDateTime(HKEY_LOCAL_MACHINE,
PAnsiChar
(StrProperties +
'0067'
),
True
, DTLastWriteTime);
MyRegQueryStringValueEx(phkResult3,
'FriendlyName'
, StrFriendlyName);
MyRegQueryStringValueEx(phkResult3,
'ClassGUID'
, StrClassGUID);
StrClassGUID:=MyGetUSBDeviceClassGUIDToStr(StrClassGUID);
StrKey_WPDBUSENUM:=
PAnsiChar
(
'SYSTEM\CurrentControlSet\Enum\SWD\WPDBUSENUM\_??_USBSTOR#'
+ KeyNamesList1[I] +
'#'
+ StrSerialNumber +
'#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}'
);
if
MyRegOpenKeyEx(HKEY_LOCAL_MACHINE, StrKey_WPDBUSENUM, KEY_READ
or
KEY_QUERY_VALUE,
True
, hkKeyLastUesrDateTime)
then
begin
MyRegQueryStringValueEx(hkKeyLastUesrDateTime,
'Mfg'
, StrMfg);
MyRegQueryStringValueEx(hkKeyLastUesrDateTime,
'FriendlyName'
, StrVolumeName);
RegCloseKey(hkKeyLastUesrDateTime);
end
else
begin
StrMfg:=
''
;
StrVolumeName:=
''
;
end
;
with
MyUSBDeviceInfo[J]
do
begin
StringCbCopyA(@USBDI_FriendlyName[
0
], SizeOf(USBDI_FriendlyName),
PAnsiChar
(StrFriendlyName));
StringCbCopyA(@USBDI_DeviceType[
0
], SizeOf(USBDI_DeviceType),
PAnsiChar
(StrClassGUID));
StrSerialNumber:=MyGetUSBSerialNumberOnRegKey(StrSerialNumber);
StringCbCopyA(@USBDI_DeviceSerialNumber[
0
], SizeOf(USBDI_DeviceSerialNumber),
PAnsiChar
(StrSerialNumber));
StringCbCopyA(@USBDI_DeviceMfg[
0
], SizeOf(USBDI_DeviceMfg),
PAnsiChar
(StrMfg));
StringCbCopyA(@USBDI_DeviceVolumeName[
0
], SizeOf(USBDI_DeviceVolumeName),
PAnsiChar
(StrVolumeName));
USBDI_SetupDateTime:=DTSetupDateTime;
USBDI_ConnectTime:=DTConnectTime;
USBDI_LastUesrDateTime:=DTLastWriteTime;
end
;
Inc(iTtemCount);
Break;
end
;
end
;
end
;
RegCloseKey(phkResult3);
end
;
end
;
RegCloseKey(phkResult2);
end
;
end
;
MySetThreadTokenOnProcess(
0
,
nil
,
False
, StrErrorInfo);
end
else
begin
MyAddDebugInfo(
'Err Reg Token:'
+ StrErrorInfo);
end
;
end
;
KeyNamesList1
.
Free;
KeyNamesList2
.
Free;
KeyNamesList3
.
Free;
RegCloseKey(phkResult);
end
;
Result:=iTtemCount >
0
;
end
;
procedure
TWindowsVisualManage_MainForm
.
PopupMenu_other2_USBSTORClick(
Sender: TObject);
var
cListItem : TListItem;
cListColumn : TListColumn;
MyUSBDeviceInfo : TMyUSBDeviceInfoArray;
I :
Integer
;
begin
MyPopupMenu_other2_AsClick(Sender);
cListColumn:=ListView_VCLShareQuery
.
Columns
.
Add;
cListColumn
.
Caption:=
'设备名称'
;
cListColumn
.
Width:=
250
;
cListColumn:=ListView_VCLShareQuery
.
Columns
.
Add;
cListColumn
.
Caption:=
'设备类型'
;
cListColumn
.
Width:=
68
;
cListColumn:=ListView_VCLShareQuery
.
Columns
.
Add;
cListColumn
.
Caption:=
'设备位置'
;
cListColumn
.
Width:=
132
;
cListColumn:=ListView_VCLShareQuery
.
Columns
.
Add;
cListColumn
.
Caption:=
'设备序列号'
;
cListColumn
.
Width:=
158
;
cListColumn:=ListView_VCLShareQuery
.
Columns
.
Add;
cListColumn
.
Caption:=
'制造商'
;
cListColumn
.
Width:=
82
;
cListColumn:=ListView_VCLShareQuery
.
Columns
.
Add;
cListColumn
.
Caption:=
'卷标'
;
cListColumn
.
Width:=
82
;
cListColumn:=ListView_VCLShareQuery
.
Columns
.
Add;
cListColumn
.
Caption:=
'首次插入时间'
;
cListColumn
.
Width:=
126
;
cListColumn:=ListView_VCLShareQuery
.
Columns
.
Add;
cListColumn
.
Caption:=
'最近插入时间'
;
cListColumn
.
Width:=
126
;
cListColumn:=ListView_VCLShareQuery
.
Columns
.
Add;
cListColumn
.
Caption:=
'最近拔出时间'
;
cListColumn
.
Width:=
126
;
if
MyGetUSBDeviceUserInfo(MyUSBDeviceInfo)
then
begin
for
I:=Low(MyUSBDeviceInfo)
to
High(MyUSBDeviceInfo)
do
begin
with
MyUSBDeviceInfo[I]
do
begin
cListItem:=ListView_VCLShareQuery
.
Items
.
Add;
cListItem
.
Caption:=USBDI_FriendlyName;
cListItem
.
SubItems
.
Add(USBDI_DeviceType);
cListItem
.
SubItems
.
Add(USBDI_LocationInformation);
cListItem
.
SubItems
.
Add(USBDI_DeviceSerialNumber);
cListItem
.
SubItems
.
Add(USBDI_DeviceMfg);
cListItem
.
SubItems
.
Add(USBDI_DeviceVolumeName);
cListItem
.
SubItems
.
Add(FormatDateTime(
'yyyy/mm/dd hh:mm:ss'
, USBDI_SetupDateTime));
cListItem
.
SubItems
.
Add(FormatDateTime(
'yyyy/mm/dd hh:mm:ss'
, USBDI_ConnectTime));
cListItem
.
SubItems
.
Add(FormatDateTime(
'yyyy/mm/dd hh:mm:ss'
, USBDI_LastUesrDateTime));
end
;
end
;
StatusBar1
.
Panels
.
Items[
4
].Text:=
'USB外接设备记录:'
+ IntToStr(ListView_VCLShareQuery
.
Items
.
Count);
end
;
end
;