197 lines
4.6 KiB
C++
197 lines
4.6 KiB
C++
|
#include "stdafx.h"
|
||
|
#include "stobject.h"
|
||
|
#include "systray.h"
|
||
|
|
||
|
|
||
|
#include <initguid.h>
|
||
|
// 7007ACCF-3202-11D1-AAD2-00805FC1270E CLSID_ConnectionTray
|
||
|
DEFINE_GUID(CLSID_ConnectionTray, 0x7007ACCF,0x3202,0x11D1,0xAA,0xD2,0x00,0x80,0x5F,0xC1,0x27,0x0E);
|
||
|
|
||
|
IOleCommandTarget *g_pctNetShell = NULL;
|
||
|
|
||
|
extern "C"
|
||
|
{
|
||
|
void StartNetShell()
|
||
|
{
|
||
|
ASSERT(!g_pctNetShell);
|
||
|
|
||
|
HRESULT hr = CoCreateInstance(CLSID_ConnectionTray, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER,
|
||
|
IID_IOleCommandTarget, (void **)&g_pctNetShell);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
g_pctNetShell->Exec(&CGID_ShellServiceObject, SSOCMDID_OPEN, 0, NULL, NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void StopNetShell()
|
||
|
{
|
||
|
if (g_pctNetShell)
|
||
|
{
|
||
|
g_pctNetShell->Exec(&CGID_ShellServiceObject, SSOCMDID_CLOSE, 0, NULL, NULL);
|
||
|
g_pctNetShell->Release();
|
||
|
g_pctNetShell = NULL;
|
||
|
}
|
||
|
}
|
||
|
} // extern C
|
||
|
|
||
|
/************************************************************************************
|
||
|
IUnknown Implementation
|
||
|
|
||
|
************************************************************************************/
|
||
|
|
||
|
HRESULT CSysTray::QueryInterface(REFIID iid, void** ppvObject)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if ((iid == IID_IOleCommandTarget) || (iid == IID_IUnknown))
|
||
|
{
|
||
|
*ppvObject = (IOleCommandTarget*) this;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ppvObject = NULL;
|
||
|
hr = E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
if (hr == S_OK)
|
||
|
{
|
||
|
((IUnknown*) (*ppvObject))->AddRef();
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
ULONG CSysTray::AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement(&m_cRef);
|
||
|
}
|
||
|
|
||
|
ULONG CSysTray::Release()
|
||
|
{
|
||
|
if (InterlockedDecrement(&m_cRef) == 0)
|
||
|
{
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return m_cRef;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
IOleCommandTarget Implementation
|
||
|
|
||
|
************************************************************************************/
|
||
|
|
||
|
HRESULT CSysTray::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT* pCmdText)
|
||
|
{
|
||
|
HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;
|
||
|
|
||
|
if (*pguidCmdGroup == CGID_ShellServiceObject)
|
||
|
{
|
||
|
// We like Shell Service Object notifications...
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CSysTray::Exec(const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG* pvaIn, VARIANTARG* pvaOut)
|
||
|
{
|
||
|
HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;
|
||
|
|
||
|
if (*pguidCmdGroup == CGID_ShellServiceObject)
|
||
|
{
|
||
|
// Handle Shell Service Object notifications here.
|
||
|
switch (nCmdID)
|
||
|
{
|
||
|
case SSOCMDID_OPEN:
|
||
|
hr = CreateSysTrayThread();
|
||
|
break;
|
||
|
|
||
|
case SSOCMDID_CLOSE:
|
||
|
hr = DestroySysTrayWindow();
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
hr = S_OK;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
Constructor/Destructor Implementation
|
||
|
|
||
|
************************************************************************************/
|
||
|
CSysTray::CSysTray(BOOL fRunTrayOnConstruct)
|
||
|
{
|
||
|
m_cRef = 1;
|
||
|
InterlockedIncrement(&g_cLocks);
|
||
|
|
||
|
if (fRunTrayOnConstruct)
|
||
|
{
|
||
|
// We are being called through SHLoadInProc - Launch the systray thread immediately
|
||
|
CreateSysTrayThread();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CSysTray::~CSysTray()
|
||
|
{
|
||
|
InterlockedDecrement(&g_cLocks);
|
||
|
}
|
||
|
|
||
|
/************************************************************************************
|
||
|
Private Function Implementation
|
||
|
|
||
|
************************************************************************************/
|
||
|
|
||
|
HRESULT CSysTray::CreateSysTrayThread()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
HANDLE hThread;
|
||
|
DWORD dwThreadId;
|
||
|
|
||
|
hThread = CreateThread(NULL, 0, CSysTray::SysTrayThreadProc, NULL, 0, &dwThreadId);
|
||
|
if (hThread != NULL)
|
||
|
{
|
||
|
CloseHandle(hThread);
|
||
|
}
|
||
|
else
|
||
|
hr = E_FAIL;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
DWORD CSysTray::SysTrayThreadProc(void* lpv)
|
||
|
{
|
||
|
// We pass a "" for the command line to so that the tray applets dont' start.
|
||
|
TCHAR szModule[MAX_PATH];
|
||
|
|
||
|
GetModuleFileName(g_hinstDll, szModule, ARRAYSIZE(szModule));
|
||
|
|
||
|
HINSTANCE hInstThis = LoadLibrary(szModule);
|
||
|
|
||
|
int Result = SysTrayMain(g_hinstDll, NULL, TEXT(""), SW_SHOWNORMAL);
|
||
|
|
||
|
FreeLibraryAndExitThread(hInstThis, (DWORD) Result);
|
||
|
|
||
|
// Never gets here
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
HRESULT CSysTray::DestroySysTrayWindow()
|
||
|
{
|
||
|
HWND hExistWnd = FindWindow(SYSTRAY_CLASSNAME, NULL);
|
||
|
if (hExistWnd)
|
||
|
{
|
||
|
// Destroy the window. Note that we can't use DestroyWindow since
|
||
|
// the window is on a different thread and DestroyWindow fails.
|
||
|
SendMessage(hExistWnd, WM_CLOSE, 0, 0);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|