Beispiel #1
0
        /// <summary>
        /// Copy a global memory block into a file
        /// </summary>
        /// <param name="hGlobal">global memory block</param>
        /// <param name="destFileName">file to copy global memory into</param>
        private void CopyHGLOBALToFile(IntPtr hGlobal, string destFileName)
        {
            HGlobalLock globalMem = new HGlobalLock(hGlobal);

            using (globalMem)
            {
                FileStream destination =
                    new FileStream(destFileName, FileMode.Create, FileAccess.ReadWrite);
                using (destination)
                {
                    // use Win32 WriteFile so we can blast the entire unmanaged memory
                    // block in a single call (if we wanted to use managed file io
                    // methods we would have to copy the entire memory block into
                    // unmanaged memory first)
                    uint bytesWritten;
                    bool success = Kernel32.WriteFile(
                        destination.SafeFileHandle, globalMem.Memory, globalMem.Size.ToUInt32(),
                        out bytesWritten, IntPtr.Zero);
                    if (!success)
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error(),
                                                 "Error occured attempting to write file: "
                                                 + destination.Name);
                    }
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Create a cloned copy of the the passed storage medium. This method works via
        /// a combination of actually copying underling data and incrementing reference
        /// counts on embedded objects.
        /// </summary>
        /// <param name="stgmIn">storage medium in</param>
        /// <param name="stgmOut">storage medium out</param>
        /// <returns>HRESULT.S_OK if the medium was successfully cloned, various
        /// OLE error codes if an error occurs during the clone </returns>
        private int CloneStgMedium(STGMEDIUM stgmIn, ref STGMEDIUM stgmOut)
        {
            // copy storage type
            stgmOut.tymed = stgmIn.tymed;

            // copy or add ref count to the actual data
            switch (stgmIn.tymed)
            {
            // global memory blocks get copied
            case TYMED.HGLOBAL:
                using (HGlobalLock input = new HGlobalLock(stgmIn.contents))
                    stgmOut.contents = input.Clone();
                break;

            // COM interfaces get copied w/ their ref-count incremented
            case TYMED.ISTREAM:
            case TYMED.ISTORAGE:
                stgmOut.contents = stgmIn.contents;
                Marshal.AddRef(stgmOut.contents);
                break;

            // don't know how to clone other storage medium types (return error)
            case TYMED.ENHMF:
            case TYMED.FILE:
            case TYMED.GDI:
            case TYMED.MFPICT:
            default:
                return(DV_E.TYMED);
            }

            // copy pUnkForRelease and add a reference count on it if there is one
            stgmOut.pUnkForRelease = stgmIn.pUnkForRelease;
            if (stgmOut.pUnkForRelease != IntPtr.Zero)
            {
                Marshal.AddRef(stgmOut.pUnkForRelease);
            }

            // return success
            return(HRESULT.S_OK);
        }
        /// <summary>
        /// Utility function to extract an array of file contents file descriptors from
        /// an IDataObject instnace
        /// </summary>
        /// <param name="dataObject">data object to extract descriptors from</param>
        /// <returns>array of file descriptors</returns>
        public static FileDescriptor[] GetFileDescriptors(IDataObject dataObject)
        {
            // Use an OleDataObject
            OleDataObject oleDataObject = OleDataObject.CreateFrom(dataObject);

            if (oleDataObject == null)
            {
                const string message = "DataObject not valid for FileContents!";
                Debug.Fail(message);
                throw
                    new InvalidOperationException(message);
            }

            // Try to get the data as FileGroupDescriptorW then try to get it
            // as FileGroupDescriptor
            bool bFileNameIsWide;
            OleStgMediumHGLOBAL stgMedium = (OleStgMediumHGLOBAL)oleDataObject.GetData(
                DataFormatsEx.FileGroupDescriptorWFormat, TYMED.HGLOBAL);

            if (stgMedium != null)
            {
                bFileNameIsWide = true;
            }
            else
            {
                stgMedium = (OleStgMediumHGLOBAL)oleDataObject.GetData(
                    DataFormatsEx.FileGroupDescriptorFormat, TYMED.HGLOBAL);

                if (stgMedium != null)
                {
                    bFileNameIsWide = false;
                }
                else
                {
                    const string message = "File group descriptor not available!";
                    Debug.Fail(message);
                    throw
                        new InvalidOperationException(message);
                }
            }


            // Copy the descriptors
            using ( stgMedium )
            {
                using (HGlobalLock globalMem = new HGlobalLock(stgMedium.Handle))
                {
                    // get a pointer to the count
                    IntPtr pCount = globalMem.Memory;

                    // determine the number of file descriptors
                    Int32 count = Marshal.ReadInt32(pCount);

                    // get a pointer to the descriptors
                    IntPtr pDescriptors =
                        new IntPtr(globalMem.Memory.ToInt32() + Marshal.SizeOf(count));

                    // allocate the array of structures that will be returned
                    FileDescriptor[] descriptors = new FileDescriptor[count];

                    // determine the sizes of the various data elements
                    const int FILENAME_BUFFER_SIZE = 260;
                    int       headerSize           = Marshal.SizeOf(typeof(FILEDESCRIPTOR_HEADER));
                    int       fileNameSize         = bFileNameIsWide ? FILENAME_BUFFER_SIZE * 2 : FILENAME_BUFFER_SIZE;
                    int       totalSize            = headerSize + fileNameSize;

                    // iterate through the memory block copying the FILEDESCRIPTOR structures
                    for (int i = 0; i < count; i++)
                    {
                        // determine the addresses of the various data elements
                        IntPtr pAddr         = new IntPtr(pDescriptors.ToInt32() + (i * totalSize));
                        IntPtr pFileNameAddr = new IntPtr(pAddr.ToInt32() + headerSize);

                        // copy the header
                        descriptors[i].header = (FILEDESCRIPTOR_HEADER)
                                                Marshal.PtrToStructure(pAddr, typeof(FILEDESCRIPTOR_HEADER));

                        // copy the file name (use Unicode or Ansi depending upon descriptor type)
                        if (bFileNameIsWide)
                        {
                            descriptors[i].fileName = Marshal.PtrToStringUni(pFileNameAddr);
                        }
                        else
                        {
                            descriptors[i].fileName = Marshal.PtrToStringAnsi(pFileNameAddr);
                        }
                    }

                    // return the descriptors
                    return(descriptors);
                }
            }
        }