Cita:
Empezado por felipe88
...es la manera de evitar mover un documento cuando se trabaja en el; yo lo veo como una cuestión de seguridad para los datos... si guardaras algo no te dejaría. La pregunta es, ¿hasta que punto Windows permite mover un archivo, estando en uso? ... no se que piensan de esto...
|
Falso; pongamos un ejemplo practico, wmplayer (Windows Media Player) reproduce una canción; lee de un archivo multimedia y moverlo (en la anterior teoria), ocasionaría fallas inesperadas en el programa... sin embargo el archivo puede ser movido, y no solo eso, puede ser hasta eliminado (lo cual ocurrirá de forma "visible" cuando sea liberado su manejador)
Esto es posible porque se ha utilizado
FILE_SHARE_DELETE al momento de abrir el archivo... que sucede? al ser borrado o eliminado el archivo los datos
siguen allí intactos lo único que cambia son las entradas de ROOT o de MFT en el sistema de archivos.
Cita:
Empezado por dec
...Pero, si la aplicación que abre un archivo (y es lo normal) no lo abre de forma exclusiva, ya digo, puedo estar equivocado, pero, ¿cómo podría averiguarse que el archivo en cuestión está abierto?...
|
He visto el tema más de un par de veces y creo que es de interés...
El S.O. bloquea por alguna razón lógica un archivo, y es necesario forzar el acceso al mismo por cualquier motivo... para ello la mejor herramienta que puedo nombrar de la telaraña es "Unlocker" de Cedrick Collomb.
Por qué es tan eficaz dicha herramienta? sin ánimos de quitar el
encanto y la excelente calidad del trabajo de Collomb, comentaré que dicha herramienta funciona basada en dos APIs (ObReferenceObjectByHandle & ObfDereferenceObject) las cuales a nivel de núcleo (S.O.) desbloquean los archivos a voluntad y de la mejor forma posible.
Lo anteriormente dicho es solo con fines informativos pues no tenemos el permiso del autor para crear una librería basada en su trabajo, pero si podemos apoyarnos en otras APIs que nos facilitaran el trabajo; adjunto un ejemplo que dará la idea de lo que digo:
Código Delphi
[-]program WhoUses;
uses Windows;
function NtQuerySystemInformation(SystemInformationClass: Cardinal; SystemInformation: Pointer; SystemInformationLength: Cardinal; ReturnLength: PCardinal): Cardinal; stdcall external 'ntdll';
function NtQueryInformationFile(FileHandle: Cardinal; IoStatusBlock: PInt64; FileInformation: Pointer; FileInformationLength, FileInformationClass: Cardinal): Cardinal; stdcall external 'ntdll';
function NtQueryObject(ObjectHandle, ObjectInformationClass: Cardinal; ObjectInformation: Pointer; ObjectInformationLength: Cardinal; ReturnLength: PCardinal): Cardinal; stdcall external 'ntdll';
function NtQueryInformationProcess(ProcessHandle, ProcessInformationClass: Cardinal; ProcessInformation: Pointer; ProcessInformationLength: Cardinal; ReturnLength: PCardinal): Cardinal; stdcall external 'ntdll';
function GetProcessImageFileNameW(hProcess: Cardinal; lpImageFileName: PWideChar; nSize: Cardinal): Cardinal; stdcall external 'psapi';
function memcmp(lpBuffer1, lpBuffer2: PWideChar; Size: Cardinal): Integer; cdecl external 'ntdll';
function GetConsoleWindow: Cardinal; stdcall external 'kernel32';
var
Buffer: array [0..1023] of WideChar;
function Thread(Handle: Cardinal): Cardinal; stdcall;
var IoStatusBlock: int64;
begin
Result := NtQueryInformationFile(Handle, @IoStatusBlock, @Buffer, SizeOf(Buffer), 9);
end;
type
TSystemHandleInformation = packed record
uCount: Cardinal;
Handles: array [0..0] of packed record
uIdProcess: Cardinal;
ObjectType,
Flags: Byte;
Handle: Word;
pObject: Pointer;
GrantedAccess: ACCESS_MASK;
end;
end;
var
hToken, Size, Index, hProcess, hObject, hThread, hOutput: Cardinal;
Info: ^TSystemHandleInformation;
Drives: array ['A'..'Z'] of record
cbSize: Cardinal;
Volume: array [0..63] of WideChar;
end;
Drive: array [0..7] of Char = '@'#0':';
begin
if OpenProcessToken($FFFFFFFF, TOKEN_ADJUST_PRIVILEGES, hToken) then
AdjustTokenPrivileges(hToken, False, PTokenPrivileges(PChar(#1#0#0#0#20#0#0#0#0#0#0#0#2#0#0#0))^, 16, nil, PDWORD(0)^);
repeat Inc(Drive[0]);
with Drives[Drive[0]] do
cbSize := QueryDosDeviceW(@Drive, @Volume, SizeOf(Volume)) * 2 - 4;
until Drive[0] = 'Z';
Drive[4] := '\';
Size := SizeOf(TSystemHandleInformation);
Info := Ptr(LocalAlloc(0, Size));
NTQuerySystemInformation(16, Info, Size, @Size);
LocalFree(Cardinal(Info));
Info := Ptr(LocalAlloc(0, Size));
NTQuerySystemInformation(16, Info, Size, nil);
hOutput := 0;
for Index := 0 to Info.uCount - 1 do
with Info.Handles[Index] do
begin
hProcess := OpenProcess(PROCESS_DUP_HANDLE or PROCESS_QUERY_INFORMATION, True, Info.Handles[Index].uIdProcess);
if hProcess = 0 then Continue;
if DuplicateHandle(hProcess, Handle, $FFFFFFFF, @hObject, 0, True, 0) and
(NtQueryObject(hObject, 2, @Buffer, SizeOf(Buffer), nil) = 0) and
(lstrcmpW(@Buffer[48], 'File') = 0) then
begin
hThread := CreateThread(nil, 0, @Thread, Ptr(hObject), 0, PDWORD(0)^);
if WaitForSingleObject(hThread, 666) = 0 then
if (NtQueryObject(hObject, 1, @Buffer, SizeOf(Buffer), nil) = 0) then
begin
Drive[0] := 'A';
while Drive[0] <= 'Z' do
with Drives[Drive[0]] do
if (cbSize <> 0) and (memcmp(@Buffer[4], @Volume, cbSize) = 0) then
Break
else
Inc(Drive[0]);
if Drive[0] > 'Z' then Continue;
if hOutput = 0 then
begin
AllocConsole;
hOutput := GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleScreenBufferSize(hOutput, PCoord(PChar(#120#0#50#0))^);
SetWindowPos(GetConsoleWindow, 0, 0, 0, $FFFF, 666, SWP_NOZORDER or SWP_NOMOVE);
end;
WriteLn(string(PWideChar(@Drive)) + string(PWideChar(@Buffer[5 + (Drives[Drive[0]].cbSize div 2)])));
if GetProcessImageFileNameW(hProcess, @Buffer, SizeOf(Buffer)) <> 0 then
begin
Drive[0] := 'A';
while Drive[0] <= 'Z' do
with Drives[Drive[0]] do
if (cbSize <> 0) and (memcmp(@Buffer, @Volume, cbSize) = 0) then
Break
else
Inc(Drive[0]);
if Drive[0] <= 'Z' then
WriteLn(string(PWideChar(@Drive)) + string(PWideChar(@Buffer[Drives[Drive[0]].cbSize div 2 + 1])));
end;
WriteLn;
end
else
else
begin
TerminateThread(hThread, 0);
CloseHandle(hThread);
end;
end;
CloseHandle(hProcess);
end;
LocalFree(Cardinal(Info));
if hOutput <> 0 then
ReadLn;
end.
La anterior aplicación de consola muestra todos los archivos abiertos y los programas que han abierto a dichos archivos y puede adaptarse para otros fines
.
Es claro que no tiene el “poder” de Unlocker, pero es un precedente para aplicaciones a nivel de usuario que requieran de dichas funcionalidades.
Saludos