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