home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / BOCOLE.PAK / BOLEPART.CPP < prev    next >
C/C++ Source or Header  |  1995-08-29  |  120KB  |  3,186 lines

  1. //
  2. //
  3. //**************************************************************************
  4. //
  5. // BOlePart.cpp -- Implements the Bolero half of the OLE2 client site.
  6. //                 BOlePart objects impersonate the server object (IPart)
  7. //                 from the point of view of the Bolero customer who's
  8. //                 writing a client site (ISite)
  9. //
  10. // Copyright (c) 1993,94 by Borland International, Inc. All rights reserved
  11. //
  12. //**************************************************************************
  13.  
  14. #include "BOleSvc.h"
  15. #include "BOleDoc.h"
  16. #include "BOlePart.h"
  17. #include "BOleData.h"
  18. #include "BOleCMan.h"
  19.  
  20.  
  21. //
  22. //
  23. //
  24. //
  25. //
  26. //
  27. //
  28. //
  29. //
  30. //
  31. //
  32. //
  33. //
  34. //
  35. //
  36. //
  37. //
  38. //
  39. //
  40. //
  41. //
  42.  
  43. // MulDiv uses int; won't work with HIMETRIC values
  44. //
  45. inline int Scale(double src, long mult, long div)
  46. {
  47.         src *= mult;
  48.         src += (div/2); //
  49.         src /= div;
  50.         return (int) src;
  51. }
  52.  
  53. const OLECHAR szcBOlePart[] = TEXT("\3BOlePart");
  54.  
  55. // Since we don't know why Excel returns RPC_E_CALL_REJECTED the
  56. // first N times and then finally works, we have this kludge.
  57. //
  58. HRESULT ForceOleRun(IOleObject *pOO)
  59. {
  60.         int timeout = 500;
  61.         while (timeout-- > 0) {
  62.                 if (ResultFromScode(RPC_E_CALL_REJECTED) != OleRun(pOO))
  63.                         break;
  64.         }
  65.         return (timeout == 0) ? ResultFromScode(RPC_E_CALL_REJECTED) : NOERROR;
  66. }
  67.  
  68.  
  69. HRESULT _IFUNC BOlePart::QueryInterfaceMain(REFIID iid, LPVOID FAR *ppv)
  70. {
  71.         HRESULT hr = ResultFromScode(E_NOINTERFACE);
  72.         *ppv = NULL;
  73.  
  74.         // Self
  75.         //
  76.         if (iid == IID_BOlePart) {
  77.                 (BOlePart*) *ppv = this;
  78.                 AddRef ();
  79.                 return NOERROR;
  80.         }
  81.  
  82.         // interfaces
  83.  
  84.            SUCCEEDED(hr = IOleInPlaceSite_QueryInterface(this, iid, ppv))
  85.         || SUCCEEDED(hr = IOleClientSite_QueryInterface(this, iid, ppv))
  86.         || SUCCEEDED(hr = IAdviseSink_QueryInterface(this, iid, ppv))
  87.  //       || SUCCEEDED(hr = IBPart_QueryInterface(this, iid, ppv))
  88.         || SUCCEEDED(hr = IBPart2_QueryInterface(this, iid, ppv))
  89.         || SUCCEEDED(hr = IBLinkable_QueryInterface(this, iid, ppv))
  90. #ifdef PART_DATA
  91.         || SUCCEEDED(hr = IPersist_QueryInterface(this, iid, ppv))
  92.         || SUCCEEDED(hr = IDataObject_QueryInterface(this, iid, ppv))
  93.         || SUCCEEDED(hr = IEnumFORMATETC_QueryInterface(this, iid, ppv))
  94. #endif
  95.         || SUCCEEDED(hr = IDropSource_QueryInterface(this, iid, ppv))
  96.         || (IsLink && SUCCEEDED(hr = IBLinkInfo_QueryInterface(this, iid, ppv)))
  97.  
  98.         // base classes
  99.  
  100.         || SUCCEEDED(hr = BOleComponent::QueryInterfaceMain(iid, ppv))
  101.  
  102.         ;
  103.  
  104.         return hr;
  105. };
  106.  
  107. //**************************************************************************
  108. //
  109. // BOlePart implementation -- functions which aren't part of any inherited
  110. //                            interface, but are just part of the private
  111. //                            implementation
  112. //
  113. //**************************************************************************
  114.  
  115. BOlePart::BOlePart (BOleClassManager *pF, IBUnknownMain * pO, BOleDocument * pOD) :
  116.         BOleComponent(pF, pO),
  117.         pDoc (pOD),             pOleObject(NULLP),   pViewObject(NULLP),
  118.         pInPlaceObject(NULLP),  pSite (NULLP),       pVerbEnumerator(NULLP),
  119.         verbIndex(0),           dwDrawAspect (0),    IsOpen(FALSE),
  120.         HasMoniker(FALSE),      IsOpenInPlace(FALSE),IsOpenInsideOut(FALSE),
  121.         IsLink (FALSE),         pNextPart(NULLP),    pPrevPart (NULLP),
  122.         pLinkObject (NULLP),    dwExtAspect(0),      pStgFromInit(NULLP),
  123.         pDataObject (NULLP),    pEnumFE (NULLP),     MonikerAssigned(FALSE),
  124.         pILinkCont (0),         pszInstName (NULLP), pShortName (NULL),
  125.         pLongName (NULL),       pAppName (NULL),     fLinkSrcAvail(TRUE),
  126.         pDocument (NULL)
  127. {
  128.         if (pDoc)
  129.                 pDoc->AddRefMain();
  130.  
  131.         oleVerb.lpszVerbName = NULLP;
  132.         mfpIcon = NULL;
  133.         CachedExtent.cx = CachedExtent.cy = 0;        //
  134.         scaleSite.xN = 1L;
  135.         scaleSite.xD = 1L;
  136.         scaleSite.yN = 1L;
  137.         scaleSite.yD = 1L;
  138.         OLEPRINTF5("Initializing scaleSite:\t {%ld, %ld, %ld, %ld}",
  139.                 scaleSite.xN, scaleSite.xD, scaleSite.yN, scaleSite.yD);
  140. }
  141.  
  142.  
  143. BOlePart::~BOlePart()
  144. {
  145.         Close();  // just to be sure
  146.  
  147.         if (pszInstName) {
  148.                 delete [] pszInstName;
  149.                 pszInstName = NULLP;
  150.         }
  151.  
  152.         if (pDocument) {        // set in BOleContainer::GetObject
  153.                 CoLockObjectExternal(pDocument, FALSE, FALSE);
  154.                 pDocument = NULL;
  155.         }
  156.         DeleteTypeNames();
  157. }
  158.  
  159. void BOlePart::DeleteTypeNames ()
  160. {
  161.     // Delete any type names which were allocated in IOleObject::GetUserType
  162.         //
  163.         if (pLongName || pShortName || pAppName) {
  164.                 LPMALLOC pMalloc = NULL;
  165.                 HRESULT hr = ::CoGetMalloc (MEMCTX_TASK, &pMalloc);
  166.                 if (SUCCEEDED(hr)) {
  167.                         if (pShortName) {
  168.                                 if (pMalloc->DidAlloc(pShortName))
  169.                                 pMalloc->Free (pShortName);
  170.                                 pShortName = NULLP;
  171.                         }
  172.                         if (pAppName) {
  173.                                 if (pMalloc->DidAlloc(pAppName))
  174.                                 pMalloc->Free (pAppName);
  175.                                 pAppName = NULLP;
  176.                         }
  177.                         if (pLongName) {
  178.                                 if (pMalloc->DidAlloc(pLongName))
  179.                                 pMalloc->Free (pLongName);
  180.                                 pLongName = NULLP;
  181.                         }
  182.                         pMalloc->Release ();
  183.                 }
  184.         }
  185. }
  186.  
  187. // Close -- Let go of all our connections to the server object
  188. //
  189. HRESULT _IFUNC BOlePart::Close()
  190. {
  191.         // We should let go of all server resources to allow the server to quit.
  192.         //
  193.         HRESULT hRes = NOERROR;
  194.  
  195.         RemoveFromList ();
  196.  
  197.         // Ask the server to close its document and exit its program
  198.         if (pOleObject) {
  199.                 hRes = pOleObject->Close(OLECLOSE_SAVEIFDIRTY);
  200.                 IsOpen = FALSE;
  201.         }
  202.  
  203.         if (pOleObject) {
  204.                 pOleObject->Release();
  205.                 pOleObject = NULL;
  206.         }
  207.         if (pViewObject) {
  208.                 pViewObject->Release();
  209.                 pViewObject = NULL;
  210.         }
  211.         if (pDataObject) {
  212.                 pDataObject->Release();
  213.                 pDataObject = NULL;
  214.         }
  215.         if (pEnumFE) {
  216.                 //
  217.                 pEnumFE = NULL;
  218.         }
  219.         if (pDoc) {
  220.                 pDoc->ReleaseMain();        // dec count on helper
  221.                 pDoc = NULL;
  222.         }
  223.         if (pLinkObject) {
  224.                 pLinkObject->Release();
  225.                 pLinkObject = NULL;
  226.         }
  227.         if (pStgFromInit) {
  228.                 pStgFromInit->Release ();
  229.                 pStgFromInit = NULL;
  230.         }
  231.  
  232.         // Required for AVI media stuff to release properly.
  233.         // And DLL servers
  234.         //
  235.         CoFreeUnusedLibraries();
  236.  
  237.         return hRes;
  238. }
  239.  
  240. BOOL _IFUNC BOlePart::InitAdvises(LPOLEOBJECT lpOleObject,
  241.                                   DWORD dwDrawAspect,
  242.                                   LPOLESTR lpszContainerApp,
  243.                                   LPOLESTR lpszContainerObj,
  244.                                   LPADVISESINK lpAdviseSink,
  245.                                   BOOL fCreate)
  246. {
  247.         LPVIEWOBJECT lpViewObject;
  248.         HRESULT hrErr;
  249.         BOOL fStatus = TRUE;
  250. #if defined( SPECIAL_CONTAINER )
  251.         DWORD dwTemp;
  252. #endif
  253.  
  254.         hrErr = lpOleObject->QueryInterface (IID_IViewObject,
  255.                 (LPVOID FAR*)&lpViewObject);
  256.  
  257.         // Setup View advise
  258.         //
  259.         if (hrErr == NOERROR) {
  260.  
  261.                 lpViewObject->SetAdvise(dwDrawAspect, (fCreate ? ADVF_PRIMEFIRST : 0),
  262.                         lpAdviseSink);
  263.  
  264.                 lpViewObject->Release();
  265.         } else
  266.                 fStatus = FALSE;
  267.  
  268. #if defined( SPECIAL_CONTAINER )
  269.         /* Setup OLE advise.
  270.         **    OLE2NOTE: normally containers do NOT need to setup an OLE
  271.         **    advise. this advise connection is only useful for the OLE's
  272.         **    DefHandler and the OleLink object implementation. some
  273.         **    special container's might need to setup this advise for
  274.         **    programatic reasons.
  275.         **
  276.         **    NOTE: this advise will be torn down automatically by the
  277.         **    server when we release the object, therefore we do not need
  278.         **    to store the connection id.
  279.         */
  280.         hrErr = lpOleObject->Advise(lpAdviseSink, (DWORD FAR*)&dwTemp);
  281.         if (hrErr != NOERROR)
  282.                 fStatus = FALSE;
  283. #endif
  284.  
  285.         // Setup the host names for the OLE object.
  286.         //
  287.         hrErr = lpOleObject->SetHostNames(lpszContainerApp,lpszContainerObj);
  288.         if (hrErr != NOERROR)
  289.                 fStatus = FALSE;
  290.  
  291.         // Inform the loadded object's handler/inproc-server that it is in
  292.         //    its embedding container's process.
  293.         //
  294.         OleSetContainedObject(lpOleObject, TRUE);
  295.  
  296.         return fStatus;
  297. }
  298.  
  299. #ifdef __BORLANDC__ //PHP OpenStream block is optimized incorrectly
  300. #pragma option -Od
  301. #endif
  302.  
  303. HRESULT BOlePart::CreateFromBOleInitInfo(BOleInitInfo *pBI, BOOL &fShowAfterCreate)
  304. {
  305.         HRESULT hRes = ResultFromScode(E_INVALIDARG);
  306.         // another result code which can fail without causing Init to fail
  307.         HRESULT hrOkToFail;
  308.  
  309.         BOOL fIcon = pBI->hIcon != NULL;
  310.         DWORD dwRenderOpt = fIcon ? OLERENDER_NONE : OLERENDER_DRAW;
  311.  
  312.         dwDrawAspect = fIcon ? DVASPECT_ICON : DVASPECT_CONTENT;
  313.  
  314.         switch (pBI->Where) {
  315.                 case BOLE_STORAGE: {
  316.  
  317.                         // Load the OLE object's display aspect out of the stream we
  318.                         // dumped it in. This is all we need to do in order to make
  319.                         // drawing aspects persistent
  320.                         //
  321.                         LPSTREAM pStream;
  322.                         if (SUCCEEDED (pStgFromInit->OpenStream (szcBOlePart, NULL,
  323.                                 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream)))  {
  324.                                 ULONG cb;
  325.                                 pStream->Read (&dwDrawAspect, sizeof(dwDrawAspect), &cb);
  326.                                 if (dwDrawAspect == DVASPECT_ICON) {
  327.                                         fIcon = TRUE;
  328.                                         dwRenderOpt = OLERENDER_NONE;
  329.                                 }
  330.                                 if (!fIcon) {
  331.                                         pStream->Read (&scaleSite, sizeof(scaleSite), &cb);
  332.                                         OLEPRINTF5("Reading scaleSite:\t {%ld, %ld, %ld, %ld}",
  333.                                                 scaleSite.xN, scaleSite.xD, scaleSite.yN, scaleSite.yD);
  334.                                         SIZE size;
  335.                                         size.cx = scaleSite.xD;     // server's extent's in Denom
  336.                                         size.cy = scaleSite.yD;
  337.  
  338.                                         if (!(size.cx == 1 && size.cy == 1))
  339.                                                 // if scale factor exists,
  340.                                                 // force the server to restore the extent from last time.
  341.  
  342.                                                 // because Word doesn't put height back to what
  343.                                                 // it was before. (they only load the width??)
  344.                                                 SetPartSize(&size);
  345.                                 }
  346.                                 pStream->Release ();
  347.                         }
  348.                         // Load OLE object from container's file
  349.                         //
  350.                         hRes = OLE::OleLoad (pStgFromInit, IID_IOleObject, this, &(LPVOID)pOleObject);
  351.  
  352.                         // Don't activate OLE objects when loading container's file. If there
  353.                         // are a bunch of objects, or if the server is a big app, performance
  354.                         // would be severely degraded.
  355.                         //
  356.                         fShowAfterCreate = FALSE;
  357.                         break;
  358.                 }
  359.  
  360.                 case BOLE_NEW:
  361.  
  362.                         hRes = OLE::OleCreate (*(LPIID)pBI->whereNew.cid, IID_IOleObject, dwRenderOpt,
  363.                                 NULL, this, pStgFromInit, &(LPVOID) pOleObject);
  364.  
  365.                         // Find out whether the object is inside out.
  366.                         //
  367.                         if (hRes == NOERROR) {
  368.                                 if (dwDrawAspect == DVASPECT_CONTENT) {
  369.                                         DWORD status = 0;
  370.  
  371.                                         // Cl2test is passing 0 and ignoring the
  372.                                         // error from Shapes. If I use the real aspect, outline returns
  373.                                         // that it's an inside-out object. Crazy.
  374.                                         //
  375.                                         hrOkToFail = pOleObject->GetMiscStatus (dwDrawAspect, &status);
  376.                                         if (hrOkToFail != NOERROR)
  377.                                                 IsOpenInsideOut = FALSE;
  378.                                         else
  379.                                                 IsOpenInsideOut = (status & (OLEMISC_INSIDEOUT|OLEMISC_ACTIVATEWHENVISIBLE)) ?
  380.                                                         TRUE : FALSE;
  381.                                 }
  382.                         }
  383.                         break;
  384.  
  385.                 case BOLE_FILE:
  386.  
  387.                         if (pBI->How == BOLE_EMBED) {
  388.                                 hRes = OLE::OleCreateFromFile(CLSID_NULL, pBI->whereFile.pPath, IID_IOleObject,
  389.                                 dwRenderOpt, NULL, this, pStgFromInit, &(VOID FAR*)pOleObject);
  390.  
  391.                                 fShowAfterCreate = FALSE;
  392.                         }
  393.                         else {
  394.                                 hRes = OLE::OleCreateLinkToFile (pBI->whereFile.pPath, IID_IOleObject,
  395.                                         dwRenderOpt, NULL, this, pStgFromInit, &(VOID FAR*)pOleObject);
  396.  
  397.                                 // User should double-click to open link source. Showing the
  398.                                 // object here would bring up the server out-of-place, which
  399.                                 // would obscure the link we just created.
  400.                                 //
  401.                                 fShowAfterCreate = FALSE;
  402.                         }
  403.                         break;
  404.  
  405.                 case BOLE_DATAOBJECT:
  406.  
  407.                         if (pBI->How == BOLE_EMBED) {
  408.                                 hRes = OLE::OleCreateFromData (pBI->whereData.pData, IID_IOleObject,
  409.                                         OLERENDER_DRAW, NULL, this, pStgFromInit, &(VOID FAR*)pOleObject);
  410.  
  411.                                 // This is the result of a drop or a paste special. The UI
  412.                                 // convention is not to inplace activate the server
  413.                                 //
  414.                                 fShowAfterCreate = FALSE;
  415.                         }
  416.                         else if (pBI->How == BOLE_LINK) {
  417.  
  418.                                 hRes = OLE::OleCreateLinkFromData (pBI->whereData.pData, IID_IOleObject,
  419.                                         OLERENDER_DRAW, NULL, this, pStgFromInit, &(VOID FAR*)pOleObject);
  420.  
  421.                                 // User should double-click to open link source. Showing the
  422.                                 // object here would bring up the server out-of-place, which
  423.                                 // would obscure the link we just created.
  424.                                 //
  425.                                 fShowAfterCreate = FALSE;
  426.  
  427.                         }
  428.                         else {
  429.                                 hRes = OleCreateStaticFromData (pBI->whereData.pData, IID_IOleObject,
  430.                                         OLERENDER_DRAW, NULL, this, pStgFromInit, &(LPVOID) pOleObject);
  431.                                 fShowAfterCreate = FALSE;
  432.                         }
  433.  
  434. //
  435. //
  436. //
  437.  
  438.                         // Get the drawing aspect for the object.
  439.                         //
  440.                         STGMEDIUM stgmed;
  441.                         dwDrawAspect = fIcon ? DVASPECT_ICON : DVASPECT_CONTENT;
  442.                         HGLOBAL memhandle = pDoc->pService->GetDataFromDataObject (
  443.                                 pBI->whereData.pData, BOleDocument::oleObjectDescFmt, NULL,
  444.                                 DVASPECT_CONTENT, &stgmed);
  445.                         if (memhandle) {
  446.                                 LPOBJECTDESCRIPTOR objDesc = (LPOBJECTDESCRIPTOR) WIN::GlobalLock (memhandle);
  447.                                 if (objDesc->dwDrawAspect == DVASPECT_ICON)
  448.                                         dwDrawAspect = DVASPECT_ICON;
  449.                                 WIN::GlobalUnlock (memhandle);
  450.                                 OLE::ReleaseStgMedium (&stgmed);
  451.                         }
  452.  
  453.                         // Find out whether the object is inside out.
  454.                         //
  455.                         if (hRes == NOERROR)
  456.                                 if (dwDrawAspect == DVASPECT_CONTENT) {
  457.                                         DWORD status;
  458.                                         pOleObject->GetMiscStatus (dwDrawAspect, &status);
  459.                                         IsOpenInsideOut = (status & (OLEMISC_INSIDEOUT|OLEMISC_ACTIVATEWHENVISIBLE)) ?
  460.                                                 TRUE : FALSE;
  461.                                 }
  462.                         break;
  463.         }
  464.         if (SUCCEEDED(hRes) && !pOleObject)
  465.                 hRes = ResultFromScode(E_NOINTERFACE);
  466.  
  467.         return hRes;
  468. }
  469.  
  470. #ifdef __BORLANDC__
  471. #pragma option -O.
  472. #endif
  473.  
  474. // Init -- Create a new OLE2 server object. Probably the BOlePart helper
  475. //         has just been created, and it's time to initiate OLE2 transactions
  476. //
  477. HRESULT _IFUNC BOlePart::Init(IBSite * pIS,BOleInitInfo *pBI)
  478. {
  479.  
  480. #ifdef _DEBUG
  481.  
  482.         // Test to make sure client's QueryInterface is implemented correctly
  483.         //
  484.         IBSite *dbgSite = NULL;
  485.         LPOLECLIENTSITE dbgCSite = NULL;
  486.         if (  (!SUCCEEDED(pObjOuter->QueryInterfaceMain(IID_IBSite, &(LPVOID)dbgSite)))
  487.                 || (!SUCCEEDED(pObjOuter->QueryInterfaceMain(IID_IOleClientSite,&(LPVOID)dbgCSite)))) {
  488.                 MessageBox (NULL,
  489.                         OLESTR("QueryInterface Aggregation isn\'t working right"),
  490.                         OLESTR("BOlePart::Init"), MB_OK);
  491.         }
  492.         else {
  493.                 dbgSite->Release();
  494.                 dbgCSite->Release();
  495.                 dbgSite = NULL;
  496.                 dbgCSite = NULL;
  497.         }
  498.  
  499. #endif
  500.  
  501.  
  502.         pSite = pIS;
  503.  
  504.         if (pBI->pContainer) {
  505.                 BOleDocument *oldDoc = pDoc;
  506.                 if (!SUCCEEDED(pBI->pContainer->QueryInterface(IID_BOleDocument, &(LPVOID) pDoc)))
  507.                         return ResultFromScode (E_NOINTERFACE);
  508.                 pDoc->Release();        // PREVENT CYCLE
  509.  
  510.                 // Since passing the container in the init info was added later, this
  511.                 // makes the reference counting semantic on our BOleDocument pointer
  512.                 // the same as is done in BOlePart::BOlePart and BOlePart::Close
  513.                 //
  514.                 pDoc->AddRefMain();             // AddRef the new doc from the init info
  515.                 if (oldDoc)
  516.                         oldDoc->ReleaseMain();  // Release the doc from the constructor
  517.  
  518.                 pContainer = pBI->pContainer;
  519.         }
  520.         else
  521.                 //  Only work if the caller is not a container/server
  522.                 pContainer = pDoc->GetContainer();
  523.  
  524.         AddToList ();
  525.  
  526.         pStgFromInit = pBI->pStorage;
  527.         pStgFromInit->AddRef();
  528.  
  529.         HRESULT hRes = ResultFromScode (E_INVALIDARG);
  530.  
  531.         BOOL fShowAfterCreate = TRUE;
  532.  
  533.         for (int idx=0; idx < 42; idx++) {    // knock 42 times if you want Excel
  534.                 if (ResultFromScode(RPC_E_CALL_REJECTED) !=
  535.                         (hRes = CreateFromBOleInitInfo(pBI, fShowAfterCreate)))
  536.                         break;
  537.         }
  538.  
  539.         if (!SUCCEEDED(hRes))
  540.                 return hRes;
  541.  
  542.         // Do standard initialization on the freshly created object
  543.         // where pOleObject is valid
  544.  
  545.  
  546.         // If we have to draw as an icon, make sure the IOleCache in
  547.         // handler for this OLE object has an iconic representation
  548.         //
  549.         // If we're loading from storage, just run the usual advises
  550.         //
  551.         if (dwDrawAspect == DVASPECT_ICON && pBI->Where != BOLE_STORAGE) {
  552. #if 0
  553.                 if (pBI->Where == BOLE_FILE)
  554.                         mfpIcon = OleGetIconOfFile ((LPSTR)(pBI->whereFile.pPath), TRUE);
  555.                 else {
  556.                         OLECHAR buf[128] = {0,};
  557.                         mfpIcon = OleGetIconOfClass (*(LPIID)pBI->whereNew.cid, buf, TRUE);
  558.                 }
  559. #endif
  560.                 mfpIcon = pBI->hIcon;
  561.                 CacheIconicAspect (mfpIcon);
  562.                 OnViewChange(dwDrawAspect, -1);
  563.         }
  564.         else {
  565.                 IBApplication * pApplication = pDoc->pApplication;
  566.                 InitAdvises (pOleObject, dwDrawAspect,
  567.                         (LPOLESTR)pApplication->GetAppName(),
  568.                         (LPOLESTR)pContainer->GetWindowTitle(), this, (pBI->Where != BOLE_STORAGE));
  569.                 //
  570.                 //
  571.         }
  572.  
  573.         if (fShowAfterCreate && hRes == NOERROR)
  574.                 hRes = DoVerb(OLEIVERB_SHOW);
  575.  
  576.         // Cache the view object interface for drawing later on
  577.         //
  578.         pOleObject->QueryInterface (IID_IViewObject, &(VOID FAR*)pViewObject);
  579.  
  580.         // Cache the data object interface for "embed from embedding"
  581.         //
  582.         pOleObject->QueryInterface (IID_IDataObject, &(VOID FAR*)pDataObject);
  583.  
  584.         // Cache the "user type name" for enumerating verbs later on
  585.         //
  586.         pOleObject->GetUserType (USERCLASSTYPE_SHORT, &pShortName);
  587.  
  588.         //      Ask the OLE object if it's a link, and cache the pointer if so
  589.         //
  590.         IsLink = SUCCEEDED(pOleObject->QueryInterface (IID_IOleLink, &(VOID FAR*) pLinkObject));
  591.  
  592.         return hRes;
  593. }
  594.  
  595. // Copies CF_EMBEDDEDOBJECT into a BOleData cache so we can do embed from
  596. // embedding with a snapshot of the embedded object. This allows the user to
  597. // change the original embedding and still paste the snapshot later.
  598. //
  599. HRESULT _IFUNC BOlePart::CopyFromOriginal (LPFORMATETC pFE, LPDATAOBJECT FAR*ppCopy)
  600. {
  601. //
  602. //
  603.  
  604.         *ppCopy = NULL;
  605.  
  606.         // Get the original object's IDataObject and IPersistStorage interfaces
  607.         // so we can write it into our cache. The server object must support
  608.         // these interfaces.
  609.         //
  610. #if 1
  611.         // We have to make sure that we DO need to know that this guy implements
  612.         // IDataObject, otherwise, just use the other branch
  613.         LPDATAOBJECT pOrig;
  614.         HRESULT hr = pOleObject->QueryInterface (IID_IDataObject, &(LPVOID) pOrig);
  615.         if (!SUCCEEDED(hr))
  616.                 return hr;
  617.         LPPERSISTSTORAGE pPersistStg = NULL;
  618.         hr = pOrig->QueryInterface (IID_IPersistStorage, &(LPVOID) pPersistStg);
  619.         // JP: Now no longer use pOrig. Lets release it
  620.         pOrig->Release();
  621.         if (!SUCCEEDED(hr))
  622.                 return hr;
  623. #else
  624.         HRESULT hr = pOleObject->QueryInterface( IID_IPersistStorage, &(LPVOID) pPersistStg);
  625.         if (!SUCCEEDED(hr))
  626.                 return hr;
  627. #endif
  628.         // Create the data cache object which will hold the snapshots in as many
  629.         // formats as we need
  630.         //
  631.         LPUNKNOWN pObjDataCache = NULL;
  632.         hr = pFactory->ComponentCreate ((LPUNKNOWN FAR*)&pObjDataCache, NULL, cidBOleData);
  633.         if (!SUCCEEDED(hr))
  634.                 return hr;
  635.         LPDATAOBJECT pIDataCache = NULL;
  636.         hr = pObjDataCache->QueryInterface (IID_IDataObject, &(LPVOID)pIDataCache);
  637.         pObjDataCache->Release(); //JP
  638.         pObjDataCache = NULL;
  639.  
  640.         if (!SUCCEEDED(hr))
  641.                 return hr;
  642.  
  643.         // Create a temporary docfile which will hold the data
  644.         //
  645.         STGMEDIUM stm;
  646.         _fmemset (&stm, 0, sizeof(STGMEDIUM));
  647.         stm.tymed = TYMED_ISTORAGE;
  648.         hr = ::StgCreateDocfile (NULL, STGM_TRANSACTED | STGM_READWRITE |
  649.                 STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stm.pstg);
  650.         if (!SUCCEEDED(hr))
  651.                 return hr;
  652.  
  653.         // Save the original OLE server object into our temporary docfile
  654.         //
  655.         if (pPersistStg->IsDirty () == NOERROR) {
  656.                 ::OleSave (pPersistStg, stm.pstg, FALSE);
  657.                 pPersistStg->SaveCompleted (NULL);
  658.         }
  659.         else
  660.                 pStgFromInit->CopyTo (0, NULL, NULL, stm.pstg);
  661.         pPersistStg->Release ();
  662.  
  663.         FORMATETC fe;
  664.         _fmemset (&fe, 0, sizeof(FORMATETC));
  665.         fe.cfFormat = BOleDocument::oleEmbdObjClipFmt;
  666.         fe.ptd = NULL;
  667.         fe.dwAspect = dwDrawAspect;
  668.         fe.lindex = -1;
  669.         fe.tymed = TYMED_ISTORAGE;
  670.  
  671.         hr = pIDataCache->SetData (&fe, &stm, TRUE);
  672.         if (!SUCCEEDED(hr))
  673.                 return hr; //
  674.  
  675.         stm.tymed = TYMED_HGLOBAL;
  676.         fe.cfFormat = BOleDocument::oleObjectDescFmt;
  677.         fe.tymed = TYMED_HGLOBAL;
  678.         POINTL unused = {0,0};
  679.         SIZEL unused2 = {0,0};
  680.         stm.hGlobal = OleStdGetObjectDescriptorDataFromOleObject (pOleObject,
  681.                 NULL, dwDrawAspect, unused, &unused2);
  682.         hr = pIDataCache->SetData (&fe, &stm, TRUE);
  683.         if (!SUCCEEDED(hr))
  684.                 return hr; //
  685.  
  686.         AddSiteData (pIDataCache);
  687.         AddCachedData( pIDataCache );
  688.  
  689.         // Setup linking formats for linking to embedding (if possible)
  690.         //
  691.         DWORD dwStat=0L;
  692.         pOleObject->GetMiscStatus (dwDrawAspect, &dwStat);
  693.         if (!(OLEMISC_CANTLINKINSIDE & dwStat)) // (says can't do in registry)
  694.                 AddLinkSourceData (pIDataCache);
  695.  
  696.         *ppCopy = pIDataCache;
  697.         return NOERROR;
  698.  
  699. }
  700.  
  701. HRESULT _IFUNC BOlePart::SwitchDisplayAspect(
  702.                 LPOLEOBJECT             lpOleObj,
  703.                 LPDWORD                 lpdwCurAspect,
  704.                 DWORD                   dwNewAspect,
  705.                 HGLOBAL                 hMetaPict,
  706.                 BOOL                    fDeleteOldAspect,
  707.                 BOOL                    fSetupViewAdvise,
  708.                 LPADVISESINK            lpAdviseSink,
  709.                 BOOL FAR*               lpfMustUpdate,
  710.                 BOOL                    fRunIfNecessary
  711. )
  712. {
  713.         LPOLECACHE      lpOleCache = NULL;
  714.         LPVIEWOBJECT    lpViewObj = NULL;
  715.         LPENUMSTATDATA  lpEnumStatData = NULL;
  716.         STATDATA        StatData;
  717.         FORMATETC       FmtEtc;
  718.         STGMEDIUM       Medium;
  719.         DWORD           dwAdvf;
  720.         DWORD           dwNewConnection;
  721.         DWORD           dwOldAspect = *lpdwCurAspect;
  722.         HRESULT         hrErr;
  723.  
  724.         // This fixes a bug in the sample code: insert a shape as an icon,
  725.         // close sr2test, then convert the icon to content. They fail because
  726.         // the object isn't running. We run it if we need to. The fRunIfNecessary
  727.         // flag may be false if we're in SwitchDisplayAspect from Insert Object.
  728.         // Obviously, then the object doesn't need to be run.
  729.         //
  730.         BOOL fMustClose = FALSE;
  731.         if (fRunIfNecessary && !OLE::OleIsRunning(pOleObject)) {
  732.                 OleRun (pOleObject);
  733.                 fMustClose = TRUE;
  734.         }
  735.  
  736.         if (lpfMustUpdate)
  737.                 *lpfMustUpdate = FALSE;
  738.  
  739.         lpOleObj->QueryInterface (IID_IOleCache, &(VOID FAR*) lpOleCache);
  740.  
  741.         // if IOleCache* is NOT available, do nothing
  742.         //
  743.         if (!lpOleCache)
  744.                 return ResultFromScode(E_INVALIDARG);
  745.  
  746.         // Setup new cache with the new aspect
  747.         FmtEtc.cfFormat = NULL;     // whatever is needed to draw
  748.         FmtEtc.ptd      = NULL;
  749.         FmtEtc.dwAspect = dwNewAspect;
  750.         FmtEtc.lindex   = -1;
  751.         FmtEtc.tymed    = TYMED_NULL;
  752.  
  753.         // Icons shouldn't receive data advise connections. If they did, the
  754.         // metafile representation of the icon in the OLE cache would be lost.
  755.         //
  756.         if (dwNewAspect == DVASPECT_ICON && hMetaPict)
  757.                 dwAdvf = ADVF_NODATA;
  758.         else
  759.                 dwAdvf = ADVF_PRIMEFIRST;
  760.  
  761.         hrErr = lpOleCache->Cache(&FmtEtc, dwAdvf, &dwNewConnection);
  762.  
  763.         if (!SUCCEEDED(hrErr)) {
  764.                 lpOleCache->Release();
  765.                 return hrErr;
  766.         }
  767.  
  768.         *lpdwCurAspect = dwNewAspect;
  769.  
  770.         // Stuff the icon into the cache
  771.         //
  772.         if (dwNewAspect == DVASPECT_ICON && hMetaPict) {
  773.  
  774.                 FmtEtc.cfFormat = CF_METAFILEPICT;
  775.                 FmtEtc.ptd      = NULL;
  776.                 FmtEtc.dwAspect = DVASPECT_ICON;
  777.                 FmtEtc.lindex   = -1;
  778.                 FmtEtc.tymed    = TYMED_MFPICT;
  779.  
  780.                 Medium.tymed            = TYMED_MFPICT;
  781.                 Medium.hGlobal          = hMetaPict;
  782.                 Medium.pUnkForRelease   = NULL;
  783.  
  784.                 hrErr = lpOleCache->SetData (&FmtEtc, &Medium, FALSE /* fRelease */);
  785.         } else {
  786.                 if (lpfMustUpdate)
  787.                         *lpfMustUpdate = TRUE;
  788.         }
  789.  
  790.         if (fSetupViewAdvise && lpAdviseSink) {
  791.                 // re-establish the ViewAdvise connection
  792.                 //
  793.                 lpOleObj->QueryInterface (IID_IViewObject, &(VOID FAR*) lpViewObj);
  794.  
  795.                 if (lpViewObj) {
  796.                         lpViewObj->SetAdvise(dwNewAspect, 0, lpAdviseSink);
  797.                         lpViewObj->Release();
  798.                 }
  799.         }
  800.  
  801.         // Remove cached presentations for the ole display aspect
  802.         //
  803.         if (fDeleteOldAspect) {
  804.                 hrErr = lpOleCache->EnumCache(&lpEnumStatData);
  805.  
  806.                 while(hrErr == NOERROR) {
  807.                         hrErr = lpEnumStatData->Next(1, &StatData, NULL);
  808.                         if (hrErr != NOERROR)
  809.                                 break;              // DONE! no more caches.
  810.  
  811.                         if (StatData.formatetc.dwAspect == dwOldAspect) {
  812.  
  813.                                 // Remove previous cache with old aspect
  814.                                 //
  815.                                 lpOleCache->Uncache(StatData.dwConnection);
  816.                         }
  817.                 }
  818.  
  819.                 if (lpEnumStatData)
  820.                         lpEnumStatData->Release();
  821.         }
  822.  
  823.         if (lpOleCache)
  824.                 lpOleCache->Release();
  825.  
  826.         if (fMustClose)
  827.                 pOleObject->Close (OLECLOSE_SAVEIFDIRTY);
  828.  
  829.         return NOERROR;
  830. }
  831.  
  832. BOOL _IFUNC BOlePart::CacheIconicAspect (HGLOBAL mfpIcon)
  833. {
  834.         BOOL fMustUpdate;
  835.         HRESULT hrErr = SwitchDisplayAspect (pOleObject, &dwDrawAspect,
  836.                 DVASPECT_ICON, mfpIcon, FALSE, TRUE, this, &fMustUpdate, FALSE);
  837.  
  838.         //if (hrErr == NOERROR)
  839.                 //hrErr = pOleObject->Update ();
  840.  
  841.         OleUIMetafilePictIconFree(mfpIcon);    // clean up metafile
  842.  
  843.         return (hrErr == NOERROR);
  844. }
  845.  
  846. void BOlePart::AddToList ()
  847. {
  848.         // Insert "this" onto the list of part instances in this document.
  849.         //
  850.         // Avoid overhead by inserting the new part at the front of the list
  851.         // rather than searching for a null pNextPart. So the list is in
  852.         // first-in-last-out order
  853.         //
  854.         BOlePart *pOldFirstPart = pDoc->GetFirstPart ();
  855.         pDoc->SetFirstPart (this);
  856.         pNextPart = pOldFirstPart;
  857.         if (pOldFirstPart)
  858.                 pOldFirstPart->pPrevPart = this;
  859. }
  860.  
  861. void BOlePart::RemoveFromList ()
  862. {
  863.         // Remove "this" from the list of part instances in this document.
  864.         //
  865.         // Standard list removal by joining the previous part with the next one
  866.         //
  867.         if (pPrevPart)
  868.                 pPrevPart->pNextPart = pNextPart;
  869.         if (pNextPart)
  870.                 pNextPart->pPrevPart = pPrevPart;
  871.  
  872.         if (pDoc)
  873.                 pDoc->OnRemovePart (this);
  874.  
  875.         pNextPart = pPrevPart = NULLP;
  876. }
  877.  
  878. // ConvertHelper -- Helper function which is used in ConvertUI and
  879. //                  ConvertGuts. The reason to have this function is
  880. //                  because the user type and clsid must be known in
  881. //                  both UI and guts, but it wouldn't be nice to put
  882. //                  them in the BOleConvertInfo struct, which would
  883. //                  otherwise be the best way to get dynamic scope.
  884. //
  885. HRESULT _IFUNC BOlePart::ConvertHelper (LPCLSID pCid,
  886.                                         LPOLESTR FAR* ppType,
  887.                                         WORD FAR* pwFormat)
  888. {
  889.         BOOL fHaveClsid = FALSE;
  890.         BOOL fHaveUserType = FALSE;
  891.         HRESULT hr = NOERROR;
  892.  
  893.         // (PHP) This isn't really nice, but if I don't save the object,
  894.         // ReadFmtUserTypeStg fails. Maybe it's not so bad since we're
  895.         // going to save it anyway to convert it.
  896.         //
  897.         LPPERSISTSTORAGE pps = NULL;
  898.         pOleObject->QueryInterface (IID_IPersistStorage, &(LPVOID) pps);
  899.         pps->Save (pStgFromInit, TRUE);
  900.         pps->Release();
  901.  
  902.         hr = ReadClassStg (pStgFromInit, pCid);
  903.         if (SUCCEEDED(hr))
  904.                 fHaveClsid = TRUE;
  905.  
  906.         hr = ReadFmtUserTypeStg (pStgFromInit, pwFormat, ppType);
  907.         if (SUCCEEDED(hr))
  908.                 fHaveUserType = TRUE;
  909.  
  910.  
  911.  
  912.         if (!fHaveClsid) {
  913.                 hr = pOleObject->GetUserClassID (pCid);
  914.                 if (!SUCCEEDED(hr))
  915.                         *pCid = CLSID_NULL;
  916.         }
  917.  
  918.         if (!fHaveUserType) {
  919.                 OLECHAR szUserType[128];
  920.                 *pwFormat = 0;
  921.                 if (OleStdGetUserTypeOfClass(
  922.                         *pCid, szUserType, sizeof(szUserType), NULL)) {
  923.                         *ppType = OleStdCopyString(szUserType, NULL);
  924.                 } else {
  925.                         *ppType = NULL;
  926.                 }
  927.         }
  928.  
  929.         return hr;
  930. }
  931.  
  932.  
  933. // Bring up the Convert dialog box to give the user a chance to convert
  934. // or emulate the OLE object associated with this part.
  935. //
  936. // Convert is actually implemented here because most of the data needed
  937. // to do the conversion lives in the BOlePart not the BOleService
  938. //
  939. //
  940. //
  941. HRESULT _IFUNC BOlePart::ConvertUI (PIBApplication pHelpApp, BOOL f, BOleConvertInfo FAR *pInfo)
  942. {
  943.         HRESULT hr = NOERROR;
  944.  
  945.         _fmemset (pInfo, 0, sizeof(BOleConvertInfo));
  946.  
  947.         OLEUICONVERT ouc;
  948.         _fmemset (&ouc, 0, sizeof (ouc));
  949.  
  950.         ouc.cbStruct = sizeof (ouc);
  951.         if (pDoc->pService->ShowHelpButton (BOLE_HELP_CONVERT))
  952.                 ouc.dwFlags = CF_SHOWHELPBUTTON;
  953.         ouc.hWndOwner = ::GetActiveWindow();    // pHelpApp->GetWindow();
  954.         ouc.fIsLinkedObject = IsLink;
  955.         ouc.dvAspect = dwDrawAspect;
  956.         ouc.dwIBApplication = (DWORD) pHelpApp;
  957.  
  958.         if (IsLink) {
  959.                 hr = pLinkObject->GetSourceDisplayName (&ouc.lpszDefLabel);
  960.                 hr = pOleObject->GetUserClassID (&ouc.clsid);
  961.         }
  962.         else
  963.                 ConvertHelper (&ouc.clsid, &ouc.lpszUserType, &ouc.wFormat);
  964.  
  965.  
  966.         STGMEDIUM medium;
  967.         if (dwDrawAspect == DVASPECT_ICON)
  968.                 ouc.hMetaPict = OleStdGetData (pDataObject, CF_METAFILEPICT, NULL,
  969.                         DVASPECT_ICON, &medium);
  970.         else
  971.                 ouc.hMetaPict = NULL;
  972.  
  973.         pDoc->pService->EnterBOleDialog (TRUE, ouc.hHook, ouc.hTask);
  974.         UINT uRet = OleUIConvert(&ouc);
  975.         pDoc->pService->EnterBOleDialog (FALSE, ouc.hHook, ouc.hTask);
  976.  
  977.         // If the user clicked OK, look at the dialog settings to see what
  978.         // we should set in the output BOleConvertInfo.
  979.         //
  980.         if (uRet == OLEUI_OK) {
  981.  
  982.                 if (ouc.dwFlags & CF_SELECTCONVERTTO && !IsEqualCLSID (ouc.clsid, ouc.clsidNew)) {
  983.                         (int) pInfo->action |= BOLE_CONVERT_TO_CLSID;
  984.                         pInfo->clsidNew = ouc.clsidNew;
  985.                 }
  986.  
  987.                 if (ouc.dwFlags & CF_SELECTACTIVATEAS) {
  988.                         (int) pInfo->action |= BOLE_ACTIVATE_AS_CLSID;
  989.                         pInfo->clsidNew = ouc.clsidNew;
  990.                 }
  991.  
  992.                 if (ouc.dvAspect != dwDrawAspect || ouc.fObjectsIconChanged) {
  993.                         if (ouc.dvAspect == DVASPECT_ICON) {
  994.                                 (int) pInfo->action |= BOLE_ASPECT_TO_ICON;
  995.                                 pInfo->hIcon = ouc.hMetaPict;
  996.                         }
  997.                         else
  998.                                 (int) pInfo->action |= BOLE_ASPECT_TO_CONTENT;
  999.                 }
  1000.         }
  1001.  
  1002.         // If the user clicked Cancel or clicked OK, but didn't actually do
  1003.         // anything, we would get here with the action bitfield cleared.
  1004.         //
  1005.         // Return S_FALSE to indicate that the BOleConvertInfo is not valid,
  1006.         // and we shouldn't call ConvertGuts
  1007.         //
  1008.         if (pInfo->action == (BOleConvertAction) 0)
  1009.                 hr = ResultFromScode (S_FALSE);
  1010.         else
  1011.                 hr = ResultFromScode (S_OK);
  1012.  
  1013.         return hr;
  1014.  
  1015. }
  1016.  
  1017. HRESULT _IFUNC BOlePart::ConvertGuts (BOOL b, BOleConvertInfo FAR *pInfo)
  1018. {
  1019.         BOOL fMustActivate = FALSE;
  1020.         BOOL fMustRun = FALSE;
  1021.         BOOL fObjConverted = TRUE;
  1022.  
  1023.         HRESULT hr = NOERROR;
  1024.  
  1025.         // This could be a while
  1026.         //
  1027.         HCURSOR hPrevCursor = ::SetCursor (::LoadCursor (NULL, IDC_WAIT));
  1028.  
  1029.         CLSID cid = CLSID_NULL;
  1030.         LPOLESTR pType = NULL;
  1031.         WORD wFormat = 0;
  1032.         ConvertHelper (&cid, &pType, &wFormat);
  1033.  
  1034.         // User selected Convert To
  1035.         //
  1036.         if (pInfo->action & BOLE_CONVERT_TO_CLSID) {
  1037.                 LPSTORAGE pTmpStg = pStgFromInit; pTmpStg->AddRef();// will be released in Close
  1038.                 BOleDocument *pTmpDoc = pDoc; pTmpDoc->AddRefMain();
  1039.                 Close ();
  1040.                 pDoc = pTmpDoc;
  1041.                 pStgFromInit = pTmpStg;
  1042.                 DeleteTypeNames();
  1043.                 hr = OleStdDoConvert (pStgFromInit, pInfo->clsidNew);
  1044.                 if (!SUCCEEDED (hr))
  1045.                         goto error;
  1046.                 hr = OLE::OleLoad (pStgFromInit, IID_IOleObject, this, &(LPVOID)pOleObject);
  1047.                 fMustRun = TRUE;
  1048.                 fObjConverted = TRUE;
  1049.  
  1050.                 InitAdvises (pOleObject, dwDrawAspect,
  1051.                         (LPOLESTR)pDoc->pApplication->GetAppName(),
  1052.                         (LPOLESTR)pContainer->GetWindowTitle(), this, FALSE);
  1053.  
  1054.         }
  1055.  
  1056.         // User selected Activate As
  1057.         //
  1058.         if (pInfo->action & BOLE_ACTIVATE_AS_CLSID) {
  1059.                 LPSTORAGE pTmpStg = pStgFromInit; pTmpStg->AddRef();// will be released in Close
  1060.                 BOleDocument *pTmpDoc = pDoc; pTmpDoc->AddRefMain();
  1061.                 Close ();
  1062.                 pDoc = pTmpDoc;
  1063.                 pStgFromInit = pTmpStg;
  1064.                 DeleteTypeNames();
  1065.  
  1066.                 pDoc->pService->UnloadObjects (cid);
  1067.                 hr = OleStdDoTreatAsClass (pType, cid, pInfo->clsidNew);
  1068.                 hr = OLE::OleLoad (pStgFromInit, IID_IOleObject, this, &(LPVOID)pOleObject);
  1069.                 fMustActivate = TRUE;
  1070.         }
  1071.  
  1072.         // We'll want to draw this object later on
  1073.         //
  1074.         if (pOleObject) {
  1075.                 if (pViewObject)
  1076.                         pViewObject->Release();
  1077.                 pOleObject->QueryInterface (IID_IViewObject, &(LPVOID) pViewObject);
  1078.                 if (pDataObject)
  1079.                         pDataObject->Release();
  1080.                 pOleObject->QueryInterface (IID_IDataObject, &(VOID FAR*)pDataObject);
  1081.         }
  1082.  
  1083.         // If we're switching to icon, don't check the curr aspect because
  1084.         // we could be switching between icons.
  1085.         //
  1086.         if (pInfo->action & BOLE_ASPECT_TO_ICON) {
  1087.  
  1088.                 // Special thing for scripting: if you ask for an object to be converted
  1089.                 // to an icon from script/macro, you probably don't have an HMETAPICT
  1090.                 // for the icon, so we let them pass 0 as a sentinel, and we use a
  1091.                 // default icon for the CLSID
  1092.                 //
  1093.                 if (pInfo->hIcon == 0) {
  1094.                         pInfo->hIcon = OleGetIconOfClass (cid, NULL, TRUE);
  1095.                 }
  1096.  
  1097.                 // Don't delete the old aspect if we're switching from one icon
  1098.                 // to another. Otherwise, deleting the old aspect depends on whether
  1099.                 // we're activating the object
  1100.                 //
  1101.                 BOOL fDeleteOld;
  1102.                 if (dwDrawAspect == DVASPECT_ICON)
  1103.                         fDeleteOld = FALSE;
  1104.                 else
  1105.                         fDeleteOld = !b;
  1106.  
  1107.                 hr = SwitchDisplayAspect (pOleObject, &dwDrawAspect, DVASPECT_ICON,
  1108.                         pInfo->hIcon, fDeleteOld, TRUE, this, &fMustRun, TRUE);
  1109.                 if (SUCCEEDED(hr)) {
  1110.                         OnViewChange(DVASPECT_ICON, -1);
  1111.                 }
  1112.         }
  1113.  
  1114.         // Switching to content aspect
  1115.         //
  1116.         if (dwDrawAspect == DVASPECT_ICON && pInfo->action & BOLE_ASPECT_TO_CONTENT) {
  1117.                 hr = SwitchDisplayAspect (pOleObject, &dwDrawAspect, DVASPECT_CONTENT,
  1118.                         NULL, !b, TRUE, this, &fMustRun, TRUE);
  1119.                 if (SUCCEEDED(hr)) {
  1120.                         OnViewChange(DVASPECT_CONTENT, -1);
  1121.                 }
  1122.         }
  1123.  
  1124.         if (fMustRun) {
  1125.                 if (!fMustActivate && !OLE::OleIsRunning (pOleObject)) {
  1126.                         hr = OleRun (pOleObject);
  1127.                         if (!SUCCEEDED(hr))
  1128.                                 return hr;
  1129.  
  1130.                         if (fObjConverted) {
  1131.  
  1132.                                 // Of course, static objects can't be run. This isn't an
  1133.                                 // error to be worried about
  1134.                                 //
  1135.                                 if (hr == ResultFromScode (OLE_E_STATIC)) {
  1136.                                         Close();
  1137.                                         pStgFromInit->Revert ();
  1138.                                         return hr; //
  1139.                                 }
  1140.                                 else {
  1141.                                         // The object probably already has an OLERENDER_DRAW cache,
  1142.                                         // but this is just to make sure.
  1143.                                         //
  1144.                                         LPOLECACHE pCache = NULL;
  1145.                                         hr = pOleObject->QueryInterface (IID_IOleCache, &(LPVOID) pCache);
  1146.                                         if (SUCCEEDED(hr)) {
  1147.                                                 FORMATETC fe;
  1148.                                                 DWORD newCnxn;
  1149.                                                 fe.cfFormat = NULL;
  1150.                                                 fe.ptd = NULL;
  1151.                                                 fe.dwAspect = DVASPECT_CONTENT;
  1152.                                                 fe.lindex = -1;
  1153.                                                 fe.tymed = TYMED_NULL;
  1154.                                                 pCache->Cache (&fe, ADVF_PRIMEFIRST, &newCnxn);
  1155.                                                 pCache->Release();
  1156.                                         }
  1157.                                 }
  1158.                                 // Force the storage to be committed
  1159.                                 //
  1160.                                 pOleObject->Close (OLECLOSE_SAVEIFDIRTY);
  1161.  
  1162.                         }
  1163.                 }
  1164.         }
  1165.  
  1166.         pSite->Invalidate(BOLE_INVAL_VIEW);
  1167.         if (fMustActivate)
  1168.                 DoVerb (OLEIVERB_PRIMARY);
  1169. error:
  1170.  
  1171.                 //
  1172.  
  1173.         ::SetCursor (hPrevCursor);
  1174.         return hr;
  1175. }
  1176.  
  1177. void _IFUNC BOlePart::ResetObjectRects ()
  1178. {
  1179.         RECT pos, clip;
  1180.         OLEPRINTF1("Entering ResetObjectRects");
  1181.         if (NOERROR == pSite->GetSiteRect (&pos, &clip)) {
  1182.                 OLEPRINTF3("GettingSiteRect:\t {%d, %d}",
  1183.                                    pos.right - pos.left, pos.bottom - pos.top);
  1184.                 pInPlaceObject->SetObjectRects (&pos, &clip);
  1185.         }
  1186. }
  1187.  
  1188. //**************************************************************************
  1189. //
  1190. // IPart implementation
  1191. //
  1192. //**************************************************************************
  1193.  
  1194. HRESULT _IFUNC BOlePart::Save (IStorage * pStg, BOOL fSameAsLoad, BOOL fRemember)
  1195. {
  1196.         HRESULT ret = NOERROR;
  1197.         // Get a pointer to the Ole object's IPersistStorage
  1198.         if (pOleObject) {
  1199.                 IPersistStorage* pPersistStg;
  1200.                 HRESULT hr = pOleObject->QueryInterface(IID_IPersistStorage,
  1201.                         &(VOID FAR *)pPersistStg);
  1202.                 if (SUCCEEDED(hr) && !pPersistStg)
  1203.                         ret = ResultFromScode (E_FAIL);
  1204.                 else {
  1205.  
  1206.                         // Write the object out to storage.
  1207.                         //
  1208.                         ret = OLE::OleSave(pPersistStg, pStg, fSameAsLoad);
  1209.  
  1210.                         // Write the object's drawing aspect out to storage so we know
  1211.                         // which presentation data to use when we reload it. OleSave
  1212.                         // already knows how to save the iconic presentation data to storage
  1213.                         //
  1214.                         // Also write out the additional scale factor for the size
  1215.                         // imposed when the user resized the size.
  1216.                         //
  1217.  
  1218.                         LPSTREAM pStream = NULLP;
  1219.  
  1220.                         if (SUCCEEDED(pStg->CreateStream(szcBOlePart,
  1221.                                 STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
  1222.                                 NULL,NULL,&pStream)))  {
  1223.                                 ULONG cb;
  1224.                                 pStream->Write(&dwDrawAspect, sizeof(dwDrawAspect), &cb);
  1225.                                 if (!(dwDrawAspect == DVASPECT_ICON)) {
  1226.                                         OLEPRINTF5("Saving scaleSite:\t {%ld, %ld, %ld, %ld}",
  1227.                                                            scaleSite.xN, scaleSite.xD, scaleSite.yN, scaleSite.yD);
  1228.                                         pStream->Write(&scaleSite, sizeof(scaleSite), &cb);
  1229.                                 }
  1230.                                 pStream->Release();
  1231.                         }
  1232.  
  1233.                         if (fRemember) {
  1234. #if 0           // not used in outline example or mfc source
  1235.                                 // for SaveAs case release initial storage and remember new one
  1236.                                 pPersistStg->HandsOffStorage();  // server releases initial storage
  1237. #endif
  1238.                                 pPersistStg->SaveCompleted ( pStg );
  1239.                                 if (pStgFromInit)
  1240.                                         pStgFromInit->Release();
  1241.                                 pStgFromInit = pStg;
  1242.                                 pStgFromInit->AddRef();
  1243.                         }
  1244.                         else {
  1245.                                 pPersistStg->SaveCompleted ( NULL );
  1246.                         }
  1247.                         pPersistStg->Release();
  1248.                 }
  1249.  
  1250.         }
  1251.         return ret;
  1252. }
  1253.  
  1254. HRESULT _IFUNC BOlePart::CanOpenInPlace ()
  1255. {
  1256.         // this is only used in our server code
  1257.         return ResultFromScode(E_FAIL);
  1258. }
  1259.  
  1260. HRESULT _IFUNC BOlePart::GetPalette (LPLOGPALETTE FAR *ppPal)
  1261. {
  1262.         if (pViewObject) {
  1263.                 HRESULT hrErr = pViewObject->GetColorSet (
  1264.                         dwDrawAspect, -1, NULL, NULL, NULL, ppPal);
  1265.                 if (hrErr == NOERROR)
  1266.                         return hrErr;
  1267.         }
  1268.  
  1269.         return ResultFromScode (E_FAIL);
  1270.  
  1271. }
  1272.  
  1273. HRESULT _IFUNC BOlePart::SetHost (IBContainer FAR *pNewContainer)
  1274. {
  1275.         if (!pNewContainer)
  1276.                 return ResultFromScode (E_FAIL);
  1277.  
  1278.         BOleDocument *pNewDoc = NULL;
  1279.         if (!SUCCEEDED(pNewContainer->QueryInterface(IID_BOleDocument, &(LPVOID) pNewDoc)))
  1280.                 return ResultFromScode (E_NOINTERFACE);
  1281.         pNewDoc->Release();    // PREVENT CYCLE
  1282.  
  1283.         if (IsOpenInPlace)
  1284.                 //
  1285.                 //
  1286.                 return ResultFromScode (E_FAIL);
  1287.  
  1288.         if (pNewDoc->pActivePart)
  1289.                 // Need to change pActivePart to a BOlePart* to
  1290.                 // we can call Activate (FALSE) here.
  1291.                 //
  1292.                 return ResultFromScode (E_FAIL);
  1293.  
  1294.  
  1295.         RemoveFromList ();
  1296.         if (pDoc) {
  1297.                 pDoc->ReleaseMain();
  1298.                 pDoc = NULLP;
  1299.         }
  1300.         if (pNewDoc) {
  1301.                 pDoc = pNewDoc;
  1302.                 pDoc->AddRefMain();     // directly on helper
  1303.                 pContainer = pNewContainer;
  1304.         }
  1305.         AddToList ();
  1306.         return NOERROR;
  1307. }
  1308.  
  1309. HRESULT _IFUNC BOlePart::Open (BOOL bOpen)
  1310. {
  1311.         if (bOpen) {
  1312.                 HRESULT hRes = DoVerb(OLEIVERB_OPEN);
  1313.                 pSite->Invalidate(BOLE_INVAL_VIEW); // ? do we need this (ICS)
  1314.                 return hRes;
  1315.         }
  1316.         else {
  1317.                 return pOleObject->DoVerb(OLEIVERB_HIDE, NULL, this, 0,
  1318.                         pContainer->GetWindow(), (LPRECT) 0);
  1319.         }
  1320. }
  1321.  
  1322. HRESULT _IFUNC BOlePart::Show (BOOL bShow)
  1323. {
  1324.         if (bShow) {
  1325.                 HRESULT hRes = DoVerb(OLEIVERB_SHOW);
  1326.                 pSite->Invalidate(BOLE_INVAL_VIEW); // ? do we need this (ICS)
  1327.                 return hRes;
  1328.         }
  1329.         else {
  1330.                 return pOleObject->DoVerb(OLEIVERB_HIDE, NULL, this, 0,
  1331.                         pContainer->GetWindow(), (LPRECT) 0);
  1332.         }
  1333.  
  1334. }
  1335.  
  1336.  
  1337. HRESULT _IFUNC BOlePart::Activate (BOOL fActivate)
  1338. {
  1339.         HRESULT hr = NOERROR;
  1340.  
  1341.         if (fActivate) {
  1342.                 hr = DoVerb (OLEIVERB_PRIMARY);
  1343.         }
  1344.         else
  1345.                 if (IsOpenInPlace) {
  1346.                         hr = pInPlaceObject->UIDeactivate ();
  1347.  
  1348. #if 1    //
  1349.                         if (hr == NOERROR)
  1350.                                 if (IsOpenInsideOut)
  1351.                                         hr = pOleObject->DoVerb (OLEIVERB_DISCARDUNDOSTATE, NULL,
  1352.                                                 this, 0, pContainer->GetWindow(), (LPRECT) 0);
  1353.                                 else {
  1354.                                         if (pInPlaceObject)
  1355.                                                 hr = pInPlaceObject->InPlaceDeactivate ();
  1356.                                 }
  1357. #endif
  1358.                 }
  1359.  
  1360.         return hr;
  1361. }
  1362.  
  1363. HWND _IFUNC BOlePart::OpenInPlace (HWND hWndParent)
  1364. {
  1365.         // this is meaningful only in our server code
  1366.         return 0;
  1367. }
  1368.  
  1369. HRESULT _IFUNC BOlePart::SetPartSize (LPSIZE pSize)
  1370. {
  1371.         SIZEL sl;
  1372.         sl.cx = MAP_PIX_TO_LOGHIM (pSize->cx, BOleService::pixPerIn.x);
  1373.         sl.cy = MAP_PIX_TO_LOGHIM (pSize->cy, BOleService::pixPerIn.y);
  1374.  
  1375.         // Size passed is in scaled units but we need to tell the server
  1376.         // its "actual size"
  1377.         //
  1378.         BOleScaleFactor scale;
  1379.         pSite->GetZoom(&scale);
  1380.         sl.cx = Scale(sl.cx, scale.xD, scale.xN);    // unscale
  1381.         sl.cy = Scale(sl.cy, scale.yD, scale.yN);
  1382.  
  1383.         // IOleObject::SetExtent only works if the object is running.
  1384.         // If not, we need to cache the extent locally and pass it on to the
  1385.         // object when it opens.
  1386.         //
  1387.         if (!pOleObject || !OLE::OleIsRunning(pOleObject)) {
  1388.  
  1389.                 // If the object's MISCSTATUS specifies that it wants to be run
  1390.                 // whenever we resize it, do so here
  1391.                 //
  1392.                 DWORD miscStatus = 0;
  1393.                 if (pOleObject &&
  1394.                         (NOERROR == pOleObject->GetMiscStatus(dwDrawAspect, &miscStatus)))
  1395.                         if (miscStatus & OLEMISC_RECOMPOSEONRESIZE)
  1396.                                 if (NOERROR == ForceOleRun (pOleObject))
  1397.                                         return pOleObject->SetExtent (dwDrawAspect, &sl);
  1398.  
  1399.                 // Cache the size of the nonrunning object
  1400.                 //
  1401.                 CachedExtent = sl;
  1402.                 return NOERROR;
  1403.  
  1404.         }
  1405.  
  1406.         // Set the size of the running object
  1407.         //
  1408.         HRESULT hr = pOleObject->SetExtent (dwDrawAspect, &sl);
  1409.         return hr;
  1410. }
  1411.  
  1412. HRESULT _IFUNC BOlePart::GetPartSize (LPSIZE pSize)
  1413. {
  1414.         if (!pSize)
  1415.                 return ResultFromScode (E_INVALIDARG);
  1416.  
  1417.         SIZEL sl;
  1418.  
  1419.         // get himetric size and convert it to pixels
  1420.         // also adjust for scaling
  1421.         // we can give it to SetPartPos and Extent
  1422.         //
  1423.         HRESULT hr = pOleObject->GetExtent(dwDrawAspect, &sl);
  1424.         if (SUCCEEDED(hr)) {
  1425.  
  1426.                 // If we've cached a modified extent for the object, inform the object
  1427.                 // now that it's running.
  1428.                 //
  1429.                 if (CachedExtent.cx) {
  1430.                         if ((sl.cx == CachedExtent.cx) && (sl.cy == CachedExtent.cy)) {
  1431.                                 CachedExtent.cx = 0L;
  1432.                         }
  1433.                         else {
  1434.                                 if (SUCCEEDED(pOleObject->SetExtent (dwDrawAspect, &CachedExtent))) {
  1435.                                         hr = pOleObject->GetExtent(dwDrawAspect, &sl);
  1436.                                         CachedExtent.cx = 0L;
  1437.                                 }
  1438.                         }
  1439.                 }
  1440.  
  1441.  
  1442.                 pSize->cx = MAP_LOGHIM_TO_PIX (sl.cx, BOleService::pixPerIn.x);
  1443.                 pSize->cy = MAP_LOGHIM_TO_PIX (sl.cy, BOleService::pixPerIn.y);
  1444.  
  1445.                 BOleScaleFactor scale;
  1446.                 pSite->GetZoom(&scale);
  1447.                 pSize->cx = Scale(pSize->cx, scale.xN, scale.xD);
  1448.                 pSize->cy = Scale(pSize->cy, scale.yN, scale.yD);
  1449.         }
  1450.         else {
  1451.                 OLEPRINTF1("Entering GetPartSize failure case");
  1452.                 // if the server isn't ready to return the size we should use the sites
  1453.                 RECT rPos, rClip;
  1454.                 pSite->GetSiteRect(&rPos, &rClip);
  1455.                 OLEPRINTF3("GettingSiteRect:\t {%d, %d}",
  1456.                                    rPos.right - rPos.left, rPos.bottom - rPos.top);
  1457.                 pSize->cx = rPos.right - rPos.left;
  1458.                 pSize->cy = rPos.bottom - rPos.top;
  1459.         }
  1460.         return hr;
  1461. }
  1462.  
  1463. HRESULT _IFUNC BOlePart::SetPartPos (LPRECT pNewSize)
  1464. {
  1465.         HRESULT hr = ResultFromScode (E_FAIL);
  1466.  
  1467.         OLEPRINTF1("Entering SetPartPos");
  1468.         // If we're open in place, we can actually change the location of the
  1469.         // object's in-place window. Used for scrolling
  1470.         //
  1471.         if (IsOpenInPlace) {
  1472.                 RECT pos, clip;
  1473.                 if (NOERROR == pSite->GetSiteRect (&pos, &clip))  {
  1474.                 hr = pInPlaceObject->SetObjectRects ((LPCRECT)pNewSize, &clip);
  1475.                 OLEPRINTF3("SettingObjectRects:\t {%d, %d}",
  1476.                    pNewSize->right - pNewSize->left,
  1477.                    pNewSize->bottom - pNewSize->top);
  1478.                 }
  1479.         }
  1480.  
  1481.         // If we're not open in place, we can only change the extent of the
  1482.         // object, and the rectangles should be right in the next IPart::Draw
  1483.         //
  1484.         else {
  1485.                 SIZE s;
  1486.                 s.cx = pNewSize->right - pNewSize->left;
  1487.                 s.cy = pNewSize->bottom - pNewSize->top;
  1488.                 SetPartSize(&s);
  1489.         }
  1490.  
  1491.         return hr;
  1492. }
  1493.  
  1494. inline BOOL IsMetafile(HDC hdc)
  1495. {
  1496.         return (DT_METAFILE == GetDeviceCaps(hdc,TECHNOLOGY));
  1497. }
  1498.  
  1499. HRESULT _IFUNC BOlePart::Draw (HDC hdc, LPCRECTL pPosRect, LPCRECTL pClipRect,
  1500.                                BOleAspect reqAspect, BOleDraw bdFlags)
  1501. {
  1502.         int oldDCInfo = WIN::SaveDC (hdc);
  1503.  
  1504.         //
  1505.         //
  1506.         //
  1507. //
  1508. //
  1509. //
  1510. //
  1511.  
  1512.         HRESULT hRes = ResultFromScode (E_FAIL);
  1513.  
  1514.         // If you're drawing objects, but not using the metafile to get it,
  1515.         // you'd get the high-res graphics data yourself, but you still need to
  1516.         // draw the open-editing shading. Hence this flag.
  1517.         //
  1518.         if (bdFlags & BOLE_DRAW_SHADINGONLY) {
  1519.                 hRes = NOERROR;
  1520.                 goto shadingOnly;
  1521.         }
  1522.  
  1523.         // If this object is a link, make sure we're bound to it just in case
  1524.         // someone else has opened the link source and makes changes to it. This
  1525.         // will force those changes to be propogated to us
  1526.         //
  1527.         if (IsLink) {
  1528.                 DWORD linkopts = 0;
  1529.                 if (SUCCEEDED(pLinkObject->GetUpdateOptions (&linkopts)))
  1530.                         if (linkopts & OLEUPDATE_ALWAYS)
  1531.                                 pLinkObject->BindIfRunning();
  1532.         }
  1533.  
  1534.         // Remove the special Bolero aspect values from the bitfield
  1535.         // so those values don't show through when we send the aspect
  1536.         // to OLE2. OLE2 will return OLE_E_BLANK for non-standard values
  1537.         //
  1538.         dwExtAspect = 0; // Clear this out so caller can use different settings each time through
  1539.         if (reqAspect & BOLE_DEFAULT)
  1540.                 dwExtAspect = dwExtAspect | BOLE_DEFAULT;
  1541.         else
  1542.                 dwDrawAspect = reqAspect;
  1543.         if (reqAspect & BOLE_ASPECT_MAINTAIN)
  1544.                 dwExtAspect = dwExtAspect | BOLE_ASPECT_MAINTAIN;
  1545.         if (reqAspect & BOLE_CLIP)
  1546.                 dwExtAspect = dwExtAspect | BOLE_CLIP;
  1547.  
  1548.         reqAspect = (reqAspect & ~(BOLE_ASPECT_MAINTAIN | BOLE_DEFAULT | BOLE_CLIP));
  1549.  
  1550.         if (pViewObject) {
  1551.                 RECTL hmRect = *pPosRect;
  1552.  
  1553.                 // Get the part's extents in himetric
  1554.                 SIZEL srvExt;
  1555.                 HRESULT hr = pOleObject->GetExtent(dwDrawAspect, &srvExt);
  1556.                 if (SUCCEEDED(hr)) {
  1557.                         // scale part's extents by client's scale factor
  1558.                         BOleScaleFactor scale;
  1559.                         pSite->GetZoom(&scale);
  1560.                         srvExt.cx = Scale(srvExt.cx, scale.xN, scale.xD);
  1561.                         srvExt.cy = Scale(srvExt.cy, scale.yN, scale.yD);
  1562.                 }
  1563.                 else {
  1564.                         OLEPRINTF1("Couldn't GetExtent during draw");
  1565.                         // if server's extent isn't available, use what's passed in
  1566.                         srvExt.cx = hmRect.right - hmRect.left;
  1567.                         srvExt.cy = hmRect.bottom - hmRect.top;
  1568.                 }
  1569.  
  1570. #if 1
  1571.                 if (dwExtAspect & BOLE_ASPECT_MAINTAIN) {
  1572.                         // Scale the rect we draw into if either the x extent or the y extent
  1573.                         // overflows. The resulting rect is in the upper left corner of the client.
  1574.                         SIZEL cliExt;
  1575.                         cliExt.cx = hmRect.right - hmRect.left;
  1576.                         cliExt.cy = hmRect.bottom - hmRect.top;
  1577.  
  1578.                         //
  1579.                         long dx, dy;
  1580.                         dx = cliExt.cx - srvExt.cx;
  1581.                         dy = cliExt.cy - srvExt.cy;
  1582.                         if (dx >= 0 && dy >= 0) {
  1583.                                 // We have enough room, both x and y, to display the object
  1584.                                 hmRect.right = hmRect.left + srvExt.cx;
  1585.                                 hmRect.bottom = hmRect.top + srvExt.cy;
  1586.                         }
  1587.                         else {
  1588.                                 // Either the x or y extent is too large. Decide which axis overflows
  1589.                                 // more, and leave it the same size as the client, which is its
  1590.                                 // maximum value. Then scale the axis which overflows less (maybe not
  1591.                                 // at all) to maintain the server's aspect ratio
  1592.                                 //
  1593.                                 if (dx < dy)
  1594.                                         hmRect.bottom = hmRect.top + Scale(srvExt.cy, cliExt.cx, srvExt.cx);
  1595.                                 else
  1596.                                         hmRect.right = hmRect.left + Scale(srvExt.cx, cliExt.cy, srvExt.cy);
  1597.                         }
  1598.                 }
  1599. #endif
  1600.  
  1601.                 if (dwExtAspect & BOLE_CLIP) {
  1602.                         hmRect.right = hmRect.left + srvExt.cx;
  1603.                         hmRect.bottom = hmRect.top + srvExt.cy;
  1604.                 }
  1605.                 // Ask the server object to draw itself.
  1606.                 //
  1607.                 hRes = pViewObject->Draw(dwDrawAspect, -1, NULL,  NULL,
  1608.                         NULL, hdc, &hmRect, IsMetafile(hdc) ? pClipRect : NULL,
  1609.                         NULL, 0);
  1610.         }
  1611.         else {
  1612.                 WIN::RestoreDC (hdc, oldDCInfo);
  1613.                 return ResultFromScode (E_FAIL);
  1614.         }
  1615.  
  1616. shadingOnly:
  1617.  
  1618.         RECT r;
  1619.         r.top = pPosRect->top;
  1620.         r.left = pPosRect->left;
  1621.         r.bottom = pPosRect->bottom;
  1622.         r.right = pPosRect->right;
  1623.  
  1624.         // If the server app has the embedded object open in its own window,
  1625.         // as opposed to inplace in our window, draw special highlighting
  1626.         //
  1627.         if (IsOpen) {
  1628.                 OUI::OleUIDrawShading(&r, hdc, OLEUI_SHADE_FULLRECT, 0);
  1629.         }
  1630.  
  1631.         // If the app wants us to draw the borders around OLE2 objects as
  1632.         // described in the OLE2 UI guidelines, do it here.
  1633.         //
  1634.         if (bdFlags & BOLE_DRAW_SHOWOBJECTS) {
  1635.                 int penStyle = IsLink ? PS_DASH : PS_SOLID;
  1636.                 HPEN p = CreatePen (penStyle, 1, RGB(0,0,0));
  1637.                 HBRUSH b = (HBRUSH) GetStockObject (HOLLOW_BRUSH);
  1638.                 HPEN oldP = (HPEN) SelectObject (hdc,p);
  1639.                 HBRUSH oldB = (HBRUSH) SelectObject (hdc,b);
  1640.                 Rectangle (hdc, ( int )r.left, ( int )r.top,
  1641.                         ( int )( r.right - r.left ),
  1642.                         ( int )( r.bottom - r.top ) );
  1643.                 SelectObject (hdc, oldP);
  1644.                 SelectObject (hdc, oldB);
  1645.                 DeleteObject (p);
  1646.                 DeleteObject (b);
  1647.         }
  1648.  
  1649.         WIN::RestoreDC (hdc, oldDCInfo);
  1650.         return hRes;
  1651. }
  1652.  
  1653. HRESULT _IFUNC BOlePart::InsertMenus (HMENU, BOleMenuWidths*)
  1654. {
  1655.         // this is meaningful only in our server code
  1656.         return ResultFromScode (E_NOTIMPL);
  1657. }
  1658.  
  1659. void _IFUNC BOlePart::FrameResized (const RECT *, BOOL)
  1660. {
  1661.         // this is meaningful only in our server code
  1662. }
  1663.  
  1664. HRESULT _IFUNC BOlePart::ShowTools (BOOL)
  1665. {
  1666.         // this is meaningful only in our server code
  1667.          return ResultFromScode (E_NOTIMPL);
  1668. }
  1669.  
  1670. HRESULT _IFUNC BOlePart::EnumVerbs (BOleVerb *pBV)
  1671. {
  1672.         // The purpose of verbIndex is to keep track of the enumerator in
  1673.         // here rather than forcing the Bolero user to do it. It is assumed
  1674.         // that the Bolero user will call EnumVerbs until it fails, otherwise
  1675.         // the enumerator will be left in an incoherent state
  1676.  
  1677.         // The strategy for pVerbEnumerator is different than other interfaces.
  1678.         // Usually, we just get a pointer to it during IPart::Init and hang on
  1679.         // to the pointer until the Part is destroyed. In this case, the verb
  1680.         // enumerator could be made invalid by closing the server app. Then
  1681.         // the Next function returns RPC_E_SERVERDIED. It seems that OLE2, probably
  1682.         // in the default handler, provides another enumerator which can get
  1683.         // the verbs, probably from the registration database, when the
  1684.         // server isn't running. So we'll obtain and release the pointer
  1685.         // dynamically.
  1686.  
  1687.         // The lpszVerbName field in the OLEVERB is dynamically allocated during
  1688.         // IEnumVerb::Next. In order to prevent a memory leak, deallocate it here.
  1689.         // The DidAlloc is probably unnecessary, but it's a little protection
  1690.         // against the user passing in a pBV->verbName which is just a random
  1691.         // value off the stack.
  1692.         //
  1693.         if (pBV->verbName) {
  1694.                 LPMALLOC pMalloc = NULL;
  1695.                 HRESULT hr = ::CoGetMalloc (MEMCTX_TASK, &pMalloc);
  1696.                 if (!SUCCEEDED(hr))
  1697.                         return hr;
  1698.                 if (!IsBadReadPtr ((LPVOID) pBV->verbName, 4) &&
  1699.                         pMalloc->DidAlloc ((LPVOID) pBV->verbName)) {
  1700.                         pMalloc->Free ((LPVOID) pBV->verbName);
  1701.                         pBV->verbName = NULL;
  1702.                 }
  1703.                 pMalloc->Release ();
  1704.         }
  1705.  
  1706.         if (verbIndex == 0) {
  1707.                 HRESULT hr = pOleObject->EnumVerbs(&pVerbEnumerator);
  1708.  
  1709.                 if (hr != NOERROR)
  1710.                         return hr;
  1711.  
  1712.                 pVerbEnumerator->Reset ();
  1713.         }
  1714.  
  1715.         // Loop over verbs looking for non-negative verb numbers. The negative
  1716.         // ones are "aliases" for other verbs, and shouldn't be displayed
  1717.         //
  1718.         // The loop stops when Next returns an error, but loops over alias
  1719.         // verbs. EnumVerbs should be called in a loop by the user
  1720.         //
  1721.         while (TRUE) {
  1722.                 SCODE sc = GetScode(pVerbEnumerator->Next (1, &oleVerb, NULL));
  1723.                 if (sc == S_OK) {
  1724.                         if (oleVerb.lVerb > -1) {
  1725.                                 pBV->verbName = oleVerb.lpszVerbName;
  1726.                                 pBV->typeName = GetName (BOLE_NAME_SHORT);
  1727.                                 pBV->verbIndex = oleVerb.lVerb;
  1728.                                 pBV->fCanDirty = !(oleVerb.grfAttribs & OLEVERBATTRIB_NEVERDIRTIES);
  1729.                                 verbIndex++;
  1730.                                 return NOERROR;
  1731.                         }
  1732.                 }
  1733.                 else {
  1734.                         verbIndex = 0;
  1735.                         pVerbEnumerator->Release ();
  1736.                         return ResultFromScode (sc);
  1737.                 }
  1738.         }
  1739. }
  1740.  
  1741. HRESULT _IFUNC BOlePart::DoVerb (UINT whichVerb)
  1742. {
  1743.         ForceOleRun(pOleObject);    // this line only added for Excel problems
  1744.  
  1745.         // Ask the container/app again for their names, in case something
  1746.         // is different from the last time we were open editing.
  1747.         //
  1748.         pOleObject->SetHostNames (pDoc->pApplication->GetAppName(),
  1749.                 pDoc->pContainer->GetWindowTitle());
  1750.  
  1751.         RECT rect;
  1752.         pSite->GetSiteRect (&rect, 0);
  1753.         HRESULT hRes = pOleObject->DoVerb((LONG) (int)whichVerb, NULL, this, 0,
  1754.                 pContainer->GetWindow(), &rect);
  1755.  
  1756.         if( !SUCCEEDED( hRes ) ){
  1757.                 // This following (potentially big) block will deserve a helper function.
  1758.                 // So far, only ONE error is implemented. Need to be completed.
  1759.                 // Reference: outline/cntrline.c: ContainerLine_ProcessOleRunError()
  1760.                 //
  1761.                 SCODE error = GetScode( hRes );
  1762.                 if ((error >= MK_E_FIRST && error <= MK_E_LAST) ||
  1763.                          (error == OLE_E_CANT_BINDTOSOURCE)) {
  1764.                         HandleLinkError();
  1765.                         fLinkSrcAvail = FALSE;
  1766.                 }
  1767.                 if( error == REGDB_E_CLASSNOTREG ){
  1768.                         // Server not registered (unexpected here?)
  1769.                 }
  1770.                 if( error == OLE_E_STATIC ){
  1771.                         // A static object with no server registered
  1772.                 }
  1773.                 if( error == OLE_E_CLASSDIFF ){
  1774.                         // Type of link has changed
  1775.                 }
  1776.                 if( ( error == CO_E_APPDIDNTREG )||( error == CO_E_APPNOTFOUND ) ){
  1777.                         // Server not found
  1778.                 }
  1779.                 if( error == E_OUTOFMEMORY ){
  1780.                         // Out of memory
  1781.                 }
  1782.                 return hRes;
  1783.         }
  1784.  
  1785.         HWND hWnd, hWndPrevParented;
  1786.         if (IsOpenInPlace && pInPlaceObject &&
  1787.                 SUCCEEDED(pInPlaceObject->GetWindow(&hWnd)) &&
  1788.                 SUCCEEDED(GetWindow(&hWndPrevParented))) {
  1789.                 while (hWnd && GetParent(hWnd) != hWndPrevParented) {
  1790.                         hWnd = GetParent(hWnd);  // make sure its the window they parented
  1791.                 }
  1792.                 if (hWnd && hWnd != GetTopWindow(GetParent(hWnd))) {
  1793.                         SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,   // MSWORD z-order workaround
  1794.                                 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  1795. #ifdef ANSI
  1796.                   LONG l = GetWindowLongA(hWnd, GWL_STYLE);  // visio paint problems
  1797.                   SetWindowLongA(hWnd, GWL_STYLE ,l | WS_CLIPSIBLINGS);  // visio paint problems
  1798. #else
  1799.                   LONG l = GetWindowLong(hWnd, GWL_STYLE);  // visio paint problems
  1800.                   SetWindowLong(hWnd, GWL_STYLE ,l | WS_CLIPSIBLINGS);  // visio paint problems
  1801. #endif
  1802.                 }
  1803.         }
  1804.  
  1805.         return hRes;
  1806. }
  1807.  
  1808. HRESULT _IFUNC BOlePart::DragFeedback(POINT*,BOOL)
  1809. {
  1810.         return ResultFromScode (E_NOTIMPL);
  1811. }
  1812.  
  1813. UINT _IFUNC BOlePart::CountFormats ()
  1814. {
  1815. #if 0
  1816.         LPENUMFORMATETC enumFormatEtc;
  1817.         UINT n = 0;
  1818.  
  1819.         if( pDataObject && SUCCEEDED( pDataObject->EnumFormatEtc( DATADIR_GET, &enumFormatEtc ) ) ){
  1820.                 FORMATETC fmt;
  1821.                 while( enumFormatEtc->Next( 1, &fmt, 0 ) == NOERROR )
  1822.                         n++;
  1823.                 enumFormatEtc->Release();
  1824.         }
  1825.         return n;
  1826. #else
  1827.         return 0;
  1828. #endif
  1829. }
  1830.  
  1831. HRESULT _IFUNC BOlePart::GetFormat ( UINT i, BOleFormat *BOleFmt )
  1832. {
  1833. #if 0
  1834.         LPENUMFORMATETC enumFormatEtc;
  1835.  
  1836.         if( pDataObject && SUCCEEDED( pDataObject->EnumFormatEtc( DATADIR_GET, &enumFormatEtc ) ) ){
  1837.                 FORMATETC fmt;
  1838.                 while( enumFormatEtc->Next( 1, &fmt, 0 ) != NOERROR && i-- );
  1839.                 _fmemset( BOleFmt, 0, sizeof( *BOleFmt ) );
  1840.                 BOleFmt->fmtId = fmt.cfFormat;
  1841.                 BOleFmt->fmtMedium = ( BOleMedium )fmt.tymed;
  1842.                 enumFormatEtc->Release();
  1843.         }
  1844.         return NOERROR;
  1845. #else
  1846.         return ResultFromScode (E_NOTIMPL);
  1847. #endif
  1848. }
  1849.  
  1850. HANDLE  _IFUNC BOlePart::GetFormatData (BOleFormat*pF)
  1851. {
  1852.         LPDATAOBJECT pDataObj = NULL;
  1853.         if (!pOleObject)
  1854.                 assert (FALSE);
  1855.  
  1856.         HRESULT hr = pOleObject->QueryInterface (IID_IDataObject, &(void FAR*) pDataObj);
  1857.  
  1858.         if (!pDataObj || !SUCCEEDED(hr))
  1859.                 return NULL;
  1860.  
  1861.         STGMEDIUM medium;
  1862.  
  1863.         // Just change it to WORD in boledefs.h please
  1864.         HANDLE h = pDoc->pService->GetDataFromDataObject (pDataObj,
  1865.                 (CLIPFORMAT)pF->fmtId, NULL, dwDrawAspect, &medium);
  1866.  
  1867.         pDataObj->Release ();
  1868.         //
  1869.  
  1870.         return h;
  1871. }
  1872.  
  1873. // Set data into the server
  1874. //
  1875. HRESULT  _IFUNC BOlePart::SetFormatData(BOleFormat* fmt, HANDLE hData, BOOL release)
  1876. {
  1877.   if (!fmt || !hData)
  1878.     return ResultFromScode(DATA_E_FORMATETC);
  1879.  
  1880.   LPDATAOBJECT pIData;
  1881.   HRESULT hr = pOleObject->QueryInterface (IID_IDataObject, &(LPVOID) pIData);
  1882.   if (!SUCCEEDED(hr))
  1883.     return hr;
  1884.  
  1885.   STGMEDIUM stm;
  1886.   _fmemset (&stm, 0, sizeof(STGMEDIUM));
  1887.   stm.tymed = TYMED_ISTORAGE;
  1888.  
  1889.   FORMATETC fe;
  1890.   _fmemset (&fe, 0, sizeof(FORMATETC));
  1891.   fe.cfFormat = fmt->fmtId;
  1892.   fe.ptd = NULL;
  1893.   fe.dwAspect = DVASPECT_CONTENT;
  1894.   fe.lindex = -1;
  1895.   fe.tymed = TYMED_HGLOBAL;
  1896.  
  1897.   return pIData->SetData (&fe, &stm, release);
  1898. }
  1899.  
  1900.  
  1901. LPOLESTR _IFUNC BOlePart::GetName (BOlePartName nameCode)
  1902. {
  1903.         // First see if we've already retrieved this name, and return
  1904.         // it without asking again
  1905.         //
  1906.         LPOLESTR FAR *ppName = NULL;
  1907.         switch (nameCode) {
  1908.                 case BOLE_NAME_LONG  : ppName = &pLongName; break;
  1909.                 case BOLE_NAME_SHORT : ppName = &pShortName; break;
  1910.                 case BOLE_NAME_APP   : ppName = &pAppName; break;
  1911.                 default              : return NULL;
  1912.         }
  1913.  
  1914.         if (*ppName)
  1915.                 return *ppName;
  1916.  
  1917.         if (!pOleObject)
  1918.                 return NULL;
  1919.  
  1920.         // Ask the OLE object for the name. GetUserType will allocate space
  1921.         // in our IMalloc, so we don't have to allocate it again. Of course,
  1922.         // we will have to free it later.
  1923.         //
  1924.         HRESULT hr = pOleObject->GetUserType (nameCode, ppName);
  1925.  
  1926.         if (!SUCCEEDED(hr) || !(*ppName))
  1927.                 return NULL;
  1928.  
  1929.         return *ppName;
  1930. }
  1931.  
  1932. HRESULT _IFUNC BOlePart::DoQueryInterface(REFIID iid, void FAR* FAR* pif)
  1933. {       return (pOleObject) ?
  1934.                 pOleObject->QueryInterface(iid, pif)
  1935.                 : ResultFromScode(E_NOINTERFACE);
  1936. }
  1937.  
  1938. #undef  OLE_INTERFACE
  1939. /**************************************************************************/
  1940. #define OLE_INTERFACE "IOleClientSite"
  1941.  
  1942. HRESULT _IFUNC BOlePart::SaveObject ()
  1943. {
  1944.         if (!pStgFromInit)
  1945.                 return ResultFromScode(E_NOTIMPL);
  1946.  
  1947.         return Save(pStgFromInit, TRUE, FALSE);
  1948. }
  1949.  
  1950. IMoniker * _IFUNC BOlePart::GetObjectMoniker(DWORD dwAssign)
  1951. {
  1952.         IMoniker* pMoniker = NULL;
  1953.         if (pszInstName) {
  1954.  
  1955.                 switch (dwAssign) {
  1956.                         case OLEGETMONIKER_FORCEASSIGN:
  1957.                                 OLE::CreateItemMoniker(TEXT("!"), pszInstName, &pMoniker);
  1958.                                 if (pOleObject && !MonikerAssigned) {
  1959.                                         pOleObject->SetMoniker(OLEWHICHMK_OBJREL, pMoniker);
  1960.                                         MonikerAssigned = TRUE;
  1961.                                 }
  1962.                                 break;
  1963.                         case OLEGETMONIKER_TEMPFORUSER:
  1964.                                 OLE::CreateItemMoniker(TEXT("!"), pszInstName, &pMoniker);
  1965.                                 break;
  1966.                         case OLEGETMONIKER_ONLYIFTHERE:
  1967.                                 if (MonikerAssigned) {
  1968.                                         OLE::CreateItemMoniker(TEXT("!"), pszInstName, &pMoniker);
  1969.                                 }
  1970.                                 break;
  1971.                         case OLEGETMONIKER_UNASSIGN:
  1972.                                 MonikerAssigned = FALSE;
  1973.                                 break;
  1974.                 }
  1975.         }
  1976.         return pMoniker;
  1977. }
  1978.  
  1979. HRESULT _IFUNC BOlePart::GetMoniker (DWORD dwAssign, DWORD dwWhichMoniker, IMoniker* FAR* ppmk)
  1980. {
  1981.         *ppmk = NULL;
  1982.         if (pILinkCont) {
  1983.                 switch (dwWhichMoniker) {
  1984.  
  1985.                         // Identifies the document within the filesystem
  1986.                         case OLEWHICHMK_CONTAINER:
  1987.                                 pILinkCont->GetMoniker(ppmk);
  1988.                                 break;
  1989.  
  1990.                         // Identifies the object relative to the document
  1991.                         case OLEWHICHMK_OBJREL:
  1992.                                 *ppmk = GetObjectMoniker(dwAssign);
  1993.                                 break;
  1994.  
  1995.                         // Identifies the doc and object absolutely
  1996.                         case OLEWHICHMK_OBJFULL:
  1997.                                 LPMONIKER pmkDoc;
  1998.                                 LPMONIKER pmkObj;
  1999.                                 if (SUCCEEDED(pILinkCont->GetMoniker(&pmkDoc))) {
  2000.                                         pmkObj = GetObjectMoniker(dwAssign);
  2001.                                         if (pmkObj) {
  2002.                                                 CreateGenericComposite(pmkDoc, pmkObj, ppmk);
  2003.                                                 pmkDoc->Release();
  2004.                                                 pmkObj->Release();
  2005.                                         }
  2006.                                 }
  2007.                                 break;
  2008.                 }
  2009.         }
  2010.         return ResultFromScode((*ppmk) ? S_OK : E_FAIL);
  2011. }
  2012.  
  2013. HRESULT _IFUNC BOlePart::GetContainer (IOleContainer* FAR* ppContainer)
  2014. {
  2015.         return pDoc->QueryInterface(IID_IOleContainer, (LPVOID*)ppContainer);
  2016. }
  2017.  
  2018. HRESULT _IFUNC BOlePart::ShowObject ()
  2019. {
  2020.         if (!IsOpenInPlace)
  2021.                 pSite->SiteShow (TRUE);
  2022.         return NOERROR;
  2023. }
  2024.  
  2025. HRESULT _IFUNC BOlePart::OnShowWindow (BOOL fShow)
  2026. {
  2027.         // The server app calls OnShowWindow when it believes we should draw
  2028.         // or redraw the open-editing shading over the object. To cut down on
  2029.         // the noise, only Invalidate if the new state is different.
  2030.         //
  2031.         if (fShow != IsOpen) {
  2032.                 IsOpen = fShow;
  2033.                 pSite->Invalidate(BOLE_INVAL_VIEW);
  2034.         }
  2035.         return NOERROR;
  2036. }
  2037.  
  2038. HRESULT _IFUNC BOlePart::RequestNewObjectLayout ()
  2039. {
  2040.         // The OUTLINE test app says OLE doesn't use this function yet.
  2041.         // The OLE docs say it can be called if the server needs more or less
  2042.         //   room in the client, but that the client can ignore the request if
  2043.         //       the client wants to determine the amount of available real estate
  2044.         //
  2045.         return ResultFromScode (E_NOTIMPL);
  2046. }
  2047.  
  2048. //*************************************************************************
  2049. //
  2050. // ILinkInfo implementation
  2051. //
  2052. //*************************************************************************
  2053.  
  2054. HRESULT _IFUNC BOlePart::SourceBreak()
  2055. {
  2056.         if (!pLinkObject)
  2057.                 return ResultFromScode (E_FAIL);
  2058.  
  2059.         // Break the link by setting its moniker to NULL
  2060.         //
  2061.         HRESULT hrErr = pLinkObject->SetSourceMoniker ((LPMONIKER)NULL, CLSID_NULL);
  2062.         if (SUCCEEDED(hrErr)) {
  2063.                 IsLink = FALSE;
  2064.                 pLinkObject->Release();
  2065.                 pLinkObject = NULL;
  2066.         }
  2067.  
  2068.         // Release all the pointers we have on this OLE object in preparation
  2069.         // for creating a new object. We might also delete the part, but it seems
  2070.         // rude to do that while the user still has a refcount on us.
  2071.         //
  2072.         //Close ();
  2073.  
  2074.         // Create a static object in place of the current link object
  2075.         //
  2076.         IDataObject *dataObj = NULL;
  2077.         hrErr = pOleObject->QueryInterface (IID_IDataObject, &(VOID FAR*)dataObj);
  2078.         if (hrErr != NOERROR)
  2079.                 return hrErr;
  2080.  
  2081.         FORMATETC fe;
  2082.         LPFORMATETC pFE;
  2083.         DWORD render;
  2084.         if (dwDrawAspect == DVASPECT_ICON) {
  2085.                 // If the link we're breaking is displayed as an icon, we'll have to
  2086.                 // display the static picture as content
  2087.                 //
  2088.                 fe.tymed = TYMED_NULL;
  2089.                 fe.ptd = NULL;
  2090.                 fe.lindex = -1;
  2091.                 fe.dwAspect = DVASPECT_ICON;
  2092.                 fe.cfFormat = 0;
  2093.                 pFE = &fe;
  2094. //              dwDrawAspect = DVASPECT_CONTENT;
  2095.         }
  2096.         else {
  2097.                 pFE = NULL;
  2098.         }
  2099.  
  2100.         render = OLERENDER_DRAW;
  2101.  
  2102.         pOleObject->Release(); //
  2103.  
  2104.         hrErr = OLE::OleCreateStaticFromData (dataObj, IID_IOleObject, render,
  2105.                 pFE, this, pStgFromInit, &(LPVOID)pOleObject);
  2106.  
  2107.         if (dataObj) {
  2108.                 dataObj->Release ();
  2109.                 dataObj = NULL;
  2110.         }
  2111.  
  2112.         return NOERROR;
  2113. }
  2114.  
  2115. HRESULT _IFUNC BOlePart::SourceGet(LPOLESTR FAR szOut, UINT count)
  2116. {
  2117.         if (!pOleObject || !pLinkObject)
  2118.                 return ResultFromScode (E_FAIL);
  2119.  
  2120.         LPOLESTR FAR *pShortType = NULL;
  2121.         LPOLESTR FAR *pFullType = NULL;
  2122.         LPOLESTR pDisplayName;
  2123.         DWORD len;
  2124.  
  2125.  
  2126.         BOOL b = SourceGet (&pDisplayName, pFullType, pShortType, &len);
  2127.  
  2128.         if (b) {
  2129.                 lstrcpyn( szOut, pDisplayName, count );
  2130.                 IMalloc *pMalloc;
  2131.                 if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pMalloc))) {
  2132.                         pMalloc->Free(pDisplayName);
  2133.                         pMalloc->Release();
  2134.                 }
  2135.         }
  2136.         return(b ? NOERROR : ResultFromScode (E_FAIL));
  2137. }
  2138.  
  2139. HRESULT _IFUNC BOlePart::SourceSet (LPOLESTR pNewSrc)
  2140. {
  2141.         if (!pLinkObject)
  2142.                 return ResultFromScode (E_FAIL);
  2143.  
  2144.         HRESULT hrErr = NOERROR;
  2145.         LPMONIKER pMk = NULLP;
  2146.         CLSID clsid   = CLSID_NULL;
  2147.         LPBC bindCtx  = NULLP;
  2148.  
  2149. //
  2150.  
  2151.         // Create a new bind context to use for these monikers
  2152.         //
  2153.         hrErr = OLE::CreateBindCtx (0 /*unused*/, &bindCtx);
  2154.         if (hrErr != NOERROR)
  2155.                 return hrErr;
  2156.  
  2157.         // Recursively resolve this textual representation into a binary moniker
  2158.         //
  2159.         DWORD chEaten = 0;
  2160.         hrErr = OLE::MkParseDisplayName (bindCtx, pNewSrc, &chEaten, &pMk);
  2161.         if (hrErr != NOERROR) {
  2162.                 bindCtx->Release ();
  2163.                 return hrErr;
  2164.         }
  2165.  
  2166.         // Obtain the CLSID of the object the moniker points to by using
  2167.         // a pointer to the IOleObject as a middleman
  2168.         //
  2169.         LPOLEOBJECT pObj = NULLP;
  2170.         hrErr = pMk->BindToObject (bindCtx, NULL, IID_IOleObject, &(VOID FAR*)pObj);
  2171.         if (hrErr == NOERROR) {
  2172.                 hrErr = pObj->GetUserClassID (&clsid);
  2173.                 pObj->Release();
  2174.  
  2175.                 OnViewChange (dwDrawAspect, -1); // get new size if any
  2176.                 fLinkSrcAvail = TRUE;
  2177.         }
  2178.         else {
  2179.                 HandleLinkError();
  2180.                 fLinkSrcAvail = FALSE;
  2181.         }
  2182. //
  2183. //
  2184. //
  2185. //
  2186. //
  2187. //
  2188. //
  2189. //
  2190. //
  2191. //
  2192. //
  2193. //
  2194. //
  2195.  
  2196.         // Make changes to the link object: if we were successful in getting a
  2197.         // moniker, use that, but fall back to the textual name if no moniker
  2198.         // was found.
  2199.         //
  2200.         if (pMk)
  2201.                 hrErr = pLinkObject->SetSourceMoniker (pMk, clsid);
  2202.         else
  2203.                 hrErr = pLinkObject->SetSourceDisplayName (pNewSrc);
  2204.  
  2205.         // Release scratch pointers (in reverse order)
  2206.         //
  2207.         if (pMk)
  2208.                 pMk->Release ();
  2209.         if (bindCtx)
  2210.                 bindCtx->Release ();
  2211.  
  2212.         // Now that the site is relinked to a new link source, we don't know
  2213.         // anything about the type of the new source. So delete the type
  2214.         // information we keep around. It will get allocated next time someone
  2215.         // asks for it.
  2216.         //
  2217.         DeleteTypeNames();
  2218.  
  2219.         if (hrErr == NOERROR)
  2220.                 UpdateNow();
  2221.  
  2222.         if (dwDrawAspect == DVASPECT_ICON) {
  2223.                 CacheIconicAspect(OleGetIconOfFile (pNewSrc, TRUE));
  2224.         }
  2225.  
  2226.         return hrErr;
  2227. }
  2228.  
  2229. HRESULT _IFUNC BOlePart::SourceOpen()
  2230. {
  2231.         if (!pOleObject)
  2232.                 return ResultFromScode (E_FAIL);
  2233.  
  2234.         return DoVerb (OLEIVERB_SHOW);
  2235. }
  2236.  
  2237. HRESULT _IFUNC BOlePart::UpdateGet(BOleLinkUpdate *pOptions)
  2238. {
  2239.         if (!pLinkObject)
  2240.                 return ResultFromScode (E_FAIL);
  2241.  
  2242.         // Use a temporary to avoid problems since BOleLinkUpdate is an enum
  2243.         // of some size (we don't want to rely on) and the update options
  2244.         // are a long
  2245.         //
  2246.         DWORD o = 0;
  2247.         HRESULT hrErr = pLinkObject->GetUpdateOptions (&o);
  2248.         *pOptions = (BOleLinkUpdate)o;
  2249.  
  2250.         return hrErr;
  2251. }
  2252.  
  2253. HRESULT _IFUNC BOlePart::UpdateSet(BOleLinkUpdate options)
  2254. {
  2255.         if (!pLinkObject)
  2256.                 return ResultFromScode (E_FAIL);
  2257.  
  2258.         HRESULT hrErr = pLinkObject->SetUpdateOptions (options);
  2259.         return hrErr;
  2260. }
  2261.  
  2262. // Since we don't know why Excel returns RPC_E_CALL_REJECTED the
  2263. // first N times and then finally works, we have this kludge.
  2264. //
  2265. HRESULT ForceOleUpdate(IOleObject *pOO)
  2266. {
  2267.         int timeout = 500;
  2268.         while (timeout-- > 0) {
  2269.                 if (ResultFromScode(RPC_E_CALL_REJECTED) != pOO->Update())
  2270.                         break;
  2271.         }
  2272.         return (timeout == 0) ? ResultFromScode(RPC_E_CALL_REJECTED) : NOERROR;
  2273. }
  2274.  
  2275. HRESULT _IFUNC BOlePart::UpdateNow()
  2276. {
  2277.         if (!pOleObject)
  2278.                 return ResultFromScode (E_FAIL);
  2279.  
  2280.         HRESULT hrErr = pOleObject->IsUpToDate ();
  2281.         if (hrErr != NOERROR)
  2282.                 hrErr = ForceOleUpdate(pOleObject);
  2283.  
  2284.         return hrErr;
  2285. }
  2286.  
  2287. // This version of SourceGet is not part of the public bolero
  2288. // interface for now. It only exists to support IOleUILinkContainer::GetLinkSource
  2289. // Maybe we'll end up putting more stuff in the Bolero version ???
  2290. //
  2291. BOOL _IFUNC BOlePart::SourceGet
  2292. (
  2293.         LPOLESTR FAR *lplpszDisplayName,
  2294.         LPOLESTR FAR *lplpszFullLinkType,
  2295.         LPOLESTR FAR *lplpszShortLinkType,
  2296.         DWORD FAR *lplenFileName
  2297. )
  2298. {
  2299.         if (!pOleObject || !pLinkObject)
  2300.                 return FALSE;
  2301.  
  2302.         LPMONIKER pmk;
  2303.         HRESULT hrErr = pLinkObject->GetSourceMoniker (&pmk);
  2304.         if (hrErr == NOERROR) {
  2305.                 pOleObject->GetUserType (USERCLASSTYPE_FULL, lplpszFullLinkType);
  2306.                 pOleObject->GetUserType (USERCLASSTYPE_SHORT, lplpszShortLinkType);
  2307.                 *lplenFileName = OleStdGetLenFilePrefixOfMoniker (pmk);
  2308.                 pmk->Release ();
  2309.         }
  2310.  
  2311.         hrErr = pLinkObject->GetSourceDisplayName (lplpszDisplayName);
  2312.         return (hrErr == NOERROR);
  2313. }
  2314.  
  2315. BOlePart * _IFUNC BOlePart::GetNextLink (BOOL fAllowThis)
  2316. {
  2317.         BOlePart *ret = fAllowThis ? this : this->pNextPart;
  2318.         while (ret) {
  2319.                 if (ret->IsLink)
  2320.                         return ret;
  2321.                 ret = ret->pNextPart;
  2322.         }
  2323.         return NULLP;
  2324. }
  2325.  
  2326. //*************************************************************************
  2327. //
  2328. // IAdviseSink implementation
  2329. //
  2330. //*************************************************************************
  2331.  
  2332. void _IFUNC BOlePart::OnDataChange (FORMATETC FAR* pFormatetc,STGMEDIUM FAR* pStgmed)
  2333. {
  2334.         // I'm not sure how to respond to this, vs how to respond to OnViewChange.
  2335.         //  It seems like if our visible view onto the data hasn't changed, then
  2336.         //  we're not interested in OnDataChange. Maybe there's some significance
  2337.         //  for non-visible server objects...
  2338.         //
  2339. #ifdef _DEBUG
  2340.         MessageBox (NULL, OLESTR("BOLE.DLL"), OLESTR("Unexpected call to OnDataChange"), MB_OK);
  2341. #endif
  2342.         return;
  2343. }
  2344.  
  2345. void _IFUNC BOlePart::OnViewChange (DWORD changedAspect, LONG lindex)
  2346. {
  2347.         // The server may generate an OnViewChange when its extent changes,
  2348.         // so try to make the site the same size.
  2349.         //
  2350.         // This is really important for Paintbrush (all OLE1 servers?) whose
  2351.         // initial size is zero, and don't send OnPosRectChanged (because
  2352.         // they're never inplace). They only send OnViewChange, and expect
  2353.         // us to get the new extent.
  2354.         //
  2355.         // The changedAspect parameter tells us which aspect's view has
  2356.         // changed. It seems like we only care if the aspect we're currently
  2357.         // viewing is the same as the one which has changed.
  2358.         //
  2359.  
  2360.         if (dwDrawAspect == changedAspect) {
  2361.  
  2362.                 // this can be called when we've resized the site, but not set
  2363.                 // the part extent. In such a case the part extent is not equal to
  2364.                 // the site extent.  The part is scaling by the ratio, scaleSite (set in
  2365.                 // OnUIActivate).  So, we need to scale the part extent
  2366.                 // and set our site size to that. If we were to just use the part's
  2367.                 // extent, the symptom would be that upon deactivation the site
  2368.                 // would return to the size it had before the (non-active) site
  2369.                 // was resized, (or worse if an in-place active resize happened too).
  2370.  
  2371.                 SIZE shortSize;
  2372.  
  2373.                 GetPartSize(&shortSize);
  2374.  
  2375.                 // adjust by additional scaling caused when resizing site while
  2376.                 // not in place active (and not setting server extent).
  2377.  
  2378.                 OLEPRINTF5("Adjusting by scaleSite:\t {%ld, %ld, %ld, %ld}",
  2379.                         scaleSite.xN, scaleSite.xD, scaleSite.yN, scaleSite.yD);
  2380.  
  2381.                 shortSize.cx = Scale(shortSize.cx, scaleSite.xN, scaleSite.xD);
  2382.                 shortSize.cy = Scale(shortSize.cy, scaleSite.yN, scaleSite.yD);
  2383.  
  2384.                 if (!SUCCEEDED(pSite->SetSiteExtent(&shortSize))) {
  2385.  
  2386.                         // if client doesn't accept server's extent maybe the
  2387.                         // server will accept the client's...
  2388.                         //
  2389.                         RECT rSite, rClip;
  2390.                         HRESULT hr = pSite->GetSiteRect(&rSite, &rClip);
  2391.                         if (SUCCEEDED(hr)) {
  2392.                                 SIZE sizeSite = {rSite.right - rSite.left, rSite.bottom - rSite.top};
  2393.                                 SetPartSize(&sizeSite);
  2394.                         }
  2395.                 }
  2396.  
  2397.                 // Generate a paint message for the client app's window, which will
  2398.                 // eventually call back to our pViewObject->Draw
  2399.                 //
  2400.                 pSite->Invalidate(BOLE_INVAL_VIEW | BOLE_INVAL_DATA);
  2401.                 UpdateSiteScaleFactor();
  2402.         }
  2403.  
  2404.         return;
  2405. }
  2406.  
  2407. void _IFUNC BOlePart::OnRename (IMoniker* pmk)
  2408. {
  2409.         // Significant for IOleLink objects which must track the link source
  2410.         //
  2411.         //
  2412.         return;
  2413. }
  2414.  
  2415. void _IFUNC BOlePart::OnSave ()
  2416. {
  2417.         // Significant if the client implements IOleCache with ADVF_ONSAVE
  2418.         //
  2419.         return;
  2420. }
  2421.  
  2422. void _IFUNC BOlePart::OnClose ()
  2423. {
  2424.         // Significant for IOleLink objects when server is shutting down
  2425.         //
  2426.         return;
  2427. }
  2428.  
  2429.  
  2430. //**************************************************************************
  2431. //
  2432. // IOleWindow implementation
  2433. //
  2434. //**************************************************************************
  2435.  
  2436. HRESULT _IFUNC BOlePart::GetWindow (HWND FAR *phwnd)
  2437. {
  2438.         HRESULT hr = NOERROR;
  2439.         PIBSite2 pSite2 = NULL;
  2440.         *phwnd = NULL;
  2441.  
  2442.         hr = pObjOuter->QueryInterfaceMain (IID_IBSite2, &(LPVOID)pSite2);
  2443.         if (SUCCEEDED (hr)) {
  2444.                 hr = pSite2->GetParentWindow (phwnd);
  2445.                 pSite2->Release();
  2446.         }
  2447.         else {
  2448.                 *phwnd = pContainer->GetWindow();
  2449.                 hr = NOERROR;
  2450.         }
  2451.  
  2452.         return hr;
  2453. }
  2454.  
  2455. HRESULT _IFUNC BOlePart::ContextSensitiveHelp (BOOL fEnterMode)
  2456. {
  2457.         // The BOleService object is responsible for keeping track of Shift-F1
  2458.         //
  2459.         pDoc->pService->SetHelpMode (fEnterMode);
  2460.  
  2461.         return NOERROR;
  2462. }
  2463.  
  2464. //**************************************************************************
  2465. //
  2466. // IOleInPlaceSite Implementation
  2467. //
  2468. //**************************************************************************
  2469.  
  2470. HRESULT _IFUNC BOlePart::CanInPlaceActivate (void)
  2471. {
  2472.         HRESULT hr;
  2473.         // Objects rendered as an icon can only be edited "out of place"
  2474.         //
  2475.         if (dwDrawAspect == DVASPECT_ICON)
  2476.                 OLERET(S_FALSE);
  2477.  
  2478.         return pContainer->AllowInPlace();
  2479. }
  2480.  
  2481. HRESULT _IFUNC BOlePart::OnInPlaceActivate (void)
  2482. {
  2483.         // In case we don't have balanced calls...
  2484.         if (pInPlaceObject) {
  2485.                 pInPlaceObject->Release();
  2486.                 pInPlaceObject = NULL;
  2487.         }
  2488.         // This is our opportunity to get a pointer to the object's
  2489.         // IOleInPlaceObject interface
  2490.         //
  2491.         HRESULT hr = pOleObject->QueryInterface(IID_IOleInPlaceObject, &(VOID FAR*)pInPlaceObject);
  2492.  
  2493.         if (hr == NOERROR) {
  2494.                 IsOpenInPlace = TRUE;
  2495.                 // If the object has opened in place site should hide themselves to
  2496.                 // avoid strange drawing behavior
  2497.                 //
  2498.                 pSite->SiteShow (FALSE);
  2499.         }
  2500.         else {
  2501.                 IsOpenInPlace = FALSE;
  2502.                 pInPlaceObject = NULL;
  2503.         }
  2504.  
  2505.         return hr;
  2506. }
  2507.  
  2508. HRESULT _IFUNC BOlePart::OnInPlaceDeactivate (void)
  2509. {
  2510.         if (pInPlaceObject) {
  2511.                 pInPlaceObject->Release();
  2512.                 pInPlaceObject = NULL;
  2513.         }
  2514.         if (IsOpenInPlace) {
  2515.                 IsOpenInPlace = FALSE;
  2516.                 pSite->SiteShow (TRUE);    // put the site window back again
  2517.         }
  2518.         return NOERROR;
  2519. }
  2520.  
  2521. // Remember the additional scale factor for this site.
  2522. // If we've resized the site the scale factor is different than normal.
  2523. // We need to know it in OnViewChange, in case the server is resized
  2524. // when in-place active.
  2525. //
  2526. void BOlePart::UpdateSiteScaleFactor()
  2527. {
  2528.         RECT rPos, rClip;
  2529.         if (SUCCEEDED(pSite->GetSiteRect (&rPos, &rClip))) {
  2530.  
  2531.                 SIZE sizePart;
  2532.                 GetPartSize(&sizePart);
  2533.  
  2534.                 if ((sizePart.cx == 0) || (sizePart.cy == 0)) {
  2535.                         scaleSite.xN = scaleSite.xD = scaleSite.yN = scaleSite.yD = 1L;
  2536.                 }
  2537.                 else {
  2538.                         scaleSite.xN = rPos.right - rPos.left;
  2539.                         scaleSite.xD = sizePart.cx;
  2540.                         scaleSite.yN = rPos.bottom - rPos.top;
  2541.                         scaleSite.yD = sizePart.cy;
  2542.                 }
  2543.                 OLEPRINTF5("Updating scaleSite:\t {%ld, %ld, %ld, %ld}",
  2544.                         scaleSite.xN, scaleSite.xD, scaleSite.yN, scaleSite.yD);
  2545.         }
  2546. }
  2547.  
  2548. HRESULT _IFUNC BOlePart::OnUIActivate (void)
  2549. {
  2550.         OLEPRINTF1("Entering OnUIActivate");
  2551.  
  2552.         // (Used to UpdateSiteScaleFactor in GetWindowContext.
  2553.         // But, MS Excel Chart doesn't give accurate extents at that point
  2554.         // In OnInPlaceActivate Excel Chart gives inaccurate extents.
  2555.         // In OnUIActivate Excel Sheet gives inaccurate extents.
  2556.         //
  2557.         UpdateSiteScaleFactor();
  2558.  
  2559.         // The inplace server is about to put up its own tool/status
  2560.         // bars, so ask the client app to remove its adorners
  2561.         //
  2562.         // Although it isn't in the official docs, the Outline example
  2563.         // (in frametls.c) uses the convention where SetBorderSpace({0,})
  2564.         // means hide adornments
  2565.  
  2566.         // hide their adornments
  2567.         //
  2568.         HRESULT hr = NOERROR;
  2569.  
  2570.         LPOLEINPLACESITE pIPS;
  2571.         if (SUCCEEDED(GetParentIPS(&pIPS))) {
  2572.                 IBPart *pServerSide;
  2573.                 if (SUCCEEDED(pDoc->QueryInterface(IID_IBPart, &(LPVOID)pServerSide))) {
  2574.                         pServerSide->ShowTools(FALSE);
  2575.                         pServerSide->Release();
  2576.                 }
  2577.                 pIPS->Release();
  2578.         }
  2579.         else {
  2580.                 RECT r = {0,0,0,0};
  2581.  
  2582.                 pContainer->BringToFront();
  2583.  
  2584.                 IBWindow *pWnd = getNegotiator(pDoc->pApplication, pContainer);
  2585.  
  2586.                 hr = pWnd->SetBorderSpace (&r);
  2587.         }
  2588.  
  2589.         pSite->OnSetFocus(TRUE);
  2590.  
  2591.         // Hitting ESC from some servers only does a UIDeactivate so
  2592.         // next time you activate it, it only calls OnUIActivate rather
  2593.         // than OnInPlaceActivate. So be sure to keep the flags coherent with
  2594.         // the real state.
  2595.         //
  2596.         IsOpenInPlace = TRUE;
  2597.         pSite->SiteShow (FALSE); // assumes hiding an already hidden site is a nop
  2598.  
  2599.         return hr;
  2600. }
  2601.  
  2602. HRESULT _IFUNC BOlePart::OnUIDeactivate (BOOL fUndoable)
  2603. {
  2604.         // The inplace server is about to remove its own tool/status
  2605.         // bars, so ask the client app to restore its adorners
  2606.         //
  2607.         // Although it isn't in the official docs, the Outline example
  2608.         // (in frametls.c) uses the convention where SetBorderSpace(NULL)
  2609.         // means show adornments
  2610.         //
  2611.  
  2612.         HRESULT hr = NOERROR;
  2613.  
  2614.         if (IsOpenInPlace && !IsOpenInsideOut) {
  2615.                 // when ESC key is used to deactivate excel and word
  2616.                 // OnInPlaceDeactivate is not called.
  2617.                 pSite->SiteShow (TRUE);    // put the site window back again
  2618.                 IsOpenInPlace = FALSE;
  2619.         }
  2620.  
  2621.         // This SetFocus call is to take the focus back from the OLE object's
  2622.         // inplace window, since that window has gone away
  2623.         //
  2624.         pSite->OnSetFocus(TRUE);
  2625.  
  2626.         LPOLEINPLACESITE pIPS;
  2627.         if (SUCCEEDED(GetParentIPS(&pIPS))) {
  2628.                 IBPart *pServerSide;
  2629.                 if (SUCCEEDED(pDoc->QueryInterface(IID_IBPart, &(LPVOID)pServerSide))) {
  2630.                         pServerSide->ShowTools(TRUE);
  2631.                         pServerSide->Release();
  2632.                 }
  2633.                 pIPS->Release();
  2634.         }
  2635.         else {
  2636.                 // show their adornments
  2637.                 //
  2638.                 IBWindow *pWnd = getNegotiator(pDoc->pApplication, pContainer);
  2639.  
  2640.                 hr = pWnd->SetBorderSpace (NULL);
  2641.  
  2642.                 // We're using this call to our own IOleInPlaceFrame implementation
  2643.                 // to get to OleSetMenuDescriptor(NULL), which is supposed to unhook
  2644.                 // OLE's message dispatching stuff. We could just call
  2645.                 // OleSetMenuDescriptor from here, but it's not clear if the server
  2646.                 // app might call SetMenu with NULL for the same purpose?
  2647.                 //
  2648.                 // The pointer-juggling here is intended to make sure we disconnect
  2649.                 // the OLE message filter from the right window (frame vs. container).
  2650.                 //
  2651.                 IOleInPlaceFrame FAR *ipframe = NULL;
  2652.                 if (S_OK == (GetScode(pDoc->pApplication->IsMDI())))
  2653.                         ipframe = pDoc->pService;
  2654.                 else
  2655.                         ipframe = pDoc;
  2656.                 PIBWindow ipNegWnd = getNegotiator (pDoc->pApplication, pDoc->pContainer);
  2657.                 hr = ipframe->SetMenu (NULL, NULL, ipNegWnd->GetWindow());
  2658.         }
  2659.  
  2660.         return hr;
  2661. }
  2662.  
  2663. HRESULT _IFUNC BOlePart::GetParentIPS(LPOLEINPLACESITE *ppIPS)
  2664. {
  2665.         HRESULT hr = ResultFromScode(E_NOINTERFACE);
  2666.         LPOLEOBJECT pSelfAsServer;
  2667.         if (SUCCEEDED(pDoc->QueryInterface(IID_IOleObject, &(LPVOID)pSelfAsServer))) {
  2668.                 LPOLECLIENTSITE pCS;
  2669.                 if (SUCCEEDED(pSelfAsServer->GetClientSite(&pCS)) && pCS) {
  2670.                         hr = pCS->QueryInterface(IID_IOleInPlaceSite, (LPVOID*)ppIPS);
  2671.                         pCS->Release();
  2672.                 }
  2673.                 pSelfAsServer->Release();
  2674.         }
  2675.         return hr;
  2676. }
  2677.  
  2678. HRESULT _IFUNC BOlePart::GetWindowContext (IOleInPlaceFrame* FAR* ppFrame, IOleInPlaceUIWindow* FAR* ppDoc, LPRECT prcPosRect, LPRECT prcVisRect, LPOLEINPLACEFRAMEINFO pFrameInfo)
  2679. {
  2680.         LPOLEINPLACESITE pIPSite;
  2681.         if (SUCCEEDED(GetParentIPS(&pIPSite)) && (S_OK == pIPSite->CanInPlaceActivate ()))
  2682.         {
  2683.                 // if nested in place active,
  2684.                 // get parent's window interfaces, but our site size
  2685.                 //
  2686.                 HRESULT hr = pIPSite->GetWindowContext(ppFrame, ppDoc, prcPosRect,
  2687.                                                prcVisRect, pFrameInfo);
  2688.                 pIPSite->Release();
  2689.                 pSite->GetSiteRect (prcPosRect, prcVisRect);
  2690.                 return hr;
  2691.         }
  2692.  
  2693.         // The isMdi flag tells the server whether it should negotiate for
  2694.         // space on the "frame" window or the "document" window
  2695.         //
  2696.         IBApplication * pApp = pDoc->pApplication;
  2697.         pFrameInfo->fMDIApp = (GetScode(pApp->IsMDI()) == S_OK) ? TRUE : FALSE;
  2698.  
  2699.         // Decide which window should do inplace negotiation
  2700.         //
  2701.         PIBWindow ipNegWnd = NULL;
  2702.         if (pFrameInfo->fMDIApp)
  2703.                 ipNegWnd = pDoc->pApplication;
  2704.         else
  2705.                 ipNegWnd = pContainer;
  2706.  
  2707.         // Decide which HWND to give out so toolbar parenting etc is correct
  2708.         //
  2709.         pFrameInfo->hwndFrame = ipNegWnd->GetWindow();
  2710.  
  2711.         // Allow the server to call back for menu negotiation at the document level
  2712.         //
  2713.         ipNegWnd->QueryInterface (IID_IOleInPlaceFrame, (void**) ppFrame);
  2714.  
  2715.         // Allow the server to call back for toolbar negotiation at the document level
  2716.         //
  2717.         if (pFrameInfo->fMDIApp)
  2718.                 pDoc->QueryInterface (IID_IOleInPlaceUIWindow, (void**)ppDoc);
  2719.         else
  2720.                 *ppDoc = NULL;
  2721.  
  2722.         // Get the accelerator table from the window
  2723.         //
  2724.         if (!SUCCEEDED(ipNegWnd->GetAccelerators (&pFrameInfo->haccel,
  2725.                 (int FAR *) (&pFrameInfo->cAccelEntries)))) {
  2726.                 pFrameInfo->haccel = NULL;
  2727.                 pFrameInfo->cAccelEntries = 0;
  2728.         }
  2729.  
  2730.         pSite->GetSiteRect (prcPosRect, prcVisRect);
  2731.  
  2732.         return NOERROR;
  2733. }
  2734.  
  2735. HRESULT _IFUNC BOlePart::DiscardUndoState ()
  2736. {
  2737.         //
  2738.         return ResultFromScode (E_NOTIMPL);
  2739. }
  2740.  
  2741. HRESULT _IFUNC BOlePart::DeactivateAndUndo ()
  2742. {
  2743.         // This is called by the server when the user picks Undo immediately
  2744.         // after activating the server inplace. We should remove the server's
  2745.         // adornments, set focus to ourselves, and pop the undo stack
  2746.         //
  2747.         HRESULT hr = pInPlaceObject->UIDeactivate();
  2748.         if (hr != NOERROR)
  2749.                 return hr;
  2750.  
  2751.         pSite->OnSetFocus(TRUE);
  2752.         //
  2753.         return NOERROR;
  2754. }
  2755.  
  2756. HRESULT _IFUNC BOlePart::Scroll (SIZE scrollExtent)
  2757. {
  2758.         //
  2759.         return ResultFromScode (E_NOTIMPL);
  2760. }
  2761.  
  2762. HRESULT _IFUNC BOlePart::OnPosRectChange (LPCRECT lprcPosRect)
  2763. {
  2764.         HRESULT hr;
  2765.         // The server size is changing, let's try to set it in the container..
  2766.  
  2767.         OLEPRINTF1("Entering OnPosRectChange");
  2768.         if (SUCCEEDED(pSite->SetSiteRect (lprcPosRect))) {
  2769.                 RECT posR, clipR;
  2770.                 pSite->GetSiteRect (&posR, &clipR);
  2771.                 if (pInPlaceObject) {
  2772.                         // use lprcPosRect because the site may not want to really
  2773.                         // change the extent.  They could succeed to allow
  2774.                         // the in-place window to be free, but when the user
  2775.                         // deactivates go back to the same old site.
  2776.                         hr = pInPlaceObject->SetObjectRects (lprcPosRect, &clipR);
  2777.                 }
  2778.         }
  2779.         else {
  2780.                 // try to back out of hatch window resize with the fewest possible
  2781.                 // side effects.  This is best all around solution.  Although visio
  2782.                 // scales inappropriately, one can live with it.
  2783.  
  2784.                 RECT rSite, rClip;
  2785.                 pSite->GetSiteRect(&rSite, &rClip);
  2786.                 SIZE sizeSite = {rSite.right - rSite.left, rSite.bottom - rSite.top};
  2787.  
  2788.                 SetPartSize(&sizeSite);
  2789.                 pInPlaceObject->SetObjectRects (&rSite, &rClip);
  2790.                 hr = ResultFromScode(E_FAIL);
  2791.  
  2792. #if 0
  2793.                 // Here are the other trials:
  2794.  
  2795.                 // this approach causes visio to scale inappropriately
  2796.                 // and excel's extents to be wrong
  2797.                 SetPartSize(&sizeSite);
  2798.                 hr = pInPlaceObject->SetObjectRects (&rSite, &rClip);
  2799.  
  2800.                 // w/o SetPartSize also excel sheet and chart scale inappropriately
  2801.                 hr = pInPlaceObject->SetObjectRects (&rSite, &rClip);
  2802.  
  2803.                 // same but chart in MS excel is a bit better
  2804.                 pInPlaceObject->SetObjectRects (&rSite, &rClip);
  2805.                 hr = ResultFromScode(E_FAIL);
  2806.  
  2807.                 // this approach causes servers (chart, visio) to leave hatch window
  2808.                 SetPartSize(&sizeSite);
  2809.                 hr = NOERROR;
  2810.  
  2811.                 // same but chart doesn't leave window, only visio
  2812.                 SetPartSize(&sizeSite);
  2813.                 hr = ResultFromScode(E_FAIL);
  2814.  
  2815.                 // just failing causes both scale factor and window problems
  2816.                 hr = ResultFromScode(E_FAIL);
  2817.  
  2818.                 // doing the set part size after plays havoc with scaling
  2819.                 pInPlaceObject->SetObjectRects (&rSite, &rClip);
  2820.                 SetPartSize(&sizeSite);
  2821.                 hr = ResultFromScode(E_FAIL);
  2822.  
  2823. #endif
  2824.         }
  2825.         return hr;
  2826. }
  2827.  
  2828. HRESULT _IFUNC BOlePart::GetMoniker(IMoniker FAR* FAR* ppMon)
  2829. {
  2830.         HRESULT hrErr = GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
  2831.                 OLEWHICHMK_OBJFULL, ppMon);
  2832.         return hrErr;
  2833. }
  2834.  
  2835. HRESULT _IFUNC BOlePart::OnRename(PIBLinkable pCont, LPCOLESTR szName)
  2836. {
  2837.         HRESULT hrErr = NOERROR;
  2838.  
  2839.         pILinkCont = pCont;
  2840.         if (pszInstName) {
  2841.                 delete pszInstName;
  2842.                 pszInstName = NULL;
  2843.         }
  2844.         if (szName) {
  2845.                 pszInstName = new OLECHAR[strlen (szName) +1];
  2846.                 lstrcpy(pszInstName, szName);
  2847.         }
  2848.  
  2849.         if (pOleObject) {
  2850.                 LPMONIKER pMon;
  2851.                 // Server registers as GetObjectMoniker calls IOleObject::SetMoniker
  2852.                 GetObjectMoniker(OLEGETMONIKER_UNASSIGN);    // really force!
  2853.                 pMon = GetObjectMoniker(OLEGETMONIKER_FORCEASSIGN);
  2854.                 if (pMon)
  2855.                         pMon->Release();
  2856.  
  2857.                 // update window title
  2858.                 if (pszInstName) {
  2859.                         pOleObject->SetHostNames (pDoc->pApplication->GetAppName(),
  2860.                         pDoc->pContainer->GetWindowTitle());
  2861.                 }
  2862.         }
  2863.         return hrErr;
  2864. }
  2865.  
  2866. //**************************************************************************
  2867. //
  2868. // IDropSource Implementation -- Although this is normally implemented by
  2869. //                               server objects, we need it on our client
  2870. //                               side helper to do "embed from embedding"
  2871. //                               which is where you drag/drop or copy/paste
  2872. //                               from an existing embedded object.
  2873. //
  2874. //**************************************************************************
  2875.  
  2876. HRESULT _IFUNC BOlePart::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
  2877. {
  2878.         SCODE sc;
  2879.  
  2880.         if (fEscapePressed)
  2881.                 sc = DRAGDROP_S_CANCEL;
  2882.         else
  2883.                 if (!(grfKeyState & MK_LBUTTON))
  2884.                         sc = DRAGDROP_S_DROP;
  2885.                 else
  2886.                         sc = S_OK;
  2887.  
  2888.         return ResultFromScode (sc);
  2889.  
  2890. }
  2891.  
  2892. HRESULT _IFUNC BOlePart::GiveFeedback(DWORD dwEffect)
  2893. {
  2894.         //
  2895.         //
  2896.         return ResultFromScode (DRAGDROP_S_USEDEFAULTCURSORS);
  2897. }
  2898.  
  2899. //**************************************************************************
  2900. //
  2901. // CopyFromOriginal() helpers
  2902. //
  2903. //**************************************************************************
  2904.  
  2905. HRESULT _IFUNC BOlePart::AddCachedData (IDataObject *pTarget)
  2906. {
  2907.         BOOL fAddedMetafile = FALSE;
  2908.         LPOLECACHE pOleCache;
  2909.  
  2910.         if (SUCCEEDED (pOleObject && pDataObject &&
  2911.                 pOleObject->QueryInterface (IID_IOleCache, &(LPVOID) pOleCache))) {
  2912.  
  2913.                 // Get IEnumSTATDATA interface for IOleCache
  2914.                 //
  2915.                 LPENUMSTATDATA lpEnumSTATDATA;
  2916.                 if (pOleCache->EnumCache (&lpEnumSTATDATA) == NOERROR && lpEnumSTATDATA) {
  2917.  
  2918.                         // Enumerate all of the cached formats
  2919.                         //
  2920.                         STATDATA statData;
  2921.                         while (lpEnumSTATDATA->Next (1, &statData, NULL) == NOERROR) {
  2922.                                 OLECHAR name[32];
  2923.                                 GetClipboardFormatName( statData.formatetc.cfFormat, name, sizeof(name));
  2924.  
  2925.                                 // For each "cachable" format, try to get a copy of the data
  2926.                                 //
  2927.                                 STGMEDIUM stgMedium;
  2928.                                 if (pDataObject->GetData (&statData.formatetc, &stgMedium) != NOERROR) {
  2929.                                         // Data is not available
  2930.                                 }
  2931.                                 else
  2932.                                         if (stgMedium.pUnkForRelease != NULL) {
  2933.  
  2934.                                                 // Don't cache data with pUnkForRelease != NULL
  2935.                                                 //
  2936.                                                 ::ReleaseStgMedium (&stgMedium);
  2937.                                                 ::OleStdDeleteTargetDevice (statData.formatetc.ptd);
  2938.                                         }
  2939.                                         else {
  2940.  
  2941.                                                 // Transfer to the target
  2942.                                                 //
  2943.                                                 pTarget->SetData (&statData.formatetc, &stgMedium, TRUE /*give ownership*/);
  2944.                                                 if (statData.formatetc.cfFormat == CF_METAFILEPICT)
  2945.                                                         fAddedMetafile = TRUE;
  2946.                                         }
  2947.                         }
  2948.                         lpEnumSTATDATA->Release();
  2949.                 }
  2950.                 pOleCache->Release();
  2951.         }
  2952.  
  2953.         // Just about everyone has a metafile in the cache. Paintbrush does not,
  2954.         // so we'll add it forcibly here.
  2955.         //
  2956.         if (!fAddedMetafile) {
  2957.                 FORMATETC fe;
  2958.                 fe.cfFormat = CF_METAFILEPICT;
  2959.                 fe.tymed = TYMED_MFPICT;
  2960.                 fe.lindex = -1;
  2961.                 fe.ptd = NULL;
  2962.  
  2963.                 SIZEL sizel;
  2964.                 if (NOERROR != pOleObject->GetExtent (dwDrawAspect, &sizel)) {
  2965.                         RECT rcpos, rcclip;
  2966.                         pSite->GetSiteRect (&rcpos, &rcclip);
  2967.                         sizel.cx = MAP_PIX_TO_LOGHIM (rcpos.right - rcpos.left, BOleService::pixPerIn.x);
  2968.                         sizel.cy = MAP_PIX_TO_LOGHIM (rcpos.bottom - rcpos.top, BOleService::pixPerIn.y);
  2969.                 }
  2970.  
  2971.                 STGMEDIUM sm;
  2972.                 sm.tymed = TYMED_MFPICT;
  2973.                 sm.pUnkForRelease = NULL;
  2974.                 sm.hGlobal = OleStdGetMetafilePictFromOleObject (pOleObject,
  2975.                         dwDrawAspect, &sizel, NULL);
  2976.                 if (sm.hGlobal)
  2977.                         pTarget->SetData (&fe, &sm, TRUE);
  2978.  
  2979.         }
  2980.  
  2981.         return NOERROR;
  2982. }
  2983.  
  2984. HRESULT _IFUNC BOlePart::AddLinkSourceData (IDataObject *pTarget)
  2985. {
  2986.         FORMATETC fe;
  2987.         STGMEDIUM stgMedium;
  2988.         LPMONIKER lpMoniker;
  2989.  
  2990.         if (!pLinkObject) {
  2991.  
  2992.                 // Get moniker from client site
  2993.                 //
  2994.                 LPOLECLIENTSITE cSite;
  2995.                 if (SUCCEEDED (pObjOuter->QueryInterfaceMain (IID_IOleClientSite, &(LPVOID)cSite))) {
  2996.                         cSite->GetMoniker (OLEGETMONIKER_TEMPFORUSER, OLEWHICHMK_OBJFULL, &lpMoniker);
  2997.                         cSite->Release();
  2998.                         if (!lpMoniker)
  2999.                                 return ResultFromScode (E_FAIL);
  3000.                 } else
  3001.                         return ResultFromScode (E_FAIL);
  3002.         }
  3003.         else {
  3004.                 // Get moniker from the link object itself
  3005.                 //
  3006.                 if (SUCCEEDED (pOleObject->GetMoniker(OLEGETMONIKER_TEMPFORUSER,
  3007.                         OLEWHICHMK_OBJFULL, &lpMoniker))) {
  3008.                 }
  3009.                 else
  3010.                         return ResultFromScode (E_FAIL);
  3011.         }
  3012.  
  3013.         // Create a memory based stream to write the moniker to
  3014.         //
  3015.         LPSTREAM lpStream;
  3016.         if (!SUCCEEDED (::CreateStreamOnHGlobal (NULL, TRUE, &lpStream))) {
  3017.                 lpMoniker->Release();
  3018.                 return ResultFromScode (E_FAIL);
  3019.         }
  3020.  
  3021.         // Write the moniker to the stream
  3022.         //
  3023.         if (!SUCCEEDED (OleSaveToStream (lpMoniker, lpStream))) {
  3024.                 lpStream->Release();
  3025.                 return ResultFromScode (E_FAIL);
  3026.         }
  3027.  
  3028.         // Write the class ID of the document to the stream as well
  3029.         //
  3030.         CLSID clsid;
  3031.         pOleObject->GetUserClassID (&clsid);
  3032.         WriteClassStm (lpStream, clsid);
  3033.  
  3034.         lpMoniker->Release();
  3035.  
  3036.         // Give this stream to the data source (which then owns it)
  3037.         //
  3038.         _fmemset (&fe, 0, sizeof (fe));
  3039.         fe.cfFormat = BOleDocument::oleLinkSrcClipFmt;
  3040.         fe.dwAspect = dwDrawAspect;
  3041.         fe.lindex = -1;
  3042.         fe.tymed = TYMED_ISTREAM;
  3043.         stgMedium.tymed = TYMED_ISTREAM;
  3044.         stgMedium.pstm = lpStream;
  3045.         stgMedium.pUnkForRelease = NULL;
  3046.         pTarget->SetData (&fe, &stgMedium, TRUE);
  3047.  
  3048.         // Set the object descriptor
  3049.         //
  3050.         stgMedium.tymed = TYMED_HGLOBAL;
  3051.         fe.cfFormat = BOleDocument::oleLinkSrcDescFmt;
  3052.         fe.tymed = TYMED_HGLOBAL;
  3053.         POINTL unused = {0,0};
  3054.         SIZEL unused2 = {0,0};
  3055.         stgMedium.hGlobal = OleStdGetObjectDescriptorDataFromOleObject(pOleObject,
  3056.                 NULL, dwDrawAspect, unused, &unused2);
  3057.         stgMedium.pUnkForRelease = NULL;
  3058.         pTarget->SetData (&fe, &stgMedium, TRUE);
  3059.  
  3060.         return NOERROR;
  3061. }
  3062.  
  3063. HRESULT _IFUNC BOlePart::AddSiteData (LPDATAOBJECT pTarget)
  3064. {
  3065.         // Ask the site if they have any data to add.
  3066.         //
  3067.         // Implementation note: this is a slightly quirky way to do this, but
  3068.         // we're not set up to change it at this point. Other ways it could work:
  3069.         //
  3070.         // 1. Use aggregation so the user calls IBService::Clip with the data
  3071.         //    provider supported on their site object. Then they would get to
  3072.         //    provide their formats first, and then call back to the data provier
  3073.         //    on BOlePart to add the cached formats. Although this seems OLE-like,
  3074.         //    abandoned this idea because the aggregation is tricky and our
  3075.         //    data format negotiation stuff is different enough from OLE2's to
  3076.         //    make it difficult to bottleneck the OLE2 cache.
  3077.         //
  3078.         // 2. Put a flag in BOlePart which would be set when we're in a CopyFrom-
  3079.         //    Original. Then our BOlePart's data provider implementation would
  3080.         //    know when to get the data of the real OLE object, and when to get
  3081.         //    it from the cache. Abandoned this idea because the idea of more
  3082.         //    weird state information isn't attractive.
  3083.         //
  3084.         // 3. Add a SetFormatData to IBPart or IBDataProvider which could do an
  3085.         //    IBDataObject::SetData on the cache directly. Abandoned this idea
  3086.         //    because it would be another stub method on the server side.
  3087.         //
  3088.  
  3089.         HRESULT hr = NOERROR;
  3090.         PIBDataProvider pProvider = NULL;
  3091.         hr = pSite->QueryInterface (IID_IBDataProvider, &(LPVOID) pProvider);
  3092.  
  3093.         // Should never happen because aggregation will always return the
  3094.         // data provider on us if the site doesn't support it.
  3095.         //
  3096.         if (hr != NOERROR)
  3097.                 return hr;
  3098.  
  3099.         if (pProvider != (PIBDataProvider)(IBPart*)this) {
  3100.                 UINT count = pProvider->CountFormats ();
  3101.  
  3102.                 HANDLE hData;
  3103.                 BOleFormat bf;
  3104.                 FORMATETC fe;
  3105.                 STGMEDIUM stm;
  3106.  
  3107.                 for (UINT i = 0; i < count; i++) {
  3108.  
  3109.                         // Get the formats the site wants to add
  3110.                         //
  3111.                         hr = pProvider->GetFormat (i, &bf);
  3112.                         if (hr == NOERROR) {
  3113.                                 hData = pProvider->GetFormatData (&bf);
  3114.  
  3115.                                 // Convert from BOleFormat to FORMATETC
  3116.                                 //
  3117.                                 if (hData) {
  3118.                                         fe.cfFormat = bf.fmtId;
  3119.                                         fe.ptd = NULL;
  3120.                                         fe.dwAspect = dwDrawAspect;
  3121.                                         fe.lindex = -1;
  3122.                                         switch (bf.fmtId) {
  3123.                                                 case CF_METAFILEPICT:
  3124.                                                         fe.tymed = TYMED_MFPICT;
  3125.                                                         break;
  3126.                                                 case CF_BITMAP:
  3127.                                                         fe.tymed = TYMED_GDI;
  3128.                                                         break;
  3129.                                                 default:
  3130.                                                         fe.tymed = TYMED_HGLOBAL;
  3131.                                         }
  3132.  
  3133.                                         // Only formats described by HGLOBALs are allowed here.
  3134.                                         // If we had this to do again, we'd just use FORMATETC
  3135.                                         //
  3136.                                         stm.tymed = fe.tymed;
  3137.                                         stm.hGlobal = hData;
  3138.                                         stm.pUnkForRelease = NULL;
  3139.                                 }
  3140.  
  3141.                                 // Set the FORMATETC and STGMEDIUM into the data cache
  3142.                                 //
  3143.                                 hr = pTarget->SetData (&fe, &stm, TRUE);
  3144.                         }
  3145.                 }
  3146.         }
  3147.  
  3148.         pProvider->Release();
  3149.         return hr;
  3150. }
  3151.  
  3152. // Link source not available
  3153. //
  3154. void _IFUNC BOlePart::HandleLinkError()
  3155. {
  3156.         HWND hWnd = pContainer->GetWindow();
  3157.         if (hWnd) {
  3158.  
  3159.                 // Need to retrieve the descriptive name for the container to make the caption
  3160.                 //
  3161.                 LPOLESTR pCaption = TEXT( "" );
  3162.                 HWND hTopWnd = GetTopWindow( hWnd );
  3163.                 if (OleUIPromptUser (IDD_LINKSOURCEUNAVAILABLE, hTopWnd, pCaption) == ID_PU_LINKS ){
  3164.  
  3165.                         // Since a link is unavailable, we ask the user whether they
  3166.                         // want to go to the links dialog box. If they do, we invoke it
  3167.                         // through the IBOverrideBrowseLinks interface. The reason we
  3168.                         // don't call it directly on the BOleDocument is so that a
  3169.                         // container app (WPWin) can use their own dialog in this case.
  3170.                         //
  3171.                         // In general, it isn't nice for Bolero to call our own dialogs
  3172.                         // because users are supposed to be able to use their own.
  3173.                         //
  3174.                         PIBOverrideBrowseLinks pOBL = NULL;
  3175.                         HRESULT qiHr = pDoc->QueryInterface (IID_IBOverrideBrowseLinks, &(LPVOID)pOBL);
  3176.                         if (SUCCEEDED(qiHr)) { // should never fail since OBL is supported on the doc
  3177.                                 pOBL->BrowseLinks();
  3178.                                 pOBL->Release();
  3179.                         }
  3180.                 }
  3181.         }
  3182. }
  3183.  
  3184.  
  3185.  
  3186.