/************************************************************************************************** FILENAME: DataIo.cpp COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. */ #define INC_OLE2 #include "stdafx.h" #ifndef SNAPIN #include #endif //#include #include #include "DataIo.h" #include "DataIoCl.h" #include "Message.h" #include "ErrMacro.h" // If we use DataIo with a console application, then we cannot use // the Windows message pump PostMessage() routine as there is No // window to post the message to, so we will use a locally created // PostMessageLocal() routine instead. #ifdef ESI_POST_MESSAGE #pragma message ("Information: ESI_POST_MESSAGE defined.") #include "PostMsgC.h" #endif /************************************************************************************************** Globals */ int vcObjects = 0; CClassFactory g_ClassFactory; extern HWND hwndMain; /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: CClassFactory::QueryInterface implementation. GLOBAL VARIABLES: None. ARGUMENTS: IN REFIID riid - reference IID of the ClassFactory Interface. OUT void** ppv.- receives a pointer to the interface pointer of the object. RETURN: HRESULT - zero = success. HRESULT - non zero = error code. */ STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void** ppv) { // Check for valid argunment - ppv should be NULL. if (ppv == NULL) { // Message(TEXT("CClassFactory::QueryInterface"), E_INVALIDARG, NULL); return E_INVALIDARG; } // Make sure we are being asked for a ClassFactory or Unknown interface. if (riid == IID_IClassFactory || riid == IID_IUnknown) { // If so return a pointer to this interface. *ppv = (IClassFactory*) this; AddRef(); // Message(TEXT("CClassFactory::QueryInterface"), S_OK, NULL); return S_OK; } // No interface. *ppv = NULL; // Message(TEXT("CClassFactory::QueryInterface"), E_NOINTERFACE, NULL); return E_NOINTERFACE; } /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: CClassFactory::CreateInstance implementation of the ESI Data Object. GLOBAL VARIABLES: None. ARGUMENTS: IN LPUNKNOWN punkOuter - aggregate pointer - must be NULL as we don't support aggregation. IN REFIID riid - reference IID of the ClassFactory Interface. OUT void** ppv.- receives a pointer to the interface pointer of the object. RETURN: HRESULT - zero = success. HRESULT - non zero = error code. */ STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN punkOuter, REFIID riid, void** ppv) { LPUNKNOWN punk; HRESULT hr; *ppv = NULL; // Check for aggregation - we don't support it.. if (punkOuter != NULL) { // Message(TEXT("CClassFactory::CreateInstance"), CLASS_E_NOAGGREGATION, NULL); return CLASS_E_NOAGGREGATION; } // Create the ESI Data Object. // Message(TEXT("CClassFactory::CreateInstance"), S_OK, NULL); punk = new EsiDataObject; // If we didn't get a pointer then we are out of memory. if (punk == NULL) { // Message(TEXT("CClassFactory::CreateInstance"), E_OUTOFMEMORY, NULL); return E_OUTOFMEMORY; } // Get a pointer to the ESI Data Object interface. hr = punk->QueryInterface(riid, ppv); // Release the pointer to the ESI Data Object. punk->Release(); return hr; } /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: EsiDataObject::EsiDataObject constructor. GLOBAL VARIABLES: None. ARGUMENTS: None. RETURN: None. */ EsiDataObject::EsiDataObject(void) { m_cRef = 1; hDataOut = NULL; hDataIn = NULL; // Message(TEXT("EsiDataObject::EsiDataObject"), S_OK, NULL); } /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: EsiDataObject::EsiDataObject destructor. GLOBAL VARIABLES: None. ARGUMENTS: None. RETURN: None. */ EsiDataObject::~EsiDataObject(void) { // Message(TEXT("EsiDataObject::~EsiDataObject"), S_OK, NULL); } /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: EsiDataObject::QueryInterface GLOBAL VARIABLES: None. ARGUMENTS: IN REFIID riid - reference IID of the EsiDataObject interfavce. OUT void** ppv.- receives a pointer to the interface pointer of the object. RETURN: HRESULT - zero = success. HRESULT - non zero = error code. */ STDMETHODIMP EsiDataObject::QueryInterface(REFIID riid, void** ppv) { // Check for valid argunment - ppv should be NULL. if (ppv == NULL) { // Message(TEXT("EsiDataObject::QueryInterface"), E_INVALIDARG, NULL); return E_INVALIDARG; } // Make sure we are being asked for a DataObject interface. if (riid == IID_IUnknown || riid == IID_IDataObject) { // If so return a pointer to this interface. *ppv = (IUnknown *) this; AddRef(); // Message(TEXT("EsiDataObject::QueryInterface"), S_OK, NULL); return S_OK; } // No interface. *ppv = NULL; // Message(TEXT("EsiDataObject::QueryInterface"), E_NOINTERFACE, NULL); return E_NOINTERFACE; } /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: Decrements the reference count and when zero deletes the interface object and post a WM_CLOSE message to terminate the program. GLOBAL VARIABLES: None. ARGUMENTS: IN REFIID riid - reference IID of the EsiDataObject interfavce. OUT void** ppv.- receives a pointer to the interface pointer of the object. RETURN: ULONG - m_cRef */ STDMETHODIMP_(ULONG) EsiDataObject::Release(void) { if (InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return m_cRef; } /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: EsiDataObject::GetData only supports CF_TEXT GLOBAL VARIABLES: None. ARGUMENTS: IN LPFORMATETC IN LPSTGMEDIUM RETURN: HRESULT - zero = success. HRESULT - non zero = error code. */ STDMETHODIMP EsiDataObject::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium) { char FAR* pstrDest; char FAR* pDataOut = NULL; // char FAR* pstrSrc; if (!(pformatetcIn->dwAspect & DVASPECT_CONTENT)) return DATA_E_FORMATETC; switch (pformatetcIn->cfFormat) { case CF_TEXT: if (!(pformatetcIn->tymed & TYMED_HGLOBAL)) return DATA_E_FORMATETC; pmedium->tymed = TYMED_HGLOBAL; pmedium->pUnkForRelease = NULL; pmedium->hGlobal = GlobalAlloc(GHND,GlobalSize(hDataOut)); EE_ASSERT(pmedium->hGlobal); pstrDest = (char FAR *)GlobalLock(pmedium->hGlobal); EE_ASSERT(pstrDest); pDataOut = (char FAR *)GlobalLock(hDataOut); EE_ASSERT(pDataOut); memcpy(pstrDest,pDataOut,(ULONG)GlobalSize(hDataOut)); GlobalUnlock(hDataOut); GlobalUnlock(pmedium->hGlobal); break; default: return DATA_E_FORMATETC; } return S_OK; } // ------------------------------------------------------------------------------------------------ // %%Function: EsiDataObject::GetData // ------------------------------------------------------------------------------------------------ // GetData only supports CF_TEXT /* STDMETHODIMP EsiDataObject::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium) { char FAR *pstrDest; char FAR *pstrSrc; if (!(pformatetcIn->dwAspect & DVASPECT_CONTENT)) return DATA_E_FORMATETC; switch (pformatetcIn->cfFormat) { case CF_TEXT: if (!(pformatetcIn->tymed & TYMED_HGLOBAL)) return DATA_E_FORMATETC; pmedium->tymed = TYMED_HGLOBAL; pmedium->hGlobal = GlobalAlloc(GHND,GlobalSize(hGuid)); pmedium->pUnkForRelease = NULL; pstrDest = (char FAR *)GlobalLock(pmedium->hGlobal); pstrSrc = (char FAR *)GlobalLock(hGuid); memcpy(pstrDest,pstrSrc,GlobalSize(hGuid)); GlobalUnlock(hGuid); GlobalUnlock(pmedium->hGlobal); break; default: return DATA_E_FORMATETC; } return S_OK; } /************************************************************************************************** EsiDataObject::GetDataHere - NOT IMPLEMENTED. */ STDMETHODIMP EsiDataObject::GetDataHere(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) { // Message(TEXT("EsiDataObject::GetDataHere"), E_NOTIMPL, NULL); return E_NOTIMPL; } /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: This routine tells the caller that we support only CF_TEXT and TYMED_HGLOBAL formats. GLOBAL VARIABLES: None. ARGUMENTS: IN LPFORMATETC RETURN: HRESULT - zero = success. HRESULT - non zero = error code. */ STDMETHODIMP EsiDataObject::QueryGetData(LPFORMATETC pformatetc) { // Check for DVASPECT_CONTENT. if (!(DVASPECT_CONTENT & pformatetc->dwAspect)) { // Message(TEXT("EsiDataObject::QueryGetData"), DATA_E_FORMATETC, NULL); return DATA_E_FORMATETC; } // Check for CF_TEXT. if (pformatetc->cfFormat != CF_TEXT) { // Message(TEXT("EsiDataObject::QueryGetData"), DATA_E_FORMATETC, NULL); return DATA_E_FORMATETC; } // Check for TYMED_HGLOBAL. if (!(TYMED_HGLOBAL & pformatetc->tymed)) { // Message(TEXT("EsiDataObject::QueryGetData"), DV_E_TYMED, NULL); return DV_E_TYMED; } // Message(TEXT("EsiDataObject::QueryGetData"), S_OK, NULL); return S_OK; } /* /************************************************************************************************** EsiDataObject::GetCanonicalFormatEtc - NOT IMPLEMENTED. */ STDMETHODIMP EsiDataObject::GetCanonicalFormatEtc(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut) { // Message(TEXT("EsiDataObject::GetCanonicalFormatEtc"), DATA_S_SAMEFORMATETC, NULL); return DATA_S_SAMEFORMATETC; } /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: EsiDataObject::GetData only supports CF_TEXT GLOBAL VARIABLES: None. ARGUMENTS: IN LPFORMATETC IN LPSTGMEDIUM IN BOOL fRelease RETURN: HRESULT - zero = success. HRESULT - non zero = error code. typedef struct { WORD dwID; // ESI data structre ID always = 0x4553 'ES' WORD dwType; // Type of data structure WORD dwVersion; // Version number WORD dwCompatibilty;// Compatibilty number ULONG ulDataSize; // Data size WPARAM wparam; // LOWORD(wparam) = Command char cData; // Void pointer to the data - NULL = no data } DATA_IO, *PDATA_IO; */ STDMETHODIMP EsiDataObject::SetData(LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium, BOOL fRelease) { WPARAM wpPostCommand; // We only support CF_TEXT if (pformatetc->cfFormat != CF_TEXT) { // Message(TEXT("EsiDataObject::SetData"), E_FAIL, NULL); return E_FAIL; } // We want memory only. if (pformatetc->tymed != TYMED_HGLOBAL) { // Message(TEXT("EsiDataObject::SetData"), E_FAIL, NULL); return E_FAIL; } DWORD dwGlobalSize; char FAR* pstrSrc; PCHAR pDataIn; // Check for valid memory handle. if(pmedium->hGlobal == NULL) { // Message(TEXT("EsiDataObject::SetData"), E_FAIL, NULL); return E_FAIL; } // Get the size of the incoming data. dwGlobalSize = (DWORD)GlobalSize(pmedium->hGlobal); // Allocate enough memory for the incoming data. hDataIn = GlobalAlloc(GHND,dwGlobalSize); EE_ASSERT(hDataIn); // Lock and get pointers to the data. pDataIn = (PCHAR)GlobalLock(hDataIn); EE_ASSERT(pDataIn); pstrSrc = (char FAR*)GlobalLock(pmedium->hGlobal); EE_ASSERT(pstrSrc); // Copy the data to this processes memory. CopyMemory(pDataIn, pstrSrc, dwGlobalSize); // Unlock and release the pointer to the source memory. GlobalUnlock(pmedium->hGlobal); // Release the memory if requested by the caller. if (fRelease) { ReleaseStgMedium(pmedium); } DATA_IO* pDataIo = (DATA_IO*)pDataIn; // Extract the Post Command message wpPostCommand = pDataIo->wparam; // Cehck ESI data structre ID which is always = 0x4553 'ES' if(pDataIo->dwID != ESI_DATA_STRUCTURE) { // Message(TEXT("EsiDataObject::SetData"), E_FAIL, NULL); return FALSE; } // Cehck the data structure type. if(pDataIo->dwType != FR_COMMAND_BUFFER) { // Message(TEXT("EsiDataObject::SetData"), E_FAIL, NULL); return FALSE; } // Check for data structure compatibility. if(pDataIo->dwCompatibilty != FR_COMMAND_BUFFER_ONE) { // Message(TEXT("EsiDataObject::SetData"), E_FAIL, NULL); return FALSE; } // Unlock the memory. GlobalUnlock(hDataIn); // Check for any data. if(pDataIo->ulDataSize == 0) { // Unlock the memory since there is no data other than the command. EH_ASSERT(GlobalFree(hDataIn) == NULL); hDataIn = NULL; } // Send the data to the message pump. // NOTE THAT THE MEMORY MUST FREED BY THE PROCESSING FUNCTION. // If we use DataIo with a console application, then we cannot use the WNT // PostMessage() routine as there is No window to post the message to, so // we will use a locally created PostMessageConsole() routine instead. #ifdef ESI_POST_MESSAGE #ifndef DKMS PostMessageLocal(NULL, WM_COMMAND, wpPostCommand, (LPARAM)hDataIn); #endif #else PostMessage(hwndMain, WM_COMMAND, wpPostCommand, (LPARAM)hDataIn); #endif // Message(TEXT("EsiDataObject::SetData"), S_OK, NULL); return S_OK; } /************************************************************************************************** EsiDataObject::EnumFormatEtc - NOT IMPLEMENTED. */ STDMETHODIMP EsiDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc) { // Message(TEXT("EsiDataObject::DAdvise"), E_NOTIMPL, NULL); return E_NOTIMPL ; } /************************************************************************************************** EsiDataObject::DAdvise - NOT SUPPORTED. */ STDMETHODIMP EsiDataObject::DAdvise(FORMATETC FAR* pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD FAR* pdwConnection) { // Message(TEXT("EsiDataObject::DAdvise"), OLE_E_ADVISENOTSUPPORTED, NULL); return OLE_E_ADVISENOTSUPPORTED; } /************************************************************************************************** EsiDataObject::DUnadvise - NOT SUPPORTED. */ STDMETHODIMP EsiDataObject::DUnadvise(DWORD dwConnection) { // Message(TEXT("EsiDataObject::DUnadvise"), OLE_E_ADVISENOTSUPPORTED, NULL); return OLE_E_ADVISENOTSUPPORTED; } /************************************************************************************************** EsiDataObject::DUnadvise - NOT SUPPORTED. */ STDMETHODIMP EsiDataObject::EnumDAdvise(LPENUMSTATDATA FAR* ppenumAdvise) { // Message(TEXT("EsiDataObject::EnumDAdvise"), OLE_E_ADVISENOTSUPPORTED, NULL); return OLE_E_ADVISENOTSUPPORTED; } /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: This is the WinMain function for the Diskeeper Gui. GLOBAL VARIABLES: None. INPUT: hInstance - The handle to this instance. hPrevInstance - The handle to the previous instance. lpCmdLine - The command line which was passed in. nCmdShow - Whether the window should be minimized or not. RETURN: TRUE - Success. FALSE - Failure to initilize. */ DWORD InitializeDataIo( IN REFCLSID refCLSID, DWORD dwRegCls ) { HRESULT hr; DWORD dwRegister; // initialize COM for free-threading. // DO NOT want this for controls that are derived from ATL. Bad Mojo #ifndef ESI_DFRGUI hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); #endif // Register the class-object with OLE. hr = CoRegisterClassObject(refCLSID, &g_ClassFactory, CLSCTX_SERVER, dwRegCls, &dwRegister); if (FAILED(hr)) { return 0; } return( dwRegister ); } /************************************************************************************************** COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc. ROUTINE DESCRIPTION: Exit routine for DataIo GLOBAL VARIABLES: None. INPUT: None RETURN: TRUE - Success. FALSE - Failure. */ BOOL ExitDataIo( ) { #ifndef ESI_DFRGUI // DO NOT want this for controls that are derived from ATL. Bad Mojo CoUninitialize(); #endif return TRUE; }