home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / oledlgs1.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  39KB  |  1,472 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_OLE2_SEG
  14. #pragma code_seg(AFX_OLE2_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. UINT CALLBACK
  25. AfxOleHookProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  26.  
  27. ////////////////////////////////////////////////////////////////////////////
  28. // implementation helpers
  29.  
  30. BOOL AFXAPI _AfxOlePropertiesEnabled()
  31. {
  32.     // edit properties is enabled if there is a handler
  33.     //  for ID_OLE_EDIT_PROPERTIES
  34.     AFX_CMDHANDLERINFO info;
  35.  
  36.     // check main window first
  37.     CWnd* pWnd = AfxGetMainWnd();
  38.     if (pWnd != NULL && pWnd->OnCmdMsg(ID_OLE_EDIT_PROPERTIES, CN_COMMAND, NULL, &info))
  39.         return TRUE;
  40.  
  41.     // check app last
  42.     return AfxGetApp()->OnCmdMsg(ID_OLE_EDIT_PROPERTIES, CN_COMMAND, NULL, &info);
  43. }
  44.  
  45. SCODE _AfxParseDisplayName(LPMONIKER lpmk, LPBC lpbc, LPTSTR lpszRemainder,
  46.     ULONG* cchEaten, LPMONIKER* plpmkOut)
  47. {
  48.     USES_CONVERSION;
  49.  
  50.     ASSERT(lpmk != NULL);
  51.     ASSERT(AfxIsValidString(lpszRemainder));
  52.     ASSERT(cchEaten != NULL);
  53.     ASSERT(plpmkOut != NULL);
  54.  
  55.     SCODE sc;
  56.     if (lpbc != NULL)
  57.     {
  58.         // ask moniker to parse the display name itself
  59.         sc = lpmk->ParseDisplayName(lpbc, NULL, T2OLE(lpszRemainder), cchEaten,
  60.             plpmkOut);
  61.     }
  62.     else
  63.     {
  64.         // skip leading delimiters
  65.         int cEaten = 0;
  66.         LPTSTR lpszSrc = lpszRemainder;
  67.         while (*lpszSrc != '\0' && (*lpszSrc == '\\' || *lpszSrc == '/' ||
  68.             *lpszSrc == ':' || *lpszSrc == '!' || *lpszSrc == '['))
  69.         {
  70.             if (_istlead(*lpszSrc))
  71.                 ++lpszSrc, ++cEaten;
  72.             ++lpszSrc;
  73.             ++cEaten;
  74.         }
  75.  
  76.         // parse next token in lpszRemainder
  77.         TCHAR szItemName[_MAX_PATH];
  78.         LPTSTR lpszDest = szItemName;
  79.         while (*lpszSrc != '\0' && *lpszSrc != '\\' && *lpszSrc != '/' &&
  80.             *lpszSrc != ':' && *lpszSrc != '!' && *lpszSrc != '[' &&
  81.             cEaten < _MAX_PATH-1)
  82.         {
  83.             if (_istlead(*lpszSrc))
  84.                 *lpszDest++ = *lpszSrc++, ++cEaten;
  85.             *lpszDest++ = *lpszSrc++;
  86.             ++cEaten;
  87.         }
  88.         *cchEaten = cEaten;
  89.         sc = CreateItemMoniker(OLESTDDELIMOLE, T2COLE(szItemName), plpmkOut);
  90.     }
  91.  
  92.     return sc;
  93. }
  94.  
  95. ////////////////////////////////////////////////////////////////////////////
  96. // COleUILinkInfo
  97.  
  98. COleUILinkInfo::COleUILinkInfo(COleDocument* pDocument)
  99. {
  100.     ASSERT(pDocument == NULL ||
  101.         pDocument->IsKindOf(RUNTIME_CLASS(COleDocument)));
  102.     m_pDocument = pDocument;
  103.     m_pSelectedItem = NULL;
  104.     m_pos = NULL;
  105.     m_bUpdateLinks = FALSE;
  106.     m_bUpdateEmbeddings = FALSE;
  107. }
  108.  
  109. STDMETHODIMP_(ULONG) COleUILinkInfo::AddRef()
  110. {
  111.     return 0;
  112. }
  113.  
  114. STDMETHODIMP_(ULONG) COleUILinkInfo::Release()
  115. {
  116.     return 0;
  117. }
  118.  
  119. STDMETHODIMP COleUILinkInfo::QueryInterface(
  120.     REFIID, LPVOID*)
  121. {
  122.     return E_NOTIMPL;
  123. }
  124.  
  125. STDMETHODIMP_(DWORD) COleUILinkInfo::GetNextLink(
  126.     DWORD dwLink)
  127. {
  128.     ASSERT(m_pDocument != NULL);
  129.     if (dwLink == 0)
  130.     {
  131.         // start enumerating from the beginning
  132.         m_pos = m_pDocument->GetStartPosition();
  133.     }
  134.     COleClientItem* pItem;
  135.     while ((pItem = m_pDocument->GetNextClientItem(m_pos)) != NULL)
  136.     {
  137.         // check for links
  138.         OLE_OBJTYPE objType = pItem->GetType();
  139.         if (m_bUpdateLinks && objType == OT_LINK)
  140.         {
  141.             // link found -- return it
  142.             return (DWORD)(void*)pItem;
  143.         }
  144.         // check for embeddings
  145.         if (m_bUpdateEmbeddings && objType == OT_EMBEDDED)
  146.         {
  147.             // embedding w/mismatched target device
  148.             return (DWORD)(void*)pItem;
  149.         }
  150.     }
  151.     return 0;   // link not found
  152. }
  153.  
  154. STDMETHODIMP COleUILinkInfo::SetLinkUpdateOptions(
  155.     DWORD dwLink, DWORD dwUpdateOpt)
  156. {
  157.     COleClientItem* pItem = (COleClientItem*)dwLink;
  158.     ASSERT_VALID(pItem);
  159.     ASSERT_KINDOF(COleClientItem, pItem);
  160.     ASSERT(pItem->GetType() == OT_LINK);
  161.  
  162.     SCODE sc;
  163.     TRY
  164.     {
  165.         // item is a link -- get its link options
  166.         pItem->SetLinkUpdateOptions((OLEUPDATE)dwUpdateOpt);
  167.         sc = S_OK;
  168.     }
  169.     CATCH_ALL(e)
  170.     {
  171.         sc = COleException::Process(e);
  172.         DELETE_EXCEPTION(e);
  173.     }
  174.     END_CATCH_ALL
  175.  
  176.     return sc;
  177. }
  178.  
  179. STDMETHODIMP COleUILinkInfo::GetLinkUpdateOptions(
  180.     DWORD dwLink, DWORD* lpdwUpdateOpt)
  181. {
  182.     COleClientItem* pItem = (COleClientItem*)dwLink;
  183.     ASSERT_VALID(pItem);
  184.     ASSERT_KINDOF(COleClientItem, pItem);
  185.  
  186.     SCODE sc;
  187.     TRY
  188.     {
  189.         if (pItem->GetType() == OT_LINK)
  190.             *lpdwUpdateOpt = pItem->GetLinkUpdateOptions();
  191.         else
  192.             *lpdwUpdateOpt = OLEUPDATE_ALWAYS;  // make believe it is auto-link
  193.         sc = S_OK;
  194.     }
  195.     CATCH_ALL(e)
  196.     {
  197.         sc = COleException::Process(e);
  198.         DELETE_EXCEPTION(e);
  199.     }
  200.     END_CATCH_ALL
  201.  
  202.     return sc;
  203. }
  204.  
  205. STDMETHODIMP COleUILinkInfo::SetLinkSource(
  206.     DWORD dwLink, LPTSTR lpszDisplayName, ULONG lenFileName,
  207.     ULONG* pchEaten, BOOL  fValidateSource)
  208. {
  209.     USES_CONVERSION;
  210.  
  211.     COleClientItem* pItem = (COleClientItem*)dwLink;
  212.     ASSERT_VALID(pItem);
  213.     ASSERT_KINDOF(COleClientItem, pItem);
  214.     ASSERT(pItem->GetType() == OT_LINK);
  215.  
  216.     LPOLEOBJECT lpObject = NULL;
  217.     CLSID clsid;
  218.  
  219.     // parse the portion known to be a file name into a file moniker
  220.     TCHAR szName[_MAX_PATH];
  221.     lstrcpyn(szName, lpszDisplayName, (int)lenFileName + 1);
  222.     LPMONIKER lpmk = NULL;
  223.     SCODE sc = CreateFileMoniker(T2COLE(szName), &lpmk);
  224.     if (lpmk == NULL)
  225.         return sc;
  226.  
  227.     LPBC lpbc = NULL;
  228.     if (fValidateSource)
  229.     {
  230.         sc = CreateBindCtx(0, &lpbc);
  231.         if (sc != S_OK)
  232.         {
  233.             lpmk->Release();
  234.             return sc;
  235.         }
  236.     }
  237.  
  238.     // nUneaten is the number of chars left to parse
  239.     UINT nUneaten = lstrlen(lpszDisplayName) - lenFileName;
  240.  
  241.     // lpszRemainder is the left over display name
  242.     LPTSTR lpszRemainder = lpszDisplayName + lenFileName;
  243.     *pchEaten = lenFileName;
  244.  
  245.     // parse the rest of the display name
  246.     while (nUneaten > 0)
  247.     {
  248.         // attempt to parse next moniker
  249.         ULONG nEaten = 0;
  250.         LPMONIKER lpmkNext = NULL;
  251.         sc = _AfxParseDisplayName(lpmk, lpbc, lpszRemainder, &nEaten, &lpmkNext);
  252.         if (sc != S_OK)
  253.         {
  254.             lpmk->Release();
  255.             lpbc->Release();
  256.             return sc;
  257.         }
  258.  
  259.         // advance through the display name
  260.         nUneaten -= nEaten;
  261.         *pchEaten += nEaten;
  262.         lpszRemainder += nEaten;
  263.  
  264.         if (lpmkNext != NULL)
  265.         {
  266.             // create composite out of current and next
  267.             LPMONIKER lpmkTemp = NULL;
  268.             sc = CreateGenericComposite(lpmk, lpmkNext, &lpmkTemp);
  269.             if (FAILED(sc))
  270.             {
  271.                 lpmk->Release();
  272.                 lpmkNext->Release();
  273.                 lpbc->Release();
  274.                 return sc;
  275.             }
  276.  
  277.             // make current = next
  278.             lpmkNext->Release();
  279.             lpmk->Release();
  280.             lpmk = lpmkTemp;
  281.         }
  282.     }
  283.  
  284.     if (fValidateSource)
  285.     {
  286.         // attempt to bind the the object
  287.         sc = lpmk->BindToObject(lpbc, NULL, IID_IOleObject, (LPLP)&lpObject);
  288.         if (FAILED(sc))
  289.         {
  290.             pItem->m_bLinkUnavail = TRUE;
  291.             lpbc->Release();
  292.             lpmk->Release();
  293.             RELEASE(lpObject);
  294.             return sc;
  295.         }
  296.         ASSERT(lpObject != NULL);
  297.  
  298.         // call GetUserClassID while bound so default handler updates
  299.         lpObject->GetUserClassID(&clsid);
  300.         pItem->m_bLinkUnavail = FALSE;
  301.     }
  302.  
  303.     // get IOleLink interface
  304.     LPOLELINK lpOleLink = QUERYINTERFACE(pItem->m_lpObject, IOleLink);
  305.     ASSERT(lpOleLink != NULL);
  306.  
  307.     // set source from moniker
  308.     sc = lpOleLink->SetSourceMoniker(lpmk, clsid);
  309.  
  310.     // update the cache if object was successfully bound
  311.     if (lpObject != NULL)
  312.     {
  313.         lpObject->Update();
  314.         lpObject->Release();
  315.     }
  316.  
  317.     // cleanup
  318.     lpOleLink->Release();
  319.     RELEASE(lpmk);
  320.     RELEASE(lpbc);
  321.  
  322.     return sc;
  323. }
  324.  
  325. STDMETHODIMP COleUILinkInfo::GetLinkSource(
  326.     DWORD dwLink, LPTSTR* lplpszDisplayName, ULONG* lplenFileName,
  327.     LPTSTR* lplpszFullLinkType, LPTSTR* lplpszShortLinkType,
  328.     BOOL* lpfSourceAvailable, BOOL* lpfIsSelected)
  329. {
  330.     COleClientItem* pItem = (COleClientItem*)dwLink;
  331.     ASSERT_VALID(pItem);
  332.     ASSERT_KINDOF(COleClientItem, pItem);
  333.     ASSERT(pItem->GetType() == OT_LINK);
  334.  
  335.     // set OUT params to NULL
  336.     ASSERT(lplpszDisplayName != NULL);
  337.     *lplpszDisplayName  = NULL;
  338.     if (lplpszFullLinkType != NULL)
  339.         *lplpszFullLinkType = NULL;
  340.     if (lplpszShortLinkType != NULL)
  341.         *lplpszShortLinkType = NULL;
  342.     if (lplenFileName != NULL)
  343.         *lplenFileName = 0;
  344.     if (lpfSourceAvailable != NULL)
  345.         *lpfSourceAvailable = !pItem->m_bLinkUnavail;
  346.  
  347.     // get IOleLink interface
  348.     LPOLELINK lpOleLink = QUERYINTERFACE(pItem->m_lpObject, IOleLink);
  349.     ASSERT(lpOleLink != NULL);
  350.  
  351.     // get moniker & object information
  352.     LPMONIKER lpmk;
  353.     if (lpOleLink->GetSourceMoniker(&lpmk) == S_OK)
  354.     {
  355.         if (lplenFileName != NULL)
  356.             *lplenFileName = _AfxOleGetLenFilePrefixOfMoniker(lpmk);
  357.         lpmk->Release();
  358.     }
  359.  
  360.  
  361.     // attempt to get the type names of the link
  362.     if (lplpszFullLinkType != NULL)
  363.     {
  364.         LPOLESTR lpOleStr = NULL;
  365.         pItem->m_lpObject->GetUserType(USERCLASSTYPE_FULL, &lpOleStr);
  366.         *lplpszFullLinkType = TASKSTRINGOLE2T(lpOleStr);
  367.         if (*lplpszFullLinkType == NULL)
  368.         {
  369.             TCHAR szUnknown[256];
  370.             VERIFY(AfxLoadString(AFX_IDS_UNKNOWNTYPE, szUnknown) != 0);
  371.             *lplpszFullLinkType = AfxAllocTaskString(szUnknown);
  372.         }
  373.     }
  374.     if (lplpszShortLinkType != NULL)
  375.     {
  376.         LPOLESTR lpOleStr = NULL;
  377.         pItem->m_lpObject->GetUserType(USERCLASSTYPE_SHORT, &lpOleStr);
  378.         *lplpszShortLinkType = TASKSTRINGOLE2T(lpOleStr);
  379.         if (*lplpszShortLinkType == NULL)
  380.         {
  381.             TCHAR szUnknown[256];
  382.             VERIFY(AfxLoadString(AFX_IDS_UNKNOWNTYPE, szUnknown) != 0);
  383.             *lplpszShortLinkType = AfxAllocTaskString(szUnknown);
  384.         }
  385.     }
  386.  
  387.     // get source display name for moniker
  388.     LPOLESTR lpOleStr = NULL;
  389.     SCODE sc = lpOleLink->GetSourceDisplayName(&lpOleStr);
  390.     *lplpszDisplayName = TASKSTRINGOLE2T(lpOleStr);
  391.     lpOleLink->Release();
  392.     if (sc != S_OK)
  393.         return sc;
  394.  
  395.     // see if item is selected if specified
  396.     if (lpfIsSelected)
  397.     {
  398.         *lpfIsSelected = (m_pSelectedItem == pItem);
  399.     }
  400.  
  401.     return S_OK;
  402. }
  403.  
  404. STDMETHODIMP COleUILinkInfo::OpenLinkSource(DWORD dwLink)
  405. {
  406.     COleClientItem* pItem = (COleClientItem*)dwLink;
  407.     ASSERT_VALID(pItem);
  408.     ASSERT_KINDOF(COleClientItem, pItem);
  409.     ASSERT(pItem->GetType() == OT_LINK);
  410.  
  411.     SCODE sc;
  412.     TRY
  413.     {
  414.         // Note: no need for valid CView* since links don't activate inplace
  415.         pItem->DoVerb(OLEIVERB_SHOW, NULL);
  416.         sc = S_OK;
  417.     }
  418.     CATCH_ALL(e)
  419.     {
  420.         sc = COleException::Process(e);
  421.         DELETE_EXCEPTION(e);
  422.     }
  423.     END_CATCH_ALL
  424.  
  425.     return sc;
  426. }
  427.  
  428. STDMETHODIMP COleUILinkInfo::UpdateLink(
  429.     DWORD dwLink, BOOL /*fErrorMessage*/, BOOL /*fErrorAction*/)
  430. {
  431.     COleClientItem* pItem = (COleClientItem*)dwLink;
  432.     ASSERT_VALID(pItem);
  433.     ASSERT_KINDOF(COleClientItem, pItem);
  434.  
  435.     SCODE sc;
  436.     TRY
  437.     {
  438.         // link not up-to-date, attempt to update it
  439.         if (!pItem->UpdateLink())
  440.             AfxThrowOleException(pItem->GetLastStatus());
  441.         pItem->m_bLinkUnavail = FALSE;
  442.         sc = S_OK;
  443.     }
  444.     CATCH_ALL(e)
  445.     {
  446.         pItem->m_bLinkUnavail = TRUE;
  447.         sc = COleException::Process(e);
  448.         pItem->ReportError(sc);
  449.         DELETE_EXCEPTION(e);
  450.     }
  451.     END_CATCH_ALL
  452.  
  453.     return sc;
  454. }
  455.  
  456. STDMETHODIMP COleUILinkInfo::CancelLink(DWORD dwLink)
  457. {
  458.     COleClientItem* pItem = (COleClientItem*)dwLink;
  459.     ASSERT_VALID(pItem);
  460.     ASSERT_KINDOF(COleClientItem, pItem);
  461.     ASSERT(pItem->GetType() == OT_LINK);
  462.  
  463.     SCODE sc = E_FAIL;
  464.     TRY
  465.     {
  466.         if (pItem->FreezeLink())
  467.             sc = S_OK;
  468.     }
  469.     CATCH_ALL(e)
  470.     {
  471.         sc = COleException::Process(e);
  472.         DELETE_EXCEPTION(e);
  473.     }
  474.     END_CATCH_ALL
  475.  
  476.     // report error
  477.     if (sc != S_OK)
  478.         pItem->ReportError(sc);
  479.  
  480.     return S_OK;
  481. }
  482.  
  483. STDMETHODIMP COleUILinkInfo::GetLastUpdate(DWORD dwLink, FILETIME*)
  484. {
  485.     COleClientItem* pItem = (COleClientItem*)dwLink;
  486.     ASSERT_VALID(pItem);
  487.  
  488.     // Note: leave last update time at unknown!
  489.  
  490.     return S_OK;
  491. }
  492.  
  493. ////////////////////////////////////////////////////////////////////////////
  494. // InsertObject dialog wrapper
  495.  
  496. COleInsertDialog::COleInsertDialog(DWORD dwFlags, CWnd* pParentWnd)
  497.     : COleDialog(pParentWnd)
  498. {
  499.     memset(&m_io, 0, sizeof(m_io)); // initialize structure to 0/NULL
  500.  
  501.     // fill in common part
  502.     m_io.cbStruct = sizeof(m_io);
  503.     m_io.dwFlags = dwFlags;
  504.     if (!afxData.bWin4 && AfxHelpEnabled())
  505.         m_io.dwFlags |= IOF_SHOWHELP;
  506.     if (_AfxOlePropertiesEnabled())
  507.         m_io.dwFlags |= IOF_HIDECHANGEICON;
  508.     m_io.lpfnHook = AfxOleHookProc;
  509.     m_nIDHelp = AFX_IDD_INSERTOBJECT;
  510.  
  511.     // specific to this dialog
  512.     m_io.lpszFile = m_szFileName;
  513.     m_io.cchFile = _countof(m_szFileName);
  514.     m_szFileName[0] = '\0';
  515. }
  516.  
  517. COleInsertDialog::~COleInsertDialog()
  518. {
  519.     _AfxDeleteMetafilePict(m_io.hMetaPict);
  520. }
  521.  
  522. void COleInsertDialog::AddClassIDToList(LPCLSID& lpList,
  523.     int& nListCount, int& nBufferLen, LPCLSID lpNewID)
  524. {
  525.     // if the list doesn't exist, create it
  526.  
  527.     if (lpList == NULL)
  528.     {
  529.         nListCount = 0;
  530.         nBufferLen = 16;
  531.         lpList = new CLSID[nBufferLen];
  532.     }
  533.  
  534.     // if the list isn't big enough grow it by twice
  535.  
  536.     if (nListCount == nBufferLen)
  537.     {
  538.         LPCLSID lpOldList = lpList;
  539.         nBufferLen <<= 2;
  540.         lpList = new CLSID[nBufferLen];
  541.         memcpy(lpList, lpOldList, sizeof(CLSID) * nListCount);
  542.         delete [] lpOldList;
  543.     }
  544.  
  545.     lpList[nListCount] = *lpNewID;
  546.     nListCount++;
  547.  
  548.     return;
  549. }
  550.  
  551. int COleInsertDialog::DoModal(DWORD dwFlags)
  552. {
  553.     LPCLSID lpNewExcludeList = NULL;
  554.     int nNewExcludeCount = 0;
  555.     int nNewExcludeLen = 0;
  556.  
  557.     // support for controls is built-in
  558.     // support doc objects by filtering what the dialog shows
  559.  
  560.     if (dwFlags == ControlsOnly)
  561.         m_io.dwFlags |= IOF_SELECTCREATECONTROL | IOF_SHOWINSERTCONTROL;
  562.     else if (dwFlags == DocObjectsOnly)
  563.     {
  564.         m_io.dwFlags |= IOF_DISABLEDISPLAYASICON | IOF_DISABLELINK;
  565.  
  566.         HKEY hkClassesRoot;
  567.         HKEY hkCLSID;
  568.         HKEY hkItem;
  569.         HKEY hkDocObject;
  570.         DWORD dwIndex = 0;
  571.         TCHAR szName[MAX_PATH+1];
  572.  
  573.         if (RegOpenKeyEx(HKEY_CLASSES_ROOT, NULL, 0, KEY_READ,
  574.                 &hkClassesRoot) == ERROR_SUCCESS)
  575.         {
  576.             if(RegOpenKeyEx(hkClassesRoot, _T("CLSID"), 0,
  577.                 KEY_ENUMERATE_SUB_KEYS, &hkCLSID) == ERROR_SUCCESS)
  578.             {
  579.                 while(RegEnumKey(hkCLSID, dwIndex++,
  580.                             szName, sizeof(szName)) == ERROR_SUCCESS)
  581.                 {
  582.                     if (RegOpenKeyEx(hkCLSID, szName, 0,
  583.                             KEY_READ, &hkItem) == ERROR_SUCCESS)
  584.                     {
  585.                         if ((RegOpenKeyEx(hkItem, _T("Insertable"), 0,
  586.                                 KEY_READ, &hkDocObject) == ERROR_SUCCESS) ||
  587.                              (RegOpenKeyEx(hkItem, _T("Ole1Class"),0,
  588.                                 KEY_READ, &hkDocObject) == ERROR_SUCCESS))
  589.                         {
  590.                             RegCloseKey(hkDocObject);
  591.                             if ((RegOpenKeyEx(hkItem, _T("DocObject"), 0,
  592.                                     KEY_READ, &hkDocObject) != ERROR_SUCCESS ) )
  593.                             {
  594.                                 USES_CONVERSION;
  595.  
  596.                                 CLSID clsid;
  597.                                 CLSIDFromString(T2OLE(szName), &clsid);
  598.                                 AddClassIDToList(lpNewExcludeList,
  599.                                     nNewExcludeCount, nNewExcludeLen, &clsid);
  600.                                 RegCloseKey(hkItem);
  601.                             }
  602.                             RegCloseKey(hkDocObject);
  603.                         }
  604.                     }
  605.                 }
  606.                 RegCloseKey(hkCLSID);
  607.             }
  608.         }
  609.         RegCloseKey(hkClassesRoot);
  610.     }
  611.  
  612.     UINT cOldClsidExclude = m_io.cClsidExclude;
  613.     LPCLSID lpOldClsidExclude = m_io.lpClsidExclude;
  614.  
  615.     if (lpNewExcludeList != NULL)
  616.     {
  617.         m_io.lpClsidExclude = lpNewExcludeList;
  618.         m_io.cClsidExclude = nNewExcludeCount;
  619.     }
  620.  
  621. QueryAgain:
  622.     int nDisposition = DoModal();
  623.  
  624.     if (nDisposition == IDOK && GetSelectionType() == insertFromFile &&
  625.         dwFlags == DocObjectsOnly)
  626.     {
  627.         USES_CONVERSION;
  628.  
  629.         // Double-check that the requested file really is serviced by a
  630.         // DocObject server.
  631.  
  632.         CLSID clsidFile;
  633.         BOOL bIsDocObject = FALSE;
  634.         if (GetClassFile(T2COLE(m_io.lpszFile), &clsidFile) == S_OK)
  635.         {
  636.             CString strKey;
  637.             CString strCLSID = AfxStringFromCLSID(clsidFile);
  638.             strKey.Format(_T("CLSID\\%s\\DocObject"), strCLSID);
  639.  
  640.             HKEY hKey;
  641.             if (ERROR_SUCCESS ==
  642.                 RegOpenKeyEx(HKEY_CLASSES_ROOT, strKey, 0, KEY_QUERY_VALUE, &hKey))
  643.             {
  644.                 RegCloseKey(hKey);
  645.                 bIsDocObject = TRUE;
  646.             }
  647.         }
  648.  
  649.         if (!bIsDocObject)
  650.         {
  651.             nDisposition =
  652.                 AfxMessageBox(AFX_IDS_NOT_DOCOBJECT, MB_RETRYCANCEL | MB_ICONHAND);
  653.             if (nDisposition == IDRETRY)
  654.                 goto QueryAgain;
  655.             else
  656.                 nDisposition = IDCANCEL;
  657.         }
  658.     }
  659.  
  660.     delete [] lpNewExcludeList;
  661.  
  662.     m_io.cClsidExclude = cOldClsidExclude;
  663.     m_io.lpClsidExclude = lpOldClsidExclude;
  664.  
  665.     return nDisposition;
  666. }
  667.  
  668. int COleInsertDialog::DoModal()
  669. {
  670.     ASSERT_VALID(this);
  671.     ASSERT(m_io.lpfnHook != NULL);  // can still be a user hook
  672.  
  673.     m_io.hWndOwner = PreModal();
  674.     int iResult = MapResult(::OleUIInsertObject(&m_io));
  675.     PostModal();
  676.     return iResult;
  677. }
  678.  
  679. UINT COleInsertDialog::GetSelectionType() const
  680. {
  681.     ASSERT_VALID(this);
  682.  
  683.     if (m_io.dwFlags & IOF_SELECTCREATEFROMFILE)
  684.     {
  685.         if (m_io.dwFlags & IOF_CHECKLINK)
  686.             return linkToFile;
  687.         else
  688.             return insertFromFile;
  689.     }
  690.     ASSERT(m_io.dwFlags & IOF_SELECTCREATENEW);
  691.     return createNewItem;
  692. }
  693.  
  694. // allocate an item first, then call this fuction to create it
  695. BOOL COleInsertDialog::CreateItem(COleClientItem* pNewItem)
  696. {
  697.     ASSERT_VALID(pNewItem);
  698.  
  699.     // switch on selection type
  700.     UINT selType = GetSelectionType();
  701.     BOOL bResult;
  702.  
  703.     switch (selType)
  704.     {
  705.     case linkToFile:
  706.         // link to file selected
  707.         ASSERT(m_szFileName[0] != 0);
  708.         bResult = pNewItem->CreateLinkFromFile(m_szFileName);
  709.         break;
  710.     case insertFromFile:
  711.         // insert file selected
  712.         ASSERT(m_szFileName[0] != 0);
  713.         bResult = pNewItem->CreateFromFile(m_szFileName);
  714.         break;
  715.     default:
  716.         // otherwise must be create new
  717.         ASSERT(selType == createNewItem);
  718.         bResult = pNewItem->CreateNewItem(m_io.clsid);
  719.         break;
  720.     }
  721.  
  722.     // deal with Display As Iconic option
  723.     if (bResult && GetDrawAspect() == DVASPECT_ICON)
  724.     {
  725.         // setup iconic cache (it will draw iconic by default as well)
  726.         if (!pNewItem->SetIconicMetafile(m_io.hMetaPict))
  727.         {
  728.             TRACE0("Warning: failed to set iconic aspect in CreateItem.\n");
  729.             return TRUE;
  730.         }
  731.  
  732.         // since picture was set OK, draw as iconic as well...
  733.         pNewItem->SetDrawAspect(DVASPECT_ICON);
  734.     }
  735.     return bResult;
  736. }
  737.  
  738. /////////////////////////////////////////////////////////////////////////////
  739. // COleInsertDialog diagnostics
  740.  
  741. #ifdef _DEBUG
  742. void COleInsertDialog::Dump(CDumpContext& dc) const
  743. {
  744.     COleDialog::Dump(dc);
  745.  
  746.     dc << "m_szFileName = " << m_szFileName;
  747.     dc << "\nm_io.cbStruct = " << m_io.cbStruct;
  748.     dc << "\nm_io.dwFlags = " << (LPVOID)m_io.dwFlags;
  749.     dc << "\nm_io.hWndOwner = " << (UINT)m_io.hWndOwner;
  750.     dc << "\nm_io.lpszCaption = " << m_io.lpszCaption;
  751.     dc << "\nm_io.lCustData = " << (LPVOID)m_io.lCustData;
  752.     dc << "\nm_io.hInstance = " << (UINT)m_io.hInstance;
  753.     dc << "\nm_io.lpszTemplate = " << (LPVOID)m_io.lpszTemplate;
  754.     dc << "\nm_io.hResource = " << (UINT)m_io.hResource;
  755.     if (m_io.lpfnHook == AfxOleHookProc)
  756.         dc << "\nhook function set to standard MFC hook function";
  757.     else
  758.         dc << "\nhook function set to non-standard hook function";
  759.     dc << "\nm_io.hMetaPict = " << (UINT)m_io.hMetaPict;
  760.  
  761.     dc << "\n";
  762. }
  763. #endif //_DEBUG
  764.  
  765. /////////////////////////////////////////////////////////////////////////////
  766. // COleConvertDialog
  767.  
  768. COleConvertDialog::COleConvertDialog(COleClientItem* pItem, DWORD dwFlags,
  769.     CLSID* pClassID, CWnd* pParentWnd) : COleDialog(pParentWnd)
  770. {
  771.     if (pItem != NULL)
  772.         ASSERT_VALID(pItem);
  773.     ASSERT(pClassID == NULL || AfxIsValidAddress(pClassID, sizeof(CLSID), FALSE));
  774.  
  775.     memset(&m_cv, 0, sizeof(m_cv)); // initialize structure to 0/NULL
  776.     if (pClassID != NULL)
  777.         m_cv.clsid = *pClassID;
  778.  
  779.     // fill in common part
  780.     m_cv.cbStruct = sizeof(m_cv);
  781.     m_cv.dwFlags = dwFlags;
  782.     if (!afxData.bWin4 && AfxHelpEnabled())
  783.         m_cv.dwFlags |= CF_SHOWHELPBUTTON;
  784.     m_cv.lpfnHook = AfxOleHookProc;
  785.     m_nIDHelp = AFX_IDD_CONVERT;
  786.  
  787.     // specific to this dialog
  788.     m_cv.fIsLinkedObject = pItem->GetType() == OT_LINK;
  789.     m_cv.dvAspect = pItem->GetDrawAspect();
  790.     if (pClassID == NULL && !m_cv.fIsLinkedObject)
  791.     {
  792.         // for embeddings, attempt to get class ID from the storage
  793.         if (ReadClassStg(pItem->m_lpStorage, &m_cv.clsid) == S_OK)
  794.             pClassID = &m_cv.clsid;
  795.  
  796.         // attempt to get user type from storage
  797.         CLIPFORMAT cf = 0;
  798.         LPOLESTR lpOleStr = NULL;
  799.         ReadFmtUserTypeStg(pItem->m_lpStorage, &cf, &lpOleStr);
  800.         m_cv.lpszUserType = TASKSTRINGOLE2T(lpOleStr);
  801.  
  802.         m_cv.wFormat = (WORD)cf;
  803.     }
  804.     // get class id if neded
  805.     if (pClassID == NULL)
  806.     {
  807.         // no class ID in the storage, use class ID of the object
  808.         pItem->GetClassID(&m_cv.clsid);
  809.     }
  810.  
  811.     // get user type if needed
  812.     if (m_cv.lpszUserType == NULL)
  813.     {
  814.         // no user type in storge, get user type from class ID
  815.         LPTSTR lpszUserType = NULL;
  816.         LPOLESTR lpOleStr = NULL;
  817.         if (OleRegGetUserType(m_cv.clsid, USERCLASSTYPE_FULL,
  818.             &lpOleStr) == S_OK)
  819.         {
  820.             lpszUserType = TASKSTRINGOLE2T(lpOleStr);
  821.         }
  822.         else
  823.         {
  824.             lpszUserType = (LPTSTR)CoTaskMemAlloc(256 * sizeof(TCHAR));
  825.             if (lpszUserType != NULL)
  826.             {
  827.                 lpszUserType[0] = '?';
  828.                 lpszUserType[1] = 0;
  829.                 VERIFY(AfxLoadString(AFX_IDS_UNKNOWNTYPE, lpszUserType) != 0);
  830.             }
  831.         }
  832.         m_cv.lpszUserType = lpszUserType;
  833.     }
  834.     m_cv.hMetaPict = pItem->GetIconicMetafile();
  835. }
  836.  
  837. COleConvertDialog::~COleConvertDialog()
  838. {
  839.     _AfxDeleteMetafilePict(m_cv.hMetaPict);
  840. }
  841.  
  842. int COleConvertDialog::DoModal()
  843. {
  844.     ASSERT_VALID(this);
  845.     ASSERT(m_cv.lpfnHook != NULL);  // can still be a user hook
  846.  
  847.     m_cv.hWndOwner = PreModal();
  848.     int iResult = MapResult(::OleUIConvert(&m_cv));
  849.     PostModal();
  850.     return iResult;
  851. }
  852.  
  853. BOOL COleConvertDialog::DoConvert(COleClientItem* pItem)
  854. {
  855.     ASSERT_VALID(pItem);
  856.  
  857.     CWaitCursor wait;
  858.  
  859.     UINT selType = GetSelectionType();
  860.     BOOL bResult = TRUE;
  861.  
  862.     if (m_cv.clsidNew != CLSID_NULL)
  863.     {
  864.         switch (selType)
  865.         {
  866.         case convertItem:
  867.             bResult = pItem->ConvertTo(m_cv.clsidNew);
  868.             break;
  869.         case activateAs:
  870.             bResult = pItem->ActivateAs(m_cv.lpszUserType, m_cv.clsid,
  871.                 m_cv.clsidNew);
  872.             break;
  873.         default:
  874.             ASSERT(selType == noConversion);
  875.             break;
  876.         }
  877.     }
  878.  
  879.     if (!bResult)
  880.     {
  881.         // if unable to convert the object show message box
  882.         AfxMessageBox(AFX_IDP_FAILED_TO_CONVERT);
  883.         return FALSE;
  884.     }
  885.  
  886.     // change to iconic/content view if changed
  887.     if ((DVASPECT)m_cv.dvAspect != pItem->GetDrawAspect())
  888.     {
  889.         pItem->OnChange(OLE_CHANGED_ASPECT, (DWORD)m_cv.dvAspect);
  890.         pItem->SetDrawAspect((DVASPECT)m_cv.dvAspect);
  891.     }
  892.  
  893.     // change the actual icon as well
  894.     if (m_cv.fObjectsIconChanged)
  895.     {
  896.         pItem->SetIconicMetafile(m_cv.hMetaPict);
  897.         if (pItem->GetDrawAspect() == DVASPECT_ICON)
  898.             pItem->OnChange(OLE_CHANGED, (DWORD)DVASPECT_ICON);
  899.     }
  900.  
  901.     return TRUE;
  902. }
  903.  
  904. UINT COleConvertDialog::GetSelectionType() const
  905. {
  906.     ASSERT_VALID(this);
  907.  
  908.     if (m_cv.clsid != m_cv.clsidNew)
  909.     {
  910.         if (m_cv.dwFlags & CF_SELECTCONVERTTO)
  911.             return convertItem;
  912.         else if (m_cv.dwFlags & CF_SELECTACTIVATEAS)
  913.             return activateAs;
  914.     }
  915.     return noConversion;
  916. }
  917.  
  918. /////////////////////////////////////////////////////////////////////////////
  919. // COleConvertDialog diagnostics
  920.  
  921. #ifdef _DEBUG
  922. void COleConvertDialog::Dump(CDumpContext& dc) const
  923. {
  924.     COleDialog::Dump(dc);
  925.  
  926.     dc << "m_cv.cbStruct = " << m_cv.cbStruct;
  927.     dc << "\nm_cv.dwFlags = " << (LPVOID)m_cv.dwFlags;
  928.     dc << "\nm_cv.hWndOwner = " << (UINT)m_cv.hWndOwner;
  929.     dc << "\nm_cv.lpszCaption = " << m_cv.lpszCaption;
  930.     dc << "\nm_cv.lCustData = " << (LPVOID)m_cv.lCustData;
  931.     dc << "\nm_cv.hInstance = " << (UINT)m_cv.hInstance;
  932.     dc << "\nm_cv.lpszTemplate = " << (LPVOID)m_cv.lpszTemplate;
  933.     dc << "\nm_cv.hResource = " << (UINT)m_cv.hResource;
  934.     if (m_cv.lpfnHook == AfxOleHookProc)
  935.         dc << "\nhook function set to standard MFC hook function";
  936.     else
  937.         dc << "\nhook function set to non-standard hook function";
  938.     dc << "\nm_cv.dvAspect = " << (UINT)m_cv.dvAspect;
  939.     dc << "\nm_cv.wFormat = " << (UINT)m_cv.wFormat;
  940.     dc << "\nm_cv.fIsLinkedObject = " << m_cv.fIsLinkedObject;
  941.     dc << "\nm_cv.hMetaPict = " << (UINT)m_cv.hMetaPict;
  942.     dc << "\nm_cv.lpszUserType = " << m_cv.lpszUserType;
  943.     dc << "\nm_cv.fObjectsIconChanged = " << m_cv.fObjectsIconChanged;
  944.  
  945.     dc << "\n";
  946. }
  947. #endif
  948.  
  949. /////////////////////////////////////////////////////////////////////////////
  950. // COleChangeIconDialog
  951.  
  952. COleChangeIconDialog::COleChangeIconDialog(COleClientItem* pItem,
  953.     DWORD dwFlags, CWnd* pParentWnd) : COleDialog(pParentWnd)
  954. {
  955.     if (pItem != NULL)
  956.         ASSERT_VALID(pItem);
  957.  
  958.     memset(&m_ci, 0, sizeof(m_ci)); // initialize structure to 0/NULL
  959.  
  960.     // fill in common part
  961.     m_ci.cbStruct = sizeof(m_ci);
  962.     m_ci.dwFlags = dwFlags;
  963.     if (!afxData.bWin4 && AfxHelpEnabled())
  964.         m_ci.dwFlags |= CIF_SHOWHELP;
  965.     m_ci.lpfnHook = AfxOleHookProc;
  966.     m_nIDHelp = AFX_IDD_CHANGEICON;
  967.  
  968.     // specific to this dialog
  969.     if (pItem != NULL)
  970.     {
  971.         pItem->GetClassID(&m_ci.clsid);
  972.         m_ci.hMetaPict = pItem->GetIconicMetafile();
  973.     }
  974. }
  975.  
  976. COleChangeIconDialog::~COleChangeIconDialog()
  977. {
  978.     _AfxDeleteMetafilePict(m_ci.hMetaPict);
  979. }
  980.  
  981. int COleChangeIconDialog::DoModal()
  982. {
  983.     ASSERT_VALID(this);
  984.     ASSERT(m_ci.lpfnHook != NULL);  // can still be a user hook
  985.  
  986.     m_ci.hWndOwner = PreModal();
  987.     int iResult = MapResult(::OleUIChangeIcon(&m_ci));
  988.     PostModal();
  989.     return iResult;
  990. }
  991.  
  992. BOOL COleChangeIconDialog::DoChangeIcon(COleClientItem* pItem)
  993. {
  994.     ASSERT_VALID(this);
  995.     ASSERT_VALID(pItem);
  996.  
  997.     // set the picture
  998.     if (!pItem->SetIconicMetafile(GetIconicMetafile()))
  999.         return FALSE;
  1000.  
  1001.     // notify the item of the change if the current draw aspect is ICON
  1002.     if (pItem->GetDrawAspect() == DVASPECT_ICON)
  1003.         pItem->OnChange(OLE_CHANGED, (DWORD)DVASPECT_ICON);
  1004.  
  1005.     return TRUE;
  1006. }
  1007.  
  1008. /////////////////////////////////////////////////////////////////////////////
  1009. // COleChangeIconDialog diagnostics
  1010.  
  1011. #ifdef _DEBUG
  1012. void COleChangeIconDialog::Dump(CDumpContext& dc) const
  1013. {
  1014.     COleDialog::Dump(dc);
  1015.  
  1016.     dc << "m_ci.cbStruct = " << m_ci.cbStruct;
  1017.     dc << "\nm_ci.dwFlags = " << (LPVOID)m_ci.dwFlags;
  1018.     dc << "\nm_ci.hWndOwner = " << (UINT)m_ci.hWndOwner;
  1019.     dc << "\nm_ci.lpszCaption = " << m_ci.lpszCaption;
  1020.     dc << "\nm_ci.lCustData = " << (LPVOID)m_ci.lCustData;
  1021.     dc << "\nm_ci.hInstance = " << (UINT)m_ci.hInstance;
  1022.     dc << "\nm_ci.lpszTemplate = " << (LPVOID)m_ci.lpszTemplate;
  1023.     dc << "\nm_ci.hResource = " << (UINT)m_ci.hResource;
  1024.     if (m_ci.lpfnHook == AfxOleHookProc)
  1025.         dc << "\nhook function set to standard MFC hook function";
  1026.     else
  1027.         dc << "\nhook function set to non-standard hook function";
  1028.     dc << "\nm_ci.hMetaPict = " << (UINT)m_ci.hMetaPict;
  1029.  
  1030.     dc << "\n";
  1031. }
  1032. #endif
  1033.  
  1034. /////////////////////////////////////////////////////////////////////////////
  1035. // COleLinksDialog
  1036.  
  1037. COleLinksDialog::COleLinksDialog(COleDocument* pDoc, CView* pView,
  1038.     DWORD dwFlags, CWnd* pParentWnd) : COleDialog(pParentWnd),
  1039.     m_xLinkInfo(pDoc)
  1040. {
  1041.     ASSERT_VALID(pDoc);
  1042.     if (pView != NULL)
  1043.         ASSERT_VALID(pView);
  1044.  
  1045.     memset(&m_el, 0, sizeof(m_el)); // initialize structure to 0/NULL
  1046.  
  1047.     // fill in common part
  1048.     m_el.cbStruct = sizeof(m_el);
  1049.     m_el.dwFlags = dwFlags;
  1050.     if (!afxData.bWin4 && AfxHelpEnabled())
  1051.         m_el.dwFlags |= ELF_SHOWHELP;
  1052.     m_el.lpfnHook = AfxOleHookProc;
  1053.     m_nIDHelp = AFX_IDD_EDITLINKS;
  1054.  
  1055.     // specific to this dialog
  1056.     if (pView != NULL)
  1057.         m_xLinkInfo.m_pSelectedItem = pDoc->GetPrimarySelectedItem(pView);
  1058.     else
  1059.         m_xLinkInfo.m_pSelectedItem = NULL;
  1060.     m_el.lpOleUILinkContainer = &m_xLinkInfo;
  1061. }
  1062.  
  1063. COleLinksDialog::~COleLinksDialog()
  1064. {
  1065. }
  1066.  
  1067. int COleLinksDialog::DoModal()
  1068. {
  1069.     ASSERT_VALID(this);
  1070.     ASSERT(m_el.lpfnHook != NULL);  // can still be a user hook
  1071.  
  1072.     // this function is always used for updating links
  1073.     m_xLinkInfo.m_bUpdateLinks = TRUE;
  1074.  
  1075.     m_el.hWndOwner = PreModal();
  1076.     int iResult = MapResult(::OleUIEditLinks(&m_el));
  1077.     PostModal();
  1078.     return iResult;
  1079. }
  1080.  
  1081. /////////////////////////////////////////////////////////////////////////////
  1082. // COleLinksDialog diagnostics
  1083.  
  1084. #ifdef _DEBUG
  1085. void COleLinksDialog::Dump(CDumpContext& dc) const
  1086. {
  1087.     COleDialog::Dump(dc);
  1088.  
  1089.     dc << "\nm_el.cbStruct = " << m_el.cbStruct;
  1090.     dc << "\nm_el.dwFlags = " << (void*)m_el.dwFlags;
  1091.     dc << "\nm_el.hWndOwner = " << (UINT)m_el.hWndOwner;
  1092.     dc << "\nm_el.lpszCaption = " << m_el.lpszCaption;
  1093.     dc << "\nm_el.lCustData = " << (void*)m_el.lCustData;
  1094.     dc << "\nm_el.hInstance = " << (UINT)m_el.hInstance;
  1095.     dc << "\nm_el.lpszTemplate = " << (void*)m_el.lpszTemplate;
  1096.     dc << "\nm_el.hResource = " << (UINT)m_el.hResource;
  1097.     if (m_el.lpfnHook == AfxOleHookProc)
  1098.         dc << "\nhook function set to standard MFC hook function";
  1099.     else
  1100.         dc << "\nhook function set to non-standard hook function";
  1101.  
  1102.     dc << "\n";
  1103. }
  1104.  
  1105. void COleLinksDialog::AssertValid() const
  1106. {
  1107.     COleDialog::AssertValid();
  1108. }
  1109. #endif
  1110.  
  1111. /////////////////////////////////////////////////////////////////////////////
  1112. // COleUpdateDialog
  1113.  
  1114. COleUpdateDialog::COleUpdateDialog(COleDocument* pDoc,
  1115.     BOOL bUpdateLinks, BOOL bUpdateEmbeddings, CWnd* pParentWnd)
  1116.         : COleLinksDialog(pDoc, NULL, 0, pParentWnd)
  1117. {
  1118.     ASSERT_VALID(pDoc);
  1119.     ASSERT(bUpdateLinks || bUpdateEmbeddings);
  1120.  
  1121.     // non-base class parameters
  1122.     m_xLinkInfo.m_bUpdateLinks = bUpdateLinks;
  1123.     m_xLinkInfo.m_bUpdateEmbeddings = bUpdateEmbeddings;
  1124.     m_strCaption.LoadString(AFX_IDS_UPDATING_ITEMS);
  1125. }
  1126.  
  1127. COleUpdateDialog::~COleUpdateDialog()
  1128. {
  1129. }
  1130.  
  1131. int COleUpdateDialog::DoModal()
  1132. {
  1133.     ASSERT_VALID(this);
  1134.  
  1135.     // first count number of links/embeddings to be updated
  1136.     DWORD dwLink = 0;
  1137.     int cLinks = 0;
  1138.     while ((dwLink = m_el.lpOleUILinkContainer->GetNextLink(dwLink)) != 0)
  1139.         ++cLinks;
  1140.     // when no links are out-of-date, don't bother
  1141.     if (cLinks == 0)
  1142.         return IDCANCEL;
  1143.  
  1144.     // bring up the dialog that processes all the links
  1145.     HWND hWndParent = PreModal();
  1146.     BOOL bResult = OleUIUpdateLinks(m_el.lpOleUILinkContainer,
  1147.         hWndParent, (LPTSTR)(LPCTSTR)m_strCaption, cLinks);
  1148.     PostModal();
  1149.     return bResult ? IDOK : -1;
  1150. }
  1151.  
  1152. /////////////////////////////////////////////////////////////////////////////
  1153. // COleUpdateDialog diagnostics
  1154.  
  1155. #ifdef _DEBUG
  1156. void COleUpdateDialog::Dump(CDumpContext& dc) const
  1157. {
  1158.     COleLinksDialog::Dump(dc);
  1159.  
  1160.     dc << "m_strCaption = " << m_strCaption;
  1161.     dc << "\n";
  1162. }
  1163. #endif
  1164.  
  1165. /////////////////////////////////////////////////////////////////////////////
  1166. // COlePasteSpecialDialog
  1167.  
  1168. COlePasteSpecialDialog::COlePasteSpecialDialog(DWORD dwFlags,
  1169.     COleDataObject* pDataObject, CWnd* pParentWnd) : COleDialog(pParentWnd)
  1170. {
  1171.     memset(&m_ps, 0, sizeof(m_ps)); // initialize structure to 0/NULL
  1172.  
  1173.     // fill in common part
  1174.     m_ps.cbStruct = sizeof(m_ps);
  1175.     m_ps.dwFlags = dwFlags | PSF_STAYONCLIPBOARDCHANGE;
  1176.     if (!afxData.bWin4 && AfxHelpEnabled())
  1177.         m_ps.dwFlags |= PSF_SHOWHELP;
  1178.     if (_AfxOlePropertiesEnabled())
  1179.         m_ps.dwFlags |= PSF_HIDECHANGEICON;
  1180.     m_ps.lpfnHook = AfxOleHookProc;
  1181.     m_nIDHelp = AFX_IDD_PASTESPECIAL;
  1182.  
  1183.     // get LPDATAOBJECT for paste special dialog
  1184.     COleDataObject dataObject;
  1185.     if (pDataObject == NULL)
  1186.     {
  1187.         VERIFY(dataObject.AttachClipboard());
  1188.         pDataObject = &dataObject;
  1189.     }
  1190.     ASSERT(pDataObject != NULL);
  1191.     m_ps.lpSrcDataObj = pDataObject->GetIDataObject(TRUE);
  1192.  
  1193.     // complete initialization
  1194.     m_ps.arrPasteEntries = NULL;
  1195.     m_ps.cPasteEntries = 0;
  1196.     m_ps.arrLinkTypes = m_arrLinkTypes;
  1197.     m_ps.cLinkTypes = 0;
  1198. }
  1199.  
  1200. COlePasteSpecialDialog::~COlePasteSpecialDialog()
  1201. {
  1202.     _AfxDeleteMetafilePict(m_ps.hMetaPict);
  1203.  
  1204.     for (int i = 0; i < m_ps.cPasteEntries; i++)
  1205.     {
  1206.         free((void*)m_ps.arrPasteEntries[i].lpstrFormatName);
  1207.         free((void*)m_ps.arrPasteEntries[i].lpstrResultText);
  1208.     }
  1209.     free(m_ps.arrPasteEntries);
  1210.  
  1211.     RELEASE(m_ps.lpSrcDataObj);
  1212. }
  1213.  
  1214. int COlePasteSpecialDialog::DoModal()
  1215. {
  1216.     ASSERT_VALID(this);
  1217.     ASSERT(m_ps.lpfnHook != NULL);  // can still be a user hook
  1218.  
  1219.     // return error if IDataObject* not available
  1220.     if (m_ps.lpSrcDataObj == NULL)
  1221.         return -1;
  1222.  
  1223.     m_ps.hWndOwner = PreModal();
  1224.     int iResult = MapResult(::OleUIPasteSpecial(&m_ps));
  1225.     PostModal();
  1226.     return iResult;
  1227. }
  1228.  
  1229. UINT COlePasteSpecialDialog::GetSelectionType() const
  1230. {
  1231.     ASSERT_VALID(this);
  1232.     ASSERT(m_ps.dwFlags & (PSF_SELECTPASTE|PSF_SELECTPASTELINK));
  1233.  
  1234.     UINT cf = m_ps.arrPasteEntries[m_ps.nSelectedIndex].fmtetc.cfFormat;
  1235.     Selection selType = pasteOther;
  1236.     if (m_ps.dwFlags & PSF_SELECTPASTELINK)
  1237.     {
  1238.         selType = pasteLink;
  1239.     }
  1240.     else if (cf == _oleData.cfEmbedSource || cf == _oleData.cfEmbeddedObject ||
  1241.             cf == _oleData.cfLinkSource)
  1242.     {
  1243.         selType = pasteNormal;
  1244.     }
  1245.     else if (cf == CF_METAFILEPICT || cf == CF_DIB || cf == CF_BITMAP)
  1246.     {
  1247.         selType = pasteStatic;
  1248.     }
  1249.     return selType;
  1250. }
  1251.  
  1252. /////////////////////////////////////////////////////////////////////////////
  1253. // COlePasteSpecialDialog diagnostics
  1254.  
  1255. #ifdef _DEBUG
  1256. void COlePasteSpecialDialog::Dump(CDumpContext& dc) const
  1257. {
  1258.     COleDialog::Dump(dc);
  1259.  
  1260.     dc << "m_ps.cbStruct = " << m_ps.cbStruct;
  1261.     dc << "\nm_ps.dwFlags = " << (LPVOID)m_ps.dwFlags;
  1262.     dc << "\nm_ps.hWndOwner = " << (UINT)m_ps.hWndOwner;
  1263.     dc << "\nm_ps.lpszCaption = " << m_ps.lpszCaption;
  1264.     dc << "\nm_ps.lCustData = " << (LPVOID)m_ps.lCustData;
  1265.     dc << "\nm_ps.hInstance = " << (UINT)m_ps.hInstance;
  1266.     dc << "\nm_ps.lpszTemplate = " << (LPVOID)m_ps.lpszTemplate;
  1267.     dc << "\nm_ps.hResource = " << (UINT)m_ps.hResource;
  1268.     if (m_ps.lpfnHook == AfxOleHookProc)
  1269.         dc << "\nhook function set to standard MFC hook function";
  1270.     else
  1271.         dc << "\nhook function set to non-standard hook function";
  1272.     dc << "\nm_ps.lpSrcDataObj = " << (LPVOID)m_ps.lpSrcDataObj;
  1273.     dc << "\nm_ps.cPasteEntries = " << m_ps.cPasteEntries;
  1274.     dc << "\nm_ps.cLinkTypes = " << m_ps.cLinkTypes;
  1275.     dc << "\nm_ps.nSelectedIndex = " << m_ps.nSelectedIndex;
  1276.     dc << "\nm_ps.fLink = " << m_ps.fLink;
  1277.  
  1278.     dc << "\n";
  1279. }
  1280.  
  1281. void COlePasteSpecialDialog::AssertValid() const
  1282. {
  1283.     COleDialog::AssertValid();
  1284.     ASSERT(m_ps.cPasteEntries == 0 || m_ps.arrPasteEntries != NULL);
  1285.     ASSERT(m_ps.arrLinkTypes != NULL);
  1286.     ASSERT(m_ps.cLinkTypes <= 8);
  1287. }
  1288. #endif
  1289.  
  1290. ////////////////////////////////////////////////////////////////////////////
  1291.  
  1292. OLEUIPASTEFLAG COlePasteSpecialDialog::AddLinkEntry(UINT cf)
  1293. {
  1294.     ASSERT_VALID(this);
  1295.     ASSERT(m_ps.cLinkTypes <= 8);
  1296.     for (int i = 0; i < m_ps.cLinkTypes; i++)
  1297.     {
  1298.         if (m_ps.arrLinkTypes[i] == cf)
  1299.             break;
  1300.     }
  1301.     if (i == 8)
  1302.         return (OLEUIPASTEFLAG)0;
  1303.     m_ps.arrLinkTypes[i] = cf;
  1304.     if (i == m_ps.cLinkTypes)
  1305.         m_ps.cLinkTypes++;
  1306.     return (OLEUIPASTEFLAG) (OLEUIPASTE_LINKTYPE1 << i);
  1307. }
  1308.  
  1309. void COlePasteSpecialDialog::AddFormat(UINT cf, DWORD tymed, UINT nFormatID,
  1310.     BOOL bEnableIcon, BOOL bLink)
  1311. {
  1312.     TCHAR szFormat[256];
  1313.     if (AfxLoadString(nFormatID, szFormat) == 0)
  1314.         AfxThrowResourceException();
  1315.  
  1316.     // the format and result strings are delimited by a newline
  1317.     LPTSTR lpszResult = _tcschr(szFormat, '\n');
  1318.     ASSERT(lpszResult != NULL);  // must contain a newline
  1319.     *lpszResult = '\0';
  1320.     ++lpszResult;    // one char past newline
  1321.  
  1322.     // add it to the array of acceptable formats
  1323.     m_ps.arrPasteEntries = (OLEUIPASTEENTRY *)realloc(m_ps.arrPasteEntries,
  1324.         sizeof(OLEUIPASTEENTRY) * (m_ps.cPasteEntries +1));
  1325.  
  1326.     OLEUIPASTEENTRY* pEntry = &m_ps.arrPasteEntries[m_ps.cPasteEntries];
  1327.     pEntry->fmtetc.cfFormat = (CLIPFORMAT)cf;
  1328.     pEntry->fmtetc.dwAspect = DVASPECT_CONTENT;
  1329.     pEntry->fmtetc.ptd = NULL;
  1330.     pEntry->fmtetc.tymed = tymed;
  1331.     pEntry->fmtetc.lindex = -1;
  1332.     pEntry->lpstrFormatName = _tcsdup(szFormat);
  1333.     pEntry->lpstrResultText = _tcsdup(lpszResult);
  1334.     pEntry->dwFlags = OLEUIPASTE_PASTE;
  1335.  
  1336.     if (bEnableIcon)
  1337.         pEntry->dwFlags |= OLEUIPASTE_ENABLEICON;
  1338.     if (bLink)
  1339.         pEntry->dwFlags |= AddLinkEntry(cf);
  1340.     if (pEntry->dwFlags == OLEUIPASTE_PASTE)
  1341.         pEntry->dwFlags = OLEUIPASTE_PASTEONLY;
  1342.     pEntry->dwScratchSpace = NULL;
  1343.     m_ps.cPasteEntries++;
  1344. }
  1345.  
  1346. // if the flags parameter includes a LINKTYPE# flag, it should be obtained
  1347. // from AddLinkEntry
  1348. void COlePasteSpecialDialog::AddFormat(const FORMATETC& formatEtc,
  1349.     LPTSTR lpszFormat, LPTSTR lpszResult, DWORD dwFlags)
  1350. {
  1351.     ASSERT_VALID(this);
  1352.  
  1353.     m_ps.arrPasteEntries = (OLEUIPASTEENTRY *)realloc(
  1354.         m_ps.arrPasteEntries, sizeof(OLEUIPASTEENTRY) * (m_ps.cPasteEntries +1));
  1355.     OLEUIPASTEENTRY* pEntry = &m_ps.arrPasteEntries[m_ps.cPasteEntries];
  1356.     pEntry->fmtetc = formatEtc;
  1357.     pEntry->lpstrFormatName = _tcsdup(lpszFormat);
  1358.     pEntry->lpstrResultText = _tcsdup(lpszResult);
  1359.     pEntry->dwFlags = dwFlags;
  1360.     pEntry->dwScratchSpace = NULL;
  1361.     m_ps.cPasteEntries++;
  1362. }
  1363.  
  1364. void COlePasteSpecialDialog::AddStandardFormats(BOOL bEnableLink)
  1365. {
  1366.     // Note: only need to add Embedded Object because Embed Source is
  1367.     //  automatically recognized by the paste special dialog implementation.
  1368.     ASSERT(_oleData.cfEmbeddedObject != NULL);
  1369.     AddFormat(_oleData.cfEmbeddedObject, TYMED_ISTORAGE, AFX_IDS_EMBED_FORMAT,
  1370.         TRUE, FALSE);
  1371.  
  1372.     // add link source if requested
  1373.     if (bEnableLink)
  1374.     {
  1375.         ASSERT(_oleData.cfLinkSource != NULL);
  1376.         AddFormat(_oleData.cfLinkSource, TYMED_ISTREAM, AFX_IDS_LINKSOURCE_FORMAT,
  1377.             TRUE, TRUE);
  1378.     }
  1379.  
  1380.     // add formats that can be used for 'static' items
  1381.     AddFormat(CF_METAFILEPICT, TYMED_MFPICT, AFX_IDS_METAFILE_FORMAT,
  1382.         FALSE, FALSE);
  1383.     AddFormat(CF_DIB, TYMED_HGLOBAL, AFX_IDS_DIB_FORMAT, FALSE, FALSE);
  1384.     AddFormat(CF_BITMAP, TYMED_GDI, AFX_IDS_BITMAP_FORMAT, FALSE, FALSE);
  1385. }
  1386.  
  1387. BOOL COlePasteSpecialDialog::CreateItem(COleClientItem *pNewItem)
  1388. {
  1389.     ASSERT_VALID(this);
  1390.     ASSERT(pNewItem != NULL);
  1391.     ASSERT(m_ps.lpSrcDataObj != NULL);
  1392.  
  1393.     CWaitCursor wait;
  1394.  
  1395.     COleDataObject dataObject;
  1396.     dataObject.Attach(m_ps.lpSrcDataObj, FALSE);
  1397.  
  1398.     UINT selType = GetSelectionType();
  1399.     BOOL bResult = TRUE;
  1400.  
  1401.     switch (selType)
  1402.     {
  1403.     case pasteLink:
  1404.         // paste link
  1405.         if (!pNewItem->CreateLinkFromData(&dataObject))
  1406.         {
  1407.             TRACE0("Warning: CreateLinkFromData failed.\n");
  1408.             bResult = FALSE;
  1409.         }
  1410.         break;
  1411.     case pasteStatic:
  1412.         if (!pNewItem->CreateStaticFromData(&dataObject))
  1413.         {
  1414.             TRACE0("Warning: CreateStaticFromData failed.\n");
  1415.             bResult = FALSE;
  1416.         }
  1417.         break;
  1418.     default:
  1419.         ASSERT(selType == pasteNormal);
  1420.         if (!pNewItem->CreateFromData(&dataObject))
  1421.         {
  1422.             TRACE0("Warning: CreateFromData failed.\n");
  1423.             bResult = FALSE;
  1424.         }
  1425.         break;
  1426.     }
  1427.  
  1428.     // deal with Display As Iconic option
  1429.     if (bResult && GetDrawAspect() == DVASPECT_ICON)
  1430.     {
  1431.         // setup iconic cache (it will draw iconic by default as well)
  1432.         if (!pNewItem->SetIconicMetafile(m_ps.hMetaPict))
  1433.         {
  1434.             TRACE0("Warning: failed to set iconic aspect.\n");
  1435.             bResult = FALSE;
  1436.         }
  1437.         else
  1438.         {
  1439.             // since picture was set OK, draw as iconic as well...
  1440.             pNewItem->SetDrawAspect(DVASPECT_ICON);
  1441.         }
  1442.     }
  1443.     return bResult;
  1444. }
  1445.  
  1446. /////////////////////////////////////////////////////////////////////////////
  1447. // Inline function declarations expanded out-of-line
  1448.  
  1449. #ifndef _AFX_ENABLE_INLINES
  1450.  
  1451. // expand inlines for OLE dialog APIs
  1452. static char _szAfxOleInl[] = "afxole.inl";
  1453. #undef THIS_FILE
  1454. #define THIS_FILE _szAfxOleInl
  1455. #define _AFXODLGS_INLINE
  1456. #include "afxole.inl"
  1457.  
  1458. #endif //!_AFX_ENABLE_INLINES
  1459.  
  1460. #ifdef AFX_INIT_SEG
  1461. #pragma code_seg(AFX_INIT_SEG)
  1462. #endif
  1463.  
  1464. IMPLEMENT_DYNAMIC(COleInsertDialog, COleDialog)
  1465. IMPLEMENT_DYNAMIC(COleConvertDialog, COleDialog)
  1466. IMPLEMENT_DYNAMIC(COleChangeIconDialog, COleDialog)
  1467. IMPLEMENT_DYNAMIC(COleLinksDialog, COleDialog)
  1468. IMPLEMENT_DYNAMIC(COleUpdateDialog, COleLinksDialog)
  1469. IMPLEMENT_DYNAMIC(COlePasteSpecialDialog, COleDialog)
  1470.  
  1471. /////////////////////////////////////////////////////////////////////////////
  1472.