304 lines
7.3 KiB
C++
304 lines
7.3 KiB
C++
/*++
|
||
|
||
Copyright (c) 1996-1997 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
oemcom.cxx
|
||
|
||
Abstract:
|
||
|
||
Implementation of Windows NT printer driver OEM COM plugins
|
||
|
||
Environment:
|
||
|
||
Windows NT
|
||
|
||
Revision History:
|
||
|
||
02/06/98 -steveki-
|
||
Initial framework.
|
||
|
||
--*/
|
||
|
||
#include <lib.h>
|
||
|
||
#undef IUnknown
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
static const CHAR szDllGetClassObject[] = "DllGetClassObject";
|
||
static const CHAR szDllCanUnloadNow[] = "DllCanUnloadNow";
|
||
|
||
#ifdef WINNT_40
|
||
extern "C" EngFindImageProcAddress(HMODULE, CHAR *);
|
||
extern "C" EngUnloadImage(HMODULE);
|
||
#endif
|
||
|
||
|
||
extern "C" HRESULT
|
||
HDriver_CoGetClassObject(
|
||
IN REFCLSID rclsid,
|
||
IN DWORD dwClsContext,
|
||
IN LPVOID pvReservedForDCOM,
|
||
IN REFIID riid,
|
||
IN LPVOID *ppv,
|
||
IN HANDLE hInstance
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Locate and connect to the class factory object associated with the class identifier rclsid.
|
||
|
||
Arguments:
|
||
|
||
rclsid - Specifies the class factory component.
|
||
dwClsContext - Specifies the context in which the executable code is to be run.
|
||
pvReservedForDCOM - Reserved for future use; must be NULL.
|
||
riid - Specifies the interface to be used to communicate with the class object.
|
||
ppv - Points to where to return the pointer to the requested interface.
|
||
hInstance - Handle to the loaded OEM plugin module.
|
||
|
||
Return Value:
|
||
|
||
S_OK if successful, E_FAIL if DllGetClassObject entry point is not found. Refer to COM spec
|
||
for other possible error codes that can be returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
HRESULT hr = E_FAIL;
|
||
LPFNGETCLASSOBJECT pfnDllGetClassObject = NULL;
|
||
|
||
//
|
||
// Get the class object procedure address.
|
||
//
|
||
|
||
if (hInstance && (pfnDllGetClassObject = (LPFNGETCLASSOBJECT)GetProcAddress((HMODULE)hInstance,
|
||
(CHAR *)szDllGetClassObject)))
|
||
{
|
||
//
|
||
// Ask for the class factory interface.
|
||
//
|
||
|
||
hr = pfnDllGetClassObject(rclsid, riid, ppv);
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
|
||
extern "C" HRESULT
|
||
HDriver_CoCreateInstance(
|
||
IN REFCLSID rclsid,
|
||
IN LPUNKNOWN pUnknownOuter,
|
||
IN DWORD dwClsContext,
|
||
IN REFIID riid,
|
||
IN LPVOID *ppv,
|
||
IN HANDLE hInstance
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Create an instance of the class rclsid, asking for interface riid using the given execution context.
|
||
|
||
Arguments:
|
||
|
||
rclsid - Specifies the class factory component.
|
||
pUnknownOuter - Specifies the controlling unknown of the aggregate.
|
||
dwClsContext - Specifies the context in which the executable is to be run.
|
||
riid - Specifies the interface to be used to communicate with the class object.
|
||
ppv - Points to where to return the pointer to the requested interface.
|
||
hInstance - Handle to the loaded OEM plugin module.
|
||
|
||
Return Value:
|
||
|
||
S_OK if successful. Refer to COM spec for other possible error codes that can be returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
HRESULT hr = E_FAIL;
|
||
IClassFactory *pIFactory = NULL;
|
||
|
||
//
|
||
// Set output parameter to NULL.
|
||
//
|
||
|
||
*ppv = NULL;
|
||
|
||
//
|
||
// We can only support in process servers. We do not have any
|
||
// code for marshaling to another process.
|
||
//
|
||
|
||
if (dwClsContext == CLSCTX_INPROC_SERVER)
|
||
{
|
||
|
||
hr = HDriver_CoGetClassObject(rclsid,
|
||
dwClsContext,
|
||
NULL,
|
||
IID_IClassFactory,
|
||
(void **)&pIFactory,
|
||
hInstance);
|
||
|
||
|
||
if(SUCCEEDED(hr))
|
||
{
|
||
hr = pIFactory->CreateInstance(pUnknownOuter, riid, ppv);
|
||
|
||
//
|
||
// Release the class factory.
|
||
//
|
||
|
||
pIFactory->Release();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
hr = E_NOTIMPL;
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
|
||
extern "C" VOID
|
||
Driver_CoFreeOEMLibrary(
|
||
IN HANDLE hInstance
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Unloads OEM plugin DLL that are no longer serving any components.
|
||
|
||
Arguments:
|
||
|
||
hInstance - Handle to the loaded OEM plugin module.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
LPFNCANUNLOADNOW pfnDllCanUnloadNow = NULL;
|
||
|
||
if (hInstance && (pfnDllCanUnloadNow = (LPFNCANUNLOADNOW)GetProcAddress((HMODULE)hInstance,
|
||
(CHAR *)szDllCanUnloadNow)))
|
||
{
|
||
(VOID) pfnDllCanUnloadNow();
|
||
|
||
//
|
||
// We don't look at the return value of DllCanUnloadNow() and always do a FreeLibrary here,
|
||
// otherwise we may end up with OEM DLL still remains in memory when all its instances are
|
||
// unloaded.
|
||
//
|
||
// If OEM DLL spins off a working thread which also uses the OEM DLL, the thread needs to
|
||
// do LoadLibrary and FreeLibraryExitThread, otherwise it may crash after we called FreeLibrary.
|
||
//
|
||
|
||
FreeLibrary((HMODULE)hInstance);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
extern "C" BOOL
|
||
BQILatestOemInterface(
|
||
IN HANDLE hInstance,
|
||
IN REFCLSID rclsid,
|
||
IN const GUID *PrintOem_IIDs[],
|
||
OUT PVOID *ppIntfOem,
|
||
OUT GUID *piidIntfOem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Retrieve the latest interface supported by OEM plugin
|
||
|
||
Arguments:
|
||
|
||
hInstance - handle to the loaded OEM plugin module
|
||
rclsid - specifies the class factory component
|
||
PrintOem_IIDs[] - array of IIDs for plugin interfaces (from latest to oldest) driver supports
|
||
ppIntfOem - points to where to return the interface pointer we get from OEM plugin
|
||
piidIntfOem - points to where to return the IID for the interface we get from OEM plguin
|
||
|
||
Return Value:
|
||
|
||
TRUE if retrieving OEM plugin interface is successful. FALSE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
IUnknown *pIUnknown = NULL;
|
||
IUnknown *pIPrintOem = NULL;
|
||
HRESULT hr;
|
||
INT iid_index;
|
||
BOOL bIntfFound;
|
||
|
||
hr = HDriver_CoCreateInstance(rclsid,
|
||
NULL,
|
||
CLSCTX_INPROC_SERVER,
|
||
IID_IUnknown,
|
||
(void **)&pIUnknown,
|
||
hInstance);
|
||
|
||
if (FAILED(hr) || pIUnknown == NULL)
|
||
{
|
||
ERR(("HDriver_CoCreateInstance failed\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
iid_index = 0;
|
||
bIntfFound = FALSE;
|
||
|
||
//
|
||
// QI for the driver supported plugin interfaces from latest to oldest,
|
||
// until one is supported by the OEM plugin, or until we hit the NULL
|
||
// terminator.
|
||
//
|
||
while (!bIntfFound && PrintOem_IIDs[iid_index] != NULL)
|
||
{
|
||
hr = pIUnknown->QueryInterface(*PrintOem_IIDs[iid_index], (void **)&pIPrintOem);
|
||
|
||
if (SUCCEEDED(hr) && pIPrintOem != NULL)
|
||
bIntfFound = TRUE;
|
||
else
|
||
iid_index++;
|
||
}
|
||
|
||
pIUnknown->Release();
|
||
|
||
if (!bIntfFound)
|
||
{
|
||
ERR(("Can't get a plugin interface we support!\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
*ppIntfOem = (PVOID)pIPrintOem;
|
||
*piidIntfOem = *PrintOem_IIDs[iid_index];
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
|