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