[Win32utils-devel] Dir.create_junction with FFI
djberg96 at gmail.com
Fri May 18 15:28:55 UTC 2012
On Fri, May 18, 2012 at 1:35 AM, Heesob Park <phasis at gmail.com> wrote:
> 2012/5/18 Daniel Berger <djberg96 at gmail.com>
>> On Thu, May 17, 2012 at 9:44 PM, Heesob Park <phasis at gmail.com> wrote:
>> > Hi,
>> > 2012/5/18 Daniel Berger <djberg96 at gmail.com>
>> >> Hi,
>> >> Try as I might, I just cannot get Dir.create_junction to work with FFI
>> >> in the ffi branch of the win32-dir project. The problem is the
>> >> REPARSE_JDATA_BUFFER struct. I'm just not sure how to set those
>> >> members, specifically, the PathBuffer member. The target looks good,
>> >> it's UTF-16LE encoded, but I can't make it work, despite trying
>> >> several ways of defining the struct, and setting various struct
>> >> members.
>> >> A quick gist for reference: https://gist.github.com/2721257
>> >> Help much appreciated!
>> > The REPARSE_JDATA_BUFFER is a kind of the variable length structure.
>> > The actual size of structure is determined by ReparseDataLength member.
>> > Here is my trial.
>> > # define sufficient size of structure.
>> > class REPARSE_JDATA_BUFFER < FFI::Struct
>> > layout(
>> > :ReparseTag, :ulong,
>> > :ReparseDataLength, :ushort,
>> > :Reserved, :ushort,
>> > :SubstituteNameOffset, :ushort,
>> > :SubstituteNameLength, :ushort,
>> > :PrintNameOffset, :ushort,
>> > :PrintNameLength, :ushort,
>> > :PathBuffer, [:char, 1024]
>> > )
>> > end
>> > # UTF-16LE encoded string
>> > target = "\\??\\".encode('UTF-16LE') + from_path
>> > rdb = REPARSE_JDATA_BUFFER.new
>> > rdb[:ReparseTag] = 2684354563 # IO_REPARSE_TAG_MOUNT_POINT
>> > rdb[:ReparseDataLength] = target.bytesize + 12
>> > rdb[:Reserved] = 0
>> > rdb[:SubstituteNameOffset] = 0
>> > rdb[:SubstituteNameLength] = target.bytesize
>> > rdb[:PrintNameOffset] = target.bytesize + 2
>> > rdb[:PrintNameLength] = 0
>> > rdb[:PathBuffer] = target
>> I tried that, but I still got: DeviceIoControl: The data present in
>> the reparse point buffer is invalid.
>> Did it work for you?
> Here is a working code.
Excellent, thank you!
Wayne Meissner showed me a trick. For PathBuffer,he said I could
declare it as "PathBuffer, [:char, 2]" (since it's really a wchar),
and then assign PathBuffer like this:
rdb[:PathBuffer].to_ptr.put_bytes(0, target, target.bytesize)
However, when I tried that I end up with a "to " directory as a
result and, although it doesn't raise an error in the code, I can't
actually cd into that directory after it's created.
I also realized there's a bug (in the original version) in that it
never checks if the "from" (2nd) argument actually exists! So, I've
added that. I'm not sure what it's doing if there's nothing for it to
junction from. I think I should add an check to make sure the 2nd arg
actually exists before proceeding.
Why rdb[:ReparseDataLength] + 8? What's the "+8" for?
Thanks again for all your help.
More information about the win32utils-devel