Ruby - DOS (Win32) 路径名到 NT(本机)路径名
Ruby - DOS (Win32) path name to NT (native) path name
我需要从 Ruby (1.9.3) 中的 DOS (Win32) 路径获取文件的 NT(本机)路径。
意思是,我有字符串:
dos_path = "C:\Windows\regedit.exe"
但我需要:
nt_path = "\Device\HarddiskVolume1\Windows\regedit.exe"
有什么办法吗?
谢谢!
MS-DOS 设备名可以用 QueryDosDevice
function. Calling such a function from Ruby can be done with Fiddle
转换为 NT 路径。自 1.9.3 以来,它是 Ruby 标准库的一部分。但是,以下示例仅适用于 2.0.0 或更新版本。
require 'fiddle/import'
require 'fiddle/types'
module DOS2NT
extend Fiddle::Importer # makes function importing easier
dlload 'kernel32.dll'
include Fiddle::Win32Types # so DWORD can be used instead of unsigned long
extern 'DWORD QueryDosDeviceW(void*, void*, DWORD)', :stdcall
extern 'DWORD GetLastError()', :stdcall
ERROR_INSUFFICIENT_BUFFER = 122
SIZEOF_WCHAR = 2 # sizeof(WCHAR) on Windows
# a generic error class
class Error < StandardError
end
def self.dos_device_name_to_path(devicename)
initial_len = 256
grow_factor = 2
# we care about Unicode (Windows uses UTF-16LE)
devicename.encode!(Encoding::UTF_16LE)
# create buffer
buf = "[=10=][=10=]".force_encoding(Encoding::UTF_16LE) * initial_len
# call QueryDosDeviceW until the call was successful
while (written_chars = QueryDosDeviceW(devicename, buf, buf.length)) == 0
# it wasn't
case (error = GetLastError())
# resize buffer as it was too short
when ERROR_INSUFFICIENT_BUFFER
buf *= grow_factor
# other errors like ERROR_FILE_NOT_FOUND (2)
else
raise Error, "QueryDosDeviceW failed (GetLastError returned #{error})"
end
end
# truncate buffer (including the null character)
path = buf[0, written_chars - SIZEOF_WCHAR]
# transcode the path to UTF-8 as that's usually more useful
path.encode!(Encoding::UTF_8)
end
end
# example strings from the question
dos_path = 'C:\Windows\regedit.exe'
nt_path = '\Device\HarddiskVolume1\Windows\regedit.exe'
# convert and print inspected result
p dos_path.sub(/\A[A-Z]:/i) { |m| DOS2NT.dos_device_name_to_path(m) } # => "\Device\HarddiskVolume1\Windows\regedit.exe"
我需要从 Ruby (1.9.3) 中的 DOS (Win32) 路径获取文件的 NT(本机)路径。
意思是,我有字符串:
dos_path = "C:\Windows\regedit.exe"
但我需要:
nt_path = "\Device\HarddiskVolume1\Windows\regedit.exe"
有什么办法吗? 谢谢!
MS-DOS 设备名可以用 QueryDosDevice
function. Calling such a function from Ruby can be done with Fiddle
转换为 NT 路径。自 1.9.3 以来,它是 Ruby 标准库的一部分。但是,以下示例仅适用于 2.0.0 或更新版本。
require 'fiddle/import'
require 'fiddle/types'
module DOS2NT
extend Fiddle::Importer # makes function importing easier
dlload 'kernel32.dll'
include Fiddle::Win32Types # so DWORD can be used instead of unsigned long
extern 'DWORD QueryDosDeviceW(void*, void*, DWORD)', :stdcall
extern 'DWORD GetLastError()', :stdcall
ERROR_INSUFFICIENT_BUFFER = 122
SIZEOF_WCHAR = 2 # sizeof(WCHAR) on Windows
# a generic error class
class Error < StandardError
end
def self.dos_device_name_to_path(devicename)
initial_len = 256
grow_factor = 2
# we care about Unicode (Windows uses UTF-16LE)
devicename.encode!(Encoding::UTF_16LE)
# create buffer
buf = "[=10=][=10=]".force_encoding(Encoding::UTF_16LE) * initial_len
# call QueryDosDeviceW until the call was successful
while (written_chars = QueryDosDeviceW(devicename, buf, buf.length)) == 0
# it wasn't
case (error = GetLastError())
# resize buffer as it was too short
when ERROR_INSUFFICIENT_BUFFER
buf *= grow_factor
# other errors like ERROR_FILE_NOT_FOUND (2)
else
raise Error, "QueryDosDeviceW failed (GetLastError returned #{error})"
end
end
# truncate buffer (including the null character)
path = buf[0, written_chars - SIZEOF_WCHAR]
# transcode the path to UTF-8 as that's usually more useful
path.encode!(Encoding::UTF_8)
end
end
# example strings from the question
dos_path = 'C:\Windows\regedit.exe'
nt_path = '\Device\HarddiskVolume1\Windows\regedit.exe'
# convert and print inspected result
p dos_path.sub(/\A[A-Z]:/i) { |m| DOS2NT.dos_device_name_to_path(m) } # => "\Device\HarddiskVolume1\Windows\regedit.exe"