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