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