[STOBJECT]
[reactos.git] / dll / win32 / stobject / stobject.cpp
1 /*
2 * PROJECT: ReactOS system libraries
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll\win32\stobject\stobject.c
5 * PURPOSE: Systray shell service object
6 * PROGRAMMERS: Copyright 2014 Robert Naumann
7 */
8
9 #include "precomp.h"
10
11 #include <olectl.h>
12
13 WINE_DEFAULT_DEBUG_CHANNEL(stobject);
14
15 const GUID CLSID_SysTray = { 0x35CEC8A3, 0x2BE6, 0x11D2, { 0x87, 0x73, 0x92, 0xE2, 0x20, 0x52, 0x41, 0x53 } };
16
17 class CShellTrayModule : public CComModule
18 {
19 public:
20 };
21
22 class CSysTray :
23 public CComCoClass<CSysTray, &CLSID_SysTray>,
24 public CComObjectRootEx<CComMultiThreadModelNoCS>,
25 public IOleCommandTarget
26 {
27 // TODO: keep icon handlers here
28
29 public:
30 CSysTray() {}
31 virtual ~CSysTray() {}
32
33 // *** IOleCommandTarget methods ***
34 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
35 {
36 UNIMPLEMENTED;
37 return S_OK;
38 }
39
40 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
41 {
42 if (!IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject))
43 return E_FAIL;
44
45 switch (nCmdID)
46 {
47 case OLECMDID_NEW: // init
48 DbgPrint("CSysTray Init TODO: Initialize tray icon handlers.\n");
49 break;
50 case OLECMDID_SAVE: // shutdown
51 DbgPrint("CSysTray Shutdown TODO: Shutdown.\n");
52 break;
53 }
54 return S_OK;
55 }
56
57 DECLARE_REGISTRY_RESOURCEID(IDR_SYSTRAY)
58 DECLARE_NOT_AGGREGATABLE(CSysTray)
59 DECLARE_PROTECT_FINAL_CONSTRUCT()
60
61 BEGIN_COM_MAP(CSysTray)
62 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
63 END_COM_MAP()
64 };
65
66
67 BEGIN_OBJECT_MAP(ObjectMap)
68 OBJECT_ENTRY(CLSID_SysTray, CSysTray)
69 END_OBJECT_MAP()
70
71 CShellTrayModule gModule;
72
73 HINSTANCE g_hInstance;
74
75 HRESULT RegisterShellServiceObject(REFGUID guidClass, LPCWSTR lpName, BOOL bRegister)
76 {
77 const LPCWSTR strRegistryLocation = L"Software\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad";
78
79 OLECHAR strGuid[128]; // shouldn't need so much!
80 LSTATUS ret = 0;
81 HKEY hKey = 0;
82 if (StringFromGUID2(guidClass, strGuid, 128))
83 {
84 if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, strRegistryLocation, 0, KEY_WRITE, &hKey))
85 {
86 if (bRegister)
87 {
88 LONG cbGuid = (lstrlenW(strGuid) + 1) * 2;
89 ret = RegSetValueExW(hKey, lpName, 0, REG_SZ, (const BYTE *) strGuid, cbGuid);
90 }
91 else
92 {
93 ret = RegDeleteValueW(hKey, lpName);
94 }
95 }
96 }
97 if (hKey)
98 RegCloseKey(hKey);
99 return /*HRESULT_FROM_NT*/(ret); // regsvr32 considers anything != S_OK to be an error
100
101 }
102
103 void *operator new (size_t, void *buf)
104 {
105 return buf;
106 }
107
108 BOOL
109 WINAPI
110 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
111 {
112 if (fdwReason == DLL_PROCESS_ATTACH)
113 {
114 /* HACK - the global constructors don't run, so I placement new them here */
115 new (&gModule) CShellTrayModule;
116 new (&_AtlWinModule) CAtlWinModule;
117 new (&_AtlBaseModule) CAtlBaseModule;
118 new (&_AtlComModule) CAtlComModule;
119
120 g_hInstance = hinstDLL;
121 DisableThreadLibraryCalls(g_hInstance);
122
123 gModule.Init(ObjectMap, g_hInstance, NULL);
124 }
125 else if (fdwReason == DLL_PROCESS_DETACH)
126 {
127 g_hInstance = NULL;
128 gModule.Term();
129 }
130 return TRUE;
131 }
132
133 HRESULT
134 WINAPI
135 DllCanUnloadNow(void)
136 {
137 return gModule.DllCanUnloadNow();
138 }
139
140 STDAPI
141 DllRegisterServer(void)
142 {
143 HRESULT hr = gModule.DllRegisterServer(FALSE);
144 if (FAILED(hr))
145 return hr;
146
147 return RegisterShellServiceObject(CLSID_SysTray, L"SysTray", TRUE);
148 }
149
150 STDAPI
151 DllUnregisterServer(void)
152 {
153 RegisterShellServiceObject(CLSID_SysTray, L"SysTray", FALSE);
154
155 return gModule.DllUnregisterServer(FALSE);
156 }
157
158 STDAPI
159 DllGetClassObject(
160 REFCLSID rclsid,
161 REFIID riid,
162 LPVOID *ppv)
163 {
164 return gModule.DllGetClassObject(rclsid, riid, ppv);
165 }