| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277 |
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- #include "stdafx.h"
- #ifdef AFX_OLE_SEG
- #pragma code_seg(AFX_OLE_SEG)
- #endif
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #define new DEBUG_NEW
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem - Container view of IOleObject and related interfaces
- COleClientItem::COleClientItem(COleDocument* pContainerDoc)
- {
- if (pContainerDoc != NULL)
- ASSERT_VALID(pContainerDoc);
- // initialize OLE client side view of IOleObject
- m_lpObject = NULL;
- m_lpViewObject = NULL;
- m_dwConnection = 0;
- m_lpStorage = NULL;
- m_lpLockBytes = NULL;
- m_scLast = S_OK;
- m_pView = NULL;
- m_pInPlaceFrame = NULL;
- m_pInPlaceDoc = NULL;
- m_nItemState = emptyState; // initially empty until OleLoad, OleCreate
- m_bMoniker = FALSE;
- m_nDrawAspect = DVASPECT_CONTENT; // default draw aspect
- m_dwItemNumber = 0;
- m_bLinkUnavail = FALSE; // set to TRUE on failed DoVerb, or in links dialog
- m_nItemType = OT_UNKNOWN; // type unknown so far
- m_hWndServer = NULL;
- m_bClosing = FALSE; // COleClientItem::Close in process
- m_bLocked = FALSE; // need CoLockObjectExternal(..., FALSE, ...)
- // initialize compound file support
- m_lpNewStorage = NULL;
- m_bNeedCommit = FALSE;
- if (pContainerDoc != NULL)
- pContainerDoc->AddItem(this);
- ASSERT(m_pDocument == pContainerDoc);
- ASSERT_VALID(this);
- AfxOleLockApp();
- }
- COleClientItem::~COleClientItem()
- {
- ASSERT_VALID(this);
- // release any references we may have to other objects
- Release();
- // only remove it from the associated document if it hasn't been detached
- // from the document already!
- if (m_pDocument != NULL)
- m_pDocument->RemoveItem(this);
- // make sure all outside connections are disconnected
- ExternalDisconnect();
- AfxOleUnlockApp();
- }
- void COleClientItem::Delete(BOOL bAutoDelete)
- {
- USES_CONVERSION;
- ASSERT_VALID(this);
- Release(); // first close it
- COleDocument* pDoc = GetDocument();
- if (pDoc != NULL && pDoc->m_bCompoundFile)
- {
- // cleanup docfile storage first
- COleDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- if (pDoc->m_lpRootStg != NULL)
- {
- // get item name
- TCHAR szItemName[OLE_MAXITEMNAME];
- GetItemName(szItemName);
- // attempt to remove it from the storage, ignore errors
- pDoc->m_lpRootStg->DestroyElement(T2COLE(szItemName));
- }
- }
- if (bAutoDelete)
- {
- // remove item from document
- if (pDoc != NULL)
- pDoc->RemoveItem(this);
- InternalRelease(); // remove the item from memory
- }
- }
- void COleClientItem::Release(OLECLOSE dwCloseOption)
- {
- ASSERT_VALID(this);
- m_scLast = S_OK;
- // cleanup view advise
- if (m_lpViewObject != NULL)
- {
- DWORD dwAspect;
- IAdviseSink* pAdviseSink;
- pAdviseSink = NULL;
- VERIFY(m_lpViewObject->GetAdvise(&dwAspect, NULL, &pAdviseSink) == S_OK);
- if( pAdviseSink != NULL )
- {
- RELEASE( pAdviseSink );
- }
- VERIFY(m_lpViewObject->SetAdvise(dwAspect, 0, NULL) == S_OK);
- RELEASE(m_lpViewObject);
- }
- // cleanup the OLE object itself
- if (m_lpObject != NULL)
- {
- // cleanup object advise
- if (m_dwConnection != 0)
- {
- VERIFY(m_lpObject->Unadvise(m_dwConnection) == S_OK);
- m_dwConnection = 0;
- }
- // close object and save (except now when called from destructor)
- // (NOTE: errors are _not_ reported as an exception)
- m_scLast = m_lpObject->Close(dwCloseOption);
- RELEASE(m_lpObject);
- }
- // cleanup storage related data
- RELEASE(m_lpStorage);
- RELEASE(m_lpLockBytes);
- // cleanup in-place editing data
- if (m_pInPlaceFrame != NULL)
- {
- m_pInPlaceFrame->InternalRelease();
- m_pInPlaceFrame = NULL;
- if (m_pInPlaceDoc != NULL)
- {
- m_pInPlaceDoc->InternalRelease();
- m_pInPlaceDoc = NULL;
- }
- }
- ASSERT(m_pInPlaceFrame == NULL);
- ASSERT(m_pInPlaceDoc == NULL);
- }
- void COleClientItem::Close(OLECLOSE dwCloseOption)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- // gaurd against re-entry
- if (m_bClosing)
- return;
- m_bClosing = TRUE;
- // attempt to close the object
- m_scLast = m_lpObject->Close(dwCloseOption);
- // remove external lock placed on item during in-place activation
- if (m_bLocked)
- {
- OleLockRunning(m_lpObject, FALSE, TRUE);
- m_bLocked = FALSE;
- }
- // handle failure cases -- COleClientItem::Close can be used to
- // robustly handle a server crashing (ie. something unexpected happens,
- // we'll call COleClientItem::Close to attempt safe shutdown)
- if (GetItemState() != loadedState)
- {
- // We'll call COleClientItem::Close anywhere a catastrophe
- // happens inside of other portions of COleClientItem. We must
- // completely exit from any in-place/open state.
- // force transition from activeUIState to activeState
- if (GetItemState() == activeUIState)
- OnDeactivateUI(FALSE);
- // force transition from activeState to loadedState
- if (GetItemState() == activeState)
- OnDeactivate();
- if (m_nItemState != loadedState)
- {
- // in case of extreme failure, force loadedState
- OnChange(OLE_CHANGED_STATE, (DWORD)loadedState);
- m_nItemState = loadedState; // force it to loaded state
- }
- }
- m_bClosing = FALSE; // now safe for further close calls
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem name management
- DWORD COleClientItem::GetNewItemNumber()
- {
- ASSERT_VALID(this);
- COleDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- DWORD dwNextItemNumber = pDoc->m_dwNextItemNumber;
- for (;;)
- {
- // make sure that m_dwNextItemNumber is not used in another item first
- POSITION pos = pDoc->GetStartPosition();
- COleClientItem* pItem;
- while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
- {
- if (pItem->m_dwItemNumber == dwNextItemNumber)
- break;
- }
- if (pItem == NULL)
- break; // no item using m_dwNextItemNumber
- // m_dwNextItemNumber is in use, bump to next one!
- ++dwNextItemNumber;
- }
- pDoc->m_dwNextItemNumber = dwNextItemNumber + 1;
- return dwNextItemNumber;
- }
- void COleClientItem::GetItemName(LPTSTR lpszItemName) const
- {
- ASSERT_VALID(this);
- ASSERT(lpszItemName != NULL);
- wsprintf(lpszItemName, _T("Embedding %lu"), m_dwItemNumber);
- ASSERT(lstrlen(lpszItemName) < OLE_MAXITEMNAME);
- }
- // extracts icon resource ID and path name from registry "file.exe,35" format
- static void AfxGetIconInfo(LPCTSTR lpszRegInfo, LPTSTR lpszImagePath,
- UINT& nIndex)
- {
- LPTSTR pstrTarget = lpszImagePath;
- LPCTSTR pstrSource = lpszRegInfo;
- while (*pstrSource != ',' && *pstrSource != '\0')
- {
- *pstrTarget = *pstrSource;
- pstrTarget = _tcsinc(pstrTarget);
- pstrSource = _tcsinc(pstrSource);
- }
- *pstrTarget = '\0';
- // extract the index
- if (*pstrSource != '\0')
- {
- LPCTSTR pstrIndex = _tcsinc(pstrSource);
- nIndex = (UINT) _ttol(pstrIndex);
- }
- else
- nIndex = 0;
- }
- HICON COleClientItem::GetIconFromRegistry() const
- {
- CLSID clsid;
- GetClassID(&clsid);
- if (clsid == CLSID_NULL)
- return NULL;
- return GetIconFromRegistry(clsid);
- }
- HICON COleClientItem::GetIconFromRegistry(CLSID& clsid)
- {
- // This function will extract the icon registered as the DefaultIcon
- // for the server referred to by clsid. We get the ProgID for the server
- // and then extract \\hkcr\progid\DefaultIcon. If that doesn't exist, we
- // get a default icon from \\hkcr\DocShortcut\DefaultIcon and if that fails
- // we just return 0.
- USES_CONVERSION;
- HICON hIcon = NULL;
- HRESULT hr;
- OLECHAR *szCLSID;
- DWORD dwType = 0;
- TCHAR szName[MAX_PATH+1];
- TCHAR szPathName[MAX_PATH+1];
- HKEY hkeyObj;
- HKEY hkeyDefIcon;
- HKEY hkeyCLSID;
- UINT nIndex;
- hr = ::StringFromCLSID(clsid, &szCLSID);
- if (!SUCCEEDED(hr))
- return NULL;
- // first, try for the real icon
- if (RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("clsid"), 0, KEY_READ, &hkeyCLSID) == ERROR_SUCCESS)
- {
- if (RegOpenKeyEx(hkeyCLSID, OLE2T(szCLSID), 0, KEY_READ, &hkeyObj) == ERROR_SUCCESS)
- {
- if (RegOpenKeyEx(hkeyObj, _T("DefaultIcon"), 0, KEY_READ, &hkeyDefIcon) == ERROR_SUCCESS)
- {
- DWORD dwCount;
- dwCount = sizeof(szName);
- if (RegQueryValueEx(hkeyDefIcon, NULL, NULL, &dwType, (BYTE*) szName, &dwCount) == ERROR_SUCCESS)
- {
- AfxGetIconInfo(szName, szPathName, nIndex);
- // Load the icon
- hIcon = ::ExtractIcon(AfxGetApp()->m_hInstance, szPathName, nIndex);
- // ExtractIcon() failure case means NULL return
- if (int(hIcon) == 1)
- hIcon = NULL;
- }
- RegCloseKey(hkeyDefIcon);
- }
- RegCloseKey(hkeyObj);
- }
- RegCloseKey(hkeyCLSID);
- }
- // if we didn't get the real icon, try the default icon
- if (hIcon == NULL)
- {
- if (RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("DocShortcut"), 0, KEY_READ,&hkeyObj) == ERROR_SUCCESS)
- {
- if (RegOpenKeyEx(hkeyObj, _T("DefaultIcon"), 0, KEY_READ, &hkeyDefIcon) == ERROR_SUCCESS)
- {
- DWORD dwCount;
- dwCount = sizeof(szName);
- if (RegQueryValueEx(hkeyDefIcon, NULL, NULL, &dwType, (BYTE*) szName, &dwCount) == ERROR_SUCCESS)
- {
- AfxGetIconInfo(szName, szPathName, nIndex);
- // Load the icon
- hIcon = ::ExtractIcon(AfxGetApp()->m_hInstance, szPathName, nIndex);
- // ExtractIcon() failure case means NULL return
- if (int(hIcon) == 1)
- hIcon = NULL;
- }
- RegCloseKey(hkeyDefIcon);
- }
- RegCloseKey(hkeyObj);
- }
- }
- ::CoTaskMemFree(szCLSID);
- return hIcon;
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem creation helpers
- void COleClientItem::UpdateItemType()
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- // check for linked object
- LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
- if (lpOleLink != NULL)
- {
- lpOleLink->Release();
- m_nItemType = OT_LINK;
- return;
- }
- // check for static object
- DWORD dwStatus;
- if (m_lpObject->GetMiscStatus(DVASPECT_CONTENT, &dwStatus) == S_OK
- && (dwStatus & OLEMISC_STATIC) == 0)
- {
- m_nItemType = OT_EMBEDDED;
- return;
- }
- // not not link, not embedding -- must be static
- m_nItemType = OT_STATIC;
- }
- BOOL COleClientItem::FinishCreate(SCODE sc)
- {
- USES_CONVERSION;
- ASSERT_VALID(this);
- ASSERT(m_pView == NULL);
- TRY
- {
- // m_lpObject is currently an IUnknown, convert to IOleObject
- if (m_lpObject != NULL)
- {
- LPUNKNOWN lpUnk = m_lpObject;
- m_lpObject = QUERYINTERFACE(lpUnk, IOleObject);
- lpUnk->Release();
- if (m_lpObject == NULL)
- AfxThrowOleException(E_OUTOFMEMORY);
- }
- // check return code from create function
- CheckGeneral(sc);
- UpdateItemType();
- // cache the IViewObject interface
- m_lpViewObject = QUERYINTERFACE(m_lpObject, IViewObject2);
- if (m_lpViewObject == NULL)
- CheckGeneral(E_NOINTERFACE);
- ASSERT(m_lpViewObject != NULL);
- if (GetType() != OT_STATIC)
- {
- // setup for advises; we assume that OLE cleans them up properly
- LPADVISESINK lpAdviseSink =
- (LPADVISESINK)GetInterface(&IID_IAdviseSink);
- ASSERT(lpAdviseSink != NULL);
- CheckGeneral(m_lpObject->Advise(lpAdviseSink, &m_dwConnection));
- ASSERT(m_dwConnection != 0);
- // set up view advise
- VERIFY(m_lpViewObject->SetAdvise(DVASPECT_CONTENT, 0, lpAdviseSink)
- == S_OK);
- // the server shows these in its user-interface
- // (as document title and in File Exit menu)
- m_lpObject->SetHostNames(T2COLE(AfxGetAppName()),
- T2COLE(m_pDocument->GetTitle()));
- }
- // all items are "contained" -- this makes our reference to this object
- // weak -- which is needed for links to embedding silent update.
- OleSetContainedObject(m_lpObject, TRUE);
- // considered loaded at this point
- m_nItemState = loadedState;
- }
- CATCH_ALL(e)
- {
- Release(); // release the object just in case
- ASSERT_VALID(this);
- DELETE_EXCEPTION(e);
- return FALSE;
- }
- END_CATCH_ALL
- // set state to loaded
- ASSERT(m_nItemState != emptyState);
- // otherwise no errors, return success!
- ASSERT_VALID(this);
- return TRUE;
- }
- //////////////////////////////////////////////////////////////////////////////
- // COleClientItem create API variants
- BOOL COleClientItem::CreateFromClipboard(
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
- // get clipboard contents
- COleDataObject dataObject;
- if (!dataObject.AttachClipboard())
- return FALSE;
- // create from IDataObject
- BOOL bResult = CreateFromData(&dataObject, render, cfFormat, lpFormatEtc);
- ASSERT_VALID(this);
- return bResult;
- }
- BOOL COleClientItem::CreateLinkFromClipboard(
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
- // get clipboard contents
- COleDataObject dataObject;
- if (!dataObject.AttachClipboard())
- return FALSE;
- // create from IDataObject
- BOOL bResult = CreateLinkFromData(&dataObject, render, cfFormat, lpFormatEtc);
- ASSERT_VALID(this);
- return bResult;
- }
- BOOL COleClientItem::CreateStaticFromClipboard(
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
- // get clipboard contents
- COleDataObject dataObject;
- if (!dataObject.AttachClipboard())
- return FALSE;
- // create from IDataObject
- BOOL bResult = CreateStaticFromData(&dataObject, render, cfFormat,
- lpFormatEtc);
- ASSERT_VALID(this);
- return bResult;
- }
- // Creation from IDataObject (used for drag-drop)
- BOOL COleClientItem::CreateFromData(COleDataObject* pDataObject,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
- // attempt to create the object
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- LPDATAOBJECT lpDataObject = pDataObject->GetIDataObject(FALSE);
- SCODE sc = ::OleCreateFromData(lpDataObject, IID_IUnknown, render,
- lpFormatEtc, lpClientSite, m_lpStorage, (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
- ASSERT_VALID(this);
- return bResult;
- }
- BOOL COleClientItem::CreateLinkFromData(COleDataObject* pDataObject,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
- // attempt to create the link
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- LPDATAOBJECT lpDataObject = pDataObject->GetIDataObject(FALSE);
- SCODE sc = ::OleCreateLinkFromData(lpDataObject, IID_IUnknown,
- render, lpFormatEtc, lpClientSite, m_lpStorage, (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
- ASSERT_VALID(this);
- return bResult;
- }
- BOOL COleClientItem::CreateStaticFromData(COleDataObject* pDataObject,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
- // attempt to create the link
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- LPDATAOBJECT lpDataObject = pDataObject->GetIDataObject(FALSE);
- SCODE sc = ::OleCreateStaticFromData(lpDataObject, IID_IUnknown,
- render, lpFormatEtc, lpClientSite, m_lpStorage, (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
- ASSERT_VALID(this);
- return bResult;
- }
- // Creation from files (in OLE 1.0, the user did this through packager)
- BOOL COleClientItem::CreateFromFile(LPCTSTR lpszFileName, REFCLSID clsid,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- USES_CONVERSION;
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
- // attempt to create the object
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- SCODE sc = ::OleCreateFromFile(clsid, T2COLE(lpszFileName),
- IID_IUnknown, render, lpFormatEtc, lpClientSite, m_lpStorage,
- (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
- ASSERT_VALID(this);
- return bResult;
- }
- BOOL COleClientItem::CreateLinkFromFile(LPCTSTR lpszFileName,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- USES_CONVERSION;
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
- // attempt to create the link
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- SCODE sc = ::OleCreateLinkToFile(T2COLE(lpszFileName),
- IID_IUnknown, render, lpFormatEtc, lpClientSite, m_lpStorage,
- (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
- ASSERT_VALID(this);
- return bResult;
- }
- // create from class name (for insert item dialog)
- BOOL COleClientItem::CreateNewItem(REFCLSID clsid,
- OLERENDER render, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT(m_pDocument != NULL);
- ASSERT(lpFormatEtc == NULL ||
- AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
- // get storage for the object via virtual function call
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
- // fill in FORMATETC struct
- FORMATETC formatEtc;
- lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
- // attempt to create the object
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- SCODE sc = ::OleCreate(clsid, IID_IUnknown,
- render, lpFormatEtc, lpClientSite, m_lpStorage, (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
- ASSERT_VALID(this);
- return bResult;
- }
- /////////////////////////////////////////////////////////////////////////////
- // More advanced creation
- BOOL COleClientItem::CreateCloneFrom(const COleClientItem* pSrcItem)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject == NULL); // one time only
- ASSERT_VALID(pSrcItem);
- ASSERT(m_pDocument != NULL);
- // create storage for the item
- m_dwItemNumber = GetNewItemNumber();
- GetItemStorage();
- ASSERT(m_lpStorage != NULL);
- // save the object first
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(pSrcItem->m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- SCODE sc = ::OleSave(lpPersistStorage, m_lpStorage, FALSE);
- lpPersistStorage->SaveCompleted(NULL);
- lpPersistStorage->Release();
- if (sc != S_OK)
- {
- // failed the save, do not attempt to create clone
- m_scLast = sc;
- return FALSE;
- }
- // get information on the view advise type
- ASSERT(pSrcItem->m_lpViewObject != NULL);
- DWORD dwAspect;
- IAdviseSink* pAdviseSink;
- pAdviseSink = NULL;
- VERIFY(pSrcItem->m_lpViewObject->GetAdvise(&dwAspect, NULL, &pAdviseSink) ==
- S_OK);
- if( pAdviseSink != NULL )
- {
- RELEASE(pAdviseSink);
- }
- // then load the new object from the new storage
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- sc = ::OleLoad(m_lpStorage, IID_IUnknown,
- lpClientSite, (LPLP)&m_lpObject);
- BOOL bResult = FinishCreate(sc);
- ASSERT_VALID(this);
- return bResult;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Storage for COleClientItem objects (memory and compound files)
- BOOL COleClientItem::IsModified() const
- {
- SCODE sc;
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- // get IPersistStorage interface, and call IsDirty
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- if( lpPersistStorage != NULL )
- {
- sc = lpPersistStorage->IsDirty();
- lpPersistStorage->Release();
- }
- else
- {
- LPPERSISTSTREAMINIT lpPersistStreamInit;
- lpPersistStreamInit = QUERYINTERFACE( m_lpObject, IPersistStreamInit );
- if( lpPersistStreamInit != NULL )
- {
- sc = lpPersistStreamInit->IsDirty();
- lpPersistStreamInit->Release();
- }
- else
- {
- LPPERSISTSTREAM lpPersistStream;
- lpPersistStream = QUERYINTERFACE( m_lpObject, IPersistStream );
- if( lpPersistStream != NULL )
- {
- sc = lpPersistStream->IsDirty();
- lpPersistStream->Release();
- }
- else
- {
- sc = E_NOINTERFACE;
- }
- }
- }
- // S_OK == S_TRUE, therefore object dirty!
- return sc == S_OK || FAILED(sc);
- }
- void COleClientItem::GetItemStorageFlat()
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStorage == NULL);
- ASSERT(m_lpLockBytes == NULL);
- SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &m_lpLockBytes);
- if (sc != S_OK)
- AfxThrowOleException(sc);
- ASSERT(m_lpLockBytes != NULL);
- sc = ::StgCreateDocfileOnILockBytes(m_lpLockBytes,
- STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &m_lpStorage);
- if (sc != S_OK)
- {
- VERIFY(m_lpLockBytes->Release() == 0);
- m_lpLockBytes = NULL;
- AfxThrowOleException(sc);
- }
- ASSERT(m_lpStorage != NULL);
- ASSERT_VALID(this);
- }
- void COleClientItem::ReadItemFlat(CArchive& ar)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStorage == NULL);
- ASSERT(m_lpLockBytes == NULL);
- // read number of bytes in the ILockBytes
- DWORD dwBytes;
- ar >> dwBytes;
- // allocate enough memory to read entire block
- HGLOBAL hStorage = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, dwBytes);
- if (hStorage == NULL)
- AfxThrowMemoryException();
- LPVOID lpBuf = ::GlobalLock(hStorage);
- ASSERT(lpBuf != NULL);
- DWORD dwBytesRead = ar.Read(lpBuf, dwBytes);
- ::GlobalUnlock(hStorage);
- // throw exception in case of partial object
- if (dwBytesRead != dwBytes)
- {
- ::GlobalFree(hStorage);
- AfxThrowArchiveException(CArchiveException::endOfFile);
- }
- SCODE sc = CreateILockBytesOnHGlobal(hStorage, TRUE, &m_lpLockBytes);
- if (sc != S_OK)
- {
- ::GlobalFree(hStorage);
- AfxThrowOleException(sc);
- }
- ASSERT(m_lpLockBytes != NULL);
- ASSERT(::StgIsStorageILockBytes(m_lpLockBytes) == S_OK);
- sc = ::StgOpenStorageOnILockBytes(m_lpLockBytes, NULL,
- STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &m_lpStorage);
- if (sc != S_OK)
- {
- VERIFY(m_lpLockBytes->Release() == 0);
- m_lpLockBytes = NULL;
- // ILockBytes::Release will GlobalFree the hStorage
- AfxThrowOleException(sc);
- }
- // attempt to load the object from the storage
- LPUNKNOWN lpUnk = NULL;
- sc = ::OleLoad(m_lpStorage, IID_IUnknown, GetClientSite(),
- (LPLP)&lpUnk);
- CheckGeneral(sc);
- ASSERT(lpUnk != NULL);
- m_lpObject = QUERYINTERFACE(lpUnk, IOleObject);
- lpUnk->Release();
- if (m_lpObject == NULL)
- AfxThrowOleException(E_OUTOFMEMORY);
- ASSERT_VALID(this);
- }
- void COleClientItem::WriteItemFlat(CArchive& ar)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStorage != NULL);
- ASSERT(m_lpLockBytes != NULL);
- // save the OLE object to its storage first
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- SCODE sc;
- if (GetDocument()->m_bCompoundFile || lpPersistStorage->IsDirty() == S_OK)
- {
- sc = ::OleSave(lpPersistStorage, m_lpStorage,
- !GetDocument()->m_bCompoundFile);
- lpPersistStorage->SaveCompleted(NULL);
- }
- lpPersistStorage->Release();
- m_lpStorage->Commit(STGC_OVERWRITE);
- ASSERT(::StgIsStorageILockBytes(m_lpLockBytes) == S_OK);
- // attempt to get the handle to the global memory
- HGLOBAL hStorage;
- sc = ::GetHGlobalFromILockBytes(m_lpLockBytes, &hStorage);
- if (sc != S_OK)
- AfxThrowOleException(sc);
- // first write a byte count
- STATSTG statstg;
- sc = m_lpLockBytes->Stat(&statstg, STATFLAG_NONAME);
- if (sc != S_OK)
- AfxThrowOleException(sc);
- ASSERT(statstg.cbSize.HighPart == 0); // don't support >4GB objects
- DWORD dwBytes = statstg.cbSize.LowPart;
- ar << dwBytes;
- // write the contents of the block
- LPVOID lpBuf = GlobalLock(hStorage);
- ASSERT(lpBuf != NULL);
- ar.Write(lpBuf, (UINT)dwBytes);
- ::GlobalUnlock(hStorage);
- }
- void COleClientItem::GetItemStorageCompound()
- {
- USES_CONVERSION;
- COleDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- ASSERT(pDoc->m_bCompoundFile);
- if (pDoc->m_lpRootStg == NULL)
- {
- ASSERT(pDoc->m_bEmbedded);
- pDoc->m_bEmbedded = FALSE;
- if (!pDoc->OnNewDocument())
- {
- TRACE0("Warning OnNewDocument failed during COleClientItem::CreateXXXX\n");
- AfxThrowMemoryException();
- }
- }
- ASSERT(pDoc->m_lpRootStg != NULL);
- // get item name
- TCHAR szItemName[OLE_MAXITEMNAME];
- GetItemName(szItemName);
- // create storage for this item
- LPSTORAGE lpStorage;
- SCODE sc = pDoc->m_lpRootStg->CreateStorage(T2COLE(szItemName),
- STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE,
- 0, 0, &lpStorage);
- if (sc != S_OK)
- {
- TRACE1("Warning: unable to create child storage %s.\n", szItemName);
- // upon failure throw file exception (item will be cleaned up)
- AfxThrowOleException(sc);
- }
- ASSERT(lpStorage != NULL);
- // everything should have worked
- m_lpStorage = lpStorage;
- ASSERT(m_lpStorage != NULL);
- }
- void COleClientItem::ReadItemCompound(CArchive& ar)
- {
- USES_CONVERSION;
- COleDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- ASSERT(pDoc->m_lpRootStg != NULL);
- ASSERT(pDoc->m_bCompoundFile);
- ASSERT(m_lpStorage == NULL);
- ASSERT(m_lpLockBytes == NULL);
- if (ar.m_bForceFlat)
- {
- ReadItemFlat(ar);
- RELEASE(m_lpStorage);
- RELEASE(m_lpLockBytes);
- // change the number to something definitely unique
- m_dwItemNumber = GetNewItemNumber();
- // create new storage
- GetItemStorageCompound();
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- SCODE sc = ::OleSave(lpPersistStorage, m_lpStorage, FALSE);
- if (FAILED(sc))
- {
- lpPersistStorage->Release();
- CheckGeneral(sc);
- }
- VERIFY(lpPersistStorage->SaveCompleted(m_lpStorage) == S_OK);
- lpPersistStorage->Release();
- }
- else
- {
- // get item name
- TCHAR szItemName[OLE_MAXITEMNAME];
- GetItemName(szItemName);
- // open storage for this item
- LPSTORAGE lpStorage;
- SCODE sc = pDoc->m_lpRootStg->OpenStorage(T2COLE(szItemName), NULL,
- STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE,
- 0, 0, &lpStorage);
- if (sc != S_OK)
- {
- TRACE1("Warning: unable to open child storage %s.\n", szItemName);
- // upon failure throw file exception (item will be cleaned up)
- AfxThrowOleException(sc);
- }
- ASSERT(lpStorage != NULL);
- // remember the storage
- m_lpStorage = lpStorage;
- ASSERT(m_lpStorage != NULL);
- // attempt to load the object from the storage
- LPUNKNOWN lpUnk = NULL;
- sc = ::OleLoad(m_lpStorage, IID_IUnknown, GetClientSite(),
- (LPLP)&lpUnk);
- CheckGeneral(sc);
- // get IOleObject interface for the newly loaded object
- ASSERT(lpUnk != NULL);
- m_lpObject = QUERYINTERFACE(lpUnk, IOleObject);
- lpUnk->Release();
- if (m_lpObject == NULL)
- AfxThrowOleException(E_OUTOFMEMORY);
- }
- }
- void COleClientItem::WriteItemCompound(CArchive& ar)
- {
- USES_CONVERSION;
- COleDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- ASSERT(pDoc->m_lpRootStg != NULL);
- ASSERT(pDoc->m_bCompoundFile);
- ASSERT(m_lpNewStorage == NULL);
- if (ar.m_bForceFlat)
- {
- LPSTORAGE pTempStorage = m_lpStorage;
- LPLOCKBYTES pTempLockBytes = m_lpLockBytes;
- m_lpStorage = NULL;
- m_lpLockBytes = NULL;
- GetItemStorageFlat();
- WriteItemFlat(ar);
- RELEASE(m_lpStorage);
- RELEASE(m_lpLockBytes);
- m_lpStorage = pTempStorage;
- m_lpLockBytes = pTempLockBytes;
- return;
- }
- // get item name
- TCHAR szItemName[OLE_MAXITEMNAME];
- GetItemName(szItemName);
- // determine destination storage
- ASSERT(m_lpStorage != NULL);
- LPSTORAGE lpStorage = m_lpStorage;
- if (!pDoc->m_bSameAsLoad)
- {
- // need to create new storage for this item
- SCODE sc = pDoc->m_lpRootStg->CreateStorage(T2COLE(szItemName),
- STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE,
- 0, 0, &lpStorage);
- if (sc != S_OK)
- {
- TRACE1("Warning: unable to create child storage %s.\n",
- szItemName);
- AfxThrowOleException(sc);
- }
- // remember the storage for CommitItem stage
- m_lpNewStorage = lpStorage;
- m_bNeedCommit = TRUE;
- }
- ASSERT(lpStorage != NULL);
- // save dirty object
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- SCODE sc = S_OK;
- if (!pDoc->m_bSameAsLoad || lpPersistStorage->IsDirty() == S_OK)
- {
- // call OleSave now and IPersistStorage::SaveCompleted later
- sc = ::OleSave(lpPersistStorage, lpStorage, pDoc->m_bSameAsLoad);
- }
- lpPersistStorage->Release();
- // if it fails, abort the save
- if (FAILED(sc))
- AfxThrowOleException(sc);
- // now will need to call CommitItem for this item
- m_bNeedCommit = TRUE;
- lpStorage->Commit(STGC_ONLYIFCURRENT);
- }
- void COleClientItem::GetItemStorage()
- {
- if (GetDocument()->m_bCompoundFile)
- GetItemStorageCompound();
- else
- GetItemStorageFlat();
- }
- void COleClientItem::ReadItem(CArchive& ar)
- {
- if (GetDocument()->m_bCompoundFile)
- ReadItemCompound(ar);
- else
- ReadItemFlat(ar);
- }
- void COleClientItem::WriteItem(CArchive& ar)
- {
- if (GetDocument()->m_bCompoundFile)
- WriteItemCompound(ar);
- else
- WriteItemFlat(ar);
- }
- void COleClientItem::CommitItem(BOOL bSuccess)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- if (!m_bNeedCommit)
- return;
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- // forget about new storage if save failed along the way...
- if (m_lpNewStorage != NULL && !bSuccess)
- RELEASE(m_lpNewStorage);
- // let the object remember the new storage
- VERIFY(lpPersistStorage->SaveCompleted(m_lpNewStorage) == S_OK);
- lpPersistStorage->Release();
- // determine/remember new storage
- if (m_lpNewStorage != NULL)
- {
- m_lpStorage->Release();
- m_lpStorage = m_lpNewStorage;
- m_lpNewStorage = NULL;
- }
- m_bNeedCommit = FALSE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem serialization
- void COleClientItem::Serialize(CArchive& ar)
- {
- ASSERT_VALID(this);
- CDocItem::Serialize(ar);
- ASSERT(m_pDocument != NULL); // must 'SetDocument' first
- if (ar.IsStoring())
- {
- ASSERT(m_lpObject != NULL);
- // first, save the type flag (this is used for versioning)
- ar << (DWORD)OT_OLE2;
- ar << m_dwItemNumber; // save the item number
- // write the view advise type to storage
- ASSERT(m_lpViewObject != NULL);
- DWORD dwAspect;
- IAdviseSink* pAdviseSink;
- pAdviseSink = NULL;
- VERIFY(m_lpViewObject->GetAdvise(&dwAspect, NULL, &pAdviseSink) == S_OK);
- if( pAdviseSink != NULL )
- {
- RELEASE(pAdviseSink);
- }
- ar << dwAspect; // save the display aspect
- // write flag indicating whether to create moniker upon load
- ar << (WORD)m_bMoniker;
- // save current default display aspect
- ar << (DWORD)m_nDrawAspect;
- // save object to storage (calls OleSave)
- WriteItem(ar);
- }
- else
- {
- ASSERT(m_lpObject == NULL);
- // first, get the type flag (for OLE 1.0 compatible reading)
- DWORD dwType;
- ar >> dwType;
- if (dwType != OT_OLE2)
- AfxThrowArchiveException(CArchiveException::generic);
- ar >> m_dwItemNumber; // get the item number
- DWORD dwAspect; // read the display aspect (aspects that are cached)
- ar >> dwAspect;
- WORD bMoniker; // see if we should create & set the moniker
- ar >> bMoniker;
- DWORD nDrawAspect; // read the default display aspect
- ar >> nDrawAspect;
- m_nDrawAspect = (DVASPECT)nDrawAspect;
- // read the OLE object from storage (calls OleLoad)
- ReadItem(ar);
- // finish OLE object creation process, setup advises, etc.
- if (!FinishCreate(S_OK))
- AfxThrowArchiveException(CArchiveException::generic);
- if (bMoniker)
- {
- // force moniker creation by calling GetMoniker
- LPMONIKER lpMoniker;
- if (GetClientSite()->GetMoniker(OLEGETMONIKER_FORCEASSIGN,
- OLEWHICHMK_OBJREL, &lpMoniker) == S_OK)
- {
- ASSERT(lpMoniker != NULL);
- lpMoniker->Release();
- ASSERT(m_bMoniker); // moniker should have been assigned
- }
- }
- // fix up the document's m_dwNextItemNumber
- if (m_dwItemNumber >= GetDocument()->m_dwNextItemNumber)
- GetDocument()->m_dwNextItemNumber = m_dwItemNumber + 1;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // default callback implementation
- void COleClientItem::OnChange(OLE_NOTIFICATION nCode, DWORD /*dwParam*/)
- {
- ASSERT_VALID(this);
- switch (nCode)
- {
- case OLE_CLOSED:
- break; // no default implementation
- case OLE_CHANGED:
- case OLE_SAVED:
- ASSERT(m_pDocument != NULL);
- m_pDocument->SetModifiedFlag();
- break;
- case OLE_CHANGED_STATE:
- case OLE_CHANGED_ASPECT:
- break; // no default implementation
- default:
- ASSERT(FALSE);
- }
- ASSERT_VALID(this);
- }
- void COleClientItem::OnDataChange(
- LPFORMATETC /*lpFormatEtc*/, LPSTGMEDIUM /*lpStgMedium*/)
- {
- ASSERT(FALSE); // derivative must override -- must not call base class
- }
- void COleClientItem::OnGetItemPosition(CRect& /*rPosition*/)
- {
- // default does nothing
- }
- void COleClientItem::OnGetClipRect(CRect& rClipRect)
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(&rClipRect, sizeof(RECT)));
- // default clips rectClip to client area of the active view
- ASSERT_VALID(m_pView);
- m_pView->GetClientRect(&rClipRect);
- }
- void COleClientItem::OnShowItem()
- {
- ASSERT_VALID(this);
- CDocument* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- // attempt to use m_pView set during activation
- CView* pView = m_pView;
- if (pView == NULL)
- {
- // otherwise, find the first view of this document
- POSITION pos = pDoc->GetFirstViewPosition();
- if (pos == NULL || (pView = pDoc->GetNextView(pos)) == NULL)
- return;
- }
- CFrameWnd* pFrameWnd = pView->GetParentFrame();
- if (pFrameWnd != NULL)
- {
- // activate frame holding view
- pFrameWnd->ActivateFrame();
- pFrameWnd->OnUpdateFrameTitle(TRUE);
- // activate app frame if necessary
- pFrameWnd = pFrameWnd->GetParentFrame();
- if (pFrameWnd != NULL)
- {
- ASSERT_KINDOF(CFrameWnd, pFrameWnd);
- pFrameWnd->ActivateFrame();
- pFrameWnd->OnUpdateFrameTitle(TRUE);
- }
- }
- if (!pDoc->GetPathName().IsEmpty())
- {
- // user is also in control of the application, when a file-based
- // document becomes visible.
- AfxOleSetUserCtrl(TRUE);
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem - attributes
- void COleClientItem::GetClassID(CLSID* pClassID) const
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- ASSERT(AfxIsValidAddress(pClassID, sizeof(CLSID)));
- if (m_lpObject->GetUserClassID(pClassID) != S_OK)
- *pClassID = CLSID_NULL;
- }
- BOOL COleClientItem::GetExtent(LPSIZE lpSize, DVASPECT nDrawAspect)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- ASSERT(AfxIsValidAddress(lpSize, sizeof(CSize)));
- // use current default aspect if specific one not specified
- if (nDrawAspect == -1)
- nDrawAspect = m_nDrawAspect;
- // get the extent
- m_scLast = m_lpObject->GetExtent(nDrawAspect, lpSize);
- return m_scLast == S_OK;
- }
- BOOL COleClientItem::GetCachedExtent(LPSIZE lpSize, DVASPECT nDrawAspect)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpViewObject != NULL);
- ASSERT(AfxIsValidAddress(lpSize, sizeof(CSize)));
- // use current default aspect if specific one not specified
- if (nDrawAspect == -1)
- nDrawAspect = m_nDrawAspect;
- COleDocument* pDoc = (COleDocument*)GetDocument();
- ASSERT_VALID(pDoc);
- // get the extent
- m_scLast = m_lpViewObject->GetExtent(nDrawAspect, -1, pDoc->m_ptd, lpSize);
- return m_scLast == S_OK;
- }
- BOOL COleClientItem::SetIconicMetafile(HGLOBAL hMetaPict)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- // get IOleCache interface
- LPOLECACHE lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
- if (lpOleCache == NULL)
- {
- TRACE0("Warning: object does not support IOleCache interface.\n");
- return FALSE;
- }
- ASSERT(lpOleCache != NULL);
- // new cache is for CF_METAFILEPICT, DVASPECT_ICON
- FORMATETC formatEtc;
- formatEtc.cfFormat = CF_METAFILEPICT;
- formatEtc.ptd = NULL;
- formatEtc.dwAspect = DVASPECT_ICON;
- formatEtc.lindex = -1;
- formatEtc.tymed = TYMED_MFPICT;
- // setup the cache so iconic aspect is now included
- DWORD dwConnection;
- SCODE sc = lpOleCache->Cache(&formatEtc,
- ADVF_NODATA|ADVF_PRIMEFIRST|ADVF_ONLYONCE, &dwConnection);
- if (FAILED(sc))
- {
- lpOleCache->Release();
- return FALSE;
- }
- // set data if iconic image provided
- if (hMetaPict != NULL)
- {
- STGMEDIUM stgMedium;
- stgMedium.tymed = TYMED_MFPICT;
- stgMedium.hGlobal = hMetaPict;
- stgMedium.pUnkForRelease = NULL;
- sc = lpOleCache->SetData(&formatEtc, &stgMedium, FALSE);
- if (FAILED(sc))
- {
- lpOleCache->Release();
- return FALSE;
- }
- }
- lpOleCache->Release();
- return TRUE;
- }
- HGLOBAL COleClientItem::GetIconicMetafile()
- {
- USES_CONVERSION;
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- // get IDataObject interface
- LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
- ASSERT(lpDataObject != NULL);
- // cache is for CF_METAFILEPICT, DVASPECT_ICON
- FORMATETC formatEtc;
- formatEtc.cfFormat = CF_METAFILEPICT;
- formatEtc.ptd = NULL;
- formatEtc.dwAspect = DVASPECT_ICON;
- formatEtc.lindex = -1;
- formatEtc.tymed = TYMED_MFPICT;
- // attempt to get the icon picture
- STGMEDIUM stgMedium;
- if (lpDataObject->GetData(&formatEtc, &stgMedium) != S_OK)
- {
- lpDataObject->Release();
- // no current picture, attempt to get from class ID
- CLSID clsid;
- if (m_lpObject->GetUserClassID(&clsid) != S_OK)
- return NULL;
- TCHAR szTemp[_MAX_PATH];
- LPTSTR lpszLabel = NULL;
- if (GetType() == OT_LINK)
- {
- // it is a link, attempt to get link name
- LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
- if (lpOleLink != NULL)
- {
- LPOLESTR lpszDisplayName = NULL;
- lpOleLink->GetSourceDisplayName(&lpszDisplayName);
- if (lpszDisplayName != NULL)
- {
- szTemp[0] = 0;
- AfxGetFileTitle(OLE2CT(lpszDisplayName), szTemp, _countof(szTemp));
- if (szTemp[0] != '\0')
- lpszLabel = szTemp;
- CoTaskMemFree(lpszDisplayName);
- }
- lpOleLink->Release();
- }
- }
- HGLOBAL hMetaPict = OleGetIconOfClass(clsid, T2OLE(lpszLabel), lpszLabel == NULL);
- if (hMetaPict != NULL)
- {
- // cache it for later GetData (or drawing)
- SetIconicMetafile(hMetaPict);
- return hMetaPict;
- }
- return NULL;
- }
- lpDataObject->Release();
- // can't handle data where punkForRelease is set
- if (stgMedium.pUnkForRelease != NULL)
- {
- ::ReleaseStgMedium(&stgMedium);
- return NULL;
- }
- ASSERT(stgMedium.tymed == TYMED_MFPICT);
- ASSERT(stgMedium.hGlobal != NULL);
- return stgMedium.hGlobal; // return HGLOBAL to METAFILEPICT
- }
- void COleClientItem::SetDrawAspect(DVASPECT nDrawAspect)
- {
- ASSERT_VALID(this);
- // prime iconic cache (in case object has never displayed iconic)
- if (nDrawAspect == DVASPECT_ICON)
- {
- SetIconicMetafile(NULL); // allow object to provide own icon
- HGLOBAL hMetaPict = GetIconicMetafile();
- _AfxDeleteMetafilePict(hMetaPict);
- }
- // Note: the aspect you are setting may be uncached and therefore blank.
- // To make sure it is cached use SetIconPicture or use IOleCache to
- // set the cache yourself.
- m_nDrawAspect = nDrawAspect;
- // mark document as dirty (m_nDrawAspect is part of persistent state)
- ASSERT_VALID(m_pDocument);
- m_pDocument->SetModifiedFlag();
- }
- // Helper used to get the DVTARGETDEVICE pointer for the first printer.
- BOOL COleClientItem::GetPrintDeviceInfo(
- LPOLECACHE* plpOleCache, DVTARGETDEVICE** pptd, DWORD* pdwConnection)
- {
- *plpOleCache = NULL;
- *pptd = NULL;
- // get IOleCache interface
- LPOLECACHE lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
- if (lpOleCache == NULL)
- {
- TRACE0("Warning: object does not support IOleCache interface.\n");
- return FALSE; // no cache -- no possible print device
- }
- ASSERT(lpOleCache != NULL);
- // get enumerator for the cache
- LPENUMSTATDATA lpEnumSTATDATA;
- if (lpOleCache->EnumCache(&lpEnumSTATDATA) != S_OK || lpEnumSTATDATA == NULL)
- {
- lpOleCache->Release();
- return FALSE;
- }
- // enumerate entries in the cache (look for one with ptd != NULL)
- STATDATA statData;
- while (lpEnumSTATDATA->Next(1, &statData, NULL) == S_OK)
- {
- ASSERT(statData.pAdvSink == NULL);
- // return first non-NULL ptd (we assume this is a printer cache)
- if (statData.formatetc.ptd != NULL)
- {
- if (pdwConnection != NULL)
- *pdwConnection = statData.dwConnection;
- *pptd = statData.formatetc.ptd;
- lpEnumSTATDATA->Release();
- *plpOleCache = lpOleCache;
- return TRUE; // Note: lpOleCache pointer is still alive
- }
- }
- // release interfaces
- lpEnumSTATDATA->Release();
- lpOleCache->Release();
- return FALSE; // data not found
- }
- void COleClientItem::AttachDataObject(COleDataObject& rDataObject) const
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- // get the IDataObject interface for the item
- LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
- ASSERT(lpDataObject != NULL);
- // return it by attaching it
- rDataObject.Attach(lpDataObject, TRUE);
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem - general operations
- BOOL COleClientItem::Draw(CDC* pDC, LPCRECT lpBounds, DVASPECT nDrawAspect)
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(lpBounds, sizeof(RECT), FALSE));
- ASSERT_VALID(pDC);
- if (m_lpObject == NULL || m_lpViewObject == NULL)
- return FALSE; // partially created COleClientItem object
- // use current draw aspect if aspect is -1 (default)
- if (nDrawAspect == -1)
- nDrawAspect = m_nDrawAspect;
- // convert RECT lpBounds to RECTL rclBounds
- RECTL rclBounds;
- rclBounds.left = lpBounds->left;
- rclBounds.top = lpBounds->top;
- rclBounds.right = lpBounds->right;
- rclBounds.bottom = lpBounds->bottom;
- // get RECTL describing window extents and origin
- RECTL rclWBounds;
- CPoint ptOrg = pDC->GetWindowOrg();
- CSize sizeExt = pDC->GetWindowExt();
- rclWBounds.left = ptOrg.x;
- rclWBounds.top = ptOrg.y;
- rclWBounds.right = sizeExt.cx;
- rclWBounds.bottom = sizeExt.cy;
- // get target device to use for draw
- COleDocument* pDoc = GetDocument();
- const DVTARGETDEVICE* ptd = NULL;
- HDC hdcTarget = NULL;
- if (pDC->IsPrinting() && pDoc->m_ptd != NULL)
- {
- ptd = pDoc->m_ptd;
- hdcTarget = pDC->m_hAttribDC;
- }
- // attempt draw with target device
- SCODE sc = m_lpViewObject->Draw(nDrawAspect, -1, NULL,
- (DVTARGETDEVICE*)ptd, hdcTarget, pDC->m_hDC,
- &rclBounds, &rclWBounds, NULL, 0);
- if (ptd != NULL && sc == OLE_E_BLANK)
- {
- // attempt draw without target device
- sc = m_lpViewObject->Draw(nDrawAspect, -1, NULL,
- NULL, NULL, pDC->m_hDC,
- &rclBounds, &rclWBounds, NULL, 0);
- }
- if (sc != S_OK && sc == OLE_E_BLANK)
- return FALSE; // return FALSE if the object is blank
- CheckGeneral(sc); // otherwise, may throw exception on error
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem clipboard helpers
- void COleClientItem::GetEmbeddedItemData(LPSTGMEDIUM lpStgMedium)
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
- LPLOCKBYTES lpLockBytes;
- SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
- if (sc != S_OK)
- AfxThrowOleException(sc);
- ASSERT(lpLockBytes != NULL);
- LPSTORAGE lpStorage;
- sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
- STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &lpStorage);
- if (sc != S_OK)
- {
- VERIFY(lpLockBytes->Release() == 0);
- AfxThrowOleException(sc);
- }
- ASSERT(lpStorage != NULL);
- lpLockBytes->Release();
- // save the object into the storage
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- sc = ::OleSave(lpPersistStorage, lpStorage, FALSE);
- lpPersistStorage->SaveCompleted(NULL);
- lpPersistStorage->Release();
- if (sc != S_OK)
- {
- VERIFY(lpStorage->Release() == 0);
- AfxThrowOleException(sc);
- }
- // add it to the data source
- lpStgMedium->tymed = TYMED_ISTORAGE;
- lpStgMedium->pstg = lpStorage;
- lpStgMedium->pUnkForRelease = NULL;
- }
- void COleClientItem::AddCachedData(COleDataSource* pDataSource)
- {
- ASSERT_VALID(this);
- ASSERT_VALID(pDataSource);
- // get IOleCache interface
- LPOLECACHE lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
- if (lpOleCache == NULL)
- {
- TRACE0("Warning: object does not support IOleCache interface.\n");
- return;
- }
- ASSERT(lpOleCache != NULL);
- // Get IEnumSTATDATA interface for IOleCache
- LPENUMSTATDATA lpEnumSTATDATA;
- if (lpOleCache->EnumCache(&lpEnumSTATDATA) != S_OK || lpEnumSTATDATA == NULL)
- {
- lpOleCache->Release();
- return;
- }
- // get IDataObject interface
- LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
- ASSERT(lpDataObject != NULL);
- // enumerate all of the cached formats
- STATDATA statData;
- while (lpEnumSTATDATA->Next(1, &statData, NULL) == S_OK)
- {
- ASSERT(statData.pAdvSink == NULL);
- // for each format supported, attempt to get copy of the data
- STGMEDIUM stgMedium;
- if (lpDataObject->GetData(&statData.formatetc, &stgMedium) != S_OK)
- {
- // data is not available
- CoTaskMemFree(statData.formatetc.ptd);
- }
- else if (stgMedium.pUnkForRelease != NULL)
- {
- // don't cache data with pUnkForRelease != NULL
- ::ReleaseStgMedium(&stgMedium);
- CoTaskMemFree(statData.formatetc.ptd);
- }
- else
- {
- // format was acceptable -- add it to the clipboard
- pDataSource->CacheData(0, &stgMedium, &statData.formatetc);
- }
- }
- // release interfaces
- lpEnumSTATDATA->Release();
- lpDataObject->Release();
- lpOleCache->Release();
- }
- BOOL COleClientItem::GetLinkSourceData(LPSTGMEDIUM lpStgMedium)
- {
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
- LPMONIKER lpMoniker = NULL;
- LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
- if (lpOleLink == NULL)
- {
- // get moniker from client site
- LPOLECLIENTSITE lpClientSite = GetClientSite();
- ASSERT(lpClientSite != NULL);
- SCODE sc = lpClientSite->GetMoniker(OLEGETMONIKER_TEMPFORUSER,
- OLEWHICHMK_OBJFULL, &lpMoniker);
- if (sc != S_OK)
- {
- TRACE0("Warning: unable to get moniker from client site.\n");
- return FALSE;
- }
- ASSERT(lpMoniker != NULL);
- }
- else
- {
- // get moniker from the link object itself
- SCODE sc = lpOleLink->GetSourceMoniker(&lpMoniker);
- lpOleLink->Release();
- if (sc != S_OK)
- {
- TRACE0("Warning: unable to get moniker from link source.\n");
- return FALSE;
- }
- ASSERT(lpMoniker != NULL);
- }
- // create a memory based stream to write the moniker to
- LPSTREAM lpStream;
- if (::CreateStreamOnHGlobal(NULL, TRUE, &lpStream) != S_OK)
- {
- lpMoniker->Release();
- AfxThrowMemoryException();
- }
- ASSERT(lpStream != NULL);
- // write the moniker to the stream, and add it to the clipboard
- SCODE sc = ::OleSaveToStream(lpMoniker, lpStream);
- lpMoniker->Release();
- if (sc != S_OK)
- {
- lpStream->Release();
- AfxThrowOleException(sc);
- }
- // write the class ID of the document to the stream as well
- CLSID clsid;
- sc = m_lpObject->GetUserClassID(&clsid);
- if (sc != S_OK)
- {
- lpStream->Release();
- AfxThrowOleException(sc);
- }
- sc = WriteClassStm(lpStream, clsid);
- if (sc != S_OK)
- {
- lpStream->Release();
- AfxThrowOleException(sc);
- }
- // add it to the data source
- lpStgMedium->tymed = TYMED_ISTREAM;
- lpStgMedium->pstm = lpStream;
- lpStgMedium->pUnkForRelease = NULL;
- return TRUE;
- }
- void COleClientItem::GetObjectDescriptorData(
- LPPOINT lpOffset, LPSIZE lpSize, LPSTGMEDIUM lpStgMedium)
- {
- USES_CONVERSION;
- ASSERT_VALID(this);
- ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
- ASSERT(lpOffset == NULL ||
- AfxIsValidAddress(lpOffset, sizeof(CPoint), FALSE));
- POINTL pointT;
- if (lpOffset != NULL)
- {
- pointT.x = lpOffset->x;
- pointT.y = lpOffset->y;
- ((CDC*)NULL)->DPtoHIMETRIC((SIZE*)&pointT);
- }
- else
- {
- pointT.x = 0;
- pointT.y = 0;
- }
- SIZE sizeT;
- if (lpSize != NULL)
- {
- sizeT.cx = lpSize->cx;
- sizeT.cy = lpSize->cy;
- ((CDC*)NULL)->DPtoHIMETRIC(&sizeT);
- }
- else
- {
- sizeT.cx = 0;
- sizeT.cy = 0;
- }
- COleDocument* pDoc = GetDocument();
- // get the object descriptor for the IOleObject
- InterlockedIncrement(&m_dwRef);
- HGLOBAL hGlobal = _AfxOleGetObjectDescriptorData(
- m_lpObject, T2COLE(pDoc->GetPathName()), m_nDrawAspect, pointT, &sizeT);
- InterlockedDecrement(&m_dwRef);
- if (hGlobal == NULL)
- AfxThrowMemoryException();
- // setup the STGMEDIUM
- lpStgMedium->tymed = TYMED_HGLOBAL;
- lpStgMedium->hGlobal = hGlobal;
- lpStgMedium->pUnkForRelease = NULL;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Embedded COleClientItem operations
- void COleClientItem::SetHostNames(LPCTSTR lpszHost, LPCTSTR lpszHostObj)
- {
- USES_CONVERSION;
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- ASSERT(AfxIsValidString(lpszHost));
- ASSERT(AfxIsValidString(lpszHostObj));
- CheckGeneral(m_lpObject->SetHostNames(T2COLE(lpszHost),
- T2COLE(lpszHostObj)));
- }
- void COleClientItem::SetExtent(const CSize& size, DVASPECT nDrawAspect)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpObject != NULL);
- CheckGeneral(m_lpObject->SetExtent(nDrawAspect, (SIZE*)&size));
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem OLE interface implementation
- BEGIN_INTERFACE_MAP(COleClientItem, CDocItem)
- INTERFACE_PART(COleClientItem, IID_IOleClientSite, OleClientSite)
- INTERFACE_PART(COleClientItem, IID_IAdviseSink, AdviseSink)
- INTERFACE_PART(COleClientItem, IID_IOleWindow, OleIPSite)
- INTERFACE_PART(COleClientItem, IID_IOleInPlaceSite, OleIPSite)
- END_INTERFACE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // Implementation of IOleClientSite
- STDMETHODIMP_(ULONG) COleClientItem::XOleClientSite::AddRef()
- {
- METHOD_PROLOGUE_EX_(COleClientItem, OleClientSite)
- return pThis->ExternalAddRef();
- }
- STDMETHODIMP_(ULONG) COleClientItem::XOleClientSite::Release()
- {
- METHOD_PROLOGUE_EX_(COleClientItem, OleClientSite)
- return pThis->ExternalRelease();
- }
- STDMETHODIMP COleClientItem::XOleClientSite::QueryInterface(
- REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_EX_(COleClientItem, OleClientSite)
- return pThis->ExternalQueryInterface(&iid, ppvObj);
- }
- STDMETHODIMP COleClientItem::XOleClientSite::SaveObject()
- {
- METHOD_PROLOGUE_EX(COleClientItem, OleClientSite)
- ASSERT_VALID(pThis);
- LPPERSISTSTORAGE lpPersistStorage =
- QUERYINTERFACE(pThis->m_lpObject, IPersistStorage);
- ASSERT(lpPersistStorage != NULL);
- SCODE sc = S_OK;
- if (lpPersistStorage->IsDirty() == S_OK)
- {
- // S_OK == S_TRUE != S_FALSE, therefore object is dirty!
- sc = ::OleSave(lpPersistStorage, pThis->m_lpStorage, TRUE);
- if (sc == S_OK)
- sc = lpPersistStorage->SaveCompleted(NULL);
- // mark the document as dirty, if save sucessful.
- pThis->m_pDocument->SetModifiedFlag();
- }
- lpPersistStorage->Release();
- return sc;
- }
- STDMETHODIMP COleClientItem::XOleClientSite::GetMoniker(
- DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMoniker)
- {
- METHOD_PROLOGUE_EX(COleClientItem, OleClientSite)
- ASSERT_VALID(pThis);
- USES_CONVERSION;
- COleDocument* pDoc = pThis->GetDocument();
- ASSERT_VALID(pDoc);
- ASSERT(ppMoniker != NULL);
- *ppMoniker = NULL;
- switch (dwWhichMoniker)
- {
- case OLEWHICHMK_CONTAINER:
- // return the current moniker for the document
- *ppMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign);
- break;
- case OLEWHICHMK_OBJREL:
- {
- if (!pDoc->IsKindOf(RUNTIME_CLASS(COleLinkingDoc)))
- break;
- // don't return relative moniker if no document moniker
- LPMONIKER lpMoniker = pDoc->GetMoniker((OLEGETMONIKER)dwAssign);
- if (lpMoniker == NULL)
- break;
- lpMoniker->Release();
- // relative monikers have to handle assignment correctly
- switch (dwAssign)
- {
- case OLEGETMONIKER_ONLYIFTHERE:
- if (!pThis->m_bMoniker)
- break; // no moniker assigned, don't return one
- // fall through...
- case OLEGETMONIKER_TEMPFORUSER:
- case OLEGETMONIKER_FORCEASSIGN:
- {
- // create item moniker from item name
- TCHAR szItemName[OLE_MAXITEMNAME];
- pThis->GetItemName(szItemName);
- CreateItemMoniker(OLESTDDELIMOLE, T2COLE(szItemName),
- ppMoniker);
- // notify the object of the assignment
- if (dwAssign != OLEGETMONIKER_TEMPFORUSER &&
- *ppMoniker != NULL && !pThis->m_bMoniker)
- {
- pThis->m_bMoniker = TRUE;
- VERIFY(pThis->m_lpObject->SetMoniker(
- OLEWHICHMK_OBJREL, *ppMoniker) == S_OK);
- ASSERT_VALID(pThis->m_pDocument);
- pThis->m_pDocument->SetModifiedFlag();
- }
- }
- break;
- case OLEGETMONIKER_UNASSIGN:
- pThis->m_bMoniker = FALSE;
- break;
- }
- }
- break;
- case OLEWHICHMK_OBJFULL:
- {
- // get each sub-moniker: item & document
- LPMONIKER lpMoniker1, lpMoniker2;
- GetMoniker(dwAssign, OLEWHICHMK_CONTAINER, &lpMoniker1);
- GetMoniker(dwAssign, OLEWHICHMK_OBJREL, &lpMoniker2);
- // create composite moniker
- if (lpMoniker1 != NULL && lpMoniker2 != NULL)
- ::CreateGenericComposite(lpMoniker1, lpMoniker2, ppMoniker);
- // release sub-monikers
- RELEASE(lpMoniker1);
- RELEASE(lpMoniker2);
- }
- break;
- }
- return *ppMoniker != NULL ? S_OK : E_FAIL;
- }
- STDMETHODIMP COleClientItem::XOleClientSite::GetContainer(
- LPOLECONTAINER* ppContainer)
- {
- #ifdef _DEBUG
- METHOD_PROLOGUE_EX(COleClientItem, OleClientSite)
- #else
- METHOD_PROLOGUE_EX_(COleClientItem, OleClientSite)
- #endif
- // return the IOleItemContainer interface in the document
- COleDocument* pDoc = pThis->GetDocument();
- ASSERT_VALID(pDoc);
- *ppContainer = pDoc->GetContainer();
- return *ppContainer != NULL ? S_OK : E_NOINTERFACE;
- }
- STDMETHODIMP COleClientItem::XOleClientSite::ShowObject()
- {
- METHOD_PROLOGUE_EX(COleClientItem, OleClientSite)
- ASSERT_VALID(pThis);
- TRY
- {
- pThis->OnShowItem();
- }
- END_TRY
- return S_OK;
- }
- STDMETHODIMP COleClientItem::XOleClientSite::OnShowWindow(BOOL fShow)
- {
- METHOD_PROLOGUE_EX(COleClientItem, OleClientSite)
- ASSERT_VALID(pThis);
- // ignore this if the item is already in-place
- if (pThis->IsInPlaceActive())
- return S_OK;
- TRY
- {
- // store new state of object -- determines how object may be drawn
- COleClientItem::ItemState uNewState;
- uNewState = fShow ? COleClientItem::openState :
- COleClientItem::loadedState;
- if (uNewState != pThis->m_nItemState)
- {
- pThis->OnChange(OLE_CHANGED_STATE, (DWORD)uNewState);
- pThis->m_nItemState = uNewState;
- }
- }
- END_TRY
- return S_OK;
- }
- STDMETHODIMP COleClientItem::XOleClientSite::RequestNewObjectLayout()
- {
- return E_NOTIMPL;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Implementation of IAdviseSink
- STDMETHODIMP_(ULONG) COleClientItem::XAdviseSink::AddRef()
- {
- METHOD_PROLOGUE_EX_(COleClientItem, AdviseSink)
- return pThis->ExternalAddRef();
- }
- STDMETHODIMP_(ULONG) COleClientItem::XAdviseSink::Release()
- {
- METHOD_PROLOGUE_EX_(COleClientItem, AdviseSink)
- return pThis->ExternalRelease();
- }
- STDMETHODIMP COleClientItem::XAdviseSink::QueryInterface(
- REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_EX_(COleClientItem, AdviseSink)
- return pThis->ExternalQueryInterface(&iid, ppvObj);
- }
- STDMETHODIMP_(void) COleClientItem::XAdviseSink::OnDataChange(
- LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
- {
- METHOD_PROLOGUE_EX(COleClientItem, AdviseSink)
- ASSERT_VALID(pThis);
- // Only interesting for advanced containers. Forward it such that
- // containers do not have to implement the entire interface.
- pThis->OnDataChange(lpFormatEtc, lpStgMedium);
- }
- STDMETHODIMP_(void) COleClientItem::XAdviseSink::OnViewChange(
- DWORD aspects, LONG /*lindex*/)
- {
- METHOD_PROLOGUE_EX(COleClientItem, AdviseSink)
- ASSERT_VALID(pThis);
- pThis->OnChange(OLE_CHANGED, (DVASPECT)aspects);
- }
- STDMETHODIMP_(void) COleClientItem::XAdviseSink::OnRename(
- LPMONIKER /*lpMoniker*/)
- {
- // only interesting to the OLE link object. Containers ignore this.
- }
- STDMETHODIMP_(void) COleClientItem::XAdviseSink::OnSave()
- {
- METHOD_PROLOGUE_EX(COleClientItem, AdviseSink)
- ASSERT_VALID(pThis);
- pThis->OnChange(OLE_SAVED, (DVASPECT)0);
- }
- STDMETHODIMP_(void) COleClientItem::XAdviseSink::OnClose()
- {
- METHOD_PROLOGUE_EX(COleClientItem, AdviseSink)
- ASSERT_VALID(pThis);
- pThis->OnChange(OLE_CLOSED, (DVASPECT)0);
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleClientItem diagnostics
- #ifdef _DEBUG
- void COleClientItem::AssertValid() const
- {
- CDocItem::AssertValid();
- if (m_lpNewStorage != NULL)
- ASSERT(m_bNeedCommit);
- if (m_pView != NULL)
- m_pView->AssertValid();
- if (m_pInPlaceFrame != NULL)
- m_pInPlaceFrame->AssertValid();
- if (m_pInPlaceDoc != NULL)
- m_pInPlaceDoc->AssertValid();
- }
- void COleClientItem::Dump(CDumpContext& dc) const
- {
- CDocItem::Dump(dc);
- // shallow dump
- dc << "m_lpObject = " << (void*)m_lpObject;
- dc << "\nm_dwItemNumber = " << m_dwItemNumber;
- dc << "\nm_nDrawAspect = " << (int)m_nDrawAspect;
- dc << "\nm_scLast = " << m_scLast;
- dc << "\nm_lpStorage = " << m_lpStorage;
- dc << "\nm_lpLockBytes = " << m_lpLockBytes;
- dc << "\nm_dwConnection = " << m_dwConnection;
- dc << "\nm_bLinkUnavail = " << m_bLinkUnavail;
- dc << "\nm_bMoniker = " << m_bMoniker;
- dc << "\nm_lpNewStorage = " << m_lpNewStorage;
- dc << "\nm_bNeedCommit = " << m_bNeedCommit;
- dc << "\nm_nItemState = " << (int)m_nItemState;
- dc << "\nm_pView = " << (void*)m_pView;
- dc << "\nm_dwContainerStyle = " << m_dwContainerStyle;
- dc << "\nm_pInPlaceFrame = " << (void*)m_pInPlaceFrame;
- dc << "\nm_hWndServer = " << m_hWndServer;
- }
- #endif //_DEBUG
- /////////////////////////////////////////////////////////////////////////////
- // Inline function declarations expanded out-of-line
- #ifndef _AFX_ENABLE_INLINES
- // expand inlines for OLE client APIs
- static char _szAfxOleInl[] = "afxole.inl";
- #undef THIS_FILE
- #define THIS_FILE _szAfxOleInl
- #define _AFXOLECLI_INLINE
- #define _AFXOLEDOBJ_INLINE
- #include "afxole.inl"
- #endif //!_AFX_ENABLE_INLINES
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
- // IMPLEMENT_DYNAMIC for COleLinkingDoc here for better .OBJ granularity
- IMPLEMENT_DYNAMIC(COleLinkingDoc, COleDocument)
- /////////////////////////////////////////////////////////////////////////////
|