Вчера для тестирования приложения понадобилась утилита, которая могла бы показать список всех открытых в процессе файлов и выполнить с ними некоторые операции (правку, удаление).
Сложность в том, что как только приложение открывает файл, оно его лочит и его нельзя ни удалить ни редактировать. А для теста нужно было удалить такой файл на этапе, когда он уже залочен. Для этого понадобилось обратиться к недокументированным API виндовса.
Задача решается следующим образом. Вызывается функция NtQuerySystemInformation из библиотеки NTDLL. Она возвращает информацию по всем хендлам (HANDLE) в ОСи в виде структур:
typedef struct _SYSTEM_HANDLE_ENTRY {
ULONG OwnerPid; // PID процесса
BYTE ObjectType; // Тип информации, на который ссылается HANDLE
BYTE HandleFlags; // Флаги, по ним я ничего не знаю
USHORT HandleValue; // Дескриптор хендла
PVOID ObjectPointer; // указатель на прочитаный обьект в памяти
ACCESS_MASK AccessMask; // маска доступа
}
Дальше мы перебираем каждый открытый HANDLE_ENTRY и смотрим его тип. До виндовс 8.1 ObjectType == 28 указывал на файлы. В виндовс 8.1 видно чего-то добавили (API не документировано, так что хрен его знает чего добавлено), так что теперь тип для файлов равняется 30. И это тот момент, который долго выносил мне мозг и я не мог понять почему код не работает.
Дальше когда мы находим ENTRY у которого OwnerPid равняется PID тестируемого процесса и ObjectType == 30, мы дублируем этот хендлер с полными правами доступа DUPLICATE_SAME_ACCESS в наш хендлер с помощью функции DuplicateHandle(). Дальше мы можем делать с этим хендлером всё что угодно, так как он ссылается уже нужный нам файл и может тоже в него писать, удалять его и т.д.
В моем примере программа выводит имена всех открытых файлов для процесса, думаю вам такое приложение тоже может быть полезно иногда, так что компилируйте на здоровье (Только ObjectType согласно вашей ОС версии подставьте). Пока что ещё криво работает, некоторые файлы повторяются, не разобрался ещё почему, API ведь не документирован и информацию приходится самому выковыривать, но тем не менее список содержит именно все файлы отрытые процессом.
Солюшин: