You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
398 lines
10 KiB
398 lines
10 KiB
/*---------------------------------------------------------------------------
|
|
| PERS.C
|
|
| This file has the IPersistStorage and IPersistfile interface implementation.
|
|
|
|
|
| Created By: Vij Rajarajan (VijR)
|
|
+---------------------------------------------------------------------------*/
|
|
#define SERVERONLY
|
|
#include <Windows.h>
|
|
#include "mpole.h"
|
|
#include "mplayer.h"
|
|
#define STRSAFE_NO_DEPRECATE
|
|
#include <strsafe.h>
|
|
|
|
#define STGM_SALL (STGM_READWRITE | STGM_SHARE_EXCLUSIVE)
|
|
|
|
/**************************************************************************
|
|
*************** IPersistStorage INTERFACE IMPLEMENTATION.
|
|
**************************************************************************/
|
|
//delegate to the common IUnknown implementation.
|
|
STDMETHODIMP PSQueryInterface(
|
|
LPPERSISTSTORAGE lpPersStg, // persist storage object ptr
|
|
REFIID riidReq, // IID required
|
|
LPVOID FAR * lplpUnk // pre for returning the interface
|
|
)
|
|
{
|
|
return UnkQueryInterface((LPUNKNOWN)lpPersStg, riidReq, lplpUnk);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) PSAddRef(
|
|
LPPERSISTSTORAGE lpPersStg // persist storage object ptr
|
|
)
|
|
{
|
|
return UnkAddRef((LPUNKNOWN) lpPersStg);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) PSRelease (
|
|
LPPERSISTSTORAGE lpPersStg // persist storage object ptr
|
|
)
|
|
{
|
|
return UnkRelease((LPUNKNOWN) lpPersStg);
|
|
}
|
|
|
|
STDMETHODIMP PSGetClassID (
|
|
LPPERSISTSTORAGE lpPersStg,
|
|
CLSID FAR* pClsid
|
|
)
|
|
{
|
|
DPF("PSGetClassID\n");
|
|
|
|
/* Return the actual class ID that gets stored:
|
|
*/
|
|
*pClsid = gClsIDOLE1Compat;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP PSIsDirty (
|
|
LPPERSISTSTORAGE lpPersStg
|
|
)
|
|
{DPF("PSIsDirty\n");
|
|
|
|
RETURN_RESULT( (fDocChanged && !(gfPlayingInPlace || gfOle2IPPlaying))
|
|
? S_OK : S_FALSE);
|
|
}
|
|
|
|
STDMETHODIMP PSInitNew (
|
|
LPPERSISTSTORAGE lpPersStg,
|
|
LPSTORAGE lpStorage
|
|
)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
* PSLoad:
|
|
* The Load method reads the embedded data from the "\1Ole10Native"
|
|
* stream of the IStorage passed as an argument. This is because
|
|
* we always pretend to be an OLE1 server when transferring data.
|
|
* ItemSetData is called with this embedded data to to run the required
|
|
* object.
|
|
**************************************************************************/
|
|
STDMETHODIMP PSLoad (
|
|
LPPERSISTSTORAGE lpPersStg,
|
|
LPSTORAGE lpStorage
|
|
)
|
|
{
|
|
LPDOC lpdoc;
|
|
SCODE error;
|
|
LPSTREAM pstm;
|
|
ULONG cbRead;
|
|
DWORD size = 0;
|
|
HGLOBAL hNative = NULL;
|
|
LPTSTR lpnative = NULL;
|
|
|
|
DPF("\nPSLoad is being called\n");
|
|
lpdoc = ((struct CPersistStorageImpl FAR*)lpPersStg)->lpdoc;
|
|
|
|
error = GetScode(IStorage_OpenStream(lpStorage, sz1Ole10Native,
|
|
NULL, STGM_SALL, 0, &pstm));
|
|
if (error == S_OK)
|
|
{
|
|
error = GetScode(IStream_Read(pstm, &size, 4, &cbRead));
|
|
}
|
|
if (error == S_OK)
|
|
{
|
|
hNative = GlobalAlloc(GMEM_DDESHARE |GMEM_ZEROINIT, (LONG)size);
|
|
if (hNative)
|
|
lpdoc->native = GLOBALLOCK(hNative);
|
|
}
|
|
|
|
if(lpdoc->native )
|
|
{
|
|
error = GetScode(IStream_Read(pstm, lpdoc->native, size, &cbRead));
|
|
|
|
if (cbRead != size) error = E_FAIL; // REVIEW SCODE stream size error
|
|
IStream_Release(pstm);
|
|
}
|
|
else error = E_OUTOFMEMORY;
|
|
|
|
if (error == S_OK)
|
|
{
|
|
error = ItemSetData((LPBYTE)lpdoc->native);
|
|
fDocChanged = FALSE;
|
|
lpdoc->doctype = doctypeEmbedded;
|
|
}
|
|
|
|
if(hNative)
|
|
{
|
|
GLOBALUNLOCK(hNative);
|
|
GLOBALFREE(hNative);
|
|
}
|
|
|
|
RETURN_RESULT( error);
|
|
}
|
|
|
|
/**************************************************************************
|
|
* PSSave:
|
|
* The Save method saves the native data in "\1Ole10Native" stream.
|
|
* This is because we always pretend to be an OLE1 server when transferring
|
|
* data. This ensures backward compatibility. GetLink is called to get
|
|
* the embedding data.
|
|
**************************************************************************/
|
|
STDMETHODIMP PSSave (
|
|
LPPERSISTSTORAGE lpPersStg,
|
|
LPSTORAGE lpStorage,
|
|
BOOL fSameAsLoad
|
|
)
|
|
{
|
|
LPDOC lpdoc;
|
|
SCODE error;
|
|
LPSTREAM pstm = NULL;
|
|
ULONG cbWritten;
|
|
DWORD_PTR size;
|
|
HGLOBAL hNative = NULL;
|
|
LPTSTR lpnative = NULL;
|
|
LPWSTR lpszUserType;
|
|
|
|
DPF("* in pssave *");
|
|
lpdoc = ((struct CPersistStorageImpl FAR*)lpPersStg)->lpdoc;
|
|
|
|
#if 0
|
|
// Allow saves if we're playing so that broken links can be fixed.
|
|
if (fSameAsLoad && (gfOle2IPPlaying || gfPlayingInPlace))
|
|
RETURN_RESULT(S_OK);
|
|
#endif
|
|
|
|
//Mark as OLE1 mplayer object.
|
|
#ifndef UNICODE
|
|
lpszUserType = AllocateUnicodeString(gachClassRoot);
|
|
#else
|
|
lpszUserType = gachClassRoot;
|
|
#endif
|
|
|
|
error = GetScode(WriteClassStg(lpStorage, &gClsIDOLE1Compat));
|
|
|
|
error = GetScode(WriteFmtUserTypeStg(lpStorage, cfMPlayer, lpszUserType));
|
|
#ifndef UNICODE
|
|
FreeUnicodeString(lpszUserType);
|
|
#endif
|
|
|
|
if(error != S_OK)
|
|
RETURN_RESULT(error);
|
|
error = GetScode(IStorage_CreateStream(lpStorage, sz1Ole10Native,
|
|
STGM_SALL | STGM_FAILIFTHERE, 0,0, &pstm));
|
|
if (error == STG_E_FILEALREADYEXISTS)
|
|
{
|
|
error = GetScode(IStorage_OpenStream(lpStorage, sz1Ole10Native,
|
|
NULL, STGM_SALL, 0,&pstm));
|
|
DPF("*pssave--openstream*");
|
|
}
|
|
|
|
if(pstm && (error == S_OK))
|
|
hNative = GetLink();
|
|
|
|
if (hNative)
|
|
{
|
|
lpnative = GLOBALLOCK(hNative);
|
|
size = GlobalSize(hNative);
|
|
}
|
|
else
|
|
error = E_OUTOFMEMORY;
|
|
|
|
if (lpnative && (size != 0L))
|
|
{
|
|
error = GetScode(IStream_Write(pstm, &size, 4, &cbWritten));
|
|
error = GetScode(IStream_Write(pstm, lpnative, (ULONG)size, &cbWritten));
|
|
|
|
DPF("\n*After pssave write");
|
|
if (cbWritten != size) error = E_FAIL ; // REVIEW SCODE stream full error
|
|
IStream_Release(pstm);
|
|
}
|
|
|
|
CleanObject();
|
|
GLOBALUNLOCK(hNative);
|
|
GLOBALFREE(hNative);
|
|
RETURN_RESULT(error);
|
|
}
|
|
|
|
/* InPowerPointSlideView
|
|
*
|
|
* Check the class name of the container window to see if we're in PowerPoint.
|
|
* This is to support the horrible hack to get around problem of PowerPoint
|
|
* crashing if we delete an empty Media Clip.
|
|
*
|
|
*/
|
|
STATICFN BOOL InPowerPointSlideView()
|
|
{
|
|
TCHAR ClassName[256];
|
|
|
|
if (GetClassName(ghwndCntr, ClassName, CHAR_COUNT(ClassName)) > 0)
|
|
{
|
|
if (lstrcmp(ClassName, TEXT("paneClassDC")) == 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
STDMETHODIMP PSSaveCompleted (
|
|
LPPERSISTSTORAGE lpPersStg,
|
|
LPSTORAGE lpStorage
|
|
)
|
|
{
|
|
LPDOC lpdoc;
|
|
DPF("\n**pssavecompleted**");
|
|
lpdoc = ((struct CPersistStorageImpl FAR*)lpPersStg)->lpdoc;
|
|
|
|
/* Win95 HOT bug #11142
|
|
*
|
|
* Stop PowerPoint crashing horribly:
|
|
*/
|
|
if ((gwDeviceID == 0) && InPowerPointSlideView())
|
|
SendDocMsg(lpdoc, OLE_CHANGED);
|
|
|
|
// inform clients that the object has been saved
|
|
return SendDocMsg (lpdoc, OLE_SAVED);
|
|
}
|
|
|
|
STDMETHODIMP PSHandsOffStorage (
|
|
LPPERSISTSTORAGE lpPersStg
|
|
)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
************ IPersistFile INTERFACE IMPLEMENTATION.
|
|
**************************************************************************/
|
|
//delegate to common IUnknown implementation.
|
|
STDMETHODIMP PFQueryInterface(
|
|
LPPERSISTFILE lpPersFile, // persist storage object ptr
|
|
REFIID riidReq, // IID required
|
|
LPVOID FAR * lplpUnk // pre for returning the interface
|
|
)
|
|
{
|
|
return UnkQueryInterface((LPUNKNOWN)lpPersFile, riidReq, lplpUnk);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) PFAddRef(
|
|
LPPERSISTFILE lpPersFile // persist storage object ptr
|
|
)
|
|
{
|
|
return UnkAddRef((LPUNKNOWN) lpPersFile);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) PFRelease (
|
|
LPPERSISTFILE lpPersFile // persist storage object ptr
|
|
)
|
|
{
|
|
return UnkRelease((LPUNKNOWN) lpPersFile);
|
|
}
|
|
|
|
|
|
STDMETHODIMP PFGetClassID (
|
|
LPPERSISTFILE lpPersFile,
|
|
CLSID FAR* pCid
|
|
)
|
|
{
|
|
DPF("\n* PFGetclassid");
|
|
|
|
/* The docs are confusing here, but apparently IPersist interfaces
|
|
* should return the old class ID:
|
|
*/
|
|
*pCid = gClsIDOLE1Compat;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP PFIsDirty (
|
|
LPPERSISTFILE lpPersFile
|
|
)
|
|
{
|
|
RETURN_RESULT( gfDirty ? S_OK : S_FALSE);
|
|
}
|
|
|
|
|
|
|
|
//This will be called when the user does a "Insert->Create from file".
|
|
//Open the file with OpenMciDevice and we will be ready to transfer the
|
|
//object.
|
|
STDMETHODIMP PFLoad (
|
|
LPPERSISTFILE lpPersFile,
|
|
LPCWSTR lpszFileName,
|
|
DWORD grfMode
|
|
)
|
|
{
|
|
size_t nLen;
|
|
LPDOC lpdoc;
|
|
TCHAR szFileName[256];
|
|
|
|
if(FAILED(StringCchLength(lpszFileName, 256, &nLen)))
|
|
RETURN_RESULT(E_FAIL);
|
|
|
|
//Don't even attempt to deal with file names greater then 256
|
|
//Don't worry about nonUnincode so casting as LPTSTR
|
|
if(nLen > 255)
|
|
RETURN_RESULT(E_FAIL);
|
|
|
|
lpdoc = ((struct CPersistStorageImpl FAR*)lpPersFile)->lpdoc;
|
|
DPF("\n***IN PFLOAD: "DTS"\n", lpszFileName);
|
|
#if UNICODE
|
|
lstrcpy(szFileName, lpszFileName);
|
|
#else
|
|
UnicodeToAnsiString(lpszFileName, szFileName, UNKNOWN_LENGTH);
|
|
#endif
|
|
if(OpenMciDevice(szFileName, NULL))
|
|
RETURN_RESULT(S_OK);
|
|
else
|
|
RETURN_RESULT(E_FAIL);
|
|
}
|
|
|
|
|
|
STDMETHODIMP PFSave (
|
|
LPPERSISTFILE lpPersFile,
|
|
LPCWSTR lpszFileName,
|
|
BOOL fRemember
|
|
)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP PFSaveCompleted (
|
|
LPPERSISTFILE lpPersFile,
|
|
LPCWSTR lpszFileName
|
|
)
|
|
{
|
|
LPDOC lpdoc;
|
|
|
|
lpdoc = ((struct CPersistStorageImpl FAR*)lpPersFile)->lpdoc;
|
|
|
|
// inform clients that the object has been saved
|
|
return SendDocMsg(lpdoc, OLE_SAVED);
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP PFGetCurFile (
|
|
LPPERSISTFILE lpPersFile,
|
|
LPWSTR FAR* lplpszFileName
|
|
)
|
|
{
|
|
RETURN_RESULT( E_NOTIMPL);
|
|
}
|
|
|