windows-nt/Source/XPSP1/NT/shell/ext/systray/dll/dll.cpp
2020-09-26 16:20:57 +08:00

212 lines
6.1 KiB
C++

#include "stdafx.h"
#include <initguid.h>
#include "stobject.h"
#include "cfact.h"
#define DECL_CRTFREE
#include <crtfree.h>
// One lock for each running component + one lock per LockServer call
long g_cLocks = 0;
HINSTANCE g_hinstDll = NULL;
const TCHAR g_szThreadModel[] = TEXT("Both");
STDAPI DllCanUnloadNow()
{
return (g_cLocks == 0);
}
STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppvObject)
{
HRESULT hr = S_OK;
BOOL fRunTrayOnConstruct;
*ppvObject = NULL;
if (clsid == CLSID_SysTray)
{
// The SysTray object is being requested - we don't actually launch the tray thread until
// told to do so though IOleCommandTarget
fRunTrayOnConstruct = FALSE;
}
else if (clsid == CLSID_SysTrayInvoker)
{
// The simple invoker object is being requested - the tray thread will be launched immediately
fRunTrayOnConstruct = TRUE;
}
else
{
// We don't support this object!
hr = CLASS_E_CLASSNOTAVAILABLE;
}
// If one of the two objects we support was requested:
if (SUCCEEDED(hr))
{
// Try to create the object
CSysTrayFactory* ptrayfact = new CSysTrayFactory(fRunTrayOnConstruct);
if (ptrayfact != NULL)
{
hr = ptrayfact->QueryInterface(iid, ppvObject);
ptrayfact->Release();
}
else
{
hr = E_OUTOFMEMORY;
}
}
return hr;
}
BOOL RegisterComponent(const CLSID& clsid, const TCHAR* szProgID)
{
// Build a CLSID string for the registry
BOOL fSuccess = FALSE;
TCHAR szSubkey[MAX_PATH];
TCHAR szCLSID[GUIDSTR_MAX];
TCHAR szModule[MAX_PATH];
HKEY hkeyCLSID = NULL;
HKEY hkeyInproc = NULL;
DWORD dwDisp;
TCHAR* pszNameOnly;
// Try and get all the strings we need
if (StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID)) != 0)
{
if ((GetModuleFileName(g_hinstDll, szModule, ARRAYSIZE(szModule)) != 0) &&
(pszNameOnly = PathFindFileName(szModule)))
{
if (wnsprintf(szSubkey, ARRAYSIZE(szSubkey), TEXT("CLSID\\%s"), szCLSID) > 0)
{
// We've built our strings, so write stuff to the registry
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CLASSES_ROOT, szSubkey, 0,
NULL, 0, KEY_WRITE, NULL, &hkeyCLSID, &dwDisp))
{
RegSetValueEx(hkeyCLSID, NULL, 0, REG_SZ, (const BYTE*) szProgID,
(lstrlen(szProgID) + 1) * sizeof(TCHAR));
if (ERROR_SUCCESS == RegCreateKeyEx(hkeyCLSID, TEXT("InprocServer32"),
0, NULL, 0, KEY_SET_VALUE, NULL, &hkeyInproc, &dwDisp))
{
RegSetValueEx(hkeyInproc, NULL, 0, REG_SZ,
(const BYTE*) szModule, (lstrlen(szModule) + 1) * sizeof(TCHAR));
RegSetValueEx(hkeyInproc, TEXT("ThreadingModel"), 0, REG_SZ,
(const BYTE*) g_szThreadModel, sizeof(g_szThreadModel));
fSuccess = TRUE;
}
}
}
}
}
if (hkeyCLSID != NULL)
RegCloseKey(hkeyCLSID);
if (hkeyInproc != NULL)
RegCloseKey(hkeyInproc);
return fSuccess;
}
BOOL UnregisterComponent(const CLSID& clsid)
{
// Build a CLSID string for the registry
BOOL fSuccess = FALSE;
TCHAR szSubkey[MAX_PATH];
TCHAR szCLSID[GUIDSTR_MAX];
HKEY hkeyCLSID = NULL;
// Try and get all the strings we need
if (StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID)) != 0)
{
if (wnsprintf(szSubkey, ARRAYSIZE(szSubkey), TEXT("CLSID\\%s"), szCLSID) > 0)
{
// We've built our strings, so delete our registry stuff
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szSubkey, 0,
KEY_WRITE, &hkeyCLSID))
{
RegDeleteKey(hkeyCLSID, TEXT("InprocServer32"));
RegCloseKey(hkeyCLSID);
hkeyCLSID = NULL;
RegDeleteKey(HKEY_CLASSES_ROOT, szSubkey);
fSuccess = TRUE;
}
}
}
if (hkeyCLSID != NULL)
RegCloseKey(hkeyCLSID);
return fSuccess;
}
BOOL RegisterShellServiceObject(const CLSID& clsid, const TCHAR* szProgID, BOOL fRegister)
{
const static TCHAR szSubkey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad");
BOOL fSuccess = FALSE;
TCHAR szCLSID[GUIDSTR_MAX];
HKEY hkey = NULL;
// Try and get all the strings we need
if (StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID)) != 0)
{
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubkey, 0,
KEY_WRITE, &hkey))
{
if (fRegister)
{
fSuccess = RegSetValueEx(hkey, szProgID, 0, REG_SZ, (const BYTE*) szCLSID,
(lstrlen(szCLSID) + 1) * sizeof(TCHAR));
}
else
{
fSuccess = RegDeleteValue(hkey, szProgID);
}
}
}
if (hkey != NULL)
RegCloseKey(hkey);
return fSuccess;
}
STDAPI DllRegisterServer()
{
BOOL fSuccess;
fSuccess = RegisterComponent(CLSID_SysTray, TEXT("SysTray"));
fSuccess &= RegisterComponent(CLSID_SysTrayInvoker, TEXT("SysTrayInvoker"));
fSuccess &= RegisterShellServiceObject(CLSID_SysTray, TEXT("SysTray"), TRUE);
return fSuccess;
}
STDAPI DllUnregisterServer()
{
BOOL fSuccess;
fSuccess = UnregisterComponent(CLSID_SysTray);
fSuccess &= UnregisterComponent(CLSID_SysTrayInvoker);
fSuccess &= RegisterShellServiceObject(CLSID_SysTray, TEXT("SysTray"), FALSE);
return fSuccess;
}
STDAPI DllMain(HINSTANCE hModule, DWORD dwReason, void* lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
SHFusionInitializeFromModule(hModule);
// Don't have DllMain called for thread init's.
DisableThreadLibraryCalls(hModule);
g_hinstDll = hModule;
}
else if (dwReason == DLL_PROCESS_DETACH)
{
SHFusionUninitialize();
}
return TRUE;
}