ReactOS 0.4.16-dev-109-gf4cb10f
dde.cpp
Go to the documentation of this file.
1/*
2 * Shell DDE Handling
3 *
4 * Copyright 2004 Robert Shearman
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include "shelldesktop.h"
22#include <ddeml.h>
23#include <strsafe.h>
24
26
27typedef DWORD(CALLBACK * pfnCommandHandler)(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS);
28
30{
33};
34
36extern const int HandlerListLength;
37
38/* DDE Instance ID */
40
41/* String handles */
42static HSZ hszProgmanTopic;
44static HSZ hszShell;
46static HSZ hszFolders;
47
49
50static BOOL Dde_OnConnect(HSZ hszTopic, HSZ hszService)
51{
52 WCHAR szTopic[MAX_PATH];
53 WCHAR szService[MAX_PATH];
54
56 DdeQueryStringW(dwDDEInst, hszService, szService, _countof(szService), CP_WINUNICODE);
57
58 TRACE("Dde_OnConnect: topic=%S, service=%S\n", szTopic, szService);
59
60 return TRUE;
61}
62
63static void Dde_OnConnectConfirm(HCONV hconv, HSZ hszTopic, HSZ hszService)
64{
65 WCHAR szTopic[MAX_PATH];
66 WCHAR szService[MAX_PATH];
67
69 DdeQueryStringW(dwDDEInst, hszService, szService, _countof(szService), CP_WINUNICODE);
70
71 TRACE("Dde_OnConnectConfirm: hconv=%p, topic=%S, service=%S\n", hconv, szTopic, szService);
72}
73
74static BOOL Dde_OnWildConnect(HSZ hszTopic, HSZ hszService)
75{
76 WCHAR szTopic[MAX_PATH];
77 WCHAR szService[MAX_PATH];
78
80 DdeQueryStringW(dwDDEInst, hszService, szService, _countof(szService), CP_WINUNICODE);
81
82 TRACE("Dde_OnWildConnect: topic=%S, service=%S\n", szTopic, szService);
83
84 return FALSE;
85}
86
87static HDDEDATA Dde_OnRequest(UINT uFmt, HCONV hconv, HSZ hszTopic, HSZ hszItem)
88{
89 WCHAR szTopic[MAX_PATH];
90 WCHAR szItem[MAX_PATH];
91
93 DdeQueryStringW(dwDDEInst, hszItem, szItem, _countof(szItem), CP_WINUNICODE);
94
95 TRACE("Dde_OnRequest: uFmt=%d, hconv=%p, topic=%S, item=%S\n", hconv, szTopic, szItem);
96
97 return NULL;
98}
99
101{
103
104 // Ensure it really is an IDLIST-formatted parameter
105 // Format for IDLIST params: ":pid:shared"
106 if (*strField != L':')
107 return NULL;
108
109 HANDLE hData = UlongToHandle(StrToIntW(strField + 1));
110 PWSTR strSecond = StrChrW(strField + 1, L':');
111
112 if (strSecond)
113 {
114 int pid = StrToIntW(strSecond + 1);
115 void* pvShared = SHLockShared(hData, pid);
116 if (pvShared)
117 {
118 ret = ILClone((LPCITEMIDLIST) pvShared);
119 SHUnlockShared(pvShared);
120 SHFreeShared(hData, pid);
121 }
122 }
123 return ret;
124}
125
126static DWORD Dde_OnExecute(HCONV hconv, HSZ hszTopic, HDDEDATA hdata)
127{
128 WCHAR szTopic[MAX_PATH];
129 WCHAR szCommand[MAX_PATH];
130 WCHAR *pszCommand;
131
133
134 pszCommand = (WCHAR*) DdeAccessData(hdata, NULL);
135 if (!pszCommand)
136 return DDE_FNOTPROCESSED;
137
138 StringCchCopyW(szCommand, _countof(szCommand), pszCommand);
139
140 DdeUnaccessData(hdata);
141
142 TRACE("Dde_OnExecute: hconv=%p, topic=%S, command=%S\n", hconv, szTopic, pszCommand);
143
144 /*
145 [ViewFolder("%l", %I, %S)] -- Open a folder in standard mode
146 [ExploreFolder("%l", %I, %S)] -- Open a folder in "explore" mode (file tree is shown to the left by default)
147 [FindFolder("%l", %I)] -- Open a folder in "find" mode (search panel is shown to the left by default)
148 [ShellFile("%1","%1",%S)] -- Execute the contents of the specified .SCF file
149
150 Approximate grammar (Upper names define rules, <lower> names define terminals, single-quotes are literals):
151
152 Rules
153 Command = ('[' Function ']') | Function
154 Function = <identifier> '(' Parameters ')'
155 Parameters = (<quoted-string> (',' <idlist> (',' <number>)?)?)?
156
157 Terminals
158 <identifier> = [a-zA-Z]+
159 <quoted-string> = \"([^\"]|\\.)\"
160 <idlist> = \:[0-9]+\:[0-9]+
161 <number> = [0-9]+
162 */
163
164 WCHAR Command[MAX_PATH] = L"";
165 WCHAR Path[MAX_PATH] = L"";
166 LPITEMIDLIST IdList = NULL;
167 INT UnknownParameter = 0;
168
169 // Simplified parsing (assumes the command will not be TOO broken):
170
171 PWSTR cmd = szCommand;
172 // 1. if starts with [, skip first char
173 if (*cmd == L'[')
174 cmd++;
175
176 if (*cmd == L']')
177 {
178 ERR("Empty command. Nothing to run.\n");
179 return DDE_FNOTPROCESSED;
180 }
181
182 // Read until first (, and take text before ( as command name
183 {
184 PWSTR cmdEnd = StrChrW(cmd, L'(');
185
186 if (!cmdEnd)
187 {
188 ERR("Could not find '('. Invalid command.\n");
189 return DDE_FNOTPROCESSED;
190 }
191
192 *cmdEnd = 0;
193
195
196 cmd = cmdEnd + 1;
197 }
198
199 // Read first param after (, expecting quoted string
200 if (*cmd != L')')
201 {
202 // Copy unescaped string
203 PWSTR dst = Path;
204 BOOL isQuote = FALSE;
205
206 PWSTR arg = cmd;
207
208 while (*arg && (isQuote || *arg != L','))
209 {
210 if (*arg == L'"')
211 {
212 isQuote = !isQuote;
213 if (isQuote && arg != cmd) // do not copy the " at the beginning of the string
214 {
215 *(dst++) = L'"';
216 }
217 }
218 else
219 {
220 *(dst++) = *arg;
221 }
222
223 arg++;
224 }
225
226 cmd = arg + 1;
227
228 while (*cmd == L' ')
229 cmd++;
230 }
231
232 // Read second param, expecting an idlist in shared memory
233 if (*cmd != L')')
234 {
235 if (*cmd != ':')
236 {
237 ERR("Expected ':'. Invalid command.\n");
238 return DDE_FNOTPROCESSED;
239 }
240
241 PWSTR idlistEnd = StrChrW(cmd, L',');
242
243 if (!idlistEnd)
244 idlistEnd = StrChrW(cmd, L')');
245
246 if (!idlistEnd)
247 {
248 ERR("Expected ',' or ')'. Invalid command.\n");
249 return DDE_FNOTPROCESSED;
250 }
251
253
254 cmd = idlistEnd + 1;
255 }
256
257 // Read third param, expecting an integer
258 if (*cmd != L')')
259 {
260 UnknownParameter = StrToIntW(cmd);
261 }
262
263 TRACE("Parse end: cmd=%S, S=%d, pidl=%p, path=%S\n", Command, UnknownParameter, IdList, Path);
264
265 // Find handler in list
266 for (int i = 0; i < HandlerListLength; i++)
267 {
269 if (StrCmpW(handler.Command, Command) == 0)
270 {
271 return handler.Handler(Command, Path, IdList, UnknownParameter);
272 }
273 }
274
275 // No handler found
276 ERR("Unknown command %S\n", Command);
277 return DDE_FNOTPROCESSED;
278}
279
280static void Dde_OnDisconnect(HCONV hconv)
281{
282 TRACE("Dde_OnDisconnect: hconv=%p\n", hconv);
283}
284
285static HDDEDATA CALLBACK DdeCallback(
286 UINT uType,
287 UINT uFmt,
288 HCONV hconv,
289 HSZ hsz1,
290 HSZ hsz2,
291 HDDEDATA hdata,
292 ULONG_PTR dwData1,
293 ULONG_PTR dwData2)
294{
295 switch (uType)
296 {
297 case XTYP_CONNECT:
298 return (HDDEDATA) (DWORD_PTR) Dde_OnConnect(hsz1, hsz2);
300 Dde_OnConnectConfirm(hconv, hsz1, hsz2);
301 return NULL;
302 case XTYP_WILDCONNECT:
303 return (HDDEDATA) (DWORD_PTR) Dde_OnWildConnect(hsz1, hsz2);
304 case XTYP_REQUEST:
305 return Dde_OnRequest(uFmt, hconv, hsz1, hsz2);
306 case XTYP_EXECUTE:
307 return (HDDEDATA) (DWORD_PTR) Dde_OnExecute(hconv, hsz1, hdata);
308 case XTYP_DISCONNECT:
309 Dde_OnDisconnect(hconv);
310 return NULL;
311 case XTYP_REGISTER:
312 return NULL;
313 default:
314 WARN("DdeCallback: unknown uType=%d\n", uType);
315 return NULL;
316 }
317}
318/*************************************************************************
319 * ShellDDEInit (SHELL32.@)
320 *
321 * Registers the Shell DDE services with the system so that applications
322 * can use them.
323 *
324 * PARAMS
325 * bInit [I] TRUE to initialize the services, FALSE to uninitialize.
326 *
327 * RETURNS
328 * Nothing.
329 */
331{
332 TRACE("ShellDDEInit bInit = %s\n", bInit ? "TRUE" : "FALSE");
333
334 if (bInit && !bInitialized)
335 {
337
343
349 {
351 }
352 }
353 else if (!bInit && bInitialized)
354 {
355 /* unregister all services */
357
358 if (hszFolders)
362 if (hszShell)
366 if (hszProgmanTopic)
368
370
372 }
373}
374
375static DWORD CALLBACK DDE_OnViewFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
376{
377 if (!pidl)
378 pidl = ILCreateFromPathW(strPath);
379
380 if (!pidl)
381 return DDE_FNOTPROCESSED;
382
383 if (FAILED(SHOpenNewFrame(pidl, NULL, 0, 0)))
384 return DDE_FNOTPROCESSED;
385
386 return DDE_FACK;
387}
388
389static DWORD CALLBACK DDW_OnExploreFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
390{
391 if (!pidl)
392 pidl = ILCreateFromPathW(strPath);
393
394 if (!pidl)
395 return DDE_FNOTPROCESSED;
396
398 return DDE_FNOTPROCESSED;
399
400 return DDE_FACK;
401}
402
403static DWORD CALLBACK DDE_OnFindFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
404{
406 return DDE_FNOTPROCESSED;
407}
408
409static DWORD CALLBACK DDE_OnShellFile(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
410{
412 return DDE_FNOTPROCESSED;
413}
414
416
417 { L"ViewFolder", DDE_OnViewFolder },
418 { L"ExploreFolder", DDW_OnExploreFolder },
419 { L"FindFolder", DDE_OnFindFolder },
420 { L"ShellFile", DDE_OnShellFile }
421};
422
PRTL_UNICODE_STRING_BUFFER Path
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define EXTERN_C
Definition: basetyps.h:12
#define UNIMPLEMENTED
Definition: debug.h:118
#define SH_EXPLORER_CMDLINE_FLAG_E
static HSZ hszProgmanTopic
Definition: dde.cpp:42
static HSZ hszFolders
Definition: dde.cpp:46
static LPITEMIDLIST _ILReadFromSharedMemory(PCWSTR strField)
Definition: dde.cpp:100
static BOOL Dde_OnConnect(HSZ hszTopic, HSZ hszService)
Definition: dde.cpp:50
static DWORD CALLBACK DDW_OnExploreFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
Definition: dde.cpp:389
static void Dde_OnDisconnect(HCONV hconv)
Definition: dde.cpp:280
static DWORD CALLBACK DDE_OnShellFile(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
Definition: dde.cpp:409
static DWORD dwDDEInst
Definition: dde.cpp:39
static DWORD Dde_OnExecute(HCONV hconv, HSZ hszTopic, HDDEDATA hdata)
Definition: dde.cpp:126
static DWORD CALLBACK DDE_OnFindFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
Definition: dde.cpp:403
DDECommandHandler HandlerList[]
Definition: dde.cpp:415
DWORD(CALLBACK * pfnCommandHandler)(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
Definition: dde.cpp:27
EXTERN_C void WINAPI ShellDDEInit(BOOL bInit)
Definition: dde.cpp:330
static HSZ hszProgmanService
Definition: dde.cpp:43
static DWORD CALLBACK DDE_OnViewFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
Definition: dde.cpp:375
static HDDEDATA Dde_OnRequest(UINT uFmt, HCONV hconv, HSZ hszTopic, HSZ hszItem)
Definition: dde.cpp:87
static HSZ hszAppProperties
Definition: dde.cpp:45
static HSZ hszShell
Definition: dde.cpp:44
static HDDEDATA CALLBACK DdeCallback(UINT uType, UINT uFmt, HCONV hconv, HSZ hsz1, HSZ hsz2, HDDEDATA hdata, ULONG_PTR dwData1, ULONG_PTR dwData2)
Definition: dde.cpp:285
static BOOL Dde_OnWildConnect(HSZ hszTopic, HSZ hszService)
Definition: dde.cpp:74
const int HandlerListLength
Definition: dde.cpp:423
static BOOL bInitialized
Definition: dde.cpp:48
static void Dde_OnConnectConfirm(HCONV hconv, HSZ hszTopic, HSZ hszService)
Definition: dde.cpp:63
#define CBF_FAIL_POKES
Definition: ddeml.h:107
#define DNS_UNREGISTER
Definition: ddeml.h:153
#define DNS_REGISTER
Definition: ddeml.h:152
BOOL WINAPI DdeUninitialize(DWORD)
Definition: ddemisc.c:1112
#define XTYP_CONNECT
Definition: ddeml.h:186
#define DDE_FACK
Definition: ddeml.h:216
#define XTYP_REQUEST
Definition: ddeml.h:191
UINT WINAPI DdeInitializeW(LPDWORD, PFNCALLBACK, DWORD, DWORD)
Definition: ddemisc.c:1095
#define XTYP_CONNECT_CONFIRM
Definition: ddeml.h:187
#define XTYP_REGISTER
Definition: ddeml.h:190
HSZ WINAPI DdeCreateStringHandleW(DWORD, LPCWSTR, INT)
Definition: ddemisc.c:608
#define DDE_FNOTPROCESSED
Definition: ddeml.h:223
#define XTYP_DISCONNECT
Definition: ddeml.h:192
DWORD WINAPI DdeQueryStringW(DWORD, HSZ, LPWSTR, DWORD, INT)
Definition: ddemisc.c:525
BOOL WINAPI DdeFreeStringHandle(DWORD, HSZ)
Definition: ddemisc.c:631
#define XTYP_EXECUTE
Definition: ddeml.h:185
HDDEDATA WINAPI DdeNameService(DWORD, HSZ, HSZ, UINT)
Definition: ddeserver.c:154
#define CP_WINUNICODE
Definition: ddeml.h:33
BOOL WINAPI DdeUnaccessData(HDDEDATA)
Definition: ddemisc.c:1447
#define XTYP_WILDCONNECT
Definition: ddeml.h:194
LPBYTE WINAPI DdeAccessData(HDDEDATA, LPDWORD)
Definition: ddemisc.c:1422
#define CBF_FAIL_ADVISES
Definition: ddeml.h:105
HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, DWORD dwFlags)
Definition: desktopipc.cpp:591
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
INT WINAPI StrToIntW(LPCWSTR lpString)
Definition: string.c:407
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:464
#define MAX_PATH
Definition: compat.h:34
#define CALLBACK
Definition: compat.h:35
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512
PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
Definition: ordinal.c:259
BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
Definition: ordinal.c:315
BOOL WINAPI SHUnlockShared(LPVOID lpView)
Definition: ordinal.c:295
int WINAPI StrCmpW(LPCWSTR lpszStr, LPCWSTR lpszComp)
Definition: string.c:434
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLenum dst
Definition: glext.h:6340
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define FAILED(hr)
Definition: intsafe.h:51
unsigned int UINT
Definition: ndis.h:50
#define DWORD
Definition: nt_native.h:44
#define L(x)
Definition: ntvdm.h:50
LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl)
Definition: pidl.c:237
LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path)
Definition: pidl.c:1003
static HSZ hszTopic
Definition: shlexec.c:148
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
#define StringCchCopy
Definition: strsafe.h:139
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
Definition: shell.h:41
pfnCommandHandler Handler
Definition: dde.cpp:32
Definition: ftp_var.h:139
#define DWORD_PTR
Definition: treelist.c:76
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
int ret
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
#define WINAPI
Definition: msvc.h:6
__wchar_t WCHAR
Definition: xmlstorage.h:180