dmose%mozilla.org 83e38c06cc updated license boilerplate to xPL v1.1
git-svn-id: svn://10.0.0.236/trunk@52594 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-02 22:43:10 +00:00

374 lines
10 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "dllcom.h"
#include <shellapi.h>
HINSTANCE CComDll::m_hInstance = NULL;
#ifdef DLL_DEBUG
// Set this to your module name if you need something
// more specific in your derived constructor.
const char *CComDll::m_pTraceID = "CComDll";
#endif
HINSTANCE CComDll::GetInstanceHandle()
{
// Should be non null by the time this
// gets called.
DLL_ASSERT(m_hInstance);
return(m_hInstance);
}
CComDll::CComDll()
{
// No COM objects created yet.
m_ulCount = 0;
// Be sure to register this instance with the
// process ID map.
m_pEntry = new CProcessEntry(this);
DLL_ASSERT(m_pEntry);
// Add a reference upon creation.
AddRef();
}
CComDll::~CComDll()
{
DLL_ASSERT(m_ulCount == 0);
// Unregister us from this particular process.
if(m_pEntry) {
delete m_pEntry;
m_pEntry = NULL;
}
}
HRESULT CComDll::QueryInterface(REFIID rIid, void **ppObj) {
HRESULT hRetval = ResultFromScode(E_NOINTERFACE);
*ppObj = NULL;
// Just check to see if we should return our IUnknown
// implementation.
if(IsEqualIID(rIid, IID_IUnknown)) {
AddRef();
*ppObj = (void *)((IUnknown *)this);
hRetval = ResultFromScode(S_OK);
}
return(hRetval);
}
DWORD CComDll::AddRef()
{
m_ulCount++;
return(m_ulCount);
}
DWORD CComDll::Release()
{
m_ulCount--;
DWORD ulRetval = m_ulCount;
if(!m_ulCount) {
delete this;
}
// DO NOTHING BETWEEN THE DELETE AND RETURN
// EXCEPT RETURN STACK DATA.
return(ulRetval);
}
// Given a CLSID, copies the string for registering the CLSID as an in-proc server
// into the specified buffer
static HRESULT
BuildRegistryCLSIDKey(REFGUID rGuid, LPSTR szStringKey)
{
// Convert the CLSID to a string.
LPSTR lpszGuid = DLL_StringFromCLSID(rGuid);
if (!lpszGuid)
return ResultFromScode(E_OUTOFMEMORY);
// Get the information into key format.
#ifdef _WIN32
wsprintf(szStringKey, "CLSID\\%s\\InprocServer32", lpszGuid);
#else
wsprintf(szStringKey, "CLSID\\%s\\InprocServer", lpszGuid);
#endif
// Free off the string
CoTaskMemFree(lpszGuid);
return NOERROR;
}
// Make registry entries for implemented CLSIDs.
// As DllRegisterServer.
HRESULT CComDll::RegisterServer()
{
HRESULT hres = ResultFromScode(E_UNEXPECTED);
// Determine our module (dll) path and name.
char szModuleName[_MAX_PATH];
DWORD dwModuleNameLen;
dwModuleNameLen = GetModuleFileName(szModuleName, sizeof(szModuleName));
if (dwModuleNameLen == 0)
return hres;
// Get the list of CLSIDs
const CLSID **ppCLSIDs = GetCLSIDs();
if (ppCLSIDs) {
const CLSID **ppTraverse = ppCLSIDs;
char szStringKey[80];
while (*ppTraverse) {
// Get the information into registry key format.
hres = BuildRegistryCLSIDKey(**ppTraverse, szStringKey);
if (FAILED(hres))
break;
// Set the registry key.
if (RegSetValue(HKEY_CLASSES_ROOT, szStringKey, REG_SZ, szModuleName, dwModuleNameLen) != ERROR_SUCCESS) {
hres = ResultFromScode(/*SELFREG_E_CLASS*/ E_UNEXPECTED);
break;
}
// Get the next CLSID
ppTraverse++;
}
// Only if we made it all the way through the loop do we consider this a success
if (*ppTraverse == NULL)
hres = NOERROR;
// Free off the list of CLSIDs
CoTaskMemFree((LPVOID)ppCLSIDs);
}
return hres;
}
// Return name of module.
DWORD CComDll::GetModuleFileName(char *pOutName, size_t stOutSize, BOOL bFullPath)
{
DWORD dwRetval = 0;
dwRetval = ::GetModuleFileName(GetInstanceHandle(), pOutName, stOutSize);
if(dwRetval && FALSE == bFullPath) {
// Don't return the full path, split it up to the filename only.
char aName[_MAX_FNAME];
char aExt[_MAX_EXT];
_splitpath(pOutName, NULL, NULL, aName, aExt);
strcpy(pOutName, aName);
strcat(pOutName, aExt);
dwRetval = strlen(pOutName);
}
return(dwRetval);
}
// Remove registry entries for implemented CLSIDs.
// As DllUnregisterServer.
HRESULT CComDll::UnregisterServer()
{
HRESULT hres = ResultFromScode(E_UNEXPECTED);
// Determine our module (dll) path and name.
char szModuleName[_MAX_PATH];
DWORD dwModuleNameLen;
dwModuleNameLen = GetModuleFileName(szModuleName, sizeof(szModuleName));
if (dwModuleNameLen == 0)
return hres;
// Get the list of CLSIDs
const CLSID **ppCLSIDs = GetCLSIDs();
if (ppCLSIDs) {
const CLSID **ppTraverse = ppCLSIDs;
char szStringKey[80];
while (*ppTraverse) {
LONG lSize;
// Get the information into registry key format.
hres = BuildRegistryCLSIDKey(**ppTraverse, szStringKey);
if (FAILED(hres))
break;
// Figure out if it points to us.
// Continue if err, as it simply may not exist.
if (RegQueryValue(HKEY_CLASSES_ROOT, szStringKey, NULL, &lSize) == ERROR_SUCCESS && lSize != 0) {
LPSTR lpszValue = NULL;
// Allocate a buffer large enough for it.
lpszValue = (LPSTR)CoTaskMemAlloc(lSize);
if (!lpszValue) {
hres = ResultFromScode(E_OUTOFMEMORY);
break;
}
// We do err on not being able to query the value if we got the size
if (RegQueryValue(HKEY_CLASSES_ROOT, szStringKey, lpszValue, &lSize) != ERROR_SUCCESS) {
hres = ResultFromScode(E_UNEXPECTED);
CoTaskMemFree(lpszValue);
break;
}
// Only delete if the same; ignore the case
if (lstrcmpi(lpszValue, szModuleName) == 0) {
// Delete the registry key.
if (RegDeleteKey(HKEY_CLASSES_ROOT, szStringKey) != ERROR_SUCCESS) {
hres = ResultFromScode(/*SELFREG_E_CLASS*/ E_UNEXPECTED);
break;
}
}
// Free the buffer
CoTaskMemFree(lpszValue);
}
// Get the next CLSID
ppTraverse++;
}
// Only if we made it through the loop do we consider this a success
if (*ppTraverse == NULL)
hres = NOERROR;
// Free off the list of CLSIDs
CoTaskMemFree((LPVOID)ppCLSIDs);
}
return hres;
}
// These routines contain the only entry points into your
// end consumer DLL.
// You must implement the functions which it calls to
// your own satisfaction.
// Standard COM callback to usually obtain an IClassFactory.
STDAPI DllGetClassObject(REFCLSID rClsid, REFIID rIid, LPVOID *ppObj)
{
HRESULT hRetval;
*ppObj = NULL;
// Under 16 bits, it is imperative to seperate out each task
// which uses this DLL so that they don't all use
// the same memory heap, but instead use task specific
// memory.
// Find the abstract Dll instance for the current task.
CComDll *pDll = CProcess::GetProcessDll();
if(pDll) {
// Do it.
hRetval = pDll->GetClassObject(rClsid, rIid, ppObj);
// Take off a reference here.
// This may also cause the instance data to self
// self destruct if no objects were created
// in the GetClassObject call.
pDll->Release();
pDll = NULL;
}
else {
hRetval = ResultFromScode(E_OUTOFMEMORY);
}
return(hRetval);
}
// Standard COM callback to see if the DLL can now be unloaded.
// This is actually never called on 16 bits (via the
// CoFreeUnusedLibraries call), but would work if that
// mechanism is ever fixed.
STDAPI DllCanUnloadNow(void)
{
HRESULT hRetval = ResultFromScode(S_FALSE);
// We tell if we can unload by simply checking if
// our process list of instance DLL objects is
// empty. If not empty, we can not unload.
if(CProcess::CanUnloadNow()) {
hRetval = ResultFromScode(S_OK);
DLL_TRACE("DllCanUnloadNow is TRUE\n");
}
return(hRetval);
}
STDAPI DllRegisterServer(void)
{
HRESULT hRetval;
// Find the abstract Dll instance for the current task.
CComDll *pDll = CProcess::GetProcessDll();
if(pDll) {
// Do it.
hRetval = pDll->RegisterServer();
// Take off a reference here.
// This should cause the instance data to self
// self destruct if no objects were created
// in the GetClassObject call.
pDll->Release();
pDll = NULL;
}
else {
hRetval = ResultFromScode(E_OUTOFMEMORY);
}
return(hRetval);
}
STDAPI DllUnregisterServer(void)
{
HRESULT hRetval;
// Find the abstract Dll instance for the current task.
CComDll *pDll = CProcess::GetProcessDll();
if(pDll) {
// Do it.
hRetval = pDll->UnregisterServer();
// Take off a reference here.
// This should cause the instance data to self
// self destruct if no objects were created
// in the GetClassObject call.
pDll->Release();
pDll = NULL;
}
else {
hRetval = ResultFromScode(E_OUTOFMEMORY);
}
return(hRetval);
}