unsafe HRESULT SaveHdropToHandle(ref IntPtr handle, string[] files) { int size = sizeof(Shell32.DROPFILES); foreach (var f in files) { size += (f.Length + 1) * 2; } size += 2; // Terminal null var hg = Kernel32.GlobalReAlloc(handle, size, Kernel32.GMEM.GMEM_MOVEABLE); if (hg.IsNull) { return(HRESULT.E_OUTOFMEMORY); } var lc = Kernel32.GlobalLock(hg); Shell32.DROPFILES *df = (Shell32.DROPFILES *)lc.ToPointer(); df->pFiles = (uint)files.Length; df->fNC = false; df->fWide = false; char *ptr = ((char *)df) + sizeof(Shell32.DROPFILES); foreach (var f in files) { fixed(char *str = f) { Buffer.MemoryCopy(str, ptr, f.Length + 2, f.Length + 2); ptr[f.Length] = '\0'; ptr += f.Length + 1; } *ptr = '\0'; } Kernel32.GlobalUnlock(hg); return(HRESULT.S_OK); }
private unsafe HRESULT SaveFileListToHandle(IntPtr handle, string[] files) { if (files is null || files.Length == 0) { return(HRESULT.S_OK); } if (handle == IntPtr.Zero) { return(HRESULT.E_INVALIDARG); } // CF_HDROP consists of a DROPFILES struct followed by an list of strings // including the terminating null character. An additional null character // is appended to the final string to terminate the array. // E.g. if the files c:\temp1.txt and c:\temp2.txt are being transferred, // the character array is: "c:\temp1.txt\0c:\temp2.txt\0\0" // Determine the size of the data structure. uint sizeInBytes = (uint)sizeof(Shell32.DROPFILES); for (int i = 0; i < files.Length; i++) { sizeInBytes += ((uint)files[i].Length + 1) * 2; } sizeInBytes += 2; // Allocate the Win32 memory IntPtr newHandle = Kernel32.GlobalReAlloc( handle, sizeInBytes, Kernel32.GMEM.MOVEABLE | Kernel32.GMEM.DDESHARE); if (newHandle == IntPtr.Zero) { return(HRESULT.E_OUTOFMEMORY); } IntPtr basePtr = Kernel32.GlobalLock(newHandle); if (basePtr == IntPtr.Zero) { return(HRESULT.E_OUTOFMEMORY); } // Write out the DROPFILES struct. Shell32.DROPFILES *pDropFiles = (Shell32.DROPFILES *)basePtr; pDropFiles->pFiles = (uint)sizeof(Shell32.DROPFILES); pDropFiles->pt = Point.Empty; pDropFiles->fNC = BOOL.FALSE; pDropFiles->fWide = BOOL.TRUE; char *dataPtr = (char *)(basePtr + (int)pDropFiles->pFiles); // Write out the strings. for (int i = 0; i < files.Length; i++) { int bytesToCopy = files[i].Length * 2; fixed(char *pFile = files[i]) { Buffer.MemoryCopy(pFile, dataPtr, bytesToCopy, bytesToCopy); } dataPtr = (char *)((IntPtr)dataPtr + bytesToCopy); *dataPtr = '\0'; dataPtr++; } *dataPtr = '\0'; dataPtr++; Kernel32.GlobalUnlock(newHandle); return(HRESULT.S_OK); }