/*++ 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 #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