|
|
#include "pch.h"
#include "atlbase.h"
#pragma hdrstop
#define INITGUID
#include <initguid.h>
#include "iids.h"
#define DECL_CRTFREE
#include <crtfree.h>
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/<bla>. / / 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; }
|