public static Stream CreateFileGroupDescriptorW(string fileName, DateTimeOffset lastWriteTime)
        {
            var fileGroupDescriptor = new FILEGROUPDESCRIPTORW()
            {
                cItems = 1
            };
            var fileDescriptor = new FILEDESCRIPTORW()
            {
                cFileName = fileName
            };

            fileDescriptor.dwFlags |= FD_SHOWPROGRESSUI;

            fileDescriptor.dwFlags |= FD_CREATETIME | FD_WRITESTIME;
            var changeTime         = lastWriteTime.ToLocalTime().ToFileTime();
            var changeTimeFileTime = new System.Runtime.InteropServices.ComTypes.FILETIME
            {
                dwLowDateTime  = (int)(changeTime & 0xffffffff),
                dwHighDateTime = (int)(changeTime >> 32),
            };

            fileDescriptor.ftLastWriteTime = changeTimeFileTime;
            fileDescriptor.ftCreationTime  = changeTimeFileTime;

            var fileGroupDescriptorBytes = StructureBytes(fileGroupDescriptor);
            var fileDescriptorBytes      = StructureBytes(fileDescriptor);

            var memoryStream = new MemoryStream();

            memoryStream.Write(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
            memoryStream.Write(fileDescriptorBytes, 0, fileDescriptorBytes.Length);

            return(memoryStream);
        }
Ejemplo n.º 2
0
        public static Stream CreateFileGroupDescriptorW(string fileName, DateTimeOffset lastWriteTime, long?fileSize)
        {
            var fileGroupDescriptor = new FILEGROUPDESCRIPTORW()
            {
                cItems = 1
            };
            var fileDescriptor = new FILEDESCRIPTORW()
            {
                cFileName = fileName
            };

            fileDescriptor.dwFlags |= FD_SHOWPROGRESSUI;

            if (lastWriteTime != default)
            {
                fileDescriptor.dwFlags |= FD_CREATETIME | FD_WRITESTIME;
                var changeTime         = lastWriteTime.ToFileTime();
                var changeTimeFileTime = new System.Runtime.InteropServices.ComTypes.FILETIME
                {
                    dwLowDateTime  = (int)(changeTime & 0xffffffff),
                    dwHighDateTime = (int)(changeTime >> 32),
                };
                fileDescriptor.ftLastWriteTime = changeTimeFileTime;
                fileDescriptor.ftCreationTime  = changeTimeFileTime;
            }

            if (fileSize.HasValue)
            {
                fileDescriptor.dwFlags |= FD_FILESIZE;
                // TODO: remove ! once https://github.com/dotnet/roslyn/issues/33330 is fixed
                fileDescriptor.nFileSizeLow  = (uint)(fileSize & 0xffffffff) !;
                fileDescriptor.nFileSizeHigh = (uint)(fileSize >> 32) !;
            }

            var fileGroupDescriptorBytes = StructureBytes(fileGroupDescriptor);
            var fileDescriptorBytes      = StructureBytes(fileDescriptor);

            var memoryStream = new MemoryStream();

            memoryStream.Write(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
            memoryStream.Write(fileDescriptorBytes, 0, fileDescriptorBytes.Length);

            return(memoryStream);
        }
        /// <summary>
        /// Retrieves the data associated with the specified data format, using a Boolean to determine whether to convert the data to the format.
        /// </summary>
        /// <param name="format">The format of the data to retrieve. See <see cref="T:System.Windows.DataFormats"></see> for predefined formats.</param>
        /// <param name="autoConvert">true to convert the data to the specified format; otherwise, false.</param>
        /// <returns>
        /// The data associated with the specified format, or null.
        /// </returns>
        public object GetData(string format, bool autoConvert)
        {
            //handle the "FileGroupDescriptor" and "FileContents" format request in this class otherwise pass through to underlying IDataObject
            switch (format)
            {
            case "FileGroupDescriptor":
                //override the default handling of FileGroupDescriptor which returns a
                //MemoryStream and instead return a string array of file names
                IntPtr fileGroupDescriptorAPointer = IntPtr.Zero;
                try
                {
                    //use the underlying IDataObject to get the FileGroupDescriptor as a MemoryStream
                    MemoryStream fileGroupDescriptorStream = (MemoryStream)this._underlyingDataObject.GetData("FileGroupDescriptor", autoConvert);
                    byte[]       fileGroupDescriptorBytes  = new byte[fileGroupDescriptorStream.Length];
                    fileGroupDescriptorStream.Read(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
                    fileGroupDescriptorStream.Close();

                    //copy the file group descriptor into unmanaged memory
                    fileGroupDescriptorAPointer = Marshal.AllocHGlobal(fileGroupDescriptorBytes.Length);
                    Marshal.Copy(fileGroupDescriptorBytes, 0, fileGroupDescriptorAPointer, fileGroupDescriptorBytes.Length);

                    //marshal the unmanaged memory to to FILEGROUPDESCRIPTORA struct
                    object fileGroupDescriptorObject         = Marshal.PtrToStructure(fileGroupDescriptorAPointer, typeof(FILEGROUPDESCRIPTORA));
                    FILEGROUPDESCRIPTORA fileGroupDescriptor = (FILEGROUPDESCRIPTORA)fileGroupDescriptorObject;

                    //create a new array to store file names in of the number of items in the file group descriptor
                    string[] fileNames = new string[fileGroupDescriptor.cItems];

                    //get the pointer to the first file descriptor
                    IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorAPointer + Marshal.SizeOf(fileGroupDescriptorAPointer));

                    //loop for the number of files acording to the file group descriptor
                    for (int fileDescriptorIndex = 0; fileDescriptorIndex < fileGroupDescriptor.cItems; fileDescriptorIndex++)
                    {
                        //marshal the pointer top the file descriptor as a FILEDESCRIPTORA struct and get the file name
                        FILEDESCRIPTORA fileDescriptor = (FILEDESCRIPTORA)Marshal.PtrToStructure(fileDescriptorPointer, typeof(FILEDESCRIPTORA));
                        fileNames[fileDescriptorIndex] = fileDescriptor.cFileName;

                        //move the file descriptor pointer to the next file descriptor
                        fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
                    }

                    //return the array of filenames
                    return(fileNames);
                }
                finally
                {
                    //free unmanaged memory pointer
                    Marshal.FreeHGlobal(fileGroupDescriptorAPointer);
                }

            case "FileGroupDescriptorW":
                //override the default handling of FileGroupDescriptorW which returns a
                //MemoryStream and instead return a string array of file names
                IntPtr fileGroupDescriptorWPointer = IntPtr.Zero;
                try
                {
                    //use the underlying IDataObject to get the FileGroupDescriptorW as a MemoryStream
                    MemoryStream fileGroupDescriptorStream = (MemoryStream)this._underlyingDataObject.GetData("FileGroupDescriptorW");
                    byte[]       fileGroupDescriptorBytes  = new byte[fileGroupDescriptorStream.Length];
                    fileGroupDescriptorStream.Read(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
                    fileGroupDescriptorStream.Close();

                    //copy the file group descriptor into unmanaged memory
                    fileGroupDescriptorWPointer = Marshal.AllocHGlobal(fileGroupDescriptorBytes.Length);
                    Marshal.Copy(fileGroupDescriptorBytes, 0, fileGroupDescriptorWPointer, fileGroupDescriptorBytes.Length);

                    //marshal the unmanaged memory to to FILEGROUPDESCRIPTORW struct
                    object fileGroupDescriptorObject         = Marshal.PtrToStructure(fileGroupDescriptorWPointer, typeof(FILEGROUPDESCRIPTORW));
                    FILEGROUPDESCRIPTORW fileGroupDescriptor = (FILEGROUPDESCRIPTORW)fileGroupDescriptorObject;

                    //create a new array to store file names in of the number of items in the file group descriptor
                    string[] fileNames = new string[fileGroupDescriptor.cItems];

                    //get the pointer to the first file descriptor
                    IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorWPointer + Marshal.SizeOf(fileGroupDescriptorWPointer));

                    //loop for the number of files acording to the file group descriptor
                    for (int fileDescriptorIndex = 0; fileDescriptorIndex < fileGroupDescriptor.cItems; fileDescriptorIndex++)
                    {
                        //marshal the pointer top the file descriptor as a FILEDESCRIPTORW struct and get the file name
                        FILEDESCRIPTORW fileDescriptor = (FILEDESCRIPTORW)Marshal.PtrToStructure(fileDescriptorPointer, typeof(FILEDESCRIPTORW));
                        fileNames[fileDescriptorIndex] = fileDescriptor.cFileName;

                        //move the file descriptor pointer to the next file descriptor
                        fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
                    }

                    //return the array of filenames
                    return(fileNames);
                }
                finally
                {
                    //free unmanaged memory pointer
                    Marshal.FreeHGlobal(fileGroupDescriptorWPointer);
                }

            case "FileContents":
                //override the default handling of FileContents which returns the
                //contents of the first file as a memory stream and instead return
                //a array of MemoryStreams containing the data to each file dropped

                //get the array of filenames which lets us know how many file contents exist
                string[] fileContentNames = (string[])this.GetData("FileGroupDescriptor");

                //create a MemoryStream array to store the file contents
                MemoryStream[] fileContents = new MemoryStream[fileContentNames.Length];

                //loop for the number of files acording to the file names
                for (int fileIndex = 0; fileIndex < fileContentNames.Length; fileIndex++)
                {
                    //get the data at the file index and store in array
                    fileContents[fileIndex] = this.GetData(format, fileIndex);
                }

                //return array of MemoryStreams containing file contents
                return(fileContents);
            }

            //use underlying IDataObject to handle getting of data
            return(this._underlyingDataObject.GetData(format, autoConvert));
        }