Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / embedding / browser / activex / src / common / IOleCommandTargetImpl.h
blobf712572d0e9aaa089abca621cd7258e431b07f1c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Adam Lock <adamlock@eircom.net>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
38 #ifndef IOLECOMMANDIMPL_H
39 #define IOLECOMMANDIMPL_H
41 // Implementation of the IOleCommandTarget interface. The template is
42 // reasonably generic and reusable which is a good thing given how needlessly
43 // complicated this interface is. Blame Microsoft for that and not me.
45 // To use this class, derive your class from it like this:
47 // class CComMyClass : public IOleCommandTargetImpl<CComMyClass>
48 // {
49 // ... Ensure IOleCommandTarget is listed in the interface map ...
50 // BEGIN_COM_MAP(CComMyClass)
51 // COM_INTERFACE_ENTRY(IOleCommandTarget)
52 // // etc.
53 // END_COM_MAP()
54 // ... And then later on define the command target table ...
55 // BEGIN_OLECOMMAND_TABLE()
56 // OLECOMMAND_MESSAGE(OLECMDID_PRINT, NULL, ID_PRINT, L"Print", L"Print the page")
57 // OLECOMMAND_MESSAGE(OLECMDID_SAVEAS, NULL, 0, L"SaveAs", L"Save the page")
58 // OLECOMMAND_HANDLER(IDM_EDITMODE, &CGID_MSHTML, EditModeHandler, L"EditMode", L"Switch to edit mode")
59 // END_OLECOMMAND_TABLE()
60 // ... Now the window that OLECOMMAND_MESSAGE sends WM_COMMANDs to ...
61 // HWND GetCommandTargetWindow() const
62 // {
63 // return m_hWnd;
64 // }
65 // ... Now procedures that OLECOMMAND_HANDLER calls ...
66 // static HRESULT _stdcall EditModeHandler(CMozillaBrowser *pThis, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
67 // }
69 // The command table defines which commands the object supports. Commands are
70 // defined by a command id and a command group plus a WM_COMMAND id or procedure,
71 // and a verb and short description.
73 // Notice that there are two macros for handling Ole Commands. The first,
74 // OLECOMMAND_MESSAGE sends a WM_COMMAND message to the window returned from
75 // GetCommandTargetWindow() (that the derived class must implement if it uses
76 // this macro).
78 // The second, OLECOMMAND_HANDLER calls a static handler procedure that
79 // conforms to the OleCommandProc typedef. The first parameter, pThis means
80 // the static handler has access to the methods and variables in the class
81 // instance.
83 // The OLECOMMAND_HANDLER macro is generally more useful when a command
84 // takes parameters or needs to return a result to the caller.
86 template< class T >
87 class IOleCommandTargetImpl : public IOleCommandTarget
89 struct OleExecData
91 const GUID *pguidCmdGroup;
92 DWORD nCmdID;
93 DWORD nCmdexecopt;
94 VARIANT *pvaIn;
95 VARIANT *pvaOut;
98 public:
99 typedef HRESULT (_stdcall *OleCommandProc)(T *pT, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
101 struct OleCommandInfo
103 ULONG nCmdID;
104 const GUID *pCmdGUID;
105 ULONG nWindowsCmdID;
106 OleCommandProc pfnCommandProc;
107 wchar_t *szVerbText;
108 wchar_t *szStatusText;
111 // Query the status of the specified commands (test if is it supported etc.)
112 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID __RPC_FAR *pguidCmdGroup, ULONG cCmds, OLECMD __RPC_FAR prgCmds[], OLECMDTEXT __RPC_FAR *pCmdText)
114 T* pT = static_cast<T*>(this);
116 if (prgCmds == NULL)
118 return E_INVALIDARG;
121 OleCommandInfo *pCommands = pT->GetCommandTable();
122 ATLASSERT(pCommands);
124 BOOL bCmdGroupFound = FALSE;
125 BOOL bTextSet = FALSE;
127 // Iterate through list of commands and flag them as supported/unsupported
128 for (ULONG nCmd = 0; nCmd < cCmds; nCmd++)
130 // Unsupported by default
131 prgCmds[nCmd].cmdf = 0;
133 // Search the support command list
134 for (int nSupported = 0; pCommands[nSupported].pCmdGUID != &GUID_NULL; nSupported++)
136 OleCommandInfo *pCI = &pCommands[nSupported];
138 if (pguidCmdGroup && pCI->pCmdGUID && memcmp(pguidCmdGroup, pCI->pCmdGUID, sizeof(GUID)) == 0)
140 continue;
142 bCmdGroupFound = TRUE;
144 if (pCI->nCmdID != prgCmds[nCmd].cmdID)
146 continue;
149 // Command is supported so flag it and possibly enable it
150 prgCmds[nCmd].cmdf = OLECMDF_SUPPORTED;
151 if (pCI->nWindowsCmdID != 0)
153 prgCmds[nCmd].cmdf |= OLECMDF_ENABLED;
156 // Copy the status/verb text for the first supported command only
157 if (!bTextSet && pCmdText)
159 // See what text the caller wants
160 wchar_t *pszTextToCopy = NULL;
161 if (pCmdText->cmdtextf & OLECMDTEXTF_NAME)
163 pszTextToCopy = pCI->szVerbText;
165 else if (pCmdText->cmdtextf & OLECMDTEXTF_STATUS)
167 pszTextToCopy = pCI->szStatusText;
170 // Copy the text
171 pCmdText->cwActual = 0;
172 memset(pCmdText->rgwz, 0, pCmdText->cwBuf * sizeof(wchar_t));
173 if (pszTextToCopy)
175 // Don't exceed the provided buffer size
176 size_t nTextLen = wcslen(pszTextToCopy);
177 if (nTextLen > pCmdText->cwBuf)
179 nTextLen = pCmdText->cwBuf;
182 wcsncpy(pCmdText->rgwz, pszTextToCopy, nTextLen);
183 pCmdText->cwActual = nTextLen;
186 bTextSet = TRUE;
188 break;
192 // Was the command group found?
193 if (!bCmdGroupFound)
195 OLECMDERR_E_UNKNOWNGROUP;
198 return S_OK;
202 // Execute the specified command
203 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID __RPC_FAR *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT __RPC_FAR *pvaIn, VARIANT __RPC_FAR *pvaOut)
205 T* pT = static_cast<T*>(this);
206 BOOL bCmdGroupFound = FALSE;
208 OleCommandInfo *pCommands = pT->GetCommandTable();
209 ATLASSERT(pCommands);
211 // Search the support command list
212 for (int nSupported = 0; pCommands[nSupported].pCmdGUID != &GUID_NULL; nSupported++)
214 OleCommandInfo *pCI = &pCommands[nSupported];
216 if (pguidCmdGroup && pCI->pCmdGUID && memcmp(pguidCmdGroup, pCI->pCmdGUID, sizeof(GUID)) == 0)
218 continue;
220 bCmdGroupFound = TRUE;
222 if (pCI->nCmdID != nCmdID)
224 continue;
227 // Send ourselves a WM_COMMAND windows message with the associated
228 // identifier and exec data
229 OleExecData cData;
230 cData.pguidCmdGroup = pguidCmdGroup;
231 cData.nCmdID = nCmdID;
232 cData.nCmdexecopt = nCmdexecopt;
233 cData.pvaIn = pvaIn;
234 cData.pvaOut = pvaOut;
236 if (pCI->pfnCommandProc)
238 pCI->pfnCommandProc(pT, pCI->pCmdGUID, pCI->nCmdID, nCmdexecopt, pvaIn, pvaOut);
240 else if (pCI->nWindowsCmdID != 0 && nCmdexecopt != OLECMDEXECOPT_SHOWHELP)
242 HWND hwndTarget = pT->GetCommandTargetWindow();
243 if (hwndTarget)
245 ::SendMessage(hwndTarget, WM_COMMAND, LOWORD(pCI->nWindowsCmdID), (LPARAM) &cData);
248 else
250 // Command supported but not implemented
251 continue;
254 return S_OK;
257 // Was the command group found?
258 if (!bCmdGroupFound)
260 OLECMDERR_E_UNKNOWNGROUP;
263 return OLECMDERR_E_NOTSUPPORTED;
267 // Macros to be placed in any class derived from the IOleCommandTargetImpl
268 // class. These define what commands are exposed from the object.
270 #define BEGIN_OLECOMMAND_TABLE() \
271 OleCommandInfo *GetCommandTable() \
273 static OleCommandInfo s_aSupportedCommands[] = \
276 #define OLECOMMAND_MESSAGE(id, group, cmd, verb, desc) \
277 { id, group, cmd, NULL, verb, desc },
279 #define OLECOMMAND_HANDLER(id, group, handler, verb, desc) \
280 { id, group, 0, handler, verb, desc },
282 #define END_OLECOMMAND_TABLE() \
283 { 0, &GUID_NULL, 0, NULL, NULL, NULL } \
284 }; \
285 return s_aSupportedCommands; \
288 #endif