ReactOS  0.4.13-dev-39-g8b6696f
shlexec.cpp
Go to the documentation of this file.
1 /*
2  * Shell Library Functions
3  *
4  * Copyright 1998 Marcus Meissner
5  * Copyright 2002 Eric Pouech
6  * Copyright 2018 Katayama Hirofumi MZ
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #include "precomp.h"
24 #include <undocshell.h>
25 
27 
28 static const WCHAR wszOpen[] = L"open";
29 static const WCHAR wszExe[] = L".exe";
30 static const WCHAR wszCom[] = L".com";
31 
32 #define SEE_MASK_CLASSALL (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)
33 
34 typedef UINT_PTR (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
35  const SHELLEXECUTEINFOW *sei, LPSHELLEXECUTEINFOW sei_out);
36 
37 static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
38 {
39  bool firstCharQuote = false;
40  bool quotes_opened = false;
41  bool backslash_encountered = false;
42 
43  for (int curArg = 0; curArg <= argNum && *args; ++curArg)
44  {
45  firstCharQuote = false;
46  if (*args == '"')
47  {
48  quotes_opened = true;
49  firstCharQuote = true;
50  args++;
51  }
52 
53  while(*args)
54  {
55  if (*args == '\\')
56  {
57  // if we found a backslash then flip the variable
58  backslash_encountered = !backslash_encountered;
59  }
60  else if (*args == '"')
61  {
62  if (quotes_opened)
63  {
64  if (*(args + 1) != '"')
65  {
66  quotes_opened = false;
67  args++;
68  break;
69  }
70  else
71  {
72  args++;
73  }
74  }
75  else
76  {
77  quotes_opened = true;
78  }
79 
80  backslash_encountered = false;
81  }
82  else
83  {
84  backslash_encountered = false;
85  if (*args == ' ' && !firstCharQuote)
86  break;
87  }
88 
89  if (curArg == argNum)
90  {
91  used++;
92  if (used < len)
93  *res++ = *args;
94  }
95 
96  args++;
97  }
98 
99  while(*args == ' ')
100  ++args;
101  }
102 }
103 
104 static void ParseTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
105 {
106  bool quotes_opened = false;
107  bool backslash_encountered = false;
108 
109  for (int curArg = 0; curArg <= argNum && *args; ++curArg)
110  {
111  while(*args)
112  {
113  if (*args == '\\')
114  {
115  // if we found a backslash then flip the variable
116  backslash_encountered = !backslash_encountered;
117  }
118  else if (*args == '"')
119  {
120  if (quotes_opened)
121  {
122  if (*(args + 1) != '"')
123  {
124  quotes_opened = false;
125  }
126  else
127  {
128  args++;
129  }
130  }
131  else
132  {
133  quotes_opened = true;
134  }
135 
136  backslash_encountered = false;
137  }
138  else
139  {
140  backslash_encountered = false;
141  if (*args == ' ' && !quotes_opened && curArg != argNum)
142  break;
143  }
144 
145  if (curArg == argNum)
146  {
147  used++;
148  if (used < len)
149  *res++ = *args;
150  }
151 
152  args++;
153  }
154  }
155 }
156 
157 /***********************************************************************
158  * SHELL_ArgifyW [Internal]
159  *
160  * this function is supposed to expand the escape sequences found in the registry
161  * some diving reported that the following were used:
162  * + %1, %2... seem to report to parameter of index N in ShellExecute pmts
163  * %1 file
164  * %2 printer
165  * %3 driver
166  * %4 port
167  * %I address of a global item ID (explorer switch /idlist)
168  * %L seems to be %1 as long filename followed by the 8+3 variation
169  * %S ???
170  * %* all following parameters (see batfile)
171  *
172  * The way we parse the command line arguments was determined through extensive
173  * testing and can be summed up by the following rules"
174  *
175  * - %2
176  * - if first letter is " break on first non literal " and include any white spaces
177  * - if first letter is NOT " break on first " or white space
178  * - if " is opened any pair of consecutive " results in ONE literal "
179  *
180  * - %~2
181  * - use rules from here http://www.autohotkey.net/~deleyd/parameters/parameters.htm
182  */
183 
184 static BOOL SHELL_ArgifyW(WCHAR* out, DWORD len, const WCHAR* fmt, const WCHAR* lpFile, LPITEMIDLIST pidl, LPCWSTR args, DWORD* out_len, const WCHAR* lpDir)
185 {
186  WCHAR xlpFile[1024];
187  BOOL done = FALSE;
188  BOOL found_p1 = FALSE;
189  PWSTR res = out;
190  PCWSTR cmd;
191  DWORD used = 0;
192  bool tildeEffect = false;
193 
194  TRACE("Before parsing: %p, %d, %s, %s, %p, %p\n", out, len, debugstr_w(fmt),
195  debugstr_w(lpFile), pidl, args);
196 
197  while (*fmt)
198  {
199  if (*fmt == '%')
200  {
201  switch (*++fmt)
202  {
203  case '\0':
204  case '%':
205  {
206  used++;
207  if (used < len)
208  *res++ = '%';
209  };
210  break;
211 
212  case '*':
213  {
214  if (args)
215  {
216  if (*fmt == '*')
217  {
218  used++;
219  while(*args)
220  {
221  used++;
222  if (used < len)
223  *res++ = *args++;
224  else
225  args++;
226  }
227  used++;
228  break;
229  }
230  }
231  };
232  break;
233 
234  case '~':
235 
236  case '2':
237  case '3':
238  case '4':
239  case '5':
240  case '6':
241  case '7':
242  case '8':
243  case '9':
244  //case '0':
245  {
246  if (*fmt == '~')
247  {
248  fmt++;
249  tildeEffect = true;
250  }
251 
252  if (args)
253  {
254  if (tildeEffect)
255  {
256  ParseTildeEffect(res, args, len, used, *fmt - '2');
257  tildeEffect = false;
258  }
259  else
260  {
261  ParseNoTildeEffect(res, args, len, used, *fmt - '2');
262  }
263  }
264  };
265  break;
266 
267  case '1':
268  if (!done || (*fmt == '1'))
269  {
270  /*FIXME Is the call to SearchPathW() really needed? We already have separated out the parameter string in args. */
271  if (SearchPathW(lpDir, lpFile, wszExe, sizeof(xlpFile) / sizeof(WCHAR), xlpFile, NULL))
272  cmd = xlpFile;
273  else
274  cmd = lpFile;
275 
276  used += wcslen(cmd);
277  if (used < len)
278  {
279  wcscpy(res, cmd);
280  res += wcslen(cmd);
281  }
282  }
283  found_p1 = TRUE;
284  break;
285 
286  /*
287  * IE uses this a lot for activating things such as windows media
288  * player. This is not verified to be fully correct but it appears
289  * to work just fine.
290  */
291  case 'l':
292  case 'L':
293  if (lpFile)
294  {
295  used += wcslen(lpFile);
296  if (used < len)
297  {
298  wcscpy(res, lpFile);
299  res += wcslen(lpFile);
300  }
301  }
302  found_p1 = TRUE;
303  break;
304 
305  case 'i':
306  case 'I':
307  if (pidl)
308  {
309  DWORD chars = 0;
310  /* %p should not exceed 8, maybe 16 when looking forward to 64bit.
311  * allowing a buffer of 100 should more than exceed all needs */
312  WCHAR buf[100];
313  LPVOID pv;
314  HGLOBAL hmem = SHAllocShared(pidl, ILGetSize(pidl), 0);
315  pv = SHLockShared(hmem, 0);
316  chars = swprintf(buf, L":%p", pv);
317 
318  if (chars >= sizeof(buf) / sizeof(WCHAR))
319  ERR("pidl format buffer too small!\n");
320 
321  used += chars;
322 
323  if (used < len)
324  {
325  wcscpy(res, buf);
326  res += chars;
327  }
328  SHUnlockShared(pv);
329  }
330  found_p1 = TRUE;
331  break;
332 
333  default:
334  /*
335  * Check if this is an env-variable here...
336  */
337 
338  /* Make sure that we have at least one more %.*/
339  if (strchrW(fmt, '%'))
340  {
341  WCHAR tmpBuffer[1024];
342  PWSTR tmpB = tmpBuffer;
343  WCHAR tmpEnvBuff[MAX_PATH];
344  DWORD envRet;
345 
346  while (*fmt != '%')
347  *tmpB++ = *fmt++;
348  *tmpB++ = 0;
349 
350  TRACE("Checking %s to be an env-var\n", debugstr_w(tmpBuffer));
351 
352  envRet = GetEnvironmentVariableW(tmpBuffer, tmpEnvBuff, MAX_PATH);
353  if (envRet == 0 || envRet > MAX_PATH)
354  {
355  used += wcslen(tmpBuffer);
356  if (used < len)
357  {
358  wcscpy( res, tmpBuffer );
359  res += wcslen(tmpBuffer);
360  }
361  }
362  else
363  {
364  used += wcslen(tmpEnvBuff);
365  if (used < len)
366  {
367  wcscpy( res, tmpEnvBuff );
368  res += wcslen(tmpEnvBuff);
369  }
370  }
371  }
372  done = TRUE;
373  break;
374  }
375  /* Don't skip past terminator (catch a single '%' at the end) */
376  if (*fmt != '\0')
377  {
378  fmt++;
379  }
380  }
381  else
382  {
383  used ++;
384  if (used < len)
385  *res++ = *fmt++;
386  else
387  fmt++;
388  }
389  }
390 
391  used++;
392  if (res - out < static_cast<int>(len))
393  *res = '\0';
394  else
395  out[len-1] = '\0';
396 
397  TRACE("used %i of %i space\n", used, len);
398  if (out_len)
399  *out_len = used;
400 
401  TRACE("After parsing: %p, %d, %s, %s, %p, %p\n", out, len, debugstr_w(fmt),
402  debugstr_w(lpFile), pidl, args);
403 
404  return found_p1;
405 }
406 
408 {
409  STRRET strret;
410  CComPtr<IShellFolder> desktop;
411 
412  HRESULT hr = SHGetDesktopFolder(&desktop);
413 
414  if (SUCCEEDED(hr))
415  {
416  hr = desktop->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strret);
417 
418  if (SUCCEEDED(hr))
419  StrRetToStrNW(pszPath, uOutSize, &strret, pidl);
420  }
421 
422  return hr;
423 }
424 
425 /*************************************************************************
426  * SHELL_ExecuteW [Internal]
427  *
428  */
429 static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
430  const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
431 {
434  UINT_PTR retval = SE_ERR_NOASSOC;
435  UINT gcdret = 0;
436  WCHAR curdir[MAX_PATH];
437  DWORD dwCreationFlags;
438  const WCHAR *lpDirectory = NULL;
439 
440  TRACE("Execute %s from directory %s\n", debugstr_w(lpCmd), debugstr_w(psei->lpDirectory));
441 
442  /* make sure we don't fail the CreateProcess if the calling app passes in
443  * a bad working directory */
444  if (psei->lpDirectory && psei->lpDirectory[0])
445  {
448  lpDirectory = psei->lpDirectory;
449  }
450 
451  /* ShellExecute specifies the command from psei->lpDirectory
452  * if present. Not from the current dir as CreateProcess does */
453  if (lpDirectory)
454  if ((gcdret = GetCurrentDirectoryW( MAX_PATH, curdir)))
456  ERR("cannot set directory %s\n", debugstr_w(lpDirectory));
457 
458  ZeroMemory(&startup, sizeof(STARTUPINFOW));
459  startup.cb = sizeof(STARTUPINFOW);
460  startup.dwFlags = STARTF_USESHOWWINDOW;
461  startup.wShowWindow = psei->nShow;
462  dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
463  if (!(psei->fMask & SEE_MASK_NO_CONSOLE))
464  dwCreationFlags |= CREATE_NEW_CONSOLE;
465  startup.lpTitle = (LPWSTR)(psei->fMask & (SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE) ? psei->lpClass : NULL);
466 
467  if (psei->fMask & SEE_MASK_HASLINKNAME)
468  startup.dwFlags |= STARTF_TITLEISLINKNAME;
469 
470  if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, dwCreationFlags, env,
471  lpDirectory, &startup, &info))
472  {
473  /* Give 30 seconds to the app to come up, if desired. Probably only needed
474  when starting app immediately before making a DDE connection. */
475  if (shWait)
476  if (WaitForInputIdle(info.hProcess, 30000) == WAIT_FAILED)
477  WARN("WaitForInputIdle failed: Error %d\n", GetLastError() );
478  retval = 33;
479 
480  if (psei->fMask & SEE_MASK_NOCLOSEPROCESS)
481  psei_out->hProcess = info.hProcess;
482  else
483  CloseHandle( info.hProcess );
484  CloseHandle( info.hThread );
485  }
486  else if ((retval = GetLastError()) >= 32)
487  {
488  WARN("CreateProcess returned error %ld\n", retval);
489  retval = ERROR_BAD_FORMAT;
490  }
491 
492  TRACE("returning %lu\n", retval);
493 
494  psei_out->hInstApp = (HINSTANCE)retval;
495 
496  if (gcdret)
497  if (!SetCurrentDirectoryW(curdir))
498  ERR("cannot return to directory %s\n", debugstr_w(curdir));
499 
500  return retval;
501 }
502 
503 
504 /***********************************************************************
505  * SHELL_BuildEnvW [Internal]
506  *
507  * Build the environment for the new process, adding the specified
508  * path to the PATH variable. Returned pointer must be freed by caller.
509  */
511 {
512  static const WCHAR wPath[] = L"PATH=";
513  WCHAR *strings, *new_env;
514  WCHAR *p, *p2;
515  int total = wcslen(path) + 1;
516  BOOL got_path = FALSE;
517 
518  if (!(strings = GetEnvironmentStringsW())) return NULL;
519  p = strings;
520  while (*p)
521  {
522  int len = wcslen(p) + 1;
523  if (!_wcsnicmp( p, wPath, 5 )) got_path = TRUE;
524  total += len;
525  p += len;
526  }
527  if (!got_path) total += 5; /* we need to create PATH */
528  total++; /* terminating null */
529 
530  if (!(new_env = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, total * sizeof(WCHAR))))
531  {
533  return NULL;
534  }
535  p = strings;
536  p2 = new_env;
537  while (*p)
538  {
539  int len = wcslen(p) + 1;
540  memcpy(p2, p, len * sizeof(WCHAR));
541  if (!_wcsnicmp( p, wPath, 5 ))
542  {
543  p2[len - 1] = ';';
544  wcscpy( p2 + len, path );
545  p2 += wcslen(path) + 1;
546  }
547  p += len;
548  p2 += len;
549  }
550  if (!got_path)
551  {
552  wcscpy(p2, wPath);
553  wcscat(p2, path);
554  p2 += wcslen(p2) + 1;
555  }
556  *p2 = 0;
558  return new_env;
559 }
560 
561 
562 /***********************************************************************
563  * SHELL_TryAppPathW [Internal]
564  *
565  * Helper function for SHELL_FindExecutable
566  * @param lpResult - pointer to a buffer of size MAX_PATH
567  * On entry: szName is a filename (probably without path separators).
568  * On exit: if szName found in "App Path", place full path in lpResult, and return true
569  */
571 {
572  HKEY hkApp = 0;
573  WCHAR buffer[1024];
574  LONG len;
575  LONG res;
576  BOOL found = FALSE;
577 
578  if (env) *env = NULL;
579  wcscpy(buffer, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\");
580  wcscat(buffer, szName);
582  if (res)
583  {
584  // Add ".exe" extension, if extension does not exists
586  {
588  }
589  if (res) goto end;
590  }
591 
592  len = MAX_PATH * sizeof(WCHAR);
593  res = RegQueryValueW(hkApp, NULL, lpResult, &len);
594  if (res) goto end;
595  found = TRUE;
596 
597  if (env)
598  {
599  DWORD count = sizeof(buffer);
600  if (!RegQueryValueExW(hkApp, L"Path", NULL, NULL, (LPBYTE)buffer, &count) && buffer[0])
602  }
603 
604 end:
605  if (hkApp) RegCloseKey(hkApp);
606  return found;
607 }
608 
609 /*************************************************************************
610  * SHELL_FindExecutableByVerb [Internal]
611  *
612  * called from SHELL_FindExecutable or SHELL_execute_class
613  * in/out:
614  * classname a buffer, big enough, to get the key name to do actually the
615  * command "WordPad.Document.1\\shell\\open\\command"
616  * passed as "WordPad.Document.1"
617  * in:
618  * lpVerb the operation on it (open)
619  * commandlen the size of command buffer (in bytes)
620  * out:
621  * command a buffer, to store the command to do the
622  * operation on the file
623  * key a buffer, big enough, to get the key name to do actually the
624  * command "WordPad.Document.1\\shell\\open\\command"
625  * Can be NULL
626  */
628 {
629  static const WCHAR wCommand[] = L"\\command";
630  HKEY hkeyClass;
631  WCHAR verb[MAX_PATH];
632 
633  if (RegOpenKeyExW(HKEY_CLASSES_ROOT, classname, 0, 0x02000000, &hkeyClass))
634  return SE_ERR_NOASSOC;
635  if (!HCR_GetDefaultVerbW(hkeyClass, lpVerb, verb, sizeof(verb) / sizeof(verb[0])))
636  return SE_ERR_NOASSOC;
637  RegCloseKey(hkeyClass);
638 
639  /* Looking for ...buffer\shell<verb>\command */
640  wcscat(classname, L"\\shell\\");
641  wcscat(classname, verb);
642  wcscat(classname, wCommand);
643 
645  &commandlen) == ERROR_SUCCESS)
646  {
647  commandlen /= sizeof(WCHAR);
648  if (key) wcscpy(key, classname);
649 #if 0
650  LPWSTR tmp;
651  WCHAR param[256];
652  LONG paramlen = sizeof(param);
653  static const WCHAR wSpace[] = {' ', 0};
654 
655  /* FIXME: it seems all Windows version don't behave the same here.
656  * the doc states that this ddeexec information can be found after
657  * the exec names.
658  * on Win98, it doesn't appear, but I think it does on Win2k
659  */
660  /* Get the parameters needed by the application
661  from the associated ddeexec key */
662  tmp = strstrW(classname, wCommand);
663  tmp[0] = '\0';
664  wcscat(classname, wDdeexec);
666  &paramlen) == ERROR_SUCCESS)
667  {
668  paramlen /= sizeof(WCHAR);
669  wcscat(command, wSpace);
670  wcscat(command, param);
671  commandlen += paramlen;
672  }
673 #endif
674 
675  command[commandlen] = '\0';
676 
677  return 33; /* FIXME see SHELL_FindExecutable() */
678  }
679 
680  return SE_ERR_NOASSOC;
681 }
682 
683 /*************************************************************************
684  * SHELL_FindExecutable [Internal]
685  *
686  * Utility for code sharing between FindExecutable and ShellExecute
687  * in:
688  * lpFile the name of a file
689  * lpVerb the operation on it (open)
690  * out:
691  * lpResult a buffer, big enough :-(, to store the command to do the
692  * operation on the file
693  * key a buffer, big enough, to get the key name to do actually the
694  * command (it'll be used afterwards for more information
695  * on the operation)
696  */
697 static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpVerb,
698  LPWSTR lpResult, DWORD resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args)
699 {
700  WCHAR *extension = NULL; /* pointer to file extension */
701  WCHAR classname[256]; /* registry name for this file type */
702  LONG classnamelen = sizeof(classname); /* length of above */
703  WCHAR command[1024]; /* command from registry */
704  WCHAR wBuffer[256]; /* Used to GetProfileString */
705  UINT retval = SE_ERR_NOASSOC;
706  WCHAR *tok; /* token pointer */
707  WCHAR xlpFile[256]; /* result of SearchPath */
708  DWORD attribs; /* file attributes */
709 
710  TRACE("%s\n", debugstr_w(lpFile));
711 
712  if (!lpResult)
714 
715  xlpFile[0] = '\0';
716  lpResult[0] = '\0'; /* Start off with an empty return string */
717  if (key) *key = '\0';
718 
719  /* trap NULL parameters on entry */
720  if (!lpFile)
721  {
722  WARN("(lpFile=%s,lpResult=%s): NULL parameter\n",
723  debugstr_w(lpFile), debugstr_w(lpResult));
724  return ERROR_FILE_NOT_FOUND; /* File not found. Close enough, I guess. */
725  }
726 
727  if (SHELL_TryAppPathW( lpFile, lpResult, env ))
728  {
729  TRACE("found %s via App Paths\n", debugstr_w(lpResult));
730  return 33;
731  }
732 
733  if (SearchPathW(lpPath, lpFile, wszExe, sizeof(xlpFile) / sizeof(WCHAR), xlpFile, NULL))
734  {
735  TRACE("SearchPathW returned non-zero\n");
736  lpFile = xlpFile;
737  /* The file was found in the application-supplied default directory (or the system search path) */
738  }
739  else if (lpPath && SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL))
740  {
741  TRACE("SearchPathW returned non-zero\n");
742  lpFile = xlpFile;
743  /* The file was found in one of the directories in the system-wide search path */
744  }
745 
746  attribs = GetFileAttributesW(lpFile);
748  {
749  wcscpy(classname, L"Folder");
750  }
751  else
752  {
753  /* Did we get something? Anything? */
754  if (xlpFile[0] == 0)
755  {
756  TRACE("Returning SE_ERR_FNF\n");
757  return SE_ERR_FNF;
758  }
759  /* First thing we need is the file's extension */
760  extension = wcsrchr(xlpFile, '.'); /* Assume last "." is the one; */
761  /* File->Run in progman uses */
762  /* .\FILE.EXE :( */
763  TRACE("xlpFile=%s,extension=%s\n", debugstr_w(xlpFile), debugstr_w(extension));
764 
765  if (extension == NULL || extension[1] == 0)
766  {
767  WARN("Returning SE_ERR_NOASSOC\n");
768  return SE_ERR_NOASSOC;
769  }
770 
771  /* Three places to check: */
772  /* 1. win.ini, [windows], programs (NB no leading '.') */
773  /* 2. Registry, HKEY_CLASS_ROOT<classname>\shell\open\command */
774  /* 3. win.ini, [extensions], extension (NB no leading '.' */
775  /* All I know of the order is that registry is checked before */
776  /* extensions; however, it'd make sense to check the programs */
777  /* section first, so that's what happens here. */
778 
779  /* See if it's a program - if GetProfileString fails, we skip this
780  * section. Actually, if GetProfileString fails, we've probably
781  * got a lot more to worry about than running a program... */
782  if (GetProfileStringW(L"windows", L"programs", L"exe pif bat cmd com", wBuffer, sizeof(wBuffer) / sizeof(WCHAR)) > 0)
783  {
784  CharLowerW(wBuffer);
785  tok = wBuffer;
786  while (*tok)
787  {
788  WCHAR *p = tok;
789  while (*p && *p != ' ' && *p != '\t') p++;
790  if (*p)
791  {
792  *p++ = 0;
793  while (*p == ' ' || *p == '\t') p++;
794  }
795 
796  if (wcsicmp(tok, &extension[1]) == 0) /* have to skip the leading "." */
797  {
798  wcscpy(lpResult, xlpFile);
799  /* Need to perhaps check that the file has a path
800  * attached */
801  TRACE("found %s\n", debugstr_w(lpResult));
802  return 33;
803  /* Greater than 32 to indicate success */
804  }
805  tok = p;
806  }
807  }
808 
809  /* Check registry */
811  &classnamelen) == ERROR_SUCCESS)
812  {
813  classnamelen /= sizeof(WCHAR);
814  if (classnamelen == sizeof(classname) / sizeof(WCHAR))
815  classnamelen--;
816 
817  classname[classnamelen] = '\0';
818  TRACE("File type: %s\n", debugstr_w(classname));
819  }
820  else
821  {
822  *classname = '\0';
823  }
824  }
825 
826  if (*classname)
827  {
828  /* pass the verb string to SHELL_FindExecutableByVerb() */
829  retval = SHELL_FindExecutableByVerb(lpVerb, key, classname, command, sizeof(command));
830 
831  if (retval > 32)
832  {
833  DWORD finishedLen;
834  SHELL_ArgifyW(lpResult, resultLen, command, xlpFile, pidl, args, &finishedLen, lpPath);
835  if (finishedLen > resultLen)
836  ERR("Argify buffer not large enough.. truncated\n");
837  /* Remove double quotation marks and command line arguments */
838  if (*lpResult == '"')
839  {
840  WCHAR *p = lpResult;
841  while (*(p + 1) != '"')
842  {
843  *p = *(p + 1);
844  p++;
845  }
846  *p = '\0';
847  }
848  else
849  {
850  /* Truncate on first space */
851  WCHAR *p = lpResult;
852  while (*p != ' ' && *p != '\0')
853  p++;
854  *p = '\0';
855  }
856  }
857  }
858  else /* Check win.ini */
859  {
860  /* Toss the leading dot */
861  extension++;
862  if (GetProfileStringW(L"extensions", extension, L"", command, sizeof(command) / sizeof(WCHAR)) > 0)
863  {
864  if (wcslen(command) != 0)
865  {
866  wcscpy(lpResult, command);
867  tok = wcschr(lpResult, '^'); /* should be ^.extension? */
868  if (tok != NULL)
869  {
870  tok[0] = '\0';
871  wcscat(lpResult, xlpFile); /* what if no dir in xlpFile? */
872  tok = wcschr(command, '^'); /* see above */
873  if ((tok != NULL) && (wcslen(tok) > 5))
874  {
875  wcscat(lpResult, &tok[5]);
876  }
877  }
878  retval = 33; /* FIXME - see above */
879  }
880  }
881  }
882 
883  TRACE("returning %s\n", debugstr_w(lpResult));
884  return retval;
885 }
886 
887 /******************************************************************
888  * dde_cb
889  *
890  * callback for the DDE connection. not really useful
891  */
892 static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv,
893  HSZ hsz1, HSZ hsz2, HDDEDATA hData,
894  ULONG_PTR dwData1, ULONG_PTR dwData2)
895 {
896  TRACE("dde_cb: %04x, %04x, %p, %p, %p, %p, %08lx, %08lx\n",
897  uType, uFmt, hConv, hsz1, hsz2, hData, dwData1, dwData2);
898  return NULL;
899 }
900 
901 /******************************************************************
902  * dde_connect
903  *
904  * ShellExecute helper. Used to do an operation with a DDE connection
905  *
906  * Handles both the direct connection (try #1), and if it fails,
907  * launching an application and trying (#2) to connect to it
908  *
909  */
910 static unsigned dde_connect(const WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
911  const WCHAR* lpFile, WCHAR *env,
912  LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc,
913  const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
914 {
915  WCHAR regkey[256];
916  WCHAR * endkey = regkey + wcslen(key);
917  WCHAR app[256], topic[256], ifexec[256], static_res[256];
918  WCHAR * dynamic_res=NULL;
919  WCHAR * res;
920  LONG applen, topiclen, ifexeclen;
921  WCHAR * exec;
922  DWORD ddeInst = 0;
923  DWORD tid;
924  DWORD resultLen, endkeyLen;
925  HSZ hszApp, hszTopic;
926  HCONV hConv;
927  HDDEDATA hDdeData;
928  unsigned ret = SE_ERR_NOASSOC;
929  BOOL unicode = !(GetVersion() & 0x80000000);
930 
931  if (strlenW(key) + 1 > sizeof(regkey) / sizeof(regkey[0]))
932  {
933  FIXME("input parameter %s larger than buffer\n", debugstr_w(key));
934  return 2;
935  }
936  wcscpy(regkey, key);
937  static const WCHAR wApplication[] = L"\\application";
938  endkeyLen = sizeof(regkey) / sizeof(regkey[0]) - (endkey - regkey);
939  if (strlenW(wApplication) + 1 > endkeyLen)
940  {
941  FIXME("endkey %s overruns buffer\n", debugstr_w(wApplication));
942  return 2;
943  }
944  wcscpy(endkey, wApplication);
945  applen = sizeof(app);
946  if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, app, &applen) != ERROR_SUCCESS)
947  {
948  WCHAR command[1024], fullpath[MAX_PATH];
949  static const WCHAR wSo[] = L".so";
950  DWORD sizeSo = sizeof(wSo) / sizeof(WCHAR);
951  LPWSTR ptr = NULL;
952  DWORD ret = 0;
953 
954  /* Get application command from start string and find filename of application */
955  if (*start == '"')
956  {
957  if (strlenW(start + 1) + 1 > sizeof(command) / sizeof(command[0]))
958  {
959  FIXME("size of input parameter %s larger than buffer\n",
960  debugstr_w(start + 1));
961  return 2;
962  }
963  wcscpy(command, start + 1);
964  if ((ptr = wcschr(command, '"')))
965  * ptr = 0;
966  ret = SearchPathW(NULL, command, wszExe, sizeof(fullpath) / sizeof(WCHAR), fullpath, &ptr);
967  }
968  else
969  {
970  LPCWSTR p;
971  LPWSTR space;
972  for (p = start; (space = const_cast<LPWSTR>(strchrW(p, ' '))); p = space + 1)
973  {
974  int idx = space - start;
975  memcpy(command, start, idx * sizeof(WCHAR));
976  command[idx] = '\0';
977  if ((ret = SearchPathW(NULL, command, wszExe, sizeof(fullpath) / sizeof(WCHAR), fullpath, &ptr)))
978  break;
979  }
980  if (!ret)
981  ret = SearchPathW(NULL, start, wszExe, sizeof(fullpath) / sizeof(WCHAR), fullpath, &ptr);
982  }
983 
984  if (!ret)
985  {
986  ERR("Unable to find application path for command %s\n", debugstr_w(start));
987  return ERROR_ACCESS_DENIED;
988  }
989  if (strlenW(ptr) + 1 > sizeof(app) / sizeof(app[0]))
990  {
991  FIXME("size of found path %s larger than buffer\n", debugstr_w(ptr));
992  return 2;
993  }
994  wcscpy(app, ptr);
995 
996  /* Remove extensions (including .so) */
997  ptr = app + wcslen(app) - (sizeSo - 1);
998  if (wcslen(app) >= sizeSo &&
999  !wcscmp(ptr, wSo))
1000  *ptr = 0;
1001 
1002  ptr = const_cast<LPWSTR>(strrchrW(app, '.'));
1003  assert(ptr);
1004  *ptr = 0;
1005  }
1006 
1007  static const WCHAR wTopic[] = L"\\topic";
1008  if (strlenW(wTopic) + 1 > endkeyLen)
1009  {
1010  FIXME("endkey %s overruns buffer\n", debugstr_w(wTopic));
1011  return 2;
1012  }
1013  wcscpy(endkey, wTopic);
1014  topiclen = sizeof(topic);
1015  if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, topic, &topiclen) != ERROR_SUCCESS)
1016  {
1017  wcscpy(topic, L"System");
1018  }
1019 
1020  if (unicode)
1021  {
1023  return 2;
1024  }
1025  else
1026  {
1028  return 2;
1029  }
1030 
1033 
1034  hConv = DdeConnect(ddeInst, hszApp, hszTopic, NULL);
1035  exec = ddeexec;
1036  if (!hConv)
1037  {
1038  TRACE("Launching %s\n", debugstr_w(start));
1039  ret = execfunc(start, env, TRUE, psei, psei_out);
1040  if (ret <= 32)
1041  {
1042  TRACE("Couldn't launch\n");
1043  goto error;
1044  }
1045  hConv = DdeConnect(ddeInst, hszApp, hszTopic, NULL);
1046  if (!hConv)
1047  {
1048  TRACE("Couldn't connect. ret=%d\n", ret);
1051  return 30; /* whatever */
1052  }
1053  static const WCHAR wIfexec[] = L"\\ifexec";
1054  if (strlenW(wIfexec) + 1 > endkeyLen)
1055  {
1056  FIXME("endkey %s overruns buffer\n", debugstr_w(wIfexec));
1057  return 2;
1058  }
1059  strcpyW(endkey, wIfexec);
1060  ifexeclen = sizeof(ifexec);
1061  if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, ifexec, &ifexeclen) == ERROR_SUCCESS)
1062  {
1063  exec = ifexec;
1064  }
1065  }
1066 
1067  SHELL_ArgifyW(static_res, sizeof(static_res)/sizeof(WCHAR), exec, lpFile, pidl, szCommandline, &resultLen, NULL);
1068  if (resultLen > sizeof(static_res)/sizeof(WCHAR))
1069  {
1070  res = dynamic_res = static_cast<WCHAR *>(HeapAlloc(GetProcessHeap(), 0, resultLen * sizeof(WCHAR)));
1071  SHELL_ArgifyW(dynamic_res, resultLen, exec, lpFile, pidl, szCommandline, NULL, NULL);
1072  }
1073  else
1074  res = static_res;
1075  TRACE("%s %s => %s\n", debugstr_w(exec), debugstr_w(lpFile), debugstr_w(res));
1076 
1077  /* It's documented in the KB 330337 that IE has a bug and returns
1078  * error DMLERR_NOTPROCESSED on XTYP_EXECUTE request.
1079  */
1080  if (unicode)
1081  hDdeData = DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0, XTYP_EXECUTE, 30000, &tid);
1082  else
1083  {
1084  DWORD lenA = WideCharToMultiByte(CP_ACP, 0, res, -1, NULL, 0, NULL, NULL);
1085  char *resA = (LPSTR)HeapAlloc(GetProcessHeap(), 0, lenA);
1086  WideCharToMultiByte(CP_ACP, 0, res, -1, resA, lenA, NULL, NULL);
1087  hDdeData = DdeClientTransaction( (LPBYTE)resA, lenA, hConv, 0L, 0,
1088  XTYP_EXECUTE, 10000, &tid );
1089  HeapFree(GetProcessHeap(), 0, resA);
1090  }
1091  if (hDdeData)
1092  DdeFreeDataHandle(hDdeData);
1093  else
1094  WARN("DdeClientTransaction failed with error %04x\n", DdeGetLastError(ddeInst));
1095  ret = 33;
1096 
1097  HeapFree(GetProcessHeap(), 0, dynamic_res);
1098 
1099  DdeDisconnect(hConv);
1100 
1101 error:
1103 
1104  return ret;
1105 }
1106 
1107 /*************************************************************************
1108  * execute_from_key [Internal]
1109  */
1111  LPCWSTR szCommandline, LPCWSTR executable_name,
1112  SHELL_ExecuteW32 execfunc,
1114 {
1115  WCHAR cmd[256], param[1024], ddeexec[256];
1116  DWORD cmdlen = sizeof(cmd), ddeexeclen = sizeof(ddeexec);
1117  UINT_PTR retval = SE_ERR_NOASSOC;
1118  DWORD resultLen;
1119  LPWSTR tmp;
1120 
1121  TRACE("%s %s %s %s %s\n", debugstr_w(key), debugstr_w(lpFile), debugstr_w(env),
1122  debugstr_w(szCommandline), debugstr_w(executable_name));
1123 
1124  cmd[0] = '\0';
1125  param[0] = '\0';
1126 
1127  /* Get the application from the registry */
1128  if (RegQueryValueW(HKEY_CLASSES_ROOT, key, cmd, (LONG *)&cmdlen) == ERROR_SUCCESS)
1129  {
1130  TRACE("got cmd: %s\n", debugstr_w(cmd));
1131 
1132  /* Is there a replace() function anywhere? */
1133  cmdlen /= sizeof(WCHAR);
1134  if (cmdlen >= sizeof(cmd) / sizeof(WCHAR))
1135  cmdlen = sizeof(cmd) / sizeof(WCHAR) - 1;
1136  cmd[cmdlen] = '\0';
1137  SHELL_ArgifyW(param, sizeof(param) / sizeof(WCHAR), cmd, lpFile, (LPITEMIDLIST)psei->lpIDList, szCommandline, &resultLen,
1138  (psei->lpDirectory && *psei->lpDirectory) ? psei->lpDirectory : NULL);
1139  if (resultLen > sizeof(param) / sizeof(WCHAR))
1140  ERR("Argify buffer not large enough, truncating\n");
1141  }
1142 
1143  /* Get the parameters needed by the application
1144  from the associated ddeexec key */
1145  tmp = const_cast<LPWSTR>(strstrW(key, L"command"));
1146  assert(tmp);
1147  wcscpy(tmp, L"ddeexec");
1148 
1149  if (RegQueryValueW(HKEY_CLASSES_ROOT, key, ddeexec, (LONG *)&ddeexeclen) == ERROR_SUCCESS)
1150  {
1151  TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(ddeexec));
1152  if (!param[0]) strcpyW(param, executable_name);
1153  retval = dde_connect(key, param, ddeexec, lpFile, env, szCommandline, (LPITEMIDLIST)psei->lpIDList, execfunc, psei, psei_out);
1154  }
1155  else if (param[0])
1156  {
1157  TRACE("executing: %s\n", debugstr_w(param));
1158  retval = execfunc(param, env, FALSE, psei, psei_out);
1159  }
1160  else
1161  WARN("Nothing appropriate found for %s\n", debugstr_w(key));
1162 
1163  return retval;
1164 }
1165 
1166 /*************************************************************************
1167  * FindExecutableA [SHELL32.@]
1168  */
1170 {
1171  HINSTANCE retval;
1172  WCHAR *wFile = NULL, *wDirectory = NULL;
1173  WCHAR wResult[MAX_PATH];
1174 
1175  if (lpFile) __SHCloneStrAtoW(&wFile, lpFile);
1176  if (lpDirectory) __SHCloneStrAtoW(&wDirectory, lpDirectory);
1177 
1178  retval = FindExecutableW(wFile, wDirectory, wResult);
1179  WideCharToMultiByte(CP_ACP, 0, wResult, -1, lpResult, MAX_PATH, NULL, NULL);
1180  SHFree(wFile);
1181  SHFree(wDirectory);
1182 
1183  TRACE("returning %s\n", lpResult);
1184  return retval;
1185 }
1186 
1187 /*************************************************************************
1188  * FindExecutableW [SHELL32.@]
1189  *
1190  * This function returns the executable associated with the specified file
1191  * for the default verb.
1192  *
1193  * PARAMS
1194  * lpFile [I] The file to find the association for. This must refer to
1195  * an existing file otherwise FindExecutable fails and returns
1196  * SE_ERR_FNF.
1197  * lpResult [O] Points to a buffer into which the executable path is
1198  * copied. This parameter must not be NULL otherwise
1199  * FindExecutable() segfaults. The buffer must be of size at
1200  * least MAX_PATH characters.
1201  *
1202  * RETURNS
1203  * A value greater than 32 on success, less than or equal to 32 otherwise.
1204  * See the SE_ERR_* constants.
1205  *
1206  * NOTES
1207  * On Windows XP and 2003, FindExecutable() seems to first convert the
1208  * filename into 8.3 format, thus taking into account only the first three
1209  * characters of the extension, and expects to find an association for those.
1210  * However other Windows versions behave sanely.
1211  */
1213 {
1214  UINT_PTR retval = SE_ERR_NOASSOC;
1215  WCHAR old_dir[1024];
1216  WCHAR res[MAX_PATH];
1217 
1218  TRACE("File %s, Dir %s\n", debugstr_w(lpFile), debugstr_w(lpDirectory));
1219 
1220  lpResult[0] = '\0'; /* Start off with an empty return string */
1221  if (lpFile == NULL)
1222  return (HINSTANCE)SE_ERR_FNF;
1223 
1224  if (lpDirectory)
1225  {
1226  GetCurrentDirectoryW(sizeof(old_dir) / sizeof(WCHAR), old_dir);
1228  }
1229 
1231  if (retval > 32)
1232  strcpyW(lpResult, res);
1233 
1234  TRACE("returning %s\n", debugstr_w(lpResult));
1235  if (lpDirectory)
1236  SetCurrentDirectoryW(old_dir);
1237  return (HINSTANCE)retval;
1238 }
1239 
1240 /* FIXME: is this already implemented somewhere else? */
1242 {
1243  LPCWSTR ext = NULL, lpClass = NULL;
1244  LPWSTR cls = NULL;
1245  DWORD type = 0, sz = 0;
1246  HKEY hkey = 0;
1247  LONG r;
1248 
1249  if (sei->fMask & SEE_MASK_CLASSALL)
1250  return sei->hkeyClass;
1251 
1252  if (sei->fMask & SEE_MASK_CLASSNAME)
1253  lpClass = sei->lpClass;
1254  else
1255  {
1256  ext = PathFindExtensionW(sei->lpFile);
1257  TRACE("ext = %s\n", debugstr_w(ext));
1258  if (!ext)
1259  return hkey;
1260 
1261  r = RegOpenKeyW(HKEY_CLASSES_ROOT, ext, &hkey);
1262  if (r != ERROR_SUCCESS)
1263  return hkey;
1264 
1265  r = RegQueryValueExW(hkey, NULL, 0, &type, NULL, &sz);
1266  if (r == ERROR_SUCCESS && type == REG_SZ)
1267  {
1268  sz += sizeof (WCHAR);
1269  cls = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sz);
1270  cls[0] = 0;
1271  RegQueryValueExW(hkey, NULL, 0, &type, (LPBYTE) cls, &sz);
1272  }
1273 
1274  RegCloseKey( hkey );
1275  lpClass = cls;
1276  }
1277 
1278  TRACE("class = %s\n", debugstr_w(lpClass));
1279 
1280  hkey = 0;
1281  if (lpClass)
1282  RegOpenKeyW( HKEY_CLASSES_ROOT, lpClass, &hkey);
1283 
1284  HeapFree(GetProcessHeap(), 0, cls);
1285 
1286  return hkey;
1287 }
1288 
1290 {
1291  LPCITEMIDLIST pidllast = NULL;
1292  CComPtr<IDataObject> dataobj;
1294  LPITEMIDLIST pidl = NULL;
1295  HRESULT r;
1296 
1297  if (sei->fMask & SEE_MASK_CLASSALL)
1298  pidl = (LPITEMIDLIST)sei->lpIDList;
1299  else
1300  {
1301  WCHAR fullpath[MAX_PATH];
1302  BOOL ret;
1303 
1304  fullpath[0] = 0;
1305  ret = GetFullPathNameW(sei->lpFile, MAX_PATH, fullpath, NULL);
1306  if (!ret)
1307  goto end;
1308 
1309  pidl = ILCreateFromPathW(fullpath);
1310  }
1311 
1312  r = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &shf), &pidllast);
1313  if (FAILED(r))
1314  goto end;
1315 
1316  shf->GetUIObjectOf(NULL, 1, &pidllast, IID_NULL_PPV_ARG(IDataObject, &dataobj));
1317 
1318 end:
1319  if (pidl != sei->lpIDList)
1320  ILFree(pidl);
1321  return dataobj.Detach();
1322 }
1323 
1325  LPSHELLEXECUTEINFOW sei)
1326 {
1328  CMINVOKECOMMANDINFOEX ici;
1330  WCHAR string[0x80];
1331  INT i, n, def = -1;
1332  HMENU hmenu = 0;
1333  HRESULT r;
1334 
1335  TRACE("%p %p\n", obj, sei);
1336 
1337  r = obj->QueryInterface(IID_PPV_ARG(IContextMenu, &cm));
1338  if (FAILED(r))
1339  return r;
1340 
1341  hmenu = CreateMenu();
1342  if (!hmenu)
1343  goto end;
1344 
1345  /* the number of the last menu added is returned in r */
1346  r = cm->QueryContextMenu(hmenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
1347  if (FAILED(r))
1348  goto end;
1349 
1351  for (i = 0; i < n; i++)
1352  {
1353  memset(&info, 0, sizeof(info));
1354  info.cbSize = sizeof info;
1356  info.dwTypeData = string;
1357  info.cch = sizeof string;
1358  string[0] = 0;
1360 
1361  TRACE("menu %d %s %08x %08lx %08x %08x\n", i, debugstr_w(string),
1362  info.fState, info.dwItemData, info.fType, info.wID);
1363  if ((!sei->lpVerb && (info.fState & MFS_DEFAULT)) ||
1364  (sei->lpVerb && !lstrcmpiW(sei->lpVerb, string)))
1365  {
1366  def = i;
1367  break;
1368  }
1369  }
1370 
1371  r = E_FAIL;
1372  if (def == -1)
1373  goto end;
1374 
1375  memset(&ici, 0, sizeof ici);
1376  ici.cbSize = sizeof ici;
1377  ici.fMask = CMIC_MASK_UNICODE | (sei->fMask & (SEE_MASK_NO_CONSOLE | SEE_MASK_NOASYNC | SEE_MASK_ASYNCOK | SEE_MASK_FLAG_NO_UI));
1378  ici.nShow = sei->nShow;
1379  ici.lpVerb = MAKEINTRESOURCEA(def);
1380  ici.hwnd = sei->hwnd;
1381  ici.lpParametersW = sei->lpParameters;
1382 
1383  r = cm->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
1384 
1385  TRACE("invoke command returned %08x\n", r);
1386 
1387 end:
1388  if (hmenu)
1389  DestroyMenu( hmenu );
1390  return r;
1391 }
1392 
1394 {
1395  // Can not use CComPtr here because of CoUninitialize at the end, before the destructors would run.
1396  IDataObject *dataobj = NULL;
1397  IObjectWithSite *ows = NULL;
1398  IShellExtInit *obj = NULL;
1399  HRESULT r;
1400 
1401  TRACE("%p %s %p\n", hkey, debugstr_guid(guid), sei);
1402 
1403  r = CoInitialize(NULL);
1404  if (FAILED(r))
1405  goto end;
1406 
1407  r = CoCreateInstance(*guid, NULL, CLSCTX_INPROC_SERVER,
1409  if (FAILED(r))
1410  {
1411  ERR("failed %08x\n", r);
1412  goto end;
1413  }
1414 
1415  dataobj = shellex_get_dataobj(sei);
1416  if (!dataobj)
1417  {
1418  ERR("failed to get data object\n");
1419  r = E_FAIL;
1420  goto end;
1421  }
1422 
1423  r = obj->Initialize(NULL, dataobj, hkey);
1424  if (FAILED(r))
1425  goto end;
1426 
1427  r = obj->QueryInterface(IID_PPV_ARG(IObjectWithSite, &ows));
1428  if (FAILED(r))
1429  goto end;
1430 
1431  ows->SetSite(NULL);
1432 
1434 
1435 end:
1436  if (ows)
1437  ows->Release();
1438  if (dataobj)
1439  dataobj->Release();
1440  if (obj)
1441  obj->Release();
1442  CoUninitialize();
1443  return r;
1444 }
1445 
1446 
1447 /*************************************************************************
1448  * ShellExecute_FromContextMenu [Internal]
1449  */
1451 {
1452  HKEY hkey, hkeycm = 0;
1453  WCHAR szguid[39];
1454  HRESULT hr;
1455  GUID guid;
1456  DWORD i;
1457  LONG r;
1458 
1459  TRACE("%s\n", debugstr_w(sei->lpFile));
1460 
1461  hkey = ShellExecute_GetClassKey(sei);
1462  if (!hkey)
1463  return ERROR_FUNCTION_FAILED;
1464 
1465  r = RegOpenKeyW(hkey, L"shellex\\ContextMenuHandlers", &hkeycm);
1466  if (r == ERROR_SUCCESS)
1467  {
1468  i = 0;
1469  while (1)
1470  {
1471  r = RegEnumKeyW(hkeycm, i++, szguid, sizeof(szguid) / sizeof(szguid[0]));
1472  if (r != ERROR_SUCCESS)
1473  break;
1474 
1475  hr = CLSIDFromString(szguid, &guid);
1476  if (SUCCEEDED(hr))
1477  {
1478  /* stop at the first one that succeeds in running */
1479  hr = shellex_load_object_and_run(hkey, &guid, sei);
1480  if (SUCCEEDED(hr))
1481  break;
1482  }
1483  }
1484  RegCloseKey(hkeycm);
1485  }
1486 
1487  if (hkey != sei->hkeyClass)
1488  RegCloseKey(hkey);
1489  return r;
1490 }
1491 
1492 static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR lpstrProtocol, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc);
1493 
1495 {
1496  WCHAR execCmd[1024], classname[1024];
1497  /* launch a document by fileclass like 'WordPad.Document.1' */
1498  /* the Commandline contains 'c:\Path\wordpad.exe "%1"' */
1499  /* FIXME: wcmd should not be of a fixed size. Fixed to 1024, MAX_PATH is way too short! */
1500  ULONG cmask = (psei->fMask & SEE_MASK_CLASSALL);
1501  DWORD resultLen;
1502  BOOL done;
1503  UINT_PTR rslt;
1504 
1505  /* FIXME: remove following block when SHELL_quote_and_execute supports hkeyClass parameter */
1506  if (cmask != SEE_MASK_CLASSNAME)
1507  {
1508  WCHAR wcmd[1024];
1510  (cmask == SEE_MASK_CLASSNAME) ? psei->lpClass : NULL,
1511  psei->lpVerb,
1512  execCmd, sizeof(execCmd));
1513 
1514  /* FIXME: get the extension of lpFile, check if it fits to the lpClass */
1515  TRACE("SEE_MASK_CLASSNAME->%s, doc->%s\n", debugstr_w(execCmd), debugstr_w(wszApplicationName));
1516 
1517  wcmd[0] = '\0';
1518  done = SHELL_ArgifyW(wcmd, sizeof(wcmd) / sizeof(WCHAR), execCmd, wszApplicationName, (LPITEMIDLIST)psei->lpIDList, NULL, &resultLen,
1519  (psei->lpDirectory && *psei->lpDirectory) ? psei->lpDirectory : NULL);
1520  if (!done && wszApplicationName[0])
1521  {
1522  strcatW(wcmd, L" ");
1523  if (*wszApplicationName != '"')
1524  {
1525  strcatW(wcmd, L"\"");
1526  strcatW(wcmd, wszApplicationName);
1527  strcatW(wcmd, L"\"");
1528  }
1529  else
1530  strcatW(wcmd, wszApplicationName);
1531  }
1532  if (resultLen > sizeof(wcmd) / sizeof(WCHAR))
1533  ERR("Argify buffer not large enough... truncating\n");
1534  return execfunc(wcmd, NULL, FALSE, psei, psei_out);
1535  }
1536 
1537  strcpyW(classname, psei->lpClass);
1538  rslt = SHELL_FindExecutableByVerb(psei->lpVerb, NULL, classname, execCmd, sizeof(execCmd));
1539 
1540  TRACE("SHELL_FindExecutableByVerb returned %u (%s, %s)\n", (unsigned int)rslt, debugstr_w(classname), debugstr_w(execCmd));
1541  if (33 > rslt)
1542  return rslt;
1543  rslt = SHELL_quote_and_execute( execCmd, L"", classname,
1544  wszApplicationName, NULL, psei,
1545  psei_out, execfunc );
1546  return rslt;
1547 
1548 }
1549 
1550 static BOOL SHELL_translate_idlist(LPSHELLEXECUTEINFOW sei, LPWSTR wszParameters, DWORD parametersLen, LPWSTR wszApplicationName, DWORD dwApplicationNameLen)
1551 {
1552  static const WCHAR wExplorer[] = L"explorer.exe";
1554  BOOL appKnownSingular = FALSE;
1555 
1556  /* last chance to translate IDList: now also allow CLSID paths */
1558  if (buffer[0] == ':' && buffer[1] == ':') {
1559  /* open shell folder for the specified class GUID */
1560  if (strlenW(buffer) + 1 > parametersLen)
1561  ERR("parameters len exceeds buffer size (%i > %i), truncating\n",
1562  lstrlenW(buffer) + 1, parametersLen);
1563  lstrcpynW(wszParameters, buffer, parametersLen);
1564  if (strlenW(wExplorer) > dwApplicationNameLen)
1565  ERR("application len exceeds buffer size (%i > %i), truncating\n",
1566  lstrlenW(wExplorer) + 1, dwApplicationNameLen);
1567  lstrcpynW(wszApplicationName, wExplorer, dwApplicationNameLen);
1568  appKnownSingular = TRUE;
1569 
1570  sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
1571  } else {
1573  DWORD attribs;
1574  DWORD resultLen;
1575  /* Check if we're executing a directory and if so use the
1576  handler for the Folder class */
1577  strcpyW(target, buffer);
1581  HCR_GetExecuteCommandW(0, L"Folder",
1582  sei->lpVerb,
1583  buffer, sizeof(buffer))) {
1584  SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen,
1585  buffer, target, (LPITEMIDLIST)sei->lpIDList, NULL, &resultLen,
1586  (sei->lpDirectory && *sei->lpDirectory) ? sei->lpDirectory : NULL);
1587  if (resultLen > dwApplicationNameLen)
1588  ERR("Argify buffer not large enough... truncating\n");
1589  appKnownSingular = FALSE;
1590  }
1591  sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
1592  }
1593  }
1594  return appKnownSingular;
1595 }
1596 
1597 static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR wszKeyname, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
1598 {
1599  UINT_PTR retval;
1600  DWORD len;
1601  WCHAR *wszQuotedCmd;
1602 
1603  /* Length of quotes plus length of command plus NULL terminator */
1604  len = 2 + lstrlenW(wcmd) + 1;
1605  if (wszParameters[0])
1606  {
1607  /* Length of space plus length of parameters */
1608  len += 1 + lstrlenW(wszParameters);
1609  }
1610  wszQuotedCmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1611  /* Must quote to handle case where cmd contains spaces,
1612  * else security hole if malicious user creates executable file "C:\\Program"
1613  */
1614  strcpyW(wszQuotedCmd, L"\"");
1615  strcatW(wszQuotedCmd, wcmd);
1616  strcatW(wszQuotedCmd, L"\"");
1617  if (wszParameters[0])
1618  {
1619  strcatW(wszQuotedCmd, L" ");
1620  strcatW(wszQuotedCmd, wszParameters);
1621  }
1622 
1623  TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), debugstr_w(psei->lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(wszKeyname));
1624 
1625  if (*wszKeyname)
1626  retval = execute_from_key(wszKeyname, wszApplicationName, env, psei->lpParameters, wcmd, execfunc, psei, psei_out);
1627  else
1628  retval = execfunc(wszQuotedCmd, env, FALSE, psei, psei_out);
1629  HeapFree(GetProcessHeap(), 0, wszQuotedCmd);
1630  return retval;
1631 }
1632 
1634 {
1635  static const WCHAR wShell[] = L"\\shell\\";
1636  static const WCHAR wCommand[] = L"\\command";
1637  UINT_PTR retval;
1638  WCHAR *lpstrProtocol;
1639  LPCWSTR lpstrRes;
1640  INT iSize;
1641  DWORD len;
1642 
1643  lpstrRes = strchrW(lpFile, ':');
1644  if (lpstrRes)
1645  iSize = lpstrRes - lpFile;
1646  else
1647  iSize = strlenW(lpFile);
1648 
1649  TRACE("Got URL: %s\n", debugstr_w(lpFile));
1650  /* Looking for ...<protocol>\shell<lpVerb>\command */
1651  len = iSize + lstrlenW(wShell) + lstrlenW(wCommand) + 1;
1652  if (psei->lpVerb && *psei->lpVerb)
1653  len += lstrlenW(psei->lpVerb);
1654  else
1655  len += lstrlenW(wszOpen);
1656  lpstrProtocol = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1657  memcpy(lpstrProtocol, lpFile, iSize * sizeof(WCHAR));
1658  lpstrProtocol[iSize] = '\0';
1659  strcatW(lpstrProtocol, wShell);
1660  strcatW(lpstrProtocol, psei->lpVerb && *psei->lpVerb ? psei->lpVerb : wszOpen);
1661  strcatW(lpstrProtocol, wCommand);
1662 
1663  retval = execute_from_key(lpstrProtocol, lpFile, NULL, psei->lpParameters,
1664  wcmd, execfunc, psei, psei_out);
1665  HeapFree(GetProcessHeap(), 0, lpstrProtocol);
1666  return retval;
1667 }
1668 
1670 {
1671  WCHAR msg[2048];
1672  DWORD_PTR msgArguments[3] = { (DWORD_PTR)filename, 0, 0 };
1673  DWORD error_code;
1674 
1676  if (retval == SE_ERR_NOASSOC)
1678  else
1680  NULL,
1681  error_code,
1683  msg,
1684  sizeof(msg) / sizeof(WCHAR),
1685  (va_list*)msgArguments);
1686 
1688 }
1689 
1691 {
1692  WCHAR *buf;
1693  DWORD len;
1694 
1696  if (!len) return NULL;
1697 
1698  buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1699  if (!buf) return NULL;
1700 
1702  if (!len)
1703  {
1704  HeapFree(GetProcessHeap(), 0, buf);
1705  return NULL;
1706  }
1707  return buf;
1708 }
1709 
1710 /*************************************************************************
1711  * SHELL_execute [Internal]
1712  */
1714 {
1715  static const DWORD unsupportedFlags =
1719 
1720  WCHAR parametersBuffer[1024], dirBuffer[MAX_PATH], wcmdBuffer[1024];
1721  WCHAR *wszApplicationName, *wszParameters, *wszDir, *wcmd;
1722  DWORD dwApplicationNameLen = MAX_PATH + 2;
1723  DWORD parametersLen = sizeof(parametersBuffer) / sizeof(WCHAR);
1724  DWORD dirLen = sizeof(dirBuffer) / sizeof(WCHAR);
1725  DWORD wcmdLen = sizeof(wcmdBuffer) / sizeof(WCHAR);
1726  DWORD len;
1727  SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */
1728  WCHAR wfileName[MAX_PATH];
1729  WCHAR *env;
1730  WCHAR wszKeyname[256];
1731  LPCWSTR lpFile;
1732  UINT_PTR retval = SE_ERR_NOASSOC;
1733  BOOL appKnownSingular = FALSE;
1734 
1735  /* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
1736  sei_tmp = *sei;
1737 
1738  TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
1739  sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
1740  debugstr_w(sei_tmp.lpFile), debugstr_w(sei_tmp.lpParameters),
1741  debugstr_w(sei_tmp.lpDirectory), sei_tmp.nShow,
1742  ((sei_tmp.fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME) ?
1743  debugstr_w(sei_tmp.lpClass) : "not used");
1744 
1745  sei->hProcess = NULL;
1746 
1747  /* make copies of all path/command strings */
1748  if (!sei_tmp.lpFile)
1749  {
1750  wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR));
1751  *wszApplicationName = '\0';
1752  }
1753  else if (*sei_tmp.lpFile == '\"' && sei_tmp.lpFile[(len = strlenW(sei_tmp.lpFile))-1] == '\"')
1754  {
1755  if(len-1 >= dwApplicationNameLen)
1756  dwApplicationNameLen = len;
1757 
1758  wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR));
1759  memcpy(wszApplicationName, sei_tmp.lpFile + 1, len * sizeof(WCHAR));
1760 
1761  if(len > 2)
1762  wszApplicationName[len-2] = '\0';
1763  appKnownSingular = TRUE;
1764 
1765  TRACE("wszApplicationName=%s\n", debugstr_w(wszApplicationName));
1766  }
1767  else
1768  {
1769  DWORD l = strlenW(sei_tmp.lpFile) + 1;
1770  if(l > dwApplicationNameLen) dwApplicationNameLen = l + 1;
1771  wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR));
1772  memcpy(wszApplicationName, sei_tmp.lpFile, l * sizeof(WCHAR));
1773  }
1774 
1775  wszParameters = parametersBuffer;
1776  if (sei_tmp.lpParameters)
1777  {
1778  len = lstrlenW(sei_tmp.lpParameters) + 1;
1779  if (len > parametersLen)
1780  {
1781  wszParameters = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1782  parametersLen = len;
1783  }
1784  strcpyW(wszParameters, sei_tmp.lpParameters);
1785  }
1786  else
1787  *wszParameters = L'\0';
1788 
1789  wszDir = dirBuffer;
1790  if (sei_tmp.lpDirectory)
1791  {
1792  len = lstrlenW(sei_tmp.lpDirectory) + 1;
1793  if (len > dirLen)
1794  {
1795  wszDir = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1796  dirLen = len;
1797  }
1798  strcpyW(wszDir, sei_tmp.lpDirectory);
1799  }
1800  else
1801  *wszDir = L'\0';
1802 
1803  /* adjust string pointers to point to the new buffers */
1804  sei_tmp.lpFile = wszApplicationName;
1805  sei_tmp.lpParameters = wszParameters;
1806  sei_tmp.lpDirectory = wszDir;
1807 
1808  if (sei_tmp.fMask & unsupportedFlags)
1809  {
1810  FIXME("flags ignored: 0x%08x\n", sei_tmp.fMask & unsupportedFlags);
1811  }
1812 
1813  /* process the IDList */
1814  if (sei_tmp.fMask & SEE_MASK_IDLIST)
1815  {
1817 
1819 
1820  if (SUCCEEDED(hr))
1821  {
1822  hr = pSEH->Execute(&sei_tmp);
1823 
1824  if (hr == S_OK)
1825  {
1826  HeapFree(GetProcessHeap(), 0, wszApplicationName);
1827  if (wszParameters != parametersBuffer)
1828  HeapFree(GetProcessHeap(), 0, wszParameters);
1829  if (wszDir != dirBuffer)
1830  HeapFree(GetProcessHeap(), 0, wszDir);
1831  return TRUE;
1832  }
1833  }
1834 
1835  SHGetPathFromIDListW((LPCITEMIDLIST)sei_tmp.lpIDList, wszApplicationName);
1836  appKnownSingular = TRUE;
1837  TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName));
1838  }
1839 
1840  if (sei_tmp.fMask & SEE_MASK_DOENVSUBST)
1841  {
1842  WCHAR *tmp;
1843 
1844  tmp = expand_environment(sei_tmp.lpFile);
1845  if (!tmp)
1846  {
1847  return FALSE;
1848  }
1849  HeapFree(GetProcessHeap(), 0, wszApplicationName);
1850  sei_tmp.lpFile = wszApplicationName = tmp;
1851 
1852  tmp = expand_environment(sei_tmp.lpDirectory);
1853  if (!tmp)
1854  {
1855  return FALSE;
1856  }
1857  if (wszDir != dirBuffer) HeapFree(GetProcessHeap(), 0, wszDir);
1858  sei_tmp.lpDirectory = wszDir = tmp;
1859  }
1860 
1862  {
1863  sei->hInstApp = (HINSTANCE) 33;
1864  HeapFree(GetProcessHeap(), 0, wszApplicationName);
1865  if (wszParameters != parametersBuffer)
1866  HeapFree(GetProcessHeap(), 0, wszParameters);
1867  if (wszDir != dirBuffer)
1868  HeapFree(GetProcessHeap(), 0, wszDir);
1869  return TRUE;
1870  }
1871 
1872  if (sei_tmp.fMask & SEE_MASK_CLASSALL)
1873  {
1874  retval = SHELL_execute_class(wszApplicationName, &sei_tmp, sei, execfunc);
1875  if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
1876  {
1877  OPENASINFO Info;
1878 
1879  //FIXME
1880  // need full path
1881 
1882  Info.pcszFile = wszApplicationName;
1883  Info.pcszClass = NULL;
1884  Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
1885 
1886  //if (SHOpenWithDialog(sei_tmp.hwnd, &Info) != S_OK)
1888  do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName);
1889  }
1890  HeapFree(GetProcessHeap(), 0, wszApplicationName);
1891  if (wszParameters != parametersBuffer)
1892  HeapFree(GetProcessHeap(), 0, wszParameters);
1893  if (wszDir != dirBuffer)
1894  HeapFree(GetProcessHeap(), 0, wszDir);
1895  return retval > 32;
1896  }
1897 
1898  /* Has the IDList not yet been translated? */
1899  if (sei_tmp.fMask & SEE_MASK_IDLIST)
1900  {
1901  appKnownSingular = SHELL_translate_idlist( &sei_tmp, wszParameters,
1902  parametersLen,
1903  wszApplicationName,
1904  dwApplicationNameLen );
1905  }
1906 
1907  /* convert file URLs */
1908  if (UrlIsFileUrlW(sei_tmp.lpFile))
1909  {
1910  LPWSTR buf;
1911  DWORD size;
1912 
1913  size = MAX_PATH;
1914  buf = static_cast<LPWSTR>(HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)));
1915  if (!buf || FAILED(PathCreateFromUrlW(sei_tmp.lpFile, buf, &size, 0)))
1916  {
1917  HeapFree(GetProcessHeap(), 0, buf);
1918  return SE_ERR_OOM;
1919  }
1920 
1921  HeapFree(GetProcessHeap(), 0, wszApplicationName);
1922  wszApplicationName = buf;
1923  sei_tmp.lpFile = wszApplicationName;
1924  }
1925  else /* or expand environment strings (not both!) */
1926  {
1927  len = ExpandEnvironmentStringsW(sei_tmp.lpFile, NULL, 0);
1928  if (len > 0)
1929  {
1930  LPWSTR buf;
1931  buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
1932 
1933  ExpandEnvironmentStringsW(sei_tmp.lpFile, buf, len + 1);
1934  HeapFree(GetProcessHeap(), 0, wszApplicationName);
1935  wszApplicationName = buf;
1936  /* appKnownSingular unmodified */
1937 
1938  sei_tmp.lpFile = wszApplicationName;
1939  }
1940  }
1941 
1942  if (*sei_tmp.lpDirectory)
1943  {
1945  if (len > 0)
1946  {
1947  LPWSTR buf;
1948  len++;
1949  buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1951  if (wszDir != dirBuffer)
1952  HeapFree(GetProcessHeap(), 0, wszDir);
1953  wszDir = buf;
1954  sei_tmp.lpDirectory = wszDir;
1955  }
1956  }
1957 
1958  /* Else, try to execute the filename */
1959  TRACE("execute: %s,%s,%s\n", debugstr_w(wszApplicationName), debugstr_w(wszParameters), debugstr_w(wszDir));
1960 
1961  /* separate out command line arguments from executable file name */
1962  if (!*sei_tmp.lpParameters && !appKnownSingular)
1963  {
1964  /* If the executable path is quoted, handle the rest of the command line as parameters. */
1965  if (sei_tmp.lpFile[0] == L'"')
1966  {
1967  LPWSTR src = wszApplicationName/*sei_tmp.lpFile*/ + 1;
1968  LPWSTR dst = wfileName;
1969  LPWSTR end;
1970 
1971  /* copy the unquoted executable path to 'wfileName' */
1972  while(*src && *src != L'"')
1973  *dst++ = *src++;
1974 
1975  *dst = L'\0';
1976 
1977  if (*src == L'"')
1978  {
1979  end = ++src;
1980 
1981  while(isspaceW(*src))
1982  ++src;
1983  }
1984  else
1985  end = src;
1986 
1987  /* copy the parameter string to 'wszParameters' */
1988  strcpyW(wszParameters, src);
1989 
1990  /* terminate previous command string after the quote character */
1991  *end = L'\0';
1992  lpFile = wfileName;
1993  }
1994  else
1995  {
1996  /* If the executable name is not quoted, we have to use this search loop here,
1997  that in CreateProcess() is not sufficient because it does not handle shell links. */
1998  WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH];
1999  LPWSTR space, s;
2000 
2001  LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
2002  for(s = beg; (space = const_cast<LPWSTR>(strchrW(s, L' '))); s = space + 1)
2003  {
2004  int idx = space - sei_tmp.lpFile;
2005  memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
2006  buffer[idx] = '\0';
2007 
2008  /*FIXME This finds directory paths if the targeted file name contains spaces. */
2009  if (SearchPathW(*sei_tmp.lpDirectory ? sei_tmp.lpDirectory : NULL, buffer, wszExe, sizeof(xlpFile) / sizeof(xlpFile[0]), xlpFile, NULL))
2010  {
2011  /* separate out command from parameter string */
2012  LPCWSTR p = space + 1;
2013 
2014  while(isspaceW(*p))
2015  ++p;
2016 
2017  strcpyW(wszParameters, p);
2018  *space = L'\0';
2019 
2020  break;
2021  }
2022  }
2023 
2024  lpFile = sei_tmp.lpFile;
2025  }
2026  }
2027  else
2028  lpFile = sei_tmp.lpFile;
2029 
2030  wcmd = wcmdBuffer;
2031  len = lstrlenW(wszApplicationName) + 3;
2032  if (sei_tmp.lpParameters[0])
2033  len += 1 + lstrlenW(wszParameters);
2034  if (len > wcmdLen)
2035  {
2036  wcmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2037  wcmdLen = len;
2038  }
2039  swprintf(wcmd, L"\"%s\"", wszApplicationName);
2040  if (sei_tmp.lpParameters[0])
2041  {
2042  strcatW(wcmd, L" ");
2043  strcatW(wcmd, wszParameters);
2044  }
2045 
2046  retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
2047  if (retval > 32)
2048  {
2049  HeapFree(GetProcessHeap(), 0, wszApplicationName);
2050  if (wszParameters != parametersBuffer)
2051  HeapFree(GetProcessHeap(), 0, wszParameters);
2052  if (wszDir != dirBuffer)
2053  HeapFree(GetProcessHeap(), 0, wszDir);
2054  if (wcmd != wcmdBuffer)
2055  HeapFree(GetProcessHeap(), 0, wcmd);
2056  return TRUE;
2057  }
2058 
2059  /* Else, try to find the executable */
2060  wcmd[0] = L'\0';
2061  retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, wcmdLen, wszKeyname, &env, (LPITEMIDLIST)sei_tmp.lpIDList, sei_tmp.lpParameters);
2062  if (retval > 32) /* Found */
2063  {
2064  retval = SHELL_quote_and_execute(wcmd, wszParameters, wszKeyname,
2065  wszApplicationName, env, &sei_tmp,
2066  sei, execfunc);
2067  HeapFree(GetProcessHeap(), 0, env);
2068  }
2069  else if (PathIsDirectoryW(lpFile))
2070  {
2071  WCHAR wExec[MAX_PATH];
2072  WCHAR * lpQuotedFile = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * (strlenW(lpFile) + 3));
2073 
2074  if (lpQuotedFile)
2075  {
2076  retval = SHELL_FindExecutable(sei_tmp.lpDirectory, L"explorer",
2077  wszOpen, wExec, MAX_PATH,
2078  NULL, &env, NULL, NULL);
2079  if (retval > 32)
2080  {
2081  swprintf(lpQuotedFile, L"\"%s\"", lpFile);
2082  retval = SHELL_quote_and_execute(wExec, lpQuotedFile,
2083  wszKeyname,
2084  wszApplicationName, env,
2085  &sei_tmp, sei, execfunc);
2086  HeapFree(GetProcessHeap(), 0, env);
2087  }
2088  HeapFree(GetProcessHeap(), 0, lpQuotedFile);
2089  }
2090  else
2091  retval = 0; /* Out of memory */
2092  }
2093  else if (PathIsURLW(lpFile)) /* File not found, check for URL */
2094  {
2095  retval = SHELL_execute_url(lpFile, wcmd, &sei_tmp, sei, execfunc );
2096  }
2097  /* Check if file specified is in the form www.??????.*** */
2098  else if (!strncmpiW(lpFile, L"www", 3))
2099  {
2100  /* if so, prefix lpFile with http:// and call ShellExecute */
2101  WCHAR lpstrTmpFile[256];
2102  strcpyW(lpstrTmpFile, L"http://");
2103  strcatW(lpstrTmpFile, lpFile);
2104  retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
2105  }
2106 
2107  TRACE("retval %lu\n", retval);
2108 
2109  if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
2110  {
2111  OPENASINFO Info;
2112 
2113  //FIXME
2114  // need full path
2115 
2116  Info.pcszFile = wszApplicationName;
2117  Info.pcszClass = NULL;
2118  Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
2119 
2120  //if (SHOpenWithDialog(sei_tmp.hwnd, &Info) != S_OK)
2122  do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName);
2123  }
2124 
2125  HeapFree(GetProcessHeap(), 0, wszApplicationName);
2126  if (wszParameters != parametersBuffer)
2127  HeapFree(GetProcessHeap(), 0, wszParameters);
2128  if (wszDir != dirBuffer)
2129  HeapFree(GetProcessHeap(), 0, wszDir);
2130  if (wcmd != wcmdBuffer)
2131  HeapFree(GetProcessHeap(), 0, wcmd);
2132 
2133  sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
2134 
2135  return retval > 32;
2136 }
2137 
2138 /*************************************************************************
2139  * ShellExecuteA [SHELL32.290]
2140  */
2142  LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
2143 {
2144  SHELLEXECUTEINFOA sei;
2145 
2146  TRACE("%p,%s,%s,%s,%s,%d\n",
2147  hWnd, debugstr_a(lpVerb), debugstr_a(lpFile),
2148  debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
2149 
2150  sei.cbSize = sizeof(sei);
2151  sei.fMask = SEE_MASK_FLAG_NO_UI;
2152  sei.hwnd = hWnd;
2153  sei.lpVerb = lpVerb;
2154  sei.lpFile = lpFile;
2155  sei.lpParameters = lpParameters;
2156  sei.lpDirectory = lpDirectory;
2157  sei.nShow = iShowCmd;
2158  sei.lpIDList = 0;
2159  sei.lpClass = 0;
2160  sei.hkeyClass = 0;
2161  sei.dwHotKey = 0;
2162  sei.hProcess = 0;
2163 
2164  ShellExecuteExA(&sei);
2165  return sei.hInstApp;
2166 }
2167 
2168 /*************************************************************************
2169  * ShellExecuteExA [SHELL32.292]
2170  *
2171  */
2172 BOOL
2173 WINAPI
2176 {
2177  SHELLEXECUTEINFOW seiW;
2178  BOOL ret;
2179  WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL, *wClass = NULL;
2180 
2181  TRACE("%p\n", sei);
2182 
2183  memcpy(&seiW, sei, sizeof(SHELLEXECUTEINFOW));
2184 
2185  if (sei->lpVerb)
2186  seiW.lpVerb = __SHCloneStrAtoW(&wVerb, sei->lpVerb);
2187 
2188  if (sei->lpFile)
2189  seiW.lpFile = __SHCloneStrAtoW(&wFile, sei->lpFile);
2190 
2191  if (sei->lpParameters)
2192  seiW.lpParameters = __SHCloneStrAtoW(&wParameters, sei->lpParameters);
2193 
2194  if (sei->lpDirectory)
2195  seiW.lpDirectory = __SHCloneStrAtoW(&wDirectory, sei->lpDirectory);
2196 
2197  if ((sei->fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME && sei->lpClass)
2198  seiW.lpClass = __SHCloneStrAtoW(&wClass, sei->lpClass);
2199  else
2200  seiW.lpClass = NULL;
2201 
2202  ret = SHELL_execute(&seiW, SHELL_ExecuteW);
2203 
2204  sei->hInstApp = seiW.hInstApp;
2205 
2206  if (sei->fMask & SEE_MASK_NOCLOSEPROCESS)
2207  sei->hProcess = seiW.hProcess;
2208 
2209  SHFree(wVerb);
2210  SHFree(wFile);
2211  SHFree(wParameters);
2212  SHFree(wDirectory);
2213  SHFree(wClass);
2214 
2215  return ret;
2216 }
2217 
2218 /*************************************************************************
2219  * ShellExecuteExW [SHELL32.293]
2220  *
2221  */
2222 BOOL
2223 WINAPI
2226 {
2227  return SHELL_execute(sei, SHELL_ExecuteW);
2228 }
2229 
2230 /*************************************************************************
2231  * ShellExecuteW [SHELL32.294]
2232  * from shellapi.h
2233  * WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpVerb,
2234  * LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
2235  */
2237  LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
2238 {
2239  SHELLEXECUTEINFOW sei;
2240 
2241  TRACE("\n");
2242  sei.cbSize = sizeof(sei);
2243  sei.fMask = SEE_MASK_FLAG_NO_UI;
2244  sei.hwnd = hwnd;
2245  sei.lpVerb = lpVerb;
2246  sei.lpFile = lpFile;
2247  sei.lpParameters = lpParameters;
2248  sei.lpDirectory = lpDirectory;
2249  sei.nShow = nShowCmd;
2250  sei.lpIDList = 0;
2251  sei.lpClass = 0;
2252  sei.hkeyClass = 0;
2253  sei.dwHotKey = 0;
2254  sei.hProcess = 0;
2255 
2257  return sei.hInstApp;
2258 }
2259 
2260 /*************************************************************************
2261  * WOWShellExecute [SHELL32.@]
2262  *
2263  * FIXME: the callback function most likely doesn't work the same way on Windows.
2264  */
2266  LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd, void *callback)
2267 {
2268  SHELLEXECUTEINFOW seiW;
2269  WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL;
2270  HANDLE hProcess = 0;
2271 
2272  seiW.lpVerb = lpVerb ? __SHCloneStrAtoW(&wVerb, lpVerb) : NULL;
2273  seiW.lpFile = lpFile ? __SHCloneStrAtoW(&wFile, lpFile) : NULL;
2274  seiW.lpParameters = lpParameters ? __SHCloneStrAtoW(&wParameters, lpParameters) : NULL;
2275  seiW.lpDirectory = lpDirectory ? __SHCloneStrAtoW(&wDirectory, lpDirectory) : NULL;
2276 
2277  seiW.cbSize = sizeof(seiW);
2278  seiW.fMask = 0;
2279  seiW.hwnd = hWnd;
2280  seiW.nShow = iShowCmd;
2281  seiW.lpIDList = 0;
2282  seiW.lpClass = 0;
2283  seiW.hkeyClass = 0;
2284  seiW.dwHotKey = 0;
2285  seiW.hProcess = hProcess;
2286 
2288 
2289  SHFree(wVerb);
2290  SHFree(wFile);
2291  SHFree(wParameters);
2292  SHFree(wDirectory);
2293  return seiW.hInstApp;
2294 }
2295 
2296 /*************************************************************************
2297  * OpenAs_RunDLLW [SHELL32.@]
2298  */
2299 EXTERN_C void WINAPI
2301 {
2302  OPENASINFO info;
2303  TRACE("%p, %p, %s, %d\n", hwnd, hinst, debugstr_w(cmdline), cmdshow);
2304 
2305  ZeroMemory(&info, sizeof(info));
2306  info.pcszFile = cmdline;
2307  info.pcszClass = NULL;
2309 
2311 }
2312 
2313 /*************************************************************************
2314  * OpenAs_RunDLLA [SHELL32.@]
2315  */
2316 EXTERN_C void WINAPI
2318 {
2319  LPWSTR pszCmdLineW = NULL;
2320  TRACE("%p, %p, %s, %d\n", hwnd, hinst, debugstr_a(cmdline), cmdshow);
2321 
2322  if (cmdline)
2323  __SHCloneStrAtoW(&pszCmdLineW, cmdline);
2324  OpenAs_RunDLLW(hwnd, hinst, pszCmdLineW, cmdshow);
2325  SHFree(pszCmdLineW);
2326 }
2327 
2328 /*************************************************************************/
2329 
2330 static LPCWSTR
2331 SplitParams(LPCWSTR psz, LPWSTR pszArg0, size_t cchArg0)
2332 {
2333  LPCWSTR pch;
2334  size_t ich = 0;
2335  if (*psz == L'"')
2336  {
2337  // 1st argument is quoted. the string in quotes is quoted 1st argument.
2338  // [pch] --> [pszArg0+ich]
2339  for (pch = psz + 1; *pch && ich + 1 < cchArg0; ++ich, ++pch)
2340  {
2341  if (*pch == L'"' && pch[1] == L'"')
2342  {
2343  // doubled double quotations found!
2344  pszArg0[ich] = L'"';
2345  }
2346  else if (*pch == L'"')
2347  {
2348  // single double quotation found!
2349  ++pch;
2350  break;
2351  }
2352  else
2353  {
2354  // otherwise
2355  pszArg0[ich] = *pch;
2356  }
2357  }
2358  }
2359  else
2360  {
2361  // 1st argument is unquoted. non-space sequence is 1st argument.
2362  // [pch] --> [pszArg0+ich]
2363  for (pch = psz; *pch && !iswspace(*pch) && ich + 1 < cchArg0; ++ich, ++pch)
2364  {
2365  pszArg0[ich] = *pch;
2366  }
2367  }
2368  pszArg0[ich] = 0;
2369 
2370  // skip space
2371  while (iswspace(*pch))
2372  ++pch;
2373 
2374  return pch;
2375 }
2376 
2378  HWND hwnd,
2379  LPCWSTR pwszCommand,
2380  LPCWSTR pwszStartDir,
2381  int nShow,
2382  LPVOID pUnused,
2383  DWORD dwSeclFlags)
2384 {
2387  LPCWSTR pszVerb = NULL;
2388  WCHAR szFile[MAX_PATH], szFile2[MAX_PATH];
2389  HRESULT hr;
2390  LPCWSTR pchParams;
2391  LPWSTR lpCommand = NULL;
2392 
2393  if (pwszCommand == NULL)
2395  1, (ULONG_PTR*)pwszCommand);
2396 
2397  __SHCloneStrW(&lpCommand, pwszCommand);
2398  StrTrimW(lpCommand, L" \t");
2399 
2400  if (dwSeclFlags & SECL_NO_UI)
2402  if (dwSeclFlags & SECL_LOG_USAGE)
2404  if (dwSeclFlags & SECL_USE_IDLIST)
2406 
2407  if (dwSeclFlags & SECL_RUNAS)
2408  {
2409  dwSize = 0;
2410  hr = AssocQueryStringW(0, ASSOCSTR_COMMAND, lpCommand, L"RunAs", NULL, &dwSize);
2411  if (SUCCEEDED(hr) && dwSize != 0)
2412  {
2413  pszVerb = L"runas";
2414  }
2415  }
2416 
2417  if (PathIsURLW(lpCommand) || UrlIsW(lpCommand, URLIS_APPLIABLE))
2418  {
2419  StringCchCopyW(szFile, _countof(szFile), lpCommand);
2420  pchParams = NULL;
2421  }
2422  else
2423  {
2424  pchParams = SplitParams(lpCommand, szFile, _countof(szFile));
2425  if (szFile[0] != UNICODE_NULL && szFile[1] == L':' &&
2426  szFile[2] == UNICODE_NULL)
2427  {
2428  PathAddBackslashW(szFile);
2429  }
2430  if (SearchPathW(NULL, szFile, NULL, _countof(szFile2), szFile2, NULL) ||
2431  SearchPathW(NULL, szFile, wszExe, _countof(szFile2), szFile2, NULL) ||
2432  SearchPathW(NULL, szFile, wszCom, _countof(szFile2), szFile2, NULL) ||
2433  SearchPathW(pwszStartDir, szFile, NULL, _countof(szFile2), szFile2, NULL) ||
2434  SearchPathW(pwszStartDir, szFile, wszExe, _countof(szFile2), szFile2, NULL) ||
2435  SearchPathW(pwszStartDir, szFile, wszCom, _countof(szFile2), szFile2, NULL))
2436  {
2437  StringCchCopyW(szFile, _countof(szFile), szFile2);
2438  }
2439  else if (SearchPathW(NULL, lpCommand, NULL, _countof(szFile2), szFile2, NULL) ||
2440  SearchPathW(NULL, lpCommand, wszExe, _countof(szFile2), szFile2, NULL) ||
2441  SearchPathW(NULL, lpCommand, wszCom, _countof(szFile2), szFile2, NULL) ||
2442  SearchPathW(pwszStartDir, lpCommand, NULL, _countof(szFile2), szFile2, NULL) ||
2443  SearchPathW(pwszStartDir, lpCommand, wszExe, _countof(szFile2), szFile2, NULL) ||
2444  SearchPathW(pwszStartDir, lpCommand, wszCom, _countof(szFile2), szFile2, NULL))
2445  {
2446  StringCchCopyW(szFile, _countof(szFile), szFile2);
2447  pchParams = NULL;
2448  }
2449 
2450  if (!(dwSeclFlags & SECL_ALLOW_NONEXE))
2451  {
2452  if (!GetBinaryTypeW(szFile, &dwType))
2453  {
2454  SHFree(lpCommand);
2455 
2456  if (!(dwSeclFlags & SECL_NO_UI))
2457  {
2458  WCHAR szText[128 + MAX_PATH], szFormat[128];
2460  StringCchPrintfW(szText, _countof(szText), szFormat, szFile);
2462  }
2463  return CO_E_APPNOTFOUND;
2464  }
2465  }
2466  else
2467  {
2469  {
2470  SHFree(lpCommand);
2471 
2472  if (!(dwSeclFlags & SECL_NO_UI))
2473  {
2474  WCHAR szText[128 + MAX_PATH], szFormat[128];
2476  StringCchPrintfW(szText, _countof(szText), szFormat, szFile);
2478  }
2480  }
2481  }
2482  }
2483 
2484  ZeroMemory(&info, sizeof(info));
2485  info.cbSize = sizeof(info);
2486  info.fMask = dwFlags;
2487  info.hwnd = hwnd;
2488  info.lpVerb = pszVerb;
2489  info.lpFile = szFile;
2490  info.lpParameters = (pchParams && *pchParams) ? pchParams : NULL;
2491  info.lpDirectory = pwszStartDir;
2492  info.nShow = nShow;
2493  if (ShellExecuteExW(&info))
2494  {
2495  if (info.lpIDList)
2496  CoTaskMemFree(info.lpIDList);
2497 
2498  SHFree(lpCommand);
2499 
2500  return S_OK;
2501  }
2502 
2503  dwError = GetLastError();
2504 
2505  SHFree(lpCommand);
2506 
2507  return HRESULT_FROM_WIN32(dwError);
2508 }
HINSTANCE hInstApp
Definition: shellapi.h:334
HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpVerb, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
Definition: shlexec.cpp:2141
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
unsigned __int3264 UINT_PTR
Definition: activex.cpp:275
#define ERROR_BAD_FORMAT
Definition: winerror.h:114
BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
Definition: path.c:1702
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
HMENU WINAPI CreateMenu(void)
Definition: menu.c:837
const uint16_t * PCWSTR
Definition: typedefs.h:55
static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
Definition: shlexec.cpp:1633
static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
Definition: shlexec.cpp:1713
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExA(LPSHELLEXECUTEINFOA sei)
Definition: shlexec.cpp:2175
HRESULT WINAPI PathCreateFromUrlW(LPCWSTR pszUrl, LPWSTR pszPath, LPDWORD pcchPath, DWORD dwReserved)
Definition: path.c:3334
#define SEE_MASK_FLAG_DDEWAIT
Definition: shellapi.h:34
#define MIIM_FTYPE
Definition: winuser.h:724
static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR lpstrProtocol, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
Definition: shlexec.cpp:1597
#define TRUE
Definition: types.h:120
#define SEE_MASK_CLASSKEY
Definition: shellapi.h:26
static WCHAR * expand_environment(const WCHAR *str)
Definition: shlexec.cpp:1690
#define CloseHandle
Definition: compat.h:398
static IDataObject * shellex_get_dataobj(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1289
void WINAPI ILFree(LPITEMIDLIST pidl)
Definition: pidl.c:925
HCONV WINAPI DdeConnect(DWORD, HSZ, HSZ, PCONVCONTEXT)
Definition: ddeclient.c:84
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:422
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
static HRESULT shellex_run_context_menu_default(IShellExtInit *obj, LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1324
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
#define WideCharToMultiByte
Definition: compat.h:101
HRESULT hr
Definition: shlfolder.c:183
#define error(str)
Definition: mkdosfs.c:1605
static HMENU hmenu
Definition: win.c:66
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define CREATE_UNICODE_ENVIRONMENT
Definition: winbase.h:186
UINT WINAPI DdeGetLastError(DWORD)
Definition: ddemisc.c:253
EXTERN_C void WINAPI OpenAs_RunDLLW(HWND hwnd, HINSTANCE hinst, LPCWSTR cmdline, int cmdshow)
Definition: shlexec.cpp:2300
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define SECL_USE_IDLIST
Definition: ftp_var.h:139
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
#define KEY_READ
Definition: nt_native.h:1023
static BOOL SHELL_ArgifyW(WCHAR *out, DWORD len, const WCHAR *fmt, const WCHAR *lpFile, LPITEMIDLIST pidl, LPCWSTR args, DWORD *out_len, const WCHAR *lpDir)
Definition: shlexec.cpp:184
#define SEE_MASK_HASTITLE
Definition: shellapi.h:49
uint16_t * PWSTR
Definition: typedefs.h:54
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
#define SEE_MASK_NO_CONSOLE
Definition: shellapi.h:38
#define CP_ACP
Definition: compat.h:99
const GLint * attribs
Definition: glext.h:10538
#define _countof(array)
Definition: fontsub.cpp:30
WINE_UNICODE_INLINE int isspaceW(WCHAR wc)
Definition: unicode.h:165
static UINT_PTR execute_from_key(LPCWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR szCommandline, LPCWSTR executable_name, SHELL_ExecuteW32 execfunc, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
Definition: shlexec.cpp:1110
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define EXCEPTION_ACCESS_VIOLATION
Definition: winbase.h:308
#define FORMAT_MESSAGE_ARGUMENT_ARRAY
Definition: winbase.h:405
#define SE_ERR_OOM
Definition: shellapi.h:125
#define SECL_NO_UI
struct _STARTUPINFOW STARTUPINFOW
#define XTYP_EXECUTE
Definition: ddeml.h:185
#define WARN(fmt,...)
Definition: debug.h:111
LPWSTR WINAPI CharLowerW(_Inout_ LPWSTR)
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
Definition: pidl.c:1280
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:413
#define CALLBACK
Definition: compat.h:27
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
HWND hWnd
Definition: settings.c:17
GLdouble n
Definition: glext.h:7729
#define EXCEPTION_NONCONTINUABLE
Definition: rtltypes.h:150
#define SEE_MASK_ASYNCOK
Definition: shellapi.h:52
#define SECL_RUNAS
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define assert(x)
Definition: debug.h:53
#define SEE_MASK_HASLINKNAME
Definition: shellapi.h:48
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1105
GLuint buffer
Definition: glext.h:5915
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
int startup(int argc, const char *argv[])
Definition: startup.c:430
#define MAKEINTRESOURCEA(i)
Definition: winuser.h:581
char * cmd
Definition: vfdcmd.c:85
static LPCWSTR SplitParams(LPCWSTR psz, LPWSTR pszArg0, size_t cchArg0)
Definition: shlexec.cpp:2331
GLuint GLuint end
Definition: gl.h:1545
TCHAR * cmdline
Definition: stretchblt.cpp:32
WCHAR classname[128]
Definition: startup.c:15
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
#define MFS_DEFAULT
Definition: winuser.h:743
char * LPSTR
Definition: xmlstorage.h:182
BOOL WINAPI DdeFreeDataHandle(HDDEDATA)
Definition: ddemisc.c:1461
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
const char * filename
Definition: ioapi.h:135
#define lstrlenW
Definition: compat.h:407
#define IID_PPV_ARG(Itype, ppType)
#define E_FAIL
Definition: ddrawi.h:102
static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, ULONG_PTR dwData1, ULONG_PTR dwData2)
Definition: shlexec.cpp:892
Definition: match.c:390
BOOL WINAPI GetBinaryTypeW(LPCWSTR lpApplicationName, LPDWORD lpBinaryType)
Definition: vdm.c:1235
HDDEDATA WINAPI DdeClientTransaction(LPBYTE, DWORD, HCONV, HSZ, UINT, UINT, DWORD, LPDWORD)
Definition: ddeclient.c:1122
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
int32_t INT
Definition: typedefs.h:56
#define pch(ap)
Definition: match.c:418
static LPWSTR SHELL_BuildEnvW(const WCHAR *path)
Definition: shlexec.cpp:510
struct TraceInfo Info
DWORD WINAPI GetVersion(VOID)
Definition: version.c:22
#define lstrcpynW
Definition: compat.h:397
BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
Definition: url.c:2432
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
#define ERROR_DDE_FAIL
Definition: winerror.h:678
struct _test_info info[]
Definition: SetCursorPos.c:19
uint32_t ULONG_PTR
Definition: typedefs.h:63
static __inline void __SHCloneStrW(WCHAR **target, const WCHAR *source)
Definition: shell32_main.h:154
static unsigned dde_connect(const WCHAR *key, const WCHAR *start, WCHAR *ddeexec, const WCHAR *lpFile, WCHAR *env, LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc, const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
Definition: shlexec.cpp:910
BOOL WINAPI PathAddExtensionW(LPWSTR lpszPath, LPCWSTR lpszExtension)
Definition: path.c:2617
#define SEE_MASK_CONNECTNETDRV
Definition: shellapi.h:32
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
const GUID * guid
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei)
Definition: shlexec.cpp:1241
unsigned char * LPBYTE
Definition: typedefs.h:52
HINSTANCE shell32_hInstance
Definition: misc.cpp:82
#define UNICODE_NULL
static const WCHAR szText[]
Definition: dialog.c:139
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
Definition: path.c:289
#define MIIM_STATE
Definition: winuser.h:716
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:802
HINSTANCE hInstApp
Definition: shellapi.h:317
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3311
LPCWSTR lpDirectory
Definition: shellapi.h:332
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
#define debugstr_w
Definition: kernel32.h:32
#define DMLERR_NO_ERROR
Definition: ddeml.h:242
#define FIXME(fmt,...)
Definition: debug.h:110
static PVOID ptr
Definition: dispmode.c:27
int WINAPI GetMenuItemCount(_In_opt_ HMENU)
EXTERN_C void WINAPI OpenAs_RunDLLA(HWND hwnd, HINSTANCE hinst, LPCSTR cmdline, int cmdshow)
Definition: shlexec.cpp:2317
static int error_code[8]
Definition: odbccp32.c:62
unsigned int idx
Definition: utils.c:41
ULONG Release()
static UINT_PTR SHELL_execute_class(LPCWSTR wszApplicationName, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
Definition: shlexec.cpp:1494
const WCHAR * str
BOOL WINAPI DdeUninitialize(DWORD)
Definition: ddemisc.c:1112
#define strstrW(d, s)
Definition: unicode.h:32
UINT_PTR(* SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, const SHELLEXECUTEINFOW *sei, LPSHELLEXECUTEINFOW sei_out)
Definition: shlexec.cpp:34
smooth NULL
Definition: ftsmooth.c:416
#define SEE_MASK_NOASYNC
Definition: shellapi.h:33
char ext[3]
Definition: mkdosfs.c:358
#define SEE_MASK_FLAG_NO_UI
Definition: shellapi.h:36
#define SECL_LOG_USAGE
static UINT SHELL_FindExecutableByVerb(LPCWSTR lpVerb, LPWSTR key, LPWSTR classname, LPWSTR command, LONG commandlen)
Definition: shlexec.cpp:627
char * va_list
Definition: acmsvcex.h:78
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
#define SECL_ALLOW_NONEXE
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2225
static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpVerb, LPWSTR lpResult, DWORD resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args)
Definition: shlexec.cpp:697
const char * LPCSTR
Definition: xmlstorage.h:183
#define STARTF_USESHOWWINDOW
Definition: winbase.h:472
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:442
static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
Definition: shlexec.cpp:37
#define debugstr_guid
Definition: kernel32.h:35
HRESULT WINAPI AssocQueryStringW(ASSOCF cfFlags, ASSOCSTR str, LPCWSTR pszAssoc, LPCWSTR pszExtra, LPWSTR pszOut, DWORD *pcchOut)
Definition: assoc.c:427
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
static const WCHAR wszCom[]
Definition: shlexec.cpp:30
#define IDS_SHLEXEC_NOASSOC
Definition: shresdef.h:174
static LONG ShellExecute_FromContextMenu(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1450
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4623
#define MIIM_ID
Definition: winuser.h:717
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
static DWORD ddeInst
Definition: shlexec.c:154
#define DECLSPEC_HOTPATCH
Definition: _mingw.h:224
r l[0]
Definition: byte_order.h:167
_In_opt_ LPCSTR lpDirectory
Definition: shellapi.h:482
c used
Definition: write.c:2885
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:326
#define IID_NULL_PPV_ARG(Itype, ppType)
MmuTrapHandler callback[0x30]
Definition: mmuobject.c:44
BOOL WINAPI GetMenuItemInfoW(_In_ HMENU, _In_ UINT, _In_ BOOL, _Inout_ LPMENUITEMINFOW)
#define TRACE(s)
Definition: solgame.cpp:4
#define SEE_MASK_CLASSNAME
Definition: shellapi.h:25
BOOL WINAPI DdeDisconnect(HCONV)
Definition: ddeclient.c:1363
HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf)
GLsizeiptr size
Definition: glext.h:5919
#define CREATE_NEW_CONSOLE
Definition: winbase.h:180
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4134
#define APPCMD_CLIENTONLY
Definition: ddeml.h:122
HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
Definition: ordinal.c:162
int WINAPI MessageBoxW(_In_opt_ HWND, _In_opt_ LPCWSTR, _In_opt_ LPCWSTR, _In_ UINT)
HRESULT WINAPI SHOpenWithDialog(HWND hwndParent, const OPENASINFO *poainfo)
BOOL WINAPI FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings)
Definition: environ.c:389
__wchar_t WCHAR
Definition: xmlstorage.h:180
LPCSTR lpParameters
Definition: shellapi.h:314
#define debugstr_a
Definition: kernel32.h:31
LONG HRESULT
Definition: typedefs.h:77
GLfloat param
Definition: glext.h:5796
LSTATUS WINAPI RegQueryValueW(HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count)
Definition: reg.c:4272
#define MAX_PATH
Definition: compat.h:26
#define swprintf(buf, format,...)
Definition: sprintf.c:56
#define WINAPI
Definition: msvc.h:8
#define SEE_MASK_DOENVSUBST
Definition: shellapi.h:35
static const WCHAR wszExe[]
Definition: shlexec.cpp:29
static FILE * out
Definition: regtests2xml.c:44
unsigned long DWORD
Definition: ntddk_ex.h:95
#define WAIT_FAILED
Definition: winbase.h:394
#define SetLastError(x)
Definition: compat.h:409
Definition: cookie.c:170
HRESULT WINAPI ShellExecCmdLine(HWND hwnd, LPCWSTR pwszCommand, LPCWSTR pwszStartDir, int nShow, LPVOID pUnused, DWORD dwSeclFlags)
Definition: shlexec.cpp:2377
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
HANDLE HINSTANCE
Definition: typedefs.h:75
#define iswspace(_c)
Definition: ctype.h:669
HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
Definition: shlexec.cpp:1169
HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpResult)
Definition: shlexec.cpp:1212
int ret
GLsizei const GLchar *const * strings
Definition: glext.h:7622
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const WCHAR L[]
Definition: oid.c:1250
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define MB_ICONERROR
Definition: winuser.h:781
#define IDS_FILE_NOT_FOUND
Definition: shresdef.h:285
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
INT WINAPI GetProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR def_val, LPWSTR buffer, UINT len)
Definition: profile.c:1267
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
#define SEE_MASK_HOTKEY
Definition: shellapi.h:30
GLenum src
Definition: glext.h:6340
BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis)
Definition: url.c:1933
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define SEE_MASK_UNICODE
Definition: shellapi.h:37
LPCSTR lpDirectory
Definition: shellapi.h:315
#define wcsicmp
Definition: string.h:1152
#define UrlIsFileUrlW(x)
Definition: shlwapi.h:1377
static HSZ hszTopic
Definition: shlexec.c:155
char string[160]
Definition: util.h:11
BOOL WINAPI DestroyMenu(_In_ HMENU)
DWORD WINAPI SearchPathW(IN LPCWSTR lpPath OPTIONAL, IN LPCWSTR lpFileName, IN LPCWSTR lpExtension OPTIONAL, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart OPTIONAL)
Definition: path.c:1297
LONG WINAPI RegEnumKeyW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, DWORD cbName)
Definition: reg.c:2430
WINE_UNICODE_INLINE WCHAR * strrchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:254
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3234
static const WCHAR wszOpen[]
Definition: shlexec.cpp:28
#define ERR(fmt,...)
Definition: debug.h:109
static HRESULT shellex_load_object_and_run(HKEY hkey, LPCGUID guid, LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1393
#define MIIM_STRING
Definition: winuser.h:722
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
static __inline LPWSTR __SHCloneStrAtoW(WCHAR **target, const char *source)
Definition: shell32_main.h:160
#define S_OK
Definition: intsafe.h:59
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
VOID WINAPI RaiseException(IN DWORD dwExceptionCode, IN DWORD dwExceptionFlags, IN DWORD nNumberOfArguments, IN CONST ULONG_PTR *lpArguments OPTIONAL)
Definition: except.c:693
BOOL HCR_GetDefaultVerbW(HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len)
Definition: classes.c:134
HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
Definition: pidl.c:1323
#define SE_ERR_FNF
Definition: shellapi.h:122
#define SEE_MASK_FLAG_LOG_USAGE
Definition: shellapi.h:57
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:1991
GLuint start
Definition: gl.h:1545
LPCWSTR lpParameters
Definition: shellapi.h:331
BOOL WINAPI SetCurrentDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:2248
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
Definition: services.c:325
GLenum GLenum dst
Definition: glext.h:6340
static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
Definition: shlexec.cpp:429
static const char topic[]
Definition: propsys.c:43
WINE_UNICODE_INLINE WCHAR * strcatW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:242
EXTERN_C HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpVerb, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd, void *callback)
Definition: shlexec.cpp:2265
#define SEE_MASK_IDLIST
Definition: shellapi.h:27
#define SEE_MASK_HMONITOR
Definition: shellapi.h:53
static BOOL SHELL_TryAppPathW(LPCWSTR szName, LPWSTR lpResult, WCHAR **env)
Definition: shlexec.cpp:570
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
Definition: ordinal.c:210
#define CP_WINUNICODE
Definition: ddeml.h:33
unsigned int UINT
Definition: ndis.h:50
BOOL HCR_GetExecuteCommandW(HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len)
Definition: classes.c:200
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
LPWSTR WINAPI GetEnvironmentStringsW(VOID)
Definition: environ.c:344
#define ILGetSize
Definition: shellclasses.h:638
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:168
BOOL WINAPI StrTrimW(LPWSTR lpszStr, LPCWSTR lpszTrim)
Definition: string.c:1869
WINE_DEFAULT_DEBUG_CHANNEL(exec)
int command(const char *fmt,...)
Definition: ftp.c:266
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:331
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1897
#define msg(x)
Definition: auth_time.c:54
static const WCHAR szName[]
Definition: msipriv.h:1194
DWORD WINAPI WaitForInputIdle(_In_ HANDLE, _In_ DWORD)
GLuint res
Definition: glext.h:9613
HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpVerb, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
Definition: shlexec.cpp:2236
BOOL WINAPI SHUnlockShared(LPVOID lpView)
Definition: ordinal.c:242
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id)
Definition: compobj.c:2247
unsigned int ULONG
Definition: retypes.h:1
GLenum target
Definition: glext.h:7315
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3381
static HINSTANCE hinst
Definition: edit.c:551
#define SEE_MASK_INVOKEIDLIST
Definition: shellapi.h:28
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
#define SE_ERR_NOASSOC
Definition: shellapi.h:132
#define CO_E_APPNOTFOUND
Definition: winerror.h:2808
static HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize)
Definition: shlexec.cpp:407
LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path)
Definition: pidl.c:982
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
static void do_error_dialog(UINT_PTR retval, HWND hwnd, WCHAR *filename)
Definition: shlexec.cpp:1669
HSZ WINAPI DdeCreateStringHandleW(DWORD, LPCWSTR, INT)
Definition: ddemisc.c:608
#define MIIM_DATA
Definition: winuser.h:721
#define SEE_MASK_CLASSALL
Definition: shlexec.cpp:32
#define EXTERN_C
Definition: basetyps.h:12
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:412
HRESULT SetSite([in] IUnknown *pUnkSite)
UINT WINAPI DdeInitializeW(LPDWORD, PFNCALLBACK, DWORD, DWORD)
Definition: ddemisc.c:1095
#define memset(x, y, z)
Definition: compat.h:39
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
#define SEE_MASK_ICON
Definition: shellapi.h:29
#define args
Definition: format.c:66
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
static TfClientId tid
Definition: dsound.c:943
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
static void ParseTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
Definition: shlexec.cpp:104
#define HeapFree(x, y, z)
Definition: compat.h:394
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
UINT WINAPI DdeInitializeA(LPDWORD, PFNCALLBACK, DWORD, DWORD)
Definition: ddemisc.c:1075
BOOL WINAPI StrRetToStrNW(LPWSTR dest, DWORD len, LPSTRRET src, const ITEMIDLIST *pidl)
Definition: shellstring.c:84
#define LANG_USER_DEFAULT
Definition: tnerror.cpp:50
#define SUCCEEDED(hr)
Definition: intsafe.h:57
Definition: path.c:42
static BOOL SHELL_translate_idlist(LPSHELLEXECUTEINFOW sei, LPWSTR wszParameters, DWORD parametersLen, LPWSTR wszApplicationName, DWORD dwApplicationNameLen)
Definition: shlexec.cpp:1550
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define REG_SZ
Definition: layer.c:22