Example #1
0
        public static IEnumerable <File> Decode(System.Windows.Forms.IDataObject data)
        {
            IntPtr fileGroupDescriptorWPointer = IntPtr.Zero;

            try
            {
                //use the underlying IDataObject to get the FileGroupDescriptorW as a MemoryStream
                MemoryStream fileGroupDescriptorStream = (MemoryStream)data.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(NativeMethods.FILEGROUPDESCRIPTORW));
                NativeMethods.FILEGROUPDESCRIPTORW fileGroupDescriptor = (NativeMethods.FILEGROUPDESCRIPTORW)fileGroupDescriptorObject;

                //create a new array to store file names in of the number of items in the file group descriptor
                List <File> files = new List <File>();

                //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
                    NativeMethods.FILEDESCRIPTORW fileDescriptor = (NativeMethods.FILEDESCRIPTORW)Marshal.PtrToStructure(fileDescriptorPointer, typeof(NativeMethods.FILEDESCRIPTORW));
                    File file = new File();
                    file.Name = fileDescriptor.cFileName;
                    file.Size = (long)fileDescriptor.nFileSizeLow + ((long)fileDescriptor.nFileSizeHigh << 32);
                    files.Add(file);

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

                int index = 0;
                foreach (File f in files)
                {
                    f.Content = GetData(data, FileContents, index++);
                }

                //return the array of files
                return(files);
            }
            finally
            {
                //free unmanaged memory pointer
                Marshal.FreeHGlobal(fileGroupDescriptorWPointer);
            }
        }
        public static string[] ReadFileGroupDescriptorW(MemoryStream ms)
        {
            if (ms == null)
            {
                return(new string[0]);
            }
            var arr = ms.ToArray();

            ms.Dispose();

            // use the underlying IDataObject to get the FileGroupDescriptorW as a MemoryStream
            // byte[] arr = new byte[ms.Length];
            // ms.Read(arr, 0, arr.Length);
            // ms.Close();
            //
            GCHandle hArr = GCHandle.Alloc(arr, GCHandleType.Pinned);

            try {
                IntPtr fileGroupDescriptorWPointer = hArr.AddrOfPinnedObject();
                var    fileGroupDescriptor         = Marshal.PtrToStructure <NativeMethods.FILEGROUPDESCRIPTORW>(fileGroupDescriptorWPointer);

                var      cItems    = fileGroupDescriptor.cItems;
                string[] fileNames = new string[cItems];

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

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

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

                return(fileNames);
            } finally {
                hArr.Free();
            }
        }
Example #3
0
        /// <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.Forms.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(NativeMethods.FILEGROUPDESCRIPTORA));
                    NativeMethods.FILEGROUPDESCRIPTORA fileGroupDescriptor = (NativeMethods.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
                        NativeMethods.FILEDESCRIPTORA fileDescriptor = (NativeMethods.FILEDESCRIPTORA)Marshal.PtrToStructure(fileDescriptorPointer, typeof(NativeMethods.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(NativeMethods.FILEGROUPDESCRIPTORW));
                    NativeMethods.FILEGROUPDESCRIPTORW fileGroupDescriptor = (NativeMethods.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
                        NativeMethods.FILEDESCRIPTORW fileDescriptor = (NativeMethods.FILEDESCRIPTORW)Marshal.PtrToStructure(fileDescriptorPointer, typeof(NativeMethods.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));
        }
Example #4
0
        static string[] GetFileGroupDescriptor(System.Windows.Forms.IDataObject _data)
        {
            MemoryStream fileGroupDescriptorStream = (MemoryStream)_data.GetData("FileGroupDescriptor");

            if (fileGroupDescriptorStream != null)
            {
                IntPtr fileGroupDescriptorAPointer = IntPtr.Zero;
                try
                {
                    byte[] fileGroupDescriptorBytes = new byte[fileGroupDescriptorStream.Length];

                    fileGroupDescriptorStream.Read(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
                    fileGroupDescriptorStream.Close();

                    fileGroupDescriptorAPointer = Marshal.AllocHGlobal(fileGroupDescriptorBytes.Length);
                    Marshal.Copy(fileGroupDescriptorBytes, 0, fileGroupDescriptorAPointer, fileGroupDescriptorBytes.Length);

                    object fileGroupDescriptorObject = Marshal.PtrToStructure(fileGroupDescriptorAPointer, typeof(NativeMethods.FILEGROUPDESCRIPTORA));
                    NativeMethods.FILEGROUPDESCRIPTORA fileGroupDescriptor = (NativeMethods.FILEGROUPDESCRIPTORA)fileGroupDescriptorObject;

                    string[] fileNames = new string[fileGroupDescriptor.cItems];

                    IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorAPointer + Marshal.SizeOf(fileGroupDescriptor.cItems));

                    for (int fileDescriptorIndex = 0; fileDescriptorIndex < fileGroupDescriptor.cItems; fileDescriptorIndex++)
                    {
                        NativeMethods.FILEDESCRIPTORA fileDescriptor = (NativeMethods.FILEDESCRIPTORA)Marshal.PtrToStructure(fileDescriptorPointer, typeof(NativeMethods.FILEDESCRIPTORA));
                        fileNames[fileDescriptorIndex] = fileDescriptor.cFileName;

                        fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
                    }

                    return(fileNames);
                }
                finally
                {
                    Marshal.FreeHGlobal(fileGroupDescriptorAPointer);
                }
            }

            fileGroupDescriptorStream = (MemoryStream)_data.GetData("FileGroupDescriptorW");
            if (fileGroupDescriptorStream != null)
            {
                IntPtr fileGroupDescriptorWPointer = IntPtr.Zero;
                try
                {
                    byte[] fileGroupDescriptorBytes = new byte[fileGroupDescriptorStream.Length];
                    int    length = fileGroupDescriptorStream.Read(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
                    fileGroupDescriptorStream.Close();

                    fileGroupDescriptorWPointer = Marshal.AllocHGlobal(length);
                    Marshal.Copy(fileGroupDescriptorBytes, 0, fileGroupDescriptorWPointer, length);

                    object fileGroupDescriptorObject = Marshal.PtrToStructure(fileGroupDescriptorWPointer, typeof(NativeMethods.FILEGROUPDESCRIPTORW));
                    NativeMethods.FILEGROUPDESCRIPTORW fileGroupDescriptor = (NativeMethods.FILEGROUPDESCRIPTORW)fileGroupDescriptorObject;

                    string[] fileNames = new string[fileGroupDescriptor.cItems];

                    IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorWPointer + Marshal.SizeOf(fileGroupDescriptor.cItems));

                    for (int fileDescriptorIndex = 0; fileDescriptorIndex < fileGroupDescriptor.cItems; fileDescriptorIndex++)
                    {
                        NativeMethods.FILEDESCRIPTORW fileDescriptor = (NativeMethods.FILEDESCRIPTORW)Marshal.PtrToStructure(fileDescriptorPointer, typeof(NativeMethods.FILEDESCRIPTORW));
                        fileNames[fileDescriptorIndex] = fileDescriptor.cFileName;

                        fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
                    }

                    return(fileNames);
                }
                finally
                {
                    Marshal.FreeHGlobal(fileGroupDescriptorWPointer);
                }
            }

            return(null);
        }
Example #5
0
        public object GetData(string format, bool autoConvert)
        {
            switch (format)
            {
            case "FileGroupDescriptor":
                IntPtr fileGroupDescriptorAPointer = IntPtr.Zero;
                try
                {
                    MemoryStream fileGroupDescriptorStream = (MemoryStream)this.underlyingDataObject.GetData("FileGroupDescriptor", autoConvert);

                    byte[] fileGroupDescriptorBytes = new byte[fileGroupDescriptorStream.Length];
                    fileGroupDescriptorStream.Read(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
                    fileGroupDescriptorStream.Close();

                    fileGroupDescriptorAPointer = Marshal.AllocHGlobal(fileGroupDescriptorBytes.Length);
                    Marshal.Copy(fileGroupDescriptorBytes, 0, fileGroupDescriptorAPointer, fileGroupDescriptorBytes.Length);

                    object fileGroupDescriptorObject = Marshal.PtrToStructure(fileGroupDescriptorAPointer, typeof(NativeMethods.FILEGROUPDESCRIPTORA));
                    NativeMethods.FILEGROUPDESCRIPTORA fileGroupDescriptor = (NativeMethods.FILEGROUPDESCRIPTORA)fileGroupDescriptorObject;

                    string[] fileNames = new string[fileGroupDescriptor.cItems];

                    IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorAPointer + Marshal.SizeOf(fileGroupDescriptor.cItems));

                    for (int fileDescriptorIndex = 0; fileDescriptorIndex < fileGroupDescriptor.cItems; fileDescriptorIndex++)
                    {
                        NativeMethods.FILEDESCRIPTORA fileDescriptor = (NativeMethods.FILEDESCRIPTORA)Marshal.PtrToStructure(fileDescriptorPointer, typeof(NativeMethods.FILEDESCRIPTORA));
                        fileNames[fileDescriptorIndex] = fileDescriptor.cFileName;

                        fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
                    }

                    return(fileNames);
                }
                finally
                {
                    Marshal.FreeHGlobal(fileGroupDescriptorAPointer);
                }

            case "FileGroupDescriptorW":
                IntPtr fileGroupDescriptorWPointer = IntPtr.Zero;
                try
                {
                    MemoryStream fileGroupDescriptorStream = (MemoryStream)this.underlyingDataObject.GetData("FileGroupDescriptorW");
                    byte[]       fileGroupDescriptorBytes  = new byte[fileGroupDescriptorStream.Length];
                    fileGroupDescriptorStream.Read(fileGroupDescriptorBytes, 0, fileGroupDescriptorBytes.Length);
                    fileGroupDescriptorStream.Close();

                    fileGroupDescriptorWPointer = Marshal.AllocHGlobal(fileGroupDescriptorBytes.Length);
                    Marshal.Copy(fileGroupDescriptorBytes, 0, fileGroupDescriptorWPointer, fileGroupDescriptorBytes.Length);

                    object fileGroupDescriptorObject = Marshal.PtrToStructure(fileGroupDescriptorWPointer, typeof(NativeMethods.FILEGROUPDESCRIPTORW));
                    NativeMethods.FILEGROUPDESCRIPTORW fileGroupDescriptor = (NativeMethods.FILEGROUPDESCRIPTORW)fileGroupDescriptorObject;

                    string[] fileNames = new string[fileGroupDescriptor.cItems];

                    IntPtr fileDescriptorPointer = (IntPtr)((int)fileGroupDescriptorWPointer + Marshal.SizeOf(fileGroupDescriptor.cItems));

                    for (int fileDescriptorIndex = 0; fileDescriptorIndex < fileGroupDescriptor.cItems; fileDescriptorIndex++)
                    {
                        NativeMethods.FILEDESCRIPTORW fileDescriptor = (NativeMethods.FILEDESCRIPTORW)Marshal.PtrToStructure(fileDescriptorPointer, typeof(NativeMethods.FILEDESCRIPTORW));
                        fileNames[fileDescriptorIndex] = fileDescriptor.cFileName;

                        fileDescriptorPointer = (IntPtr)((int)fileDescriptorPointer + Marshal.SizeOf(fileDescriptor));
                    }

                    return(fileNames);
                }
                finally
                {
                    Marshal.FreeHGlobal(fileGroupDescriptorWPointer);
                }

            case "FileContents":
                string fgdFormatName;
                if (GetDataPresent("FileGroupDescriptorW"))
                {
                    fgdFormatName = "FileGroupDescriptorW";
                }
                else if (GetDataPresent("FileGroupDescriptor"))
                {
                    fgdFormatName = "FileGroupDescriptor";
                }
                else
                {
                    return(null);
                }

                string[] fileContentNames = (string[])this.GetData(fgdFormatName);

                MemoryStream[] fileContents = new MemoryStream[fileContentNames.Length];

                for (int fileIndex = 0; fileIndex < fileContentNames.Length; fileIndex++)
                {
                    fileContents[fileIndex] = this.GetData(format, fileIndex);
                }

                return(fileContents);
            }

            return(this.underlyingDataObject.GetData(format, autoConvert));
        }
Example #6
0
        /// <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
                    //FIX FROM - https://stackoverflow.com/questions/27173844/accessviolationexception-after-copying-a-file-from-inside-a-zip-archive-to-the-c
                    int ITEMCOUNT = Marshal.ReadInt32(fileGroupDescriptorAPointer);

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

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

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

                        //move the file descriptor pointer to the next file descriptor
                        fileDescriptorPointer = (IntPtr)((long)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
                    //FIX FROM - https://stackoverflow.com/questions/27173844/accessviolationexception-after-copying-a-file-from-inside-a-zip-archive-to-the-c
                    int ITEMCOUNT = Marshal.ReadInt32(fileGroupDescriptorWPointer);

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

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

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

                        //move the file descriptor pointer to the next file descriptor
                        fileDescriptorPointer = (IntPtr)((long)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
                //
                // FILECONTENTS requires a companion FILEGROUPDESCRIPTOR to be
                // available so we bail out if we don't find one in the data object.

                string fgdFormatName;
                if (GetDataPresent("FileGroupDescriptorW"))
                {
                    fgdFormatName = "FileGroupDescriptorW";
                }
                else if (GetDataPresent("FileGroupDescriptor"))
                {
                    fgdFormatName = "FileGroupDescriptor";
                }
                else
                {
                    return(null);
                }
                //get the array of filenames which lets us know how many file contents exist
                string[] fileContentNames = (string[])this.GetData(fgdFormatName);

                //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));
        }