天天看點

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的檔案句柄類型,如果是其他系統,則應該注意修改之

繼續閱讀