OLEDOC.CPP

/************************************************************************** 
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright 1997 Microsoft Corporation. All Rights Reserved.
**************************************************************************/

/**************************************************************************

File: OleDoc.cpp

Description: COleDocument implementation.

**************************************************************************/

/**************************************************************************
#include statements
**************************************************************************/

#include "OleDoc.h"
#include "comcat.h"

/**************************************************************************
global variables
**************************************************************************/

extern DWORD g_DllRefCount;

/**************************************************************************

COleDocument::COleDocument()

**************************************************************************/

COleDocument::COleDocument()
{
OutputDebugString(TEXT("COleDocument's constructor\n"));

m_ObjRefCount = 0;

m_fDirty = FALSE;
m_fNoScribbleMode = FALSE;
m_pOleAdviseHolder = NULL;
m_pOleClientSite = NULL;
m_dwRegister = 0;
m_pOleDocView = NULL;
m_Color = DEFAULT_COLOR;
m_fCreated = FALSE;

m_pOleObject = new COleObject(this);

m_pDataObject = new CDataObject(this);

m_pOleInPlaceObject = new COleInPlaceObject(this);

m_pOleInPlaceActiveObject = new COleInPlaceActiveObject(this);

m_pPersistStorage = new CPersistStorage(this);

m_pPersistFile = new CPersistFile(this, m_pPersistStorage);

m_pOleDocView = new COleDocumentView(this);

g_DllRefCount++;
}

/**************************************************************************

COleDocument::~COleDocument()

**************************************************************************/

COleDocument::~COleDocument()
{
OutputDebugString(TEXT("COleDocument's destructor\n"));

if(m_pOleAdviseHolder)
m_pOleAdviseHolder->Release();

if(m_pOleClientSite)
m_pOleClientSite->Release();

delete m_pOleDocView;

delete m_pPersistFile;

delete m_pPersistStorage;

delete m_pOleInPlaceActiveObject;

delete m_pOleInPlaceObject;

delete m_pDataObject;

delete m_pOleObject;

g_DllRefCount--;

PostQuitMessage(0);
}

///////////////////////////////////////////////////////////////////////////
//
// IUnknown Implementation
//

/**************************************************************************

COleDocument::QueryInterface

**************************************************************************/

STDMETHODIMP COleDocument::QueryInterface(REFIID riid, LPVOID *ppReturn)
{
OutputDebugString(TEXT("COleDocument::QueryInterface - "));

HRESULT hr = E_NOINTERFACE;
*ppReturn = NULL;

if(riid == IID_IUnknown)
{
*ppReturn = this;
OutputDebugString(TEXT("IUnknown requested - "));
}
else if (riid == IID_IOleDocument)
{
*ppReturn = this;
OutputDebugString(TEXT("IOleDocument requested - "));
}
else if (riid == IID_IOleDocumentView)
{
*ppReturn = m_pOleDocView;
OutputDebugString(TEXT("IOleDocumentView requested - "));
}
else if (riid == IID_IOleObject)
{
*ppReturn = m_pOleObject;
OutputDebugString(TEXT("IOleObject requested - "));
}
else if (riid == IID_IDataObject)
{
*ppReturn = m_pDataObject;
OutputDebugString(TEXT("IDataObject requested - "));
}
else if (riid == IID_IOleInPlaceObject)
{
*ppReturn = m_pOleInPlaceObject;
OutputDebugString(TEXT("IOleInPlaceObject requested - "));
}
else if (riid == IID_IOleInPlaceActiveObject)
{
*ppReturn = m_pOleInPlaceActiveObject;
OutputDebugString(TEXT("IOleInPlaceActiveObject requested - "));
}
else if((riid == IID_IPersistStorage) || (riid == IID_IPersist))
{
*ppReturn = m_pPersistStorage;
OutputDebugString(TEXT("IPersistStorage requested - "));
}
else if(riid == IID_IPersistFile)
{
*ppReturn = m_pPersistFile;
OutputDebugString(TEXT("IPersistFile requested - "));
}

if (*ppReturn)
{
OutputDebugString(TEXT("Interface Found\n"));
((LPUNKNOWN)*ppReturn)->AddRef();
hr = S_OK;
}
else
{
OutputDebugString(TEXT("No Interface - "));

LPWSTR pwsz;
TCHAR szString[MAX_PATH] = TEXT("");

StringFromIID(riid, &pwsz);

if(pwsz)
{
#ifdef UNICODE
lstrcpy(szString, pwsz);
#else
WideCharToMultiByte( CP_ACP,
0,
pwsz,
-1,
szString,
ARRAYSIZE(szString),
NULL,
NULL);
#endif
OutputDebugString(szString);
OutputDebugString(TEXT("\n"));

//free the string
LPMALLOC pMalloc;
CoGetMalloc(1, &pMalloc);
pMalloc->Free(pwsz);
pMalloc->Release();
}
}

return hr;
}

/**************************************************************************

COleDocument::AddRef

**************************************************************************/

STDMETHODIMP_(DWORD) COleDocument::AddRef()
{
//OutputDebugString("COleDocument::AddRef\n");
TCHAR szText[MAX_PATH];
wsprintf(szText, TEXT("COleDocument::AddRef - ref count will be %d\n"), m_ObjRefCount + 1);
OutputDebugString(szText);

return ++m_ObjRefCount;
}


/**************************************************************************

COleDocument::Release

**************************************************************************/

STDMETHODIMP_(DWORD) COleDocument::Release()
{
//OutputDebugString("COleDocument::Release\n");
TCHAR szText[MAX_PATH];
wsprintf(szText, TEXT("COleDocument::Release - ref count will be %d\n"), m_ObjRefCount - 1);
OutputDebugString(szText);

if(0 == --m_ObjRefCount)
{
delete this;
return 0;
}

return m_ObjRefCount;
}

/**************************************************************************

COleDocument::CreateView()

**************************************************************************/

STDMETHODIMP COleDocument::CreateView( IOleInPlaceSite *pInPlaceSite,
IStream *pStream,
DWORD dwReserved,
IOleDocumentView **ppOleDocumentView)
{
OutputDebugString(TEXT("COleDocument::CreateView\n"));

HRESULT hr = E_FAIL;

//NULL the view pointer
*ppOleDocumentView = NULL;

//we only support one view, so fail if the view already exists
if(!m_fCreated)
{
//AddRef since we are giving away the pointer
m_pOleDocView->AddRef();

// if we were given a site, set this as the site for the view we just created
if(pInPlaceSite)
{
m_pOleDocView->SetInPlaceSite(pInPlaceSite);
}

// if given a stream to initialize from, initialize our view state
if(pStream)
{
m_pOleDocView->ApplyViewState(pStream);
}

*ppOleDocumentView = m_pOleDocView;

m_fCreated = TRUE;

hr = S_OK;
}

return hr;
}

/**************************************************************************

COleDocument::GetDocMiscStatus()

**************************************************************************/

STDMETHODIMP COleDocument::GetDocMiscStatus(DWORD *pdwStatus)
{
OutputDebugString(TEXT("COleDocument::GetDocMiscStatus\n"));

if(!pdwStatus)
return E_INVALIDARG;

*pdwStatus = 0;

return S_OK;
}

/**************************************************************************

COleDocument::EnumViews()

**************************************************************************/

STDMETHODIMP COleDocument::EnumViews( IEnumOleDocumentViews **ppEnum,
IOleDocumentView **ppView)
{
OutputDebugString(TEXT("COleDocument::EnumViews\n"));

*ppEnum = NULL;
*ppView = NULL;

return E_NOTIMPL;
}

/**************************************************************************

COleDocument::GetWindow()

**************************************************************************/

STDMETHODIMP COleDocument::GetWindow(HWND *phwnd)
{
OutputDebugString(TEXT("COleDocument::GetWindow\n"));

if(!phwnd)
return E_INVALIDARG;

*phwnd = NULL;

if(m_pOleDocView)
*phwnd = m_pOleDocView->m_hwndView;

return S_OK;
}

/**************************************************************************

COleDocument::UIDeactivate()

**************************************************************************/

STDMETHODIMP COleDocument::DeactivateUI()
{
OutputDebugString(TEXT("COleInPlaceObject::DeactivateUI\n"));

if(m_pOleDocView)
return m_pOleDocView->DeactivateUI();

return E_FAIL;
}

/**************************************************************************

COleDocumentView::DeactivateInPlace()

**************************************************************************/

STDMETHODIMP COleDocument::DeactivateInPlace()
{
OutputDebugString(TEXT("COleDocument::DeactivateInPlace\n"));

if(m_pOleDocView)
return m_pOleDocView->DeactivateInPlace();

return E_FAIL;
}

/**************************************************************************

COleDocument::RegisterServer

**************************************************************************/

typedef struct{
HKEY hRootKey;
TCHAR szSubKey[MAX_PATH];
TCHAR szValue[MAX_PATH];
}DOREGSTRUCT, *LPDOREGSTRUCT;

BOOL COleDocument::RegisterServer(void)
{
OutputDebugString("COleDocument::RegisterServer\n");

int i;
HKEY hKey;
LRESULT lResult;
DWORD dwDisp;
TCHAR szSubKey[MAX_PATH];
TCHAR szCLSID[MAX_PATH];
TCHAR szApp[MAX_PATH];
LPWSTR pwsz;
CLSID clsid;

//get this app's CLSID in string form
m_pPersistStorage->GetClassID(&clsid);
StringFromIID(clsid, &pwsz);

if(pwsz)
{
#ifdef UNICODE
lstrcpy(szCLSID, pwsz);
#else
WideCharToMultiByte( CP_ACP,
0,
pwsz,
-1,
szCLSID,
ARRAYSIZE(szCLSID),
NULL,
NULL);
#endif

//free the string
LPMALLOC pMalloc;
CoGetMalloc(1, &pMalloc);
pMalloc->Free(pwsz);
pMalloc->Release();
}

//get this app's path and file name
GetModuleFileName(NULL, szApp, ARRAYSIZE(szApp));

//register the file extension entries
{
DOREGSTRUCT FileEntries[] = { HKEY_CLASSES_ROOT, TEXT("%s"), PROG_ID,
0, TEXT(""), TEXT("")};

for(i = 0; FileEntries[i].hRootKey; i++)
{
//create the sub key string - for this case, insert the file extension
wsprintf(szSubKey, FileEntries[i].szSubKey, FILE_EXT);

lResult = RegCreateKeyEx( FileEntries[i].hRootKey,
szSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisp);

if(NOERROR == lResult)
{
lResult = RegSetValueEx( hKey,
NULL,
0,
REG_SZ,
(LPBYTE)FileEntries[i].szValue,
lstrlen(FileEntries[i].szValue) + 1);

RegCloseKey(hKey);
}
else
return FALSE;
}
}

{
DOREGSTRUCT ProgEntries[] = { HKEY_CLASSES_ROOT, TEXT("%s"), DOC_NAME,
HKEY_CLASSES_ROOT, TEXT("%s\\CLSID"), TEXT("%s"),
HKEY_CLASSES_ROOT, TEXT("%s\\DocObject"), TEXT(""),
0, TEXT(""), TEXT("")};

//register the ProgID entries
for(i = 0; ProgEntries[i].hRootKey; i++)
{
//create the sub key string - for this case, insert the ProgID
wsprintf(szSubKey, ProgEntries[i].szSubKey, PROG_ID);

lResult = RegCreateKeyEx( ProgEntries[i].hRootKey,
szSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisp);

if(NOERROR == lResult)
{
TCHAR szValue[MAX_PATH];

//if necessary, create the value string
wsprintf(szValue, ProgEntries[i].szValue, szCLSID);

lResult = RegSetValueEx( hKey,
NULL,
0,
REG_SZ,
(LPBYTE)szValue,
lstrlen(szValue) + 1);

RegCloseKey(hKey);
}
else
return FALSE;
}
}

{
DOREGSTRUCT ClsidEntries[] = {HKEY_CLASSES_ROOT, TEXT("CLSID\\%s"), DOC_NAME,
HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\LocalServer32"), TEXT("%s"),
HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\InprocHandler32"), TEXT("ole32.dll"),
HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\DefaultIcon"), TEXT("%s,0"),
HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\DocObject"), TEXT("0"),
HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\ProgID"), PROG_ID,
0, TEXT(""), TEXT("")};

//register the CLSID entries
for(i = 0; ClsidEntries[i].hRootKey; i++)
{
//create the sub key string - for this case, insert the file extension
wsprintf(szSubKey, ClsidEntries[i].szSubKey, szCLSID);

lResult = RegCreateKeyEx( ClsidEntries[i].hRootKey,
szSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisp);

if(NOERROR == lResult)
{
TCHAR szValue[MAX_PATH];

//if necessary, create the value string
wsprintf(szValue, ClsidEntries[i].szValue, szApp);

lResult = RegSetValueEx( hKey,
NULL,
0,
REG_SZ,
(LPBYTE)szValue,
lstrlen(szValue) + 1);

RegCloseKey(hKey);
}
else
return FALSE;
}
}

//register the component as insertable and a document object
ICatRegister *pcr;
HRESULT hr = S_OK ;

CoInitialize(NULL);

hr = CoCreateInstance( CLSID_StdComponentCategoriesMgr,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICatRegister,
(LPVOID*)&pcr);

if(SUCCEEDED(hr))
{
CATID rgcatid[2];

rgcatid[0] = CATID_Insertable;
rgcatid[1] = CATID_DocObject;

hr = pcr->RegisterClassImplCategories(clsid, 2, rgcatid);

pcr->Release();
}

CoUninitialize();

return SUCCEEDED(hr);
}

/**************************************************************************

COleDocument::CreateFile(HWND)

**************************************************************************/

BOOL COleDocument::CreateFile(HWND hwndParent)
{
OutputDebugString("COleDocument::CreateFile(HWND)\n");

OPENFILENAME ofn;
TCHAR szFilter[MAX_PATH];
TCHAR szFile[MAX_PATH] = TEXT("");
LPTSTR pTemp;

//build the filter string
pTemp = szFilter;
lstrcpy(pTemp, DOC_NAME);
pTemp += lstrlen(pTemp) + 1;
lstrcpy(pTemp, TEXT("*"));
lstrcat(pTemp, FILE_EXT);
pTemp += lstrlen(pTemp) + 1;
*pTemp = 0;

ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwndParent;
ofn.hInstance = g_hInst;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFile;
ofn.nMaxFile = ARRAYSIZE(szFile);
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.lpTemplateName = MAKEINTRESOURCE(IDD_COLOR_DIALOG);
ofn.lpfnHook = (LPOFNHOOKPROC)ColorHookProc;
ofn.lCustData = (DWORD)this;
ofn.Flags = OFN_EXPLORER |
OFN_OVERWRITEPROMPT |
OFN_HIDEREADONLY |
OFN_ENABLEHOOK |
OFN_ENABLETEMPLATE |
0;

if(GetSaveFileName(&ofn))
{
//if the extension isn't attached, attach it
pTemp = szFile + lstrlen(szFile) - 4;
if(lstrcmpi(pTemp, FILE_EXT))
{
lstrcat(szFile, FILE_EXT);
}

return CreateFile(szFile);
}

return FALSE;
}


/**************************************************************************

COleDocument::CreateFile(LPTSTR)

**************************************************************************/

BOOL COleDocument::CreateFile(LPTSTR pszFile)
{
OutputDebugString("COleDocument::CreateFile(LPTSTR)\n");

WCHAR szwFile[MAX_PATH];

#ifdef UNICODE
lstrcpy(szwFile, pszFile);
#else
MultiByteToWideChar( CP_ACP,
MB_PRECOMPOSED,
pszFile,
-1,
szwFile,
ARRAYSIZE(szwFile));
#endif

m_pPersistFile->Save(szwFile, FALSE);

return TRUE;
}