[Win32utils-devel] Dir.create_junction with FFI
Heesob Park
phasis at gmail.com
Fri May 18 15:52:03 UTC 2012
Hi, Dan
2012/5/19 Daniel Berger <djberg96 at gmail.com>
> On Fri, May 18, 2012 at 1:35 AM, Heesob Park <phasis at gmail.com> wrote:
> > Hi,
> >
> > 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.
> > https://gist.github.com/1c431b679b26c947a7d2
>
> 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?
>
>
The 8 is called REPARSE_DATA_BUFFER_HEADER_SIZE.
It is calculated by
sizeof(ReparseTag)+sizeof(ReparseDataLength)+sizeof(Reserved).
> Thanks again for all your help.
>
> It's my pleasure to help you.
Regards,
Park Heesob
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/win32utils-devel/attachments/20120519/9ac1e2e5/attachment.html>
More information about the win32utils-devel
mailing list