348 lines
6.5 KiB
C++
348 lines
6.5 KiB
C++
|
// 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;
|
||
|
}
|