📄 dsofdocobj.cpp
字号:
DBPROP rdbp[4];
BSTR bstrLock;
DWORD dw = 256;
CHAR szUserName[256];
if (FAILED(CoCreateInstance(CLSID_MSDAIPP_BINDER, NULL,
CLSCTX_INPROC, IID_IDBProperties, (void**)&pdbprops)))
return NULL;
bstrLock = (GetUserName(szUserName, &dw) ? DsoConvertToBSTR(szUserName) : NULL);
memset(rdbp, 0, sizeof(4 * sizeof(DBPROP)));
rdbpset.cProperties = 4;
rdbpset.guidPropertySet = DBPROPSET_DBINIT;
rdbpset.rgProperties = rdbp;
rdbp[0].dwPropertyID = DBPROP_INIT_BINDFLAGS;
rdbp[0].vValue.vt = VT_I4;
rdbp[0].vValue.lVal = DBBINDURLFLAG_OUTPUT;
rdbp[1].dwPropertyID = DBPROP_INIT_LOCKOWNER;
rdbp[1].vValue.vt = VT_BSTR;
rdbp[1].vValue.bstrVal = bstrLock;
rdbp[2].dwPropertyID = DBPROP_INIT_LCID;
rdbp[2].vValue.vt = VT_I4;
rdbp[2].vValue.lVal = GetThreadLocale();
rdbp[3].dwPropertyID = DBPROP_INIT_PROMPT;
rdbp[3].vValue.vt = VT_I2;
rdbp[3].vValue.iVal = DBPROMPT_COMPLETE;
if (pdbprops->SetProperties(1, &rdbpset) == S_OK)
{
hr = pdbprops->QueryInterface(IIDX_IBindResource, (void**)&pres);
}
SAFE_FREEBSTR(bstrLock);
pdbprops->Release();
return (IUnknown*)pres;
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::DownloadWebResource (protected)
//
// Downloads the file specified by the URL to the given temp file. Locks
// the web resource for editing if ppstmKeepForSave is requested.
//
STDMETHODIMP CDsoDocObject::DownloadWebResource(LPWSTR pwszURL, LPWSTR pwszFile, LPWSTR pwszUsername, LPWSTR pwszPassword, IStream** ppstmKeepForSave)
{
HRESULT hr = E_UNEXPECTED;
IStream *pstm = NULL;
IBindResource *pres = NULL;
BYTE *rgbBuf;
DWORD dwStatus, dwBindFlags;
ULONG cbRead, cbWritten;
HANDLE hFile;
// First thing, we save out the user name and password (if provided)
// for IAuthenticate which can be caled by either URLMON or MSDAIPP...
if (pwszUsername)
{
SAFE_FREESTRING(m_pwszUsername);
m_pwszUsername = DsoCopyString(pwszUsername);
SAFE_FREESTRING(m_pwszPassword);
m_pwszPassword = DsoCopyString(pwszPassword);
}
// If we don't need to write access, we can just use IE for "read-only" download...
if (ppstmKeepForSave == NULL)
{
hr = URLDownloadFile((IUnknown*)&m_xAuthenticate, pwszURL, pwszFile);
if (SUCCEEDED(hr) || (hr == E_ABORT)) return hr;
// If it fails for whatever reason, try MSDAIPP (which can use
// FPSE authentication as well as HTTP/DAV web access)...
}
// Otherwise, we want to use MSDAIPP for full access...
if (!m_punkRosebud) return DSO_E_REQUIRESMSDAIPP;
rgbBuf = new BYTE[10240]; //a 10-k buffer for reading
if (!rgbBuf) return E_OUTOFMEMORY;
// Use IBindResource::Bind to open an IStream and copy out the date to
// the file given. This will then be used to load the object from the file...
if (SUCCEEDED(m_punkRosebud->QueryInterface(IIDX_IBindResource, (void**)&pres)))
{
dwBindFlags = (DBBINDURLFLAG_READ | DBBINDURLFLAG_OUTPUT);
if (ppstmKeepForSave)
dwBindFlags |= (DBBINDURLFLAG_WRITE | DBBINDURLFLAG_SHARE_DENY_WRITE); //DBBINDURLFLAG_SHARE_EXCLUSIVE);
callagain:
if (SUCCEEDED(hr = pres->Bind(NULL, pwszURL, dwBindFlags, DBGUIDX_STREAM,
IID_IStream, (IAuthenticate*)&m_xAuthenticate, NULL, &dwStatus, (IUnknown**)&pstm)))
{
LARGE_INTEGER lintStart; lintStart.QuadPart = 0;
hr = pstm->Seek(lintStart, STREAM_SEEK_SET, NULL);
if (FOpenLocalFile(pwszFile, GENERIC_WRITE, 0, CREATE_ALWAYS, &hFile))
{
while (SUCCEEDED(hr))
{
if (FAILED(hr = pstm->Read((void*)rgbBuf, 10240, &cbRead)) ||
(cbRead == 0))
break;
if (FALSE == WriteFile(hFile, rgbBuf, cbRead, &cbWritten, NULL))
{
hr = E_WIN32_LASTERROR;
break;
}
}
CloseHandle(hFile);
}
else hr = E_WIN32_LASTERROR;
if (ppstmKeepForSave)
{ SAFE_SET_INTERFACE(*ppstmKeepForSave, pstm); }
pstm->Release();
}
else if ((hr == DB_E_NOTSUPPORTED) && ((dwBindFlags & DBBINDURLFLAG_OUTPUT) == DBBINDURLFLAG_OUTPUT))
{
// WEC4 does not support DBBINDURLFLAG_OUTPUT flag, but if we are using WEC
// we don't really need the flag since this is not an HTTP GET call. Flip the
// flag off and call the method again to connect to server...
dwBindFlags &= ~DBBINDURLFLAG_OUTPUT;
goto callagain;
}
pres->Release();
}
// Map an OLEDB error to a common "file" error so a user
// (and VB/VBScript) would better understand...
if (FAILED(hr))
{
switch (hr)
{
case DB_E_NOTFOUND: hr = STG_E_FILENOTFOUND; break;
case DB_E_READONLY:
case DB_E_RESOURCELOCKED: hr = STG_E_LOCKVIOLATION; break;
case DB_SEC_E_PERMISSIONDENIED:
case DB_SEC_E_SAFEMODE_DENIED: hr = E_ACCESSDENIED; break;
case DB_E_CANNOTCONNECT:
case DB_E_TIMEOUT: hr = E_VBA_NOREMOTESERVER; break;
case E_NOINTERFACE: hr = E_UNEXPECTED; break;
}
}
delete [] rgbBuf;
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::UploadWebResource (protected)
//
// Uploads the file to a URL. The code can be used two ways:
//
// 1.) If ppstmSave contains a pointer to an existing IStream*, then we
// just upload to the existing stream. This allows for normal "Save"
// on an open web resource.
//
// 2.) If ppstmSave is NULL (or contains a NULL IStream*), we create a new
// web resource at the location given by pwszURLSaveTo and save to its
// stream. If ppstmSave is passed, we return the new IStream* to the
// caller who can then use it to do the other type of save next time.
//
STDMETHODIMP CDsoDocObject::UploadWebResource(LPWSTR pwszFile, IStream** ppstmSave, LPWSTR pwszURLSaveTo, BOOL fOverwriteFile, LPWSTR pwszUsername, LPWSTR pwszPassword)
{
HRESULT hr = E_UNEXPECTED;
ICreateRow *pcrow = NULL;
IStream *pstm = NULL;
BYTE *rgbBuf;
HANDLE hFile;
BOOL fstmIn = FALSE;
ULONG cbRead, cbWritten;
DWORD dwStatus, dwBindFlags;
ASSERT(m_punkRosebud); // MSDAIPP is required for save...
if (!m_punkRosebud) return DSO_E_REQUIRESMSDAIPP;
// Check if this a "Save" on existing IStream* and jump to loop...
if ((ppstmSave) && (fstmIn = (BOOL)(pstm = *ppstmSave)))
goto uploadfrominstm;
// Save the user name and password (if provided) for IAuthenticate...
if (pwszUsername)
{
SAFE_FREESTRING(m_pwszUsername);
m_pwszUsername = DsoCopyString(pwszUsername);
SAFE_FREESTRING(m_pwszPassword);
m_pwszPassword = DsoCopyString(pwszPassword);
}
// Check the URL string and ask for ICreateRow (to make new web resource)...
if (!(pwszURLSaveTo) || !LooksLikeHTTP(pwszURLSaveTo) ||
FAILED(m_punkRosebud->QueryInterface(IIDX_ICreateRow, (void**)&pcrow)))
return hr;
dwBindFlags = ( DBBINDURLFLAG_READ |
DBBINDURLFLAG_WRITE |
DBBINDURLFLAG_SHARE_DENY_WRITE |
(fOverwriteFile ? DBBINDURLFLAG_OVERWRITE : 0));
if (SUCCEEDED(hr = pcrow->CreateRow(NULL, pwszURLSaveTo, dwBindFlags, DBGUIDX_STREAM,
IID_IStream, (IAuthenticate*)&m_xAuthenticate, NULL, &dwStatus, NULL, (IUnknown**)&pstm)))
{
// Once we are here, we have a stream (either handed in or opened from above).
// We just loop through and read from the file to the stream...
uploadfrominstm:
if (rgbBuf = new BYTE[10240]) //a 10-k buffer for reading
{
if (FOpenLocalFile(pwszFile, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &hFile))
{
LARGE_INTEGER lintStart; lintStart.QuadPart = 0;
hr = pstm->Seek(lintStart, STREAM_SEEK_SET, NULL);
while (SUCCEEDED(hr))
{
if (FALSE == ReadFile(hFile, rgbBuf, 10240, &cbRead, NULL))
{
hr = E_WIN32_LASTERROR;
break;
}
if (0 == cbRead) break;
if (FAILED(hr = pstm->Write((void*)rgbBuf, cbRead, &cbWritten)))
break;
}
// Need to commit the changes to make it official...
if (SUCCEEDED(hr))
hr = pstm->Commit(STGC_DEFAULT);
CloseHandle(hFile);
}
else hr = E_WIN32_LASTERROR;
delete [] rgbBuf;
}
else hr = E_OUTOFMEMORY;
// If we are not using a passed in IStream (and therefore created one), we
// should AddRef and pass back (if caller asked us to)...
if (!fstmIn)
{
if (SUCCEEDED(hr) && (ppstmSave) && (!(*ppstmSave)))
{
SAFE_SET_INTERFACE(*ppstmSave, pstm);
}
pstm->Release();
}
}
// Map an OLEDB error to a common "file" error so a user
// (and VB/VBScript) would better understand...
if (FAILED(hr))
{
switch (hr)
{
case DB_E_RESOURCEEXISTS: hr = STG_E_FILEALREADYEXISTS; break;
case DB_E_NOTFOUND: hr = STG_E_PATHNOTFOUND; break;
case DB_E_READONLY:
case DB_E_RESOURCELOCKED: hr = STG_E_LOCKVIOLATION; break;
case DB_SEC_E_PERMISSIONDENIED:
case DB_SEC_E_SAFEMODE_DENIED: hr = E_ACCESSDENIED; break;
case DB_E_CANNOTCONNECT:
case DB_E_TIMEOUT: hr = E_VBA_NOREMOTESERVER; break;
case DB_E_OUTOFSPACE: hr = STG_E_MEDIUMFULL; break;
case E_NOINTERFACE: hr = E_UNEXPECTED; break;
}
}
if (pcrow)
pcrow->Release();
return hr;
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::TurnOffWebToolbar (protected)
//
// This function "turns off" the Web toolbar used by Office apps to
// do in-site navigation. The problem is when toggling tools off the
// bar may still be visible, so we have to explicitly turn it off if
// we want a true "no tool" state.
//
STDMETHODIMP_(void) CDsoDocObject::TurnOffWebToolbar()
{
IDispatch *pdisp;
VARIANT vtT[5];
// Can't change toolbar state in print preview...
if (InPrintPreview()) return;
if ((m_pipactive) &&
(SUCCEEDED(m_pipactive->QueryInterface(IID_IDispatch, (void**)&pdisp))))
{
if (SUCCEEDED(DsoDispatchInvoke(pdisp,
L"CommandBars", 0, DISPATCH_PROPERTYGET, 0, NULL, &vtT[0])))
{
ASSERT(vtT[0].vt == VT_DISPATCH);
vtT[1].vt = VT_BSTR; vtT[1].bstrVal = SysAllocString(L"Web");
if (SUCCEEDED(DsoDispatchInvoke(vtT[0].pdispVal,
L"Item", 0, DISPATCH_PROPERTYGET, 1, &vtT[1], &vtT[2])))
{
ASSERT(vtT[2].vt == VT_DISPATCH);
vtT[3].vt = VT_BOOL; vtT[3].boolVal = 0;
DsoDispatchInvoke(vtT[2].pdispVal,
L"Visible", 0, DISPATCH_PROPERTYPUT, 1, &vtT[3], &vtT[2]);
VariantClear(&vtT[2]);
}
VariantClear(&vtT[1]);
VariantClear(&vtT[0]);
}
pdisp->Release();
}
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::ClearMergedMenu (protected)
//
// Frees the merged menu set by host.
//
STDMETHODIMP_(void) CDsoDocObject::ClearMergedMenu()
{
if (m_hMenuMerged)
{
int cbMenuCnt = GetMenuItemCount(m_hMenuMerged);
for (int i = cbMenuCnt; i >= 0; --i)
RemoveMenu(m_hMenuMerged, i, MF_BYPOSITION);
DestroyMenu(m_hMenuMerged);
m_hMenuMerged = NULL;
}
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::CalcDocNameIndex (protected)
//
// Calculates position of the name portion of the full path string.
//
STDMETHODIMP_(DWORD) CDsoDocObject::CalcDocNameIndex(LPCWSTR pwszPath)
{
DWORD cblen, idx = 0;
if ((pwszPath) && ((cblen = lstrlenW(pwszPath)) > 1))
{
for (idx = cblen; idx > 0; --idx)
{
if (pwszPath[idx] == L'\\')
break;
}
if ((idx) && !(++idx < cblen))
idx = 0;
}
return idx;
}
////////////////////////////////////////////////////////////////////////
// CDsoDocObject::IsStorageDirty
//
// Ask the object if it is dirty and return result.
//
STDMETHODIMP_(BOOL) CDsoDocObject::IsStorageDirty()
{
BOOL fDirty = TRUE; // Assume we are dirty unless object says we are not
IPersistStorage *pprststg;
IPersistFile *pprst;
// Can't be dirty without object
CHECK_NULL_RETURN(m_pole, FALSE);
// Ask object its dirty state. Use IPersistStorage (it is more ac
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -