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