获取文件占用进程信息

 
 
转自http://blog.csdn.net/linuxsmallping/article/details/51732956
#pragma once
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <atlbase.h>
#include <shlwapi.h>
#include <vector>
#include <map>
using namespace std ;
#include <string>
typedef std :: basic_string < TCHAR , std :: char_traits < TCHAR > , std :: allocator < TCHAR >> tstring ;
#include <winternl.h>
#include <psapi.h>
#pragma comment(lib, "psapi.lib")
#define NT_SUCCESS(status) (status == (NTSTATUS)0x00000000L)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
#define SystemHandleInformation ((SYSTEM_INFORMATION_CLASS)16)
// NTQUERYOBJECT
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING Name ;
WCHAR NameBuffer [ 1 ];
} OBJECT_NAME_INFORMATION , * POBJECT_NAME_INFORMATION ;
typedef enum _OBJECT_INFORMATION_CLASS {
ObjectBasicInformation ,
ObjectNameInformation ,
ObjectTypeInformation ,
ObjectAllInformation ,
ObjectDataInformation
} OBJECT_INFORMATION_CLASS , * POBJECT_INFORMATION_CLASS ;
typedef NTSTATUS ( WINAPI * NTQUERYOBJECT )(
_In_opt_ HANDLE Handle ,
_In_ OBJECT_INFORMATION_CLASS ObjectInformationClass ,
_Out_opt_ PVOID ObjectInformation ,
_In_ ULONG ObjectInformationLength ,
_Out_opt_ PULONG ReturnLength );
// NTQUERYSYSTEMINFORMATION
typedef struct _SYSTEM_HANDLE {
DWORD dwProcessId ;
BYTE bObjectType ;
BYTE bFlags ;
WORD wValue ;
PVOID pAddress ;
DWORD GrantedAccess ;
} SYSTEM_HANDLE , * PSYSTEM_HANDLE ;
typedef struct _SYSTEM_HANDLE_INFORMATION {
DWORD dwCount ;
SYSTEM_HANDLE Handles [ 1 ];
} SYSTEM_HANDLE_INFORMATION , * PSYSTEM_HANDLE_INFORMATION ;
typedef NTSTATUS ( WINAPI * NTQUERYSYSTEMINFORMATION )(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass ,
OUT PVOID SystemInformation ,
IN ULONG SystemInformationLength ,
OUT PULONG ReturnLength OPTIONAL );
//
// NtQueryInformationFile
//
#define FileNameInformation ((FILE_INFORMATION_CLASS)9)
// typedef struct _FILE_NAME_INFORMATION {
// ULONG FileNameLength;
// WCHAR FileName[1];
// } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
typedef NTSTATUS ( WINAPI * NTQUERYINFORMATIONFILE )(
IN HANDLE FileHandle ,
OUT PIO_STATUS_BLOCK IoStatusBlock ,
OUT PVOID FileInformation ,
IN ULONG Length ,
IN FILE_INFORMATION_CLASS FileInformationClass );
// typedef struct _CLIENT_ID {
// HANDLE UniqueProcess;
// HANDLE UniqueThread;
// } CLIENT_ID, *PCLIENT_ID;
// ncScopedHandle
class ncScopedHandle
{
ncScopedHandle ( const ncScopedHandle & );
ncScopedHandle & operator = ( const ncScopedHandle & );
public:
ncScopedHandle ( HANDLE handle )
: _handle ( handle )
{
}
~ ncScopedHandle ()
{
if ( _handle != NULL ) {
CloseHandle ( _handle );
}
}
operator HANDLE () const
{
return _handle ;
}
PHANDLE operator & ()
{
return & _handle ;
}
void operator = ( HANDLE handle )
{
if ( _handle != NULL ) {
CloseHandle ( _handle );
}
_handle = handle ;
}
private:
HANDLE _handle ;
};
// ncFileHandle
struct ncFileHandle
{
SYSTEM_HANDLE _handle ;
tstring _filePath ;
tstring _path ;
ncFileHandle ( SYSTEM_HANDLE handle , const tstring & filePath , const tstring & path )
: _handle ( handle )
, _filePath ( filePath )
, _path ( path )
{
}
};
// GetDeviceDriveMap
void GetDeviceDriveMap ( std :: map < tstring , tstring >& mapDeviceDrive )
{
TCHAR szDrives [ 512 ];
if ( ! GetLogicalDriveStrings ( _countof ( szDrives ) - 1 , szDrives )) {
return ;
}
TCHAR * lpDrives = szDrives ;
TCHAR szDevice [ MAX_PATH ];
TCHAR szDrive [ 3 ] = _T ( " :" );
do {
* szDrive = * lpDrives ;
if ( QueryDosDevice ( szDrive , szDevice , MAX_PATH )) {
mapDeviceDrive [ szDevice ] = szDrive ;
}
while ( * lpDrives ++ );
}
while ( * lpDrives );
}
// DevicePathToDrivePath
BOOL DevicePathToDrivePath ( tstring & path )
{
static std :: map < tstring , tstring > mapDeviceDrive ;
if ( mapDeviceDrive . empty ()) {
GetDeviceDriveMap ( mapDeviceDrive );
}
for ( std :: map < tstring , tstring >:: const_iterator it = mapDeviceDrive . begin (); it != mapDeviceDrive . end (); ++ it ) {
size_t nLength = it -> first . length ();
if ( _tcsnicmp ( it -> first . c_str (), path . c_str (), nLength ) == 0 ) {
path . replace ( 0 , nLength , it -> second );
return TRUE ;
}
}
return FALSE ;
}
// GetHandlePath
BOOL GetHandlePath ( HANDLE handle , tstring & path )
{
static NTQUERYOBJECT fpNtQueryObject =
( NTQUERYOBJECT ) GetProcAddress ( GetModuleHandle ( _T ( "ntdll" )), "NtQueryObject" );
if ( fpNtQueryObject == NULL ) {
return FALSE ;
}
DWORD dwLength = 0 ;
OBJECT_NAME_INFORMATION info ;
NTSTATUS status = fpNtQueryObject ( handle , ObjectNameInformation , & info , sizeof ( info ), & dwLength );
if ( status != STATUS_BUFFER_OVERFLOW ) {
return FALSE ;
}
POBJECT_NAME_INFORMATION pInfo = ( POBJECT_NAME_INFORMATION ) malloc ( dwLength );
while ( true ) {
status = fpNtQueryObject ( handle , ObjectNameInformation , pInfo , dwLength , & dwLength );
if ( status != STATUS_BUFFER_OVERFLOW ) {
break ;
}
pInfo = ( POBJECT_NAME_INFORMATION ) realloc ( pInfo , dwLength );
}
BOOL bRes = FALSE ;
if ( NT_SUCCESS ( status )) {
path = pInfo -> Name . Buffer ;
bRes = DevicePathToDrivePath ( path );
}
free ( pInfo );
return bRes ;
}
// GetSystemHandleInfo
PSYSTEM_HANDLE_INFORMATION GetSystemHandleInfo ()
{
static NTQUERYSYSTEMINFORMATION fpNtQuerySystemInformation =
( NTQUERYSYSTEMINFORMATION ) GetProcAddress ( GetModuleHandle ( _T ( "ntdll" )), "NtQuerySystemInformation" );
if ( fpNtQuerySystemInformation == NULL ) {
return NULL ;
}
DWORD dwLength = 0 ;
SYSTEM_HANDLE_INFORMATION shi ;
NTSTATUS status = fpNtQuerySystemInformation ( SystemHandleInformation , & shi , sizeof ( shi ), & dwLength );
if ( status != STATUS_INFO_LENGTH_MISMATCH ) {
return NULL ;
}
PSYSTEM_HANDLE_INFORMATION pshi = ( PSYSTEM_HANDLE_INFORMATION ) malloc ( dwLength );
while ( true ) {
status = fpNtQuerySystemInformation ( SystemHandleInformation , pshi , dwLength , & dwLength );
if ( status != STATUS_INFO_LENGTH_MISMATCH ) {
break ;
}
pshi = ( PSYSTEM_HANDLE_INFORMATION ) realloc ( pshi , dwLength );
}
if ( ! NT_SUCCESS ( status )) {
free ( pshi );
pshi = NULL ;
}
return pshi ;
}
//
// 检测指定句柄是否可能导致NtQueryObject卡死:
// 1.注意必须使用NtQueryInformationFile而不是NtQueryObject进行检测,否则可能导致WinXP系统
// 下进程死锁而无法结束。
//
void CheckBlockThreadFunc ( void * param )
{
static NTQUERYINFORMATIONFILE fpNtQueryInformationFile =
( NTQUERYINFORMATIONFILE ) GetProcAddress ( GetModuleHandle ( _T ( "ntdll" )), "NtQueryInformationFile" );
if ( fpNtQueryInformationFile != NULL ) {
BYTE buf [ 1024 ];
IO_STATUS_BLOCK ioStatus ;
fpNtQueryInformationFile (( HANDLE ) param , & ioStatus , buf , 1024 , FileNameInformation );
}
}
// IsBlockingHandle
BOOL IsBlockingHandle ( HANDLE handle )
{
HANDLE hThread = ( HANDLE ) _beginthread ( CheckBlockThreadFunc , 0 , ( void * ) handle );
if ( WaitForSingleObject ( hThread , 100 ) != WAIT_TIMEOUT ) {
return FALSE ;
}
TerminateThread ( hThread , 0 );
return TRUE ;
}
// FindFileHandle
BOOL FindFileHandle ( LPCTSTR lpName , vector < ncFileHandle >& handles )
{
handles . clear ();
if ( lpName == NULL ) {
return FALSE ;
}
// 打开“NUL”文件以便后续获取文件句柄类型值。
ncScopedHandle hTempFile = CreateFile ( _T ( "NUL" ), GENERIC_READ , 0 , NULL , OPEN_EXISTING , 0 , 0 );
if ( hTempFile == NULL ) {
return FALSE ;
}
// 获取当前系统中所有的句柄信息。
PSYSTEM_HANDLE_INFORMATION pshi = GetSystemHandleInfo ();
if ( pshi == NULL ) {
return FALSE ;
}
// 查询当前系统的文件句柄类型值。
BYTE nFileType = 0 ;
DWORD dwCrtPid = GetCurrentProcessId ();
for ( DWORD i = 0 ; i < pshi -> dwCount ; ++ i ) {
if ( pshi -> Handles [ i ]. dwProcessId == dwCrtPid && hTempFile == ( HANDLE ) pshi -> Handles [ i ]. wValue ) {
nFileType = pshi -> Handles [ i ]. bObjectType ;
break ;
}
}
HANDLE hCrtProc = GetCurrentProcess ();
for ( DWORD i = 0 ; i < pshi -> dwCount ; ++ i ) {
// 过滤掉非文件类型的句柄。
if ( pshi -> Handles [ i ]. bObjectType != nFileType ) {
continue ;
}
// 将上述句柄复制到当前进程中。
ncScopedHandle handle = NULL ;
ncScopedHandle hProc = OpenProcess ( PROCESS_DUP_HANDLE , FALSE , pshi -> Handles [ i ]. dwProcessId );
if ( hProc == NULL || ! DuplicateHandle ( hProc , ( HANDLE ) pshi -> Handles [ i ]. wValue , hCrtProc , & handle , 0 , FALSE , DUPLICATE_SAME_ACCESS )) {
continue ;
}
// 过滤掉会导致NtQueryObject卡死的句柄(如管道等)。
if ( IsBlockingHandle ( handle )) {
continue ;
}
// 获取句柄对应的文件路径并进行匹配检查。
tstring filePath ;
if ( GetHandlePath ( handle , filePath ) && filePath . find ( lpName ) != tstring :: npos ) {
ncScopedHandle hProcess = OpenProcess ( MAXIMUM_ALLOWED , FALSE , pshi -> Handles [ i ]. dwProcessId );
TCHAR szProcName [ MAX_PATH ];
GetProcessImageFileName ( hProcess , szProcName , MAX_PATH );
tstring path ( szProcName );
DevicePathToDrivePath ( path );
ncFileHandle fh ( pshi -> Handles [ i ], filePath , path );
handles . push_back ( fh );
}
}
free ( pshi );
return TRUE ;
}
// BOOL CloseHandleEx (HANDLE handle, DWORD dwPid)
// {
// if (GetCurrentProcessId () == dwPid)
// return CloseHandle (handle);
//
// ncScopedHandle hProcess = OpenProcess (PROCESS_DUP_HANDLE, FALSE, dwPid);
// if (hProcess == NULL)
// return FALSE;
//
// return DuplicateHandle (hProcess, handle, GetCurrentProcess (), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE);
// }
// main
int _tmain ( int argc , _TCHAR * argv [])
{
tstring path ( _T ( "E: \\ TDDOWNLOAD \\ " ));
vector < ncFileHandle > vecHandles ;
if ( ! FindFileHandle ( path . c_str (), vecHandles )) {
return - 1 ;
}
return 0 ;
}
前言 上一次发布过的程序:【首发】检测文件占用,具有学习和商业价值(By超级用户),可以使用,仿电脑管家 正文 对于怎么枚举文件句柄 ,上一帖子对此有介绍,核心代码大概如下:如果 (ZwQueryObject (handle, #ObjectTypeInformation, unicode, 0, size) ≠ #STATUS_INVALID_HANDLE )' 只要不是无效的,为什么,详细看下面的注释 ' 参数 ' Handle ' 对象的一个句柄来获取信息。 ' ObjectInformationClass ' 指定一个OBJECT_INFORMATION_CLASS返回值的类型决定了信息在ObjectInformation缓冲区。 ' ObjectInformation ' 一个指向caller-allocated缓冲接收请求的信息。 ' ObjectInformationLength ' 指定的大小,以字节为单位,ObjectInformation缓冲区。 ' ReturnLength ' 一个指向变量的指针,接收的大小,以字节为单位,请求的关键信息。如果NtQueryObject STATUS_SUCCESS返回,返回的变量包含的数据量。如果NtQueryObject返回STATUS_BUFFER_OVERFLOW或STATUS_BUFFER_TOO_SMALL,您可以使用变量的值来确定所需的缓冲区大小。 ' 返回值 ' NtQueryObject返回STATUS_SUCCESS或适当的错误状态。可能的错误状态码包括以下: ' 返回代码 描述 ' STATUS_ACCESS_DENIED ' 有足够的权限来执行该cha询。 ' STATUS_INVALID_HANDLE ' 提供对象句柄无效。 ' STATUS_INFO_LENGTH_MISMATCH ' 信息长度不足以容纳数据。 unicode = 取空白字节集 (size) ZwQueryObject (handle, #ObjectTypeInformation, unicode, size, 0)' 读取信息的unicode文本 RtlUnicodeStringToAnsiString (ansi, unicode, 真)' 编码转换 ' RtlUnicodeStringToAnsiString例程将给定Unicode字符串转换成一个ANSI字符串。 str = 指针到文本 (ansi.Buffer) ' RtlFreeAnsiString常规版本存储由RtlUnicodeStringToAnsiString分配。 ' 参数 ' AnsiString ' 指针ANSI字符串缓冲区由RtlUnicodeStringToAnsiString以前分配的。 RtlFreeAnsiString (ansi) str = “无法获取”' 无效的怎么获取…… 返回 (str) 这一次呢更新了一个RemoteCloseHandle ,大概的原理是什么呢? 同时也采用了一些比较骚的方法,这种方法的限制较多,但是对于32位进程就很有效果。 NtClose在MSDN的大概介绍 1. NtClose is a generic routine that operates on any type of object. 2. Closing an open object handle causes that handle to become invalid. The system also decrements the handle count for the object and checks whether the object can be deleted. The system does not actually delete the object until all of the object's handles are closed and no referenced pointers remain. 3. A driver must close every handle that it opens as soon as the handle is no longer required. Kernel handles, which are those that are opened by a system thread or by specifying the OBJ_KERNEL_HANDLE flag, can be closed only when the previous processor mo
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值