# encoding: utf-8 require "ffi" module Winhelper extend FFI::Library ffi_lib 'kernel32' ffi_convention :stdcall class FileTime < FFI::Struct layout :lowDateTime, :uint, :highDateTime, :uint end #http://msdn.microsoft.com/en-us/library/windows/desktop/aa363788(v=vs.85).aspx class FileInformation < FFI::Struct layout :fileAttributes, :uint, #DWORD dwFileAttributes; :createTime, FileTime, #FILETIME ftCreationTime; :lastAccessTime, FileTime, #FILETIME ftLastAccessTime; :lastWriteTime, FileTime, #FILETIME ftLastWriteTime; :volumeSerialNumber, :uint, #DWORD dwVolumeSerialNumber; :fileSizeHigh, :uint, #DWORD nFileSizeHigh; :fileSizeLow, :uint, #DWORD nFileSizeLow; :numberOfLinks, :uint, #DWORD nNumberOfLinks; :fileIndexHigh, :uint, #DWORD nFileIndexHigh; :fileIndexLow, :uint #DWORD nFileIndexLow; end #http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx #HANDLE WINAPI CreateFile(_In_ LPCTSTR lpFileName,_In_ DWORD dwDesiredAccess,_In_ DWORD dwShareMode, # _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,_In_ DWORD dwCreationDisposition, # _In_ DWORD dwFlagsAndAttributes,_In_opt_ HANDLE hTemplateFile); attach_function :GetOpenFileHandle, :CreateFileA, [:pointer, :uint, :uint, :pointer, :uint, :uint, :pointer], :pointer #http://msdn.microsoft.com/en-us/library/windows/desktop/aa364952(v=vs.85).aspx #BOOL WINAPI GetFileInformationByHandle(_In_ HANDLE hFile,_Out_ LPBY_HANDLE_FILE_INFORMATION lpFileInformation); attach_function :GetFileInformationByHandle, [:pointer, :pointer], :int attach_function :CloseHandle, [:pointer], :int def self.GetWindowsUniqueFileIdentifier(path) handle = GetOpenFileHandle(path, 0, 7, nil, 3, 128, nil) fileInfo = Winhelper::FileInformation.new success = GetFileInformationByHandle(handle, fileInfo) CloseHandle(handle) if success == 1 #args = [ # fileInfo[:fileAttributes], fileInfo[:volumeSerialNumber], fileInfo[:fileSizeHigh], fileInfo[:fileSizeLow], # fileInfo[:numberOfLinks], fileInfo[:fileIndexHigh], fileInfo[:fileIndexLow] # ] #p "Information: %u %u %u %u %u %u %u " % args #this is only guaranteed on NTFS, for ReFS on windows 2012, GetFileInformationByHandleEx should be used with FILE_ID_INFO, which returns a 128 bit identifier return "#{fileInfo[:volumeSerialNumber]}-#{fileInfo[:fileIndexLow]}-#{fileInfo[:fileIndexHigh]}" else #p "cannot retrieve file information, returning path" return path; end end end #fileId = Winhelper.GetWindowsUniqueFileIdentifier('C:\inetpub\logs\LogFiles\W3SVC1\u_ex1fdsadfsadfasdf30612.log') #p "FileId: " + fileId #p "outside function, sleeping" #sleep(10)