You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
7.3 KiB
303 lines
7.3 KiB
/*++
|
|
|
|
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
|
|
|
|
|