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