📄 dsofdocobj.cpp
字号:
SAFE_RELEASE_INTERFACE(m_pdocv);
SAFE_RELEASE_INTERFACE(m_pipobj);
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::UIActivateView
//
// UI Activates/Deactivates the object as needed.
//
STDMETHODIMP CDsoDocObject::UIActivateView(BOOL fFocus)
{
HRESULT hr = S_FALSE;
TRACE1("CDsoDocObject::UIActivateView(%d)\n", fFocus);
if (m_pdocv)
hr = m_pdocv->UIActivate(fFocus);
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::SaveDefault
//
// Saves the open object back to the original open location (unless it
// was opened read-only, or is a new object). There are three types of
// loaded doc objects we can save: (1) Files obtained by URL write bind
// via MSDAIPP; (2) Files opened from local file source; and (3) Objects
// already running or files linked to via OLE moniker obtained by an
// Automation instance passed to us in Open. This function determines
// which type we should do and call the right code for that type.
//
STDMETHODIMP CDsoDocObject::SaveDefault()
{
HRESULT hr = DSO_E_NOTBEENSAVED;
// We can't do save default if file was open read-only,
// caller must do save with new file name...
if (IsReadOnly()) return DSO_E_DOCUMENTREADONLY;
// If we have a URL (write-access) resource, do MSDAIPP save...
if (m_pstmWebResource)
{
hr = SaveStorageToURL(NULL, TRUE, NULL, NULL);
}
// Else if it is local file, do a local save...
else if (m_pwszSourceFile)
{
hr = SaveStorageToFile(NULL, TRUE);
}
// If opened by moniker, try to get storage for object and save there...
else if ((m_pmkSourceObject) && (m_pstgfile))
{
IBindCtx *pbc;
IStorage *pstg;
// First save the current state of the object in the internal
// storage for the control and then make a bind context to access
// the storage for the original source object (which may be file or other object)...
if (SUCCEEDED(hr = SaveObjectStorage()) &&
SUCCEEDED(hr = CreateBindCtx(NULL, &pbc)))
{
BIND_OPTS bndopt;
bndopt.cbStruct = sizeof(BIND_OPTS);
bndopt.grfFlags = BIND_MAYBOTHERUSER;
bndopt.grfMode = (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE);
bndopt.dwTickCountDeadline = 6000;
hr = pbc->SetBindOptions(&bndopt);
ASSERT(SUCCEEDED(hr));
// Ask moniker for the original storage and save our data to it (by copy).
// It is possible this can fail if orginal storage is file open with exclusive
// access, or if moniker was for non-saved object that is no longer running...
hr = m_pmkSourceObject->BindToStorage(pbc, NULL, IID_IStorage, (void**)&pstg);
if (SUCCEEDED(hr))
{
hr = m_pstgfile->CopyTo(0, NULL, NULL, pstg);
if (SUCCEEDED(hr))
{
// Commit the changes to the file if content is current...
hr = pstg->Commit(STGC_ONLYIFCURRENT);
}
pstg->Release();
}
pbc->Release();
}
}
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::SaveStorageToFile
//
// Saves the open object to a file. If you pass NULL for the file, we'll
// save back to the original open location.
//
STDMETHODIMP CDsoDocObject::SaveStorageToFile(LPWSTR pwszFile, BOOL fOverwriteFile)
{
HRESULT hr = E_UNEXPECTED;
IPersistFile *pipfile;
IStorage *pstg;
LPWSTR pwszFullName = NULL;
LPWSTR pwszRename = NULL;
BOOL fDoNormalSave = FALSE;
BOOL fDoOverwriteOps = FALSE;
BOOL fFileOpSuccess = FALSE;
// Make sure we have the most current state for the file...
if ((!m_pole) || FAILED(hr = SaveObjectStorage()))
return hr;
// If they passed no file, use the default if current file is not read-only...
if ((!pwszFile) &&
!((fDoNormalSave = !!(pwszFile = m_pwszSourceFile)) && (!IsReadOnly())))
return DSO_E_DOCUMENTREADONLY;
// Make sure a file extension is given (add one if not)...
if (ValidateFileExtension(pwszFile, &pwszFullName))
pwszFile = pwszFullName;
// See if we will be overwriting, and error unless given permission to do so...
if ((fDoOverwriteOps = FFileExists(pwszFile)) && !(fOverwriteFile))
return STG_E_FILEALREADYEXISTS;
// If we had a previous lock, we have to free it...
SAFE_RELEASE_INTERFACE(m_pstgSourceFile);
// If we are overwriting, we do a little Shell Operation here. This is done
// for two reasons: (1) it keeps the server from asking us to overwrite the
// file as it normally would in case of normal save; and (2) it lets us
// restore the original if the save fails...
if (fDoOverwriteOps)
{
pwszRename = DsoCopyStringCat(pwszFile, L".dstmp");
fFileOpSuccess = ((pwszRename) && FPerformShellOp(FO_RENAME, pwszFile, pwszRename));
}
// Let's do it. First ask for server to save to file if it supports IPersistFile.
// This gives us a "real" file as output. This will work with almost all Office servers...
if (SUCCEEDED(hr = m_pole->QueryInterface(IID_IPersistFile, (void**)&pipfile)))
{
hr = pipfile->Save(pwszFile, FALSE);
pipfile->Release();
}
else
{
// If that doesn't work, save out the storage to OLE file. This may not produce
// the same type of file as you would get by the UI, but it would give a file
// that can be opened here again and in any "good" OLE server.
if (SUCCEEDED(hr = StgCreateDocfile(pwszFile, STGM_TRANSACTED |
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, &pstg)))
{
WriteClassStg(pstg, m_clsidObject);
if (SUCCEEDED(hr = m_pstgfile->CopyTo(0, NULL, NULL, pstg)))
hr = pstg->Commit(STGC_OVERWRITE);
pstg->Release();
}
}
// If we made a copy to protect on overwrite, either restore or delete it as needed...
if ((fDoOverwriteOps) && (fFileOpSuccess) && (pwszRename))
{
FPerformShellOp((FAILED(hr) ? FO_RENAME : FO_DELETE), pwszRename, pwszFile);
}
// If this is an exisitng file save, or the operation failed, relock the
// the original file save source...
if (((fDoNormalSave) || (FAILED(hr))) && (m_pwszSourceFile))
{
StgOpenStorage(m_pwszSourceFile, NULL,
((m_pwszWebResource) ?
(STGM_READ | STGM_SHARE_DENY_WRITE) :
(STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE)),
NULL, 0, &m_pstgSourceFile);
}
else if (SUCCEEDED(hr))
{
// Otherwise if we succeeded, free any existing file info we have it and
// save the new file info for later re-saves (and lock)...
SAFE_FREESTRING(m_pwszSourceFile);
SAFE_FREESTRING(m_pwszWebResource);
SAFE_RELEASE_INTERFACE(m_pstmWebResource);
// Save the name, and try to lock the file for editing...
if (m_pwszSourceFile = DsoCopyString(pwszFile))
{
m_idxSourceName = CalcDocNameIndex(m_pwszSourceFile);
StgOpenStorage(m_pwszSourceFile, NULL,
(STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE), NULL, 0, &m_pstgSourceFile);
}
}
if (pwszRename)
DsoMemFree(pwszRename);
if (pwszFullName)
DsoMemFree(pwszFullName);
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::SaveStorageToURL
//
// Saves the open object to a URL. If you pass NULL, we'll save back to
// the original open location.
//
// This works very similar to the LoadStorageFromURL in that we save to
// a local file first using the normal SaveStorageToFile and then push an
// upload to the server.
//
STDMETHODIMP CDsoDocObject::SaveStorageToURL(LPWSTR pwszURL, BOOL fOverwriteFile, LPWSTR pwszUserName, LPWSTR pwszPassword)
{
HRESULT hr = DSO_E_DOCUMENTREADONLY;
// If we have no URL to save to and no previously open web stream, fail...
if ((!pwszURL) && (!m_pstmWebResource))
return hr;
if (!(m_punkRosebud) && !(m_punkRosebud = CreateRosebudIPP()))
return DSO_E_REQUIRESMSDAIPP;
if ((pwszURL) && (m_pwszWebResource) &&
(DsoCompareStringsEx(pwszURL, -1, m_pwszWebResource, -1) == CSTR_EQUAL))
pwszURL = NULL;
if (pwszURL)
{
IStream *pstmT = NULL;
LPWSTR pwszFullUrl = NULL;
LPWSTR pwszTempFile;
IStream *pstmBkupStm;
IStorage *pstgBkupStg;
LPWSTR pwszBkupFile, pwszBkupUrl;
UINT idxBkup;
if (!GetTempPathForURLDownload(pwszURL, &pwszTempFile))
return E_INVALIDARG;
if (ValidateFileExtension(pwszURL, &pwszFullUrl))
pwszURL = pwszFullUrl;
// We are going to save out the current file info in case of
// an error we can restore it to do native saves back to open location...
pstmBkupStm = m_pstmWebResource; m_pstmWebResource = NULL;
pwszBkupUrl = m_pwszWebResource; m_pwszWebResource = NULL;
pwszBkupFile = m_pwszSourceFile; m_pwszSourceFile = NULL;
pstgBkupStg = m_pstgSourceFile; m_pstgSourceFile = NULL;
idxBkup = m_idxSourceName; m_idxSourceName = 0;
// Save the object to a new (temp) file on the local drive...
if (SUCCEEDED(hr = SaveStorageToFile(pwszTempFile, TRUE)))
{
// Then upload from that file...
hr = UploadWebResource(pwszTempFile, &pstmT, pwszURL, fOverwriteFile, pwszUserName, pwszPassword);
}
// If both calls succeed, we can free the old file/url location info
// and save the new information, otherwise restore the old info from backup...
if (SUCCEEDED(hr))
{
SAFE_RELEASE_INTERFACE(pstgBkupStg);
if ((pstmBkupStm) && (pwszBkupFile))
FPerformShellOp(FO_DELETE, pwszBkupFile, NULL);
SAFE_RELEASE_INTERFACE(pstmBkupStm);
SAFE_FREESTRING(pwszBkupUrl);
SAFE_FREESTRING(pwszBkupFile);
m_pstmWebResource = pstmT;
m_pwszWebResource = DsoCopyString(pwszURL);
//m_pwszSourceFile already saved in SaveStorageToFile
//m_pstgSourceFile already saved in SaveStorageToFile
//m_idxSourceName already calced in SaveStorageToFile;
}
else
{
if (m_pstgSourceFile)
m_pstgSourceFile->Release();
if (m_pwszSourceFile)
{
FPerformShellOp(FO_DELETE, m_pwszSourceFile, NULL);
DsoMemFree(m_pwszSourceFile);
}
m_pstmWebResource = pstmBkupStm;
m_pwszWebResource = pwszBkupUrl;
m_pwszSourceFile = pwszBkupFile;
m_pstgSourceFile = pstgBkupStg;
m_idxSourceName = idxBkup;
}
if (pwszFullUrl)
DsoMemFree(pwszFullUrl);
DsoMemFree(pwszTempFile);
}
else if ((m_pstmWebResource) && (m_pwszSourceFile))
{
if (SUCCEEDED(hr = SaveStorageToFile(NULL, TRUE)))
hr = UploadWebResource(m_pwszSourceFile, &m_pstmWebResource,
NULL, TRUE, pwszUserName, pwszPassword);
}
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::DoOleCommand
//
// Calls IOleCommandTarget::Exec on the active object to do a specific
// command (like Print, SaveCopy, Zoom, etc.).
//
STDMETHODIMP CDsoDocObject::DoOleCommand(DWORD dwOleCmdId, DWORD dwOptions, VARIANT* vInParam, VARIANT* vInOutParam)
{
HRESULT hr;
OLECMD cmd = {dwOleCmdId, 0};
TRACE2("CDsoDocObject::DoOleCommand(cmd=%d, Opts=%d\n", dwOleCmdId, dwOptions);
// Can't issue OLECOMMANDs when in print preview mode (object calls us)...
if (InPrintPreview()) return E_ACCESSDENIED;
// The server must support IOleCommandTarget, the CmdID being requested, and
// the command should be enabled. If this is the case, do the command...
if ((m_pcmdt) && SUCCEEDED(m_pcmdt->QueryStatus(NULL, 1, &cmd, NULL)) &&
((cmd.cmdf & OLECMDF_SUPPORTED) && (cmd.cmdf & OLECMDF_ENABLED)))
{
TRACE1("QueryStatus say supported = 0x%X\n", cmd.cmdf);
// Do the command asked by caller on default command group...
hr = m_pcmdt->Exec(NULL, cmd.cmdID, dwOptions, vInParam, vInOutParam);
TRACE1("CMT called = 0x%X\n", hr);
// If user canceled an Office dialog, that's OK.
if ((dwOptions == OLECMDEXECOPT_PROMPTUSER) && (hr == 0x80040103))
hr = S_FALSE;
}
else
{
TRACE1("Command Not supportted (%d)\n", cmd.cmdf);
hr = DSO_E_COMMANDNOTSUPPORTED;
}
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::Close
//
// Close down the object and disconnect us from any handlers/proxies.
//
STDMETHODIMP_(void) CDsoDocObject::Close()
{
HRESULT hr;
ODS("CDsoDocObject::Close\n");
m_fInClose = TRUE;
// Make sure we are not in print preview before close...
if (InPrintPreview())
ExitPrintPreview(TRUE);
// Go ahead an IP deactivate the object...
hr = IPDeactivateView();
// Release the OLE object and cleanup...
if (m_pole)
{
hr = m_pole->Close(OLECLOSE_NOSAVE);
m_pole->SetClientSite(NULL);
FreeRunningLock();
SAFE_RELEASE_INTERFACE(m_pole);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -