windows-nt/Source/XPSP1/NT/shell/ext/dsui/dsquery/dll.cpp
2020-09-26 16:20:57 +08:00

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;
}