[Win32utils-devel] win32-dir, unicode
Heesob Park
phasis at gmail.com
Sat May 27 08:25:16 EDT 2006
Hi,
2006/5/27, Daniel Berger <djberg96 at gmail.com>:<snip>> Hi Heesob,>> That came through as a single line for some reason...>> Anyway, I modified the approach somewhat. Instead of adding a 'unicode'> flag, I altered the windows-pr package to wrap methods like this:>> def CreateDirectory(path, attributes)> if $KCODE != 'NONE'> CreateDirectoryW.call(path, attributes) != 0> else> CreateDirectory.call(path, attributes) != 0> end> end>> Within dir.rb, I did this:>> if $KCODE != 'NONE'> to_path = to_path.split("\0\0").first> else> to_path = to_path.split(0.chr).first> end>> However, after making those changes I got this:>> dir.rb:123:in `create_junction': DeviceIoControl() failed: The data> present in the reparse point buffer is invalid. (RuntimeError).>> Does rdb need to be packed differently?>> BTW, I also tinkered with the idea of using IsTextUnicode():>> def CreateDirectory(path, attributes)> if IsTextUnicode(path, path.size, 0)> CreateDirectoryW.call(path, attributes) != 0> else> CreateDirectory.call(path, attributes) != 0> end> end>> But this didn't seem to handle UCS-2, i.e it worked for> "\x95\x03\xBB\x03\xBB\x03\xAC\x03\xC3\x03\0\0" but not "Ελλάσ". I> imagine it's also slower.>> Regards,>> Dan> _______________________________________________> win32utils-devel mailing list> win32utils-devel at rubyforge.org> http://rubyforge.org/mailman/listinfo/win32utils-develI have managed to succeed in creating junction with create_junction method.
First modify multi_to_wide and wide_to_multi to support UTF8 and Ansi string.For english users, UTF8 encoding is sufficient but other languageusers like Korean, both UTF8 and Ansi are required.
def multi_to_wide(str) cp = ($KCODE == 'UTF8') ? CP_UTF8 : CP_ACP buf = 0.chr * 260 int = MultiByteToWideChar(cp, 0, str, -1, buf, buf.size) if int > 0 buf[0, int*2] else str end end
def wide_to_multi(str) cp = ($KCODE == 'UTF8') ? CP_UTF8 : CP_ACP buf = 0.chr * 260 int = WideCharToMultiByte(cp, 0, str, -1, buf, buf.size, 0, 0)
if int > 0 buf[0, int] else str end end
Second, modify create_junction method like this:
def self.create_junction(to, from) # Normalize the paths to.tr!('/', "\\") from.tr!('/', "\\")
to_path = 0.chr * 260 from_path = 0.chr * 260 buf_target = 0.chr * 260
from = multi_to_wide(from) to = multi_to_wide(to) if GetFullPathNameW.call(from, from_path.size, from_path, 0) == 0 raise StandardError, 'GetFullPathName() failed: ' + get_last_error end
if GetFullPathNameW.call(to, to_path.size, to_path, 0) == 0 raise StandardError, 'GetFullPathName() failed: ' + get_last_error end
to_path = to_path.strip+"\0\0\0" from_path = from_path.strip+"\0\0\0"
# You can create a junction to a directory that already exists, so # long as it's empty.
rv = CreateDirectoryW.call(to_path, 0) if rv == 0 && GetLastError.call != ERROR_ALREADY_EXISTS raise StandardError, 'CreateDirectory() failed: ' + get_last_error end
handle = CreateFileW.call( to_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0 )
if handle == INVALID_HANDLE_VALUE raise StandardError, 'CreateFile() failed: ' + get_last_error end buf_target = multi_to_wide("\\??\\") length = buf_target.size-2 buf_target = buf_target[0,length] + from_path length = buf_target.size-2 wide_string = buf_target
# REPARSE_JDATA_BUFFER rdb = [ "0xA0000003L".hex, # ReparseTag (IO_REPARSE_TAG_MOUNT_POINT) length + 12, # ReparseDataLength 0, # Reserved 0, # SubstituteNameOffset length, # SubstituteNameLength length + 2, # PrintNameOffset 0, # PrintNameLength wide_string # PathBuffer ].pack('LSSSSSSa' + (length + 4).to_s)
bytes = [length].pack('L')
bool = DeviceIoControl( handle, CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED,FILE_ANY_ACCESS), rdb, rdb.size, 0, 0, bytes, 0 )
unless bool error = 'DeviceIoControl() failed: ' + get_last_error
RemoveDirectoryW.call(to_path) CloseHandle(handle) raise error end
CloseHandle(handle)
self end
Make test.rb like this:
from = "C:\\test"to = "Ελλάσ"Dir.mkdir(from) unless File.exists?(from)Dir.create_junction(to, from)
The file format must be UTF8 DOS format.
Run with KCODE option like this:
ruby -Ku test.rb
Regards,
Park Heesob
More information about the win32utils-devel
mailing list