ReactOS  0.4.14-dev-98-gb0d4763
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 
27 typedef DWORD(CALLBACK * pfnCommandHandler)(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS);
28 
30 {
33 };
34 
36 extern const int HandlerListLength;
37 
38 /* DDE Instance ID */
40 
41 /* String handles */
42 static HSZ hszProgmanTopic;
43 static HSZ hszProgmanService;
44 static HSZ hszShell;
45 static HSZ hszAppProperties;
46 static HSZ hszFolders;
47 
49 
50 static 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 
63 static 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 
74 static 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 
87 static 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 
126 static 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 
252  IdList = _ILReadFromSharedMemory(cmd);
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 
280 static void Dde_OnDisconnect(HCONV hconv)
281 {
282  TRACE("Dde_OnDisconnect: hconv=%p\n", hconv);
283 }
284 
285 static 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  {
350  bInitialized = TRUE;
351  }
352  }
353  else if (!bInit && bInitialized)
354  {
355  /* unregister all services */
357 
358  if (hszFolders)
360  if (hszAppProperties)
362  if (hszShell)
364  if (hszProgmanService)
366  if (hszProgmanTopic)
368 
370 
372  }
373 }
374 
375 static 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 
389 static 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 
403 static DWORD CALLBACK DDE_OnFindFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
404 {
406  return DDE_FNOTPROCESSED;
407 }
408 
409 static 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 
#define DNS_UNREGISTER
Definition: ddeml.h:153
const uint16_t * PCWSTR
Definition: typedefs.h:55
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3835
#define XTYP_REQUEST
Definition: ddeml.h:191
static BOOL Dde_OnWildConnect(HSZ hszTopic, HSZ hszService)
Definition: dde.cpp:74
#define TRUE
Definition: types.h:120
#define CBF_FAIL_ADVISES
Definition: ddeml.h:105
#define DWORD_PTR
Definition: treelist.c:76
static void Dde_OnConnectConfirm(HCONV hconv, HSZ hszTopic, HSZ hszService)
Definition: dde.cpp:63
Definition: ftp_var.h:139
static DWORD dwDDEInst
Definition: dde.cpp:39
static BOOL Dde_OnConnect(HSZ hszTopic, HSZ hszService)
Definition: dde.cpp:50
LPBYTE WINAPI DdeAccessData(HDDEDATA, LPDWORD)
Definition: ddemisc.c:1422
uint16_t * PWSTR
Definition: typedefs.h:54
static void Dde_OnDisconnect(HCONV hconv)
Definition: dde.cpp:280
#define _countof(array)
Definition: fontsub.cpp:30
#define XTYP_EXECUTE
Definition: ddeml.h:185
#define WARN(fmt,...)
Definition: debug.h:111
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define CALLBACK
Definition: compat.h:27
#define XTYP_CONNECT_CONFIRM
Definition: ddeml.h:187
char * cmd
Definition: vfdcmd.c:85
#define CBF_FAIL_POKES
Definition: ddeml.h:107
#define DDE_FNOTPROCESSED
Definition: ddeml.h:223
Definition: shell.h:41
#define DWORD
Definition: nt_native.h:44
int32_t INT
Definition: typedefs.h:56
#define DNS_REGISTER
Definition: ddeml.h:152
const int HandlerListLength
Definition: dde.cpp:423
static HSZ hszAppProperties
Definition: dde.cpp:45
uint32_t ULONG_PTR
Definition: typedefs.h:63
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
unsigned int BOOL
Definition: ntddk_ex.h:94
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
static HSZ hszShell
Definition: dde.cpp:44
#define SH_EXPLORER_CMDLINE_FLAG_E
BOOL WINAPI DdeUninitialize(DWORD)
Definition: ddemisc.c:1112
smooth NULL
Definition: ftsmooth.c:416
#define XTYP_WILDCONNECT
Definition: ddeml.h:194
DDECommandHandler HandlerList[]
Definition: dde.cpp:415
#define XTYP_CONNECT
Definition: ddeml.h:186
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
#define TRACE(s)
Definition: solgame.cpp:4
HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, DWORD dwFlags)
Definition: desktopipc.cpp:578
BOOL WINAPI DdeFreeStringHandle(DWORD, HSZ)
Definition: ddemisc.c:631
WINE_DEFAULT_DEBUG_CHANNEL(shelldde)
__wchar_t WCHAR
Definition: xmlstorage.h:180
static HSZ hszFolders
Definition: dde.cpp:46
#define XTYP_REGISTER
Definition: ddeml.h:190
static DWORD Dde_OnExecute(HCONV hconv, HSZ hszTopic, HDDEDATA hdata)
Definition: dde.cpp:126
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:8
#define DDE_FACK
Definition: ddeml.h:216
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
Definition: ordinal.c:262
int ret
static const WCHAR L[]
Definition: oid.c:1250
#define StringCchCopy
Definition: strsafe.h:139
static HSZ hszTopic
Definition: shlexec.c:155
static BOOL bInitialized
Definition: dde.cpp:48
#define ERR(fmt,...)
Definition: debug.h:109
int WINAPI StrCmpW(LPCWSTR lpszStr, LPCWSTR lpszComp)
Definition: string.c:434
static HSZ hszProgmanService
Definition: dde.cpp:43
#define XTYP_DISCONNECT
Definition: ddeml.h:192
PRTL_UNICODE_STRING_BUFFER Path
LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl)
Definition: pidl.c:228
pfnCommandHandler Handler
Definition: dde.cpp:32
GLenum GLenum dst
Definition: glext.h:6340
EXTERN_C void WINAPI ShellDDEInit(BOOL bInit)
Definition: dde.cpp:330
PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
Definition: ordinal.c:210
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:468
#define CP_WINUNICODE
Definition: ddeml.h:33
unsigned int UINT
Definition: ndis.h:50
HDDEDATA WINAPI DdeNameService(DWORD, HSZ, HSZ, UINT)
Definition: ddeserver.c:154
INT WINAPI StrToIntW(LPCWSTR lpString)
Definition: string.c:411
static DWORD CALLBACK DDE_OnViewFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
Definition: dde.cpp:375
BOOL WINAPI DdeUnaccessData(HDDEDATA)
Definition: ddemisc.c:1447
BOOL WINAPI SHUnlockShared(LPVOID lpView)
Definition: ordinal.c:242
static LPITEMIDLIST _ILReadFromSharedMemory(PCWSTR strField)
Definition: dde.cpp:100
#define UNIMPLEMENTED
Definition: debug.h:114
static DWORD CALLBACK DDE_OnShellFile(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
Definition: dde.cpp:409
DWORD WINAPI DdeQueryStringW(DWORD, HSZ, LPWSTR, DWORD, INT)
Definition: ddemisc.c:525
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7786
LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path)
Definition: pidl.c:982
DWORD(CALLBACK * pfnCommandHandler)(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
Definition: dde.cpp:27
HSZ WINAPI DdeCreateStringHandleW(DWORD, LPCWSTR, INT)
Definition: ddemisc.c:608
#define EXTERN_C
Definition: basetyps.h:12
UINT WINAPI DdeInitializeW(LPDWORD, PFNCALLBACK, DWORD, DWORD)
Definition: ddemisc.c:1095
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
static HSZ hszProgmanTopic
Definition: dde.cpp:42
static DWORD CALLBACK DDW_OnExploreFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
Definition: dde.cpp:389
static DWORD CALLBACK DDE_OnFindFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
Definition: dde.cpp:403
static HDDEDATA Dde_OnRequest(UINT uFmt, HCONV hconv, HSZ hszTopic, HSZ hszItem)
Definition: dde.cpp:87