- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2602 lines
81 KiB
C++
2602 lines
81 KiB
C++
//
|
|
//**************************************************************************
|
|
//
|
|
// BOleSite.cpp -- Implements the Bolero half of the OLE2 server object.
|
|
// BOleSite objects impersonate the client application
|
|
// from the point of view of the Bolero customer who's
|
|
// writing a server object (IPart)
|
|
//
|
|
// Copyright (c) 1993,94 by Borland International, Inc. All rights reserved
|
|
//
|
|
//**************************************************************************
|
|
|
|
// Bolero headers
|
|
//
|
|
#include "BOle.h"
|
|
#include "BOleSite.h"
|
|
#include "BOleDoc.h"
|
|
#include "BOleCMan.h"
|
|
|
|
extern "C" {
|
|
#include "ole2ui.h"
|
|
}
|
|
|
|
// System/RTL headers
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
#define NOT_IMPLEMENTED OLERET(E_NOTIMPL);
|
|
|
|
|
|
HRESULT _IFUNC BOleSite::QueryInterfaceMain(REFIID iid, LPVOID FAR *ppv)
|
|
{
|
|
HRESULT hr = ResultFromScode(E_NOINTERFACE);
|
|
*ppv = NULL;
|
|
|
|
// Self
|
|
//
|
|
if (IID_BOleSite == iid) {
|
|
(BOleSite *)*ppv = this;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
// nested interface class
|
|
|
|
if (IID_IBApplication == iid) {
|
|
((IBApplication *)*ppv) = &iApplication;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
// interfaces
|
|
if (SUCCEEDED(hr = IBContainer_QueryInterface(this, iid, ppv))) {
|
|
}
|
|
else if (SUCCEEDED(hr = IBLinkable_QueryInterface(this, iid, ppv))) {
|
|
}
|
|
else if (SUCCEEDED(hr = IPersistStorage_QueryInterface(this, iid, ppv))) {
|
|
}
|
|
else if (SUCCEEDED(hr = IDataObject_QueryInterface(this, iid, ppv))) {
|
|
}
|
|
else if (SUCCEEDED(hr = IDropSource_QueryInterface(this, iid, ppv))) {
|
|
}
|
|
else if (SUCCEEDED(hr = IOleObject_QueryInterface(this, iid, ppv))) {
|
|
}
|
|
else if (SUCCEEDED(hr = IOleInPlaceObject_QueryInterface(this, iid, ppv))) {
|
|
}
|
|
else if (SUCCEEDED(hr = IOleInPlaceActiveObject_QueryInterface(this, iid, ppv))) {
|
|
}
|
|
else if (SUCCEEDED(hr = IBSite_QueryInterface(this, iid, ppv))) {
|
|
}
|
|
else if (SUCCEEDED(hr = IEnumFORMATETC_QueryInterface(this, iid, ppv))) {
|
|
}
|
|
|
|
// base classes
|
|
else if (SUCCEEDED(hr = BOleComponent::QueryInterfaceMain(iid, ppv))) {
|
|
}
|
|
|
|
return hr;
|
|
};
|
|
|
|
|
|
//
|
|
// BOleSite implementation -- These functions aren't part of an inherited
|
|
// interface, but are part of the private
|
|
// implementation of BOleSite
|
|
//
|
|
|
|
BOleSite::BOleSite(BOleClassManager * pFact, IBUnknownMain *pOuter,
|
|
BOleService *pSvc)
|
|
: BOleComponent (pFact, pOuter) , iApplication(this, pOuter),
|
|
cid (CLSID_NULL)
|
|
{
|
|
pService = pSvc;
|
|
|
|
#ifdef OLEDBG
|
|
DebugMode = 0;
|
|
#endif
|
|
|
|
pClientSite = NULL;
|
|
pStg = NULL;
|
|
pDAdvHolder = NULL;
|
|
pAdvHolder = NULL;
|
|
pPart = NULL; // (IPart *) pOuter->InterfaceGet(IID(IPart));
|
|
pProvider = NULL;
|
|
pIPSite = 0;
|
|
pIPFrame = 0;
|
|
pIPDoc = 0;
|
|
fShown = FALSE;
|
|
fInPlaceActive = FALSE;
|
|
fInPlaceVisible = FALSE;
|
|
fInsideOut = FALSE;
|
|
fUIActive = FALSE;
|
|
fInHelpMode = FALSE;
|
|
fInClose = FALSE;
|
|
hWndParent = 0;
|
|
pHatchWnd = NULLP;
|
|
hWndInPlace = 0;
|
|
hOleMenu = 0;
|
|
hMenuShared = 0;
|
|
pszProgID = NULLP;
|
|
pmkDoc = NULLP;
|
|
hatchOffset.x = hatchOffset.y = 0;
|
|
pFactory->ServerCount(+1L);
|
|
regLink = 0L;
|
|
pszInstName = NULL;
|
|
pWindowTitle = NULL;
|
|
pAppName = NULL;
|
|
fHandsOff = FALSE;
|
|
fIsDirty = TRUE;
|
|
formatList = NULL;
|
|
formatCount = 0;
|
|
formatLink = TRUE; // default pending moniker existence
|
|
formatEmbed = TRUE;
|
|
pInPlaceName = NULL;
|
|
pDocument = NULL;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Init (PIBDataProvider pProv, PIBPart ppart, LPCOLESTR psz, BOOL fHatchWnd)
|
|
{
|
|
// If the provider also supports IBPart, then it's a full-fledged
|
|
// server object capable of inplace activation. If it doesn't, this
|
|
// BOleSite will only be used for data transfer.
|
|
//
|
|
pProvider = pProv;
|
|
pPart = ppart;
|
|
|
|
// Bind to BOleFact so we can get the CLSID
|
|
//
|
|
if (pszProgID != NULLP)
|
|
delete pszProgID;
|
|
pszProgID = new OLECHAR [lstrlen(psz) + 1];
|
|
if (!pszProgID)
|
|
return ResultFromScode (E_OUTOFMEMORY);
|
|
lstrcpy (pszProgID, psz);
|
|
|
|
CLSIDFromProgID(pszProgID, &cid);
|
|
|
|
// Cache the available formats because OLE2 will ask for formats
|
|
// during link/embed from file, even though no Clip or Drag
|
|
// happened.
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
pService->FormatHelper (&formatList, &formatCount, formatLink,
|
|
formatEmbed, pProvider);
|
|
|
|
// Create a hatched window which is visible during visual editing
|
|
//
|
|
if (pPart && fHatchWnd) {
|
|
//pHatchWnd = BOleHatchWindow::Create (NULL, boleInst, this);
|
|
pHatchWnd = new BOleHatchWindow(NULL, boleInst, this);
|
|
if (!pHatchWnd || !(HANDLE)pHatchWnd)
|
|
return ResultFromScode (E_OUTOFMEMORY);
|
|
}
|
|
|
|
// Catenate the APPNAME and the SHORTUSERTYPENAME together. This seems
|
|
// to be the convention for SetActiveObject
|
|
//
|
|
LPOLESTR appname = NULL, shortname = NULL;
|
|
int c = 0;
|
|
OleRegGetUserType (cid, USERCLASSTYPE_APPNAME, &appname);
|
|
if (appname)
|
|
c += lstrlen (appname) + lstrlen ( TEXT(" - ") );
|
|
OleRegGetUserType (cid, USERCLASSTYPE_SHORT, &shortname);
|
|
if (shortname)
|
|
c += lstrlen (shortname);
|
|
|
|
pInPlaceName = new OLECHAR [c + 1]; // +1 for null term
|
|
if (!pInPlaceName)
|
|
return ResultFromScode (E_OUTOFMEMORY);
|
|
pInPlaceName[0] = 0;
|
|
|
|
if (appname) {
|
|
strcat (pInPlaceName, appname);
|
|
strcat (pInPlaceName, TEXT(" - ") );
|
|
}
|
|
if (shortname)
|
|
strcat (pInPlaceName, shortname);
|
|
|
|
IMalloc *pMalloc;
|
|
if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pMalloc))) {
|
|
pMalloc->Free(appname);
|
|
pMalloc->Free(shortname);
|
|
pMalloc->Release();
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
BOleSite::~BOleSite ()
|
|
{
|
|
// Don't translate any more accelerators through this helper
|
|
//
|
|
if (pService->pFocusedSite == this)
|
|
OnSetFocus (NULL);
|
|
|
|
DoClose();
|
|
|
|
// Release the client site here (not in DoClose) so that we can in place
|
|
// activate after an open-edit session (Dll server case).
|
|
//
|
|
if (pClientSite) {
|
|
pClientSite->Release ();
|
|
pClientSite = NULL;
|
|
}
|
|
if (pWindowTitle) {
|
|
delete [] pWindowTitle;
|
|
pWindowTitle = NULL;
|
|
}
|
|
if (pAppName) {
|
|
delete [] pAppName;
|
|
pAppName = NULL;
|
|
}
|
|
if (pszProgID) {
|
|
delete pszProgID;
|
|
pszProgID = NULL;
|
|
}
|
|
if (pHatchWnd) {
|
|
delete pHatchWnd;
|
|
pHatchWnd = NULL;
|
|
}
|
|
if (pDocument) { // Set in BOleContainer::GetObject
|
|
CoLockObjectExternal(pDocument, FALSE, FALSE);
|
|
pDocument = NULL;
|
|
}
|
|
if (pmkDoc) {
|
|
pmkDoc->Release();
|
|
pmkDoc = NULL;
|
|
}
|
|
if (pszInstName) {
|
|
delete [] pszInstName;
|
|
pszInstName = NULL;
|
|
}
|
|
if (pInPlaceName) {
|
|
delete [] pInPlaceName;
|
|
pInPlaceName = NULL;
|
|
}
|
|
if (formatList) {
|
|
delete [] formatList;
|
|
}
|
|
pFactory->ServerCount(-1L);
|
|
|
|
}
|
|
|
|
//
|
|
// Accessor functions for format lists
|
|
//
|
|
void _IFUNC BOleSite::GetFormatFlags(BOOL *pfEmbed, BOOL *pfLink)
|
|
{
|
|
if (pService->dropCount || (pService->clipCount && pService->IsOnClipboard(this))) {
|
|
*pfLink = pService->fUseDropList ? pService->dropOkToLink : pService->clipOkToLink;
|
|
*pfEmbed = pService->fUseDropList ? pService->dropOkToEmbed : pService->clipOkToEmbed;
|
|
}
|
|
else {
|
|
if (!formatList) {
|
|
// Cache the available formats because OLE2 will ask for formats
|
|
// during link/embed from file, even though no Clip or Drag
|
|
// happened.
|
|
pService->FormatHelper (&formatList, &formatCount, formatLink,
|
|
formatEmbed, pProvider);
|
|
}
|
|
*pfLink = formatLink;
|
|
*pfEmbed = formatEmbed;
|
|
}
|
|
}
|
|
|
|
void _IFUNC BOleSite::GetFormatList(LPFORMATETC *ppList, UINT *pCount)
|
|
{
|
|
if (pService->dropCount || (pService->clipCount && pService->IsOnClipboard(this))) {
|
|
*ppList = pService->fUseDropList ? pService->dropList : pService->clipList;
|
|
*pCount = pService->fUseDropList ? pService->dropCount : pService->clipCount;
|
|
}
|
|
else {
|
|
if (!formatList) {
|
|
// Cache the available formats because OLE2 will ask for formats
|
|
// during link/embed from file, even though no Clip or Drag
|
|
// happened.
|
|
pService->FormatHelper (&formatList, &formatCount, formatLink,
|
|
formatEmbed, pProvider);
|
|
}
|
|
*ppList = formatList;
|
|
*pCount = formatCount;
|
|
}
|
|
}
|
|
|
|
void _IFUNC BOleSite::GetFormatCount(UINT *pCount)
|
|
{
|
|
if (pService->dropCount || (pService->clipCount && pService->IsOnClipboard(this))) {
|
|
*pCount = pService->fUseDropList ? pService->dropCount : pService->clipCount;
|
|
}
|
|
else {
|
|
if (!formatList) {
|
|
// Cache the available formats because OLE2 will ask for formats
|
|
// during link/embed from file, even though no Clip or Drag
|
|
// happened.
|
|
pService->FormatHelper (&formatList, &formatCount, formatLink,
|
|
formatEmbed, pProvider);
|
|
}
|
|
*pCount = formatCount;
|
|
}
|
|
}
|
|
|
|
void _IFUNC BOleSite::GetFormatInfo(BOOL *pfEmbed, BOOL *pfLink, LPFORMATETC *ppList, UINT *pCount)
|
|
{
|
|
if (pService->dropCount || (pService->clipCount && pService->IsOnClipboard(this))) {
|
|
*pfLink = pService->fUseDropList ? pService->dropOkToLink : pService->clipOkToLink;
|
|
*pfEmbed = pService->fUseDropList ? pService->dropOkToEmbed : pService->clipOkToEmbed;
|
|
*ppList = pService->fUseDropList ? pService->dropList : pService->clipList;
|
|
*pCount = pService->fUseDropList ? pService->dropCount : pService->clipCount;
|
|
}
|
|
else {
|
|
if (!formatList) {
|
|
// Cache the available formats because OLE2 will ask for formats
|
|
// during link/embed from file, even though no Clip or Drag
|
|
// happened.
|
|
pService->FormatHelper (&formatList, &formatCount, formatLink,
|
|
formatEmbed, pProvider);
|
|
}
|
|
*pfLink = formatLink;
|
|
*pfEmbed = formatEmbed;
|
|
*ppList = formatList;
|
|
*pCount = formatCount;
|
|
}
|
|
}
|
|
|
|
// Render this server object onto a storage medium.
|
|
//
|
|
HRESULT _IFUNC BOleSite::GetEmbeddedObjectData (LPFORMATETC pFmt, LPSTGMEDIUM pMed)
|
|
{
|
|
LPSTORAGE lpstg = NULL;
|
|
SCODE sc = S_OK;
|
|
HRESULT hrErr;
|
|
|
|
pMed->pUnkForRelease = NULL;
|
|
|
|
if (pMed->tymed == TYMED_NULL) {
|
|
|
|
// If the tymed passed in is NULL, we will create a temporary storage
|
|
// in memory in order to render the object
|
|
//
|
|
if (pFmt->tymed & TYMED_ISTORAGE) {
|
|
lpstg = CreateStorageInMemory (STGM_READWRITE
|
|
| STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE /*| STGM_DELETEONRELEASE??*/);
|
|
if (!lpstg)
|
|
return ResultFromScode(E_OUTOFMEMORY);
|
|
|
|
pMed->pstg = lpstg;
|
|
pMed->tymed = TYMED_ISTORAGE;
|
|
pMed->pUnkForRelease = NULL;
|
|
}
|
|
else
|
|
return ResultFromScode(DATA_E_FORMATETC);
|
|
}
|
|
|
|
// If the tymed passed in is non-NULL, we will use the storage they
|
|
// gave us. If it's not a storage, return failure.
|
|
//
|
|
else if (pMed->tymed & TYMED_ISTORAGE) {
|
|
pMed->tymed = TYMED_ISTORAGE;
|
|
|
|
// The online dox say that OleSave does this, but there's no
|
|
// CompObj stream without WriteFmtUseTypeStg and no CLSID in the
|
|
// stream without WriteClassStg
|
|
//
|
|
CLSID clsid = CLSID_NULL;
|
|
CLSIDFromProgID (pszProgID, &clsid);
|
|
if ((hrErr = WriteClassStg (pMed->pstg, clsid)) != NOERROR)
|
|
return hrErr;
|
|
LPOLESTR lpLongType = NULL;
|
|
OleRegGetUserType (clsid, USERCLASSTYPE_FULL, &lpLongType);
|
|
hrErr = WriteFmtUserTypeStg (pMed->pstg, pFmt->cfFormat, lpLongType);
|
|
}
|
|
else
|
|
return ResultFromScode(DATA_E_FORMATETC);
|
|
|
|
// We don't really expect anyone to respond to this call, but WPWin
|
|
// is going to try to decide whether a new object is linked or embedded
|
|
// based on this notification.
|
|
//
|
|
BOleFormat f;
|
|
f.fmtId = BOleDocument::oleEmbSrcClipFmt;
|
|
f.fmtMedium = BOLE_MED_STORAGE;
|
|
f.fmtName[0] = 0;
|
|
f.fmtResultName[0] = 0;
|
|
f.fmtIsLinkable = FALSE;
|
|
pProvider->GetFormatData (&f);
|
|
|
|
hrErr = OleSave(this, pMed->pstg, FALSE /* fSameAsLoad */);
|
|
if (hrErr != NOERROR)
|
|
sc = GetScode(hrErr);
|
|
|
|
// Always call SaveCompleted, but don't stomp the error code if
|
|
// OleSave failed
|
|
//
|
|
hrErr = SaveCompleted (NULL);
|
|
if (hrErr != NOERROR && sc == S_OK)
|
|
sc = GetScode(hrErr);
|
|
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
// Render the data for a link source into a stream medium
|
|
//
|
|
HRESULT _IFUNC BOleSite::GetLinkSourceData(LPMONIKER lpmk, REFCLSID cid,
|
|
LPFORMATETC lpformatetc, LPSTGMEDIUM lpMedium)
|
|
{
|
|
LPSTREAM lpstm = NULL;
|
|
HRESULT hrErr;
|
|
|
|
// We don't really expect anyone to respond to this call, but WPWin
|
|
// is going to try to decide whether a new object is linked or embedded
|
|
// based on this notification.
|
|
//
|
|
BOleFormat f;
|
|
f.fmtId = BOleDocument::oleLinkSrcClipFmt;
|
|
f.fmtMedium = BOLE_MED_STREAM;
|
|
f.fmtName[0] = 0;
|
|
f.fmtResultName[0] = 0;
|
|
f.fmtIsLinkable = TRUE;
|
|
pProvider->GetFormatData (&f);
|
|
|
|
if (lpMedium->tymed == TYMED_NULL) {
|
|
if (lpformatetc->tymed & TYMED_ISTREAM) {
|
|
hrErr = CreateStreamOnHGlobal(
|
|
NULL, // auto allocate
|
|
TRUE, // delete on release
|
|
(LPSTREAM FAR*)&lpstm
|
|
);
|
|
if (hrErr != NOERROR) {
|
|
lpMedium->pUnkForRelease = NULL;
|
|
return ResultFromScode (E_OUTOFMEMORY);
|
|
}
|
|
lpMedium->pstm = lpstm;
|
|
lpMedium->tymed = TYMED_ISTREAM;
|
|
lpMedium->pUnkForRelease = NULL;
|
|
}
|
|
else {
|
|
lpMedium->pUnkForRelease = NULL;
|
|
return ResultFromScode (DATA_E_FORMATETC);
|
|
}
|
|
}
|
|
else {
|
|
if (lpMedium->tymed & TYMED_ISTREAM) {
|
|
lpMedium->tymed = TYMED_ISTREAM;
|
|
lpMedium->pstm = lpMedium->pstm;
|
|
lpMedium->pUnkForRelease = NULL;
|
|
}
|
|
else {
|
|
lpMedium->pUnkForRelease = NULL;
|
|
return ResultFromScode (DATA_E_FORMATETC);
|
|
}
|
|
}
|
|
|
|
hrErr = OleSaveToStream((LPPERSISTSTREAM)lpmk, lpMedium->pstm);
|
|
if (hrErr != NOERROR)
|
|
return hrErr;
|
|
return WriteClassStm (lpMedium->pstm, cid);
|
|
}
|
|
|
|
// Creates an LPSTORAGE with the specified flags on a memory lockbytes
|
|
//
|
|
LPSTORAGE _IFUNC BOleSite::CreateStorageInMemory (DWORD grfMode)
|
|
{
|
|
DWORD grfCreateMode =grfMode | STGM_CREATE;
|
|
HRESULT hrErr;
|
|
LPLOCKBYTES lpLockBytes = NULL;
|
|
DWORD reserved = 0;
|
|
LPSTORAGE lpStg = NULL;
|
|
|
|
hrErr = CreateILockBytesOnHGlobal(NULL, TRUE /*delete on release*/,
|
|
&lpLockBytes);
|
|
if (hrErr != NOERROR)
|
|
return NULL;
|
|
|
|
hrErr = StgCreateDocfileOnILockBytes(lpLockBytes, grfCreateMode,
|
|
reserved, &lpStg);
|
|
if (hrErr != NOERROR) {
|
|
lpLockBytes->Release();
|
|
return NULL;
|
|
}
|
|
lpLockBytes->Release();
|
|
return lpStg;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IDataObject implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
HRESULT _IFUNC BOleSite::GetData (LPFORMATETC pFormatEtcIn, LPSTGMEDIUM pMedium)
|
|
{
|
|
#ifdef ANSI
|
|
char name[32];
|
|
GetClipboardFormatNameA(pFormatEtcIn->cfFormat, name, sizeof(name));
|
|
#else
|
|
OLECHAR name[32];
|
|
GetClipboardFormatName(pFormatEtcIn->cfFormat, name, sizeof(name));
|
|
#endif
|
|
|
|
HRESULT hrErr = ResultFromScode (DATA_E_FORMATETC);
|
|
|
|
BOOL fLink = TRUE;
|
|
BOOL fEmbed = TRUE;
|
|
|
|
GetFormatFlags(&fEmbed, &fLink);
|
|
|
|
if (pFormatEtcIn->dwAspect & (DVASPECT_CONTENT | DVASPECT_DOCPRINT)) {
|
|
|
|
pMedium->tymed = 0L;
|
|
pMedium->pUnkForRelease = NULL;
|
|
pMedium->hGlobal = NULL;
|
|
|
|
if (pFormatEtcIn->cfFormat == BOleDocument::oleEmbSrcClipFmt) {
|
|
if( fEmbed )
|
|
hrErr = GetEmbeddedObjectData (pFormatEtcIn, pMedium);
|
|
}
|
|
else if (pFormatEtcIn->cfFormat == BOleDocument::oleObjectDescFmt) {
|
|
if( fEmbed )
|
|
goto _getobjdesc;
|
|
}
|
|
else if (pFormatEtcIn->cfFormat == BOleDocument::oleLinkSrcClipFmt) {
|
|
if( fLink ) {
|
|
LPMONIKER pMon;
|
|
hrErr = GetMoniker(OLEGETMONIKER_ONLYIFTHERE,OLEWHICHMK_OBJFULL, &pMon);
|
|
if (SUCCEEDED(hrErr)) {
|
|
CLSID id;
|
|
hrErr = GetUserClassID(&id);
|
|
pMedium->tymed = TYMED_NULL; // for GetLinkSourceData
|
|
pFormatEtcIn->cfFormat = BOleDocument::oleLinkSrcClipFmt; // per Brockshmit's suggestion
|
|
pFormatEtcIn->tymed = TYMED_ISTREAM; // pg. 773
|
|
if (SUCCEEDED(hrErr)) {
|
|
hrErr = GetLinkSourceData(pMon, id, pFormatEtcIn, pMedium);
|
|
}
|
|
pMon->Release();
|
|
}
|
|
}
|
|
}
|
|
else if (pFormatEtcIn->cfFormat == BOleDocument::oleLinkSrcDescFmt) {
|
|
if( fLink ) {
|
|
_getobjdesc:;
|
|
// Object descriptors *must* be returned in a memory handle
|
|
//
|
|
if (pFormatEtcIn->tymed & TYMED_HGLOBAL) {
|
|
pMedium->hGlobal = GetObjDescData ();
|
|
if (pMedium->hGlobal) {
|
|
pMedium->tymed = TYMED_HGLOBAL;
|
|
hrErr = ResultFromScode (S_OK);
|
|
}
|
|
else
|
|
hrErr = ResultFromScode (E_OUTOFMEMORY);
|
|
}
|
|
}
|
|
}
|
|
else if (pFormatEtcIn->cfFormat == CF_METAFILEPICT && (pFormatEtcIn->tymed & TYMED_MFPICT)) {
|
|
hrErr = GetMetaFileData (pMedium->hGlobal);
|
|
if (hrErr == NOERROR)
|
|
pMedium->tymed = TYMED_MFPICT;
|
|
}
|
|
// It's not an OLE2 format, maybe it's a regular clipboard format
|
|
// the client would know.
|
|
//
|
|
else {
|
|
BOleFormat boleFmt;
|
|
_fmemset(&boleFmt, 0, sizeof(boleFmt));
|
|
boleFmt.fmtId = pFormatEtcIn->cfFormat;
|
|
boleFmt.fmtMedium = (BOleMedium) pFormatEtcIn->tymed;
|
|
|
|
//PHP It would be more efficient to use our list of formats
|
|
//from enumFormatEtc to check before calling GetFormatData
|
|
|
|
if (pMedium) {
|
|
pMedium->hGlobal = pProvider->GetFormatData (&boleFmt);
|
|
if (pMedium->hGlobal) {
|
|
pMedium->tymed = boleFmt.fmtMedium & ~BOLE_MED_STATIC;
|
|
}
|
|
}
|
|
|
|
if (pMedium->hGlobal)
|
|
hrErr = ResultFromScode (S_OK);
|
|
}
|
|
}
|
|
|
|
return hrErr;
|
|
}
|
|
|
|
#ifdef TESTMETAFILE
|
|
extern HINSTANCE boleInst;
|
|
|
|
void RenderMetaFile(HGLOBAL hMFPict)
|
|
{
|
|
LPMETAFILEPICT pMFPict = (LPMETAFILEPICT) GlobalLock (hMFPict);
|
|
int xPix = MAP_LOGHIM_TO_PIX (pMFPict->xExt, BOleService::pixPerIn.x);
|
|
int yPix = MAP_LOGHIM_TO_PIX (pMFPict->yExt, BOleService::pixPerIn.y);
|
|
|
|
HWND w = GetDesktopWindow();
|
|
|
|
if (w) {
|
|
HDC dc = GetDC (w);
|
|
UINT oldMapMode = SetMapMode(dc, MM_ANISOTROPIC);
|
|
SetWindowExt (dc, 1000, 1000);
|
|
SetViewportExt (dc, xPix, yPix);
|
|
PlayMetaFile (dc, pMFPict->hMF);
|
|
SetMapMode (dc, oldMapMode);
|
|
ReleaseDC(w, dc);
|
|
GlobalUnlock (hMFPict);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
HRESULT _IFUNC BOleSite::GetMetaFileData (HGLOBAL& hMem)
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
#ifdef ANSI
|
|
HDC hDC = CreateMetaFileA(NULL);
|
|
#else
|
|
HDC hDC = CreateMetaFile(NULL);
|
|
#endif
|
|
if (hDC) {
|
|
// Get server size in pixels
|
|
SIZE s;
|
|
pProvider->GetPartSize (&s);
|
|
// Convert server size to himetric, and set up dc for drawing
|
|
//
|
|
SIZEL sl;
|
|
sl.cx = MAP_PIX_TO_LOGHIM (s.cx, BOleService::pixPerIn.x);
|
|
sl.cy = MAP_PIX_TO_LOGHIM (s.cy, BOleService::pixPerIn.y);
|
|
|
|
SetMapMode(hDC, MM_ANISOTROPIC);
|
|
SetWindowOrg(hDC, 0, 0);
|
|
SetWindowExt(hDC, sl.cx, sl.cy);
|
|
|
|
RECTL rPos = {0L, 0L, sl.cx, sl.cy}, rExt = {0L, 0L, sl.cx, sl.cy};
|
|
pProvider->Draw (hDC, &rPos, &rExt, BOLE_CONTENT);
|
|
HMETAFILE hMF = CloseMetaFile (hDC);
|
|
|
|
if (hMF) {
|
|
HGLOBAL hMFPict = ::GlobalAlloc (GMEM_SHARE|GMEM_ZEROINIT, sizeof (METAFILEPICT));
|
|
if (hMFPict) {
|
|
LPMETAFILEPICT pPict = (LPMETAFILEPICT) ::GlobalLock (hMFPict);
|
|
if (pPict) {
|
|
pPict->mm = MM_ANISOTROPIC;
|
|
pPict->hMF = hMF;
|
|
pPict->xExt = sl.cx;
|
|
pPict->yExt = sl.cy; // add minus sign to make it +ve
|
|
GlobalUnlock (hMFPict);
|
|
hMem = hMFPict;
|
|
}
|
|
else {
|
|
GlobalFree (hMFPict);
|
|
DeleteMetaFile (hMF);
|
|
hrErr = ResultFromScode (E_OUTOFMEMORY);
|
|
}
|
|
}
|
|
else {
|
|
DeleteMetaFile (hMF);
|
|
hrErr = ResultFromScode (E_OUTOFMEMORY);
|
|
}
|
|
}
|
|
else
|
|
hrErr = ResultFromScode (E_OUTOFMEMORY);
|
|
}
|
|
#ifdef TESTMETAFILE
|
|
if (SUCCEEDED(hrErr))
|
|
RenderMetaFile(hMem);
|
|
#endif
|
|
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetDataHere (LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
|
|
{
|
|
#ifdef ANSI
|
|
char name[32];
|
|
GetClipboardFormatNameA(pFormatEtc->cfFormat, name, sizeof(name));
|
|
#else
|
|
OLECHAR name[32];
|
|
GetClipboardFormatName(pFormatEtc->cfFormat, name, sizeof(name));
|
|
#endif
|
|
|
|
BOOL fLink = TRUE;
|
|
BOOL fEmbed = TRUE;
|
|
|
|
GetFormatFlags(&fEmbed, &fLink);
|
|
|
|
HRESULT hr = ResultFromScode(DATA_E_FORMATETC);
|
|
|
|
if (pFormatEtc->cfFormat == BOleDocument::oleEmbSrcClipFmt) {
|
|
if( fEmbed )
|
|
hr = GetEmbeddedObjectData (pFormatEtc, pMedium);
|
|
}
|
|
else
|
|
if (pFormatEtc->cfFormat == BOleDocument::oleLinkSrcClipFmt) {
|
|
if (fLink) {
|
|
LPMONIKER pMon;
|
|
hr = GetMoniker(OLEGETMONIKER_ONLYIFTHERE,OLEWHICHMK_OBJFULL, &pMon);
|
|
if (SUCCEEDED(hr)) {
|
|
CLSID id;
|
|
hr = GetUserClassID (&id);
|
|
pMedium->tymed = TYMED_NULL; // for GetLinkSourceData
|
|
pFormatEtc->cfFormat = BOleDocument::oleLinkSrcClipFmt; // per Brockshmit's suggestion
|
|
pFormatEtc->tymed = TYMED_ISTREAM; // pg. 773
|
|
if (SUCCEEDED(hr))
|
|
hr = GetLinkSourceData(pMon, id, pFormatEtc, pMedium);
|
|
pMon->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::QueryGetData (LPFORMATETC pFormatEtc)
|
|
{
|
|
#ifdef ANSI
|
|
char name[32];
|
|
GetClipboardFormatNameA(pFormatEtc->cfFormat, name, sizeof(name));
|
|
#else
|
|
OLECHAR name[32];
|
|
GetClipboardFormatName(pFormatEtc->cfFormat, name, sizeof(name));
|
|
#endif
|
|
|
|
BOOL fLink = TRUE;
|
|
BOOL fEmbed = TRUE;
|
|
LPFORMATETC pList;
|
|
UINT count;
|
|
|
|
GetFormatInfo(&fEmbed, &fLink, &pList, &count);
|
|
|
|
HRESULT hrErr = ResultFromScode (DV_E_FORMATETC);
|
|
|
|
if (pFormatEtc->cfFormat == BOleDocument::oleObjectDescFmt) {
|
|
if (fEmbed) {
|
|
// Object Descriptors must be offered in global handles
|
|
//
|
|
if (pFormatEtc->tymed & TYMED_HGLOBAL)
|
|
hrErr = NOERROR;
|
|
else
|
|
hrErr = ResultFromScode (DV_E_FORMATETC);
|
|
}
|
|
}
|
|
|
|
else if (pFormatEtc->cfFormat == BOleDocument::oleLinkSrcDescFmt) {
|
|
if (fLink) {
|
|
// Link Src Desc, like Obj Desc, must be offered in a global handle
|
|
//
|
|
if (pFormatEtc->tymed & TYMED_HGLOBAL)
|
|
hrErr = NOERROR;
|
|
else
|
|
hrErr = ResultFromScode (DV_E_FORMATETC);
|
|
}
|
|
}
|
|
|
|
for (UINT i = 0; i < count; i++) {
|
|
if ((pList[i].cfFormat == pFormatEtc->cfFormat) &&
|
|
(pList[i].tymed & pFormatEtc->tymed)) {
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
}
|
|
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetCanonicalFormatEtc (LPFORMATETC pFormatetc, LPFORMATETC pFormatetcOut)
|
|
{
|
|
if (!pFormatetcOut)
|
|
return ResultFromScode( E_INVALIDARG );
|
|
|
|
pFormatetcOut->ptd = NULL;
|
|
|
|
if (!pFormatetc)
|
|
return ResultFromScode (E_INVALIDARG);
|
|
|
|
HRESULT hrErr;
|
|
|
|
hrErr = QueryGetData (pFormatetc);
|
|
if (hrErr != NOERROR)
|
|
return hrErr;
|
|
|
|
*pFormatetcOut = *pFormatetc;
|
|
if (!pFormatetc->ptd)
|
|
return ResultFromScode (DATA_S_SAMEFORMATETC);
|
|
|
|
pFormatetcOut->ptd = NULL;
|
|
return NOERROR;
|
|
}
|
|
|
|
// Set data into the server
|
|
//
|
|
HRESULT _IFUNC BOleSite::SetData (LPFORMATETC pFormatEtc, STGMEDIUM FAR* pMedium, BOOL fRelease)
|
|
{
|
|
PIBDataProvider2 pProvider2 = NULL;
|
|
|
|
// Does client implement IBDataProvider2?
|
|
//
|
|
if (!SUCCEEDED(pObjOuter->QueryInterfaceMain (IID_IBDataProvider2,&(LPVOID)pProvider2)))
|
|
NOT_IMPLEMENTED
|
|
|
|
HRESULT hr = ResultFromScode (DATA_E_FORMATETC);
|
|
|
|
if ((BOleMedium) pFormatEtc->tymed == BOLE_MED_HGLOBAL) {
|
|
BOleFormat boleFmt;
|
|
_fmemset(&boleFmt, 0, sizeof(boleFmt));
|
|
boleFmt.fmtId = pFormatEtc->cfFormat;
|
|
boleFmt.fmtMedium = (BOleMedium) pFormatEtc->tymed;
|
|
|
|
if (pMedium) {
|
|
hr = pProvider2->SetFormatData(&boleFmt, pMedium->hGlobal, FALSE);
|
|
|
|
// Always do release here instead of in SetFormatData
|
|
//
|
|
if (fRelease)
|
|
ReleaseStgMedium(pMedium);
|
|
}
|
|
}
|
|
|
|
pProvider2->Release();
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::EnumFormatEtc (DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)
|
|
{
|
|
if (dwDirection == DATADIR_GET) {
|
|
*ppenumFormatEtc = this;
|
|
enumFmtIndex = 0L;
|
|
AddRef(); // caller must release
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
// I'm not sure what it would mean to call IDataObject::SetData
|
|
// on the BOleSite so it's blank until I can do more research
|
|
//
|
|
return ResultFromScode (E_FAIL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::DAdvise (FORMATETC FAR* pFormatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD FAR* pdwConnection)
|
|
{
|
|
HRESULT hrErr;
|
|
|
|
*pdwConnection = 0;
|
|
if (pDAdvHolder == 0)
|
|
hrErr = CreateDataAdviseHolder (&pDAdvHolder);
|
|
if (pDAdvHolder)
|
|
hrErr = pDAdvHolder->Advise (this, pFormatetc, advf, pAdvSink, pdwConnection);
|
|
else
|
|
hrErr = ResultFromScode (E_OUTOFMEMORY);
|
|
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::DUnadvise (DWORD dwConnection)
|
|
{
|
|
HRESULT hrErr = ResultFromScode(E_FAIL);
|
|
if (pDAdvHolder)
|
|
hrErr = pDAdvHolder->Unadvise (dwConnection);
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::EnumDAdvise (IEnumSTATDATA* FAR* ppenumAdvise)
|
|
{
|
|
HRESULT hrErr = ResultFromScode(E_FAIL);
|
|
if (pDAdvHolder)
|
|
hrErr = pDAdvHolder->EnumAdvise (ppenumAdvise);
|
|
return hrErr;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IEnumFORMATETC implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
HRESULT _IFUNC BOleSite::Next (ULONG celt, FORMATETC FAR * pFE, ULONG FAR* pceltFetched)
|
|
{
|
|
LPFORMATETC pList;
|
|
UINT count;
|
|
|
|
GetFormatList(&pList, &count);
|
|
|
|
if (pceltFetched)
|
|
*pceltFetched = 0;
|
|
|
|
if( !celt )
|
|
return ResultFromScode (E_INVALIDARG);
|
|
|
|
short nCopied = 0;
|
|
while ( (enumFmtIndex < count) && (nCopied < celt) ) {
|
|
pFE[nCopied] = pList[enumFmtIndex];
|
|
enumFmtIndex++;
|
|
nCopied++;
|
|
if (pceltFetched)
|
|
(*pceltFetched)++;
|
|
}
|
|
return ResultFromScode( nCopied != celt ? S_FALSE : S_OK);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Skip (ULONG celt)
|
|
{
|
|
UINT count;
|
|
GetFormatCount(&count);
|
|
|
|
if( celt > count )
|
|
return ResultFromScode (E_INVALIDARG);
|
|
|
|
if( enumFmtIndex < count ) {
|
|
int diff = count - enumFmtIndex;
|
|
enumFmtIndex += celt;
|
|
return ResultFromScode (diff < celt ? S_OK : S_FALSE);
|
|
}
|
|
return ResultFromScode (S_FALSE);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Reset ()
|
|
{
|
|
enumFmtIndex = 0L;
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Clone (IEnumFORMATETC FAR* FAR* ppenum)
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IOleObject implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
HRESULT _IFUNC BOleSite::SetClientSite (IOleClientSite* pCS)
|
|
{
|
|
if (pClientSite)
|
|
pClientSite->Release ();
|
|
pClientSite = pCS;
|
|
if (pClientSite)
|
|
pClientSite->AddRef ();
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetClientSite (IOleClientSite* FAR* ppClientSite)
|
|
{
|
|
if (pClientSite) {
|
|
pClientSite->AddRef ();
|
|
*ppClientSite = pClientSite;
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
else {
|
|
*ppClientSite = NULL;
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::SetHostNames (LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
|
|
{
|
|
// Delete the old ones if any
|
|
//
|
|
if (pAppName) {
|
|
delete [] pAppName;
|
|
pAppName = NULL;
|
|
}
|
|
if (pWindowTitle) {
|
|
delete [] pWindowTitle;
|
|
pWindowTitle = NULL;
|
|
}
|
|
|
|
// Copy the new ones into member data so they're around in case
|
|
// the part object asks for them (through IBContainer or IBApplication)
|
|
//
|
|
short c = strlen (szContainerApp) + 1; //+1 for \0 terminator
|
|
pAppName = new OLECHAR[c];
|
|
if (!pAppName)
|
|
return ResultFromScode (E_OUTOFMEMORY);
|
|
lstrcpyn( pAppName, szContainerApp, c );
|
|
if (szContainerObj) { // docs say this could be NULL
|
|
c = strlen (szContainerObj) + 1; //+1 for \0 terminator
|
|
pWindowTitle = new OLECHAR[c];
|
|
if (!pWindowTitle)
|
|
return ResultFromScode (E_OUTOFMEMORY);
|
|
lstrcpyn ( pWindowTitle, szContainerObj, c);
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
HRESULT _IFUNC BOleSite::DoClose ()
|
|
{
|
|
// If closed while open in place, exit in-place mode
|
|
//
|
|
if (fInPlaceActive) {
|
|
DoInPlaceDeactivate ();
|
|
}
|
|
|
|
// If closed while open editing, exit open edit mode
|
|
//
|
|
if (fShown) {
|
|
// pass FALSE here to not allow Lock(FALSE) to cause ::Close to be
|
|
// called recursively in in-proc server case.
|
|
// Unlocking is done at the end of ::Close (see comments below).
|
|
//
|
|
HideWindow(FALSE);
|
|
}
|
|
|
|
// If this object is on the clipboard, render all formats
|
|
//
|
|
if (pService->IsOnClipboard(this))
|
|
pService->FlushClipboardData(FALSE);
|
|
|
|
// Unregister for linking
|
|
//
|
|
if (regLink != 0L) {
|
|
LPRUNNINGOBJECTTABLE pROT = NULL;
|
|
HRESULT hr = OLE::GetRunningObjectTable (0, &pROT);
|
|
if (SUCCEEDED(hr)) {
|
|
pROT->Revoke(regLink);
|
|
regLink = 0L;
|
|
pROT->Release();
|
|
}
|
|
}
|
|
|
|
// Notify containers of exit from "running state"
|
|
//
|
|
if (pDAdvHolder) {
|
|
pDAdvHolder->SendOnDataChange (this, 0, ADVF_DATAONSTOP);
|
|
pDAdvHolder->Release ();
|
|
pDAdvHolder = NULL;
|
|
}
|
|
if (pAdvHolder) {
|
|
BOOL tmp = fInClose;
|
|
fInClose = TRUE;
|
|
pAdvHolder->SendOnClose (); // SendOnClose recursively calls Close!
|
|
pAdvHolder->Release ();
|
|
fInClose = tmp;
|
|
pAdvHolder = NULL;
|
|
}
|
|
|
|
// Release some remaining references to others
|
|
//
|
|
if (pIPSite) {
|
|
pIPSite->Release();
|
|
pIPSite = NULL;
|
|
}
|
|
if (pIPFrame) {
|
|
pIPFrame->Release();
|
|
pIPFrame = NULL;
|
|
}
|
|
if (pIPDoc) {
|
|
pIPDoc->Release();
|
|
pIPDoc = NULL;
|
|
}
|
|
if (pStg) {
|
|
pStg->Release ();
|
|
pStg = NULL;
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Close (DWORD dwSaveOption)
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
if (fInClose)
|
|
return NOERROR;
|
|
AddRef();
|
|
fInClose = TRUE;
|
|
|
|
if (fIsDirty) {
|
|
if (dwSaveOption == OLECLOSE_PROMPTSAVE) {
|
|
if (pAppName) {
|
|
UINT nResponse = MessageBox(NULL, TEXT("Save Object before closing?"),
|
|
pAppName, MB_ICONQUESTION | MB_YESNOCANCEL );
|
|
switch (nResponse) {
|
|
case IDNO:
|
|
dwSaveOption = OLECLOSE_NOSAVE;
|
|
break;
|
|
case IDCANCEL:
|
|
hrErr = ResultFromScode(OLE_E_PROMPTSAVECANCELLED); // don't close
|
|
fInClose = FALSE;
|
|
return hrErr;
|
|
case IDYES:
|
|
dwSaveOption = OLECLOSE_SAVEIFDIRTY;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
switch (dwSaveOption) {
|
|
case OLECLOSE_SAVEIFDIRTY:
|
|
if (pClientSite) {
|
|
pClientSite->SaveObject();
|
|
fIsDirty = FALSE;
|
|
}
|
|
break;
|
|
case OLECLOSE_NOSAVE:
|
|
break;
|
|
}
|
|
}
|
|
|
|
DoClose();
|
|
|
|
// Might not have a pPart if this helper object was only used by a
|
|
// pProvider for data transfer
|
|
//
|
|
if (pPart) {
|
|
pPart->Close();
|
|
}
|
|
|
|
// This allows self embedded apps to in place activate and still shutdown
|
|
// properly. In self embed in place activation, default handler aggregator
|
|
// seems to have interfaces that don't go away until a last unlock releases.
|
|
//
|
|
// Unfortunately, the default handler also calls IOleObject::Close
|
|
// recursively. Wish it would just drop those references without
|
|
// calling Close! or Release those references before calling close...
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
CoDisconnectObject(AsPIUnknown(pObjOuter), 0);
|
|
fInClose = FALSE;
|
|
Release();
|
|
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::SetMoniker (DWORD dwWhichMoniker, IMoniker* pmk)
|
|
{
|
|
HRESULT hr= ResultFromScode(E_FAIL);
|
|
LPMONIKER pmkFull;
|
|
|
|
// To play "link to embedding", we need to register this object
|
|
// under the full moniker given by the client site.
|
|
|
|
// get the running object table
|
|
LPRUNNINGOBJECTTABLE pROT = NULL;
|
|
hr = OLE::GetRunningObjectTable (0, &pROT);
|
|
if (SUCCEEDED(hr)) {
|
|
// Register the new moniker BEFORE revoking the old moniker.
|
|
// Otherwise the object's "StubManager" gets hosed.
|
|
//
|
|
DWORD oldRegLink = regLink;
|
|
|
|
hr = GetMoniker(OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL, &pmkFull);
|
|
if (SUCCEEDED(hr)) {
|
|
hr = pROT->Register (0, //ROTFLAGS_REGISTRATIONKEEPSALIVE,
|
|
AsPIUnknown(pObjOuter), pmkFull, ®Link);
|
|
if (pAdvHolder) {
|
|
pAdvHolder->SendOnRename (pmkFull);
|
|
}
|
|
pmkFull->Release();
|
|
}
|
|
else
|
|
regLink = 0L;
|
|
|
|
// release any old running object table registration
|
|
if (oldRegLink != 0L) {
|
|
pROT->Revoke(oldRegLink);
|
|
oldRegLink = 0L;
|
|
}
|
|
pROT->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT _IFUNC BOleSite::GetMoniker (DWORD dwAssign, DWORD dwWhichMoniker, IMoniker* FAR* ppmk)
|
|
{
|
|
// If we're open in a server doc its relative to the one in pmkDoc
|
|
// If we're an embedding, its relative to the container's doc
|
|
HRESULT hr = ResultFromScode(E_FAIL);
|
|
*ppmk = NULL;
|
|
if (pClientSite) {
|
|
hr = pClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
|
|
OLEWHICHMK_OBJFULL, ppmk);
|
|
}
|
|
else if (pmkDoc && pszInstName) {
|
|
LPMONIKER pmkObj = NULL;
|
|
|
|
if (SUCCEEDED(CreateItemMoniker(TEXT("!"), pszInstName, &pmkObj))) {
|
|
hr = CreateGenericComposite(pmkDoc, pmkObj, ppmk);
|
|
pmkObj->Release();
|
|
}
|
|
}
|
|
else if (pmkDoc && !pszInstName) {
|
|
*ppmk = pmkDoc;
|
|
pmkDoc->AddRef();
|
|
hr = NOERROR;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::InitFromData (IDataObject* pDataObject, BOOL fCreation, DWORD dwReserved)
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetClipboardData (DWORD dwReserved, IDataObject* FAR* ppDataObject)
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
// Put external lock on document
|
|
HRESULT _IFUNC BOleSite::Lock (BOOL fLock, BOOL fLastUnlockReleases)
|
|
{
|
|
return CoLockObjectExternal (AsPIUnknown(pObjOuter), fLock, fLastUnlockReleases);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::ShowWindow ()
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
if (fShown)
|
|
hrErr = pPart->Open(TRUE); // show window and set focus anyway
|
|
else {
|
|
// If there's no pClientSite, this is a linked object
|
|
//
|
|
if (!pClientSite) {
|
|
hrErr = pPart->Open(TRUE);
|
|
fShown = SUCCEEDED(hrErr);
|
|
}
|
|
else {
|
|
// This is an embedded object. ask container to show itself and object
|
|
//
|
|
pClientSite->ShowObject();
|
|
if (!fInPlaceActive) {
|
|
hrErr = pPart->Open(TRUE); // show app main window
|
|
fShown = SUCCEEDED(hrErr);
|
|
if (fShown) // show open edit hatching
|
|
pClientSite->OnShowWindow (TRUE);
|
|
}
|
|
else
|
|
fShown = TRUE;
|
|
}
|
|
if (fShown)
|
|
Lock (TRUE, FALSE); // lock document till window is hidden
|
|
}
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::HideWindow (BOOL fShutdown)
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
if (fShown) {
|
|
fShown = FALSE;
|
|
|
|
// If there's no pClientSite, this is a linked object
|
|
//
|
|
if (!pClientSite)
|
|
hrErr = pPart->Open(FALSE);
|
|
else {
|
|
// This is an embedded object.
|
|
// inform container that our window is hiding
|
|
//
|
|
if (!fInPlaceVisible) {
|
|
pClientSite->OnShowWindow (FALSE); // hide open edit hatching
|
|
hrErr = pPart->Open(FALSE);
|
|
}
|
|
}
|
|
|
|
// Must unlock at the bottom in case object gets deleted
|
|
//
|
|
Lock (FALSE, fShutdown);
|
|
}
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::AssembleMenus ()
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
|
|
hMenuShared = CreateMenu ();
|
|
if (hMenuShared) {
|
|
hrErr = pIPFrame->InsertMenus (hMenuShared, &menuGroupWidths);
|
|
if (hrErr == NOERROR) {
|
|
hrErr = pPart->InsertMenus (hMenuShared, (BOleMenuWidths *)&menuGroupWidths);
|
|
}
|
|
else {
|
|
// Even when the in-place container does not allow menu merging
|
|
// the server must still call OleCreateMenuDescriptor(NULL)
|
|
//
|
|
DestroyMenu (hMenuShared);
|
|
hMenuShared = NULL;
|
|
}
|
|
}
|
|
hOleMenu = OleCreateMenuDescriptor (hMenuShared, &menuGroupWidths);
|
|
if (!hOleMenu)
|
|
hrErr = ResultFromScode (E_OUTOFMEMORY);
|
|
return hrErr;
|
|
}
|
|
|
|
void _IFUNC BOleSite::DisassembleMenus ()
|
|
{
|
|
if (hOleMenu) {
|
|
OleDestroyMenuDescriptor (hOleMenu);
|
|
hOleMenu = 0;
|
|
}
|
|
if (hMenuShared) {
|
|
UINT uDeleteAt = 0;
|
|
for (UINT uGroup = 0; uGroup < 6; uGroup++) {
|
|
uDeleteAt += menuGroupWidths.width [uGroup++];
|
|
for (UINT uCount = 0; uCount < menuGroupWidths.width [uGroup]; uCount++)
|
|
DeleteMenu (hMenuShared, uDeleteAt, MF_BYPOSITION);
|
|
}
|
|
if (pIPFrame)
|
|
pIPFrame->RemoveMenus (hMenuShared);
|
|
DestroyMenu (hMenuShared);
|
|
hMenuShared = 0;
|
|
}
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::DoInPlaceActivate (BOOL fActivateOnly)
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
if (pClientSite && !fInPlaceActive /*&& !fShown*/) {
|
|
hrErr = pClientSite->QueryInterface(IID_IOleInPlaceSite,&(void *)pIPSite);
|
|
if (SUCCEEDED(hrErr)) {
|
|
hrErr = pIPSite->CanInPlaceActivate ();
|
|
if (GetScode(hrErr) == S_OK) { //returns S_FALSE instead of E_FAIL
|
|
hrErr = pIPSite->OnInPlaceActivate ();
|
|
if (SUCCEEDED(hrErr)) {
|
|
fInPlaceActive = TRUE;
|
|
hrErr = DoInPlaceShow (fActivateOnly);
|
|
if (SUCCEEDED(hrErr))
|
|
hrErr = DoUIActivate ();
|
|
}
|
|
else {
|
|
pIPSite->Release();
|
|
pIPSite = 0;
|
|
}
|
|
}
|
|
else {
|
|
pIPSite->Release();
|
|
pIPSite = 0;
|
|
}
|
|
}
|
|
}
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::CalcZoom( LPCRECT rcPosRect )
|
|
{
|
|
SIZE sCurrent;
|
|
HRESULT hr = pProvider->GetPartSize (&sCurrent);
|
|
if (SUCCEEDED(hr)) {
|
|
if (sCurrent.cx == 0) {
|
|
scale.xN = 1;
|
|
scale.xD = 1;
|
|
} else {
|
|
scale.xN = rcPosRect->right - rcPosRect->left;
|
|
scale.xD = sCurrent.cx;
|
|
}
|
|
if (sCurrent.cy == 0) {
|
|
scale.yN = 1;
|
|
scale.yD = 1;
|
|
} else {
|
|
scale.yN = rcPosRect->bottom - rcPosRect->top;
|
|
scale.yD = sCurrent.cy;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::DoInPlaceShow (BOOL fActivateOnly)
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
if (!fInPlaceVisible) {
|
|
fInPlaceVisible = TRUE;
|
|
hrErr = pIPSite->GetWindow (&hWndParent);
|
|
if (SUCCEEDED(hrErr)) {
|
|
frameInfo.cb = sizeof (frameInfo);
|
|
hrErr = pIPSite->GetWindowContext (
|
|
&pIPFrame, &pIPDoc, &rcPosRect, &rcClipRect, &frameInfo);
|
|
|
|
CalcZoom( &rcPosRect );
|
|
|
|
if (SUCCEEDED(hrErr) && pIPFrame) {
|
|
// set message filter (ICS)
|
|
|
|
hWndInPlace = pPart->OpenInPlace (hWndParent);
|
|
|
|
AssembleMenus ();
|
|
if (fInsideOut && fActivateOnly) {
|
|
// show object without adornments and border
|
|
pPart->SetPartPos (&rcPosRect);
|
|
}
|
|
}
|
|
else {
|
|
DoInPlaceDeactivate ();
|
|
}
|
|
}
|
|
else {
|
|
DoInPlaceDeactivate ();
|
|
}
|
|
}
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::DoUIActivate ()
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
if (!fUIActive) {
|
|
fUIActive = TRUE;
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
hrErr = pIPSite->OnUIActivate ();
|
|
if (SUCCEEDED(hrErr)) {
|
|
|
|
if (pHatchWnd) {
|
|
|
|
// Put the hatch window around the inplace window. The offset
|
|
// is necessary because we're reparenting the inplace window
|
|
// behind the scenes, so the border of the hatch window would
|
|
// throw rcPosRect off.
|
|
//
|
|
::SetParent (hWndInPlace, *pHatchWnd);
|
|
::SetParent (*pHatchWnd, hWndParent);
|
|
pHatchWnd->SetSize (&rcPosRect, &rcClipRect, &hatchOffset);
|
|
pHatchWnd->Show (TRUE, pIPSite);
|
|
::OffsetRect (&rcPosRect, hatchOffset.x, hatchOffset.y);
|
|
}
|
|
|
|
pPart->SetPartPos (&rcPosRect);
|
|
pPart->Show(TRUE); // Show after SetPos to prevent flashing
|
|
|
|
// window position of part may need to move but the extent
|
|
// should be the same
|
|
pPart->Activate (TRUE);
|
|
pIPFrame->SetActiveObject (this, pInPlaceName);
|
|
if (pIPDoc)
|
|
pIPDoc->SetActiveObject (this, pInPlaceName);
|
|
pIPFrame->SetMenu (hMenuShared, hOleMenu, hWndInPlace);
|
|
pPart->ShowTools (TRUE);
|
|
|
|
}
|
|
else {
|
|
fUIActive = FALSE;
|
|
}
|
|
}
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::DoInPlaceDeactivate ()
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
if (fInPlaceActive) {
|
|
|
|
hrErr = DoUIDeactivate ();
|
|
if (SUCCEEDED(hrErr) && fInPlaceActive) {
|
|
fInPlaceActive = FALSE;
|
|
|
|
pIPSite->OnInPlaceDeactivate ();
|
|
pIPSite->Release();
|
|
pIPSite = 0;
|
|
}
|
|
}
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::DoUIDeactivate ()
|
|
{
|
|
if (!SUCCEEDED(pPart->Show (FALSE)))
|
|
return ResultFromScode (E_FAIL); // Hide here to match Show which prevents flashing
|
|
|
|
HRESULT hrErr = NOERROR;
|
|
if (fUIActive) {
|
|
fUIActive = FALSE;
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// remove shading and adornments
|
|
if (pIPDoc)
|
|
pIPDoc->SetActiveObject (NULL, NULL);
|
|
if (pIPFrame)
|
|
pIPFrame->SetActiveObject (NULL, NULL);
|
|
pPart->ShowTools (FALSE);
|
|
pIPSite->OnUIDeactivate (FALSE);
|
|
// deactivate contained objects if any
|
|
if (!fInsideOut) {
|
|
DoInPlaceHide ();
|
|
if (pIPFrame) {
|
|
pIPFrame->Release();
|
|
pIPFrame = 0;
|
|
}
|
|
if (pIPDoc) {
|
|
pIPDoc->Release();
|
|
pIPDoc = 0;
|
|
}
|
|
}
|
|
}
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::DoInPlaceHide ()
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
if (fInPlaceVisible) {
|
|
// deactivate contained objects (ICS)
|
|
// remove shading and adornments (ICS)
|
|
hrErr = pPart->OpenInPlace (0) == NULL ? ResultFromScode (E_FAIL) : NOERROR;
|
|
if (pHatchWnd)
|
|
// Hide the hatch window
|
|
//
|
|
pHatchWnd->Show (FALSE);
|
|
|
|
// set filter ? (ICS)
|
|
DisassembleMenus ();
|
|
HideWindow (FALSE);
|
|
fInPlaceVisible = FALSE;
|
|
}
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::DoVerb (LONG lVerb, LPMSG lpmsg, IOleClientSite* pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect)
|
|
{
|
|
HRESULT hrErr = NOERROR;
|
|
|
|
switch (lVerb) {
|
|
default:
|
|
// First ask the server app if it knows this verb
|
|
//
|
|
hrErr = pPart->DoVerb ((UINT)lVerb);
|
|
if (SUCCEEDED(hrErr))
|
|
return hrErr;
|
|
|
|
// If the server app doesn't know it, and it's a predefined (<0)
|
|
// verb, return an error
|
|
//
|
|
hrErr = ResultFromScode (OLEOBJ_S_INVALIDVERB);
|
|
if (lVerb < 0)
|
|
OLERES(hrErr);
|
|
|
|
// If it's not a predefined verb and we don't know it, deliberately
|
|
// fall through to Primary Verb
|
|
|
|
case OLEIVERB_PRIMARY:
|
|
case OLEIVERB_SHOW:
|
|
// If the window is already open (primary verb has already been
|
|
// run, just bring the window to the front
|
|
//
|
|
if (pClientSite && !fShown && !fInPlaceActive &&
|
|
(S_OK == GetScode(pPart->CanOpenInPlace())))
|
|
hrErr = DoInPlaceActivate (FALSE);
|
|
else if (fInPlaceActive && !fInPlaceVisible) {
|
|
if (SUCCEEDED(DoInPlaceShow (FALSE))) {
|
|
hrErr = DoUIActivate ();
|
|
}
|
|
}
|
|
hrErr = ShowWindow ();
|
|
break;
|
|
case 1:
|
|
case OLEIVERB_OPEN:
|
|
if (pClientSite && fInPlaceActive)
|
|
hrErr = DoInPlaceDeactivate ();
|
|
hrErr = ShowWindow ();
|
|
break;
|
|
case OLEIVERB_HIDE:
|
|
if (pClientSite && fInPlaceActive)
|
|
hrErr = DoInPlaceHide ();
|
|
else
|
|
hrErr = HideWindow (TRUE /*fShutdown*/);
|
|
break;
|
|
case OLEIVERB_UIACTIVATE:
|
|
case OLEIVERB_INPLACEACTIVATE:
|
|
|
|
// If our window is already open-editing we can't activate in-place.
|
|
//
|
|
if (pClientSite && !fShown && !fInPlaceActive &&
|
|
(S_OK == GetScode(pPart->CanOpenInPlace())))
|
|
hrErr = DoInPlaceActivate (lVerb == OLEIVERB_INPLACEACTIVATE);
|
|
else
|
|
hrErr = ResultFromScode (OLE_E_NOT_INPLACEACTIVE);
|
|
break;
|
|
}
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::EnumVerbs (IEnumOLEVERB* FAR* ppenumOleVerb)
|
|
{
|
|
return OleRegEnumVerbs(cid, ppenumOleVerb);
|
|
//
|
|
//
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Update ()
|
|
{
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IsUpToDate ()
|
|
{
|
|
return ResultFromScode(MK_E_UNAVAILABLE);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetUserClassID (CLSID FAR* pClsid)
|
|
{
|
|
*pClsid = cid;
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetUserType (DWORD dwFormOfType, LPOLESTR FAR* pszUserType)
|
|
{
|
|
return ResultFromScode (OLE_S_USEREG);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::SetExtent (DWORD dwDrawAspect, LPSIZEL lpsizel)
|
|
{
|
|
RECT pos;
|
|
pos.left = pos.top = 0;
|
|
pos.right = MAP_LOGHIM_TO_PIX (lpsizel->cx, BOleService::pixPerIn.x);
|
|
pos.bottom = MAP_LOGHIM_TO_PIX (lpsizel->cy, BOleService::pixPerIn.y);
|
|
SIZE size;
|
|
size.cx = pos.right;
|
|
size.cy = pos.bottom;
|
|
|
|
HRESULT hr = pPart->SetPartSize(&size);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
Invalidate(BOLE_INVAL_VIEW);
|
|
pPart->SetPartPos (&pos);
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetExtent (DWORD dwDrawAspect, LPSIZEL lpsizel)
|
|
{
|
|
if (dwDrawAspect != DVASPECT_CONTENT) //PHP for now.
|
|
return ResultFromScode (E_FAIL);
|
|
|
|
if (!lpsizel)
|
|
return ResultFromScode (E_INVALIDARG);
|
|
|
|
SIZE s;
|
|
HRESULT hr = pProvider->GetPartSize (&s); //PHP do we need aspect here?
|
|
|
|
lpsizel->cx = MAP_PIX_TO_LOGHIM (s.cx, BOleService::pixPerIn.x);
|
|
lpsizel->cy = MAP_PIX_TO_LOGHIM (s.cy, BOleService::pixPerIn.y);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Advise (IAdviseSink* pAdvSink, DWORD FAR* pdwConnection)
|
|
{
|
|
HRESULT hrErr;
|
|
|
|
*pdwConnection = 0;
|
|
if (pAdvHolder == 0)
|
|
hrErr = CreateOleAdviseHolder (&pAdvHolder);
|
|
if (pAdvHolder)
|
|
hrErr = pAdvHolder->Advise (pAdvSink, pdwConnection);
|
|
else
|
|
hrErr = ResultFromScode (E_OUTOFMEMORY);
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Unadvise (DWORD dwConnection)
|
|
{
|
|
HRESULT hrErr = ResultFromScode (E_FAIL);
|
|
if (pAdvHolder)
|
|
hrErr = pAdvHolder->Unadvise (dwConnection);
|
|
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::EnumAdvise (IEnumSTATDATA* FAR* ppenumAdvise)
|
|
{
|
|
HRESULT hrErr = ResultFromScode (E_FAIL);
|
|
if (pAdvHolder)
|
|
hrErr = pAdvHolder->EnumAdvise (ppenumAdvise);
|
|
|
|
return hrErr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetMiscStatus (DWORD dwAspect, DWORD FAR* pdwStatus)
|
|
{
|
|
return ResultFromScode (OLE_S_USEREG);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::SetColorScheme (LPLOGPALETTE lpLogpal)
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IPersist implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
HRESULT _IFUNC BOleSite::GetClassID (LPCLSID lpClassID)
|
|
{
|
|
*lpClassID = cid;
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IsDirty ()
|
|
{
|
|
return ResultFromScode((fIsDirty) ? S_OK : S_FALSE);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IPersistStorage implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
HRESULT _IFUNC BOleSite::InitNew (IStorage* pStgNew)
|
|
{
|
|
if (pStg) {
|
|
pStg->Release ();
|
|
pStg = NULL;
|
|
}
|
|
pStg = pStgNew;
|
|
if (pStg) {
|
|
pStg->AddRef();
|
|
}
|
|
BOleInitInfo bi;
|
|
bi.pContainer = NULL;
|
|
bi.Where = BOLE_NEW;
|
|
bi.How = BOLE_EMBED;
|
|
bi.pStorage = pStgNew;
|
|
|
|
HRESULT hr = pPart->Init(this, &bi);
|
|
if (!SUCCEEDED(hr))
|
|
return hr;
|
|
|
|
Invalidate(BOLE_INVAL_DATA);
|
|
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Load (IStorage* pStgFrom)
|
|
{
|
|
HRESULT hresult = NOERROR;
|
|
|
|
fIsDirty = FALSE; // data will be the same as what was saved
|
|
|
|
if (pStg) {
|
|
pStg->Release ();
|
|
pStg= NULL;
|
|
}
|
|
pStg = pStgFrom;
|
|
pStg->AddRef();
|
|
|
|
BOleInitInfo bi;
|
|
bi.pContainer = NULL;
|
|
bi.Where = BOLE_STORAGE;
|
|
bi.How = BOLE_EMBED;
|
|
bi.pStorage = pStg;
|
|
hresult = pPart->Init (this, &bi);
|
|
|
|
return hresult;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Save (IStorage* pStgSave, BOOL fSameAsLoad)
|
|
{
|
|
// if (fSameAsLoad && !fIsDirty) // don't bother, its up to date
|
|
// return NOERROR;
|
|
|
|
HRESULT hresult = ResultFromScode(S_OK);
|
|
|
|
if (!pStgSave && fSameAsLoad)
|
|
pStgSave = pStg;
|
|
|
|
// The online dox say that OleSave does this, but there's no
|
|
// CompObj stream without WriteFmtUseTypeStg and no CLSID in the
|
|
// stream without WriteClassStg
|
|
//
|
|
CLSID clsid = CLSID_NULL;
|
|
CLSIDFromProgID (pszProgID, &clsid);
|
|
if ((hresult = WriteClassStg (pStgSave, clsid)) != NOERROR)
|
|
return hresult;
|
|
LPOLESTR lpLongType = NULL;
|
|
OleRegGetUserType (clsid, USERCLASSTYPE_FULL, &lpLongType);
|
|
hresult = WriteFmtUserTypeStg (pStgSave, BOleDocument::oleEmbSrcClipFmt, lpLongType);
|
|
|
|
// We pass along the fHandsOff flag here to "fRemember"
|
|
// If HandsOffStorage was called before it means SaveAs is happening
|
|
// and objects need to remember their new substorages as they create them.
|
|
// We use the fRemember flag to do what what HandsOffStorage and
|
|
// SaveCompleted do (we can't scribble to storages between saves anyway)
|
|
|
|
if (SUCCEEDED(pProvider->Save( pStgSave, fSameAsLoad, fHandsOff))) {
|
|
|
|
// since we don't scribble, do the SaveCompleted stuff here
|
|
// where we know fSameAsLoad
|
|
|
|
if (fHandsOff || fSameAsLoad) { // ! save copy as situation
|
|
fIsDirty = FALSE;
|
|
if (pAdvHolder)
|
|
hresult = pAdvHolder->SendOnSave();
|
|
if (fHandsOff) {
|
|
fHandsOff = FALSE;
|
|
pStg = pStgSave; // pStg was Released in HandsOffStorage
|
|
if (pStg)
|
|
pStg->AddRef();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
hresult = ResultFromScode(STG_E_CANTSAVE);
|
|
|
|
return hresult;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::SaveCompleted (IStorage* pStgNew)
|
|
{
|
|
if (fHandsOff) { // HandsOffStorage, SaveCompleted without Save
|
|
Save(pStgNew, FALSE);
|
|
}
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::HandsOffStorage ()
|
|
{
|
|
fHandsOff = TRUE;
|
|
if (pStg) {
|
|
pStg->Release();
|
|
pStg = NULL;
|
|
}
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IDropSource implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
HRESULT _IFUNC BOleSite::QueryContinueDrag (BOOL fEscapePressed, DWORD grfKeyState)
|
|
{
|
|
if (fEscapePressed) {
|
|
OLERET (DRAGDROP_S_CANCEL);
|
|
}
|
|
|
|
if (!(grfKeyState & (MK_LBUTTON))) {
|
|
OLERET (DRAGDROP_S_DROP);
|
|
}
|
|
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GiveFeedback (DWORD dwEffect)
|
|
{
|
|
POINT p = {0,0};
|
|
BOOL fNearScroll = FALSE;
|
|
|
|
//
|
|
// of IBDataProvider so we can do drag/drop with only a provider
|
|
//
|
|
if (!pPart)
|
|
return ResultFromScode (DRAGDROP_S_USEDEFAULTCURSORS);
|
|
|
|
if (S_OK == GetScode(pPart->DragFeedback (&p, fNearScroll))) {
|
|
return ResultFromScode (DRAGDROP_S_USEDEFAULTCURSORS);
|
|
}
|
|
else {
|
|
return ResultFromScode (S_OK);
|
|
}
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IOleWindow implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
HRESULT _IFUNC BOleSite::GetWindow (HWND FAR* lphwnd)
|
|
{
|
|
if (lphwnd) {
|
|
*lphwnd = hWndInPlace;
|
|
return NOERROR;
|
|
}
|
|
return ResultFromScode (E_INVALIDARG);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::ContextSensitiveHelp (BOOL fEnterMode)
|
|
{
|
|
return pService->ContextSensitiveHelp (fEnterMode);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IOleInPlaceObject implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
HRESULT _IFUNC BOleSite::InPlaceDeactivate ()
|
|
{
|
|
return DoInPlaceDeactivate ();
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::UIDeactivate ()
|
|
{
|
|
return DoUIDeactivate ();
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::SetObjectRects (LPCRECT lprcPosRect, LPCRECT lprcClipRect)
|
|
{
|
|
rcPosRect = *lprcPosRect;
|
|
rcClipRect = *lprcClipRect;
|
|
RECT r;
|
|
|
|
if (pHatchWnd) {
|
|
// if (! fUIActive) // hatch and adornments should not be drawn
|
|
// lprcClipRect = lprcPosRect;
|
|
|
|
pHatchWnd->SetSize (&rcPosRect, &rcClipRect, &hatchOffset);
|
|
r = rcPosRect;
|
|
|
|
// offset hatch border
|
|
|
|
::OffsetRect (&r, hatchOffset.x, hatchOffset.y);
|
|
|
|
}
|
|
else
|
|
r = rcPosRect;
|
|
|
|
|
|
CalcZoom (lprcPosRect);
|
|
|
|
pPart->SetPartPos (&r);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetZoom( BOleScaleFactor *pScale)
|
|
{
|
|
if (fInPlaceActive) {
|
|
*pScale = scale;
|
|
}
|
|
else {
|
|
pScale->xN = 1;
|
|
pScale->yN = 1;
|
|
pScale->xD = 1;
|
|
pScale->yD = 1;
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::ReactivateAndUndo ()
|
|
{
|
|
HRESULT hrErr;
|
|
if (pClientSite && !fShown && !fInPlaceActive &&
|
|
(S_OK == GetScode(pPart->CanOpenInPlace())))
|
|
hrErr = DoInPlaceActivate (OLEIVERB_INPLACEACTIVATE);
|
|
else
|
|
hrErr = ResultFromScode (OLE_E_NOT_INPLACEACTIVE);
|
|
|
|
// do undo?
|
|
|
|
return hrErr;
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IOleInPlaceActiveObject implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
HRESULT _IFUNC BOleSite::TranslateAccelerator (LPMSG lpmsg)
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::OnFrameWindowActivate (BOOL fActivate)
|
|
{
|
|
// post message to server app ? (ICS)
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::OnDocWindowActivate (BOOL fActivate)
|
|
{
|
|
if (fActivate) {
|
|
pIPFrame->SetActiveObject ((IOleInPlaceActiveObject *)this, pInPlaceName);
|
|
pIPFrame->SetMenu (hMenuShared, hOleMenu, hWndInPlace);
|
|
pPart->ShowTools (TRUE);
|
|
}
|
|
else {
|
|
pIPFrame->SetActiveObject (NULL, NULL);
|
|
|
|
pPart->ShowTools (FALSE);
|
|
// deactivate contained objects if any (ICS)
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::ResizeBorder (LPCRECT lprectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL fFrameWindow)
|
|
{
|
|
pPart->FrameResized(lprectBorder, fFrameWindow);
|
|
return ResultFromScode(S_OK);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::EnableModeless (BOOL fEnable)
|
|
{
|
|
return pService->GetApplication()->OnModalDialog (!fEnable);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IContainer implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
HRESULT _IFUNC BOleSite::AllowInPlace()
|
|
{
|
|
// anything we can use this for on server side??
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::BringToFront()
|
|
{
|
|
// anything we can use this for on server side??
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::FindDropDest (LPPOINT, PIBDropDest FAR*)
|
|
{
|
|
// anything we can use this for on server side??
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
HWND _IFUNC BOleSite::GetWindow()
|
|
{
|
|
HWND hWnd;
|
|
return (pIPSite && pIPSite->GetWindow (&hWnd) == NOERROR) ? hWnd : 0;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetWindowRect(LPRECT pR)
|
|
{
|
|
if (pIPDoc)
|
|
return pIPDoc->GetBorder (pR);
|
|
|
|
return ResultFromScode (E_FAIL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::RequestBorderSpace(LPCRECT pR)
|
|
{
|
|
BORDERWIDTHS r;
|
|
if (pR) {
|
|
r = *pR; // Word bums modify our LPCRECT contents
|
|
pR = &r;
|
|
}
|
|
if (pIPDoc)
|
|
return pIPDoc->RequestBorderSpace (pR);
|
|
|
|
return ResultFromScode (E_FAIL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::SetBorderSpace(LPCRECT pR)
|
|
{
|
|
BORDERWIDTHS r;
|
|
if (pR) {
|
|
r = *pR; // Word bums modify our LPCRECT contents
|
|
pR = &r;
|
|
}
|
|
|
|
if (pIPDoc)
|
|
return pIPDoc->SetBorderSpace (pR);
|
|
|
|
return ResultFromScode (E_FAIL);
|
|
}
|
|
|
|
LPCOLESTR _IFUNC BOleSite::GetWindowTitle()
|
|
{
|
|
return pWindowTitle;
|
|
}
|
|
|
|
void _IFUNC BOleSite::AppendWindowTitle(LPCOLESTR)
|
|
{
|
|
//PHP Do we need to call SetActiveObject???
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// ISite implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
|
|
HRESULT _IFUNC BOleSite::SiteShow(BOOL)
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::DiscardUndo()
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetSiteRect(LPRECT prcPos,LPRECT prcClip)
|
|
{
|
|
if( prcPos )
|
|
*prcPos = rcPosRect;
|
|
if( prcClip )
|
|
*prcClip = rcClipRect;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::SetSiteRect(LPCRECT pR)
|
|
{
|
|
// Can be useful for hatch window implementations or resizing
|
|
// the server when in-place active
|
|
HRESULT hr;
|
|
SIZE s;
|
|
s.cx = pR->right - pR->left;
|
|
s.cy = pR->bottom - pR->top;
|
|
|
|
if (SUCCEEDED(hr = SetSiteExtent(&s))) {
|
|
// Ask the client to resize to the new size of the window
|
|
if (pIPSite) {
|
|
hr = pIPSite->OnPosRectChange (pR);
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::SetSiteExtent (LPCSIZE pS)
|
|
{
|
|
SIZE s = *pS;
|
|
// Servers call this to update their own scaled size
|
|
// and notify the container of the change
|
|
|
|
BOleScaleFactor scale;
|
|
GetZoom(&scale);
|
|
s.cx = s.cx * scale.xD / scale.xN; // unscale
|
|
s.cy = s.cy * scale.yD / scale.yN;
|
|
HRESULT hr = pPart->SetPartSize(&s);
|
|
if (SUCCEEDED(hr)) {
|
|
// Invalidate the metafile since it's size has changed
|
|
Invalidate(BOLE_INVAL_VIEW);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
void _IFUNC BOleSite::Invalidate(BOleInvalidate inval)
|
|
{
|
|
// The PERSISTENT flag is used for servers "Update" menu.
|
|
//
|
|
if (inval & BOLE_INVAL_PERSISTENT && pClientSite) {
|
|
pClientSite->SaveObject ();
|
|
fIsDirty = FALSE;
|
|
}
|
|
|
|
// We're not distinguishing between the other two flags on the
|
|
// server side
|
|
//
|
|
if (inval & BOLE_INVAL_VIEW || inval & BOLE_INVAL_DATA) {
|
|
fIsDirty = TRUE;
|
|
if (pDAdvHolder)
|
|
pDAdvHolder->SendOnDataChange (this, 0, 0);
|
|
}
|
|
}
|
|
|
|
void _IFUNC BOleSite::OnSetFocus(BOOL bSet)
|
|
{
|
|
pService->SetFocusedSite( bSet ? this : NULL );
|
|
}
|
|
|
|
void _IFUNC BOleSite::Disconnect ()
|
|
{
|
|
//
|
|
//
|
|
//
|
|
|
|
Close(OLECLOSE_SAVEIFDIRTY);
|
|
}
|
|
|
|
//**************************************************************************
|
|
//
|
|
// IApplication implementation
|
|
//
|
|
//**************************************************************************
|
|
|
|
LPCOLESTR _IFUNC BOleSite::IBApplicationImpl::GetAppName()
|
|
{
|
|
return pThis->pAppName;
|
|
}
|
|
|
|
// This is called when an inplace active object receives a Shift-F1
|
|
// keystroke. We need to call our container so that other objects can
|
|
// be prepared to give context-sensitive help if clicked.
|
|
//
|
|
BOleHelp _IFUNC BOleSite::IBApplicationImpl::HelpMode (BOleHelp newMode)
|
|
{
|
|
BOleHelp oldMode = (BOleHelp) pThis->fInHelpMode;
|
|
if (newMode != BOLE_HELP_GET)
|
|
if (pThis->pIPSite) {
|
|
pThis->fInHelpMode = newMode == BOLE_HELP_ENTER;
|
|
pThis->pIPSite->ContextSensitiveHelp (pThis->fInHelpMode);
|
|
}
|
|
|
|
return oldMode;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::InsertContainerMenus(HMENU hMenu,BOleMenuWidths FAR* pMW)
|
|
{
|
|
return pThis->InsertContainerMenus(hMenu, pMW);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::SetFrameMenu (HMENU h)
|
|
{
|
|
return pThis->SetFrameMenu(h);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::Accelerator(MSG FAR*pMsg)
|
|
{
|
|
return pThis->Accelerator(pMsg);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::GetAccelerators (HACCEL FAR*, int FAR*)
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::CanLink()
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::CanEmbed()
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
HWND _IFUNC BOleSite::IBApplicationImpl::GetWindow ()
|
|
{
|
|
HWND hWnd;
|
|
return (pThis->pIPFrame && pThis->pIPFrame->GetWindow (&hWnd) == NOERROR) ? hWnd : 0;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::RequestBorderSpace (LPCRECT pR)
|
|
{
|
|
BORDERWIDTHS r;
|
|
if (pR) {
|
|
r = *pR; // Word modifies our LPCRECT contents
|
|
pR = &r;
|
|
}
|
|
|
|
if (pThis->pIPFrame)
|
|
return pThis->pIPFrame->RequestBorderSpace (pR);
|
|
|
|
return ResultFromScode (E_FAIL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::SetBorderSpace (LPCRECT pR)
|
|
{
|
|
BORDERWIDTHS r;
|
|
if (pR) {
|
|
r = *pR; // Word bums modify our LPCRECT contents
|
|
pR = &r;
|
|
}
|
|
|
|
if (pThis->pIPFrame)
|
|
return pThis->pIPFrame->SetBorderSpace (pR);
|
|
|
|
return ResultFromScode (E_FAIL);
|
|
}
|
|
|
|
|
|
void _IFUNC BOleSite::IBApplicationImpl::AppendWindowTitle (LPCOLESTR s)
|
|
{
|
|
if (pThis->pIPFrame)
|
|
pThis->pIPFrame->SetActiveObject(pThis, s);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::SetStatusText (LPCOLESTR s)
|
|
{
|
|
if (pThis->pIPFrame)
|
|
return pThis->pIPFrame->SetStatusText(s);
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::IsMDI ()
|
|
{
|
|
if (pThis->pIPDoc)
|
|
return ResultFromScode (S_OK);
|
|
else
|
|
return ResultFromScode (S_FALSE);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::OnModalDialog (BOOL fDialogComingActive)
|
|
{
|
|
return (pThis->pIPFrame) ?
|
|
pThis->pIPFrame->EnableModeless (!fDialogComingActive) :
|
|
NOERROR;
|
|
}
|
|
|
|
void _IFUNC BOleSite::IBApplicationImpl::RestoreUI ()
|
|
{
|
|
//PHP Server object should use this instead of SetBorderSpace(NULL)
|
|
// and AppendWindowTitle(NULL). Semantics are much cleaner.
|
|
}
|
|
|
|
void _IFUNC BOleSite::IBApplicationImpl::DialogHelpNotify (BOleDialogHelp helpCode)
|
|
{
|
|
// unimplemented in server side helper
|
|
}
|
|
|
|
void _IFUNC BOleSite::IBApplicationImpl::ShutdownMaybe ()
|
|
{
|
|
// unimplemented in server side helper
|
|
}
|
|
|
|
//
|
|
// ILinkable
|
|
//
|
|
|
|
HRESULT _IFUNC BOleSite::GetMoniker(IMoniker FAR* FAR* ppMon)
|
|
{
|
|
return GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
|
|
OLEWHICHMK_OBJFULL, ppMon);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::OnRename(PIBLinkable pCont, LPCOLESTR szName)
|
|
{
|
|
HRESULT ret = NOERROR;
|
|
|
|
if (pCont)
|
|
pCont->GetMoniker(&pmkDoc);
|
|
else if (pmkDoc) {
|
|
// Reset cached format list to cause it to be updated next time
|
|
// (now that link format is enabled/disabled).
|
|
//
|
|
//
|
|
if (formatList) {
|
|
delete [] formatList;
|
|
formatLink = FALSE;
|
|
formatEmbed = FALSE;
|
|
formatList = NULL;
|
|
formatCount = 0;
|
|
}
|
|
|
|
if (pService->IsOnClipboard(this)) {
|
|
// remove the linking capability from this object if one calls
|
|
// OnRename(NULL, NULL) before Close rather during Close
|
|
//
|
|
//
|
|
AddRef();
|
|
pService->Clip(NULL, FALSE, FALSE, FALSE);
|
|
pService->Clip(pProvider, FALSE, pService->clipOkToEmbed, FALSE);
|
|
Release();
|
|
}
|
|
|
|
if (pmkDoc) {
|
|
pmkDoc->Release();
|
|
pmkDoc = NULL;
|
|
}
|
|
}
|
|
|
|
if (pszInstName) {
|
|
delete [] pszInstName;
|
|
pszInstName = NULL;
|
|
}
|
|
if (szName) {
|
|
pszInstName = new OLECHAR[strlen (szName) +1];
|
|
lstrcpy(pszInstName, szName);
|
|
}
|
|
|
|
// Don't register if this is a clone (pPart is NULL)
|
|
// otherwise we would link to what's on the clipboard...
|
|
//
|
|
// Also don't bother if it is only a document (no item name)
|
|
// (pszInstName may be NULL and pmkDoc valid, in that case
|
|
// we shouldn't register here. BOleContainer already registered it.
|
|
//
|
|
//
|
|
if (pPart && pmkDoc && pszInstName)
|
|
SetMoniker(OLEWHICHMK_OBJFULL, NULLP); // register
|
|
|
|
if (!pmkDoc && (regLink != 0L)) {
|
|
// Unregister for linking if pmkDoc is NULL
|
|
LPRUNNINGOBJECTTABLE pROT = NULL;
|
|
HRESULT hr = OLE::GetRunningObjectTable (0, &pROT);
|
|
if (SUCCEEDED(hr)) {
|
|
pROT->Revoke(regLink);
|
|
regLink = 0L;
|
|
pROT->Release();
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
HRESULT _IFUNC BOleSite::SetStatusText (LPCOLESTR s)
|
|
{
|
|
if (pIPFrame)
|
|
return pIPFrame->SetStatusText(s);
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
|
|
|
|
|
|
LPCOLESTR _IFUNC BOleSite::IBApplicationImpl::GetWindowTitle()
|
|
{
|
|
return pThis->pWindowTitle;
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::IBApplicationImpl::GetWindowRect(LPRECT pR)
|
|
{
|
|
if (pThis->pIPFrame)
|
|
return pThis->pIPFrame->GetBorder (pR);
|
|
return ResultFromScode(CO_E_OBJNOTCONNECTED);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::GetAccelerators( HACCEL FAR *,int far*)
|
|
{
|
|
return ResultFromScode (E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::Accelerator(MSG FAR*pMsg)
|
|
{
|
|
// Give the container a chance to handle its accelerators.
|
|
// Returns S_OK if processed or S_FALSE if no accelerator was met.
|
|
if (pIPFrame)
|
|
return OleTranslateAccelerator( pIPFrame, &frameInfo, pMsg );
|
|
return ResultFromScode(S_FALSE);
|
|
}
|
|
|
|
void _IFUNC BOleSite::RestoreUI()
|
|
{
|
|
}
|
|
|
|
// This little trick allows Bolero servers to dynamically renegotiate
|
|
// the menu bar in case some state changes while they're inplace active
|
|
//
|
|
HRESULT _IFUNC BOleSite::SetFrameMenu(HMENU)
|
|
{
|
|
// First get the client to let go of the menus so we can put new ones up
|
|
//
|
|
if (pIPFrame)
|
|
pIPFrame->SetMenu (NULL, hOleMenu, hWndInPlace);
|
|
|
|
DisassembleMenus (); // Tear down the old shared menu
|
|
HRESULT hr = AssembleMenus (); // Put together a new shared menu
|
|
if (!SUCCEEDED(hr))
|
|
return hr;
|
|
// Tell the client to install it
|
|
return pIPFrame->SetMenu (hMenuShared, hOleMenu, hWndInPlace);
|
|
}
|
|
|
|
HRESULT _IFUNC BOleSite::InsertContainerMenus(HMENU hMenu,BOleMenuWidths far*)
|
|
{
|
|
if (pIPFrame)
|
|
return pIPFrame->InsertMenus (hMenu, &menuGroupWidths);
|
|
return ResultFromScode (CO_E_OBJNOTCONNECTED);
|
|
}
|
|
|
|
|