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.
864 lines
23 KiB
864 lines
23 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 1997
|
|
*
|
|
* TITLE: CFactory.Cpp
|
|
*
|
|
* VERSION: 2.0
|
|
*
|
|
* AUTHOR: ReedB
|
|
*
|
|
* DATE: 26 Dec, 1997
|
|
*
|
|
* DESCRIPTION:
|
|
* Class factory implementation for ImageIn.
|
|
*
|
|
*******************************************************************************/
|
|
#include "precomp.h"
|
|
#include "stiexe.h"
|
|
|
|
//#include <assert.h>
|
|
|
|
#include "wiacfact.h"
|
|
#include <sddl.h>
|
|
|
|
extern HINSTANCE g_hInst;
|
|
|
|
BOOL setValue(LPCTSTR, LPCTSTR, LPCTSTR);
|
|
BOOL setBinValue(LPCTSTR, LPCTSTR, DWORD, BYTE*);
|
|
BOOL setKeyAndValue(LPCTSTR, LPCTSTR, LPCTSTR);
|
|
BOOL SubkeyExists(LPCTSTR, LPCTSTR);
|
|
LONG recursiveDeleteKey(HKEY, LPCTSTR);
|
|
|
|
BOOL GetWiaDefaultDCOMSecurityDescriptor(
|
|
VOID **ppSecurityDescriptor,
|
|
ULONG *pulSize)
|
|
{
|
|
ULONG ulAclSize = 0;
|
|
BOOL bRet = FALSE;
|
|
|
|
|
|
//
|
|
// Create our security descriptor. We do this using a string format security
|
|
// descriptor, which we then convert to a real security descriptor.
|
|
//
|
|
// NOTE: Caller has to free the security descriptor with LocalFree...
|
|
//
|
|
if ( ConvertStringSecurityDescriptorToSecurityDescriptor(wszDefaultDaclForDCOMAccessPermission,
|
|
SDDL_REVISION_1,
|
|
(PSECURITY_DESCRIPTOR*)ppSecurityDescriptor,
|
|
pulSize)) {
|
|
bRet = TRUE;
|
|
} else {
|
|
DBG_ERR(("ConvertStringSecurityDescriptorToSecurityDescriptor Failed"));
|
|
}
|
|
return bRet;
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegisterServer
|
|
*
|
|
* DESCRIPTION:
|
|
* Register a COM component in the Registry. From Inside COM.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT RegisterServer(
|
|
LPCTSTR szModuleFileName,
|
|
const CLSID* pclsid,
|
|
LPCTSTR szFriendlyName,
|
|
LPCTSTR szVerIndProgID,
|
|
LPCTSTR szProgID,
|
|
LPCTSTR szService,
|
|
const GUID* plibid,
|
|
BOOLEAN bOutProc)
|
|
{
|
|
BOOL bResult = TRUE;
|
|
|
|
//
|
|
// Fill in the path to the module file name.
|
|
//
|
|
|
|
TCHAR szModule[MAX_PATH] = {0};
|
|
|
|
if (!GetModuleFileName(g_hInst, szModule, sizeof(szModule)/sizeof(szModule[0]) - 1)) {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("Error extracting service module name."));
|
|
#endif
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// Strip the filename from the path
|
|
//
|
|
|
|
TCHAR *pChar = &szModule[lstrlen(szModule)];
|
|
while ((pChar > szModule) && (*pChar != '\\')) {
|
|
pChar--;
|
|
}
|
|
|
|
if (pChar == szModule) {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("Error extracting Still Image service path."));
|
|
#endif
|
|
return E_FAIL;
|
|
} else {
|
|
pChar++;
|
|
*pChar = '\0';
|
|
}
|
|
|
|
if (szModuleFileName) {
|
|
if (lstrlen(szModuleFileName) > (int)((sizeof(szModule) / sizeof(szModule[0]) - lstrlen(szModule)))) {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("szModuleFileName parameter is too long."));
|
|
#endif
|
|
return E_INVALIDARG;
|
|
}
|
|
} else {
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("NULL szModuleFileName parameter"));
|
|
#endif
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Concatenate server module name (XXXXX.exe) with path
|
|
//
|
|
|
|
if( lstrcat(szModule, szModuleFileName) == NULL)
|
|
{
|
|
#ifdef DEBUG
|
|
OutputDebugString(TEXT("Error concatenating module file name and path"));
|
|
#endif
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Convert the CLSID into a char.
|
|
LPOLESTR pszCLSID;
|
|
LPOLESTR pszLIBID;
|
|
TCHAR szCLSID[64];
|
|
TCHAR szLIBID[64];
|
|
|
|
HRESULT hr = StringFromCLSID(*pclsid, &pszCLSID);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
hr = StringFromCLSID(*plibid, &pszLIBID);
|
|
if (FAILED(hr)) {
|
|
return hr;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
lstrcpy(szCLSID, pszCLSID);
|
|
lstrcpy(szLIBID, pszLIBID);
|
|
#else
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pszCLSID,
|
|
-1,
|
|
szCLSID,
|
|
sizeof(szCLSID),
|
|
NULL,
|
|
NULL);
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pszLIBID,
|
|
-1,
|
|
szLIBID,
|
|
sizeof(szLIBID),
|
|
NULL,
|
|
NULL);
|
|
#endif
|
|
|
|
// Build the key CLSID\\{...}
|
|
TCHAR szKey[64] = TEXT("CLSID\\");
|
|
|
|
lstrcat(szKey, szCLSID);
|
|
|
|
|
|
// Add the CLSID to the registry.
|
|
bResult &= setKeyAndValue(szKey, NULL, szFriendlyName) ;
|
|
|
|
// Add the server filename subkey under the CLSID key.
|
|
if (bOutProc) {
|
|
bResult &= setKeyAndValue(szKey, TEXT("LocalServer32"), szModule);
|
|
|
|
// If the server is implemented as a service add the service
|
|
// AppID keys and values.
|
|
if (szService) {
|
|
// Add the service AppID value to the CLSID key.
|
|
bResult &= setValue(szKey, TEXT("AppID"), szCLSID);
|
|
|
|
// Add the AppID key.
|
|
TCHAR szAppID[64] = TEXT("AppID\\");
|
|
|
|
lstrcat(szAppID, szCLSID);
|
|
bResult &= setKeyAndValue(szAppID, NULL, szFriendlyName);
|
|
|
|
bResult &= setValue(szAppID, TEXT("LocalService"), szService);
|
|
|
|
//
|
|
// Add an ACL to protect instantiation.
|
|
//
|
|
DWORD dwSize = 0;
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
|
|
|
|
if (GetWiaDefaultDCOMSecurityDescriptor((VOID**)&pSecurityDescriptor, &dwSize)) {
|
|
//
|
|
// Write this self-relative security descriptor to the AccessPermission value
|
|
// under our AppID
|
|
//
|
|
setBinValue(szAppID, TEXT("AccessPermission"), dwSize, (BYTE*)pSecurityDescriptor);
|
|
LocalFree(pSecurityDescriptor);
|
|
pSecurityDescriptor = NULL;
|
|
} else {
|
|
DBG_ERR(("GetWiaDefaultDCOMSecurityDescriptor failed"));
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
bResult &= setKeyAndValue(szKey, TEXT("InprocServer32"), szModule);
|
|
}
|
|
|
|
// Add the ProgID subkey under the CLSID key.
|
|
bResult &= setKeyAndValue(szKey, TEXT("ProgID"), szProgID) ;
|
|
|
|
// Add the version-independent ProgID subkey under CLSID key.
|
|
bResult &= setKeyAndValue(szKey, TEXT("VersionIndependentProgID"),
|
|
szVerIndProgID) ;
|
|
|
|
// Add the Type Library ID subkey under the CLSID key.
|
|
bResult &= setKeyAndValue(szKey, TEXT("TypeLib"), szLIBID) ;
|
|
|
|
// Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
|
|
bResult &= setKeyAndValue(szVerIndProgID, NULL, szFriendlyName) ;
|
|
bResult &= setKeyAndValue(szVerIndProgID, TEXT("CLSID"), szCLSID) ;
|
|
bResult &= setKeyAndValue(szVerIndProgID, TEXT("CurVer"), szProgID) ;
|
|
|
|
// Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
|
|
bResult &= setKeyAndValue(szProgID, NULL, szFriendlyName) ;
|
|
bResult &= setKeyAndValue(szProgID, TEXT("CLSID"), szCLSID) ;
|
|
CoTaskMemFree(pszCLSID);
|
|
CoTaskMemFree(pszLIBID);
|
|
|
|
if (bResult) {
|
|
return S_OK;
|
|
}
|
|
else {
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* UnregisterServer
|
|
*
|
|
* DESCRIPTION:
|
|
* Remove a COM component from the registry. From Inside COM.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT UnregisterServer(
|
|
const CLSID* pclsid,
|
|
LPCTSTR szVerIndProgID,
|
|
LPCTSTR szProgID,
|
|
LPCTSTR szService)
|
|
{
|
|
// Convert the CLSID into a char.
|
|
LPOLESTR pszCLSID;
|
|
|
|
HRESULT hr = StringFromCLSID(*pclsid, &pszCLSID);
|
|
|
|
if (FAILED(hr) || !pszCLSID) {
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
TCHAR szCLSID[64];
|
|
|
|
#ifdef UNICODE
|
|
lstrcpy(szCLSID, pszCLSID);
|
|
#else
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pszCLSID,
|
|
-1,
|
|
szCLSID,
|
|
sizeof(szCLSID),
|
|
NULL,
|
|
NULL);
|
|
#endif
|
|
|
|
// Build the key CLSID\\{...}
|
|
TCHAR szKey[64] = TEXT("CLSID\\");
|
|
lstrcat(szKey, szCLSID) ;
|
|
|
|
// Delete the CLSID Key - CLSID\{...}
|
|
LONG lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szKey);
|
|
if ((lResult != ERROR_SUCCESS) &&
|
|
(lResult != ERROR_FILE_NOT_FOUND)) {
|
|
return HRESULT_FROM_WIN32(lResult);
|
|
}
|
|
|
|
// Delete the AppID Key - AppID\{...}
|
|
if (szService) {
|
|
TCHAR szAppID[64] = TEXT("AppID\\");
|
|
lstrcat(szAppID, szCLSID) ;
|
|
|
|
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szAppID);
|
|
if ((lResult != ERROR_SUCCESS) &&
|
|
(lResult != ERROR_FILE_NOT_FOUND)) {
|
|
return HRESULT_FROM_WIN32(lResult);
|
|
}
|
|
}
|
|
|
|
// Delete the version-independent ProgID Key.
|
|
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID);
|
|
if ((lResult != ERROR_SUCCESS) &&
|
|
(lResult != ERROR_FILE_NOT_FOUND)) {
|
|
return HRESULT_FROM_WIN32(lResult);
|
|
}
|
|
|
|
// Delete the ProgID key.
|
|
lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID);
|
|
if ((lResult != ERROR_SUCCESS) &&
|
|
(lResult != ERROR_FILE_NOT_FOUND)) {
|
|
return HRESULT_FROM_WIN32(lResult);
|
|
}
|
|
|
|
CoTaskMemFree(pszCLSID);
|
|
return S_OK ;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* recursiveDeleteKey
|
|
*
|
|
* DESCRIPTION:
|
|
* Delete a key and all of its descendents. From Inside COM.
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
LONG recursiveDeleteKey(
|
|
HKEY hKeyParent,
|
|
LPCTSTR lpszKeyChild
|
|
)
|
|
{
|
|
// Open the child.
|
|
HKEY hKeyChild ;
|
|
LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,
|
|
KEY_ALL_ACCESS, &hKeyChild) ;
|
|
if (lRes != ERROR_SUCCESS)
|
|
{
|
|
return lRes ;
|
|
}
|
|
|
|
// Enumerate all of the decendents of this child.
|
|
FILETIME time ;
|
|
TCHAR szBuffer[256] ;
|
|
DWORD dwSize = 256 ;
|
|
while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,
|
|
NULL, NULL, &time) == S_OK)
|
|
{
|
|
// Delete the decendents of this child.
|
|
lRes = recursiveDeleteKey(hKeyChild, szBuffer) ;
|
|
if (lRes != ERROR_SUCCESS)
|
|
{
|
|
// Cleanup before exiting.
|
|
RegCloseKey(hKeyChild) ;
|
|
return lRes;
|
|
}
|
|
dwSize = 256 ;
|
|
}
|
|
|
|
// Close the child.
|
|
RegCloseKey(hKeyChild) ;
|
|
|
|
// Delete this child.
|
|
return RegDeleteKey(hKeyParent, lpszKeyChild) ;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* SubkeyExists
|
|
*
|
|
* DESCRIPTION:
|
|
* Determine if a particular subkey exists. From Inside COM.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOL SubkeyExists(
|
|
LPCTSTR pszPath,
|
|
LPCTSTR szSubkey
|
|
)
|
|
{
|
|
HKEY hKey ;
|
|
TCHAR szKeyBuf[80];
|
|
UINT uSubKeyChars = 0;
|
|
|
|
if (!pszPath) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (szSubkey)
|
|
{
|
|
// The "+1" is for the TEXT("\\")
|
|
uSubKeyChars = lstrlen(szSubkey) + 1;
|
|
}
|
|
|
|
if ((lstrlen(pszPath)+uSubKeyChars) > (sizeof(szKeyBuf) / sizeof(szKeyBuf[0]) - 1)) {
|
|
return FALSE;
|
|
}
|
|
|
|
// Copy keyname into buffer.
|
|
lstrcpy(szKeyBuf, pszPath) ;
|
|
|
|
// Add subkey name to buffer.
|
|
if (szSubkey != NULL)
|
|
{
|
|
lstrcat(szKeyBuf, TEXT("\\")) ;
|
|
lstrcat(szKeyBuf, szSubkey ) ;
|
|
}
|
|
|
|
// Determine if key exists by trying to open it.
|
|
LONG lResult = ::RegOpenKeyEx(HKEY_CLASSES_ROOT,
|
|
szKeyBuf,
|
|
0,
|
|
KEY_READ,
|
|
&hKey) ;
|
|
if (lResult == ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey) ;
|
|
return TRUE ;
|
|
}
|
|
return FALSE ;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* setKeyAndValue
|
|
*
|
|
* DESCRIPTION:
|
|
* Create a key and set its value. From Inside OLE.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOL setKeyAndValue(
|
|
LPCTSTR szKey,
|
|
LPCTSTR szSubkey,
|
|
LPCTSTR szValue)
|
|
{
|
|
HKEY hKey;
|
|
TCHAR szKeyBuf[1024] ;
|
|
BOOL bVal = FALSE;
|
|
UINT uSubKeyChars = 0;
|
|
|
|
if (!szKey) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (szSubkey)
|
|
{
|
|
// the "+1" is for the TEXT("\\")
|
|
uSubKeyChars = lstrlen(szSubkey) + 1;
|
|
}
|
|
|
|
if ((lstrlen(szKey)+uSubKeyChars) > (sizeof(szKeyBuf) / sizeof(szKeyBuf[0]) - 1)) {
|
|
return FALSE;
|
|
}
|
|
|
|
// Copy keyname into buffer.
|
|
lstrcpy(szKeyBuf, szKey) ;
|
|
|
|
// Add subkey name to buffer.
|
|
if (szSubkey != NULL)
|
|
{
|
|
lstrcat(szKeyBuf, TEXT("\\")) ;
|
|
lstrcat(szKeyBuf, szSubkey ) ;
|
|
}
|
|
|
|
// Create and open key and subkey.
|
|
long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,
|
|
szKeyBuf,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS, NULL,
|
|
&hKey, NULL) ;
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
return FALSE ;
|
|
}
|
|
|
|
// Set the Value.
|
|
if (szValue != NULL)
|
|
{
|
|
lResult = RegSetValueEx(hKey, NULL, 0, REG_SZ,
|
|
(BYTE *)szValue,
|
|
(lstrlen(szValue)+1) * sizeof(TCHAR)) ;
|
|
if (lResult == ERROR_SUCCESS) {
|
|
bVal = TRUE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey) ;
|
|
return bVal;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* setValue
|
|
*
|
|
* DESCRIPTION:
|
|
* Create and set a value.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOL setValue(
|
|
LPCTSTR pszKey,
|
|
LPCTSTR pszValueName,
|
|
LPCTSTR pszValue)
|
|
{
|
|
HKEY hKey;
|
|
DWORD dwSize;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (RegOpenKey(HKEY_CLASSES_ROOT, pszKey, &hKey) == ERROR_SUCCESS) {
|
|
|
|
dwSize = (lstrlen(pszValue) + 1) * sizeof(TCHAR);
|
|
if (RegSetValueEx(hKey,
|
|
pszValueName,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE) pszValue,
|
|
dwSize) == ERROR_SUCCESS) {
|
|
bRet = TRUE;
|
|
//
|
|
// NOTE: Leak here on failure - this should be moved out of this block
|
|
//
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* setBinValue
|
|
*
|
|
* DESCRIPTION:
|
|
* Create and set a binary value.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
BOOL setBinValue(
|
|
LPCTSTR pszKey,
|
|
LPCTSTR pszValueName,
|
|
DWORD dwSize,
|
|
BYTE *pbValue)
|
|
{
|
|
HKEY hKey;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (RegOpenKey(HKEY_CLASSES_ROOT, pszKey, &hKey) == ERROR_SUCCESS) {
|
|
|
|
if (RegSetValueEx(hKey,
|
|
pszValueName,
|
|
0,
|
|
REG_BINARY,
|
|
pbValue,
|
|
dwSize) == ERROR_SUCCESS) {
|
|
bRet = TRUE;
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* S T A T I C D A T A
|
|
*
|
|
*******************************************************************************/
|
|
|
|
LONG CFactory::s_cServerLocks = 0; // Count of server locks
|
|
HMODULE CFactory::s_hModule = NULL; // DLL module handle
|
|
DWORD CFactory::s_dwThreadID = 0;
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CFactory constructor
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
CFactory::CFactory(PFACTORY_DATA pFactoryData): m_cRef(1)
|
|
{
|
|
m_pFactoryData = pFactoryData;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CFactory::QueryInterface
|
|
*
|
|
* DESCRIPTION:
|
|
* IUnknown implementation.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT __stdcall CFactory::QueryInterface(REFIID iid, void** ppv)
|
|
{
|
|
if ((iid == IID_IUnknown) || (iid==IID_IClassFactory)) {
|
|
*ppv = (IClassFactory*)this;
|
|
}
|
|
else {
|
|
return E_NOINTERFACE;
|
|
}
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CFactory::AddRef
|
|
* CFactory::Release
|
|
*
|
|
* DESCRIPTION:
|
|
* Reference counting methods.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
ULONG __stdcall CFactory::AddRef()
|
|
{
|
|
return ::InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
ULONG __stdcall CFactory::Release()
|
|
{
|
|
if (::InterlockedDecrement(&m_cRef) == 0) {
|
|
delete this;
|
|
return 0 ;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CreateInstance
|
|
* LockServer
|
|
*
|
|
* DESCRIPTION:
|
|
* Class Factory Interface.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT __stdcall CFactory::CreateInstance(
|
|
IUnknown* pOuter,
|
|
const IID& iid,
|
|
void** ppv
|
|
)
|
|
{
|
|
*ppv = NULL;
|
|
|
|
// No support for aggregation, if we have an outer class then bail.
|
|
if (pOuter) {
|
|
return CLASS_E_NOAGGREGATION;
|
|
}
|
|
|
|
return m_pFactoryData->CreateInstance(iid, ppv);
|
|
}
|
|
|
|
HRESULT __stdcall CFactory::LockServer(BOOL bLock)
|
|
{
|
|
if (bLock) {
|
|
CWiaSvc::AddRef();
|
|
}
|
|
else {
|
|
CWiaSvc::Release();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CFactory::CanUnloadNow
|
|
*
|
|
* DESCRIPTION:
|
|
* Determine if the component can be unloaded.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT CFactory::CanUnloadNow()
|
|
{
|
|
if (IsLocked()) {
|
|
return S_FALSE;
|
|
}
|
|
else {
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CFactory::RegisterUnregisterAll
|
|
*
|
|
* DESCRIPTION:
|
|
* Register/Unregister all components.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
HRESULT CFactory::RegisterUnregisterAll(
|
|
PFACTORY_DATA pFactoryData,
|
|
UINT uiFactoryDataCount,
|
|
BOOLEAN bRegister,
|
|
BOOLEAN bOutProc
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
UINT i;
|
|
|
|
for (i = 0; i < uiFactoryDataCount; i++) {
|
|
if (bRegister) {
|
|
hr = RegisterServer(pFactoryData[i].szModuleFileName,
|
|
pFactoryData[i].pclsid,
|
|
pFactoryData[i].szRegName,
|
|
pFactoryData[i].szVerIndProgID,
|
|
pFactoryData[i].szProgID,
|
|
pFactoryData[i].szService,
|
|
pFactoryData[i].plibid,
|
|
bOutProc);
|
|
}
|
|
else {
|
|
hr = UnregisterServer(pFactoryData[i].pclsid,
|
|
pFactoryData[i].szVerIndProgID,
|
|
pFactoryData[i].szProgID,
|
|
pFactoryData[i].szService);
|
|
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
break;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CFactory::StartFactories
|
|
*
|
|
* DESCRIPTION:
|
|
* Start the class factories.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOL CFactory::StartFactories(
|
|
PFACTORY_DATA pFactoryData,
|
|
UINT uiFactoryDataCount
|
|
)
|
|
{
|
|
PFACTORY_DATA pData, pStart = pFactoryData;
|
|
PFACTORY_DATA pEnd = &pFactoryData[uiFactoryDataCount - 1];
|
|
|
|
|
|
for (pData = pStart; pData <= pEnd; pData++) {
|
|
|
|
// Initialize the class factory pointer and cookie.
|
|
pData->pIClassFactory = NULL;
|
|
pData->dwRegister = NULL;
|
|
|
|
// Create the class factory for this component.
|
|
IClassFactory* pIFactory = new CFactory(pData);
|
|
if (pIFactory) {
|
|
// Register the class factory.
|
|
DWORD dwRegister;
|
|
HRESULT hr = ::CoRegisterClassObject(
|
|
*(pData->pclsid),
|
|
static_cast<IUnknown*>(pIFactory),
|
|
CLSCTX_LOCAL_SERVER,
|
|
REGCLS_MULTIPLEUSE,
|
|
&dwRegister);
|
|
|
|
if (FAILED(hr)) {
|
|
DBG_ERR(("CFactory::StartFactories, CoRegisterClassObject CFactory Failed 0x%X", hr));
|
|
pIFactory->Release();
|
|
return FALSE;
|
|
}
|
|
|
|
// Set the data.
|
|
pData->pIClassFactory = pIFactory;
|
|
pData->dwRegister = dwRegister;
|
|
}
|
|
else {
|
|
DBG_ERR(("CFactory::StartFactories, New CFactory Failed"));
|
|
}
|
|
}
|
|
DBG_TRC(("CFactory::StartFactories, Success"));
|
|
return TRUE;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CFactory::StopFactories
|
|
*
|
|
* DESCRIPTION:
|
|
* Stop the class factories.
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
void CFactory::StopFactories(
|
|
PFACTORY_DATA pFactoryData,
|
|
UINT uiFactoryDataCount
|
|
)
|
|
{
|
|
PFACTORY_DATA pData, pStart = pFactoryData;
|
|
PFACTORY_DATA pEnd = &pFactoryData[uiFactoryDataCount - 1];
|
|
|
|
for (pData = pStart; pData <= pEnd; pData++) {
|
|
|
|
// Get the magic cookie and stop the factory from running.
|
|
DWORD dwRegister = pData->dwRegister;
|
|
if (dwRegister != 0) {
|
|
::CoRevokeClassObject(dwRegister);
|
|
}
|
|
|
|
// Release the class factory.
|
|
IClassFactory* pIFactory = pData->pIClassFactory ;
|
|
if (pIFactory != NULL) {
|
|
pIFactory->Release() ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|