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; 
}