#include "pch.h" #include "atlbase.h" #pragma hdrstop #define INITGUID #include #include "iids.h" #define DECL_CRTFREE #include HINSTANCE g_hInstance = 0; DWORD g_tls = 0; LONG g_cRef = 0; HRESULT _OpenSavedDsQuery(LPTSTR pSavedQuery); STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: SHFusionInitializeFromModule(hInstance); TraceSetMaskFromCLSID(CLSID_DsQuery); GLOBAL_HINSTANCE = hInstance; DisableThreadLibraryCalls(GLOBAL_HINSTANCE); break; case DLL_PROCESS_DETACH: SHFusionUninitialize(); break; } return TRUE; } // Lifetime management of the DLL STDAPI_(void) DllAddRef() { InterlockedIncrement(&g_cRef); } STDAPI_(void) DllRelease() { TraceAssert( 0 != g_cRef ); InterlockedDecrement(&g_cRef); } STDAPI DllCanUnloadNow(VOID) { return (g_cRef > 0) ? S_FALSE : S_OK; } // expose objects CF_TABLE_BEGIN(g_ObjectInfo) // core query handler stuff CF_TABLE_ENTRY( &CLSID_CommonQuery, CCommonQuery_CreateInstance, COCREATEONLY), CF_TABLE_ENTRY( &CLSID_DsQuery, CDsQuery_CreateInstance, COCREATEONLY), CF_TABLE_ENTRY( &CLSID_DsFolderProperties, CDsFolderProperties_CreateInstance, COCREATEONLY), // start/find and context menu entries CF_TABLE_ENTRY( &CLSID_DsFind, CDsFind_CreateInstance, COCREATEONLY), CF_TABLE_ENTRY( &CLSID_DsStartFind, CDsFind_CreateInstance, COCREATEONLY), // column handler for object class and adspath CF_TABLE_ENTRY( &CLSID_PublishedAtCH, CQueryThreadCH_CreateInstance, COCREATEONLY), CF_TABLE_ENTRY( &CLSID_ObjectClassCH, CQueryThreadCH_CreateInstance, COCREATEONLY), CF_TABLE_ENTRY( &CLSID_MachineRoleCH, CQueryThreadCH_CreateInstance, COCREATEONLY), CF_TABLE_ENTRY( &CLSID_MachineOwnerCH, CQueryThreadCH_CreateInstance, COCREATEONLY), // domain query form specific column handlers CF_TABLE_ENTRY( &CLSID_PathElement1CH, CDomainCH_CreateInstance, COCREATEONLY), CF_TABLE_ENTRY( &CLSID_PathElement3CH, CDomainCH_CreateInstance, COCREATEONLY), CF_TABLE_ENTRY( &CLSID_PathElementDomainCH, CDomainCH_CreateInstance, COCREATEONLY), CF_TABLE_END(g_ObjectInfo) STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown)) { for (LPCOBJECTINFO pcls = g_ObjectInfo; pcls->pclsid; pcls++) { if (IsEqualGUID(rclsid, *(pcls->pclsid))) { *ppv = (void*)pcls; DllAddRef(); return NOERROR; } } } *ppv = NULL; return CLASS_E_CLASSNOTAVAILABLE; } // registration STDAPI DllRegisterServer(VOID) { return CallRegInstall(GLOBAL_HINSTANCE, "RegDll"); } STDAPI DllUnregisterServer(VOID) { return CallRegInstall(GLOBAL_HINSTANCE, "UnRegDll"); } STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) { return S_OK; } LPWSTR WfromA(LPSTR lpa) { int nChars=strlen(lpa)+1; LPWSTR lpw = (LPWSTR)LocalAlloc(LMEM_FIXED,nChars*sizeof(WCHAR)); if(lpw==NULL) return NULL; lpw[0] = '\0'; MultiByteToWideChar( CP_ACP, 0, lpa, -1, lpw, nChars); return lpw; } /*----------------------------------------------------------------------------- / OpenQueryWindow (runndll) / ---------------- / Opens the query window, parsing the specified CLSID for the form to / select, in the same way invoking Start/Search/. / / In: / hInstanec, hPrevInstance = instance information / pCmdLine = .dsq File to be opened / nCmdShow = display flags for our window / / Out: / INT /----------------------------------------------------------------------------*/ STDAPI_(int) OpenQueryWindow(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, INT nCmdShow) { HRESULT hr, hrCoInit; CLSID clsidForm; OPENQUERYWINDOW oqw = { 0 }; DSQUERYINITPARAMS dqip = { 0 }; ICommonQuery* pCommonQuery = NULL; USES_CONVERSION; TraceEnter(TRACE_CORE, "OpenQueryWindow"); // // get the ICommonQuery object we are going to use // hr = hrCoInit = CoInitialize(NULL); FailGracefully(hr, "Failed to CoInitialize"); hr = CoCreateInstance(CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ICommonQuery, &pCommonQuery)); FailGracefully(hr, "Failed in CoCreateInstance of CLSID_CommonQuery"); dqip.cbStruct = SIZEOF(dqip); dqip.dwFlags = 0; dqip.pDefaultScope = NULL; oqw.cbStruct = SIZEOF(oqw); oqw.dwFlags = 0; oqw.clsidHandler = CLSID_DsQuery; oqw.pHandlerParameters = &dqip; // // can we parse the form CLSID from the command line? // LPWSTR wpCmdLine=WfromA(pCmdLine); if (wpCmdLine!=NULL) { if(GetGUIDFromString(wpCmdLine, &oqw.clsidDefaultForm) ) { TraceMsg("Parsed out the form CLSID, so specifying the def form/remove forms"); oqw.dwFlags |= OQWF_DEFAULTFORM|OQWF_REMOVEFORMS; } LocalFree(wpCmdLine); } hr = pCommonQuery->OpenQueryWindow(NULL, &oqw, NULL); FailGracefully(hr, "OpenQueryWindow failed"); exit_gracefully: DoRelease(pCommonQuery); if ( SUCCEEDED(hrCoInit) ) CoUninitialize(); TraceLeaveValue(0); } /*----------------------------------------------------------------------------- / OpenSavedDsQuery / ---------------- / Open a saved DS query and display the query UI with that query. / / In: / hInstanec, hPrevInstance = instance information / pCmdLine = .dsq File to be opened / nCmdShow = display flags for our window / / Out: / INT /----------------------------------------------------------------------------*/ // UNICODE platforms export the W export as the prefered way of invoking the DLL // on a .QDS, we provide the ANSI version as a thunk to ensure compatibility. #ifdef UNICODE INT WINAPI OpenSavedDsQueryW(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR pCmdLineW, INT nCmdShow) { HRESULT hr; TraceEnter(TRACE_CORE, "OpenSavedDsQueryW"); Trace(TEXT("pCmdLine: %s, nCmdShow %d"), pCmdLineW, nCmdShow); hr = _OpenSavedDsQuery(pCmdLineW); FailGracefully(hr, "Failed when calling _OpenSavedDsQuery"); // hr = S_OK; // success exit_gracefully: TraceLeaveResult(hr); } #endif INT WINAPI OpenSavedDsQuery(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, INT nCmdShow) { HRESULT hr; USES_CONVERSION; TraceEnter(TRACE_CORE, "OpenSavedDsQuery"); LPWSTR wpCmdLine=WfromA(pCmdLine); if (wpCmdLine!=NULL) { Trace(TEXT("pCmdLine: %s, nCmdShow %d"), wpCmdLine, nCmdShow); hr = _OpenSavedDsQuery(wpCmdLine); LocalFree(wpCmdLine); FailGracefully(hr, "Failed when calling _OpenSavedDsQuery"); } else { hr=E_OUTOFMEMORY; } // hr = S_OK; // success exit_gracefully: TraceLeaveResult(hr); } HRESULT _OpenSavedDsQuery(LPTSTR pSavedQuery) { HRESULT hr, hrCoInit; ICommonQuery* pCommonQuery = NULL; IPersistQuery *ppq = NULL; OPENQUERYWINDOW oqw; DSQUERYINITPARAMS dqip; USES_CONVERSION; TraceEnter(TRACE_CORE, "OpenSavedQueryW"); Trace(TEXT("Filename is: "), pSavedQuery); hr = hrCoInit = CoInitialize(NULL); FailGracefully(hr, "Failed to CoInitialize"); // Construct the persistance object so that we can load objects from the given file // assuming that pSavedQuery is a valid filename. hr = CPersistQuery_CreateInstance(pSavedQuery, &ppq); FailGracefully(hr, "Failed to create persistance object"); // Now lets get the ICommonQuery and get it to open itself based on the // IPersistQuery stream that are giving it. hr =CoCreateInstance(CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ICommonQuery, &pCommonQuery)); FailGracefully(hr, "Failed in CoCreateInstance of CLSID_CommonQuery"); dqip.cbStruct = SIZEOF(dqip); dqip.dwFlags = 0; dqip.pDefaultScope = NULL; oqw.cbStruct = SIZEOF(oqw); oqw.dwFlags = OQWF_LOADQUERY|OQWF_ISSUEONOPEN|OQWF_REMOVEFORMS; oqw.clsidHandler = CLSID_DsQuery; oqw.pHandlerParameters = &dqip; oqw.pPersistQuery = ppq; hr = pCommonQuery->OpenQueryWindow(NULL, &oqw, NULL); FailGracefully(hr, "OpenQueryWindow failed"); exit_gracefully: // Failed so report that this was a bogus query file, however the user may have // already been prompted with nothing. if ( FAILED(hr) ) { WIN32_FIND_DATA fd; HANDLE handle; Trace(TEXT("FindFirstFile on: %s"), pSavedQuery); handle = FindFirstFile(pSavedQuery, &fd); if ( INVALID_HANDLE_VALUE != handle ) { Trace(TEXT("Resulting 'long' name is: "), fd.cFileName); pSavedQuery = fd.cFileName; FindClose(handle); } FormatMsgBox(NULL, GLOBAL_HINSTANCE, IDS_WINDOWTITLE, IDS_ERR_BADDSQ, MB_OK|MB_ICONERROR, pSavedQuery); } DoRelease(ppq); if ( SUCCEEDED(hrCoInit) ) CoUninitialize(); TraceLeaveValue(0); } // static class factory STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObj) { if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown)) { *ppvObj = (void *)GET_ICLASSFACTORY(this); InterlockedIncrement(&g_cRef); return NOERROR; } *ppvObj = NULL; return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CClassFactory::AddRef() { return InterlockedIncrement(&g_cRef); } STDMETHODIMP_(ULONG) CClassFactory::Release() { TraceAssert( 0 != g_cRef ); InterlockedDecrement(&g_cRef); // // TODO: gpease 27-FEB-2002 // Why doesn't this object get destroyed? And why does it return // "1" (and "2" in the AddRef) case? // return 1; } STDMETHODIMP CClassFactory::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv) { *ppv = NULL; if (punkOuter && !IsEqualIID(riid, IID_IUnknown)) { // It is technically illegal to aggregate an object and request // any interface other than IUnknown. Enforce this. // return CLASS_E_NOAGGREGATION; } else { LPOBJECTINFO pthisobj = (LPOBJECTINFO)this; if ( punkOuter ) return CLASS_E_NOAGGREGATION; IUnknown *punk; HRESULT hres = pthisobj->pfnCreateInstance(punkOuter, &punk, pthisobj); if (SUCCEEDED(hres)) { hres = punk->QueryInterface(riid, ppv); punk->Release(); } return hres; } } STDMETHODIMP CClassFactory::LockServer(BOOL fLock) { if (fLock) { InterlockedIncrement(&g_cRef); } else { TraceAssert( 0 != g_cRef ); InterlockedDecrement(&g_cRef); } return S_OK; }