Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Кто "держит" файл  (Прочитано 8668 раз)
0 Пользователей и 1 Гость смотрят эту тему.
АлександрII
Гость
« : 15-09-2003 20:27 » 

Пытаюсь в программе удалить папку с файлами, но те могут быть кем то заняты. Есть ли способ определить, какая программа "держит" файл? Вроде бы HandleEx от Russinovich'а как-то определяет, но вот как? Нужно под все платформы. Может из драйвера это как-то можно сделать? Подскажите пожалуйста, если кто знает.
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #1 : 16-09-2003 06:11 » 

Могу предложить два способа.
1)Можно так сделать.
Сначала скачать с сайта книгу "Windows NT/2000 Native API" и использовать ее как справочник.
Потом при помощи ф-ции ZwQuerySystemInformation получить SystemHandleInformation, далее пройтись по всем полученным handle отобразить их в свой процесс и исследовать(не забывай их закрывать, а то таблица описателей разрастется, а также заблокируеш на время работы своего процесса возможность уничтожения объектов). Вот пример получения информации об открытых описателях для конкретного процесса, переделать его для получения инфы обо всех процессах не проблема(надо вместо проверки равенства pid открывать процесс с этим pid). Вот код из книги
Код:
#include "ntdll.h"
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc == 1) return 0;

ULONG pid = strtoul(argv[1], 0, 0);

EnablePrivilege(SE_DEBUG_NAME);

HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);

ULONG n = 0x1000;
PULONG p = new ULONG[n];
while (NT::ZwQuerySystemInformation(NT::SystemHandleInformation,
p, n * sizeof *p, 0)
== STATUS_INFO_LENGTH_MISMATCH)
delete [] p, p = new ULONG[n *= 2];

NT::PSYSTEM_HANDLE_INFORMATION h = NT::PSYSTEM_HANDLE_INFORMATION(p + 1);

for (ULONG i = 0; i < *p; i++) {
if (h[i].ProcessId == pid) {
HANDLE hObject;
if (NT::ZwDuplicateObject(hProcess, HANDLE(h[i].Handle),
NtCurrentProcess(), &hObject,
0, 0, DUPLICATE_SAME_ATTRIBUTES)
!= STATUS_SUCCESS)
                  continue;
NT::OBJECT_BASIC_INFORMATION obi;
NT::ZwQueryObject(hObject, NT::ObjectBasicInformation,
&obi, sizeof obi, &n);

printf("%p %04hx %6lx %2x %3lx %3ld %4ld ",
h[i].Object, h[i].Handle, h[i].GrantedAccess,
int(h[i].Flags), obi.Attributes,
obi.HandleCount - 1, obi.PointerCount - 2);

n = obi.TypeInformationLength + 2;
NT::POBJECT_TYPE_INFORMATION oti
= NT::POBJECT_TYPE_INFORMATION(new CHAR[n]);

NT::ZwQueryObject(hObject, NT::ObjectTypeInformation,
oti, n, &n);

printf("%-14.*ws ", oti[0].Name.Length / 2, oti[0].Name.Buffer);
n = obi.NameInformationLength == 0
? MAX_PATH * sizeof (WCHAR) : obi.NameInformationLength;
NT::POBJECT_NAME_INFORMATION oni
= NT::POBJECT_NAME_INFORMATION(new CHAR[n]);

NTSTATUS rv = NT::ZwQueryObject(hObject,
NT::ObjectNameInformation,
oni, n, &n);

if (NT_SUCCESS(rv))
printf("%.*ws", oni[0].Name.Length / 2, oni[0].Name.Buffer);
printf("\n");

CloseHandle(hObject);
}
}

delete [] p;
CloseHandle(hProcess);
return 0;
}

Заметь- тебе нужна привилегия отладки.
Привожу код с сайта проекта HE4(http://he4dev.e1.bmstu.ru). Там получают список процессов, но сначала получают привилегию отладки(код для получения списка процессов оставлю, может пригодится). Код для ф-ции NtGetProcessList смотри на сайте проекта.
Код:
#define STRICT
#include <windows.h>
#include <stdio.h>
#include <wchar.h>
#include "NtProcessList.h"

BOOL EnableDebugPriv(VOID);
void Win32ErrorMessage(void);

void main(int nCountArg, char *lpszArg[], char *lpszEnv[])
{
  NTSTATUS           NtStatus;
  PROCESS_INFO       ProcInfo[1024];
  PPROCESS_INFO      lpProcInfo;
  ULONG              LehgthReturned = 0;
  ULONG              i;
 

  NtStatus = NtGetProcessList(ProcInfo, sizeof(ProcInfo), &LehgthReturned);
  if(NtStatus == STATUS_SUCCESS)
    {
     lpProcInfo = ProcInfo;
     EnableDebugPriv();
     while(1)
       {
        printf("\n------------------------------------------------------\n");
        printf("| ID|         Name| Threads| Parent| Offset|Priority\n");
        printf("------------------------------------------------------\n");
        wprintf(L"%4lX|%13s|%8ld|%7lX|%7ld",
                lpProcInfo->dwProcessID,
                //(lpProcInfo->pszProcessName == 0 ? L"(System Idle)" : lpProcInfo->pszProcessName),
                lpProcInfo->ProcessName.Buffer,
                lpProcInfo->dwThreadCount,
                lpProcInfo->dwParentProcessID,
                lpProcInfo->dwOffset);
        printf("|%4ld\n", lpProcInfo->dwBasePriority);
 
        printf("        -------------- Threads -----------------------\n");
        printf("\t|  ID|Owner|State|Priority|Base Priority\n");

        for(i=0; i<lpProcInfo->dwThreadCount; i++)
           {
            printf("\t|%4lX|%5lX|%5lX|%8X|%8X\n",
                   lpProcInfo->ti[i].dwThreadID,
                   lpProcInfo->ti[i].dwOwningPID,
                   lpProcInfo->ti[i].dwThreadState,
                   lpProcInfo->ti[i].dwCurrentPriority,
                   lpProcInfo->ti[i].dwBasePriority);
           }
        PPROCESS_DEBUG_INFORMATION lpBuf = NtRtlCreateQueryDebugBuffer();
        if(lpBuf)
          {
           DWORD dwRes = NtRtlQueryProcessDebugInformation(lpBuf, lpProcInfo->dwProcessID);
           if(!dwRes)
             {
              printf("\n------------------------------------------------------\n");
              printf("| Modules                                             \n");
              printf("------------------------------------------------------\n");
              for(i=0; i<lpBuf->lpModules->dwModuleCount; i++)
                 {
                  printf("   %s\n", lpBuf->lpModules->ModuleInfo[i].lpszModuleFileName);
                 }
             }
           dwRes = NtRtlDestroyQueryDebugBuffer(lpBuf);
          }
        if(lpProcInfo->dwOffset == 0) break;
        lpProcInfo = (PPROCESS_INFO)((CHAR*)lpProcInfo + lpProcInfo->dwOffset);
        }
    }
  else
     printf("\nError NtQuerySystemInformation !!!");
}

BOOL EnableDebugPriv(VOID)
{
    HANDLE hToken;
    LUID DebugValue;
    TOKEN_PRIVILEGES tkp;
    //
    // Retrieve a handle of the access token
    //
    if (!OpenProcessToken(GetCurrentProcess(),
            TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
            &hToken)) {
        Win32ErrorMessage();
        printf("   OpenProcessToken failed");
        return FALSE;
    }
    //
    // Enable the SE_DEBUG_NAME privilege
    //
    if (!LookupPrivilegeValue((LPSTR) NULL,
            SE_DEBUG_NAME,
            &DebugValue)) {
        Win32ErrorMessage();
        printf("   LookupPrivilegeValue failed");
        return FALSE;
    }

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = DebugValue;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    AdjustTokenPrivileges(hToken,
        FALSE,
        &tkp,
        sizeof(TOKEN_PRIVILEGES),
        (PTOKEN_PRIVILEGES) NULL,
        (PDWORD) NULL);
    //
    // The return value of AdjustTokenPrivileges can't be tested
    //
    if (GetLastError() != ERROR_SUCCESS) {
        Win32ErrorMessage();
        printf("   AdjustTokenPrivileges failed");
        return FALSE;
    }

    return TRUE;
"

void Win32ErrorMessage(void)
{
  LPTSTR MsgBuf;
  char   lpMultiByteStr[1024];

  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                  NULL,
                  GetLastError(),
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                  (LPTSTR) &MsgBuf,
                  0,
                  NULL
                );
  CharToOem(MsgBuf, lpMultiByteStr);
  printf("%s", lpMultiByteStr);
  LocalFree(MsgBuf);
}


///////////////////////////////////////////////////////////////////////

2) Теперь втрой вариант. Более трудный, но более быстрый.
Надо написать свой драйвер, получить через handle указатель на объект(ObReferenceObjectByHandle), далее получить указатель на заголовок объекта(по смещению - 0x18 ниже адреса объекта)
typedef struct _OBJECT_HEADER
        {
/*000*/ DWORD        PointerCount;       // number of references
/*004*/ DWORD        HandleCount;        // number of open handles
/*008*/ POBJECT_TYPE ObjectType;
/*00C*/ BYTE         NameOffset;         // -> OBJECT_NAME
/*00D*/ BYTE         HandleDBOffset;     // -> OBJECT_HANDLE_DB
/*00E*/ BYTE         QuotaChargesOffset; // -> OBJECT_QUOTA_CHARGES
/*00F*/ BYTE         ObjectFlags;        // OB_FLAG_*
/*010*/ union
            { // OB_FLAG_CREATE_INFO ? ObjectCreateInfo : QuotaBlock
/*010*/     PQUOTA_BLOCK        QuotaBlock;
/*010*/     POBJECT_CREATE_INFO ObjectCreateInfo;
/*014*/     };
/*014*/ PSECURITY_DESCRIPTOR SecurityDescriptor;
/*018*/ }
        OBJECT_HEADER,
     * POBJECT_HEADER,
    **PPOBJECT_HEADER;

далее по смещению HandleDBOffset от указателя на объект(по моему от него все отчитывают, но это легко проверить или самому или у Шрайбера почитать ) в сторону уменьшения адресов получить указатель на
typedef struct _OBJECT_HANDLE_DB
        {
/*000*/ union
            {
/*000*/     struct _EPROCESS              *Process;
/*000*/     struct _OBJECT_HANDLE_DB_LIST *HandleDBList;
/*004*/     };
/*004*/ DWORD HandleCount;
/*008*/ }
        OBJECT_HANDLE_DB,
     * POBJECT_HANDLE_DB,
    **PPOBJECT_HANDLE_DB;

в этой структуре если счетчик 1 то в объединение указаетль на процесс владелец, если больше единицы- указатель на
typedef struct _OBJECT_HANDLE_DB_LIST
        {
/*000*/ DWORD            Count;
/*004*/ OBJECT_HANDLE_DB Entries [];
/*Не понял*/ }
        OBJECT_HANDLE_DB_LIST,
     * POBJECT_HANDLE_DB_LIST,
    **PPOBJECT_HANDLE_DB_LIST;

которая содержит массив структур OBJECT_HANDLE_DB с указателями на процессы(вроде так). Утиочнить все это можно в книге C.Шрайбер "Недокументированные возможности Windows 2000"(до сих пор в продаже есть). У меня ее под рукой сейчас нет, могу завтра посмотреть.
« Последнее редактирование: 19-11-2007 19:30 от Алексей1153++ » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines