Alle offenen Handles einer Datei herausfinden
-
Gegeben ist ein Dateiname (z.B. "c:\x.txt"). Nun möchte ich alle Handles herausfinden die diese Datei gerade geöffnet haben.
Im zweiten Schritt bräuchte ich dann noch das Handle des Prozesses der die Datei geöffnet hat.Geht sowas?
Das Programm darf ausdrücklich mit Administarationsrechten laufen.
-
Nein, das geht nicht. Man kann sowas für "lokale" Prozess z.B. mit dem Prozess-Explorer machen. Wenn die Datei aber via Netzwerkshare geöffnet ist, hilft Dir das nicht viel weiter...
WAS willst Du denn genau? bzw. WARUM?
-
Manchmal "blockiert" irgendein Programm / Thread eine Datei, und behindert diese am geschrieben werden oder am löschen.
Ich möchte nun ein Programm schrieben welches mir anzeigt, welches Programm der Verursacher ist.
-
Dann schau am besten mit dem Prozess Explorer nach... solche Funktion in Dein eigenes Programm einzubauen, würde ich nicht machen... ch vermute eher, Du vergisst selber das Dateihandle zu schliessen...
-
das geht mit der nativen NT API. hab ich mal gemacht. über normale winapi geht es nicht.
-
ich kann dir nachher mal meinen code geben, wenn du ihn dan nnoch brauchst.
-
Mein Programm öffnet (bisher) keine Handels. Es soll extra für diesen Zweck ein Programm sein.
@hack0r
Am Codebeispiel bin ich interressiert.
-
so, bitte schön
openfiles.c
#include "openfiles.h" /* * GetNumOpenFiles - Returns the number of open files for a process. * * The function returns the number of open file handles for the specified * process. * * @pid * Identifier of the process to retrieve the number of open files for. * * @return * The number of open files on success, -1 on error. * */ int GetNumOpenFiles( DWORD pid ) { ULONG *p, n, i, count = 0; PSYSTEM_HANDLE_INFORMATION h; HANDLE hProcess; PFN_NtQuerySystemInformation NtQuerySystemInformation = (PFN_NtQuerySystemInformation) GetProcAddress(LoadLibrary("NTDLL"), "NtQuerySystemInformation"); PFN_NtQueryObject NtQueryObject = (PFN_NtQueryObject) GetProcAddress(LoadLibrary("NTDLL"), "NtQueryObject"); if(!NtQuerySystemInformation || !NtQueryObject) return -1; if(!(hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid))) return -1; n = 0x1000; p = malloc(sizeof(ULONG) * n); while(NtQuerySystemInformation(SystemHandleInformation, p, n * sizeof(*p), 0) == STATUS_INFO_LENGTH_MISMATCH) { free(p); n = n * 2; p = malloc(sizeof(ULONG) * n); } h = (PSYSTEM_HANDLE_INFORMATION)(p + 1); for(i = 0; i < *p; i++) { /* handle belongs to target process */ if(h[i].ProcessId == pid) count++; } CloseHandle(hProcess); free(p); return count; } /* * GetOpenFiles - Retrieves a list of open files for a process. * * The function retrieves a list of files opened by the specified * process. * * @pid * Identifier of the process to retrieve the list of files for. * * @pFiles * Pointer to an array of POPENFILE_T structures that will receive the * information on the opened files. * * @pNumFiles * Maximum number of files to retrieve. * * @return * The function returns the number of entries in pFiles on success, * -1 on failure. * */ int GetOpenFiles( DWORD pid, POPENFILE_T pFiles, DWORD dwNumFiles ) { ULONG *p, n, i, count = 0; PSYSTEM_HANDLE_INFORMATION h; HANDLE hProcess; PFN_NtQuerySystemInformation NtQuerySystemInformation = (PFN_NtQuerySystemInformation) GetProcAddress(LoadLibrary("NTDLL"), "NtQuerySystemInformation"); PFN_NtQueryObject NtQueryObject = (PFN_NtQueryObject) GetProcAddress(LoadLibrary("NTDLL"), "NtQueryObject"); if(!NtQuerySystemInformation || !NtQueryObject) return -1; if(!(hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid))) return -1; n = 0x1000; p = malloc(sizeof(ULONG) * n); while(NtQuerySystemInformation(SystemHandleInformation, p, n * sizeof(*p), 0) == STATUS_INFO_LENGTH_MISMATCH) { free(p); n = n * 2; p = malloc(sizeof(ULONG) * n); } h = (PSYSTEM_HANDLE_INFORMATION)(p + 1); for(i = 0; i < *p; i++) { if(count >= dwNumFiles) break; /* handle belongs to target process */ if(h[i].ProcessId == pid) { HANDLE hObject; OBJECT_BASIC_INFORMATION obi; OBJECT_NAME_INFORMATION *poni; if(!DuplicateHandle(hProcess, (HANDLE)h[i].Handle, GetCurrentProcess(), &hObject, 0, 0, DUPLICATE_SAME_ATTRIBUTES)) continue; NtQueryObject(hObject, ObjectBasicInformation, &obi, sizeof(obi), NULL); n = obi.NameInformationLength == 0 ? MAX_PATH * sizeof(WCHAR) : obi.NameInformationLength; poni = (POBJECT_NAME_INFORMATION)malloc(n); NtQueryObject(hObject, ObjectNameInformation, poni, n, NULL); /* convert from something like \Device\Harddisk0\some_file to dos drive letter path */ if(DeviceToDosPath(poni->Name.Buffer, pFiles[count].szFileName, sizeof(pFiles[count].szFileName))) { pFiles[count].dwFlags = h[i].GrantedAccess; count++; } CloseHandle(hObject); } } CloseHandle(hProcess); free(p); return count; } /* * GetPIDsFromFile - Returns process identifiers of all processes that have * currently opened target file. * * @lpFileName * Name of the file to look up. * * @lpPIDs * Pointer to an array of DWORDs that will receive the process identifiers. * * @dwNumPIDs * Maximum number of entries to store in the buffer pointed to by lpPIDs. * * @return * The function returns the actual number of entries in lpPIDs on success, * -1 on failure. * */ int GetPIDsFromFile( PTCHAR lpFileName, PDWORD lpPIDs, DWORD dwNumPIDs ) { ULONG *p, n, i, count = 0; PSYSTEM_HANDLE_INFORMATION h; HANDLE hProcess; PFN_NtQuerySystemInformation NtQuerySystemInformation = (PFN_NtQuerySystemInformation) GetProcAddress(LoadLibrary("NTDLL"), "NtQuerySystemInformation"); PFN_NtQueryObject NtQueryObject = (PFN_NtQueryObject) GetProcAddress(LoadLibrary("NTDLL"), "NtQueryObject"); if(!NtQuerySystemInformation || !NtQueryObject) return -1; n = 0x1000; p = malloc(sizeof(ULONG) * n); while(NtQuerySystemInformation(SystemHandleInformation, p, n * sizeof(*p), 0) == STATUS_INFO_LENGTH_MISMATCH) { free(p); n = n * 2; p = malloc(sizeof(ULONG) * n); } h = (PSYSTEM_HANDLE_INFORMATION)(p + 1); for(i = 0; i < *p; i++) { HANDLE hObject; OBJECT_BASIC_INFORMATION obi; OBJECT_NAME_INFORMATION *poni; TCHAR szFileName[MAX_PATH]; if(count >= dwNumPIDs) break; if(!(hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, h[i].ProcessId))) continue; if(!DuplicateHandle(hProcess, (HANDLE)h[i].Handle, GetCurrentProcess(), &hObject, 0, 0, DUPLICATE_SAME_ATTRIBUTES)) { CloseHandle(hProcess); continue; } CloseHandle(hProcess); NtQueryObject(hObject, ObjectBasicInformation, &obi, sizeof(obi), NULL); n = obi.NameInformationLength == 0 ? MAX_PATH * sizeof(WCHAR) : obi.NameInformationLength; poni = (POBJECT_NAME_INFORMATION)malloc(n); NtQueryObject(hObject, ObjectNameInformation, poni, n, NULL); if(DeviceToDosPath(poni->Name.Buffer, szFileName, sizeof(szFileName))) { if(!_tcscmp(lpFileName, szFileName)) lpPIDs[count++] = h[i].ProcessId; } CloseHandle(hObject); } free(p); return count; } /* * DeviceToDosPath - Converts Device Path to Dos Path. * */ int DeviceToDosPath( PWCHAR lpDevice, PTCHAR lpDosPath, INT nSize ) { int i; DWORD dwDrives; WCHAR szDev[MAX_PATH] = {0}, szRet[MAX_PATH], *p; if(!lpDevice) return 0; /* extract device path */ if(wcsncmp(lpDevice, L"\\Device\\", wcslen(L"\\Device\\"))) return 0; p = lpDevice + wcslen(L"\\Device\\"); while(*p != '\\') { if(*p == 0) return 0; p++; } wcsncpy(szDev, lpDevice, p - lpDevice); dwDrives = GetLogicalDrives(); for(i = 0; i < 32; i++) { if((dwDrives >> i) & 0x01) { WCHAR szDosDevice[MAX_PATH], szDrive[3] = L"A:"; szDrive[0] = 'A' + i; QueryDosDeviceW(szDrive, szDosDevice, sizeof(szDosDevice)); if(!wcscmp(szDev, szDosDevice)) { wcscpy(szRet, szDrive); wcsncat(szRet, p, nSize); #ifndef _UNICODE /* convert to single byte */ WideCharToMultiByte(CP_ACP, 0, szRet, wcslen(szRet) * sizeof(WCHAR), lpDosPath, nSize, NULL, NULL); #else wcscpy(lpDosPath, szRet); #endif } } } return 1; } /* example */ #if 0 int main(int argc, char *argv[]) { DWORD dwPIDs[10]; /* open some file */ HANDLE hFile = CreateFile("C:\\WINDOWS\\win.ini", GENERIC_EXECUTE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); /* get number of open files for this process */ DWORD dwNum = GetNumOpenFiles(GetCurrentProcessId()), i; POPENFILE_T pFiles; if(hFile == INVALID_HANDLE_VALUE) { printf("Could not open C:\\WINDOWS\\win.ini\n"); return 0; } /* get a list of all files this process has currently opened */ pFiles = (POPENFILE_T)malloc(sizeof(OPENFILE_T) * dwNum); dwNum = GetOpenFiles(GetCurrentProcessId(), pFiles, dwNum); printf("Process %i has handles for following files:\n\n", GetCurrentProcessId()); for(i = 0; i < dwNum; i++) printf("%s\n", pFiles[i].szFileName); printf("\n"); /* get a list of processes that have currently opened C:\WINDOWS\win.ini */ dwNum = GetPIDsFromFile( _T("C:\\WINDOWS\\win.ini"), dwPIDs, sizeof(dwPIDs) / sizeof(dwPIDs[0]) ); printf("%i processes have currently opened \"C:\\WINDOWS\\win.ini\" :\n\n", dwNum); for(i = 0; i < dwNum; i++) printf("- %i\n", dwPIDs[i]); free(pFiles); CloseHandle(hFile); return 0; } #endifopenfiles.h
#ifndef _OPENFILES_H_ #define _OPENFILES_H_ #include <Windows.h> #include <tchar.h> /************** public interface **************/ typedef struct OPENFILE_S { TCHAR szFileName[MAX_PATH]; DWORD dwFlags; } OPENFILE_T, *POPENFILE_T; /* * GetNumOpenFiles - Returns the number of open files for a process. * * The function returns the number of open file handles for the specified * process. * * @pid * Identifier of the process to retrieve the number of open files for. * * @return * The number of open files on success, -1 on error. * */ int GetNumOpenFiles( DWORD pid ); /* * GetOpenFiles - Retrieves a list of open files for a process. * * The function retrieves a list of files opened by the specified process. * * @pid * Identifier of the process to retrieve the list of files for. * * @pFiles * Pointer to an array of POPENFILE_T structures that will receive the * information on the opened files. * * @pNumFiles * Maximum number of files to retrieve. * * @return * The function returns 1 on success, -1 on failure. * */ int GetOpenFiles( DWORD pid, POPENFILE_T pFiles, DWORD dwNumFiles ); /* * GetPIDsFromFile - Returns process identifiers of all processes that have * currently opened target file. * * @lpFileName * Name of the file to look up. * * @lpPIDs * Pointer to an array of DWORDs that will receive the process identifiers. * * @dwNumPIDs * Maximum number of entries to store in the buffer pointed to by lpPIDs. * * @return * The function returns the actual number of entries in lpPIDs on success, * -1 on failure. * */ int GetPIDsFromFile( PTCHAR lpFileName, PDWORD lpPIDs, DWORD dwNumPIDs ); /************** private interface **************/ #define NTSTATUS DWORD #define SYSTEM_INFORMATION_CLASS DWORD #define OBJECT_INFORMATION_CLASS DWORD #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 #define DUPLICATE_SAME_ATTRIBUTES 0x00000004 #define SystemHandleInformation 0x10 #define ObjectBasicInformation 0x00 #define ObjectNameInformation 0x01 #define ObjectTypeInformation 0x02 typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef struct _SYSTEM_HANDLE_INFORMATION { ULONG ProcessId; UCHAR ObjectTypeNumber; UCHAR Flags; USHORT Handle; PVOID Object; ACCESS_MASK GrantedAccess; } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; typedef struct _OBJECT_BASIC_INFORMATION { ULONG Attributes; ACCESS_MASK DesiredAccess; ULONG HandleCount; ULONG ReferenceCount; ULONG PagedPoolUsage; ULONG NonPagedPoolUsage; ULONG Reserved[3]; ULONG NameInformationLength; ULONG TypeInformationLength; ULONG SecurityDescriptorLength; LARGE_INTEGER CreationTime; } OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION; typedef struct _OBJECT_TYPE_INFORMATION { UNICODE_STRING TypeName; ULONG TotalNumberOfHandles; ULONG TotalNumberOfObjects; WCHAR Unused1[8]; ULONG HighWaterNumberOfHandles; ULONG HighWaterNumberOfObjects; WCHAR Unused2[8]; ACCESS_MASK InvalidAttributes; GENERIC_MAPPING GenericMapping; ACCESS_MASK ValidAttributes; BOOLEAN SecurityRequired; BOOLEAN MaintainHandleCount; USHORT MaintainTypeList; DWORD PoolType; ULONG DefaultPagedPoolCharge; ULONG DefaultNonPagedPoolCharge; } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; typedef struct _OBJECT_NAME_INFORMATION { UNICODE_STRING Name; WCHAR NameBuffer[0]; } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; typedef NTSTATUS (WINAPI *PFN_NtQuerySystemInformation)( SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG ); typedef NTSTATUS (WINAPI *PFN_NtQueryObject)( HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG); int DeviceToDosPath( PWCHAR lpDevice, PTCHAR lpDosPath, INT nSize ); #endif /* _OPENFILES_H_ */
-
Erst mal danke für ein so ausführiches Codebeispiel.
Mir ist es gelungen die Funktionen in ein BCB Projekt einzubetten.
Leider Bekomme ich "nur" diese Ausgaben:
Process xxx has handles for following files:
0 processes have currently opened C:\test.txtund das obwohl mein Programm mehrere Dateien offen hat.
Öffne ich die test-Datei in meinem Programm (oder in einem anderen) dann scheitert der Aufruf mit "Could not open..."Gibt es da noch einen Lösungsweg?