Текущий архив: 2005.08.21;
Скачать: CL | DM;
Вниз
Расположение заблокированного файла на диске. Найти похожие ветки
← →
Семен Сорокин © (2005-06-22 18:06) [0]Приветствую гуру, кто может подсказать как получить покластерное расположение заблокированного файла на диске, например pagefile.sys (NT4, W2k, XP). Не блокированные файлы просмотриваю с помощью ф-ии DeviceIoControl с управляющим кодом FSCTL_GET_RETRIEVAL_POINTERS, но дело в том что там входным параметром используется Handle открытого файла, а если он заблокирован, то этот Handle не удасться получить.
С уважением, Семен.
← →
Игорь Шевченко © (2005-06-22 18:22) [1]
> Приветствую гуру, кто может подсказать как получить покластерное
> расположение заблокированного файла на диске, например pagefile.sys
Среди API дефрагментации ничего нету ?
← →
Семен Сорокин © (2005-06-22 18:28) [2]3 функции:
FSCTL_GET_RETRIEVAL_POINTERS Get information about a file"s cluster use.
FSCTL_GET_VOLUME_BITMAP Get a bitmap of cluster allocation.
FSCTL_MOVE_FILE Move all or part of a file from one set of clusters to another within a volume.
FSCTL_GET_VOLUME_BITMAP - возвращает карту диска по занятым/незанятым кластерам без конкретики по файлам...
FSCTL_GET_RETRIEVAL_POINTERS - именно эту я использую для получения информации по отдельному открытому(!) файлу.
FSCTL_MOVE_FILE - непосредственно для дефрагментации...
PS. ведь O&O Defrag как-то показывает расположение того же свопа на диске... наверняка есть какие нибудь функции, а я не знаю куда копать
PPS. можно конечно попробовать вычислить из общей карты диска - вычитанием имеющихся расположений файлов, но, имхо, не то...
← →
Игорь Шевченко © (2005-06-22 18:32) [3]А открыть файл с FILE_SHARE_READ + FILE_SHARE_WRITE не помогает ?
← →
Семен Сорокин © (2005-06-22 18:39) [4]
> Игорь Шевченко © (22.06.05 18:32) [3]
> А открыть файл с FILE_SHARE_READ + FILE_SHARE_WRITE не помогает
> ?
неа, я уже перепробовал все возможные флаги :)
результат один и тот-же:
32 The process cannot access the file because it is being used by another process. ERROR_SHARING_VIOLATION
я уже даже пробовал открывть его из сервиса с SYSTEM-правами - та же песня.
← →
Игорь Шевченко © (2005-06-22 18:49) [5]Семен Сорокин © (22.06.05 18:39) [4]
Defrag имени Руссиновича тоже не показывает :)
Можно, конечно, и структуры NTFS читать, у Свена Шрайбера пример есть, но уж больно муторно.
← →
Семен Сорокин © (2005-06-22 18:57) [6]ага, а ведь есть же что-то :) по поводу структуры NTFS - это да (через FSCTL_GET_NTFS_FILE_RECORD если я не ошибаюсь), а что делать если FAT32... необходимо нечто универсальное.
PS. Спасибо за помощь.
← →
Игорь Шевченко © (2005-06-22 23:32) [7]Семен Сорокин © (22.06.05 18:57) [6]
Кстати, я ошибся в посте [5] - не у Свена Шрайбера, а у Гэри Неббета есть описание структур NTFS и пример непосредственной работы с ними. Только он честно предупреждает, что граблей на этом пути раскидано немеряно.
← →
MS-MEN © (2005-06-23 07:09) [8]unit PSL_DirectFile;
{***********************************************************
Чтение из файла / запись в файл
через прямое обращение к диску
Нужны права администратора
p0s0l, 2004
***********************************************************}
interface
function DF_Read (const FileName : string; Offset, Size : Cardinal; Buf : Pointer) : Boolean;
function DF_Write (const FileName : string; Offset, Size : Cardinal; Buf : Pointer) : Boolean;
function DF_GetFileSize (const FileName : string) : Int64;
implementation
uses Windows;
////////////////////////////////////////////////////////////////////////////////
const
FILE_READ_DATA = $0001;
FILE_WRITE_DATA = $0002;
FILE_READ_ATTRIBUTES = $0080;
FSCTL_GET_RETRIEVAL_POINTERS = $90073;
type
PSTARTING_VCN_INPUT_BUFFER = ^STARTING_VCN_INPUT_BUFFER;
STARTING_VCN_INPUT_BUFFER = record
StartingVcn: Int64;
end;
TRPBExtends = record
NextVcn: Int64;
Lcn: Int64;
end;
PRETRIEVAL_POINTERS_BUFFER = ^RETRIEVAL_POINTERS_BUFFER;
RETRIEVAL_POINTERS_BUFFER = record
ExtentCount: DWORD;
StartingVcn: Int64;
Extends: array [0..0] of TRPBExtends;
end;
type
TClusterList = array of Int64;
////////////////////////////////////////////////////////////////////////////////
type
PFAT32BootSector = ^TFat32BootSector;
TFAT32BootSector = packed record
Jmp : array [0..2] of byte;
Name : array [0..7] of char;
// BPB
SectSiz : word; // (в байтах)
ClustSiz : byte; // (в секторах)
ResSecs : word; // кол-во зарезерв. секторов перед первым FAT"ом
FatCnt : byte; // кол-во FAT"ов
RootSiz : word; // (в 32-байтовых записях)
TotSecs : word;
Media : byte;
FatSize : word; // размер одного FAT (в секторах)
TrkSecs : word; // секторов в дорожке
HeadCnt : word; // головок (поверхностей)
HidnSec : dword;
TotSecs32 : dword;
// FAT32
FatSize32 : dword;
Flags : word;
Version : word;
RootClust : dword;
FSInfo : word;
BUInfo : word;
Reserved : array [0..11] of byte;
//
Drive : byte;
Reserved2 : byte;
BootSign : byte;
Serial : dword;
VolLabel : array [0..10] of char;
FileSys : array [0..7] of char;
end;
////////////////////////////////////////////////////////////////////////////////
function DF_GetDrive (const FileName : string) : string;
begin
Result := FileName[1]+FileName[2];
end;
////////////////////////////////////////////////////////////////////////////////
function DF_GetClusterSize (const Drive : string) : Cardinal;
var
SectorSize, ClusterSize, Tmp : DWORD;
begin
Result := 0;
if GetDiskFreeSpace (PChar(DF_GetDrive(Drive)+"\"), SectorSize, ClusterSize, Tmp, Tmp) then
Result := SectorSize * ClusterSize;
end;
////////////////////////////////////////////////////////////////////////////////
function DF_GetFileSize (const FileName : string) : Int64;
var
hFile : THandle;
Tmp : DWORD;
begin
Result := -1;
hFile := CreateFile (PChar(FileName),
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if hFile = INVALID_HANDLE_VALUE then Exit;
Result := GetFileSize (hFile, @Tmp);
Result := Result or (Int64(Tmp) shl 32);
CloseHandle (hFile);
end;
////////////////////////////////////////////////////////////////////////////////
function DF_GetFileClusters (const FileName : string; var Clusters : TClusterList) : boolean;
var
hFile : THandle;
FileSize, PrevVCN, Lcn : Int64;
InputBuffer : STARTING_VCN_INPUT_BUFFER;
OutputBuffer : PRETRIEVAL_POINTERS_BUFFER;
ClusterSize, BufferSize, Tmp : Cardinal;
i, Cl : integer;
begin
Result := False;
SetLength (Clusters, 0);
hFile := CreateFile (PChar(FileName),
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if hFile = INVALID_HANDLE_VALUE then Exit;
FileSize := DF_GetFileSize (FileName);
ClusterSize := DF_GetClusterSize (FileName);
BufferSize := SizeOf(OutputBuffer^) + (FileSize div ClusterSize) * SizeOf(TRPBExtends);
GetMem (OutputBuffer, BufferSize);
InputBuffer.StartingVcn := 0;
if DeviceIoControl (hFile, FSCTL_GET_RETRIEVAL_POINTERS,
@InputBuffer, SizeOf(InputBuffer),
OutputBuffer, BufferSize, Tmp,
nil) then
begin
// По смыслу Tmp := (FileSize + (ClusterSize-1)) div ClusterSize;
// но мало ли ?... :)
Tmp := 0;
PrevVCN := OutputBuffer.StartingVcn;
for i := 0 to OutputBuffer.ExtentCount-1 do
begin
Inc (Tmp, OutputBuffer.Extends[i].NextVcn - PrevVCN);
PrevVCN := OutputBuffer.Extends[i].NextVcn;
end;
SetLength (Clusters, Tmp);
PrevVCN := OutputBuffer.StartingVcn;
Cl := 0;
for i := 0 to OutputBuffer.ExtentCount-1 do
begin
Tmp := OutputBuffer.Extends[i].NextVcn-PrevVCN;
Lcn := OutputBuffer.Extends[i].Lcn;
while Tmp > 0 do
begin
Clusters[Cl] := Lcn;
Inc (Cl);
Inc (Lcn);
Dec (Tmp);
end;
PrevVCN := OutputBuffer.Extends[i].NextVcn;
end;
Result := True;
end;
FreeMem (OutputBuffer);
CloseHandle (hFile);
end;
← →
MS-MEN © (2005-06-23 07:09) [9]function DF_Access (const FileName : string; FileOffset : Int64; Size : Cardinal; Buf : Pointer; IsRead : Boolean) : Boolean;
var
ClusterSize, Offset, BlockSize : Cardinal;
Clusters : TClusterList;
hDrive : THandle;
ClusterNo, AbsOffset, FileSize, Cluster0Offset : Int64;
AccessRights, FileFlags, Tmp : DWORD;
ClusterBuf : Pointer;
FileSystem : array [0..255] of Char;
BootSector : PFAT32BootSector absolute ClusterBuf;
begin
Result := False;
if (FileOffset < 0) or (Size <= 0) then Exit;
//------------------------------------------------------------------------------
// Получение размера кластера
ClusterSize := DF_GetClusterSize (FileName);
if ClusterSize = 0 then Exit;
//------------------------------------------------------------------------------
// Получение списка кластеров, занимаемых файлом
Result := DF_GetFileClusters (FileName, Clusters);
if not Result then Exit;
//------------------------------------------------------------------------------
// Открытие устройства для операции чтения/записи
AccessRights := FILE_READ_DATA;
if not IsRead then AccessRights := AccessRights or FILE_WRITE_DATA;
FileFlags := FILE_FLAG_RANDOM_ACCESS;
if not IsRead then FileFlags := FileFlags or FILE_FLAG_WRITE_THROUGH;
// FileFlags := FileFlags or FILE_FLAG_NO_BUFFERING;
hDrive := CreateFile (PChar("\\.\" + DF_GetDrive(FileName)),
AccessRights,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
nil,
OPEN_EXISTING,
FileFlags,
0);
if hDrive = INVALID_HANDLE_VALUE then Exit;
//------------------------------------------------------------------------------
// Получение инфы о диске, в частности - файловая система
if not GetVolumeInformation (PChar(DF_GetDrive(FileName) + "\"),
nil,
0,
nil,
Tmp,
Tmp,
@FileSystem[0],
SizeOf(FileSystem)) then Exit;
// VirtualAlloc хорош тем, что буфер выровнен по странице памяти
ClusterBuf := VirtualAlloc (nil, ClusterSize, MEM_COMMIT, PAGE_READWRITE);
//------------------------------------------------------------------------------
// Вычисление смещения нулевого кластера относительно начала раздела
// На NTFS"ах нулевой кластер начинается с 0 сектора раздела...
// А на FAT"ах - после таблиц размещения файлов...
Cluster0Offset := 0;
if Copy(FileSystem, 1, 3) = "FAT" then
begin
// чтение bootsector"а (0 сектор)
SetFilePointer (hDrive, 0, nil, FILE_BEGIN);
ReadFile (hDrive, ClusterBuf^, 512, Tmp, nil);
with BootSector^ do
// FAT32 (тестил)
if FileSystem[3] = "3" then Cluster0Offset := ResSecs + (FatCnt * FatSize32)
// FAT16 (не тестил) - юзать на свой риск и страх!!!
else Cluster0Offset := ResSecs + (FatCnt * FatSize);
Cluster0Offset := Cluster0Offset * BootSector.SectSiz;
end;
//------------------------------------------------------------------------------
// Мало ли прочитать хотят больше, чем есть в файле ?
FileSize := DF_GetFileSize (FileName);
Dec (FileSize, FileOffset);
if FileSize < Size then Size := FileSize;
//------------------------------------------------------------------------------
// Собственно чтение/запись
repeat
// № кластера
ClusterNo := FileOffset div ClusterSize;
if ClusterNo >= Length(Clusters) then Break;
ClusterNo := Clusters[ClusterNo];
// смещение в байтах относительно начала диска
AbsOffset := ClusterSize * ClusterNo + Cluster0Offset;
// смещение начала данных внутри кластера
Offset := FileOffset mod ClusterSize;
// вычисление размера данных, подлежащих чтению/записи
BlockSize := ClusterSize;
if BlockSize > Size then BlockSize := Size;
if BlockSize > (ClusterSize-Offset) then BlockSize := (ClusterSize-Offset);
// переход на нужный кластер
SetFilePointer (hDrive, AbsOffset, Pointer(Integer(@AbsOffset)+4), FILE_BEGIN);
// чтение кластера в буфер происходит еще и в случае,
// если нужно записать кластер не полностью
if IsRead or (BlockSize <> ClusterSize) then
begin
ReadFile (hDrive, ClusterBuf^, ClusterSize, Tmp, nil);
if IsRead then Move (Pointer(Cardinal(ClusterBuf)+Offset)^, Buf^, BlockSize);
// полчаса возился с записью! :)
// и всё из-за того, что забыл возвращать указатель...
if not IsRead then SetFilePointer (hDrive, AbsOffset, Pointer(Integer(@AbsOffset)+4), FILE_BEGIN);
end;
// запись кластера
if not IsRead then
begin
Move (Buf^, Pointer(Cardinal(ClusterBuf)+Offset)^, BlockSize);
WriteFile (hDrive, ClusterBuf^, ClusterSize, Tmp, nil);
end;
// продолжение работы...
Inc (FileOffset, BlockSize);
Dec (Size, BlockSize);
Inc (Cardinal(Buf), BlockSize);
until Size <= 0;
// на всякий случай, хотя не помогает...
if not IsRead then FlushFileBuffers (hDrive);
VirtualFree (ClusterBuf, 0, MEM_RELEASE);
CloseHandle (hDrive);
Result := (Size = 0); // всё прочитано/записано ?
end;
////////////////////////////////////////////////////////////////////////////////
function DF_Read (const FileName : string; Offset, Size : Cardinal; Buf : Pointer) : Boolean;
begin
Result := DF_Access (FileName, Offset, Size, Buf, True);
end;
function DF_Write (const FileName : string; Offset, Size : Cardinal; Buf : Pointer) : Boolean;
begin
Result := DF_Access (FileName, Offset, Size, Buf, False);
end;
////////////////////////////////////////////////////////////////////////////////
end.
← →
Семен Сорокин © (2005-06-23 10:13) [10]>MS-MEN ©
Благодарю за проявленный интерес к ветке, но проблему этот код не разрешает, дело в том что в функции DF_GetFileClusters используется все тот-же незамысловатый CreateFile, который на заблокированный файл типа pagefile.sys вернет INVALID_HANDLE_VALUE и функция не сработает. :(
Еще раз спасибо за код, почерпнул пару моментов.
← →
MS-MEN © (2005-06-23 10:18) [11]> Семен Сорокин
Обращайся к нему физ.
← →
Семен Сорокин © (2005-06-23 10:20) [12]
> MS-MEN © (23.06.05 10:18) [11]
>
> Обращайся к нему физ.
Как? какие функции использовать? или в какую сторону хотя бы копать в MSDN?
← →
Kerk © (2005-06-23 10:22) [13]Семен Сорокин © (23.06.05 10:20) [12]
или в какую сторону хотя бы копать в MSDN?
все тот же CreateFile/ReadFile
если номера кластеров есть, то проблем быть не должно.
← →
MS-MEN © (2005-06-23 10:28) [14]Семен Сорокин © (23.06.05 10:20) [12]
Как? какие функции использовать? или в какую сторону хотя бы копать в MSDN?
Сегодня на мыло мне MS-MEN@yandex.ru просто сейчас лень копатся.
Я тебе скину свой модуль IODISK.PAS через него ты не только
можешь копатся в файлах но и даже Scandisk можешь сделать )
← →
Kerk © (2005-06-23 10:30) [15]
function ReadSectorsNT(DriveNumber: Byte; StartingSector, SectorCount: DWORD;
Buffer: Pointer): DWORD;
var
hFile: THandle;
br,TmpLo,TmpHi: DWORD;
begin
Result := 0;
hFile := CreateFile(PChar("\\.\PhysicalDrive"+IntToStr(DriveNumber)),
GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if hFile = INVALID_HANDLE_VALUE then Exit;
TmpLo := __Mul(StartingSector,
PhysicalDrives[DriveNumber].DiskGeometry.BytesPerSector,TmpHi);
if SetFilePointer(hFile,TmpLo,@TmpHi,FILE_BEGIN) = TmpLo then
begin
SectorCount := SectorCount*PhysicalDrives[DriveNumber].DiskGeometry.BytesPerSector;
if not ReadFile(hFile,Buffer^,SectorCount,br,nil) then Exit;
Result := br;
end;
CloseHandle(hFile);
end;
из http://kladovka.net.ru/index.cgi?pid=list&rid=9
← →
Семен Сорокин © (2005-06-23 10:38) [16]>Kerk
спасибо, только это немного не то: у меня есть имя файла "f:\pagefile.sys", покластерного распложения нет (!), файл заблокирован системой, Файловая система FAT32
>MS-MEN
ок, отправил мылом
← →
Игорь Шевченко © (2005-06-23 19:28) [17]Семен Сорокин © (23.06.05 10:38) [16]
> файл заблокирован системой, Файловая система FAT32
Для fat32 тебе не обязательно открывать файл. Открой диск, прочитай корневой каталог, найди там цепочки для pagefile.sys и будет тебе счастье. Правда, счастье будет неполным, если размер файла автоматически устанавливается системой, так как реальные кластеры, отведенные под него, в данный конкретный момент находятся в кэше.
А кстати, вопрос такой - нафига тебе надо покластерное расположение pagefile.sys ?
← →
Семен Сорокин © (2005-06-24 12:33) [18]
> А кстати, вопрос такой - нафига тебе надо покластерное расположение
> pagefile.sys ?
Мне нужно нарисовать карту диска, и разукрасить ее различными цветами (по типу O&O Defrag: фрагментированные/дефрагментированные/сжаты/системные/... файлы) с основной задачей справился, за одним исключением (сабж)...
Тут в голову пришла другая идея для получения Locked file handle:
- Перебирать все процессы (искать заблокировавший данный файл
процесс (для Pagefile.sys - system))
- Перебирать все handle этого процесса
- находить handle имя которого pagefile
- делаеть DuplicateHandle
интересует мнение, реализуем ли такой алгоритм? и с какими трудностями я могу сттолкнуться? :)
← →
BiN © (2005-06-24 12:42) [19]Семен Сорокин © (24.06.05 12:33) [18]
Алгоритм-то реализуем, но стоит ли овчинка?
← →
Игорь Шевченко © (2005-06-24 12:52) [20]
> интересует мнение, реализуем ли такой алгоритм?
Реализуем. Только вот при дублировании файловых хэндлов ты можешь повиснуть. Это проблема широко известна.
← →
Семен Сорокин © (2005-06-24 13:05) [21]
> BiN © (24.06.05 12:42) [19]
> Алгоритм-то реализуем, но стоит ли овчинка?
Можешь предложить иной выход? :))
> Игорь Шевченко © (24.06.05 12:52) [20]
> Реализуем. Только вот при дублировании файловых хэндлов
> ты можешь повиснуть. Это проблема широко известна.
хм. даже если дублировать с минимальными правами: FILE_SHARE_READ + FILE_SHARE_WRITE?
а можно поподробней? где про эти проблемы можно почитать?
← →
Игорь Шевченко © (2005-06-24 13:15) [22]Семен Сорокин © (24.06.05 13:05) [21]
> где про эти проблемы можно почитать?
Гэри Неббет, справочник по функциям базового API Windows 2000/NT
← →
BiN © (2005-06-24 13:35) [23]Семен Сорокин © (24.06.05 13:05) [21]
Можешь предложить иной выход? :))
Внедрение?
Не очень красивый метод, но зато можно обойтись без DuplicateHandle.
← →
BiN © (2005-06-24 14:14) [24]Игорь Шевченко © (24.06.05 12:52) [20]
Только вот при дублировании файловых хэндлов ты можешь повиснуть.
Почему-то при работе с файлами FS (не с пайпами) добиться зависания не удалось. Что я делаю не так?
← →
Игорь Шевченко © (2005-06-24 14:19) [25]BiN © (24.06.05 14:14) [24]
> Что я делаю не так?
Знаешь заранее, что это не pipe.
← →
NikNet © (2005-06-24 20:32) [26]Удалено модератором
Страницы: 1 вся ветка
Текущий архив: 2005.08.21;
Скачать: CL | DM;
Память: 0.56 MB
Время: 0.035 c