C++解除文件占用

1.解除文件占用,其过程比较简单,当然在寻找这个过程还是吃了不少苦头的,首先呢,我们需要,遍历系统中所有的文件句柄该过程呢,就要是检测句柄类型,如果是28,则可以认为是文件,然后检测先该文件名是不是我们需要的,如果是我们需要的,则要记录下该句柄的ProcessId,然后再打开该进程,然后向该进程中注入远程线程,关掉该文件即可

现在呢,实现了,可以遍历系统中所有正在使用的文件


#include"stdafx.h"

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <psapi.h>
#include <strsafe.h>
#include <assert.h>
#include<iostream>
#include<fstream>
using namespace std;
#pragma comment(lib,"PSAPI.LIB")
//#pragma comment(lib,"Ntoskrnl.lib")


typedef struct _IO_STATUS_BLOCK {
	union {
		NTSTATUS Status;
		PVOID    Pointer;
	};
	ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

typedef struct _SYSTEM_HANDLE
{
	ULONG ProcessId;
	UCHAR ObjectTypeNumber;
	UCHAR Flags;
	USHORT Handle;
	PVOID Object;
	ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE,*PSYSTEM_HANDLE;

typedef struct _SYSTEM_HANDLE_INFORMATION
{
	ULONG NumberOfHandles;
	SYSTEM_HANDLE HandleInfo[1];
}SYSTEM_HANDLE_INFORMATION,*PSYSTEM_HANDLE_INFORMATION;


typedef enum _SYSTEM_INFORMATION_CLASS {

	SystemBasicInformation, SystemProcessorInformation, SystemPerformanceInformation, SystemTimeOfDayInformation, SystemPathInformation, SystemProcessInformation, SystemCallCountInformation, SystemDeviceInformation, SystemProcessorPerformanceInformation, SystemFlagsInformation, SystemCallTimeInformation, SystemModuleInformation, SystemLocksInformation, SystemStackTraceInformation, SystemPagedPoolInformation, SystemNonPagedPoolInformation, SystemHandleInformation, SystemObjectInformation, SystemPageFileInformation, SystemVdmInstemulInformation, SystemVdmBopInformation, SystemFileCacheInformation, SystemPoolTagInformation, SystemInterruptInformation, SystemDpcBehaviorInformation, SystemFullMemoryInformation, SystemLoadGdiDriverInformation, SystemUnloadGdiDriverInformation, SystemTimeAdjustmentInformation, SystemSummaryMemoryInformation, SystemNextEventIdInformation, SystemEventIdsInformation, SystemCrashDumpInformation, SystemExceptionInformation, SystemCrashDumpStateInformation, SystemKernelDebuggerInformation, SystemContextSwitchInformation, SystemRegistryQuotaInformation, SystemExtendServiceTableInformation, SystemPrioritySeperation, SystemPlugPlayBusInformation, SystemDockInformation, SystemProcessorSpeedInformation, SystemCurrentTimeZoneInformation, SystemLookasideInformation

} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;



typedef enum _FILE_INFORMATION_CLASS { 
	FileDirectoryInformation                 = 1,
	FileFullDirectoryInformation,
	FileBothDirectoryInformation,
	FileBasicInformation,
	FileStandardInformation,
	FileInternalInformation,
	FileEaInformation,
	FileAccessInformation,
	FileNameInformation,
	FileRenameInformation,
	FileLinkInformation,
	FileNamesInformation,
	FileDispositionInformation,
	FilePositionInformation,
	FileFullEaInformation,
	FileModeInformation,
	FileAlignmentInformation,
	FileAllInformation,
	FileAllocationInformation,
	FileEndOfFileInformation,
	FileAlternateNameInformation,
	FileStreamInformation,
	FilePipeInformation,
	FilePipeLocalInformation,
	FilePipeRemoteInformation,
	FileMailslotQueryInformation,
	FileMailslotSetInformation,
	FileCompressionInformation,
	FileObjectIdInformation,
	FileCompletionInformation,
	FileMoveClusterInformation,
	FileQuotaInformation,
	FileReparsePointInformation,
	FileNetworkOpenInformation,
	FileAttributeTagInformation,
	FileTrackingInformation,
	FileIdBothDirectoryInformation,
	FileIdFullDirectoryInformation,
	FileValidDataLengthInformation,
	FileShortNameInformation,
	FileIoCompletionNotificationInformation,
	FileIoStatusBlockRangeInformation,
	FileIoPriorityHintInformation,
	FileSfioReserveInformation,
	FileSfioVolumeInformation,
	FileHardLinkInformation,
	FileProcessIdsUsingFileInformation,
	FileNormalizedNameInformation,
	FileNetworkPhysicalNameInformation,
	FileIdGlobalTxDirectoryInformation,
	FileIsRemoteDeviceInformation,
	FileAttributeCacheInformation,
	FileNumaNodeInformation,
	FileStandardLinkInformation,
	FileRemoteProtocolInformation,
	FileReplaceCompletionInformation,
	FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;


typedef struct _FILE_NAME_INFORMATION {
	ULONG FileNameLength;
	WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;


HANDLE hCopy;


typedef enum _OBJECT_INFORMATION_CLASS {

	ObjectBasicInformation, ObjectNameInformation, ObjectTypeInformation, ObjectAllInformation, ObjectDataInformation

} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;

typedef struct _LSA_UNICODE_STRING {
	USHORT Length;
	USHORT MaximumLength;
	PWSTR  Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;



typedef struct _OBJECT_NAME_INFORMATION {

	UNICODE_STRING Name; WCHAR NameBuffer[0];

} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
typedef long(__stdcall*PNtQueryObject)(HANDLE ObjectHandle,ULONG ObjectInformationClass,PVOID ObjectInformation,ULONG ObjectInformationLength,PULONG ReturnLength);


//声明Native API函数
typedef NTSTATUS (WINAPI *NTQUERYSYSTEMINFOMATION)(
	IN SYSTEM_INFORMATION_CLASS SystemClass,
	OUT LPVOID SystemInfo,
	IN ULONG SystemInfoLength,
	OUT PULONG ReturnLength
	);




char filename[256]={0};


DWORD WINAPI GetFileName(LPVOID p )
{	
	int* ProcessId=(int*)p;
	HMODULE hNtDll=LoadLibrary(L"ntdll.dll");
	if(hNtDll==NULL)
	{
		return 0;
	}
	PNtQueryObject NtQueryObject=(PNtQueryObject)GetProcAddress(hNtDll,"NtQueryObject");	
	POBJECT_NAME_INFORMATION pObject=NULL;
	pObject=(POBJECT_NAME_INFORMATION)HeapAlloc(GetProcessHeap(),0,MAX_PATH*2);
	memset(pObject,0,MAX_PATH*2);
	ULONG returnLength;
	DWORD dwReturn=NtQueryObject(hCopy,ObjectNameInformation,pObject,MAX_PATH*2,&returnLength);
	//将卷路径名修改成盘符路径	
		
	if((pObject->NameBuffer!=NULL)&&(dwReturn==0))
	{
		DWORD n=WideCharToMultiByte(CP_OEMCP,NULL,pObject->NameBuffer,-1,NULL,0,NULL,FALSE);
	    char*	name=new char[n+1];
		memset(name,0,n+1);
		WideCharToMultiByte(CP_OEMCP,NULL,pObject->NameBuffer,-1,name,n,NULL,FALSE);	
		char tmp[256]={0};
		sprintf(tmp,"%d",ProcessId);
		if(strstr(name,filename))
		{
			cout<<"该进程ID 是"<<*ProcessId<<endl;		
		}
	//	cout<<name<<endl;
		ofstream out("E:\\result.txt",ios::app);
		out.write(name,strlen(name));
		out.write("\n",strlen("\n"));
		out.close();
		delete[] name;
	}
	HeapFree(GetProcessHeap(),0,pObject);
	return dwReturn;
}

//根据进程ID获取当前进程所使用的所有文件的句柄
void EnumFileHandle(DWORD pid)
{
	HMODULE hNtDll=LoadLibrary(L"ntdll.dll");
	if(hNtDll==NULL)
	{
		return;
	}
	//开始获取,其他API地址
	NTQUERYSYSTEMINFOMATION NtQuerySystemInformation=(NTQUERYSYSTEMINFOMATION)
		GetProcAddress(hNtDll,"NtQuerySystemInformation");
	if(NtQuerySystemInformation==NULL)
	{
		return;
	}	
	//开始为我们需要信息开辟内存
	DWORD nSize=4096,nReturn=0;
	PSYSTEM_HANDLE_INFORMATION pHandleInfo=(PSYSTEM_HANDLE_INFORMATION)	HeapAlloc(GetProcessHeap(),0,nSize);
	while(NtQuerySystemInformation(SystemHandleInformation,pHandleInfo,nSize,&nReturn)==0xc0000004)
	{
		HeapFree(GetProcessHeap(),0,pHandleInfo);
		nSize+=4096;
		pHandleInfo=(PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(),0,nSize);
	}
	//这样就开辟成功了
	//然后打开指定的进程

	DWORD dwFileCount=0;	
	for(ULONG i=0;i<pHandleInfo->NumberOfHandles;i++)
	{
		PSYSTEM_HANDLE pHandle=(PSYSTEM_HANDLE)&(pHandleInfo->HandleInfo[i]);

		if((pHandle->ObjectTypeNumber==0x1c)&&(pHandle->ProcessId!=4))
		{			
			//如果是当前进程的某个文件,这说明,该进程下有文件操作			
			HANDLE hProcess=OpenProcess(PROCESS_DUP_HANDLE|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,pHandle->ProcessId);
			if(hProcess==NULL)
			{
				int a=GetLastError();
			//	cout<<"OpenProcess "<<a<<endl;
				continue;
			}

			if(!DuplicateHandle(hProcess,(HANDLE)pHandle->Handle,GetCurrentProcess(),&hCopy,MAXIMUM_ALLOWED,FALSE,0))
			{
				continue;
			}		
			int curID=pHandle->ProcessId;
			HANDLE hThread=CreateThread(NULL,0,GetFileName,(LPVOID)&curID,0,NULL);
			if(WaitForSingleObject(hThread,100)==WAIT_TIMEOUT)
			{
				TerminateThread(hThread,0);
			}
			CloseHandle(hThread);
			CloseHandle(hCopy);
			hCopy=0;
			CloseHandle(hProcess);
			hProcess=0;
		}
	}
	HeapFree(GetProcessHeap(),0,pHandleInfo);
}


bool EnableDebugPrivilege()   
{   
	HANDLE hToken;   
	LUID sedebugnameValue;   
	TOKEN_PRIVILEGES tkp;   
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
	{   
		return   FALSE;   
	}   
	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))  
	{   
		CloseHandle(hToken);   
		return false;   
	}   
	tkp.PrivilegeCount = 1;   
	tkp.Privileges[0].Luid = sedebugnameValue;   
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;   
	if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) 
	{   
		CloseHandle(hToken);   
		return false;   
	}   
	return true;   
}
int main()
{
	cout<<"请输入查找的文件名称"<<endl;
	cin>>filename;
	EnableDebugPrivilege();
	HANDLE hFile1=CreateFile(L"D:\\2.txt", GENERIC_READ,0, NULL, OPEN_EXISTING, 0, NULL);
	DWORD dwTmp;
	WriteFile(hFile1,L"DASD",4,&dwTmp,NULL);
	EnumFileHandle(::GetCurrentProcessId());	
	CloseHandle(hFile1);
	system("pause");
	return 0;
}
这样就能根据文件名称获得该文件所在的进程ID了,不足的是我们使用的是28,也就是32bit的win7的文件句柄类型,如果是其他系统,则应该注意修改之

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世纪殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值