Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

347 lines
6.5 KiB

// Copyright (C) 1999 Microsoft Corporation
//
// DllMain and COM DllXxx functions
//
// sburns 5-3-99
#include "headers.hxx"
#include "implmain.hpp"
HINSTANCE hResourceModuleHandle = 0;
const wchar_t* HELPFILE_NAME = 0;
const wchar_t* RUNTIME_NAME = L"clonepr";
DWORD DEFAULT_LOGGING_OPTIONS = OUTPUT_MUTE;
TCHAR g_szFileName[MAX_PATH];
struct REG_DATA
{
const wchar_t *keyName;
const wchar_t *valueName;
const wchar_t *value;
};
const REG_DATA g_rgEntries[] =
{
{
L"CLSID\\" CLSID_STRING,
0,
CLASSNAME_STRING
},
{
L"CLSID\\" CLSID_STRING L"\\InprocServer32",
0,
g_szFileName
},
{
L"CLSID\\" CLSID_STRING L"\\InprocServer32",
L"ThreadingModel",
L"Apartment"
},
{
L"CLSID\\" CLSID_STRING L"\\ProgID",
0,
PROGID_VERSION_STRING
},
{
L"CLSID\\" CLSID_STRING L"\\VersionIndependentProgID",
0,
PROGID_STRING
},
{
PROGID_VERSION_STRING,
0,
CLASSNAME_STRING
},
{
PROGID_VERSION_STRING L"\\CLSID",
0,
CLSID_STRING
},
{
PROGID_STRING,
0,
CLASSNAME_STRING
},
{
PROGID_STRING L"\\CLSID",
0,
CLSID_STRING
},
{
PROGID_STRING L"\\CurVer",
0,
PROGID_VERSION_STRING
},
// register for IADsSID
{
PROGID_VERSION_STRING_ADSSID,
0,
CLASSNAME_STRING
},
{
PROGID_VERSION_STRING_ADSSID L"\\CLSID",
0,
CLSID_STRING
},
{
PROGID_STRING_ADSSID,
0,
CLASSNAME_STRING
},
{
PROGID_STRING_ADSSID L"\\CLSID",
0,
CLSID_STRING
},
{
PROGID_STRING_ADSSID L"\\CurVer",
0,
PROGID_VERSION_STRING_ADSSID
},
// register for IADsError
{
PROGID_VERSION_STRING_ADSERROR,
0,
CLASSNAME_STRING
},
{
PROGID_VERSION_STRING_ADSERROR L"\\CLSID",
0,
CLSID_STRING
},
{
PROGID_STRING_ADSERROR,
0,
CLASSNAME_STRING
},
{
PROGID_STRING_ADSERROR L"\\CLSID",
0,
CLSID_STRING
},
{
PROGID_STRING_ADSERROR L"\\CurVer",
0,
PROGID_VERSION_STRING_ADSERROR
}
};
const int g_cEntries = sizeof(g_rgEntries)/sizeof(*g_rgEntries);
static
HRESULT
Unregister(const REG_DATA *rgEntries, int cEntries)
{
LOG_FUNCTION(Unregister);
LOG(L"Calling UnRegisterTypeLib");
HRESULT hr =
::UnRegisterTypeLib(LIBID_CloneSecurityPrincipalLib, 1, 0, 0, SYS_WIN32);
LOG_HRESULT(hr);
// don't break: continue on attempting to remove as much as possible
// of our registration
bool success = SUCCEEDED(hr);
for (int i = cEntries - 1; i >= 0; i--)
{
LONG err = ::RegDeleteKey(HKEY_CLASSES_ROOT, rgEntries[i].keyName);
if (err != ERROR_SUCCESS)
{
success = false;
}
}
return success ? S_OK : S_FALSE;
}
static HRESULT Register(const REG_DATA *rgEntries, int cEntries)
{
BOOL bSuccess = TRUE;
HRESULT hr = S_OK; // 447822 prefix warning
const REG_DATA *pEntry = rgEntries;
while (pEntry < rgEntries + cEntries)
{
HKEY hkey;
LONG err = RegCreateKey(HKEY_CLASSES_ROOT,
pEntry->keyName,
&hkey);
if (err == ERROR_SUCCESS)
{
if (pEntry->value)
err = RegSetValueEx(hkey,
pEntry->valueName,
0, REG_SZ,
(const BYTE*)pEntry->value,
(lstrlen(pEntry->value) + 1) * sizeof(TCHAR));
if (err != ERROR_SUCCESS)
{
bSuccess = FALSE;
Unregister(rgEntries, static_cast<int>(1 + pEntry - rgEntries));
}
RegCloseKey(hkey);
}
if (err != ERROR_SUCCESS)
{
bSuccess = FALSE;
if (pEntry != rgEntries)
Unregister(rgEntries, static_cast<int>(pEntry - rgEntries));
}
pEntry++;
};
if (bSuccess)
{
OLECHAR g_wszFileName[MAX_PATH];
lstrcpy(g_wszFileName, g_szFileName);
ITypeLib *ptl = 0;
hr = LoadTypeLib(g_wszFileName, &ptl);
if (SUCCEEDED(hr))
{
hr = RegisterTypeLib(ptl, g_wszFileName, 0);
ptl->Release();
}
if (bSuccess)
hr = S_OK;
else
hr = E_FAIL;
}
return hr ;//bSuccess ? S_OK : E_FAIL;
}
BOOL
APIENTRY
DllMain(HINSTANCE h, DWORD dwReason, void *)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
hResourceModuleHandle = h;
LOG(L"DLL_PROCESS_ATTACH");
// @@ remove this
GetModuleFileName(h, g_szFileName, MAX_PATH);
break;
}
case DLL_PROCESS_DETACH:
{
#ifdef DEBUG_BUILD
LOG(TEXT("DLL_PROCESS_DETACH"));
if (!ComServerLockState::CanUnloadNow())
{
LOG(L"server locks and/or outstanding object instances exit");
}
else
{
LOG(L"server can unload now.");
}
#endif
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
default:
{
break;
}
}
return TRUE;
}
STDAPI
DllRegisterServer()
{
LOG_FUNCTION(DllRegisterServer);
return Register(g_rgEntries, g_cEntries);
}
STDAPI
DllUnregisterServer()
{
LOG_FUNCTION(DllUnregisterServer);
return Unregister(g_rgEntries, g_cEntries);
}
STDAPI
DllCanUnloadNow()
{
LOG_FUNCTION(DllCanUnloadNow);
if (ComServerLockState::CanUnloadNow())
{
return S_OK;
}
return S_FALSE;
}
STDAPI
DllGetClassObject(
const CLSID& classID,
const IID& interfaceID,
void** interfaceDesired)
{
LOG_FUNCTION(DllGetClassObject);
IClassFactory* factory = 0;
// The class objects are instances of ClassFactory<>, which are ref-counted
// in the usual fashion (i.e. they track their ref counts, and
// self-destruct on final Release). I could have used static instances of
// a C++ class that ignored the refcounting (ala Don Box's examples in
// Essential COM)
if (classID == CLSID_CloneSecurityPrincipal)
{
factory = new ClassFactory<CloneSecurityPrincipal>;
}
else
{
*interfaceDesired = 0;
return CLASS_E_CLASSNOTAVAILABLE;
}
// the class factory instance starts with a ref count of 1. If the QI
// fails, then it self-destructs upon Release.
HRESULT hr = factory->QueryInterface(interfaceID, interfaceDesired);
factory->Release();
return hr;
}