internal static string[] GetFilenamesUnicode(NativeMethods.IDataObject data) { IntPtr fgdaPtr = IntPtr.Zero; try { //Define FileGroupDescriptorW format FORMATETC format = new FORMATETC(); format.cfFormat = (short)System.Windows.Forms.DataFormats.GetFormat("FileGroupDescriptorW").Id; format.dwAspect = DVASPECT.DVASPECT_CONTENT; format.lindex = -1; format.ptd = IntPtr.Zero; format.tymed = TYMED.TYMED_ISTREAM | TYMED.TYMED_ISTORAGE | TYMED.TYMED_HGLOBAL; //Query if format exists in data if (data.QueryGetData(format) != NativeMethods.S_OK) { return(null); } //Get data into medium STGMEDIUM medium = new STGMEDIUM(); data.GetData(format, out medium); //Read medium into string byte[] bytes; using (MemoryStream stream = new MemoryStream()) { DataObjectHelper.ReadMediumIntoStream(medium, stream); bytes = new byte[stream.Length]; stream.Seek(0, SeekOrigin.Begin); stream.Read(bytes, 0, bytes.Length); } //Copy the file group descriptor into unmanaged memory fgdaPtr = Marshal.AllocHGlobal(bytes.Length); if (fgdaPtr == IntPtr.Zero) { throw new OutOfMemoryException(); } Marshal.Copy(bytes, 0, fgdaPtr, bytes.Length); //Marshal the unmanaged memory to a FILEGROUPDESCRIPTORA struct object fgdObj = Marshal.PtrToStructure(fgdaPtr, typeof(NativeMethods.FILEGROUPDESCRIPTORW)); NativeMethods.FILEGROUPDESCRIPTORW fgd = (NativeMethods.FILEGROUPDESCRIPTORW)fgdObj; //Create an array to store file names string[] filenames = new string[fgd.cItems]; //Get the pointer to the first file descriptor IntPtr fdPtr = (IntPtr)((int)fgdaPtr + Marshal.SizeOf(fgdaPtr)); //Loop for the number of files acording to the file group descriptor for (int fdIndex = 0; fdIndex < fgd.cItems; fdIndex++) { //Marshal the pointer to the file descriptor as a FILEDESCRIPTORW struct object fdObj = Marshal.PtrToStructure(fdPtr, typeof(NativeMethods.FILEDESCRIPTORW)); NativeMethods.FILEDESCRIPTORW fd = (NativeMethods.FILEDESCRIPTORW)fdObj; //Get filename of file descriptor and put in array filenames[fdIndex] = fd.cFileName; //Move the file descriptor pointer to the next file descriptor fdPtr = (IntPtr)((int)fdPtr + Marshal.SizeOf(fd)); } return(filenames); } finally { Marshal.FreeHGlobal(fgdaPtr); } }
internal static string[] GetFilenamesUnicode(NativeMethods.IDataObject data) { log.Debug("Getting filenames (Unicode)"); IntPtr ptrFgd = IntPtr.Zero; STGMEDIUM medium = new STGMEDIUM(); try { //Define FileGroupDescriptorW format FORMATETC format = new FORMATETC(); format.cfFormat = (short)GetClipboardFormat("FileGroupDescriptorW"); format.dwAspect = DVASPECT.DVASPECT_CONTENT; format.lindex = -1; format.ptd = IntPtr.Zero; format.tymed = TYMED.TYMED_ISTREAM | TYMED.TYMED_ISTORAGE | TYMED.TYMED_HGLOBAL; //Query if format exists in data if (data.QueryGetData(format) != NativeMethods.S_OK) { log.Debug("No filenames found"); return(null); } //Get data into medium int retVal = data.GetData(format, out medium); if (retVal != NativeMethods.S_OK) { throw new Exception(string.Format("Could not get FileGroupDescriptorW format. Error returned: {0}", retVal)); } //Read medium into byte array log.Debug("Reading structure into memory stream"); byte[] bytes; using (MemoryStream stream = new MemoryStream()) { DataObjectHelper.ReadMediumIntoStream(medium, stream); bytes = new byte[stream.Length]; stream.Seek(0, SeekOrigin.Begin); stream.Read(bytes, 0, bytes.Length); } //Copy byte array into unmanaged memory log.Debug("Copying structure into unmanaged memory"); ptrFgd = Marshal.AllocHGlobal(bytes.Length); Marshal.Copy(bytes, 0, ptrFgd, bytes.Length); //Marshal unmanaged memory to a FILEGROUPDESCRIPTORW struct log.Debug("Marshaling unmanaged memory into FILEGROUPDESCRIPTORW struct"); NativeMethods.FILEGROUPDESCRIPTORW fgd = (NativeMethods.FILEGROUPDESCRIPTORW)Marshal.PtrToStructure(ptrFgd, typeof(NativeMethods.FILEGROUPDESCRIPTORW)); log.Debug(string.Format("Files found: {0}", fgd.cItems)); //Create an array to store file names string[] filenames = new string[fgd.cItems]; //Get the pointer to the first file descriptor IntPtr ptrFd = IntPtr.Add(ptrFgd, sizeof(uint)); //Loop for the number of files acording to the file group descriptor for (int fdIndex = 0; fdIndex < fgd.cItems; fdIndex++) { log.DebugFormat("Getting filename {0}", fdIndex); //Marshal pointer to a FILEDESCRIPTORW struct NativeMethods.FILEDESCRIPTORW fd = (NativeMethods.FILEDESCRIPTORW)Marshal.PtrToStructure(ptrFd, typeof(NativeMethods.FILEDESCRIPTORW)); //Get filename of file descriptor and put in array filenames[fdIndex] = fd.cFileName; //Move the file descriptor pointer to the next file descriptor ptrFd = IntPtr.Add(ptrFd, Marshal.SizeOf(fd)); } log.DebugFormat("Filenames found: {0}", string.Join(", ", filenames)); return(filenames); } finally { //Release all unmanaged objects Marshal.FreeHGlobal(ptrFgd); if (medium.pUnkForRelease == null) { NativeMethods.ReleaseStgMedium(ref medium); } } }