Greetings Monks,

Im working on getting where files exists physicaly (raw) on disk (sector). But Im having some trouble getting the Windows things to work in Perl... I thought this would be easy, following PodMaster's nicely Win32::ReadDirectoryChanges module, but apparently not. However, this may be some windows specific thing, that I need to know to make it work. Im using Win32::API and have the following code:
# #!/usr/bin/env perl use Win32::API; use Win32API::File qw /:Func :IOCTL_DISK_/; use Data::Dumper; use strict; use warnings; #use diagnostics; # HANDLE CreateFile( # LPCTSTR lpFileName, # DWORD dwDesiredAccess, # DWORD dwShareMode, # LPSECURITY_ATTRIBUTES lpSecurityAttributes, # DWORD dwCreationDisposition, # DWORD dwFlagsAndAttributes, # HANDLE hTemplateFile # ); # BOOL DeviceIoControl( # (HANDLE) hDevice, // handle to volume # IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, // dwIoControlCode # (LPVOID) lpInBuffer, // input buffer # (DWORD) nInBufferSize, // size of input buffer # (LPVOID) lpOutBuffer, // output buffer # (DWORD) nOutBufferSize, // size of output buffer # (LPDWORD) lpBytesReturned, // number of bytes returned # (LPOVERLAPPED) lpOverlapped // OVERLAPPED structure # ); # typedef struct _VOLUME_DISK_EXTENTS { # DWORD NumberOfDiskExtents; # DISK_EXTENT Extents[1]; # } VOLUME_DISK_EXTENTS, # *PVOLUME_DISK_EXTENTS; # typedef struct _DISK_EXTENT { # DWORD DiskNumber; # LARGE_INTEGER StartingOffset; # LARGE_INTEGER ExtentLength; # } DISK_EXTENT, # *PDISK_EXTENT; # DWORD = N ## Internal stuff my ($CloseHandle, $GetCurrentProcess, $OpenProcessToken, $LookupPrivilegeValue, $AdjustTokenPrivileges, $CreateFile, $ReadDirectoryChanges, $DeviceIoControl); sub FILE_LIST_DIRECTORY { 0x00000001 } sub FILE_SHARE_READ { 0x00000001 } sub FILE_SHARE_WRITE { 0x00000002 } sub OPEN_EXISTING { 3 } sub FILE_FLAG_BACKUP_SEMANTICS { 0x02000000 } sub IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS { 5636096 } sub FILE_READ_ATTRIBUTES { 0x0080 } sub FILE_NOTIFY_CHANGE_NAME { 0x00000003 } sub DWORD_SIZE { 4 } sub TOKEN_ADJUST_PRIVILEGES { 0x0020 } sub TOKEN_QUERY { 0x0008 } sub SE_BACKUP_NAME { 'SeBackupPrivilege' } sub SE_RESTORE_NAME { 'SeRestorePrivilege' } sub SE_CHANGE_NOTIFY_NAME { 'SeChangeNotifyPrivilege' } sub SE_PRIVILEGE_ENABLED { 2 } sub _InitializeAPI { my $kernel32 = 'kernel32.dll'; my $advapi32 = 'advapi32.dll'; $CloseHandle = new Win32::API($kernel32, 'CloseHandle', 'N', 'I') || die; $GetCurrentProcess = new Win32::API($kernel32, 'GetCurrentProcess', '', 'N') || die $^E; $OpenProcessToken = new Win32::API($advapi32, 'OpenProcessToken', 'NNP', 'I' ) || die $^E; $LookupPrivilegeValue = new Win32::API($advapi32, 'LookupPrivilegeValue', 'PPP', 'I') || die $^E; $AdjustTokenPrivileges = new Win32::API($advapi32, 'AdjustTokenPrivileges', 'NIPNPP', 'I') || die $^E; $CreateFile = new Win32::API($kernel32, 'CreateFileA', 'PNNPNNN', 'N') or die $^E; $ReadDirectoryChanges = new Win32::API($kernel32, 'ReadDirectoryChangesW', 'NPNINPPP', 'I') || die $^E +; $DeviceIoControl = new Win32::API($kernel32, 'DeviceIoControl', 'NPPNPNPP', 'I') || die $^E; } sub _EnablePrivileges { my $phToken = pack("L", 0); if($OpenProcessToken->Call($GetCurrentProcess->Call(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, $phToken)) { my $hToken = unpack("L", $phToken); _SetPrivilege($hToken, SE_BACKUP_NAME, 1); _SetPrivilege($hToken, SE_RESTORE_NAME, 1); _SetPrivilege($hToken, SE_CHANGE_NOTIFY_NAME, 1); $CloseHandle->Call($hToken); } #print "privileges altered\n"; } sub _SetPrivilege { my ($hToken, $pszPriv, $bSetFlag) = @_; my $iResult; my $pLuid = pack("Ll", 0, 0); if($LookupPrivilegeValue->Call("\x00\x00", $pszPriv, $pLuid)) { my $pPrivStruct = pack("LLlL", 1, unpack("Ll", $pLuid), (($bSetFlag)? SE_PRIVILEGE_ENABLED : 0) +); $iResult = (0 != $AdjustTokenPrivileges->Call($hToken, 0, $pPrivStruct, length($pPrivStr +uct), 0, 0)); } return ($iResult); } _InitializeAPI(); _EnablePrivileges(); my $hDevice; #my $dwIoControlCode = FSCTL_GET_RETRIEVAL_POINTERS; #my $lpInBuffer = pack("L", 0); my $lpInBuffer = []; my $nInBufferSize = 0; my $lpOutBuffer = 0; my $nOutBufferSize = 0; my $lpBytesReturned = 0; my $lpOverlapped = []; #$hDevice = createFile( "//./PhysicalDrive1", "r", "rw") # or die "Can't open: $^E\n"; #my $path = "//./D:/Snap1.gif"; #my $path = "D:/Snap1.gif"; my $path = "D:/"; $hDevice = $CreateFile->Call($path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_W +RITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0) || die $^E; my $nBufferLength = 1024; #1024 * DWORD_SIZE; my $pBuffer = "\x00" x $nBufferLength; my $pBytesReturned = pack("L", 0); # my $iResult = $ReadDirectoryChanges->Call($hDevice, # $pBuffer, # $nBufferLength, # 1, # FILE_NOTIFY_CHANGE_NAME +, # $pBytesReturned, # 0, 0) || die $^E; # my $bytesReturned = unpack("L", $pBytesReturned); #print Dumper($iResult); print Dumper($hDevice); #if ($iResult < 1) { # print Win32::GetLastError() . "\n"; # print $^E . "\n"; # exit; #} if ($hDevice < 1) { print $^E . "\n"; exit; } #$hDevice = unpack("L", $hDevice); #print $hDevice . "\n"; #Win32API::File::DeviceIoControl($hDevice, # IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, # 0, # [], # $lpOutBuffer, # $nOutBufferSize, # $lpBytesReturned, # 0, # ) || die $^E; my $iResult2 = $DeviceIoControl->Call($hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 0, [], $lpOutBuffer, $nOutBufferSize, $lpBytesReturned, 0, ) || die $^E; print Dumper($lpOutBuffer); print Dumper($nOutBufferSize); my $pBytesReturned2 = pack("L", 0); my $bytesReturned2 = unpack("L", $pBytesReturned2); my @results = (); print $bytesReturned2 . "\n"; __END__ if ($bytesReturned > 0) { my ($NextEntryOffset, $Action, $FileNameLength, $FileName); while (1) { my ($NextEntryOffset, $Action, $FileNameLength) = unpack("LLL" +, $pBuffer); (undef, undef, undef, $FileName) = unpack("LLLa$FileNameLength +", $pBuffer); $FileName = pack "C*", unpack "S*", $FileName; push @results, $Action => $FileName; last if($NextEntryOffset <= 0); $pBuffer = substr($pBuffer, $NextEntryOffset); } } #print Win32::GetLastError();
I get access denied as it is. If I use Win32API::File::DeviceIoControl instead, I get some error about the handle.

Im not even sure this is enough, and if it will work. I mean, Im not sure I can send a file to the DeviceIoControl, and that returns all sectors the file uses, or I somehow need to use FSCTL_GET_RETRIEVAL_POINTERS too. ( http://www.wd-3.com/archive/luserland.htm )
I get the same error with FSCTL_GET_RETRIEVAL_POINTERS (used in DeviceIOControl as second parameter) too though, as I tried to get all clusters a file is on, just like they do here: http://www.sysinternals.com/Information/DiskDefragmenting.html , but with no luck...

So, what am I missing here? And, how am I supposed to know the size of for instance lpInBuffer? ( sizeof(lpInBuffer) ) doesn't really work in Perl)...

Oh, and btw, you may have to change the path to the file.


UPDATE: Updated the code with the privileges enableing... No luck... But, after some research, I think I dont need the IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, but I have to use FSCTL_GET_RETRIEVAL_POINTERS...

Thanks,
Ace

In reply to From File to at Sectors on harddrive (Windows) by Ace128

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.