ReactOS 0.4.16-dev-1260-g901af6a
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-2024 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 <winbase_undoc.h>
25#include <undocshell.h>
26
28
30
31#define SEE_MASK_CLASSALL (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)
32
33typedef UINT_PTR (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
34 const SHELLEXECUTEINFOW *sei, LPSHELLEXECUTEINFOW sei_out);
35
36// Is the current process a rundll32.exe?
38{
39 WCHAR szModule[MAX_PATH];
40 static INT s_bInDllProcess = -1;
41
42 if (s_bInDllProcess != -1)
43 return s_bInDllProcess;
44
45 s_bInDllProcess = GetModuleFileNameW(NULL, szModule, _countof(szModule)) &&
46 (StrStrIW(PathFindFileNameW(szModule), L"rundll") != NULL);
47 return s_bInDllProcess;
48}
49
51{
52 extern HRESULT SH32_InvokeOpenWith(PCWSTR, LPCMINVOKECOMMANDINFO, HANDLE *);
53
54 HANDLE *phProc = (sei.fMask & SEE_MASK_NOCLOSEPROCESS) ? &sei.hProcess : NULL;
55 UINT fCmic = (sei.fMask & SEE_CMIC_COMMON_BASICFLAGS) | CMIC_MASK_FLAG_NO_UI;
56 CMINVOKECOMMANDINFO ici = { sizeof(ici), fCmic, hWndOwner };
57 ici.nShow = SW_SHOW;
58 HRESULT hr = SH32_InvokeOpenWith(sei.lpFile, &ici, phProc);
60 return SUCCEEDED(hr) ? 42 : SE_ERR_NOASSOC;
61}
62
63static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
64{
65 bool firstCharQuote = false;
66 bool quotes_opened = false;
67 bool backslash_encountered = false;
68
69 for (int curArg = 0; curArg <= argNum && *args; ++curArg)
70 {
71 firstCharQuote = false;
72 if (*args == '"')
73 {
74 quotes_opened = true;
75 firstCharQuote = true;
76 args++;
77 }
78
79 while(*args)
80 {
81 if (*args == '\\')
82 {
83 // if we found a backslash then flip the variable
84 backslash_encountered = !backslash_encountered;
85 }
86 else if (*args == '"')
87 {
88 if (quotes_opened)
89 {
90 if (*(args + 1) != '"')
91 {
92 quotes_opened = false;
93 args++;
94 break;
95 }
96 else
97 {
98 args++;
99 }
100 }
101 else
102 {
103 quotes_opened = true;
104 }
105
106 backslash_encountered = false;
107 }
108 else
109 {
110 backslash_encountered = false;
111 if (*args == ' ' && !firstCharQuote)
112 break;
113 }
114
115 if (curArg == argNum)
116 {
117 used++;
118 if (used < len)
119 *res++ = *args;
120 }
121
122 args++;
123 }
124
125 while(*args == ' ')
126 ++args;
127 }
128}
129
130static void ParseTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
131{
132 bool quotes_opened = false;
133 bool backslash_encountered = false;
134
135 for (int curArg = 0; curArg <= argNum && *args; ++curArg)
136 {
137 while(*args)
138 {
139 if (*args == '\\')
140 {
141 // if we found a backslash then flip the variable
142 backslash_encountered = !backslash_encountered;
143 }
144 else if (*args == '"')
145 {
146 if (quotes_opened)
147 {
148 if (*(args + 1) != '"')
149 {
150 quotes_opened = false;
151 }
152 else
153 {
154 args++;
155 }
156 }
157 else
158 {
159 quotes_opened = true;
160 }
161
162 backslash_encountered = false;
163 }
164 else
165 {
166 backslash_encountered = false;
167 if (*args == ' ' && !quotes_opened && curArg != argNum)
168 break;
169 }
170
171 if (curArg == argNum)
172 {
173 used++;
174 if (used < len)
175 *res++ = *args;
176 }
177
178 args++;
179 }
180 }
181}
182
183/***********************************************************************
184 * SHELL_ArgifyW [Internal]
185 *
186 * this function is supposed to expand the escape sequences found in the registry
187 * some diving reported that the following were used:
188 * + %1, %2... seem to report to parameter of index N in ShellExecute pmts
189 * %1 file
190 * %2 printer
191 * %3 driver
192 * %4 port
193 * %I address of a global item ID (explorer switch /idlist)
194 * %L seems to be %1 as long filename followed by the 8+3 variation
195 * %S ???
196 * %W Working directory
197 * %V Use either %L or %W
198 * %* all following parameters (see batfile)
199 *
200 * The way we parse the command line arguments was determined through extensive
201 * testing and can be summed up by the following rules"
202 *
203 * - %2
204 * - if first letter is " break on first non literal " and include any white spaces
205 * - if first letter is NOT " break on first " or white space
206 * - if " is opened any pair of consecutive " results in ONE literal "
207 *
208 * - %~2
209 * - use rules from here http://www.autohotkey.net/~deleyd/parameters/parameters.htm
210 */
211
212static BOOL SHELL_ArgifyW(WCHAR* out, DWORD len, const WCHAR* fmt, const WCHAR* lpFile, LPITEMIDLIST pidl, LPCWSTR args, DWORD* out_len, const WCHAR* lpDir)
213{
214 BOOL done = FALSE;
215 BOOL found_p1 = FALSE;
216 PWSTR res = out;
217 DWORD used = 0;
218 bool tildeEffect = false;
219
220 TRACE("Before parsing: %p, %d, %s, %s, %p, %p\n", out, len, debugstr_w(fmt),
221 debugstr_w(lpFile), pidl, args);
222
223 while (*fmt)
224 {
225 if (*fmt == '%')
226 {
227 switch (*++fmt)
228 {
229 case '\0':
230 case '%':
231 {
232 used++;
233 if (used < len)
234 *res++ = '%';
235 };
236 break;
237
238 case '*':
239 {
240 if (args)
241 {
242 if (*fmt == '*')
243 {
244 used++;
245 while(*args)
246 {
247 used++;
248 if (used < len)
249 *res++ = *args++;
250 else
251 args++;
252 }
253 used++;
254 break;
255 }
256 }
257 };
258 break;
259
260 case '~':
261
262 case '2':
263 case '3':
264 case '4':
265 case '5':
266 case '6':
267 case '7':
268 case '8':
269 case '9':
270 //case '0':
271 {
272 if (*fmt == '~')
273 {
274 fmt++;
275 tildeEffect = true;
276 }
277
278 if (args)
279 {
280 if (tildeEffect)
281 {
282 ParseTildeEffect(res, args, len, used, *fmt - '2');
283 tildeEffect = false;
284 }
285 else
286 {
288 }
289 }
290 };
291 break;
292
293 case '1':
294 if ((!done || (*fmt == '1')) && lpFile)
295 {
296 SIZE_T filelen = wcslen(lpFile);
297 used += filelen;
298 if (used < len)
299 {
300 wcscpy(res, lpFile);
301 res += filelen;
302 }
303 }
304 found_p1 = TRUE;
305 break;
306
307 /*
308 * IE uses this a lot for activating things such as windows media
309 * player. This is not verified to be fully correct but it appears
310 * to work just fine.
311 */
312 case 'l':
313 case 'L':
314 if (lpFile)
315 {
316 used += wcslen(lpFile);
317 if (used < len)
318 {
319 wcscpy(res, lpFile);
320 res += wcslen(lpFile);
321 }
322 }
323 found_p1 = TRUE;
324 break;
325
326 case 'w':
327 case 'W':
328 if (lpDir)
329 {
330 used += wcslen(lpDir);
331 if (used < len)
332 {
333 wcscpy(res, lpDir);
334 res += wcslen(lpDir);
335 }
336 }
337 break;
338
339 case 'v':
340 case 'V':
341 if (lpFile)
342 {
343 used += wcslen(lpFile);
344 if (used < len)
345 {
346 wcscpy(res, lpFile);
347 res += wcslen(lpFile);
348 }
349 found_p1 = TRUE;
350 }
351 else if (lpDir)
352 {
353 used += wcslen(lpDir);
354 if (used < len)
355 {
356 wcscpy(res, lpDir);
357 res += wcslen(lpDir);
358 }
359 }
360 break;
361
362 case 'i':
363 case 'I':
364 if (pidl)
365 {
366 DWORD chars = 0;
367 /* %p should not exceed 8, maybe 16 when looking forward to 64bit.
368 * allowing a buffer of 100 should more than exceed all needs */
369 WCHAR buf[100];
370 LPVOID pv;
371 HGLOBAL hmem = SHAllocShared(pidl, ILGetSize(pidl), 0);
372 pv = SHLockShared(hmem, 0);
373 chars = swprintf(buf, L":%p", pv);
374
375 if (chars >= ARRAY_SIZE(buf))
376 ERR("pidl format buffer too small!\n");
377
378 used += chars;
379
380 if (used < len)
381 {
382 wcscpy(res, buf);
383 res += chars;
384 }
385 SHUnlockShared(pv);
386 }
387 found_p1 = TRUE;
388 break;
389
390 default:
391 /*
392 * Check if this is an env-variable here...
393 */
394
395 /* Make sure that we have at least one more %.*/
396 if (strchrW(fmt, '%'))
397 {
398 WCHAR tmpBuffer[1024];
399 PWSTR tmpB = tmpBuffer;
400 WCHAR tmpEnvBuff[MAX_PATH];
401 DWORD envRet;
402
403 while (*fmt != '%')
404 *tmpB++ = *fmt++;
405 *tmpB++ = 0;
406
407 TRACE("Checking %s to be an env-var\n", debugstr_w(tmpBuffer));
408
409 envRet = GetEnvironmentVariableW(tmpBuffer, tmpEnvBuff, MAX_PATH);
410 if (envRet == 0 || envRet > MAX_PATH)
411 {
412 used += wcslen(tmpBuffer);
413 if (used < len)
414 {
415 wcscpy( res, tmpBuffer );
416 res += wcslen(tmpBuffer);
417 }
418 }
419 else
420 {
421 used += wcslen(tmpEnvBuff);
422 if (used < len)
423 {
424 wcscpy( res, tmpEnvBuff );
425 res += wcslen(tmpEnvBuff);
426 }
427 }
428 }
429 done = TRUE;
430 break;
431 }
432 /* Don't skip past terminator (catch a single '%' at the end) */
433 if (*fmt != '\0')
434 {
435 fmt++;
436 }
437 }
438 else
439 {
440 used ++;
441 if (used < len)
442 *res++ = *fmt++;
443 else
444 fmt++;
445 }
446 }
447
448 used++;
449 if (res - out < static_cast<int>(len))
450 *res = '\0';
451 else
452 out[len-1] = '\0';
453
454 TRACE("used %i of %i space\n", used, len);
455 if (out_len)
456 *out_len = used;
457
458 TRACE("After parsing: %p, %d, %s, %s, %p, %p\n", out, len, debugstr_w(fmt),
459 debugstr_w(lpFile), pidl, args);
460
461 return found_p1;
462}
463
465{
466 STRRET strret;
467 CComPtr<IShellFolder> desktop;
468
469 HRESULT hr = SHGetDesktopFolder(&desktop);
470
471 if (SUCCEEDED(hr))
472 {
473 hr = desktop->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strret);
474
475 if (SUCCEEDED(hr))
476 StrRetToStrNW(pszPath, uOutSize, &strret, pidl);
477 }
478
479 return hr;
480}
481
482/*************************************************************************
483 * SHELL_ExecuteW [Internal]
484 *
485 */
486static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
487 const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
488{
492 UINT gcdret = 0;
493 WCHAR curdir[MAX_PATH];
494 DWORD dwCreationFlags;
495 const WCHAR *lpDirectory = NULL;
496
497 TRACE("Execute %s from directory %s\n", debugstr_w(lpCmd), debugstr_w(psei->lpDirectory));
498
499 /* make sure we don't fail the CreateProcess if the calling app passes in
500 * a bad working directory */
501 if (!StrIsNullOrEmpty(psei->lpDirectory))
502 {
505 lpDirectory = psei->lpDirectory;
506 }
507
508 /* ShellExecute specifies the command from psei->lpDirectory
509 * if present. Not from the current dir as CreateProcess does */
510 if (lpDirectory)
511 if ((gcdret = GetCurrentDirectoryW( MAX_PATH, curdir)))
513 ERR("cannot set directory %s\n", debugstr_w(lpDirectory));
514
516 startup.cb = sizeof(STARTUPINFOW);
518 startup.wShowWindow = psei->nShow;
519 dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
520 if (!(psei->fMask & SEE_MASK_NO_CONSOLE))
521 dwCreationFlags |= CREATE_NEW_CONSOLE;
522 if (psei->fMask & SEE_MASK_FLAG_SEPVDM)
523 dwCreationFlags |= CREATE_SEPARATE_WOW_VDM;
524 startup.lpTitle = (LPWSTR)(psei->fMask & (SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE) ? psei->lpClass : NULL);
525
526 if (psei->fMask & SEE_MASK_HASLINKNAME)
527 startup.dwFlags |= STARTF_TITLEISLINKNAME;
528
529 if (psei->fMask & SEE_MASK_HOTKEY)
530 {
531 startup.hStdInput = UlongToHandle(psei->dwHotKey);
532 startup.dwFlags |= STARTF_USEHOTKEY;
533 }
534
535 if (psei->fMask & SEE_MASK_ICON) // hIcon has higher precedence than hMonitor
536 {
537 startup.hStdOutput = psei->hIcon;
538 startup.dwFlags |= STARTF_SHELLPRIVATE;
539 }
540 else if ((psei->fMask & SEE_MASK_HMONITOR) || psei->hwnd)
541 {
542 if (psei->fMask & SEE_MASK_HMONITOR)
543 startup.hStdOutput = psei->hMonitor;
544 else if (psei->hwnd)
545 startup.hStdOutput = MonitorFromWindow(psei->hwnd, MONITOR_DEFAULTTONEAREST);
546 if (startup.hStdOutput)
547 startup.dwFlags |= STARTF_SHELLPRIVATE;
548 }
549
550 if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, dwCreationFlags, env,
552 {
553 /* Give 30 seconds to the app to come up, if desired. Probably only needed
554 when starting app immediately before making a DDE connection. */
555 if (shWait)
556 if (WaitForInputIdle(info.hProcess, 30000) == WAIT_FAILED)
557 WARN("WaitForInputIdle failed: Error %d\n", GetLastError() );
558 retval = 33;
559
560 if (psei->fMask & SEE_MASK_NOCLOSEPROCESS)
561 psei_out->hProcess = info.hProcess;
562 else
563 CloseHandle( info.hProcess );
564 CloseHandle( info.hThread );
565 }
566 else if ((retval = GetLastError()) >= 32)
567 {
568 WARN("CreateProcess returned error %ld\n", retval);
570 }
571
572 TRACE("returning %lu\n", retval);
573
574 psei_out->hInstApp = (HINSTANCE)retval;
575
576 if (gcdret)
577 if (!SetCurrentDirectoryW(curdir))
578 ERR("cannot return to directory %s\n", debugstr_w(curdir));
579
580 return retval;
581}
582
583
584/***********************************************************************
585 * SHELL_BuildEnvW [Internal]
586 *
587 * Build the environment for the new process, adding the specified
588 * path to the PATH variable. Returned pointer must be freed by caller.
589 */
591{
593 WCHAR *strings, *p, *p2;
594 int total = wcslen(path) + 1;
595 BOOL got_path = FALSE;
596
597 if (!(strings = GetEnvironmentStringsW())) return NULL;
598 p = strings;
599 while (*p)
600 {
601 int len = wcslen(p) + 1;
602 if (!_wcsnicmp( p, L"PATH=", 5 )) got_path = TRUE;
603 total += len;
604 p += len;
605 }
606 if (!got_path) total += 5; /* we need to create PATH */
607 total++; /* terminating null */
608
609 if (!new_env.Allocate(total))
610 {
612 return NULL;
613 }
614 p = strings;
615 p2 = new_env;
616 while (*p)
617 {
618 int len = wcslen(p) + 1;
619 memcpy(p2, p, len * sizeof(WCHAR));
620 if (!_wcsnicmp( p, L"PATH=", 5 ))
621 {
622 p2[len - 1] = ';';
623 wcscpy( p2 + len, path );
624 p2 += wcslen(path) + 1;
625 }
626 p += len;
627 p2 += len;
628 }
629 if (!got_path)
630 {
631 wcscpy(p2, L"PATH=");
632 wcscat(p2, path);
633 p2 += wcslen(p2) + 1;
634 }
635 *p2 = 0;
637 return new_env.Detach();
638}
639
640/***********************************************************************
641 * SHELL_TryAppPathW [Internal]
642 *
643 * Helper function for SHELL_FindExecutable
644 * @param lpResult - pointer to a buffer of size MAX_PATH
645 * On entry: szName is a filename (probably without path separators).
646 * On exit: if szName found in "App Path", place full path in lpResult, and return true
647 */
649{
650 HKEY hkApp = NULL;
651 WCHAR buffer[1024];
652 DWORD len, dwType;
653 LONG res;
654 BOOL found = FALSE;
655
656 if (env) *env = NULL;
657 wcscpy(buffer, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\");
660 if (res)
661 {
662 // Add ".exe" extension, if extension does not exists
663 if (PathAddExtensionW(buffer, L".exe"))
664 {
666 }
667 if (res) goto end;
668 }
669
670 len = MAX_PATH * sizeof(WCHAR);
671 res = SHRegQueryValueExW(hkApp, NULL, NULL, &dwType, (LPBYTE)lpResult, &len);
672 if (res != ERROR_SUCCESS || dwType != REG_SZ)
673 goto end;
674
675 found = TRUE;
676
677 if (env)
678 {
679 len = sizeof(buffer);
680 res = SHRegQueryValueExW(hkApp, L"Path", NULL, &dwType, (LPBYTE)buffer, &len);
681 if (res == ERROR_SUCCESS && dwType == REG_SZ && buffer[0])
683 }
684
685end:
686 if (hkApp) RegCloseKey(hkApp);
687 return found;
688}
689
690/*************************************************************************
691 * SHELL_FindExecutableByVerb [Internal]
692 *
693 * called from SHELL_FindExecutable or SHELL_execute_class
694 * in/out:
695 * classname a buffer, big enough, to get the key name to do actually the
696 * command "WordPad.Document.1\\shell\\open\\command"
697 * passed as "WordPad.Document.1"
698 * in:
699 * lpVerb the operation on it (open)
700 * commandlen the size of command buffer (in bytes)
701 * out:
702 * command a buffer, to store the command to do the
703 * operation on the file
704 * key a buffer, big enough, to get the key name to do actually the
705 * command "WordPad.Document.1\\shell\\open\\command"
706 * Can be NULL
707 */
709{
710 HKEY hkeyClass;
711 WCHAR verb[MAX_PATH];
712
714 return SE_ERR_NOASSOC;
715 if (!HCR_GetDefaultVerbW(hkeyClass, lpVerb, verb, ARRAY_SIZE(verb)))
716 return SE_ERR_NOASSOC;
717 RegCloseKey(hkeyClass);
718
719 /* Looking for ...buffer\shell<verb>\command */
720 wcscat(classname, L"\\shell\\"); // FIXME: Use HCR_GetExecuteCommandW or AssocAPI
721 wcscat(classname, verb);
722 wcscat(classname, L"\\command");
723
725 &commandlen) == ERROR_SUCCESS)
726 {
727 commandlen /= sizeof(WCHAR);
728 if (key) wcscpy(key, classname);
729#if 0
730 LPWSTR tmp;
731 WCHAR param[256];
732 LONG paramlen = sizeof(param);
733
734 /* FIXME: it seems all Windows version don't behave the same here.
735 * the doc states that this ddeexec information can be found after
736 * the exec names.
737 * on Win98, it doesn't appear, but I think it does on Win2k
738 */
739 /* Get the parameters needed by the application
740 from the associated ddeexec key */
741 tmp = strstrW(classname, L"\\command");
742 tmp[0] = '\0';
743 wcscat(classname, wDdeexec);
745 &paramlen) == ERROR_SUCCESS)
746 {
747 paramlen /= sizeof(WCHAR);
748 wcscat(command, L" ");
750 commandlen += paramlen;
751 }
752#endif
753
754 command[commandlen] = '\0';
755
756 return 33; /* FIXME see SHELL_FindExecutable() */
757 }
758
759 return SE_ERR_NOASSOC;
760}
761
762/*************************************************************************
763 * SHELL_FindExecutable [Internal]
764 *
765 * Utility for code sharing between FindExecutable and ShellExecute
766 * in:
767 * lpFile the name of a file
768 * lpVerb the operation on it (open)
769 * out:
770 * lpResult a buffer, big enough :-(, to store the command to do the
771 * operation on the file
772 * key a buffer, big enough, to get the key name to do actually the
773 * command (it'll be used afterwards for more information
774 * on the operation)
775 */
776static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpVerb,
777 LPWSTR lpResult, DWORD resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args)
778{
779 WCHAR *extension = NULL; /* pointer to file extension */
780 WCHAR classname[256]; /* registry name for this file type */
781 LONG classnamelen = sizeof(classname); /* length of above */
782 WCHAR command[1024]; /* command from registry */
783 WCHAR wBuffer[256]; /* Used to GetProfileString */
785 WCHAR *tok; /* token pointer */
786 WCHAR xlpFile[MAX_PATH]; /* result of PathResolve */
787 DWORD attribs; /* file attributes */
788 WCHAR curdir[MAX_PATH];
789 const WCHAR *search_paths[3] = {0};
790
791 TRACE("%s\n", debugstr_w(lpFile));
792
793 if (!lpResult)
795
796 xlpFile[0] = '\0';
797 lpResult[0] = '\0'; /* Start off with an empty return string */
798 if (key) *key = '\0';
799
800 /* trap NULL parameters on entry */
801 if (!lpFile)
802 {
803 WARN("(lpFile=%s,lpResult=%s): NULL parameter\n",
804 debugstr_w(lpFile), debugstr_w(lpResult));
805 return ERROR_FILE_NOT_FOUND; /* File not found. Close enough, I guess. */
806 }
807
808 if (SHELL_TryAppPathW( lpFile, lpResult, env ))
809 {
810 TRACE("found %s via App Paths\n", debugstr_w(lpResult));
811 return 33;
812 }
813
814 GetCurrentDirectoryW(ARRAY_SIZE(curdir), curdir);
815 if (lpPath && *lpPath)
816 {
817 search_paths[0] = lpPath;
818 search_paths[1] = curdir;
819 }
820 else
821 {
822 search_paths[0] = curdir;
823 }
824
825 lstrcpyW(xlpFile, lpFile);
826 if (PathResolveW(xlpFile, search_paths, PRF_TRYPROGRAMEXTENSIONS | PRF_VERIFYEXISTS) ||
827 PathFindOnPathW(xlpFile, search_paths))
828 {
829 TRACE("PathResolveW returned non-zero\n");
830 lpFile = xlpFile;
831 PathRemoveBlanksW(xlpFile);
832
833 /* Clear any trailing periods */
834 SIZE_T i = wcslen(xlpFile);
835 while (i > 0 && xlpFile[i - 1] == '.')
836 {
837 xlpFile[--i] = '\0';
838 }
839
840 lstrcpyW(lpResult, xlpFile);
841 /* The file was found in lpPath or one of the directories in the system-wide search path */
842 }
843 else
844 {
845 xlpFile[0] = '\0';
846 }
847
848 attribs = GetFileAttributesW(lpFile);
850 {
851 wcscpy(classname, L"Folder");
852 }
853 else
854 {
855 /* Did we get something? Anything? */
856 if (xlpFile[0] == 0)
857 {
858 TRACE("Returning SE_ERR_FNF\n");
859 return SE_ERR_FNF;
860 }
861 /* First thing we need is the file's extension */
862 extension = wcsrchr(xlpFile, '.'); /* Assume last "." is the one; */
863 /* File->Run in progman uses */
864 /* .\FILE.EXE :( */
865 TRACE("xlpFile=%s,extension=%s\n", debugstr_w(xlpFile), debugstr_w(extension));
866
867 if (extension == NULL || extension[1] == 0)
868 {
869 WARN("Returning SE_ERR_NOASSOC\n");
870 return SE_ERR_NOASSOC;
871 }
872
873 /* Three places to check: */
874 /* 1. win.ini, [windows], programs (NB no leading '.') */
875 /* 2. Registry, HKEY_CLASS_ROOT<classname>\shell\open\command */
876 /* 3. win.ini, [extensions], extension (NB no leading '.' */
877 /* All I know of the order is that registry is checked before */
878 /* extensions; however, it'd make sense to check the programs */
879 /* section first, so that's what happens here. */
880
881 /* See if it's a program - if GetProfileString fails, we skip this
882 * section. Actually, if GetProfileString fails, we've probably
883 * got a lot more to worry about than running a program... */
884 if (GetProfileStringW(L"windows", L"programs", L"exe pif bat cmd com", wBuffer, ARRAY_SIZE(wBuffer)) > 0)
885 {
886 CharLowerW(wBuffer);
887 tok = wBuffer;
888 while (*tok)
889 {
890 WCHAR *p = tok;
891 while (*p && *p != ' ' && *p != '\t') p++;
892 if (*p)
893 {
894 *p++ = 0;
895 while (*p == ' ' || *p == '\t') p++;
896 }
897
898 if (_wcsicmp(tok, &extension[1]) == 0) /* have to skip the leading "." */
899 {
900 wcscpy(lpResult, xlpFile);
901 /* Need to perhaps check that the file has a path
902 * attached */
903 TRACE("found %s\n", debugstr_w(lpResult));
904 return 33;
905 /* Greater than 32 to indicate success */
906 }
907 tok = p;
908 }
909 }
910
911 /* Check registry */
913 &classnamelen) == ERROR_SUCCESS)
914 {
915 classnamelen /= sizeof(WCHAR);
916 if (classnamelen == ARRAY_SIZE(classname))
917 classnamelen--;
918
919 classname[classnamelen] = '\0';
920 TRACE("File type: %s\n", debugstr_w(classname));
921 }
922 else
923 {
924 *classname = '\0';
925 }
926 }
927
928 if (*classname)
929 {
930 /* pass the verb string to SHELL_FindExecutableByVerb() */
932
933 if (retval > 32)
934 {
935 DWORD finishedLen;
936 SHELL_ArgifyW(lpResult, resultLen, command, xlpFile, pidl, args, &finishedLen, lpPath);
937 if (finishedLen > resultLen)
938 ERR("Argify buffer not large enough.. truncated\n");
939 /* Remove double quotation marks and command line arguments */
940 if (*lpResult == '"')
941 {
942 WCHAR *p = lpResult;
943 while (*(p + 1) != '"')
944 {
945 *p = *(p + 1);
946 p++;
947 }
948 *p = '\0';
949 }
950 else
951 {
952 /* Truncate on first space */
953 WCHAR *p = lpResult;
954 while (*p != ' ' && *p != '\0')
955 p++;
956 *p = '\0';
957 }
958 }
959 }
960 else /* Check win.ini */
961 {
962 /* Toss the leading dot */
963 extension++;
964 if (GetProfileStringW(L"extensions", extension, L"", command, ARRAY_SIZE(command)) > 0)
965 {
966 if (wcslen(command) != 0)
967 {
968 wcscpy(lpResult, command);
969 tok = wcschr(lpResult, '^'); /* should be ^.extension? */
970 if (tok != NULL)
971 {
972 tok[0] = '\0';
973 wcscat(lpResult, xlpFile); /* what if no dir in xlpFile? */
974 tok = wcschr(command, '^'); /* see above */
975 if ((tok != NULL) && (wcslen(tok) > 5))
976 {
977 wcscat(lpResult, &tok[5]);
978 }
979 }
980 retval = 33; /* FIXME - see above */
981 }
982 }
983 }
984
985 TRACE("returning path %s, retval %d\n", debugstr_w(lpResult), retval);
986 return retval;
987}
988
989/******************************************************************
990 * dde_cb
991 *
992 * callback for the DDE connection. not really useful
993 */
994static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv,
995 HSZ hsz1, HSZ hsz2, HDDEDATA hData,
996 ULONG_PTR dwData1, ULONG_PTR dwData2)
997{
998 TRACE("dde_cb: %04x, %04x, %p, %p, %p, %p, %08lx, %08lx\n",
999 uType, uFmt, hConv, hsz1, hsz2, hData, dwData1, dwData2);
1000 return NULL;
1001}
1002
1003/******************************************************************
1004 * dde_connect
1005 *
1006 * ShellExecute helper. Used to do an operation with a DDE connection
1007 *
1008 * Handles both the direct connection (try #1), and if it fails,
1009 * launching an application and trying (#2) to connect to it
1010 *
1011 */
1012static unsigned dde_connect(const WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
1013 const WCHAR* lpFile, WCHAR *env,
1014 LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc,
1015 const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
1016{
1017 WCHAR regkey[256];
1018 WCHAR * endkey = regkey + wcslen(key);
1019 WCHAR app[256], topic[256], ifexec[256], static_res[256];
1021 WCHAR * res;
1022 LONG applen, topiclen, ifexeclen;
1023 WCHAR * exec;
1024 DWORD ddeInst = 0;
1025 DWORD tid;
1026 DWORD resultLen, endkeyLen;
1027 HSZ hszApp, hszTopic;
1028 HCONV hConv;
1029 HDDEDATA hDdeData;
1030 unsigned ret = SE_ERR_NOASSOC;
1031 BOOL unicode = !(GetVersion() & 0x80000000);
1032
1033 if (strlenW(key) + 1 > ARRAY_SIZE(regkey))
1034 {
1035 FIXME("input parameter %s larger than buffer\n", debugstr_w(key));
1036 return 2;
1037 }
1038 wcscpy(regkey, key);
1039 endkeyLen = ARRAY_SIZE(regkey) - (endkey - regkey);
1040 if (strlenW(L"\\application") + 1 > endkeyLen)
1041 {
1042 FIXME("endkey %s overruns buffer\n", debugstr_w(L"\\application"));
1043 return 2;
1044 }
1045 wcscpy(endkey, L"\\application");
1046 applen = sizeof(app);
1047 if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, app, &applen) != ERROR_SUCCESS)
1048 {
1049 WCHAR command[1024], fullpath[MAX_PATH];
1050 LPWSTR ptr = NULL;
1051 DWORD ret = 0;
1052
1053 /* Get application command from start string and find filename of application */
1054 if (*start == '"')
1055 {
1056 if (strlenW(start + 1) + 1 > ARRAY_SIZE(command))
1057 {
1058 FIXME("size of input parameter %s larger than buffer\n",
1059 debugstr_w(start + 1));
1060 return 2;
1061 }
1062 wcscpy(command, start + 1);
1063 if ((ptr = wcschr(command, '"')))
1064 * ptr = 0;
1065 ret = SearchPathW(NULL, command, L".exe", ARRAY_SIZE(fullpath), fullpath, &ptr);
1066 }
1067 else
1068 {
1069 LPCWSTR p;
1070 LPWSTR space;
1071 for (p = start; (space = const_cast<LPWSTR>(strchrW(p, ' '))); p = space + 1)
1072 {
1073 int idx = space - start;
1074 memcpy(command, start, idx * sizeof(WCHAR));
1075 command[idx] = '\0';
1076 if ((ret = SearchPathW(NULL, command, L".exe", ARRAY_SIZE(fullpath), fullpath, &ptr)))
1077 break;
1078 }
1079 if (!ret)
1080 ret = SearchPathW(NULL, start, L".exe", ARRAY_SIZE(fullpath), fullpath, &ptr);
1081 }
1082
1083 if (!ret)
1084 {
1085 ERR("Unable to find application path for command %s\n", debugstr_w(start));
1086 return ERROR_ACCESS_DENIED;
1087 }
1088 if (strlenW(ptr) + 1 > ARRAY_SIZE(app))
1089 {
1090 FIXME("size of found path %s larger than buffer\n", debugstr_w(ptr));
1091 return 2;
1092 }
1093 wcscpy(app, ptr);
1094
1095 /* Remove extensions (including .so) */
1096 ptr = app + wcslen(app) - 3;
1097 if (ptr > app && !wcscmp(ptr, L".so"))
1098 *ptr = 0;
1099
1100 ptr = const_cast<LPWSTR>(strrchrW(app, '.'));
1101 assert(ptr);
1102 *ptr = 0;
1103 }
1104
1105 if (strlenW(L"\\topic") + 1 > endkeyLen)
1106 {
1107 FIXME("endkey %s overruns buffer\n", debugstr_w(L"\\topic"));
1108 return 2;
1109 }
1110 wcscpy(endkey, L"\\topic");
1111 topiclen = sizeof(topic);
1112 if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, topic, &topiclen) != ERROR_SUCCESS)
1113 {
1114 wcscpy(topic, L"System");
1115 }
1116
1117 if (unicode)
1118 {
1120 return 2;
1121 }
1122 else
1123 {
1125 return 2;
1126 }
1127
1130
1131 hConv = DdeConnect(ddeInst, hszApp, hszTopic, NULL);
1132 exec = ddeexec;
1133 if (!hConv)
1134 {
1135 TRACE("Launching %s\n", debugstr_w(start));
1136 ret = execfunc(start, env, TRUE, psei, psei_out);
1137 if (ret <= 32)
1138 {
1139 TRACE("Couldn't launch\n");
1140 goto error;
1141 }
1142 /* if ddeexec is NULL, then we just need to exit here */
1143 if (ddeexec == NULL)
1144 {
1145 TRACE("Exiting because ddeexec is NULL. ret=42.\n");
1146 /* See https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew */
1147 /* for reason why we use 42 here and also "Shell32_apitest ShellExecuteW" regression test */
1148 return 42;
1149 }
1150 /* if ddeexec is 'empty string', then we just need to exit here */
1151 if (wcscmp(ddeexec, L"") == 0)
1152 {
1153 TRACE("Exiting because ddeexec is 'empty string'. ret=42.\n");
1154 /* See https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutew */
1155 /* for reason why we use 42 here and also "Shell32_apitest ShellExecuteW" regression test */
1156 return 42;
1157 }
1158 hConv = DdeConnect(ddeInst, hszApp, hszTopic, NULL);
1159 if (!hConv)
1160 {
1161 TRACE("Couldn't connect. ret=%d\n", ret);
1164 return 30; /* whatever */
1165 }
1166 if (strlenW(L"\\ifexec") + 1 > endkeyLen)
1167 {
1168 FIXME("endkey %s overruns buffer\n", debugstr_w(L"\\ifexec"));
1169 return 2;
1170 }
1171 strcpyW(endkey, L"\\ifexec");
1172 ifexeclen = sizeof(ifexec);
1173 if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, ifexec, &ifexeclen) == ERROR_SUCCESS)
1174 {
1175 exec = ifexec;
1176 }
1177 }
1178
1179 SHELL_ArgifyW(static_res, ARRAY_SIZE(static_res), exec, lpFile, pidl, szCommandline, &resultLen, NULL);
1180 if (resultLen > ARRAY_SIZE(static_res))
1181 {
1182 dynamic_res.Allocate(resultLen);
1183 res = dynamic_res;
1184 SHELL_ArgifyW(dynamic_res, resultLen, exec, lpFile, pidl, szCommandline, NULL, NULL);
1185 }
1186 else
1187 res = static_res;
1188 TRACE("%s %s => %s\n", debugstr_w(exec), debugstr_w(lpFile), debugstr_w(res));
1189
1190 /* It's documented in the KB 330337 that IE has a bug and returns
1191 * error DMLERR_NOTPROCESSED on XTYP_EXECUTE request.
1192 */
1193 if (unicode)
1194 hDdeData = DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0, XTYP_EXECUTE, 30000, &tid);
1195 else
1196 {
1197 DWORD lenA = WideCharToMultiByte(CP_ACP, 0, res, -1, NULL, 0, NULL, NULL);
1199 resA.Allocate(lenA);
1200 WideCharToMultiByte(CP_ACP, 0, res, -1, resA, lenA, NULL, NULL);
1201 hDdeData = DdeClientTransaction( (LPBYTE)(LPSTR)resA, lenA, hConv, 0L, 0,
1202 XTYP_EXECUTE, 10000, &tid );
1203 }
1204 if (hDdeData)
1205 DdeFreeDataHandle(hDdeData);
1206 else
1207 WARN("DdeClientTransaction failed with error %04x\n", DdeGetLastError(ddeInst));
1208 ret = 33;
1209
1210 DdeDisconnect(hConv);
1211
1212error:
1214
1215 return ret;
1216}
1217
1218/*************************************************************************
1219 * execute_from_key [Internal]
1220 */
1222 LPCWSTR szCommandline, LPCWSTR executable_name,
1223 SHELL_ExecuteW32 execfunc,
1225{
1226 WCHAR cmd[256], param[1024], ddeexec[256];
1227 DWORD cmdlen = sizeof(cmd), ddeexeclen = sizeof(ddeexec);
1229 DWORD resultLen;
1230 LPWSTR tmp;
1231
1232 TRACE("%s %s %s %s %s\n", debugstr_w(key), debugstr_w(lpFile), debugstr_w(env),
1233 debugstr_w(szCommandline), debugstr_w(executable_name));
1234
1235 cmd[0] = '\0';
1236 param[0] = '\0';
1237
1238 /* Get the application from the registry */
1240 {
1241 TRACE("got cmd: %s\n", debugstr_w(cmd));
1242
1243 /* Is there a replace() function anywhere? */
1244 cmdlen /= sizeof(WCHAR);
1245 if (cmdlen >= ARRAY_SIZE(cmd))
1246 cmdlen = ARRAY_SIZE(cmd) - 1;
1247 cmd[cmdlen] = '\0';
1248 SHELL_ArgifyW(param, ARRAY_SIZE(param), cmd, lpFile, (LPITEMIDLIST)psei->lpIDList, szCommandline, &resultLen,
1249 (psei->lpDirectory && *psei->lpDirectory) ? psei->lpDirectory : NULL);
1250 if (resultLen > ARRAY_SIZE(param))
1251 ERR("Argify buffer not large enough, truncating\n");
1252 }
1253
1254 /* Get the parameters needed by the application
1255 from the associated ddeexec key */
1256 tmp = const_cast<LPWSTR>(strstrW(key, L"command"));
1257 assert(tmp);
1258 wcscpy(tmp, L"ddeexec");
1259
1260 if (RegQueryValueW(HKEY_CLASSES_ROOT, key, ddeexec, (LONG *)&ddeexeclen) == ERROR_SUCCESS)
1261 {
1262 TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(ddeexec));
1263 if (!param[0]) strcpyW(param, executable_name);
1264 retval = dde_connect(key, param, ddeexec, lpFile, env, szCommandline, (LPITEMIDLIST)psei->lpIDList, execfunc, psei, psei_out);
1265 }
1266 else if (param[0])
1267 {
1268 TRACE("executing: %s\n", debugstr_w(param));
1269 retval = execfunc(param, env, FALSE, psei, psei_out);
1270 }
1271 else
1272 WARN("Nothing appropriate found for %s\n", debugstr_w(key));
1273
1274 return retval;
1275}
1276
1277/*************************************************************************
1278 * FindExecutableA [SHELL32.@]
1279 */
1281{
1283 WCHAR *wFile = NULL, *wDirectory = NULL;
1284 WCHAR wResult[MAX_PATH];
1285
1286 if (lpFile) __SHCloneStrAtoW(&wFile, lpFile);
1287 if (lpDirectory) __SHCloneStrAtoW(&wDirectory, lpDirectory);
1288
1289 retval = FindExecutableW(wFile, wDirectory, wResult);
1290 WideCharToMultiByte(CP_ACP, 0, wResult, -1, lpResult, MAX_PATH, NULL, NULL);
1291 SHFree(wFile);
1292 SHFree(wDirectory);
1293
1294 TRACE("returning %s\n", lpResult);
1295 return retval;
1296}
1297
1298/*************************************************************************
1299 * FindExecutableW [SHELL32.@]
1300 *
1301 * This function returns the executable associated with the specified file
1302 * for the default verb.
1303 *
1304 * PARAMS
1305 * lpFile [I] The file to find the association for. This must refer to
1306 * an existing file otherwise FindExecutable fails and returns
1307 * SE_ERR_FNF.
1308 * lpResult [O] Points to a buffer into which the executable path is
1309 * copied. This parameter must not be NULL otherwise
1310 * FindExecutable() segfaults. The buffer must be of size at
1311 * least MAX_PATH characters.
1312 *
1313 * RETURNS
1314 * A value greater than 32 on success, less than or equal to 32 otherwise.
1315 * See the SE_ERR_* constants.
1316 *
1317 * NOTES
1318 * On Windows XP and 2003, FindExecutable() seems to first convert the
1319 * filename into 8.3 format, thus taking into account only the first three
1320 * characters of the extension, and expects to find an association for those.
1321 * However other Windows versions behave sanely.
1322 */
1324{
1326 WCHAR old_dir[MAX_PATH], res[MAX_PATH];
1327 DWORD cch = _countof(res);
1328 LPCWSTR dirs[2];
1329
1330 TRACE("File %s, Dir %s\n", debugstr_w(lpFile), debugstr_w(lpDirectory));
1331
1332 *lpResult = UNICODE_NULL;
1333
1334 GetCurrentDirectoryW(_countof(old_dir), old_dir);
1335
1336 if (lpDirectory && *lpDirectory)
1337 {
1339 dirs[0] = lpDirectory;
1340 }
1341 else
1342 {
1343 dirs[0] = old_dir;
1344 }
1345 dirs[1] = NULL;
1346
1347 if (!GetShortPathNameW(lpFile, res, _countof(res)))
1348 StringCchCopyW(res, _countof(res), lpFile);
1349
1351 {
1352 // NOTE: The last parameter of this AssocQueryStringW call is "strange" in Windows.
1353 if (PathIsExeW(res) ||
1355 {
1356 StringCchCopyW(lpResult, MAX_PATH, res);
1357 retval = 42;
1358 }
1359 else
1360 {
1362 }
1363 }
1364 else
1365 {
1367 }
1368
1369 TRACE("returning %s\n", debugstr_w(lpResult));
1370 SetCurrentDirectoryW(old_dir);
1371 return (HINSTANCE)retval;
1372}
1373
1374/* FIXME: is this already implemented somewhere else? */
1376{
1378 return sei->hkeyClass;
1379
1380 HKEY hKey = NULL;
1381 if (sei->fMask & SEE_MASK_CLASSNAME)
1382 {
1383 TRACE("class = %s\n", debugstr_w(sei->lpClass));
1385 return hKey;
1386 }
1388 TRACE("ext = %s\n", debugstr_w(ext));
1389 if (!StrIsNullOrEmpty(ext) && SUCCEEDED(HCR_GetProgIdKeyOfExtension(ext, &hKey, FALSE)))
1390 return hKey;
1391 return NULL;
1392}
1393
1395{
1396 CComHeapPtr<ITEMIDLIST> allocatedPidl;
1397 LPITEMIDLIST pidl = NULL;
1398
1399 if (sei->fMask & SEE_MASK_CLASSALL) // FIXME: This makes no sense? SEE_MASK_IDLIST?
1400 {
1401 pidl = (LPITEMIDLIST)sei->lpIDList;
1402 }
1403 else
1404 {
1405 WCHAR fullpath[MAX_PATH];
1406 BOOL ret;
1407
1408 fullpath[0] = 0;
1409 ret = GetFullPathNameW(sei->lpFile, MAX_PATH, fullpath, NULL);
1410 if (!ret)
1412
1413 pidl = ILCreateFromPathW(fullpath);
1414 allocatedPidl.Attach(pidl);
1415 }
1417}
1418
1421{
1423 CMINVOKECOMMANDINFOEX ici;
1425 WCHAR string[0x80];
1426 INT i, n, def = -1;
1427 HMENU hmenu = 0;
1428 HRESULT r;
1429
1430 TRACE("%p %p\n", obj, sei);
1431
1432 r = obj->QueryInterface(IID_PPV_ARG(IContextMenu, &cm));
1433 if (FAILED(r))
1434 return r;
1435
1436 hmenu = CreateMenu();
1437 if (!hmenu)
1438 goto end;
1439
1440 /* the number of the last menu added is returned in r */
1441 r = cm->QueryContextMenu(hmenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
1442 if (FAILED(r))
1443 goto end;
1444
1446 for (i = 0; i < n; i++)
1447 {
1448 memset(&info, 0, sizeof(info));
1449 info.cbSize = sizeof info;
1451 info.dwTypeData = string;
1452 info.cch = sizeof string;
1453 string[0] = 0;
1455
1456 TRACE("menu %d %s %08x %08lx %08x %08x\n", i, debugstr_w(string),
1457 info.fState, info.dwItemData, info.fType, info.wID);
1458 if ((!sei->lpVerb && (info.fState & MFS_DEFAULT)) ||
1459 (sei->lpVerb && !lstrcmpiW(sei->lpVerb, string)))
1460 {
1461 def = i;
1462 break;
1463 }
1464 }
1465
1466 r = E_FAIL;
1467 if (def == -1)
1468 goto end;
1469
1470 memset(&ici, 0, sizeof ici);
1471 ici.cbSize = sizeof ici;
1472 ici.fMask = (sei->fMask & SEE_CMIC_COMMON_BASICFLAGS) | CMIC_MASK_UNICODE;
1473 ici.nShow = sei->nShow;
1474 ici.lpVerb = MAKEINTRESOURCEA(def);
1475 ici.hwnd = sei->hwnd;
1476 ici.lpParametersW = sei->lpParameters;
1477
1478 r = cm->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
1479
1480 TRACE("invoke command returned %08x\n", r);
1481
1482end:
1483 if (hmenu)
1484 DestroyMenu( hmenu );
1485 return r;
1486}
1487
1489{
1490 TRACE("%p %s %p\n", hkey, debugstr_guid(guid), sei);
1491
1492 CCoInit coInit;
1493
1494 if (FAILED_UNEXPECTEDLY(coInit.hr))
1495 return coInit.hr;
1496
1498 HRESULT hr = CoCreateInstance(*guid, NULL, CLSCTX_INPROC_SERVER,
1501 return hr;
1502
1503 CComPtr<IDataObject> dataobj;
1504 hr = shellex_get_dataobj(sei, dataobj);
1506 return hr;
1507
1508 hr = obj->Initialize(NULL, dataobj, hkey);
1510 return hr;
1511
1513 hr = obj->QueryInterface(IID_PPV_ARG(IObjectWithSite, &ows));
1515 return hr;
1516
1517 ows->SetSite(NULL);
1518
1520}
1521
1523{
1524 CComHeapPtr<ITEMIDLIST> allocatedPidl;
1525 LPITEMIDLIST pidl = NULL;
1526
1527 if (sei->lpIDList)
1528 {
1529 pidl = (LPITEMIDLIST)sei->lpIDList;
1530 }
1531 else
1532 {
1533 SFGAOF sfga = 0;
1534 HRESULT hr = SHParseDisplayName(sei->lpFile, NULL, &allocatedPidl, SFGAO_STORAGECAPMASK, &sfga);
1535 if (FAILED(hr))
1536 {
1537 WCHAR Buffer[MAX_PATH] = {};
1538 // FIXME: MAX_PATH.....
1540 if (retval <= 32)
1541 return HRESULT_FROM_WIN32(retval);
1542
1543 hr = SHParseDisplayName(Buffer, NULL, &allocatedPidl, SFGAO_STORAGECAPMASK, &sfga);
1544 // This should not happen, we found it...
1546 return hr;
1547 }
1548
1549 pidl = allocatedPidl;
1550 }
1551
1553 LPCITEMIDLIST pidllast = NULL;
1554 HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &shf), &pidllast);
1555 if (FAILED(hr))
1556 return hr;
1557
1558 return shf->GetUIObjectOf(NULL, 1, &pidllast, IID_NULL_PPV_ARG(IContextMenu, &cm));
1559}
1560
1562{
1563 TRACE("%p\n", sei);
1564
1565 CCoInit coInit;
1566
1567 if (FAILED_UNEXPECTEDLY(coInit.hr))
1568 return coInit.hr;
1569
1573 return hr;
1574
1575 CComHeapPtr<char> verb, parameters, dir;
1576 __SHCloneStrWtoA(&verb, sei->lpVerb);
1577 __SHCloneStrWtoA(&parameters, sei->lpParameters);
1579
1580 BOOL fDefault = StrIsNullOrEmpty(sei->lpVerb);
1581 CMINVOKECOMMANDINFOEX ici = { sizeof(ici) };
1582 ici.fMask = SeeFlagsToCmicFlags(sei->fMask) | CMIC_MASK_UNICODE;
1583 ici.nShow = sei->nShow;
1584 if (!fDefault)
1585 {
1586 ici.lpVerb = verb;
1587 ici.lpVerbW = sei->lpVerb;
1588 }
1589 ici.hwnd = sei->hwnd;
1590 ici.lpParameters = parameters;
1591 ici.lpParametersW = sei->lpParameters;
1592 ici.lpDirectory = dir;
1593 ici.lpDirectoryW = sei->lpDirectory;
1594 ici.dwHotKey = sei->dwHotKey;
1595 ici.hIcon = sei->hIcon;
1596 if (ici.fMask & (CMIC_MASK_HASLINKNAME | CMIC_MASK_HASTITLE))
1597 ici.lpTitleW = sei->lpClass;
1598
1599 enum { idFirst = 1, idLast = 0x7fff };
1600 HMENU hMenu = CreatePopupMenu();
1601 // Note: Windows does not pass CMF_EXTENDEDVERBS so "hidden" verbs cannot be executed
1602 hr = cm->QueryContextMenu(hMenu, 0, idFirst, idLast, fDefault ? CMF_DEFAULTONLY : 0);
1603 if (!FAILED_UNEXPECTEDLY(hr))
1604 {
1605 if (fDefault)
1606 {
1607 INT uDefault = GetMenuDefaultItem(hMenu, FALSE, 0);
1608 uDefault = (uDefault != -1) ? uDefault - idFirst : 0;
1609 ici.lpVerb = MAKEINTRESOURCEA(uDefault);
1610 ici.lpVerbW = MAKEINTRESOURCEW(uDefault);
1611 }
1612
1613 hr = cm->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
1614 if (!FAILED_UNEXPECTEDLY(hr))
1615 hr = S_OK;
1616 }
1617
1618 DestroyMenu(hMenu);
1619
1620 return hr;
1621}
1622
1623
1624/*************************************************************************
1625 * ShellExecute_FromContextMenu [Internal]
1626 */
1628{
1629 HKEY hkey, hkeycm = 0;
1630 WCHAR szguid[39];
1631 HRESULT hr;
1632 GUID guid;
1633 DWORD i;
1634 LONG r;
1635
1636 TRACE("%s\n", debugstr_w(sei->lpFile));
1637
1638 hkey = ShellExecute_GetClassKey(sei);
1639 if (!hkey)
1640 return ERROR_FUNCTION_FAILED;
1641
1642 // FIXME: Words cannot describe how broken this is, all of it needs to die
1643 r = RegOpenKeyW(hkey, L"shellex\\ContextMenuHandlers", &hkeycm);
1644 if (r == ERROR_SUCCESS)
1645 {
1646 i = 0;
1647 while (1)
1648 {
1649 r = RegEnumKeyW(hkeycm, i++, szguid, ARRAY_SIZE(szguid));
1650 if (r != ERROR_SUCCESS)
1651 break;
1652
1653 hr = CLSIDFromString(szguid, &guid);
1654 if (SUCCEEDED(hr))
1655 {
1656 /* stop at the first one that succeeds in running */
1657 hr = shellex_load_object_and_run(hkey, &guid, sei);
1658 if (SUCCEEDED(hr))
1659 break;
1660 }
1661 }
1662 RegCloseKey(hkeycm);
1663 }
1664
1665 if (hkey != sei->hkeyClass)
1666 RegCloseKey(hkey);
1667 return r;
1668}
1669
1670static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR wszKeyname, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc);
1671
1673{
1674 WCHAR execCmd[1024], classname[1024];
1675 /* launch a document by fileclass like 'WordPad.Document.1' */
1676 /* the Commandline contains 'c:\Path\wordpad.exe "%1"' */
1677 /* FIXME: wcmd should not be of a fixed size. Fixed to 1024, MAX_PATH is way too short! */
1678 ULONG cmask = (psei->fMask & SEE_MASK_CLASSALL);
1679 DWORD resultLen;
1680 BOOL done;
1681 UINT_PTR rslt;
1682
1683 /* FIXME: remove following block when SHELL_quote_and_execute supports hkeyClass parameter */
1684 if (cmask != SEE_MASK_CLASSNAME)
1685 {
1686 WCHAR wcmd[1024];
1688 (cmask == SEE_MASK_CLASSNAME) ? psei->lpClass : NULL,
1689 psei->lpVerb,
1690 execCmd, sizeof(execCmd));
1691
1692 /* FIXME: get the extension of lpFile, check if it fits to the lpClass */
1693 TRACE("SEE_MASK_CLASSNAME->%s, doc->%s\n", debugstr_w(execCmd), debugstr_w(wszApplicationName));
1694
1695 wcmd[0] = '\0';
1696 done = SHELL_ArgifyW(wcmd, ARRAY_SIZE(wcmd), execCmd, wszApplicationName, (LPITEMIDLIST)psei->lpIDList, psei->lpParameters,
1697 &resultLen, (psei->lpDirectory && *psei->lpDirectory) ? psei->lpDirectory : NULL);
1698 if (!done && wszApplicationName[0])
1699 {
1700#if 0 // Given HKCR\.test=SZ:"test" and HKCR\test\shell\open\command=SZ:"cmd.exe /K echo.Hello", no filename is
1701 // appended on Windows when there is no %1 nor %L when executed with: shlextdbg.exe /shellexec=c:\file.test /INVOKE
1702 strcatW(wcmd, L" ");
1703 if (*wszApplicationName != '"')
1704 {
1705 strcatW(wcmd, L"\"");
1706 strcatW(wcmd, wszApplicationName);
1707 strcatW(wcmd, L"\"");
1708 }
1709 else
1710 strcatW(wcmd, wszApplicationName);
1711#endif
1712 }
1713 if (resultLen > ARRAY_SIZE(wcmd))
1714 ERR("Argify buffer not large enough... truncating\n");
1715 return execfunc(wcmd, NULL, FALSE, psei, psei_out);
1716 }
1717
1718 strcpyW(classname, psei->lpClass);
1719 rslt = SHELL_FindExecutableByVerb(psei->lpVerb, NULL, classname, execCmd, sizeof(execCmd));
1720
1721 TRACE("SHELL_FindExecutableByVerb returned %u (%s, %s)\n", (unsigned int)rslt, debugstr_w(classname), debugstr_w(execCmd));
1722 if (33 > rslt)
1723 return rslt;
1724 rslt = SHELL_quote_and_execute( execCmd, L"", classname,
1725 wszApplicationName, NULL, psei,
1726 psei_out, execfunc );
1727 return rslt;
1728
1729}
1730
1731static BOOL SHELL_translate_idlist(LPSHELLEXECUTEINFOW sei, LPWSTR wszParameters, DWORD parametersLen, LPWSTR wszApplicationName, DWORD dwApplicationNameLen)
1732{
1734 BOOL appKnownSingular = FALSE;
1735
1736 /* last chance to translate IDList: now also allow CLSID paths */
1738 if (buffer[0] == ':' && buffer[1] == ':') {
1739 /* open shell folder for the specified class GUID */
1740 if (strlenW(buffer) + 1 > parametersLen)
1741 ERR("parameters len exceeds buffer size (%i > %i), truncating\n",
1742 lstrlenW(buffer) + 1, parametersLen);
1743 lstrcpynW(wszParameters, buffer, parametersLen);
1744 if (strlenW(L"explorer.exe") > dwApplicationNameLen)
1745 ERR("application len exceeds buffer size (%i), truncating\n",
1746 dwApplicationNameLen);
1747 lstrcpynW(wszApplicationName, L"explorer.exe", dwApplicationNameLen);
1748 appKnownSingular = TRUE;
1749
1750 sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
1751 } else {
1753 DWORD attribs;
1754 DWORD resultLen;
1755 /* Check if we're executing a directory and if so use the
1756 handler for the Folder class */
1761 HCR_GetExecuteCommandW(0, L"Folder",
1762 sei->lpVerb,
1763 buffer, sizeof(buffer))) {
1764 SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen,
1765 buffer, target, (LPITEMIDLIST)sei->lpIDList, NULL, &resultLen,
1766 !StrIsNullOrEmpty(sei->lpDirectory) ? sei->lpDirectory : NULL);
1767 if (resultLen > dwApplicationNameLen)
1768 ERR("Argify buffer not large enough... truncating\n"); // FIXME: Report this to the caller?
1769 appKnownSingular = FALSE;
1770 // HACKFIX: We really want the !appKnownSingular code in SHELL_execute to split the
1771 // parameters for us but we cannot guarantee that the exe in the registry is quoted.
1772 // We have now turned 'explorer.exe "%1" into 'explorer.exe "c:\path\from\pidl"' and
1773 // need to split to application and parameters.
1774 LPCWSTR params = PathGetArgsW(wszApplicationName);
1775 lstrcpynW(wszParameters, params, parametersLen);
1776 PathRemoveArgsW(wszApplicationName);
1777 PathUnquoteSpacesW(wszApplicationName);
1778 appKnownSingular = TRUE;
1779 }
1780 sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
1781 }
1782 }
1783 return appKnownSingular;
1784}
1785
1786static BOOL
1789 _In_ LPCITEMIDLIST pidl)
1790{
1791 // Bind pidl
1792 CComPtr<IShellFolder> psfFolder;
1793 LPCITEMIDLIST pidlLast;
1794 HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &psfFolder), &pidlLast);
1796 return FALSE;
1797
1798 // Get the context menu to invoke a command
1800 hr = psfFolder->GetUIObjectOf(NULL, 1, &pidlLast, IID_NULL_PPV_ARG(IContextMenu, &pCM));
1802 return FALSE;
1803
1804 // Invoke a command
1805 CMINVOKECOMMANDINFO ici = { sizeof(ici) };
1806 ici.fMask = (sei->fMask & SEE_CMIC_COMMON_BASICFLAGS) & ~CMIC_MASK_UNICODE; // FIXME: Unicode?
1807 ici.nShow = sei->nShow;
1808 ici.hwnd = sei->hwnd;
1809 char szVerb[VERBKEY_CCHMAX];
1810 if (sei->lpVerb && sei->lpVerb[0])
1811 {
1812 WideCharToMultiByte(CP_ACP, 0, sei->lpVerb, -1, szVerb, _countof(szVerb), NULL, NULL);
1813 szVerb[_countof(szVerb) - 1] = ANSI_NULL; // Avoid buffer overrun
1814 ici.lpVerb = szVerb;
1815 }
1816 else // The default verb?
1817 {
1818 HMENU hMenu = CreatePopupMenu();
1819 const INT idCmdFirst = 1, idCmdLast = 0x7FFF;
1820 hr = pCM->QueryContextMenu(hMenu, 0, idCmdFirst, idCmdLast, CMF_DEFAULTONLY);
1822 {
1823 DestroyMenu(hMenu);
1824 return FALSE;
1825 }
1826
1827 INT nDefaultID = GetMenuDefaultItem(hMenu, FALSE, 0);
1828 DestroyMenu(hMenu);
1829 if (nDefaultID == -1)
1830 nDefaultID = idCmdFirst;
1831
1832 ici.lpVerb = MAKEINTRESOURCEA(nDefaultID - idCmdFirst);
1833 }
1834 hr = pCM->InvokeCommand(&ici);
1835
1836 return !FAILED_UNEXPECTEDLY(hr);
1837}
1838
1839static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR wszKeyname, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
1840{
1842 DWORD len;
1844
1845 /* Length of quotes plus length of command plus NULL terminator */
1846 len = 2 + lstrlenW(wcmd) + 1;
1847 if (wszParameters[0])
1848 {
1849 /* Length of space plus length of parameters */
1850 len += 1 + lstrlenW(wszParameters);
1851 }
1852 wszQuotedCmd.Allocate(len);
1853 /* Must quote to handle case where cmd contains spaces,
1854 * else security hole if malicious user creates executable file "C:\\Program"
1855 */
1856 strcpyW(wszQuotedCmd, L"\"");
1857 strcatW(wszQuotedCmd, wcmd);
1858 strcatW(wszQuotedCmd, L"\"");
1859 if (wszParameters[0])
1860 {
1861 strcatW(wszQuotedCmd, L" ");
1862 strcatW(wszQuotedCmd, wszParameters);
1863 }
1864
1865 TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), debugstr_w(psei->lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(wszKeyname));
1866
1867 if (*wszKeyname)
1868 retval = execute_from_key(wszKeyname, wszApplicationName, env, psei->lpParameters, wcmd, execfunc, psei, psei_out);
1869 else
1870 retval = execfunc(wszQuotedCmd, env, FALSE, psei, psei_out);
1871
1872 return retval;
1873}
1874
1876{
1879 LPCWSTR lpstrRes;
1880 INT iSize;
1881 DWORD len;
1882
1883 lpstrRes = strchrW(lpFile, ':');
1884 if (lpstrRes)
1885 iSize = lpstrRes - lpFile;
1886 else
1887 iSize = strlenW(lpFile);
1888
1889 TRACE("Got URL: %s\n", debugstr_w(lpFile));
1890 /* Looking for ...<protocol>\shell<lpVerb>\command */
1891 len = iSize + lstrlenW(L"\\shell\\") + lstrlenW(L"\\command") + 1;
1892 if (psei->lpVerb && *psei->lpVerb)
1893 len += lstrlenW(psei->lpVerb);
1894 else
1895 len += lstrlenW(L"open"); // FIXME: Use HCR_GetExecuteCommandW or AssocAPI
1896 lpstrProtocol.Allocate(len);
1897 memcpy(lpstrProtocol, lpFile, iSize * sizeof(WCHAR));
1898 lpstrProtocol[iSize] = '\0';
1899 strcatW(lpstrProtocol, L"\\shell\\");
1900 strcatW(lpstrProtocol, psei->lpVerb && *psei->lpVerb ? psei->lpVerb : L"open");
1901 strcatW(lpstrProtocol, L"\\command");
1902
1903 retval = execute_from_key(lpstrProtocol, lpFile, NULL, psei->lpParameters,
1904 wcmd, execfunc, psei, psei_out);
1905
1906 return retval;
1907}
1908
1910{
1911 WCHAR msg[2048];
1912 DWORD_PTR msgArguments[3] = { (DWORD_PTR)filename, 0, 0 };
1913 const DWORD error_code = GetLastError();
1914
1915 if (retval == SE_ERR_NOASSOC)
1917 else
1919 NULL,
1920 error_code,
1922 msg,
1923 ARRAY_SIZE(msg),
1924 (va_list*)msgArguments);
1925
1927 SetLastError(error_code); // Restore
1928}
1929
1931{
1933 DWORD len;
1934
1936 if (!len) return NULL;
1937
1938 if (!buf.Allocate(len))
1939 return NULL;
1940
1942 if (!len)
1943 return NULL;
1944
1945 return buf.Detach();
1946}
1947
1948/*************************************************************************
1949 * SHELL_execute [Internal]
1950 */
1952{
1953 static const DWORD unsupportedFlags =
1955
1956 DWORD len;
1958 BOOL appKnownSingular = FALSE;
1959
1960 /* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
1961 sei->hProcess = NULL;
1962 SHELLEXECUTEINFOW sei_tmp = *sei;
1963
1964 TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
1965 sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
1966 debugstr_w(sei_tmp.lpFile), debugstr_w(sei_tmp.lpParameters),
1967 debugstr_w(sei_tmp.lpDirectory), sei_tmp.nShow,
1968 ((sei_tmp.fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME) ?
1969 debugstr_w(sei_tmp.lpClass) : "not used");
1970
1971 /* make copies of all path/command strings */
1972 CHeapPtr<WCHAR, CLocalAllocator> wszApplicationName;
1973 DWORD dwApplicationNameLen = MAX_PATH + 2;
1974 if (!sei_tmp.lpFile)
1975 {
1976 wszApplicationName.Allocate(dwApplicationNameLen);
1977 *wszApplicationName = '\0';
1978 }
1979 else if (*sei_tmp.lpFile == '\"' && sei_tmp.lpFile[(len = strlenW(sei_tmp.lpFile))-1] == '\"')
1980 {
1981 if(len-1 >= dwApplicationNameLen)
1982 dwApplicationNameLen = len;
1983
1984 wszApplicationName.Allocate(dwApplicationNameLen);
1985 memcpy(wszApplicationName, sei_tmp.lpFile + 1, len * sizeof(WCHAR));
1986
1987 if(len > 2)
1988 wszApplicationName[len-2] = '\0';
1989 appKnownSingular = TRUE;
1990
1991 TRACE("wszApplicationName=%s\n", debugstr_w(wszApplicationName));
1992 }
1993 else
1994 {
1995 DWORD l = strlenW(sei_tmp.lpFile) + 1;
1996 if(l > dwApplicationNameLen) dwApplicationNameLen = l + 1;
1997 wszApplicationName.Allocate(dwApplicationNameLen);
1998 memcpy(wszApplicationName, sei_tmp.lpFile, l * sizeof(WCHAR));
1999
2000 if (wszApplicationName[2] == 0 && wszApplicationName[1] == L':' &&
2001 ((L'A' <= wszApplicationName[0] && wszApplicationName[0] <= L'Z') ||
2002 (L'a' <= wszApplicationName[0] && wszApplicationName[0] <= L'z')))
2003 {
2004 // 'C:' --> 'C:\'
2005 PathAddBackslashW(wszApplicationName);
2006 }
2007 }
2008
2009 WCHAR parametersBuffer[1024];
2010 LPWSTR wszParameters = parametersBuffer;
2012 DWORD parametersLen = _countof(parametersBuffer);
2013
2014 if (sei_tmp.lpParameters)
2015 {
2016 len = lstrlenW(sei_tmp.lpParameters) + 1;
2017 if (len > parametersLen)
2018 {
2019 wszParamAlloc.Allocate(len);
2020 wszParameters = wszParamAlloc;
2021 parametersLen = len;
2022 }
2023 strcpyW(wszParameters, sei_tmp.lpParameters);
2024 }
2025 else
2026 *wszParameters = L'\0';
2027
2028 // Get the working directory
2029 WCHAR dirBuffer[MAX_PATH];
2030 LPWSTR wszDir = dirBuffer;
2031 wszDir[0] = UNICODE_NULL;
2033 if (sei_tmp.lpDirectory && *sei_tmp.lpDirectory)
2034 {
2035 if (sei_tmp.fMask & SEE_MASK_DOENVSUBST)
2036 {
2037 LPWSTR tmp = expand_environment(sei_tmp.lpDirectory);
2038 if (tmp)
2039 {
2040 wszDirAlloc.Attach(tmp);
2041 wszDir = wszDirAlloc;
2042 }
2043 }
2044 else
2045 {
2046 __SHCloneStrW(&wszDirAlloc, sei_tmp.lpDirectory);
2047 if (wszDirAlloc)
2048 wszDir = wszDirAlloc;
2049 }
2050 }
2051 if (!wszDir[0])
2052 {
2053 ::GetCurrentDirectoryW(_countof(dirBuffer), dirBuffer);
2054 wszDir = dirBuffer;
2055 }
2056 // NOTE: ShellExecute should accept the invalid working directory for historical reason.
2057 if (!PathIsDirectoryW(wszDir))
2058 {
2059 INT iDrive = PathGetDriveNumberW(wszDir);
2060 if (iDrive >= 0)
2061 {
2062 PathStripToRootW(wszDir);
2063 if (!PathIsDirectoryW(wszDir))
2064 {
2065 ::GetWindowsDirectoryW(dirBuffer, _countof(dirBuffer));
2066 wszDir = dirBuffer;
2067 }
2068 }
2069 }
2070
2071 /* adjust string pointers to point to the new buffers */
2072 sei_tmp.lpFile = wszApplicationName;
2073 sei_tmp.lpParameters = wszParameters;
2074 sei_tmp.lpDirectory = wszDir;
2075
2076 if (sei_tmp.fMask & unsupportedFlags)
2077 {
2078 FIXME("flags ignored: 0x%08x\n", sei_tmp.fMask & unsupportedFlags);
2079 }
2080
2081 /* process the IDList */
2082 if (sei_tmp.fMask & SEE_MASK_IDLIST &&
2084 {
2085 LPCITEMIDLIST pidl = (LPCITEMIDLIST)sei_tmp.lpIDList;
2086
2089 if (SUCCEEDED(hr))
2090 {
2091 hr = pSEH->Execute(&sei_tmp);
2092 if (hr == S_OK)
2093 return TRUE;
2094 }
2095
2096 hr = SHGetNameAndFlagsW(pidl, SHGDN_FORPARSING, wszApplicationName, dwApplicationNameLen, NULL);
2097 if (FAILED(hr))
2098 {
2099 if (dwApplicationNameLen)
2100 *wszApplicationName = UNICODE_NULL;
2101 if (!_ILIsDesktop(pidl))
2102 TRACE("Unable to get PIDL parsing path\n");
2103 }
2104 appKnownSingular = TRUE;
2105 TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName));
2106 }
2107
2108 if ((sei_tmp.fMask & SEE_MASK_DOENVSUBST) && !StrIsNullOrEmpty(sei_tmp.lpFile))
2109 {
2110 WCHAR *tmp = expand_environment(sei_tmp.lpFile);
2111 if (tmp)
2112 {
2113 wszApplicationName.Attach(tmp);
2114 sei_tmp.lpFile = wszApplicationName;
2115 }
2116 }
2117
2119 {
2121 if (SUCCEEDED(hr))
2122 {
2123 sei->hInstApp = (HINSTANCE)42;
2124 return TRUE;
2125 }
2126 }
2127
2129 {
2130 sei->hInstApp = (HINSTANCE) 33;
2131 return TRUE;
2132 }
2133
2134 if (sei_tmp.fMask & SEE_MASK_CLASSALL)
2135 {
2136 retval = SHELL_execute_class(wszApplicationName, &sei_tmp, sei, execfunc);
2137 if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
2138 {
2140
2141 //FIXME
2142 // need full path
2143
2144 Info.pcszFile = wszApplicationName;
2145 Info.pcszClass = NULL;
2146 Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
2147
2148 //if (SHOpenWithDialog(sei_tmp.hwnd, &Info) != S_OK)
2150 do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName);
2151 }
2152 return retval > 32;
2153 }
2154
2155 if (!(sei_tmp.fMask & SEE_MASK_IDLIST) && // Not an ID List
2156 (StrCmpNIW(sei_tmp.lpFile, L"shell:", 6) == 0 ||
2157 StrCmpNW(sei_tmp.lpFile, L"::{", 3) == 0))
2158 {
2159 CComHeapPtr<ITEMIDLIST> pidlParsed;
2160 HRESULT hr = SHParseDisplayName(sei_tmp.lpFile, NULL, &pidlParsed, 0, NULL);
2161 if (SUCCEEDED(hr) && SHELL_InvokePidl(&sei_tmp, pidlParsed))
2162 {
2163 sei_tmp.hInstApp = (HINSTANCE)UlongToHandle(42);
2164 return TRUE;
2165 }
2166 }
2167
2168 /* Has the IDList not yet been translated? */
2169 if (sei_tmp.fMask & SEE_MASK_IDLIST)
2170 {
2171 appKnownSingular = SHELL_translate_idlist( &sei_tmp, wszParameters,
2172 parametersLen,
2173 wszApplicationName,
2174 dwApplicationNameLen );
2175 }
2176
2177 /* convert file URLs */
2178 if (UrlIsFileUrlW(sei_tmp.lpFile))
2179 {
2182 if (!buf.Allocate(size) || FAILED(PathCreateFromUrlW(sei_tmp.lpFile, buf, &size, 0)))
2183 {
2185 return FALSE;
2186 }
2187
2188 wszApplicationName.Attach(buf.Detach());
2189 sei_tmp.lpFile = wszApplicationName;
2190 }
2191
2192 /* Else, try to execute the filename */
2193 TRACE("execute: %s,%s,%s\n", debugstr_w(wszApplicationName), debugstr_w(wszParameters), debugstr_w(wszDir));
2194
2195 /* separate out command line arguments from executable file name */
2196 LPCWSTR lpFile = sei_tmp.lpFile;
2197 if (!*sei_tmp.lpParameters && !appKnownSingular)
2198 {
2199 /* If the executable path is quoted, handle the rest of the command line as parameters. */
2200 if (sei_tmp.lpFile[0] == L'"')
2201 {
2202 LPWSTR pszArgs = PathGetArgsW(wszApplicationName);
2203 PathRemoveArgsW(wszApplicationName);
2204 PathUnquoteSpacesW(wszApplicationName);
2205 parametersLen = lstrlenW(pszArgs);
2206 if (parametersLen < _countof(parametersBuffer))
2207 {
2208 StringCchCopyW(parametersBuffer, _countof(parametersBuffer), pszArgs);
2209 wszParameters = parametersBuffer;
2210 }
2211 else
2212 {
2213 wszParamAlloc.Attach(StrDupW(pszArgs));
2214 wszParameters = wszParamAlloc;
2215 }
2216 }
2217 /* We have to test sei instead of sei_tmp because sei_tmp had its
2218 * input fMask modified above in SHELL_translate_idlist.
2219 * This code is needed to handle the case where we only have an
2220 * lpIDList with multiple CLSID/PIDL's (not 'My Computer' only) */
2221 else if ((sei->fMask & SEE_MASK_IDLIST) == SEE_MASK_IDLIST)
2222 {
2223 WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH];
2224 LPWSTR space, s;
2225
2226 LPWSTR beg = wszApplicationName;
2227 for(s = beg; (space = const_cast<LPWSTR>(strchrW(s, L' '))); s = space + 1)
2228 {
2229 int idx = space - sei_tmp.lpFile;
2230 memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
2231 buffer[idx] = '\0';
2232
2233 if (SearchPathW(*sei_tmp.lpDirectory ? sei_tmp.lpDirectory : NULL,
2234 buffer, L".exe", _countof(xlpFile), xlpFile, NULL))
2235 {
2236 /* separate out command from parameter string */
2237 LPCWSTR p = space + 1;
2238
2239 while(isspaceW(*p))
2240 ++p;
2241
2242 strcpyW(wszParameters, p);
2243 *space = L'\0';
2244
2245 break;
2246 }
2247 }
2248 }
2249 }
2250
2251 WCHAR wcmdBuffer[1024];
2252 LPWSTR wcmd = wcmdBuffer;
2253 DWORD wcmdLen = _countof(wcmdBuffer);
2255
2256 /* Only execute if it has an executable extension */
2257 if (PathIsExeW(lpFile))
2258 {
2259 len = lstrlenW(wszApplicationName) + 3;
2260 if (sei_tmp.lpParameters[0])
2261 len += 1 + lstrlenW(wszParameters);
2262 if (len > wcmdLen)
2263 {
2264 wcmdAlloc.Allocate(len);
2265 wcmd = wcmdAlloc;
2266 wcmdLen = len;
2267 }
2268 swprintf(wcmd, L"\"%s\"", (LPWSTR)wszApplicationName);
2269 if (sei_tmp.lpParameters[0])
2270 {
2271 strcatW(wcmd, L" ");
2272 strcatW(wcmd, wszParameters);
2273 }
2274
2275 retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
2276 if (retval > 32)
2277 return TRUE;
2278 }
2279
2280 /* Else, try to find the executable */
2281 WCHAR wszKeyname[256];
2283 wcmd[0] = UNICODE_NULL;
2284 retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, wcmdLen, wszKeyname, &env, (LPITEMIDLIST)sei_tmp.lpIDList, sei_tmp.lpParameters);
2285 if (retval > 32) /* Found */
2286 {
2287 retval = SHELL_quote_and_execute(wcmd, wszParameters, wszKeyname,
2288 wszApplicationName, env, &sei_tmp,
2289 sei, execfunc);
2290 }
2291 else if (PathIsDirectoryW(lpFile))
2292 {
2293 WCHAR wExec[MAX_PATH];
2295 if (lpQuotedFile.Allocate(strlenW(lpFile) + 3))
2296 {
2297 retval = SHELL_FindExecutable(sei_tmp.lpDirectory, L"explorer",
2298 L"open", wExec, MAX_PATH,
2299 NULL, &env, NULL, NULL);
2300 if (retval > 32)
2301 {
2302 swprintf(lpQuotedFile, L"\"%s\"", lpFile);
2303 retval = SHELL_quote_and_execute(wExec, lpQuotedFile,
2304 wszKeyname,
2305 wszApplicationName, env,
2306 &sei_tmp, sei, execfunc);
2307 }
2308 }
2309 else
2310 retval = 0; /* Out of memory */
2311 }
2312 else if (PathIsURLW(lpFile)) /* File not found, check for URL */
2313 {
2314 retval = SHELL_execute_url(lpFile, wcmd, &sei_tmp, sei, execfunc );
2315 }
2316 /* Check if file specified is in the form www.??????.*** */
2317 else if (!strncmpiW(lpFile, L"www", 3))
2318 {
2319 /* if so, prefix lpFile with http:// and call ShellExecute */
2320 WCHAR lpstrTmpFile[256];
2321 strcpyW(lpstrTmpFile, L"http://");
2322 strcatW(lpstrTmpFile, lpFile); // FIXME: Possible buffer overflow
2323 // FIXME: This will not correctly return the hProcess to the caller
2324 retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
2325 }
2326
2327 TRACE("retval %lu\n", retval);
2328
2329 if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
2330 {
2331 if (retval == SE_ERR_NOASSOC && !(sei->fMask & SEE_MASK_CLASSALL))
2332 retval = InvokeOpenWith(sei_tmp.hwnd, *sei);
2333 if (retval <= 32)
2334 do_error_dialog(retval, sei_tmp.hwnd, lpFile);
2335 }
2336
2337 sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
2338
2339 return retval > 32;
2340}
2341
2342/*************************************************************************
2343 * ShellExecuteA [SHELL32.290]
2344 */
2346 LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
2347{
2349
2350 TRACE("%p,%s,%s,%s,%s,%d\n",
2351 hWnd, debugstr_a(lpVerb), debugstr_a(lpFile),
2352 debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
2353
2354 sei.cbSize = sizeof(sei);
2356 sei.hwnd = hWnd;
2357 sei.lpVerb = lpVerb;
2358 sei.lpFile = lpFile;
2359 sei.lpParameters = lpParameters;
2361 sei.nShow = iShowCmd;
2362 sei.lpIDList = 0;
2363 sei.lpClass = 0;
2364 sei.hkeyClass = 0;
2365 sei.dwHotKey = 0;
2366 sei.hProcess = 0;
2367
2369 sei.fMask |= SEE_MASK_NOASYNC;
2370 ShellExecuteExA(&sei);
2371 return sei.hInstApp;
2372}
2373
2374static DWORD
2376{
2377 // FIXME
2378 if (SHELL_execute(sei, SHELL_ExecuteW))
2379 return ERROR_SUCCESS;
2381#if DBG
2382 if (!err)
2383 DbgPrint("FIXME: Failed with error 0 on '%ls'\n", sei->lpFile);
2384#endif
2385 return err ? err : ERROR_FILE_NOT_FOUND;
2386}
2387
2388static VOID
2390 _In_ const SHELLEXECUTEINFOW *ExecInfo,
2391 _In_opt_ LPCWSTR pszCaption,
2392 _In_ DWORD dwError)
2393{
2394 // FIXME: Show error message
2395}
2396
2397/*************************************************************************
2398 * ShellExecuteExA [SHELL32.292]
2399 */
2400BOOL
2401WINAPI
2404{
2405 SHELLEXECUTEINFOW seiW;
2406 BOOL ret;
2407 WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL, *wClass = NULL;
2408
2409 TRACE("%p\n", sei);
2410
2411 if (sei->cbSize != sizeof(SHELLEXECUTEINFOA))
2412 {
2415 return FALSE;
2416 }
2417
2418 memcpy(&seiW, sei, sizeof(SHELLEXECUTEINFOW));
2419
2420 seiW.cbSize = sizeof(SHELLEXECUTEINFOW);
2421
2422 if (sei->lpVerb)
2423 seiW.lpVerb = __SHCloneStrAtoW(&wVerb, sei->lpVerb);
2424
2425 if (sei->lpFile)
2426 seiW.lpFile = __SHCloneStrAtoW(&wFile, sei->lpFile);
2427
2428 if (sei->lpParameters)
2429 seiW.lpParameters = __SHCloneStrAtoW(&wParameters, sei->lpParameters);
2430
2431 if (sei->lpDirectory)
2432 seiW.lpDirectory = __SHCloneStrAtoW(&wDirectory, sei->lpDirectory);
2433
2434 if ((sei->fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME && sei->lpClass)
2435 seiW.lpClass = __SHCloneStrAtoW(&wClass, sei->lpClass);
2436 else
2437 seiW.lpClass = NULL;
2438
2439 ret = ShellExecuteExW(&seiW);
2440
2441 sei->hInstApp = seiW.hInstApp;
2442
2443 if (sei->fMask & SEE_MASK_NOCLOSEPROCESS)
2444 sei->hProcess = seiW.hProcess;
2445
2446 SHFree(wVerb);
2447 SHFree(wFile);
2448 SHFree(wParameters);
2449 SHFree(wDirectory);
2450 SHFree(wClass);
2451
2452 return ret;
2453}
2454
2455/*************************************************************************
2456 * ShellExecuteExW [SHELL32.293]
2457 */
2458BOOL
2459WINAPI
2462{
2463 HRESULT hrCoInit;
2464 DWORD dwError;
2465 ULONG fOldMask;
2466
2467 if (sei->cbSize != sizeof(SHELLEXECUTEINFOW))
2468 {
2471 return FALSE;
2472 }
2473
2474 hrCoInit = SHCoInitializeAnyApartment();
2475
2476 if (SHRegGetBoolUSValueW(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
2477 L"MaximizeApps", FALSE, FALSE))
2478 {
2479 switch (sei->nShow)
2480 {
2481 case SW_SHOW:
2482 case SW_SHOWDEFAULT:
2483 case SW_SHOWNORMAL:
2484 case SW_RESTORE:
2485 sei->nShow = SW_SHOWMAXIMIZED;
2486 break;
2487 default:
2488 break;
2489 }
2490 }
2491
2492 fOldMask = sei->fMask;
2493
2494 if (!(fOldMask & SEE_MASK_NOASYNC) && SHELL_InRunDllProcess())
2496
2497 dwError = ShellExecute_Normal(sei);
2498
2499 if (dwError && dwError != ERROR_DLL_NOT_FOUND && dwError != ERROR_CANCELLED)
2500 ShellExecute_ShowError(sei, NULL, dwError);
2501
2502 sei->fMask = fOldMask;
2503
2504 if (SUCCEEDED(hrCoInit))
2506
2507 if (dwError)
2508 SetLastError(dwError);
2509
2510 return dwError == ERROR_SUCCESS;
2511}
2512
2513/*************************************************************************
2514 * ShellExecuteW [SHELL32.294]
2515 */
2517 LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
2518{
2520
2521 TRACE("\n");
2522 sei.cbSize = sizeof(sei);
2524 sei.hwnd = hwnd;
2525 sei.lpVerb = lpVerb;
2526 sei.lpFile = lpFile;
2527 sei.lpParameters = lpParameters;
2529 sei.nShow = nShowCmd;
2530 sei.lpIDList = 0;
2531 sei.lpClass = 0;
2532 sei.hkeyClass = 0;
2533 sei.dwHotKey = 0;
2534 sei.hProcess = 0;
2535
2537 sei.fMask |= SEE_MASK_NOASYNC;
2538 ShellExecuteExW(&sei);
2539 return sei.hInstApp;
2540}
2541
2542/*************************************************************************
2543 * WOWShellExecute [SHELL32.@]
2544 *
2545 * FIXME: the callback function most likely doesn't work the same way on Windows.
2546 */
2548 LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd, void *callback)
2549{
2550 SHELLEXECUTEINFOW seiW;
2551 WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL;
2552 HANDLE hProcess = 0;
2553
2554 seiW.lpVerb = lpVerb ? __SHCloneStrAtoW(&wVerb, lpVerb) : NULL;
2555 seiW.lpFile = lpFile ? __SHCloneStrAtoW(&wFile, lpFile) : NULL;
2556 seiW.lpParameters = lpParameters ? __SHCloneStrAtoW(&wParameters, lpParameters) : NULL;
2557 seiW.lpDirectory = lpDirectory ? __SHCloneStrAtoW(&wDirectory, lpDirectory) : NULL;
2558
2559 seiW.cbSize = sizeof(seiW);
2560 seiW.fMask = 0;
2561 seiW.hwnd = hWnd;
2562 seiW.nShow = iShowCmd;
2563 seiW.lpIDList = 0;
2564 seiW.lpClass = 0;
2565 seiW.hkeyClass = 0;
2566 seiW.dwHotKey = 0;
2567 seiW.hProcess = hProcess;
2568
2570
2571 SHFree(wVerb);
2572 SHFree(wFile);
2573 SHFree(wParameters);
2574 SHFree(wDirectory);
2575 return seiW.hInstApp;
2576}
2577
2578/*************************************************************************
2579 * OpenAs_RunDLLW [SHELL32.@]
2580 */
2581EXTERN_C void WINAPI
2583{
2585 TRACE("%p, %p, %s, %d\n", hwnd, hinst, debugstr_w(cmdline), cmdshow);
2587}
2588
2589/*************************************************************************
2590 * OpenAs_RunDLLA [SHELL32.@]
2591 */
2592EXTERN_C void WINAPI
2594{
2595 LPWSTR pszCmdLineW = NULL;
2596 TRACE("%p, %p, %s, %d\n", hwnd, hinst, debugstr_a(cmdline), cmdshow);
2597
2598 if (cmdline)
2599 __SHCloneStrAtoW(&pszCmdLineW, cmdline);
2600 OpenAs_RunDLLW(hwnd, hinst, pszCmdLineW, cmdshow);
2601 SHFree(pszCmdLineW);
2602}
2603
2604/*************************************************************************/
2605
2606static LPCWSTR
2607SplitParams(LPCWSTR psz, LPWSTR pszArg0, size_t cchArg0)
2608{
2609 LPCWSTR pch;
2610 size_t ich = 0;
2611 if (*psz == L'"')
2612 {
2613 // 1st argument is quoted. the string in quotes is quoted 1st argument.
2614 // [pch] --> [pszArg0+ich]
2615 for (pch = psz + 1; *pch && ich + 1 < cchArg0; ++ich, ++pch)
2616 {
2617 if (*pch == L'"' && pch[1] == L'"')
2618 {
2619 // doubled double quotations found!
2620 pszArg0[ich] = L'"';
2621 }
2622 else if (*pch == L'"')
2623 {
2624 // single double quotation found!
2625 ++pch;
2626 break;
2627 }
2628 else
2629 {
2630 // otherwise
2631 pszArg0[ich] = *pch;
2632 }
2633 }
2634 }
2635 else
2636 {
2637 // 1st argument is unquoted. non-space sequence is 1st argument.
2638 // [pch] --> [pszArg0+ich]
2639 for (pch = psz; *pch && !iswspace(*pch) && ich + 1 < cchArg0; ++ich, ++pch)
2640 {
2641 pszArg0[ich] = *pch;
2642 }
2643 }
2644 pszArg0[ich] = 0;
2645
2646 // skip space
2647 while (iswspace(*pch))
2648 ++pch;
2649
2650 return pch;
2651}
2652
2654 HWND hwnd,
2655 LPCWSTR pwszCommand,
2656 LPCWSTR pwszStartDir,
2657 int nShow,
2658 LPVOID pUnused,
2659 DWORD dwSeclFlags)
2660{
2663 LPCWSTR pszVerb = NULL;
2664 WCHAR szFile[MAX_PATH], szFile2[MAX_PATH];
2665 HRESULT hr;
2666 LPCWSTR pchParams;
2667 LPWSTR lpCommand = NULL;
2668
2669 if (pwszCommand == NULL)
2671 1, (ULONG_PTR*)pwszCommand);
2672
2673 __SHCloneStrW(&lpCommand, pwszCommand);
2674 StrTrimW(lpCommand, L" \t");
2675
2676 if (dwSeclFlags & SECL_NO_UI)
2678 if (dwSeclFlags & SECL_LOG_USAGE)
2680 if (dwSeclFlags & SECL_USE_IDLIST)
2682
2683 if (dwSeclFlags & SECL_RUNAS)
2684 {
2685 dwSize = 0;
2686 hr = AssocQueryStringW(ASSOCF_NONE, ASSOCSTR_COMMAND, lpCommand, L"runas", NULL, &dwSize);
2687 if (SUCCEEDED(hr) && dwSize != 0)
2688 {
2689 pszVerb = L"runas";
2690 }
2691 }
2692
2693 if (PathIsURLW(lpCommand) || UrlIsW(lpCommand, URLIS_APPLIABLE))
2694 {
2695 StringCchCopyW(szFile, _countof(szFile), lpCommand);
2696 pchParams = NULL;
2697 }
2698 else
2699 {
2700 PCWSTR apPathList[2];
2701
2702 pchParams = SplitParams(lpCommand, szFile, _countof(szFile));
2703 if (szFile[0] != UNICODE_NULL && szFile[1] == L':' &&
2704 szFile[2] == UNICODE_NULL)
2705 {
2706 PathAddBackslashW(szFile);
2707 }
2708
2709 WCHAR szCurDir[MAX_PATH];
2710 GetCurrentDirectoryW(_countof(szCurDir), szCurDir);
2711 if (pwszStartDir)
2712 {
2713 SetCurrentDirectoryW(pwszStartDir);
2714 }
2715
2716 if ((PathIsRelativeW(szFile) &&
2717 GetFullPathNameW(szFile, _countof(szFile2), szFile2, NULL) &&
2718 PathFileExistsW(szFile2)) ||
2719 SearchPathW(NULL, szFile, NULL, _countof(szFile2), szFile2, NULL))
2720 {
2721 StringCchCopyW(szFile, _countof(szFile), szFile2);
2722 }
2723
2724 apPathList[0] = pwszStartDir;
2725 apPathList[1] = NULL;
2726 PathFindOnPathExW(szFile, apPathList, WHICH_DEFAULT);
2727
2728 if (!(dwSeclFlags & SECL_ALLOW_NONEXE))
2729 {
2730 if (!GetBinaryTypeW(szFile, &dwType))
2731 {
2732 SHFree(lpCommand);
2733
2734 if (!(dwSeclFlags & SECL_NO_UI))
2735 {
2736 WCHAR szText[128 + MAX_PATH], szFormat[128];
2738 StringCchPrintfW(szText, _countof(szText), szFormat, szFile);
2739 MessageBoxW(hwnd, szText, NULL, MB_ICONERROR);
2740 }
2741 return CO_E_APPNOTFOUND;
2742 }
2743 }
2744 else
2745 {
2747 {
2748 SHFree(lpCommand);
2749
2750 if (!(dwSeclFlags & SECL_NO_UI))
2751 {
2752 WCHAR szText[128 + MAX_PATH], szFormat[128];
2754 StringCchPrintfW(szText, _countof(szText), szFormat, szFile);
2755 MessageBoxW(hwnd, szText, NULL, MB_ICONERROR);
2756 }
2758 }
2759 }
2760 }
2761
2762 ZeroMemory(&info, sizeof(info));
2763 info.cbSize = sizeof(info);
2764 info.fMask = dwFlags;
2765 info.hwnd = hwnd;
2766 info.lpVerb = pszVerb;
2767 info.lpFile = szFile;
2768 info.lpParameters = (pchParams && *pchParams) ? pchParams : NULL;
2769 info.lpDirectory = pwszStartDir;
2770 info.nShow = nShow;
2772 SHFree(lpCommand);
2773 return HRESULT_FROM_WIN32(error);
2774}
2775
2776/*************************************************************************
2777 * RealShellExecuteExA (SHELL32.266)
2778 */
2783 _In_opt_ LPCSTR lpOperation,
2784 _In_opt_ LPCSTR lpFile,
2785 _In_opt_ LPCSTR lpParameters,
2787 _In_opt_ LPSTR lpReturn,
2790 _In_ INT nCmdShow,
2791 _Out_opt_ PHANDLE lphProcess,
2793{
2794 SHELLEXECUTEINFOA ExecInfo;
2795
2796 TRACE("(%p, %s, %s, %s, %s, %p, %s, %p, %u, %p, %lu)\n",
2797 hwnd, debugstr_a(lpOperation), debugstr_a(lpFile), debugstr_a(lpParameters),
2799 lpReserved, nCmdShow, lphProcess, dwFlags);
2800
2801 ZeroMemory(&ExecInfo, sizeof(ExecInfo));
2802 ExecInfo.cbSize = sizeof(ExecInfo);
2804 ExecInfo.hwnd = hwnd;
2805 ExecInfo.lpVerb = lpOperation;
2806 ExecInfo.lpFile = lpFile;
2807 ExecInfo.lpParameters = lpParameters;
2808 ExecInfo.lpDirectory = lpDirectory;
2809 ExecInfo.nShow = (WORD)nCmdShow;
2810
2811 if (lpReserved)
2812 {
2813 ExecInfo.fMask |= SEE_MASK_USE_RESERVED;
2814 ExecInfo.hInstApp = (HINSTANCE)lpReserved;
2815 }
2816
2817 if (lpTitle)
2818 {
2819 ExecInfo.fMask |= SEE_MASK_HASTITLE;
2820 ExecInfo.lpClass = lpTitle;
2821 }
2822
2823 if (dwFlags & 1)
2824 ExecInfo.fMask |= SEE_MASK_FLAG_SEPVDM;
2825
2826 if (dwFlags & 2)
2827 ExecInfo.fMask |= SEE_MASK_NO_CONSOLE;
2828
2829 if (lphProcess == NULL)
2830 {
2831 ShellExecuteExA(&ExecInfo);
2832 }
2833 else
2834 {
2835 ExecInfo.fMask |= SEE_MASK_NOCLOSEPROCESS;
2836 ShellExecuteExA(&ExecInfo);
2837 *lphProcess = ExecInfo.hProcess;
2838 }
2839
2840 return ExecInfo.hInstApp;
2841}
2842
2843/*************************************************************************
2844 * RealShellExecuteExW (SHELL32.267)
2845 */
2850 _In_opt_ LPCWSTR lpOperation,
2851 _In_opt_ LPCWSTR lpFile,
2852 _In_opt_ LPCWSTR lpParameters,
2854 _In_opt_ LPWSTR lpReturn,
2857 _In_ INT nCmdShow,
2858 _Out_opt_ PHANDLE lphProcess,
2860{
2861 SHELLEXECUTEINFOW ExecInfo;
2862
2863 TRACE("(%p, %s, %s, %s, %s, %p, %s, %p, %u, %p, %lu)\n",
2864 hwnd, debugstr_w(lpOperation), debugstr_w(lpFile), debugstr_w(lpParameters),
2866 lpReserved, nCmdShow, lphProcess, dwFlags);
2867
2868 ZeroMemory(&ExecInfo, sizeof(ExecInfo));
2869 ExecInfo.cbSize = sizeof(ExecInfo);
2871 ExecInfo.hwnd = hwnd;
2872 ExecInfo.lpVerb = lpOperation;
2873 ExecInfo.lpFile = lpFile;
2874 ExecInfo.lpParameters = lpParameters;
2875 ExecInfo.lpDirectory = lpDirectory;
2876 ExecInfo.nShow = (WORD)nCmdShow;
2877
2878 if (lpReserved)
2879 {
2880 ExecInfo.fMask |= SEE_MASK_USE_RESERVED;
2881 ExecInfo.hInstApp = (HINSTANCE)lpReserved;
2882 }
2883
2884 if (lpTitle)
2885 {
2886 ExecInfo.fMask |= SEE_MASK_HASTITLE;
2887 ExecInfo.lpClass = lpTitle;
2888 }
2889
2890 if (dwFlags & 1)
2891 ExecInfo.fMask |= SEE_MASK_FLAG_SEPVDM;
2892
2893 if (dwFlags & 2)
2894 ExecInfo.fMask |= SEE_MASK_NO_CONSOLE;
2895
2896 if (lphProcess == NULL)
2897 {
2898 ShellExecuteExW(&ExecInfo);
2899 }
2900 else
2901 {
2902 ExecInfo.fMask |= SEE_MASK_NOCLOSEPROCESS;
2903 ShellExecuteExW(&ExecInfo);
2904 *lphProcess = ExecInfo.hProcess;
2905 }
2906
2907 return ExecInfo.hInstApp;
2908}
2909
2910/*************************************************************************
2911 * RealShellExecuteA (SHELL32.265)
2912 */
2917 _In_opt_ LPCSTR lpOperation,
2918 _In_opt_ LPCSTR lpFile,
2919 _In_opt_ LPCSTR lpParameters,
2921 _In_opt_ LPSTR lpReturn,
2924 _In_ INT nCmdShow,
2925 _Out_opt_ PHANDLE lphProcess)
2926{
2928 lpOperation,
2929 lpFile,
2930 lpParameters,
2932 lpReturn,
2933 lpTitle,
2934 lpReserved,
2935 nCmdShow,
2936 lphProcess,
2937 0);
2938}
2939
2940/*************************************************************************
2941 * RealShellExecuteW (SHELL32.268)
2942 */
2947 _In_opt_ LPCWSTR lpOperation,
2948 _In_opt_ LPCWSTR lpFile,
2949 _In_opt_ LPCWSTR lpParameters,
2951 _In_opt_ LPWSTR lpReturn,
2954 _In_ INT nCmdShow,
2955 _Out_opt_ PHANDLE lphProcess)
2956{
2958 lpOperation,
2959 lpFile,
2960 lpParameters,
2962 lpReturn,
2963 lpTitle,
2964 lpReserved,
2965 nCmdShow,
2966 lphProcess,
2967 0);
2968}
2969
2970/*************************************************************************
2971 * PathProcessCommandW [Internal]
2972 *
2973 * @see https://learn.microsoft.com/en-us/windows/win32/api/shlobj/nf-shlobj-pathprocesscommand
2974 * @see ./wine/shellpath.c
2975 */
2978 _In_ PCWSTR pszSrc,
2979 _Out_writes_opt_(dwBuffSize) PWSTR pszDest,
2982{
2983 TRACE("%s, %p, %d, 0x%X\n", wine_dbgstr_w(pszSrc), pszDest, cchDest, dwFlags);
2984
2985 if (!pszSrc)
2986 return -1;
2987
2989 PCWSTR pchArg = NULL;
2990
2991 if (*pszSrc == L'"') // Quoted?
2992 {
2993 ++pszSrc;
2994
2995 PCWSTR pch = wcschr(pszSrc, L'"');
2996 if (pch)
2997 {
2998 szPath.SetString(pszSrc, pch - pszSrc);
2999 pchArg = pch + 1;
3000 }
3001 else
3002 {
3003 szPath = pszSrc;
3004 }
3005
3007 {
3009 szPath.ReleaseBuffer();
3010 if (!ret)
3011 return -1;
3012 }
3013 }
3014 else // Not quoted?
3015 {
3016 BOOL resolved = FALSE;
3017 BOOL resolveRelative = PathIsRelativeW(pszSrc) || (dwFlags & PPCF_FORCEQUALIFY);
3018 INT cchPath = 0;
3019
3020 for (INT ich = 0; ; ++ich)
3021 {
3022 szPath += pszSrc[ich];
3023
3024 if (pszSrc[ich] && pszSrc[ich] != L' ')
3025 continue;
3026
3027 szPath = szPath.Left(ich);
3028
3029 if (resolveRelative &&
3031 {
3032 szPath.ReleaseBuffer();
3033 szPath += pszSrc[ich];
3034 }
3035 else
3036 {
3037 szPath.ReleaseBuffer();
3038
3040 if (attrs != INVALID_FILE_ATTRIBUTES &&
3042 {
3043 resolved = TRUE;
3044 pchArg = pszSrc + ich;
3045
3047 break;
3048
3049 cchPath = ich;
3050 break;
3051 }
3052 else if (!resolveRelative)
3053 {
3054 szPath += pszSrc[ich];
3055 }
3056 }
3057
3058 if (!szPath[ich])
3059 {
3060 szPath.ReleaseBuffer(); // Remove excessive '\0'
3061 break;
3062 }
3063 }
3064
3065 if (!resolved)
3066 return -1;
3067
3068 if (cchPath && (dwFlags & PPCF_LONGESTPOSSIBLE))
3069 {
3070 szPath = szPath.Left(cchPath);
3071 pchArg = pszSrc + cchPath;
3072 }
3073 }
3074
3075 BOOL needsQuoting = (dwFlags & PPCF_ADDQUOTES) && wcschr(szPath, L' ');
3076 CStringW result = needsQuoting ? (L"\"" + szPath + L"\"") : szPath;
3077
3078 if (pchArg && (dwFlags & PPCF_ADDARGUMENTS))
3079 result += pchArg;
3080
3081 LONG requiredSize = result.GetLength() + 1;
3082 if (!pszDest)
3083 return requiredSize;
3084
3085 if (requiredSize > cchDest || StringCchCopyW(pszDest, cchDest, result) != S_OK)
3086 return -1;
3087
3088 return requiredSize;
3089}
3090
3091// The common helper of ShellExec_RunDLLA and ShellExec_RunDLLW
3092static VOID
3096 _In_ PCWSTR pszCmdLine,
3097 _In_ INT nCmdShow)
3098{
3099 TRACE("(%p, %p, %s, 0x%X)\n", hwnd, hInstance, wine_dbgstr_w(pszCmdLine), nCmdShow);
3100
3101 if (!pszCmdLine || !*pszCmdLine)
3102 return;
3103
3104 // '?' enables us to specify the additional mask value
3105 ULONG fNewMask = SEE_MASK_NOASYNC;
3106 if (*pszCmdLine == L'?') // 1st question
3107 {
3108 INT MaskValue;
3109 if (StrToIntExW(pszCmdLine + 1, STIF_SUPPORT_HEX, &MaskValue))
3110 fNewMask |= MaskValue;
3111
3112 PCWSTR pch2ndQuestion = StrChrW(pszCmdLine + 1, L'?'); // 2nd question
3113 if (pch2ndQuestion)
3114 pszCmdLine = pch2ndQuestion + 1;
3115 }
3116
3117 WCHAR szPath[2 * MAX_PATH];
3119 if (PathProcessCommandW(pszCmdLine, szPath, _countof(szPath), dwFlags) == -1)
3120 StrCpyNW(szPath, pszCmdLine, _countof(szPath));
3121
3122 // Split arguments from the path
3124 if (*Args)
3125 *(Args - 1) = UNICODE_NULL;
3126
3128
3129 // Execute
3130 SHELLEXECUTEINFOW execInfo = { sizeof(execInfo) };
3131 execInfo.fMask = fNewMask;
3132 execInfo.hwnd = hwnd;
3133 execInfo.lpFile = szPath;
3134 execInfo.lpParameters = Args;
3135 execInfo.nShow = nCmdShow;
3136 if (!ShellExecuteExW(&execInfo))
3137 {
3138 DWORD dwError = GetLastError();
3139 if (SHELL_InRunDllProcess()) // Is it a RUNDLL process?
3140 ExitProcess(dwError); // Terminate it now
3141 }
3142}
3143
3144/*************************************************************************
3145 * ShellExec_RunDLLA [SHELL32.358]
3146 *
3147 * @see https://www.hexacorn.com/blog/2024/11/30/1-little-known-secret-of-shellexec_rundll/
3148 */
3154 _In_ PCSTR pszCmdLine,
3155 _In_ INT nCmdShow)
3156{
3157 CStringW strCmdLine = pszCmdLine; // Keep
3158 ShellExec_RunDLL_Helper(hwnd, hInstance, strCmdLine, nCmdShow);
3159}
3160
3161/*************************************************************************
3162 * ShellExec_RunDLLW [SHELL32.359]
3163 *
3164 * @see https://www.hexacorn.com/blog/2024/11/30/1-little-known-secret-of-shellexec_rundll/
3165 */
3171 _In_ PCWSTR pszCmdLine,
3172 _In_ INT nCmdShow)
3173{
3174 ShellExec_RunDLL_Helper(hwnd, hInstance, pszCmdLine, nCmdShow);
3175}
BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
Definition: CBandSite.h:24
HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf)
HRESULT WINAPI SHOpenWithDialog(HWND hwndParent, const OPENASINFO *poainfo)
HRESULT SH32_InvokeOpenWith(_In_ PCWSTR pszPath, _In_ LPCMINVOKECOMMANDINFO pici, _Out_ HANDLE *phProcess)
#define PRF_VERIFYEXISTS
Definition: PathResolve.cpp:38
#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
char ** Args
Definition: acdebug.h:353
char * va_list
Definition: acmsvcex.h:78
static int used
Definition: adh-main.c:39
static void startup(void)
unsigned int dir
Definition: maze.c:112
#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:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define EXTERN_C
Definition: basetyps.h:12
#define RegCloseKey(hKey)
Definition: registry.h:49
r l[0]
Definition: byte_order.h:168
HINSTANCE hInstance
Definition: charmap.c:19
Definition: bufpool.h:45
T * Detach()
Definition: atlalloc.h:168
bool Allocate(_In_ size_t nElements=1)
Definition: atlalloc.h:143
void Attach(T *lp)
Definition: atlalloc.h:162
wcscat
wcscpy
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_OUTOFMEMORY
Definition: deptool.c:13
#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 RegEnumKeyW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, DWORD cbName)
Definition: reg.c:2393
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:464
INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
Definition: string.c:307
LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:380
INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
Definition: string.c:500
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#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 MAX_PATH
Definition: compat.h:34
#define CALLBACK
Definition: compat.h:35
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static const WCHAR *const ext[]
Definition: module.c:53
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
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
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
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2352
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:4598
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
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
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4262
void WINAPI PathRemoveBlanksW(WCHAR *path)
Definition: path.c:1853
void WINAPI PathUnquoteSpacesW(WCHAR *path)
Definition: path.c:1949
int WINAPI PathGetDriveNumberW(const WCHAR *path)
Definition: path.c:1753
HRESULT WINAPI PathCreateFromUrlW(const WCHAR *url, WCHAR *path, DWORD *pcchPath, DWORD dwReserved)
Definition: path.c:3016
WCHAR *WINAPI PathFindFileNameW(const WCHAR *path)
Definition: path.c:1644
BOOL WINAPI UrlIsW(const WCHAR *url, URLIS Urlis)
Definition: path.c:4755
LPWSTR WINAPI PathFindExtensionW(const WCHAR *path)
Definition: path.c:1217
BOOL WINAPI PathIsRelativeW(const WCHAR *path)
Definition: path.c:973
BOOL WINAPI PathStripToRootW(WCHAR *path)
Definition: path.c:1138
BOOL WINAPI PathIsURLW(const WCHAR *path)
Definition: path.c:3181
WCHAR *WINAPI PathGetArgsW(const WCHAR *path)
Definition: path.c:1683
BOOL WINAPI PathFileExistsW(const WCHAR *path)
Definition: path.c:2550
LPWSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsW(void)
Definition: process.c:1538
BOOL WINAPI SHRegGetBoolUSValueW(const WCHAR *subkey, const WCHAR *value, BOOL ignore_hkcu, BOOL default_value)
Definition: registry.c:4139
BOOL WINAPI StrToIntExW(const WCHAR *str, DWORD flags, INT *ret)
Definition: string.c:972
INT WINAPI DECLSPEC_HOTPATCH LoadStringW(HINSTANCE instance, UINT resource_id, LPWSTR buffer, INT buflen)
Definition: string.c:1220
BOOL WINAPI StrTrimW(WCHAR *str, const WCHAR *trim)
Definition: string.c:796
LPWSTR WINAPI CharLowerW(WCHAR *str)
Definition: string.c:1092
WCHAR *WINAPI StrDupW(const WCHAR *str)
Definition: string.c:313
WCHAR *WINAPI StrCpyNW(WCHAR *dst, const WCHAR *src, int count)
Definition: string.c:462
GUID guid
Definition: version.c:147
DWORD WINAPI GetVersion(void)
Definition: version.c:1458
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 DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
#define VERBKEY_CCHMAX
Definition: precomp.h:130
HRESULT SHGetNameAndFlagsW(_In_ LPCITEMIDLIST pidl, _In_ DWORD dwFlags, _Out_opt_ LPWSTR pszText, _In_ UINT cchBuf, _Inout_opt_ DWORD *pdwAttributes)
Definition: utils.cpp:480
EXTERN_C HRESULT SHELL_GetUIObjectOfAbsoluteItem(_In_opt_ HWND hWnd, _In_ PCIDLIST_ABSOLUTE pidl, _In_ REFIID riid, _Out_ void **ppvObj)
Definition: utils.cpp:380
HRESULT SHCoInitializeAnyApartment(VOID)
Definition: utils.cpp:471
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:1032
HRESULT WINAPI AssocQueryStringW(ASSOCF cfFlags, ASSOCSTR str, LPCWSTR pszAssoc, LPCWSTR pszExtra, LPWSTR pszOut, DWORD *pcchOut)
Definition: assoc.c:441
HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
Definition: ordinal.c:169
DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
Definition: ordinal.c:4565
PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
Definition: ordinal.c:259
BOOL WINAPI SHUnlockShared(LPVOID lpView)
Definition: ordinal.c:295
void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
Definition: path.c:779
BOOL WINAPI PathFindOnPathW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs)
Definition: path.c:1409
BOOL WINAPI PathFindOnPathExW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs, DWORD dwWhich)
Definition: path.c:1357
BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
Definition: path.c:1729
#define FAILED_UNEXPECTEDLY
Definition: utils.cpp:30
#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
FxAutoRegKey hKey
size_t total
GLuint start
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
GLdouble n
Definition: glext.h:7729
GLuint res
Definition: glext.h:9613
GLsizei const GLchar *const * strings
Definition: glext.h:7622
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint64EXT * result
Definition: glext.h:11304
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
#define DbgPrint
Definition: hal.h:12
#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 wine_dbgstr_w
Definition: kernel32.h:34
#define REG_SZ
Definition: layer.c:22
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:71
#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
LPCWSTR szPath
Definition: env.c:37
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
static HMENU hmenu
Definition: win.c:66
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
HMONITOR WINAPI MonitorFromWindow(HWND, DWORD)
unsigned int UINT
Definition: ndis.h:50
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Out_writes_opt_(s)
Definition: no_sal2.h:226
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#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:331
#define UNICODE_NULL
#define ANSI_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
#define STARTF_USEHOTKEY
Definition: pch.h:41
long LONG
Definition: pedump.c:60
HRESULT WINAPI SHParseDisplayName(LPCWSTR pszName, IBindCtx *pbc, LPITEMIDLIST *ppidl, SFGAOF sfgaoIn, SFGAOF *psfgaoOut)
Definition: pidl.c:1541
HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
Definition: pidl.c:1497
LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path)
Definition: pidl.c:1101
static const WCHAR szName[]
Definition: powrprof.c:45
static const char topic[]
Definition: propsys.c:45
#define strncmpiW(s1, s2, n)
Definition: unicode.h:46
#define strstrW(d, s)
Definition: unicode.h:38
#define strchrW(s, c)
Definition: unicode.h:40
#define strlenW(s)
Definition: unicode.h:34
#define strrchrW(s, c)
Definition: unicode.h:41
#define strcatW(d, s)
Definition: unicode.h:36
#define isspaceW(n)
Definition: unicode.h:58
#define strcpyW(d, s)
Definition: unicode.h:35
#define err(...)
WCHAR classname[128]
Definition: startup.c:15
const WCHAR * str
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_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 DECLSPEC_HOTPATCH
Definition: config.h:9
#define memset(x, y, z)
Definition: compat.h:39
BOOL HCR_GetDefaultVerbW(HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len)
Definition: classes.c:152
BOOL HCR_GetExecuteCommandW(HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len)
Definition: classes.c:220
HRESULT HCR_GetProgIdKeyOfExtension(PCWSTR szExtension, PHKEY phKey, BOOL AllowFallback)
Definition: classes.c:55
static __inline void __SHCloneStrWtoA(char **target, const WCHAR *source)
Definition: shell32_main.h:172
static __inline LPWSTR __SHCloneStrAtoW(WCHAR **target, const char *source)
Definition: shell32_main.h:185
static __inline void __SHCloneStrW(WCHAR **target, const WCHAR *source)
Definition: shell32_main.h:179
#define SEE_MASK_FLAG_LOG_USAGE
Definition: shellapi.h:55
#define SEE_MASK_DOENVSUBST
Definition: shellapi.h:37
#define SEE_MASK_CLASSKEY
Definition: shellapi.h:26
#define SEE_MASK_HOTKEY
Definition: shellapi.h:32
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:33
struct _SHELLEXECUTEINFOW SHELLEXECUTEINFOW
#define SEE_MASK_HMONITOR
Definition: shellapi.h:45
#define SEE_MASK_CLASSNAME
Definition: shellapi.h:25
#define SEE_MASK_ASYNCOK
Definition: shellapi.h:43
#define SEE_MASK_IDLIST
Definition: shellapi.h:27
#define SEE_MASK_NOASYNC
Definition: shellapi.h:35
#define SE_ERR_ACCESSDENIED
Definition: shellapi.h:127
#define SEE_MASK_WAITFORINPUTIDLE
Definition: shellapi.h:52
#define SEE_MASK_FLAG_DDEWAIT
Definition: shellapi.h:36
#define SEE_MASK_CONNECTNETDRV
Definition: shellapi.h:34
_In_opt_ LPCSTR lpDirectory
Definition: shellapi.h:496
#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:38
#define SE_ERR_NOASSOC
Definition: shellapi.h:135
#define SEE_MASK_NO_CONSOLE
Definition: shellapi.h:41
#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:1672
static HRESULT ShellExecute_ContextMenuVerb(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1561
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExA(LPSHELLEXECUTEINFOA sei)
Definition: shlexec.cpp:2403
static UINT_PTR InvokeOpenWith(HWND hWndOwner, SHELLEXECUTEINFOW &sei)
Definition: shlexec.cpp:50
EXTERN_C VOID WINAPI ShellExec_RunDLLW(_In_opt_ HWND hwnd, _In_opt_ HINSTANCE hInstance, _In_ PCWSTR pszCmdLine, _In_ INT nCmdShow)
Definition: shlexec.cpp:3168
HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpResult)
Definition: shlexec.cpp:1323
static HRESULT shellex_load_object_and_run(HKEY hkey, LPCGUID guid, LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1488
static void do_error_dialog(UINT_PTR retval, HWND hwnd, PCWSTR filename)
Definition: shlexec.cpp:1909
static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
Definition: shlexec.cpp:63
static BOOL SHELL_InvokePidl(_In_ LPSHELLEXECUTEINFOW sei, _In_ LPCITEMIDLIST pidl)
Definition: shlexec.cpp:1787
EXTERN_C void WINAPI OpenAs_RunDLLA(HWND hwnd, HINSTANCE hinst, LPCSTR cmdline, int cmdshow)
Definition: shlexec.cpp:2593
static LPCWSTR SplitParams(LPCWSTR psz, LPWSTR pszArg0, size_t cchArg0)
Definition: shlexec.cpp:2607
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:2848
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:1221
EXTERN_C void WINAPI OpenAs_RunDLLW(HWND hwnd, HINSTANCE hinst, LPCWSTR cmdline, int cmdshow)
Definition: shlexec.cpp:2582
static LONG ShellExecute_FromContextMenuHandlers(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1627
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:776
static DWORD ShellExecute_Normal(_Inout_ LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2375
EXTERN_C VOID WINAPI ShellExec_RunDLLA(_In_opt_ HWND hwnd, _In_opt_ HINSTANCE hInstance, _In_ PCSTR pszCmdLine, _In_ INT nCmdShow)
Definition: shlexec.cpp:3151
EXTERN_C HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpVerb, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd, void *callback)
Definition: shlexec.cpp:2547
static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
Definition: shlexec.cpp:1951
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:994
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:212
#define SEE_MASK_CLASSALL
Definition: shlexec.cpp:31
static WCHAR * expand_environment(const WCHAR *str)
Definition: shlexec.cpp:1930
HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
Definition: shlexec.cpp:1280
static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
Definition: shlexec.cpp:1875
EXTERN_C LONG PathProcessCommandW(_In_ PCWSTR pszSrc, _Out_writes_opt_(dwBuffSize) PWSTR pszDest, _In_ INT cchDest, _In_ DWORD dwFlags)
Definition: shlexec.cpp:2977
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:1012
static VOID ShellExecute_ShowError(_In_ const SHELLEXECUTEINFOW *ExecInfo, _In_opt_ LPCWSTR pszCaption, _In_ DWORD dwError)
Definition: shlexec.cpp:2389
EXTERN_C BOOL PathIsExeW(LPCWSTR lpszPath)
Definition: shellpath.c:539
static HRESULT shellex_run_context_menu_default(IShellExtInit *obj, LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1419
HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpVerb, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
Definition: shlexec.cpp:2516
static UINT SHELL_FindExecutableByVerb(LPCWSTR lpVerb, LPWSTR key, LPWSTR classname, LPWSTR command, LONG commandlen)
Definition: shlexec.cpp:708
static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
Definition: shlexec.cpp:486
static BOOL SHELL_InRunDllProcess(VOID)
Definition: shlexec.cpp:37
static BOOL SHELL_translate_idlist(LPSHELLEXECUTEINFOW sei, LPWSTR wszParameters, DWORD parametersLen, LPWSTR wszApplicationName, DWORD dwApplicationNameLen)
Definition: shlexec.cpp:1731
static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei)
Definition: shlexec.cpp:1375
static HRESULT shellex_get_contextmenu(LPSHELLEXECUTEINFOW sei, CComPtr< IContextMenu > &cm)
Definition: shlexec.cpp:1522
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:2915
static HRESULT shellex_get_dataobj(LPSHELLEXECUTEINFOW sei, CComPtr< IDataObject > &dataObj)
Definition: shlexec.cpp:1394
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2461
static VOID ShellExec_RunDLL_Helper(_In_opt_ HWND hwnd, _In_opt_ HINSTANCE hInstance, _In_ PCWSTR pszCmdLine, _In_ INT nCmdShow)
Definition: shlexec.cpp:3093
static LPWSTR SHELL_BuildEnvW(const WCHAR *path)
Definition: shlexec.cpp:590
UINT_PTR(* SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, const SHELLEXECUTEINFOW *sei, LPSHELLEXECUTEINFOW sei_out)
Definition: shlexec.cpp:33
static HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize)
Definition: shlexec.cpp:464
static void ParseTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
Definition: shlexec.cpp:130
HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpVerb, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
Definition: shlexec.cpp:2345
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:2781
static BOOL SHELL_TryAppPathW(LPCWSTR szName, LPWSTR lpResult, WCHAR **env)
Definition: shlexec.cpp:648
static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR wszKeyname, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
Definition: shlexec.cpp:1839
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:2945
HRESULT hr
Definition: shlfolder.c:183
#define PPCF_FORCEQUALIFY
Definition: shlobj.h:2429
#define PPCF_INCLUDEARGS
Definition: shlobj.h:2425
#define PPCF_LONGESTPOSSIBLE
Definition: shlobj.h:2430
@ OAIF_EXEC
Definition: shlobj.h:2690
@ OAIF_REGISTER_EXT
Definition: shlobj.h:2689
@ OAIF_ALLOW_REGISTRATION
Definition: shlobj.h:2688
#define PPCF_ADDQUOTES
Definition: shlobj.h:2424
#define PPCF_ADDARGUMENTS
Definition: shlobj.h:2426
#define PPCF_NODIRECTORIES
Definition: shlobj.h:2427
#define UrlIsFileUrlW(x)
Definition: shlwapi.h:1423
@ ASSOCSTR_COMMAND
Definition: shlwapi.h:612
@ ASSOCSTR_EXECUTABLE
Definition: shlwapi.h:613
#define STIF_SUPPORT_HEX
Definition: shlwapi.h:1498
@ URLIS_APPLIABLE
Definition: shlwapi.h:1238
@ ASSOCF_NONE
Definition: shlwapi.h:590
#define WHICH_DEFAULT
#define SHACF_WIN95SHLEXEC
#define IDS_FILE_NOT_FOUND
Definition: shresdef.h:365
#define IDS_SHLEXEC_NOASSOC
Definition: shresdef.h:187
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define _countof(array)
Definition: sndvol32.h:70
#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:340
HINSTANCE hInstApp
Definition: shellapi.h:342
LPCWSTR lpParameters
Definition: shellapi.h:339
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 max(a, b)
Definition: svc.c:63
#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
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
const char * PCSTR
Definition: typedefs.h:52
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define SEE_MASK_USE_RESERVED
Definition: undocshell.h:683
#define SEE_MASK_FLAG_SEPVDM
Definition: undocshell.h:682
#define SEE_MASK_HASTITLE
Definition: undocshell.h:684
#define SEE_MASK_UNKNOWN_0x1000
Definition: undocshell.h:680
#define SEE_MASK_HASLINKNAME
Definition: undocshell.h:681
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
int ret
int retval
Definition: wcstombs.cpp:91
_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
#define ZeroMemory
Definition: winbase.h:1753
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define STARTF_USESHOWWINDOW
Definition: winbase.h:524
#define CREATE_UNICODE_ENVIRONMENT
Definition: winbase.h:196
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:456
#define CREATE_SEPARATE_WOW_VDM
Definition: winbase.h:197
#define FORMAT_MESSAGE_ARGUMENT_ARRAY
Definition: winbase.h:457
#define WAIT_FAILED
Definition: winbase.h:446
#define EXCEPTION_ACCESS_VIOLATION
Definition: winbase.h:344
#define CREATE_NEW_CONSOLE
Definition: winbase.h:190
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 ERROR_DLL_NOT_FOUND
Definition: winerror.h:679
#define ERROR_NO_ASSOCIATION
Definition: winerror.h:677
#define ERROR_CANCELLED
Definition: winerror.h:726
#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
_In_ DWORD _In_ int _In_ int _In_opt_ LPNLSVERSIONINFO _In_opt_ LPVOID lpReserved
Definition: winnls.h:1199
_In_ DWORD _In_ int _In_ int cchDest
Definition: winnls.h:1197
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
#define SW_SHOWNORMAL
Definition: winuser.h:781
#define SW_SHOWMAXIMIZED
Definition: winuser.h:784
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:738
#define MIIM_ID
Definition: winuser.h:733
int WINAPI GetMenuItemCount(_In_opt_ HMENU)
HMENU WINAPI CreateMenu(void)
Definition: menu.c:829
#define MIIM_FTYPE
Definition: winuser.h:740
int WINAPI MessageBoxW(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType)
#define MIIM_STATE
Definition: winuser.h:732
#define MFS_DEFAULT
Definition: winuser.h:759
#define SW_SHOWDEFAULT
Definition: winuser.h:791
#define MB_ICONERROR
Definition: winuser.h:798
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 SW_RESTORE
Definition: winuser.h:790
#define SW_SHOW
Definition: winuser.h:786
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
#define MIIM_DATA
Definition: winuser.h:737
#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