|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
[Windows - qualsiasi] Accesso in lettura a files utilizzati da un altro processo
Hola,
è possibile accedere in qualche modo in lettura a dei file lockati con delle API di "alto livello" o bisogna per forza "sporcarsi le mani" con qualche trucchetto un pò + a basso livello? ![]()
__________________
![]() |
![]() |
![]() |
![]() |
#2 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
potrebbe non essere possibile per nulla. questo è il prototipo della CreateFile: http://msdn2.microsoft.com/en-us/library/aa363858.aspx
come vedi dai flag del terzo parametro, è possibile riservarsi un file impedendo agli altri processi anche la lettura. |
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
Ma a livello di accesso a basso livello dei blocchi sul disco non dovrebbe essere possibile farlo? Qualcuno sa da che parte iniziare per implementare qualcosa di simile in .Net? ![]()
__________________
![]() |
|
![]() |
![]() |
![]() |
#4 | |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
![]() o se ti vuoi fidare di quelle ricostruite "ad intuito" dal team di LinuxNTFS... ![]() può darsi che ci siano altre vie prima di arrivare alla lettura manuale dei settori, ma di sicuro non in user-mode; a meno che il file non sia bloccato in lettura (cioè a meno che chi l'ha aperto abbia avuto la magnanimità di specificare FILE_SHARE_READ; tu hai la certezza che non l'abbia fatto?). |
|
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
![]() cmq mi sa che lascio perdere e trovo un'altra soluzione perchè ho intravisto come fare sul blog di uno che ha scritto delle API per il defrag in C# e ha wrappato pure a mia nonna utilizzando chiamate native a kernel32.dll e mi è venuto il mal di testa a leggere quel codice ![]() Se in caso devo per forza unlockare il file me lo studio con calma... Ma per ora è yagni mi sa ![]() ecco il codice che ho trovato giusto per info.... Codice:
// // a set of simple C# wrappers over the NT Defragmenter APIs // // // Refrences // // http://www.sysinternals.com/ntw2k/info/defrag.shtml // // msdn how-to // ms-help://MS.MSDNQTR.2004JUL.1033/fileio/base/defragmenting_files.htm // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/defragmenting_files.asp // // FSCTL_GET_VOLUME_BITMAP // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/fsctl_get_volume_bitmap.asp // // interesting structures... // FSCTL_MOVE_FILE // FSCTL_GET_RETRIEVAL_POINTERS // RETRIEVAL_POINTERS_BUFFER // FSCTL_GET_RETRIEVAL_POINTERS // // DeviceIoControl // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/deviceiocontrol.asp // using System; using System.Diagnostics; using System.Collections; using System.Runtime.InteropServices; namespace defraglib { public class IOWrapper { // // CreateFile constants // const uint FILE_SHARE_READ = 0x00000001; const uint FILE_SHARE_WRITE = 0x00000002; const uint FILE_SHARE_DELETE = 0x00000004; const uint OPEN_EXISTING = 3; const uint GENERIC_READ = (0x80000000); const uint GENERIC_WRITE = (0x40000000); const uint FILE_FLAG_NO_BUFFERING = 0x20000000; const uint FILE_READ_ATTRIBUTES = (0x0080); const uint FILE_WRITE_ATTRIBUTES = 0x0100; const uint ERROR_INSUFFICIENT_BUFFER = 122; [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr CreateFile( string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport("kernel32.dll", SetLastError = true)] static extern int CloseHandle(IntPtr hObject); [DllImport("kernel32.dll", SetLastError = true)] static extern bool DeviceIoControl( IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, [Out] IntPtr lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, IntPtr lpOverlapped); static private IntPtr OpenVolume(string DeviceName) { IntPtr hDevice; hDevice = CreateFile( @"\\.\" + DeviceName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if ((int)hDevice == -1) { throw new Exception(Marshal.GetLastWin32Error().ToString()); } return hDevice; } static private IntPtr OpenFile(string path) { IntPtr hFile; hFile = CreateFile( path, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if ((int)hFile == -1) { throw new Exception(Marshal.GetLastWin32Error().ToString()); } return hFile; } /// <summary> /// Get cluster usage for a device /// </summary> /// <param name="DeviceName">use "c:"</param> /// <returns>a bitarray for each cluster</returns> static public BitArray GetVolumeMap(string DeviceName) { IntPtr pAlloc = IntPtr.Zero; IntPtr hDevice = IntPtr.Zero; try { hDevice = OpenVolume(DeviceName); Int64 i64 = 0; GCHandle handle = GCHandle.Alloc(i64, GCHandleType.Pinned); IntPtr p = handle.AddrOfPinnedObject(); // alloc off more than enough for my machine // 64 megs == 67108864 bytes == 536870912 bits == cluster count // NTFS 4k clusters == 2147483648 k of storage == 2097152 megs == 2048 gig disk storage uint q = 1024 * 1024 * 64; // 1024 bytes == 1k * 1024 == 1 meg * 64 == 64 megs uint size = 0; pAlloc = Marshal.AllocHGlobal((int)q); IntPtr pDest = pAlloc; bool fResult = DeviceIoControl( hDevice, FSConstants.FSCTL_GET_VOLUME_BITMAP, p, (uint)Marshal.SizeOf(i64), pDest, q, ref size, IntPtr.Zero); if (!fResult) { throw new Exception(Marshal.GetLastWin32Error().ToString()); } handle.Free(); /* object returned was... typedef struct { LARGE_INTEGER StartingLcn; LARGE_INTEGER BitmapSize; BYTE Buffer[1]; } VOLUME_BITMAP_BUFFER, *PVOLUME_BITMAP_BUFFER; */ Int64 StartingLcn = (Int64)Marshal.PtrToStructure(pDest, typeof(Int64)); Debug.Assert(StartingLcn == 0); pDest = (IntPtr)((Int64)pDest + 8); Int64 BitmapSize = (Int64)Marshal.PtrToStructure(pDest, typeof(Int64)); Int32 byteSize = (int)(BitmapSize / 8); byteSize++; // round up - even with no remainder IntPtr BitmapBegin = (IntPtr)((Int64)pDest + 8); byte[] byteArr = new byte[byteSize]; Marshal.Copy(BitmapBegin, byteArr, 0, (Int32)byteSize); BitArray retVal = new BitArray(byteArr); retVal.Length = (int)BitmapSize; // truncate to exact cluster count return retVal; } finally { CloseHandle(hDevice); hDevice = IntPtr.Zero; Marshal.FreeHGlobal(pAlloc); pAlloc = IntPtr.Zero; } } /// <summary> /// returns a 2*number of extents array - /// the vcn and the lcn as pairs /// </summary> /// <param name="path">file to get the map for ex: "c:\windows\explorer.exe" </param> /// <returns>An array of [virtual cluster, physical cluster]</returns> static public Array GetFileMap(string path) { IntPtr hFile = IntPtr.Zero; IntPtr pAlloc = IntPtr.Zero; try { hFile = OpenFile(path); Int64 i64 = 0; GCHandle handle = GCHandle.Alloc(i64, GCHandleType.Pinned); IntPtr p = handle.AddrOfPinnedObject(); uint q = 1024 * 1024 * 64; // 1024 bytes == 1k * 1024 == 1 meg * 64 == 64 megs uint size = 0; pAlloc = Marshal.AllocHGlobal((int)q); IntPtr pDest = pAlloc; bool fResult = DeviceIoControl( hFile, FSConstants.FSCTL_GET_RETRIEVAL_POINTERS, p, (uint)Marshal.SizeOf(i64), pDest, q, ref size, IntPtr.Zero); if (!fResult) { throw new Exception(Marshal.GetLastWin32Error().ToString()); } handle.Free(); /* returned back one of... typedef struct RETRIEVAL_POINTERS_BUFFER { DWORD ExtentCount; LARGE_INTEGER StartingVcn; struct { LARGE_INTEGER NextVcn; LARGE_INTEGER Lcn; } Extents[1]; } RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER; */ Int32 ExtentCount = (Int32)Marshal.PtrToStructure(pDest, typeof(Int32)); pDest = (IntPtr)((Int64)pDest + 4); Int64 StartingVcn = (Int64)Marshal.PtrToStructure(pDest, typeof(Int64)); Debug.Assert(StartingVcn == 0); pDest = (IntPtr)((Int64)pDest + 8); // now pDest points at an array of pairs of Int64s. Array retVal = Array.CreateInstance(typeof(Int64), new int[2] { ExtentCount, 2 }); for (int i = 0; i < ExtentCount; i++) { for (int j = 0; j < 2; j++) { Int64 v = (Int64)Marshal.PtrToStructure(pDest, typeof(Int64)); retVal.SetValue(v, new int[2] { i, j }); pDest = (IntPtr)((Int64)pDest + 8); } } return retVal; } finally { CloseHandle(hFile); hFile = IntPtr.Zero; Marshal.FreeHGlobal(pAlloc); pAlloc = IntPtr.Zero; } } /// <summary> /// input structure for use in MoveFile /// </summary> private struct MoveFileData { public IntPtr hFile; public Int64 StartingVCN; public Int64 StartingLCN; public Int32 ClusterCount; } /// <summary> /// move a virtual cluster for a file to a logical cluster on disk, repeat for count clusters /// </summary> /// <param name="deviceName">device to move on"c:"</param> /// <param name="path">file to muck with "c:\windows\explorer.exe"</param> /// <param name="VCN">cluster number in file to move</param> /// <param name="LCN">cluster on disk to move to</param> /// <param name="count">for how many clusters</param> static public void MoveFile(string deviceName, string path, Int64 VCN, Int64 LCN, Int32 count) { IntPtr hVol = IntPtr.Zero; IntPtr hFile = IntPtr.Zero; try { hVol = OpenVolume(deviceName); hFile = OpenFile(path); MoveFileData mfd = new MoveFileData(); mfd.hFile = hFile; mfd.StartingVCN = VCN; mfd.StartingLCN = LCN; mfd.ClusterCount = count; GCHandle handle = GCHandle.Alloc(mfd, GCHandleType.Pinned); IntPtr p = handle.AddrOfPinnedObject(); uint bufSize = (uint)Marshal.SizeOf(mfd); uint size = 0; bool fResult = DeviceIoControl( hVol, FSConstants.FSCTL_MOVE_FILE, p, bufSize, IntPtr.Zero, // no output data from this FSCTL 0, ref size, IntPtr.Zero); handle.Free(); if (!fResult) { throw new Exception(Marshal.GetLastWin32Error().ToString()); } } finally { CloseHandle(hVol); CloseHandle(hFile); } } } /// <summary> /// constants lifted from winioctl.h from platform sdk /// </summary> internal class FSConstants { const uint FILE_DEVICE_FILE_SYSTEM = 0x00000009; const uint METHOD_NEITHER = 3; const uint METHOD_BUFFERED = 0; const uint FILE_ANY_ACCESS = 0; const uint FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS; public static uint FSCTL_GET_VOLUME_BITMAP = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 27, METHOD_NEITHER, FILE_ANY_ACCESS); public static uint FSCTL_GET_RETRIEVAL_POINTERS = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 28, METHOD_NEITHER, FILE_ANY_ACCESS); public static uint FSCTL_MOVE_FILE = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 29, METHOD_BUFFERED, FILE_SPECIAL_ACCESS); static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access) { return ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method); } } }
__________________
![]() |
|
![]() |
![]() |
![]() |
#6 | |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
![]() be' ma scusa in .NET puro, senza wrappare le Win32, non si può già aprire un file in sola lettura? ho poca esperienza purtroppo, ho scritto solo qualche programmetto in C#, ma su MSDN vedo che per esempio la classe FileStream permette di specificare modalità di accesso ed algoritmi di apertura praticamente identici alle loro controparti Win32: http://msdn2.microsoft.com/en-us/lib...ilestream.aspx http://msdn2.microsoft.com/en-us/library/4z36sx0f.aspx http://msdn2.microsoft.com/en-us/lib....filemode.aspx |
|
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
![]() Cmq avevo visto in qualche posto che basterebbe usare un'opzione backup.read o qualcosa del genere nelle API a basso livello per aprire il file... Ma sinceramente wrappare mezzo mondo, usare quest'opzione e accedere a codice non-managed non mi pare proprio bellissimo da fare ![]() Quindi mi sa che utilizzerò la famosa tecnica dello struzzo per risolvere il problema ![]()
__________________
![]() |
|
![]() |
![]() |
![]() |
#8 | |
Senior Member
Iscritto dal: Nov 2001
Città: Bastia Umbra (PG)
Messaggi: 6394
|
Quote:
In entrambi i casi non è comunque immediato, se puoi evita.
__________________
:: Il miglior argomento contro la democrazia è una conversazione di cinque minuti con l'elettore medio :: Ultima modifica di eraser : 19-02-2008 alle 23:34. |
|
![]() |
![]() |
![]() |
#9 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Se puoi lanciare una shell esterna e se ti va di farlo, ho un eseguibile che permette da linea di comando di liberare un file completamente.
Anche quelli caricati in memoria, non solo quelli aperti in lettura/scrittura da altri. Dicono funzioni anche per kernel.exe, volendo puoi cancellarlo. Ovviamente non ho provato, se vuole provare qualcuno poi mi dice se c'e' riuscito...
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#10 | |||
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
Quote:
Quote:
![]() |
|||
![]() |
![]() |
![]() |
#11 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
ehm, asd, ho riletto meglio: il qualcosa che non andava ero io
![]() c'era quel non che mi incasinava un po' ![]() bene bene, oggi posso definitivamente affermare di essere totalmente rincoglionito: per la terza volta in poche ore mi vedo costretto a domandare umilmente scusa per le castronerie che dico su HWU ![]() ribadisco: ho avuto una giornataccia -.-' |
![]() |
![]() |
![]() |
#12 | |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
ci stavo riflettendo... come si potrebbe fare?
![]() servirebbe un file system filter? ho una discreta esperienza con la storage architecture ma quasi niente coi FSD. Quote:
|
|
![]() |
![]() |
![]() |
#13 |
Senior Member
Iscritto dal: Nov 2001
Città: Bastia Umbra (PG)
Messaggi: 6394
|
Si, è necessario un FSD e Windows viene in aiuto (da XP in poi).
Per quanto riguarda un ntfs parser, non è impossibile ma sicuramente non è immediato. È possibile e funzionerebbe ovviamente semplicemente da user mode.
__________________
:: Il miglior argomento contro la democrazia è una conversazione di cinque minuti con l'elettore medio :: |
![]() |
![]() |
![]() |
#14 | |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
lanciare una console esterna non credo sia un problema: al limite basta che nel creare il processo redirige gli standard streams su una pipe, anche se poi non la usa; purché la pipe abbia abbastanza buffer da non far bloccare il programma per un banale output.
Quote:
Ultima modifica di 71104 : 20-02-2008 alle 00:22. |
|
![]() |
![]() |
![]() |
#15 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
|
![]() |
![]() |
![]() |
#16 |
Senior Member
Iscritto dal: Nov 2001
Città: Bastia Umbra (PG)
Messaggi: 6394
|
Da XP in poi sono presenti delle API native che permettono di ignorare gli share-access checks (poi migliorate in Vista).
__________________
:: Il miglior argomento contro la democrazia è una conversazione di cinque minuti con l'elettore medio :: |
![]() |
![]() |
![]() |
#17 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
API native, cioè quelle che iniziano con Zw ma anche Nt? da quanto mi risulta quelle si possono usare anche in user-mode, quindi costituirebbero la soluzione per TigerShark. sono documentate?
|
![]() |
![]() |
![]() |
#18 |
Senior Member
Iscritto dal: Nov 2001
Città: Bastia Umbra (PG)
Messaggi: 6394
|
No, sono API esportate dal kernel (Io*) utilizzabili esclusivamente lato kernel mode, in un FSD.
__________________
:: Il miglior argomento contro la democrazia è una conversazione di cinque minuti con l'elettore medio :: |
![]() |
![]() |
![]() |
#19 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
![]()
__________________
![]() |
|
![]() |
![]() |
![]() |
#20 | ||
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
Quote:
Ma sinceramente il rapporto costi/benefici di andare ad implementare tutto questo bel casino (e soprattutto il testarlo) non è a suo favore, quindi per ora ho deciso semplicemente di ignorare il problema... In caso + avanti mi rendo conto che è assolutamente necessario allora torno a sbatterci al testa.. grazie a tutti per l'aiuto cmq ![]()
__________________
![]() |
||
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 12:13.