#include "pch.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() { 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; } /*----------------------------------------------------------------------------- / 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_ICommonQuery, (LPVOID*)&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? // if ( GetGUIDFromString(A2T(pCmdLine), &oqw.clsidDefaultForm) ) { TraceMsg("Parsed out the form CLSID, so specifying the def form/remove forms"); oqw.dwFlags |= OQWF_DEFAULTFORM|OQWF_REMOVEFORMS; } 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"); Trace(TEXT("pCmdLine: %s, nCmdShow %d"), A2T(pCmdLine), nCmdShow); hr = _OpenSavedDsQuery(A2T(pCmdLine)); FailGracefully(hr, "Failed when calling _OpenSavedDsQuery"); // 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_ICommonQuery, (LPVOID*)&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() { InterlockedIncrement(&g_cRef); return 2; } STDMETHODIMP_(ULONG) CClassFactory::Release() { InterlockedDecrement(&g_cRef); 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 InterlockedDecrement(&g_cRef); return S_OK; }