/*************************************************************************/ /* Copyright (C) 1999 Microsoft Corporation */ /* File: CCObj.cpp */ /* Description: Contains holder for container objects. */ /*************************************************************************/ #include "stdafx.h" #include "ccobj.h" #define GET_SITE CComPtr pSite; \ HRESULT hr = GetWindowlessSite(pSite); \ if(FAILED(hr)) return(hr); #define GET_CONTAINER CComPtr pContainer; \ HRESULT hr = GetContainer(pContainer); \ if(FAILED(hr)) return(hr); /*************************************************************************/ /* Function: CContainerObject */ /* Description: Constructor that should set needed objects. */ /*************************************************************************/ CContainerObject::CContainerObject(IUnknown* pUnknown, CHostedObject* pObj){ Init(); SetObjects(pUnknown, pObj); }/* end of function CContainerObject */ /*************************************************************************/ /* Function: SetObjects */ /* Description: Sets the internal objects. */ /*************************************************************************/ HRESULT CContainerObject::SetObjects(IUnknown* pUnknown, CHostedObject* pObj){ m_pUnkContainer = pUnknown; m_pObj = pObj; return(S_OK); }/* end of function SetObjects */ /*************************************************************************/ /* Function: Init */ /* Description: Initializes the member variables */ /*************************************************************************/ void CContainerObject::Init(){ //m_pUnkContainer = NULL; // using smart pointer m_pObj = NULL; m_lRefCount = 1; m_bLocked = 0; }/* end of function Init */ /*************************************************************************/ /* Function: QueryInterface */ /* Description: Gets the supported interface rest sends to the aggregated*/ /* object */ /*************************************************************************/ STDMETHODIMP CContainerObject::QueryInterface(const IID& iid, void**ppv){ if(iid == IID_IUnknown){ *ppv = static_cast(this); } else if(iid == IID_IOleInPlaceSiteWindowless){ *ppv = static_cast(this); } else if(iid == IID_IOleInPlaceSiteEx){ *ppv = static_cast(this); } else if(iid == IID_IOleClientSite){ *ppv = static_cast(this); } else if(iid == IID_IOleContainer){ *ppv = static_cast(this); } else if(iid == IID_IOleInPlaceSite){ *ppv = static_cast(this); } else if(iid == IID_IObjectWithSite){ *ppv = static_cast(this); } else if(iid == IID_IPropertyBag){ *ppv = static_cast(this); } // TODO: Not Right way to agregate // this breaks the rules since we really do not // have non delegating object there else { // blindly aggregate if(!m_pUnkContainer){ *ppv = NULL; return (E_NOINTERFACE); }/* end of if statement */ return(m_pUnkContainer->QueryInterface(iid, ppv)); }/* end of if statement */ reinterpret_cast(*ppv)->AddRef(); return(S_OK); }/* end of function QueryInterface */ /*************************************************************************/ /* Function: AddRef */ /* Description: Adds the reference count. */ /*************************************************************************/ STDMETHODIMP_(ULONG) CContainerObject::AddRef ( void){ return(InterlockedIncrement(&m_lRefCount)); }/* end of function AddRef */ /*************************************************************************/ /* Function: Release */ /* Description: Decrements the reference count and the possibly releases */ /*************************************************************************/ STDMETHODIMP_(ULONG) CContainerObject::Release( void){ if(InterlockedIncrement(&m_lRefCount) <=0){ delete this; return 0; }/* end of if statement */ return (m_lRefCount); }/* end of function Release */ /*************************************************************************/ /* Helper functions */ /*************************************************************************/ /*************************************************************************/ /* Function: GetWindowlessSite */ /* Description: Returns an interface for windowless site. */ /*************************************************************************/ inline HRESULT CContainerObject::GetWindowlessSite(CComPtr& pSite){ if(!m_pUnkContainer){ return(E_UNEXPECTED); }/* end of if statement */ return(m_pUnkContainer->QueryInterface(&pSite)); }/* end of function GetWindowlessSite */ /*************************************************************************/ /* Function: GetContainer */ /* Description: Returns an interface for windowless site. */ /*************************************************************************/ inline HRESULT CContainerObject::GetContainer(CComPtr& pContainer){ if(!m_pUnkContainer){ return(E_UNEXPECTED); }/* end of if statement */ return(m_pUnkContainer->QueryInterface(&pContainer)); }/* end of function GetContainer */ /*************************************************************************/ /* IOleContainer Implementation */ /*************************************************************************/ /*************************************************************************/ /* Function: ParseDisplayName */ /*************************************************************************/ STDMETHODIMP CContainerObject::ParseDisplayName(IBindCtx* /*pbc*/, LPOLESTR /*pszDisplayName*/, ULONG* /*pchEaten*/, IMoniker** /*ppmkOut*/){ ATLTRACENOTIMPL(_T("IOleClientSite::ParseDisplayName")); }/* end of function ParseDisplayName */ /*************************************************************************/ /* Function: EnumObjects */ /*************************************************************************/ STDMETHODIMP CContainerObject::EnumObjects(DWORD grfFlags, IEnumUnknown** ppenum){ GET_CONTAINER return(pContainer->EnumObjects(grfFlags, ppenum)); }/* end of function EnumObjects */ /*************************************************************************/ /* Function: LockContainer */ /* Description: Sets the container locked so it does not go away. */ /*************************************************************************/ STDMETHODIMP CContainerObject::LockContainer(BOOL fLock){ // TODO: Actually do use the m_bLocked flag m_bLocked = fLock; return S_OK; }/* end of function LockContainer */ /*************************************************************************/ /* IOleClientSite Implementation */ /*************************************************************************/ /*************************************************************************/ /* Function: GetContainer */ /* Description: Basically returns our self */ /*************************************************************************/ STDMETHODIMP CContainerObject::GetContainer(IOleContainer** ppContainer){ ATLTRACE2(atlTraceHosting, 0, _T("IOleClientSite::GetContainer\n")); HRESULT hr = E_POINTER; if (NULL == ppContainer){ return(hr); }/* end of if statement */ if (m_pUnkContainer){ (*ppContainer) = NULL; hr = QueryInterface(IID_IOleContainer, (void**)ppContainer); // return our selfs }/* end of if statement */ return hr; }/* end of function GetContainer */ /*************************************************************************/ /* Function: ShowObject */ /* Description: Redraws the object. */ /*************************************************************************/ STDMETHODIMP CContainerObject::ShowObject(){ HRESULT hr = S_OK; ATLTRACE2(atlTraceHosting, 0, _T("IOleClientSite::ShowObject\r\n")); if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ hr = InvalidateObjectRect(); return (hr); }/* end of function ShowObject */ /*************************************************************************/ /* Function: OnShowWindow */ /* Description: Shows or hides the window. If no window to show or hide */ /* we deactivate it. */ /*************************************************************************/ STDMETHODIMP CContainerObject::OnShowWindow(BOOL fShow){ HRESULT hr = S_OK; if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ hr = m_pObj->SetActive(fShow ? true: false); return(hr); }/* end of function OnShowWindow */ /*************************************************************************/ /* IOleInPlaceSiteEx Implementation */ /* Just pass throw in most cases, in some do some extra house keeping */ /* since we know which object we are containing. */ /*************************************************************************/ // IOleWindow /*************************************************************************/ /* Function: GetWindow */ /*************************************************************************/ STDMETHODIMP CContainerObject::GetWindow(HWND *phwnd){ GET_SITE return(pSite->GetWindow(phwnd)); }/* end of function GetWindow */ /*************************************************************************/ /* Function: ContextSensitiveHelp */ /*************************************************************************/ STDMETHODIMP CContainerObject::ContextSensitiveHelp(BOOL fEnterMode){ GET_SITE return(pSite->ContextSensitiveHelp(fEnterMode)); }/* end of function ContextSensitiveHelp */ //IOleInPlaceSite /*************************************************************************/ /* Function: CanInPlaceActivate */ /*************************************************************************/ STDMETHODIMP CContainerObject::CanInPlaceActivate(){ GET_SITE return(pSite->CanInPlaceActivate()); }/* end of function CanInPlaceActivate */ /*************************************************************************/ /* Function: OnUIActivate */ /*************************************************************************/ STDMETHODIMP CContainerObject::OnUIActivate(){ GET_SITE return(pSite->OnUIActivate()); }/* end of function OnUIActivate */ /*************************************************************************/ /* Function: OnInPlaceActivate */ /* Description: Activates non windowless object. */ /*************************************************************************/ STDMETHODIMP CContainerObject::OnInPlaceActivate(){ ATLTRACE(TEXT("CContainerObject::OnInPlaceActivate \n")); HRESULT hr = E_FAIL; if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ CComPtr pUnk = m_pObj->GetUnknown(); // get the control object that is being inserted if(!pUnk){ return(E_UNEXPECTED); }/* end of if statement */ //OleLockRunning(pUnk, TRUE, FALSE); // not sure if needed here m_pObj->SetWindowless(false); //m_pObj->SetActive(true); return(hr); }/* end of function OnInPlaceActivate */ /*************************************************************************/ /* Function: OnUIDeactivate */ /* Description: Deactivates the object. */ /*************************************************************************/ STDMETHODIMP CContainerObject::OnUIDeactivate(BOOL fUndoable){ HRESULT hr = S_OK; if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ m_pObj->SetActive(false); ATLTRACE(TEXT("TODO: In the deactivation code, time to cleanup the contained object!!! \n")); return(hr); }/* end of function OnUIDeactivate */ /*************************************************************************/ /* Function: OnInPlaceDeactivate */ /* Description: Deactivates the object. */ /*************************************************************************/ STDMETHODIMP CContainerObject::OnInPlaceDeactivate(){ HRESULT hr = S_OK; if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ m_pObj->SetActive(false); ATLTRACE(TEXT("TODO: In the deactivation code, time to cleanup the contained object!!! \n")); return(hr); }/* end of function OnInPlaceDeactivate */ /*************************************************************************/ /* Function: DiscardUndoState */ /*************************************************************************/ STDMETHODIMP CContainerObject::DiscardUndoState(){ GET_SITE return(pSite->DiscardUndoState()); }/* end of function DiscardUndoState */ /*************************************************************************/ /* Function: DeactivateAndUndo */ /*************************************************************************/ STDMETHODIMP CContainerObject::DeactivateAndUndo(){ GET_SITE return(pSite->DeactivateAndUndo()); // TODO: Handle specific container }/* end of function DeactivateAndUndo */ /*************************************************************************/ /* Function: OnPosRectChange */ /*************************************************************************/ STDMETHODIMP CContainerObject::OnPosRectChange(LPCRECT lprcPosRect){ GET_SITE return(pSite->OnPosRectChange(lprcPosRect)); // TODO: Handle specific container }/* end of function OnPosRectChange */ /*************************************************************************/ /* Function: Scroll */ /*************************************************************************/ STDMETHODIMP CContainerObject::Scroll(SIZE scrollExtent){ GET_SITE return(pSite->Scroll(scrollExtent)); // TODO: Handle specific container }/* end of function OnPosRectChange */ /*************************************************************************/ /* Function: GetWindowContext */ /* Description: Finish this function to be container specific. */ /*************************************************************************/ STDMETHODIMP CContainerObject::GetWindowContext(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo){ HRESULT hr = S_OK; if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL || lprcClipRect == NULL){ hr = E_POINTER; return(hr); }/* end of if statement */ if (!m_spInPlaceFrame){ //CComObject* pFrameWindow; //CComObject::CreateInstance(&pFrameWindow); // ?? MODS DJ QueryInterface(IID_IOleInPlaceFrame, (void**) &m_spInPlaceFrame); ATLASSERT(m_spInPlaceFrame); }/* end of if statement */ if (!m_spInPlaceUIWindow){ // ?? MODS DJ //CComObject* pUIWindow; //CComObject::CreateInstance(&pUIWindow); QueryInterface(IID_IOleInPlaceUIWindow, (void**) &m_spInPlaceUIWindow); ATLASSERT(m_spInPlaceUIWindow); }/* end of if statement */ m_spInPlaceFrame.CopyTo(ppFrame); m_spInPlaceUIWindow.CopyTo(ppDoc); RECT rc; hr = m_pObj->GetPos(&rc); if(FAILED(hr)){ return(hr); }/* end of if statement */ *lprcPosRect = rc; *lprcClipRect = rc; HWND hwnd; hr = GetWindow(&hwnd); if(FAILED(hr)){ hr = S_FALSE; //return(hr); }/* end of if statement */ HWND hParent = NULL; if(NULL != hwnd){ hParent = ::GetParent(hwnd); }/* end of function GetParent */ ACCEL ac = { 0,0,0 }; HACCEL hac = ::CreateAcceleratorTable(&ac, 1); pFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO); pFrameInfo->fMDIApp = 0; pFrameInfo->hwndFrame = hParent; pFrameInfo->haccel = hac; pFrameInfo->cAccelEntries = 1; return hr; }/* end of function GetWindowContext */ /*************************************************************************/ /* Function: GetSite */ /* Description: Returns pretty much QI, client sets the site and then */ /* container is using it. */ /*************************************************************************/ STDMETHODIMP CContainerObject::GetSite(REFIID riid, void **ppvSite){ return(QueryInterface(riid, ppvSite)); }/* end of function GetSite */ //IOleInPlaceSiteEx /*************************************************************************/ /* Function: OnInPlaceActivateEx */ /* Description: Checks what way we shall instantiate the control. */ /*************************************************************************/ STDMETHODIMP CContainerObject::OnInPlaceActivateEx(BOOL* /*pfNoRedraw*/, DWORD dwFlags){ HRESULT hr = E_FAIL; if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ CComPtr pUnk = m_pObj->GetUnknown(); // get the control object that is being inserted if(!pUnk){ return(E_UNEXPECTED); }/* end of if statement */ OleLockRunning(pUnk, TRUE, FALSE); CComPtr spInPlaceObjectWindowless; bool bWindowless = false; if (dwFlags & ACTIVATE_WINDOWLESS){ m_pObj->SetWindowless(true); hr = pUnk->QueryInterface(IID_IOleInPlaceObjectWindowless,(void**) &spInPlaceObjectWindowless); }/* end of if statement */ if (FAILED(hr)){ m_pObj->SetWindowless(false); hr = pUnk->QueryInterface(IID_IOleInPlaceObject, (void**) &spInPlaceObjectWindowless); }/* end of if statement */ if (SUCCEEDED(hr)){ RECT rcPos; hr = m_pObj->GetPos(&rcPos); if (FAILED(hr)){ return(hr); }/* end of if statement */ if(m_pObj->IsWindowless()){ spInPlaceObjectWindowless->SetObjectRects(&rcPos, &rcPos); ATLTRACE(TEXT("Windowless object is contained object with ID %ls Rect left = %d top %d right %d bottom %d\n"), m_pObj->GetID(), rcPos.left, rcPos.top, rcPos.right, rcPos.bottom); }/* end of if statement */ }/* end of if statement */ //m_pObj->SetActive(true); return S_OK; }/* end of function OnInPlaceActivateEx */ /*************************************************************************/ /* Function: OnInPlaceDeactivateEx */ /* Description: Deactivates the object. */ /*************************************************************************/ STDMETHODIMP CContainerObject::OnInPlaceDeactivateEx(BOOL fNoRedraw){ HRESULT hr = S_OK; if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ m_pObj->SetActive(false); ATLTRACE(TEXT("TODO: In the deactivation code, time to cleanup the contained object!!! \n")); return(hr); }/* end of function OnInPlaceDeactivateEx */ /*************************************************************************/ /* Function: RequestUIActivate */ /*************************************************************************/ STDMETHODIMP CContainerObject::RequestUIActivate(){ GET_SITE return(pSite->RequestUIActivate()); }/* end of function RequestUIActivate */ /*************************************************************************/ /* Function: CanWindowlessActivate */ /*************************************************************************/ STDMETHODIMP CContainerObject::CanWindowlessActivate(){ GET_SITE return(pSite->CanWindowlessActivate()); }/* end of function CanWindowlessActivate */ /*************************************************************************/ /* Function: GetDC */ /*************************************************************************/ STDMETHODIMP CContainerObject::GetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC){ GET_SITE return(pSite->GetDC(pRect, grfFlags, phDC)); }/* end of function GetDC */ /*************************************************************************/ /* Function: ReleaseDC */ /*************************************************************************/ STDMETHODIMP CContainerObject::ReleaseDC(HDC hDC){ GET_SITE return(pSite->ReleaseDC(hDC)); }/* end of function ReleaseDC */ /*************************************************************************/ /* Function: InvalidateRect */ /*************************************************************************/ STDMETHODIMP CContainerObject::InvalidateRect(LPCRECT pRect, BOOL fErase){ GET_SITE return(pSite->InvalidateRect(pRect, fErase)); }/* end of function InvalidateRect */ /*************************************************************************/ /* Function: InvalidateObjectRect */ /* Description: Invalidates the whole control. */ /*************************************************************************/ HRESULT CContainerObject::InvalidateObjectRect(){ HRESULT hr = S_OK; if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ RECT rc; hr = m_pObj->GetPos(&rc); if(FAILED(hr)){ return(hr); }/* end of if statement */ hr = InvalidateRect(&rc, FALSE); // invalidate the region instead // of drawing the object directly return(hr); }/* end of function InvalidateRect */ /*************************************************************************/ /* Function: InvalidateRgn */ /*************************************************************************/ STDMETHODIMP CContainerObject::InvalidateRgn(HRGN hRGN, BOOL fErase){ GET_SITE return(pSite->InvalidateRgn(hRGN, fErase)); }/* end of function InvalidateRgn */ /*************************************************************************/ /* Function: ScrollRect */ /*************************************************************************/ STDMETHODIMP CContainerObject::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip){ GET_SITE return(pSite->ScrollRect(dx, dy, pRectScroll, pRectClip)); }/* end of function ScrollRect */ /*************************************************************************/ /* Function: AdjustRect */ /*************************************************************************/ STDMETHODIMP CContainerObject::AdjustRect(LPRECT prc){ GET_SITE return(pSite->AdjustRect(prc)); }/* end of function AdjustRect */ /*************************************************************************/ /* Function: OnDefWindowMessage */ /*************************************************************************/ STDMETHODIMP CContainerObject::OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult){ GET_SITE return(pSite->OnDefWindowMessage(msg, wParam, lParam, plResult)); }/* end of function OnDefWindowMessage */ /*************************************************************************/ /* Function: GetCapture */ /* Description: Used to determine if we have a cupature or not */ /*************************************************************************/ STDMETHODIMP CContainerObject::GetCapture(){ GET_SITE if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ hr = pSite->GetCapture(); if(SUCCEEDED(hr)){ // we checked with the container if we // have a capture if(m_pObj->HasCapture() == false){ hr = S_FALSE; } else { if(hr == S_FALSE){ // case when the container say we do not have // the capture any more // but the object thinks it has a capture // we better reset the flag m_pObj->SetCapture(false); // and say that we do not have capture hr = S_FALSE; }/* end of if statement */ }/* end of if statement */ }/* end of if statement */ return(hr); }/* end of function GetCapture */ /*************************************************************************/ /* Function: SetCapture */ /* Description: Used to set the capture for mouse events */ /*************************************************************************/ STDMETHODIMP CContainerObject::SetCapture(BOOL fCapture){ GET_SITE if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ if(fCapture && !m_pObj->IsActive()){ hr = S_FALSE; return(hr); }/* end of if statement */ if(m_pObj->HasCapture() == (fCapture ? true: false)){ hr = S_FALSE; return(hr); }/* end of if statement */ // Call our "real" container object for count keeping // and signaling to its window or another container hr = pSite->SetCapture(fCapture); if(SUCCEEDED(hr)){ m_pObj->SetCapture(fCapture? true: false); // set the capture on the object }/* end of if statement */ return (hr); }/* end of function SetCapture */ /*************************************************************************/ /* Function: GetFocus */ /* Description: Determine if we have a focus or not. */ /*************************************************************************/ STDMETHODIMP CContainerObject::GetFocus(){ GET_SITE if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ hr = pSite->GetFocus(); if(SUCCEEDED(hr)){ if(m_pObj->HasFocus() == false){ hr = S_FALSE; } else { if(S_FALSE == hr){ m_pObj->SetFocus(false); hr = S_FALSE; }/* end of if statement */ }/* end of if statement */ }/* end of if statement */ return(hr); }/* end of function GetFocus */ /*************************************************************************/ /* Function: SetFocus */ /* Description: Sets focus to the control */ /*************************************************************************/ STDMETHODIMP CContainerObject::SetFocus(BOOL fFocus){ GET_SITE if(NULL == m_pObj){ hr = E_UNEXPECTED; return(hr); }/* end of if statement */ if(fFocus && !m_pObj->IsActive()){ // can't set focus to not active objects // but can take away focus from non active ones hr = S_FALSE; return(hr); }/* end of if statement */ if(m_pObj->HasFocus() == (fFocus ? true: false)){ // we are not chaning focus state so do not bother calling container hr = S_FALSE; return(hr); }/* end of if statement */ // Call our "real" container object for count keeping // and signaling to its window or another container hr = pSite->SetFocus(fFocus); if(SUCCEEDED(hr)){ m_pObj->SetFocus(fFocus ? true: false); // set the capture on the object }/* end of if statement */ InvalidateObjectRect(); return (hr); }/* end of function SetFocus */ /*************************************************************************/ /* Function: SetHostedObject */ /* Description: Sets the control that we are hosting. */ /*************************************************************************/ STDMETHODIMP CContainerObject::SetHostedObject(LONG lVoid){ // TODO!!! // THIS WILL BREAK ON WIN64 // NEED TO PASS REAL INTERFACE AROUND HRESULT hr = S_OK; try { m_pObj = reinterpret_cast(lVoid); } catch(...){ hr = E_UNEXPECTED; }/* end of catch statement */ return (hr); }/* end of function SetHostedObject */ /*************************************************************************/ /* IPropertyBag */ /*************************************************************************/ /*************************************************************************/ /* Function: Read */ /* Description: Reads a specific control property from a bag. */ /* The bag looks like IE compatible */ /*************************************************************************/ STDMETHODIMP CContainerObject::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog){ HRESULT hr = S_OK; try { ATLTRACE2(atlTraceHosting, 0, _T("IPropertyBag::Read\r\n")); if(NULL == m_pObj){ throw(E_UNEXPECTED); }/* end of if statement */ if (NULL == pVar){ throw(E_POINTER); }/* end of if statement */ hr = ParsePropertyBag(pszPropName, pVar, pErrorLog); } catch(...){ hr = E_UNEXPECTED; }/* end of catch statement */ return (hr); }/* end of function Read */ /*************************************************************************/ /* Function: MyIsWhiteSpace */ /* Local function implementation, since we do not have standart C lib */ /* support */ /*************************************************************************/ static bool MyIsWhiteSpace( WCHAR c ){ return c == L' ' || c == L'\t' || c == L'\r' || c == L'\n'; }/* end of function MyIsWhiteSpace */ /*************************************************************************/ /* Function: MyStrToDouble */ /* Description: Reads in string and converts it to double */ /* Returns E_INVALIDARG if there is alpah or some other undesired string*/ /* S_OK if we got some string, S_FALSE if no number string (empty or spac*/ /*************************************************************************/ static HRESULT MyStrToDouble(WCHAR* pstr, double &n) { HRESULT hr = S_FALSE; int Sign = 1; n = 0; // result wil be n*Sign bool bBeforeDecimalPoint = true; double k = 10; // eat whitespace at start while( *pstr != L'\n' && MyIsWhiteSpace( *pstr ) ) { pstr++; } while( pstr[lstrlenW(pstr)-1]!= L'\n' && MyIsWhiteSpace( *pstr ) ) { pstr[lstrlenW(pstr)-1] = L'\0'; } //lstrcmpiW is not implemented on 98 need to use STDLIB // TODO: eventaully replace the below _wcsicmp with our own so we can remove support // on standard C library if (_wcsicmp(pstr, L"true") == 0) { n = -1; return S_OK; } if (_wcsicmp(pstr, L"false") == 0) { n = 0; return S_OK; } if (pstr[0]==L'-'){ Sign = -1; ++pstr; }/* end of if statement */ for( ; ; ) { if (pstr[0]>=L'0' && pstr[0]<=L'9') { if(bBeforeDecimalPoint == true){ n = 10*n+(int)(pstr[0]-L'0'); } else { n = n+ ((int)(pstr[0]-L'0'))/k; k = k * 10; // decrease the decimal point }/* end of if statement */ hr = S_OK; } else if ( MyIsWhiteSpace( pstr[0] ) || pstr[0] == L'\0' ) { break; } else if( bBeforeDecimalPoint && pstr[0] == L'.') { bBeforeDecimalPoint = false; } else { hr = E_INVALIDARG; break; }/* end of if statement */ ++pstr; }/* end of for loop */ n *= Sign; // adjust the sign return(hr); }/* end of function MyStrToDouble */ /*************************************************************************/ /* Function: CompSubstr */ /* Description: ComaparesSubstr, eats up whithe spaces. */ /*************************************************************************/ HRESULT CompSubstr(WCHAR*& strSource, const WCHAR* strKey){ bool bEatSpaces = true; register WCHAR wcKey = *strKey; register WCHAR wcSrc = *strSource; for(INT i = 0; wcKey != NULL; wcSrc = *(++strSource)){ if(bEatSpaces){ // eat up the spaces and tabs and enters and cr if(MyIsWhiteSpace(wcSrc)){ continue; } else { bEatSpaces = false; }/* end of if statement */ }/* end of if statement */ if(wcKey != wcSrc){ return(E_FAIL); }/* end of if statement */ if(NULL == wcSrc){ return(E_FAIL); // ran out of space in the source string }/* end of if statement */ wcKey = strKey[++i]; // advance the key }/* end of for loop */ return(S_OK); }/* end of function CompSubstr */ /*************************************************************************/ /* Function: ParsePropertyBag */ /* Description: Retrives a property from the bag and puts it into variant*/ /* if it fails returns E_FAIL. */ /*************************************************************************/ HRESULT CContainerObject::ParsePropertyBag(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* /* pErrorLog */){ HRESULT hr = S_OK; try { BSTR strBag = m_pObj->GetPropBag(); if(NULL == strBag){ throw(E_FAIL); }/* end of if statement */ WCHAR* strValue = NULL; // the place where we are going to stick the actuall value // before putting it into variant WCHAR* strTmpValue = L""; WCHAR* strTmpBag = strBag; if(NULL == *strTmpBag){ throw(E_FAIL); }/* end of if statement */ INT iState = 0; // 0 start bool fFound = false; bool fFinished = false; INT iLength = 0; // noting the start and end of the value string // now try to parse out the value for the appropriate string for(INT i = 0; NULL != *strTmpBag && !fFinished; i++){ switch(iState){ case 0: // looking for start < if(FAILED(CompSubstr(strTmpBag, L"<"))) return (E_FAIL); iState = 1; break; case 1: // PARAM if(FAILED(CompSubstr(strTmpBag, L"PARAM"))) return (E_FAIL); iState = 2; break; case 2: // NAME if(FAILED(CompSubstr(strTmpBag, L"NAME"))) return (E_FAIL); iState = 3; break; case 3: // = if(FAILED(CompSubstr(strTmpBag, L"="))) return (E_FAIL); iState = 4; break; case 4: // " if(FAILED(CompSubstr(strTmpBag, L"\""))) return (E_FAIL); iState = 5; break; case 5: // pszPropName (the actual name) if(SUCCEEDED(CompSubstr(strTmpBag, pszPropName))){ fFound = true; // found the PropName }/* end of if statement */ iState = 6; break; case 6: // " if(SUCCEEDED(CompSubstr(strTmpBag, L"\""))){ iState = 7; } else { strTmpBag++; }/* end of if statement */ break; case 7: // VALUE if(FAILED(CompSubstr(strTmpBag, L"VALUE"))) return (E_FAIL); iState = 8; break; case 8: // = if(FAILED(CompSubstr(strTmpBag, L"="))) return (E_FAIL); iState = 9; break; case 9: // " if(FAILED(CompSubstr(strTmpBag, L"\""))) return (E_FAIL); iState = 10; break; case 10: // VALUE if(fFound){ // read up the string and exit the loop strTmpValue = strTmpBag; }/* end of if statement */ iState = 11; break; case 11: // " if(SUCCEEDED(CompSubstr(strTmpBag, L"\""))){ iState = 12; if(fFound){ iLength = strTmpBag - strTmpValue; strValue = new WCHAR[iLength]; memcpy(strValue, strTmpValue, iLength * sizeof(WCHAR)); strValue[iLength - 1] = NULL; // read up the string and exit the loop fFinished = true; // exit the loop }/* end of if statement */ } else { strTmpBag++; }/* end of if statement */ break; case 12: // closing brakcet > if(FAILED(CompSubstr(strTmpBag, L">"))) return (E_FAIL); iState = 0; break; }/* end of switch statement */ }/* end of for loop */ if(!fFinished){ return(E_FAIL); }/* end of if statement */ // at this moment we have value parsed out switch(pVar->vt){ case VT_BSTR: pVar->bstrVal = ::SysAllocString(strValue); break; case VT_I4: { double dbl; if(MyStrToDouble(strValue, dbl) != S_OK){ // S_FALSE denotes empty string throw(E_FAIL); }/* end of if statement */ // TODO: Create MyStrToInt and do not cast pVar->lVal = (INT)dbl; } case VT_UI4:{ double dbl; if(MyStrToDouble(strValue, dbl) != S_OK){ // S_FALSE denotes empty string throw(E_FAIL); }/* end of if statement */ // TODO: Create MyStrToInt and do not cast pVar->ulVal = (ULONG)dbl; } break; case VT_R4: { double dbl; if(MyStrToDouble(strValue, dbl) != S_OK){ // S_FALSE denotes empty string throw(E_FAIL); }/* end of if statement */ // TODO: Create MyStrToInt and do not cast pVar->fltVal = (FLOAT) dbl; } break; case VT_R8: { double dbl; if(MyStrToDouble(strValue, dbl) != S_OK){ // S_FALSE denotes empty string throw(E_FAIL); }/* end of if statement */ // TODO: Create MyStrToInt and do not cast pVar->dblVal = dbl; } break; case VT_BOOL: { double dbl; if(MyStrToDouble(strValue, dbl) != S_OK){ // S_FALSE denotes empty string throw(E_FAIL); }/* end of if statement */ // TODO: Create MyStrToInt and do not cast if(0.0 == dbl){ pVar->boolVal = VARIANT_FALSE; } else if(1.0 == dbl || -1.0 == dbl){ pVar->boolVal = VARIANT_TRUE; } else { throw(E_FAIL); }/* end of if statement */ } break; default: ATLTRACE2(atlTraceHosting, 0, _T("This type is not implemented please add.\r\n")); ATLASSERT(FALSE); throw(E_FAIL); }/* end of switch statement */ delete strValue; // cleanup our variable } catch(...){ hr = E_UNEXPECTED; }/* end of catch statement */ return (hr); }/* end of function ParsePropertyBag */ /*************************************************************************/ /* End of file: CCObj.cpp */ /*************************************************************************/