home *** CD-ROM | disk | FTP | other *** search
- //-------------------------------------------------------------
- // CDO.cs
- //
- // This implements the object that is responsible for transfering
- // data about nodes to the MMC.
- //-------------------------------------------------------------
- using System;
- using System.Runtime.InteropServices;
-
-
- namespace Microsoft.SampleMMC
- {
-
- public class CDO : IDataObject
- {
- private ushort m_cfDisplayName; // Clipboard format # for Display Name
- private ushort m_cfNodeType; // Clipboard format # for NodeType
- private ushort m_cfSZNodeType; // Clipboard format # for SZNodeType
- private ushort m_cfSnapinClsid; // Clipboard format # for SnapinClsid
-
- private CNode m_NodeData; // The node that this Data object is
- // responsible for
-
- //-------------------------------------------------
- // CDO
- //
- // The constructor is responsible for loading the about images
- // that will be displayed in the MMC
- //-------------------------------------------------
- public CDO(ref CNode initData)
- {
- // Set the Node this Data Object will be responsible for
- m_NodeData = initData;
-
- // Get the Clipboard Format Numbers for these various items.
- // MMC should have already registered these Clipboard Formats,
- // so this call just gives us the id assigned for each format.
-
- m_cfDisplayName = RegisterClipboardFormat("CCF_DISPLAY_NAME");
- m_cfNodeType = RegisterClipboardFormat("CCF_NODETYPE");
- m_cfSZNodeType = RegisterClipboardFormat("CCF_SZNODETYPE");
- m_cfSnapinClsid = RegisterClipboardFormat("CCF_SNAPIN_CLASSID");
- }// CDO
-
- //-------------------------------------------------
- // Node
- //
- // Provides access to the Data Object's Node
- //-------------------------------------------------
- public CNode Node
- {
- get
- {
- return m_NodeData;
- }
- }// Node
-
- //-------------------------------------------------
- // GetDataHere
- //
- // This function will send certain data to the MMC. Note
- // this function uses the "unsafe" context... we need to
- // send a pointer to a byte array to IStream:Write, and this
- // is the easiest way to do it.
- //-------------------------------------------------
- public unsafe void GetDataHere(ref FORMATETC pFormatEtc, ref STGMEDIUM pMedium)
- {
- IStream pStream=null;
- byte[] bDataToSend;
- int iLengthOfData;
- uint iDataSent=0;
-
- try
- {
- // We'll send this array if we don't know what to send
- byte[] Nothing = {0x0, 0x0};
-
- ushort cf = (ushort)pFormatEtc.cfFormat;
-
- CreateStreamOnHGlobal(pMedium.hGlobal, 0, out pStream );
-
- // If we couldn't open a global handle....
- if (pStream == null)
- {
- throw new ExternalException("CDO::GetDataHere - Fail on CreateStreamOnHGlobal");
- }
-
- Marshal.AddRef(Marshal.GetIUnknownForObject(pStream));
-
- // Let's determine what data we need to send.
- if (cf == m_cfDisplayName)
- bDataToSend = m_NodeData.bDisplayName;
- else if (cf == m_cfNodeType)
- bDataToSend= m_NodeData.bGuid;
- else if (cf == m_cfSZNodeType)
- bDataToSend = Nothing;
- else if (cf == m_cfSnapinClsid)
- {
- // The GUID for this snapin
- byte[] CLSID = {9,4,0xb,9,0xd, 5, 1, 0xf,
- 0xc, 8, 7, 4,
- 4, 0xd, 0xa, 0,
- 0xb, 0xc, 1, 3,
- 0xf, 0xd, 0xa, 9, 4, 0xc, 0xb, 0xf, 7, 2, 0xd, 0xe};
- bDataToSend = CLSID;
-
- }
- else // We don't know what to send
- bDataToSend = Nothing;
-
- iLengthOfData = bDataToSend.Length;
-
- // NOTE: the use of pointers is only possible because the function was marked
- // unsafe. Also, pData will only point to a valid address inside the "fixed"
- // block... outside of the "fixed" block the GC could move our memory around, resulting
- // in pData pointing to garbage.
- fixed(byte* pData = bDataToSend)
- {
- pStream.Write((int)pData, (uint)iLengthOfData, out iDataSent);
- }
-
- // Close/Flush the stream
- Marshal.ReleaseComObject(pStream);
-
- // We'll create a object so unmanaged code won't try to free this memory.
- pMedium.pUnkForRelease = new Object();
-
- }
- catch(Exception)
- {
- if (pStream != null)
- Marshal.ReleaseComObject(pStream);
- }
- }// GetDataHere
-
- //-------------------------------------------------
- // Other IDataObject Methods
- //
- // We don't need to implement any of these other
- // methods, so if they are called, we'll just return
- // E_NOTIMPL
- //-------------------------------------------------
-
- public void GetData(ref FORMATETC a, ref STGMEDIUM b)
- {
- throw new ExternalException("", HRESULT.E_NOTIMPL);
- }// GetData
-
- public void QueryGetData(ref FORMATETC a)
- {
- throw new ExternalException("", HRESULT.E_NOTIMPL);
- }// QueryGetData
-
- public void GetCanonicalFormatEtc(ref FORMATETC a, out FORMATETC b)
- {
- throw new ExternalException("", HRESULT.E_NOTIMPL);
- }// GetCanonicalFormatEtc
-
- public void SetData(ref FORMATETC a, ref userFLAG_STGMEDIUM b, int c)
- {
- throw new ExternalException("", HRESULT.E_NOTIMPL);
- }// SetData
-
- public void EnumFormatEtc(uint a, out Object b)
- {
- throw new ExternalException("", HRESULT.E_NOTIMPL);
- }// EnumFormatEtc
-
- public void DAdvise(ref FORMATETC a, uint b, ref Object c, out uint d)
- {
- throw new ExternalException("", HRESULT.E_NOTIMPL);
- }// DAdvise
-
- public void DUnadvise(uint a)
- {
- throw new ExternalException("", HRESULT.E_NOTIMPL);
- }// DUnadvise
-
- public void EnumDAdvise(out Object a)
- {
- throw new ExternalException("", HRESULT.E_NOTIMPL);
- }// EnumDAdvise
-
- //-------------------------------------------------
- // We need to import the Win32 API calls used to deal with
- // clipboard formats and HGlobal streams.
- //-------------------------------------------------
-
- [DllImport("ole32.dll")]
- public static extern int CreateStreamOnHGlobal(int hGlobal, int fDeleteOnRelease, out IStream ppstm);
-
- // All the MMC stuff is done in Unicode, which is why we're using
- // that character set here
-
- [DllImport("user32.dll", CharSet=CharSet.Unicode)]
- public static extern ushort RegisterClipboardFormat(String format);
-
- }// class CDO
- }// namespace Microsoft.SampleMMC
-