[Win32utils-devel] GetFinalPathNameByHandle for XP and earlier
Daniel Berger
djberg96 at gmail.com
Sat Nov 22 03:17:52 EST 2008
Hi all,
How's this look? I based it on
http://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx.
I'm undecided as to when I should raise an error versus when I should just let
it fall through, but this is how it is for now.
You'll need the latest windows-pr from CVS, btw.
Regards,
Dan
PS - Where should I put it? In Windows::File directly? In a separate helper module?
require 'windows/file'
require 'windows/file_mapping'
require 'windows/volume'
require 'windows/process'
require 'windows/limits'
require 'windows/handle'
require 'windows/error'
require 'windows/memory'
include Windows::File
include Windows::FileMapping
include Windows::Volume
include Windows::Process
include Windows::Limits
include Windows::Handle
include Windows::Error
include Windows::Memory
# The buf, buf_size, and flags arguments are ignored, but are
# present in order to keep the function parameters identical
# to the function defined for Windows Vista and later.
#
def GetFinalPathNameByHandle(handle, buf, buf_size, flags)
size_ptr = [0].pack('Q')
unless GetFileSizeEx(handle, size_ptr)
raise get_last_error
end
if size_ptr.unpack('Q')[0] <= 0
raise 'file size must be greater than zero'
end
map = CreateFileMapping(handle, nil, PAGE_READONLY, 0, 1, nil)
final_path = nil
if map && map > 0
pmem = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 1)
if pmem
begin
buf = 0.chr * MAXPATH
# Buf will contain the full path, but with the device name instead
# of the drive letter that we ultimately want.
if GetMappedFileName(GetCurrentProcess(), pmem, buf, MAXPATH) > 0
buf.strip!
dbuf = 0.chr * 512
# Get a list of logical devices
if GetLogicalDriveStrings(dbuf.size, dbuf) > 0
devices = dbuf.split("\0")
devices.delete_if{ |d| d.empty? || d.size > 3 }
# Match the drive letter to a device. Once we find a match to
# the device returned by GetMappedFileName, replace the device
# name from our original buffer with the drive letter.
devices.each{ |device|
name = 0.chr * MAXPATH
device.chop! # Remove trailing slash
if QueryDosDevice(device, name, name.size) > 0
name.strip!
if buf.include?(name)
final_path = device << buf[name.length..-1]
break
end
end
}
end
else
raise get_last_error
end
ensure
UnmapViewOfFile(pmem)
end
end
else
raise get_last_error
end
final_path
end
# Test program
file = File.join(Dir.pwd, 'test.txt')
handle = CreateFile(
file,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
nil,
OPEN_ALWAYS,
nil,
nil
)
if handle == INVALID_HANDLE_VALUE
raise get_last_error
end
p GetFinalPathNameByHandle(handle, nil, nil, nil)
CloseHandle(handle)
More information about the win32utils-devel
mailing list