390 lines
10 KiB
C++
390 lines
10 KiB
C++
|
#include "pch.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()
|
||
|
{
|
||
|
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/<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_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;
|
||
|
}
|
||
|
|