Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как определить что файл заблокирован LockFile 
:(
    Опции темы
denism
Дата 16.4.2006, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 16.4.2006

Репутация: нет
Всего: нет



Кто с этим имел дело или примерно представляете куда
копать  - подскажите?

Суть следующая: 
файл находится на NT-образном сервере, открыт все время для 
чтения клиентами с разных рабочих станций (win9x, NT-образные),
перед чтением клиенты лочат нужный блок файла ф-цией LoсkFile,
после чтения - разлочивают. Бывают ситуации когда разлочивания
не происходит, в рез-те серверное приложение не может получить
доступ ко всему файлу. Что нужно делать чтобы узнать что файл 
открыт и держится другим процессом и как его отцепить - 
я представляю (начинать с юзания ф-ций NTQuery...).

Вопрос: как узнать что файл залочен ф-цией LockFile и как его
насильно разлочить?

P.S. Сам факт залочивания Computer Management  отображает в
\System Tools\Open Files\ колонка "Locks".

 
PM MAIL   Вверх
_hunter
Дата 17.4.2006, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 9
Всего: 98



а если UnlockFile вызвать? 


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
denism
Дата 17.4.2006, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 16.4.2006

Репутация: нет
Всего: нет



Клиент, который залочил файл - не может этого
сделать, т.к. висит.
На серверном приложении это эффекта на даст,
т.к. оно не может при помощи этой ф-ции
снять чужую блокировку.

Возможно я не корректно сформулировал вопрос, перефразирую:
То что файл залочен кем-то видно по коду возврата из ф-ции LockFile,
как узнать какой процесс его залочил? 
PM MAIL   Вверх
Snowy
Дата 17.4.2006, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 30
Всего: 484



А зачем вообще лочить файл для чтения?
Лочить нужно только для записи.
А читать можно спокойно всем вместе. Главное на чтение открывать с флагом ShareDenyNone. 
PM MAIL   Вверх
denism
Дата 18.4.2006, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 16.4.2006

Репутация: нет
Всего: нет



Потому что клиенты под 98-й. когда читают без блокировки 
в определенных ситуациях вместо того чтобы ждать когда блокировка 
по записи снимется возвращают блоки данных забитые нулями.
И не узнать действительно ли эта область файла была забита
нулями или нет. 
PM MAIL   Вверх
Nickel
Дата 18.4.2006, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 77
Регистрация: 7.2.2006

Репутация: 2
Всего: 4



Блокировка точно при помощи LockFile? Если да, то щас подумаю что можно сделать... 
PM   Вверх
Nickel
Дата 18.4.2006, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 77
Регистрация: 7.2.2006

Репутация: 2
Всего: 4



Придумал:
Код

type
PSYSTEM_HANDLE_INFORMATION = ^SYSTEM_HANDLE_INFORMATION;
SYSTEM_HANDLE_INFORMATION = packed record
   ProcessId: dword;
   ObjectTypeNumber: byte;
   Flags: byte;
   Handle: word;
   pObject: pointer;
   GrantedAccess: dword;
end;

PSYSTEM_HANDLE_INFORMATION_EX = ^SYSTEM_HANDLE_INFORMATION_EX;
SYSTEM_HANDLE_INFORMATION_EX = packed record
   NumberOfHandles: dword;
   Information: array [0..0] of SYSTEM_HANDLE_INFORMATION;
end;

PUnicodeString = ^TUnicodeString;
  TUnicodeString = packed record
    Length: Word;
    MaximumLength: Word;
    Buffer: PWideChar;
end;

const OB_TYPE_FILE             =  28;
      SystemHandleInformation  =    16;

function ZwQueryObject(ObjectHandle: THandle;
  ObjectInformationClass: integer; ObjectInformation:Pointer;
  Length: ULONG; ReturnLength: PULONG): cardinal; stdcall;
  external 'ntdll.dll';

Function ZwQuerySystemInformation(ASystemInformationClass: dword;
                                  ASystemInformation: Pointer;
                                  ASystemInformationLength: dword;
                                  AReturnLength:PCardinal): cardinal;
                                  stdcall;external 'ntdll.dll';


Function GetInfoTable(ATableType:dword):Pointer;
var
 mSize: dword;
 mPtr: pointer;
 St: cardinal;
begin
 Result := nil;
 mSize := $4000;
 repeat
   mPtr := VirtualAlloc(nil, mSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
   if mPtr = nil then Exit;
   St := ZwQuerySystemInformation(ATableType, mPtr, mSize, nil);
   if St = cardinal($C0000004) then
      begin
        VirtualFree(mPtr, 0, MEM_RELEASE);
        mSize := mSize * 2;
      end;
 until St <> cardinal($C0000004);
 if St = 0
   then Result := mPtr
   else VirtualFree(mPtr, 0, MEM_RELEASE);
end;


function Unlock(FileName:string):boolean;
var inf:PSYSTEM_HANDLE_INFORMATION_EX;
    i:integer;
    process,h:cardinal;
    p:pointer;
    buf:array[0..max_path] of char;
    s:string;
begin
result:=false;
p:=GetMemory(max_path);
ZeroMemory(p,max_path);
QueryDosDevice(PChar(ExtractFileDrive('c:\1.txt')),@buf,SizeOf(buf));
s:=FileName;
Delete(s,1,2);
s:=buf+s;
inf:=GetInfoTable(SystemHandleInformation);
for i:=0 to inf.NumberOfHandles-1 do begin
if inf.Information[i].ObjectTypeNumber=OB_TYPE_FILE then begin
process:=OpenProcess(PROCESS_DUP_HANDLE,false,inf.Information[i].ProcessId);
DuplicateHandle(process,inf.Information[i].Handle,getcurrentprocess,
                                  @h,0,false,DUPLICATE_SAME_ACCESS);
ZwQueryObject(h,1,p,max_path,nil);
if s=WideCharToString(TUnicodeString(p^).Buffer) then
  begin
   CloseHandle(h);
   if DuplicateHandle(process,inf.Information[i].Handle,GetCurrentProcess,
                    @h,0,false,DUPLICATE_CLOSE_SOURCE) then result:=true;
  end;
ZeroMemory(p,max_path);
CloseHandle(h);
CloseHandle(process);
end;
end;
end;

Вроде неплохо получилось - надо будет оформить ввиде статейки... Видимо таким же образом действует програмка Unlocker. Код конечно не супер, надо кое-где проверку на ошибки добавить, да и процесс у которого мы закрыли хендл может потом себя не корректно повести. 
ЗЫ извините за второе наподряд сообщение... 

Это сообщение отредактировал(а) Nickel - 18.4.2006, 18:58
PM   Вверх
denism
Дата 19.4.2006, 02:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 16.4.2006

Репутация: нет
Всего: нет



Спасибо, завтра потестирую код (сегодня - на рыбалку еду).
Программа Unlocker, действительно хорошая программа,
она закрывает файлы, открытые сетевыми клиентами,
другие программы, которые я нашел в Инете с исходным кодом - этого не 
могли делать, т.к. работали через CreateRemoteHandle,
и вызывать эту ф-цию в данном случае приходилось для процесса
System, что, как я понимаю запрещено. 
PM MAIL   Вверх
denism
Дата 21.4.2006, 05:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 16.4.2006

Репутация: нет
Всего: нет



Спасибо, работает, только на некоторых процессах на некоторых файлах 
программа зависает в ф-ции QueryObject.
Видимо нужно поразбираться с правами доступа в поле GrantedAccess. 
PM MAIL   Вверх
denism
Дата 26.4.2006, 14:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 16.4.2006

Репутация: нет
Всего: нет



С зависаниями разобрался, GrantedAccess не при чем, зависает на pipe, которые 
открыты в блокирующем режиме и находятся в ждущем режиме.
Но вопрос так и остался открытым, прямого отношения к блокировкам через ф-цию LockFile
приведенный код отношения не имеет. С файлами, открытыми и заблокированными локальными
процессами - все ОК, а вот с файлами открытыми клиентами по сети - блокировка остается, 
хотя хэндл, принадлежащий процессу System (т.к. по сети), закрывается. Следовательно
по прежнему не можем его нормально читать.

И еще интересный момент: ф-ция CopyFile благополучно копирует залоченный
файл со всем его содержимым, чихая на блокировку части данных. 
Может кто знает как она это делает? 
PM MAIL   Вверх
Nickel
Дата 28.4.2006, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 77
Регистрация: 7.2.2006

Репутация: 2
Всего: 4



Цитата(denism @ 26.4.2006,  14:56)
Но вопрос так и остался открытым, прямого отношения к блокировкам через ф-цию LockFile приведенный код отношения не имеет.

Очень даже имеет: мы закрываем хендл файла, который залочен, (надо сказать довольно необычным способом через DuplicateHandle)  и блокировка пропадает вмсете с хендлом. Кстати ты под какой виндой пробуешь? У меня на XP sp2 system не открывается с PROCESS_DUP_HANDLE а когда беру привелегии отладчика ловлю нехилый подвисон моей проги. Мб всё-таки проблема что хендл не закрывается?
Цитата(denism @ 26.4.2006,  14:56)
И еще интересный момент: ф-ция CopyFile благополучно копирует залоченный файл со всем его содержимым, чихая на блокировку части данных. 
Может кто знает как она это делает? 
 
LockFile блокирует часть файла только на запись. 
PM   Вверх
denism
Дата 2.5.2006, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 16.4.2006

Репутация: нет
Всего: нет



У меня система WinXP SP2, system открывается с PROCESS_DUP_HANDLE 
с привилегиями отладчика, никаких зависаний с этим нет.
Хэндл у залоченного файла успешно закрывается, 
это показывает и прога Unlocker, и монитор 
procexplorers от Sysinternals, но когда серверное приложение 
пытается залочить файл для записи возвращается ошибка о том
что другой процесс залочил файл. Даже в фаре нажимаем F3,
чтобы поглядеть содержимое файла - он показывает пустое окно.

И еще - ф-ция NTQueryObject при попытке получения имени файла
взвисает на pipe'ах так что даже если ее поместить в поток, то поток
потом не убивается, вследствие чего не убивается процесс ничем,
кроме перезагрузки системы. Ф-ция же NTQueryInformationFile,
взвисает на pipe'ах не так смертельно, поток можно убить, но 
имя файла она возвращает без имени диска...  А то что я юзаю
ф-ции NT... вместо Zw... может иметь какое-то значение? 
PM MAIL   Вверх
Rouse_
Дата 29.5.2006, 21:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 469
Регистрация: 23.4.2005

Репутация: 18
Всего: 29



Цитата(denism @  2.5.2006,  13:37 Найти цитируемый пост)
 еще - ф-ция NTQueryObject при попытке получения имени файла
взвисает на pipe'ах так что даже если ее поместить в поток, то поток
потом не убивается, вследствие чего не убивается процесс ничем,
кроме перезагрузки системы

Пайп, это объект ядра и он не принадлежит процессу. Зависание происзходит на синхронных Трубах, которые, имея приоритет выше, чем твое приложение, отпустят поток только после завершения своей операции... 


--------------------
 Vae Victis
(Горе побежденным (лат.))
Демо с открытым кодом: http://rouse.drkb.ru 
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0811 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.