示例#1
0
        //-----------------------------------------------------------------------
        // Gets the target path for a reparse point
        private static void GetTarget(ref ReparsePoint rp)
        {
            string wPath = rp.Path;

            if (!wPath.StartsWith(@"\\?\"))
            {
                wPath = @"\\?\" + wPath;
            }

            if (((uint)rp.TagType & (uint)ReparseTagType.IO_REPARSE_TAG_MOUNT_POINT) != (uint)ReparseTagType.IO_REPARSE_TAG_MOUNT_POINT)
            {
                rp.Target = "";
                return;
            }

            try
            {
                // We need a handle to the reparse point to pass to DeviceIocontrol down below.
                // CreateFile is how we get that handle.
                // We want to play nice with others, so we note that we're only reading it, and we want to
                // allow others to be able to access (but not delete) it as well while we have the handle (the
                // GENERIC_READ and FILE_SHARE_READ | FILE_SHARE_WRITE values)
                //
                // Biggest key is the flag FILE_FLAG_OPEN_REPARSE_POINT, which tells CreateFile that we want
                // a handle to the reparse point itself and not to the target of the reparse point
                //
                // CreateFile will return INVALID_HANDLE_VALUE with a last error of 5 - Access Denied
                // if the FILE_FLAG_BACKUP_SEMANTICS is not specified when opening a directory/reparse point
                // It's noted in the directory section of the CreateFile MSDN page
                IntPtr pathHndl = CreateFileW(wPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero,
                                              OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, IntPtr.Zero);

                if (pathHndl.ToInt32() == INVALID_HANDLE_VALUE)
                {
                    rp.Err    = Marshal.GetLastWin32Error();
                    rp.ErrMsg = "Invalid Handle returned by CreateFile";
                    rp.Target = "";
                    return;
                }

                uint lenDataReturned          = 0;
                REPARSE_DATA_BUFFER rpDataBuf = new REPARSE_DATA_BUFFER();

                //Allocate a buffer to get the "user defined data" out of the reaprse point.
                //MSDN page on FSCTL_GET_REPARSE_POINT discusses size calculation
                IntPtr pMem = Marshal.AllocHGlobal(Marshal.SizeOf(rpDataBuf) + ReparseHeaderSize);

                //DeviceIocontrol takes a handle to a file/directory/device etc, that's obtained via CreateFile
                // In our case, it's a handle to the directory that's marked a reparse point
                //We pass in the FSCTL_GET_REPARSE_POINT flag to getll DeviceIoControl that we want to get data about a reparse point
                //There is no In buffer. pMem is our out buffer that will hold the returned REPARSE_DATA_BUFFER
                //lenDataReturned is of course how much data was copied into our buffer pMem.
                //We're doing a simple call.. no asyncronous stuff going on, so Overlapped is a null pointer
                if (!DeviceIoControl(pathHndl, FSCTL_GET_REPARSE_POINT, IntPtr.Zero, 0, pMem,
                                     (uint)Marshal.SizeOf(rpDataBuf) + ReparseHeaderSize, out lenDataReturned, IntPtr.Zero))
                {
                    rp.ErrMsg = "Call to DeviceIoControl failed";
                    rp.Err    = Marshal.GetLastWin32Error();
                    rp.Target = "";
                }
                else
                {
                    rpDataBuf = (REPARSE_DATA_BUFFER)Marshal.PtrToStructure(pMem, rpDataBuf.GetType());
                    rp.Target = rpDataBuf.PathBuffer;
                }
                Marshal.FreeHGlobal(pMem);
                CloseHandle(pathHndl);
            }
            catch (Exception e)
            {
                rp.Err    = -1;
                rp.ErrMsg = e.Message;
                rp.Target = "";
            }

            return;
        }
        //-----------------------------------------------------------------------
        // Gets the target path for a reparse point
        private static void GetTarget(ref ReparsePoint rp)
        {

            string wPath = rp.Path;
            if (!wPath.StartsWith(@"\\?\")) wPath = @"\\?\" + wPath;

            if (((uint)rp.TagType & (uint)ReparseTagType.IO_REPARSE_TAG_MOUNT_POINT) != (uint)ReparseTagType.IO_REPARSE_TAG_MOUNT_POINT)
            {
                rp.Target = "";
                return;
            }

            try
            {
                // We need a handle to the reparse point to pass to DeviceIocontrol down below.
                // CreateFile is how we get that handle.
                // We want to play nice with others, so we note that we're only reading it, and we want to
                // allow others to be able to access (but not delete) it as well while we have the handle (the
                // GENERIC_READ and FILE_SHARE_READ | FILE_SHARE_WRITE values)
                //
                // Biggest key is the flag FILE_FLAG_OPEN_REPARSE_POINT, which tells CreateFile that we want
                // a handle to the reparse point itself and not to the target of the reparse point
                //
                // CreateFile will return INVALID_HANDLE_VALUE with a last error of 5 - Access Denied
                // if the FILE_FLAG_BACKUP_SEMANTICS is not specified when opening a directory/reparse point
                // It's noted in the directory section of the CreateFile MSDN page
                IntPtr pathHndl = CreateFileW(wPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero,
                OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, IntPtr.Zero);

                if (pathHndl.ToInt32() == INVALID_HANDLE_VALUE)
                {
                    rp.Err = Marshal.GetLastWin32Error();
                    rp.ErrMsg = "Invalid Handle returned by CreateFile";
                    rp.Target = "";
                    return;
                }

                uint lenDataReturned = 0;
                REPARSE_DATA_BUFFER rpDataBuf = new REPARSE_DATA_BUFFER();

                //Allocate a buffer to get the "user defined data" out of the reaprse point.
                //MSDN page on FSCTL_GET_REPARSE_POINT discusses size calculation
                IntPtr pMem = Marshal.AllocHGlobal(Marshal.SizeOf(rpDataBuf) + ReparseHeaderSize);

                //DeviceIocontrol takes a handle to a file/directory/device etc, that's obtained via CreateFile
                // In our case, it's a handle to the directory that's marked a reparse point
                //We pass in the FSCTL_GET_REPARSE_POINT flag to getll DeviceIoControl that we want to get data about a reparse point
                //There is no In buffer. pMem is our out buffer that will hold the returned REPARSE_DATA_BUFFER
                //lenDataReturned is of course how much data was copied into our buffer pMem.
                //We're doing a simple call.. no asyncronous stuff going on, so Overlapped is a null pointer
                if (!DeviceIoControl(pathHndl, FSCTL_GET_REPARSE_POINT, IntPtr.Zero, 0, pMem,
                (uint)Marshal.SizeOf(rpDataBuf) + ReparseHeaderSize, out lenDataReturned, IntPtr.Zero))
                {
                    rp.ErrMsg = "Call to DeviceIoControl failed";
                    rp.Err = Marshal.GetLastWin32Error();
                    rp.Target = "";
                }
                else
                {
                    rpDataBuf = (REPARSE_DATA_BUFFER)Marshal.PtrToStructure(pMem, rpDataBuf.GetType());
                    rp.Target = rpDataBuf.PathBuffer;
                }
                Marshal.FreeHGlobal(pMem);
                CloseHandle(pathHndl);

            }
            catch (Exception e)
            {
                rp.Err = -1;
                rp.ErrMsg = e.Message;
                rp.Target = "";
            }

            return;
        }