ReactOS 0.4.15-dev-8102-g108db8f
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{
562 WCHAR *strings, *new_env;
563 WCHAR *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 = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, total * sizeof(WCHAR))))
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;
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];
967 WCHAR * dynamic_res=NULL;
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 res = dynamic_res = static_cast<WCHAR *>(HeapAlloc(GetProcessHeap(), 0, resultLen * sizeof(WCHAR)));
1130 SHELL_ArgifyW(dynamic_res, resultLen, exec, lpFile, pidl, szCommandline, NULL, NULL);
1131 }
1132 else
1133 res = static_res;
1134 TRACE("%s %s => %s\n", debugstr_w(exec), debugstr_w(lpFile), debugstr_w(res));
1135
1136 /* It's documented in the KB 330337 that IE has a bug and returns
1137 * error DMLERR_NOTPROCESSED on XTYP_EXECUTE request.
1138 */
1139 if (unicode)
1140 hDdeData = DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0, XTYP_EXECUTE, 30000, &tid);
1141 else
1142 {
1143 DWORD lenA = WideCharToMultiByte(CP_ACP, 0, res, -1, NULL, 0, NULL, NULL);
1144 char *resA = (LPSTR)HeapAlloc(GetProcessHeap(), 0, lenA);
1145 WideCharToMultiByte(CP_ACP, 0, res, -1, resA, lenA, NULL, NULL);
1146 hDdeData = DdeClientTransaction( (LPBYTE)resA, lenA, hConv, 0L, 0,
1147 XTYP_EXECUTE, 10000, &tid );
1148 HeapFree(GetProcessHeap(), 0, resA);
1149 }
1150 if (hDdeData)
1151 DdeFreeDataHandle(hDdeData);
1152 else
1153 WARN("DdeClientTransaction failed with error %04x\n", DdeGetLastError(ddeInst));
1154 ret = 33;
1155
1156 HeapFree(GetProcessHeap(), 0, dynamic_res);
1157
1158 DdeDisconnect(hConv);
1159
1160error:
1162
1163 return ret;
1164}
1165
1166/*************************************************************************
1167 * execute_from_key [Internal]
1168 */
1170 LPCWSTR szCommandline, LPCWSTR executable_name,
1171 SHELL_ExecuteW32 execfunc,
1173{
1174 WCHAR cmd[256], param[1024], ddeexec[256];
1175 DWORD cmdlen = sizeof(cmd), ddeexeclen = sizeof(ddeexec);
1176 UINT_PTR retval = SE_ERR_NOASSOC;
1177 DWORD resultLen;
1178 LPWSTR tmp;
1179
1180 TRACE("%s %s %s %s %s\n", debugstr_w(key), debugstr_w(lpFile), debugstr_w(env),
1181 debugstr_w(szCommandline), debugstr_w(executable_name));
1182
1183 cmd[0] = '\0';
1184 param[0] = '\0';
1185
1186 /* Get the application from the registry */
1188 {
1189 TRACE("got cmd: %s\n", debugstr_w(cmd));
1190
1191 /* Is there a replace() function anywhere? */
1192 cmdlen /= sizeof(WCHAR);
1193 if (cmdlen >= ARRAY_SIZE(cmd))
1194 cmdlen = ARRAY_SIZE(cmd) - 1;
1195 cmd[cmdlen] = '\0';
1196 SHELL_ArgifyW(param, ARRAY_SIZE(param), cmd, lpFile, (LPITEMIDLIST)psei->lpIDList, szCommandline, &resultLen,
1197 (psei->lpDirectory && *psei->lpDirectory) ? psei->lpDirectory : NULL);
1198 if (resultLen > ARRAY_SIZE(param))
1199 ERR("Argify buffer not large enough, truncating\n");
1200 }
1201
1202 /* Get the parameters needed by the application
1203 from the associated ddeexec key */
1204 tmp = const_cast<LPWSTR>(strstrW(key, L"command"));
1205 assert(tmp);
1206 wcscpy(tmp, L"ddeexec");
1207
1208 if (RegQueryValueW(HKEY_CLASSES_ROOT, key, ddeexec, (LONG *)&ddeexeclen) == ERROR_SUCCESS)
1209 {
1210 TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(ddeexec));
1211 if (!param[0]) strcpyW(param, executable_name);
1212 retval = dde_connect(key, param, ddeexec, lpFile, env, szCommandline, (LPITEMIDLIST)psei->lpIDList, execfunc, psei, psei_out);
1213 }
1214 else if (param[0])
1215 {
1216 TRACE("executing: %s\n", debugstr_w(param));
1217 retval = execfunc(param, env, FALSE, psei, psei_out);
1218 }
1219 else
1220 WARN("Nothing appropriate found for %s\n", debugstr_w(key));
1221
1222 return retval;
1223}
1224
1225/*************************************************************************
1226 * FindExecutableA [SHELL32.@]
1227 */
1229{
1230 HINSTANCE retval;
1231 WCHAR *wFile = NULL, *wDirectory = NULL;
1232 WCHAR wResult[MAX_PATH];
1233
1234 if (lpFile) __SHCloneStrAtoW(&wFile, lpFile);
1235 if (lpDirectory) __SHCloneStrAtoW(&wDirectory, lpDirectory);
1236
1237 retval = FindExecutableW(wFile, wDirectory, wResult);
1238 WideCharToMultiByte(CP_ACP, 0, wResult, -1, lpResult, MAX_PATH, NULL, NULL);
1239 SHFree(wFile);
1240 SHFree(wDirectory);
1241
1242 TRACE("returning %s\n", lpResult);
1243 return retval;
1244}
1245
1246/*************************************************************************
1247 * FindExecutableW [SHELL32.@]
1248 *
1249 * This function returns the executable associated with the specified file
1250 * for the default verb.
1251 *
1252 * PARAMS
1253 * lpFile [I] The file to find the association for. This must refer to
1254 * an existing file otherwise FindExecutable fails and returns
1255 * SE_ERR_FNF.
1256 * lpResult [O] Points to a buffer into which the executable path is
1257 * copied. This parameter must not be NULL otherwise
1258 * FindExecutable() segfaults. The buffer must be of size at
1259 * least MAX_PATH characters.
1260 *
1261 * RETURNS
1262 * A value greater than 32 on success, less than or equal to 32 otherwise.
1263 * See the SE_ERR_* constants.
1264 *
1265 * NOTES
1266 * On Windows XP and 2003, FindExecutable() seems to first convert the
1267 * filename into 8.3 format, thus taking into account only the first three
1268 * characters of the extension, and expects to find an association for those.
1269 * However other Windows versions behave sanely.
1270 */
1272{
1273 UINT_PTR retval;
1274 WCHAR old_dir[MAX_PATH], res[MAX_PATH];
1275 DWORD cch = _countof(res);
1276 LPCWSTR dirs[2];
1277
1278 TRACE("File %s, Dir %s\n", debugstr_w(lpFile), debugstr_w(lpDirectory));
1279
1280 *lpResult = UNICODE_NULL;
1281
1282 GetCurrentDirectoryW(_countof(old_dir), old_dir);
1283
1284 if (lpDirectory && *lpDirectory)
1285 {
1287 dirs[0] = lpDirectory;
1288 }
1289 else
1290 {
1291 dirs[0] = old_dir;
1292 }
1293 dirs[1] = NULL;
1294
1295 if (!GetShortPathNameW(lpFile, res, _countof(res)))
1296 StringCchCopyW(res, _countof(res), lpFile);
1297
1299 {
1300 // NOTE: The last parameter of this AssocQueryStringW call is "strange" in Windows.
1301 if (PathIsExeW(res) ||
1303 {
1304 StringCchCopyW(lpResult, MAX_PATH, res);
1305 retval = 42;
1306 }
1307 else
1308 {
1309 retval = SE_ERR_NOASSOC;
1310 }
1311 }
1312 else
1313 {
1314 retval = SE_ERR_FNF;
1315 }
1316
1317 TRACE("returning %s\n", debugstr_w(lpResult));
1318 SetCurrentDirectoryW(old_dir);
1319 return (HINSTANCE)retval;
1320}
1321
1322/* FIXME: is this already implemented somewhere else? */
1324{
1325 LPCWSTR ext = NULL, lpClass = NULL;
1326 LPWSTR cls = NULL;
1327 DWORD type = 0, sz = 0;
1328 HKEY hkey = 0;
1329 LONG r;
1330
1331 if (sei->fMask & SEE_MASK_CLASSALL)
1332 return sei->hkeyClass;
1333
1334 if (sei->fMask & SEE_MASK_CLASSNAME)
1335 lpClass = sei->lpClass;
1336 else
1337 {
1339 TRACE("ext = %s\n", debugstr_w(ext));
1340 if (!ext)
1341 return hkey;
1342
1344 if (r != ERROR_SUCCESS)
1345 return hkey;
1346
1347 r = RegQueryValueExW(hkey, NULL, 0, &type, NULL, &sz);
1348 if (r == ERROR_SUCCESS && type == REG_SZ)
1349 {
1350 sz += sizeof (WCHAR);
1351 cls = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sz);
1352 cls[0] = 0;
1353 RegQueryValueExW(hkey, NULL, 0, &type, (LPBYTE) cls, &sz);
1354 }
1355
1356 RegCloseKey( hkey );
1357 lpClass = cls;
1358 }
1359
1360 TRACE("class = %s\n", debugstr_w(lpClass));
1361
1362 hkey = 0;
1363 if (lpClass)
1364 RegOpenKeyW( HKEY_CLASSES_ROOT, lpClass, &hkey);
1365
1366 HeapFree(GetProcessHeap(), 0, cls);
1367
1368 return hkey;
1369}
1370
1372{
1373 CComHeapPtr<ITEMIDLIST> allocatedPidl;
1374 LPITEMIDLIST pidl = NULL;
1375
1376 if (sei->fMask & SEE_MASK_CLASSALL)
1377 {
1378 pidl = (LPITEMIDLIST)sei->lpIDList;
1379 }
1380 else
1381 {
1382 WCHAR fullpath[MAX_PATH];
1383 BOOL ret;
1384
1385 fullpath[0] = 0;
1386 ret = GetFullPathNameW(sei->lpFile, MAX_PATH, fullpath, NULL);
1387 if (!ret)
1389
1390 pidl = ILCreateFromPathW(fullpath);
1391 allocatedPidl.Attach(pidl);
1392 }
1393
1395 LPCITEMIDLIST pidllast = NULL;
1396 HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &shf), &pidllast);
1398 return hr;
1399
1400 return shf->GetUIObjectOf(NULL, 1, &pidllast, IID_NULL_PPV_ARG(IDataObject, &dataObj));
1401}
1402
1405{
1407 CMINVOKECOMMANDINFOEX ici;
1409 WCHAR string[0x80];
1410 INT i, n, def = -1;
1411 HMENU hmenu = 0;
1412 HRESULT r;
1413
1414 TRACE("%p %p\n", obj, sei);
1415
1416 r = obj->QueryInterface(IID_PPV_ARG(IContextMenu, &cm));
1417 if (FAILED(r))
1418 return r;
1419
1420 hmenu = CreateMenu();
1421 if (!hmenu)
1422 goto end;
1423
1424 /* the number of the last menu added is returned in r */
1425 r = cm->QueryContextMenu(hmenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
1426 if (FAILED(r))
1427 goto end;
1428
1430 for (i = 0; i < n; i++)
1431 {
1432 memset(&info, 0, sizeof(info));
1433 info.cbSize = sizeof info;
1435 info.dwTypeData = string;
1436 info.cch = sizeof string;
1437 string[0] = 0;
1439
1440 TRACE("menu %d %s %08x %08lx %08x %08x\n", i, debugstr_w(string),
1441 info.fState, info.dwItemData, info.fType, info.wID);
1442 if ((!sei->lpVerb && (info.fState & MFS_DEFAULT)) ||
1443 (sei->lpVerb && !lstrcmpiW(sei->lpVerb, string)))
1444 {
1445 def = i;
1446 break;
1447 }
1448 }
1449
1450 r = E_FAIL;
1451 if (def == -1)
1452 goto end;
1453
1454 memset(&ici, 0, sizeof ici);
1455 ici.cbSize = sizeof ici;
1456 ici.fMask = CMIC_MASK_UNICODE | (sei->fMask & (SEE_MASK_NO_CONSOLE | SEE_MASK_NOASYNC | SEE_MASK_ASYNCOK | SEE_MASK_FLAG_NO_UI));
1457 ici.nShow = sei->nShow;
1458 ici.lpVerb = MAKEINTRESOURCEA(def);
1459 ici.hwnd = sei->hwnd;
1460 ici.lpParametersW = sei->lpParameters;
1461
1462 r = cm->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
1463
1464 TRACE("invoke command returned %08x\n", r);
1465
1466end:
1467 if (hmenu)
1468 DestroyMenu( hmenu );
1469 return r;
1470}
1471
1473{
1474 TRACE("%p %s %p\n", hkey, debugstr_guid(guid), sei);
1475
1476 CCoInit coInit;
1477
1478 if (FAILED_UNEXPECTEDLY(coInit.hr))
1479 return coInit.hr;
1480
1482 HRESULT hr = CoCreateInstance(*guid, NULL, CLSCTX_INPROC_SERVER,
1485 return hr;
1486
1487 CComPtr<IDataObject> dataobj;
1488 hr = shellex_get_dataobj(sei, dataobj);
1490 return hr;
1491
1492 hr = obj->Initialize(NULL, dataobj, hkey);
1494 return hr;
1495
1497 hr = obj->QueryInterface(IID_PPV_ARG(IObjectWithSite, &ows));
1499 return hr;
1500
1501 ows->SetSite(NULL);
1502
1504}
1505
1507{
1508 CComHeapPtr<ITEMIDLIST> allocatedPidl;
1509 LPITEMIDLIST pidl = NULL;
1510
1511 if (sei->lpIDList)
1512 {
1513 pidl = (LPITEMIDLIST)sei->lpIDList;
1514 }
1515 else
1516 {
1517 SFGAOF sfga = 0;
1518 HRESULT hr = SHParseDisplayName(sei->lpFile, NULL, &allocatedPidl, SFGAO_STORAGECAPMASK, &sfga);
1519 if (FAILED(hr))
1520 {
1521 WCHAR Buffer[MAX_PATH] = {};
1522 // FIXME: MAX_PATH.....
1524 if (retval <= 32)
1525 return HRESULT_FROM_WIN32(retval);
1526
1527 hr = SHParseDisplayName(Buffer, NULL, &allocatedPidl, SFGAO_STORAGECAPMASK, &sfga);
1528 // This should not happen, we found it...
1530 return hr;
1531 }
1532
1533 pidl = allocatedPidl;
1534 }
1535
1537 LPCITEMIDLIST pidllast = NULL;
1538 HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &shf), &pidllast);
1539 if (FAILED(hr))
1540 return hr;
1541
1542 return shf->GetUIObjectOf(NULL, 1, &pidllast, IID_NULL_PPV_ARG(IContextMenu, &cm));
1543}
1544
1546{
1547 TRACE("%p\n", sei);
1548
1549 CCoInit coInit;
1550
1551 if (FAILED_UNEXPECTEDLY(coInit.hr))
1552 return coInit.hr;
1553
1557 return hr;
1558
1559 CComHeapPtr<char> verb, parameters;
1560 __SHCloneStrWtoA(&verb, sei->lpVerb);
1561 __SHCloneStrWtoA(&parameters, sei->lpParameters);
1562
1563 CMINVOKECOMMANDINFOEX ici = {};
1564 ici.cbSize = sizeof ici;
1566 ici.nShow = sei->nShow;
1567 ici.lpVerb = verb;
1568 ici.hwnd = sei->hwnd;
1569 ici.lpParameters = parameters;
1570
1571 HMENU hMenu = CreatePopupMenu();
1572 BOOL fDefault = !ici.lpVerb || !ici.lpVerb[0];
1573 hr = cm->QueryContextMenu(hMenu, 0, 1, 0x7fff, fDefault ? CMF_DEFAULTONLY : 0);
1574 if (!FAILED_UNEXPECTEDLY(hr))
1575 {
1576 if (fDefault)
1577 {
1578 INT uDefault = GetMenuDefaultItem(hMenu, FALSE, 0);
1579 uDefault = (uDefault != -1) ? uDefault - 1 : 0;
1580 ici.lpVerb = MAKEINTRESOURCEA(uDefault);
1581 }
1582
1583 hr = cm->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
1584 if (!FAILED_UNEXPECTEDLY(hr))
1585 hr = S_OK;
1586 }
1587
1588 DestroyMenu(hMenu);
1589
1590 return hr;
1591}
1592
1593
1594
1595/*************************************************************************
1596 * ShellExecute_FromContextMenu [Internal]
1597 */
1599{
1600 HKEY hkey, hkeycm = 0;
1601 WCHAR szguid[39];
1602 HRESULT hr;
1603 GUID guid;
1604 DWORD i;
1605 LONG r;
1606
1607 TRACE("%s\n", debugstr_w(sei->lpFile));
1608
1609 hkey = ShellExecute_GetClassKey(sei);
1610 if (!hkey)
1611 return ERROR_FUNCTION_FAILED;
1612
1613 r = RegOpenKeyW(hkey, L"shellex\\ContextMenuHandlers", &hkeycm);
1614 if (r == ERROR_SUCCESS)
1615 {
1616 i = 0;
1617 while (1)
1618 {
1619 r = RegEnumKeyW(hkeycm, i++, szguid, ARRAY_SIZE(szguid));
1620 if (r != ERROR_SUCCESS)
1621 break;
1622
1623 hr = CLSIDFromString(szguid, &guid);
1624 if (SUCCEEDED(hr))
1625 {
1626 /* stop at the first one that succeeds in running */
1627 hr = shellex_load_object_and_run(hkey, &guid, sei);
1628 if (SUCCEEDED(hr))
1629 break;
1630 }
1631 }
1632 RegCloseKey(hkeycm);
1633 }
1634
1635 if (hkey != sei->hkeyClass)
1636 RegCloseKey(hkey);
1637 return r;
1638}
1639
1640static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR lpstrProtocol, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc);
1641
1643{
1644 WCHAR execCmd[1024], classname[1024];
1645 /* launch a document by fileclass like 'WordPad.Document.1' */
1646 /* the Commandline contains 'c:\Path\wordpad.exe "%1"' */
1647 /* FIXME: wcmd should not be of a fixed size. Fixed to 1024, MAX_PATH is way too short! */
1648 ULONG cmask = (psei->fMask & SEE_MASK_CLASSALL);
1649 DWORD resultLen;
1650 BOOL done;
1651 UINT_PTR rslt;
1652
1653 /* FIXME: remove following block when SHELL_quote_and_execute supports hkeyClass parameter */
1654 if (cmask != SEE_MASK_CLASSNAME)
1655 {
1656 WCHAR wcmd[1024];
1658 (cmask == SEE_MASK_CLASSNAME) ? psei->lpClass : NULL,
1659 psei->lpVerb,
1660 execCmd, sizeof(execCmd));
1661
1662 /* FIXME: get the extension of lpFile, check if it fits to the lpClass */
1663 TRACE("SEE_MASK_CLASSNAME->%s, doc->%s\n", debugstr_w(execCmd), debugstr_w(wszApplicationName));
1664
1665 wcmd[0] = '\0';
1666 done = SHELL_ArgifyW(wcmd, ARRAY_SIZE(wcmd), execCmd, wszApplicationName, (LPITEMIDLIST)psei->lpIDList, NULL, &resultLen,
1667 (psei->lpDirectory && *psei->lpDirectory) ? psei->lpDirectory : NULL);
1668 if (!done && wszApplicationName[0])
1669 {
1670 strcatW(wcmd, L" ");
1671 if (*wszApplicationName != '"')
1672 {
1673 strcatW(wcmd, L"\"");
1674 strcatW(wcmd, wszApplicationName);
1675 strcatW(wcmd, L"\"");
1676 }
1677 else
1678 strcatW(wcmd, wszApplicationName);
1679 }
1680 if (resultLen > ARRAY_SIZE(wcmd))
1681 ERR("Argify buffer not large enough... truncating\n");
1682 return execfunc(wcmd, NULL, FALSE, psei, psei_out);
1683 }
1684
1685 strcpyW(classname, psei->lpClass);
1686 rslt = SHELL_FindExecutableByVerb(psei->lpVerb, NULL, classname, execCmd, sizeof(execCmd));
1687
1688 TRACE("SHELL_FindExecutableByVerb returned %u (%s, %s)\n", (unsigned int)rslt, debugstr_w(classname), debugstr_w(execCmd));
1689 if (33 > rslt)
1690 return rslt;
1691 rslt = SHELL_quote_and_execute( execCmd, L"", classname,
1692 wszApplicationName, NULL, psei,
1693 psei_out, execfunc );
1694 return rslt;
1695
1696}
1697
1698static BOOL SHELL_translate_idlist(LPSHELLEXECUTEINFOW sei, LPWSTR wszParameters, DWORD parametersLen, LPWSTR wszApplicationName, DWORD dwApplicationNameLen)
1699{
1701 BOOL appKnownSingular = FALSE;
1702
1703 /* last chance to translate IDList: now also allow CLSID paths */
1705 if (buffer[0] == ':' && buffer[1] == ':') {
1706 /* open shell folder for the specified class GUID */
1707 if (strlenW(buffer) + 1 > parametersLen)
1708 ERR("parameters len exceeds buffer size (%i > %i), truncating\n",
1709 lstrlenW(buffer) + 1, parametersLen);
1710 lstrcpynW(wszParameters, buffer, parametersLen);
1711 if (strlenW(L"explorer.exe") > dwApplicationNameLen)
1712 ERR("application len exceeds buffer size (%i), truncating\n",
1713 dwApplicationNameLen);
1714 lstrcpynW(wszApplicationName, L"explorer.exe", dwApplicationNameLen);
1715 appKnownSingular = TRUE;
1716
1717 sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
1718 } else {
1720 DWORD attribs;
1721 DWORD resultLen;
1722 /* Check if we're executing a directory and if so use the
1723 handler for the Folder class */
1728 HCR_GetExecuteCommandW(0, L"Folder",
1729 sei->lpVerb,
1730 buffer, sizeof(buffer))) {
1731 SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen,
1732 buffer, target, (LPITEMIDLIST)sei->lpIDList, NULL, &resultLen,
1733 (sei->lpDirectory && *sei->lpDirectory) ? sei->lpDirectory : NULL);
1734 if (resultLen > dwApplicationNameLen)
1735 ERR("Argify buffer not large enough... truncating\n");
1736 appKnownSingular = FALSE;
1737 }
1738 sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
1739 }
1740 }
1741 return appKnownSingular;
1742}
1743
1744static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR wszKeyname, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
1745{
1746 UINT_PTR retval;
1747 DWORD len;
1748 WCHAR *wszQuotedCmd;
1749
1750 /* Length of quotes plus length of command plus NULL terminator */
1751 len = 2 + lstrlenW(wcmd) + 1;
1752 if (wszParameters[0])
1753 {
1754 /* Length of space plus length of parameters */
1755 len += 1 + lstrlenW(wszParameters);
1756 }
1757 wszQuotedCmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1758 /* Must quote to handle case where cmd contains spaces,
1759 * else security hole if malicious user creates executable file "C:\\Program"
1760 */
1761 strcpyW(wszQuotedCmd, L"\"");
1762 strcatW(wszQuotedCmd, wcmd);
1763 strcatW(wszQuotedCmd, L"\"");
1764 if (wszParameters[0])
1765 {
1766 strcatW(wszQuotedCmd, L" ");
1767 strcatW(wszQuotedCmd, wszParameters);
1768 }
1769
1770 TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), debugstr_w(psei->lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(wszKeyname));
1771
1772 if (*wszKeyname)
1773 retval = execute_from_key(wszKeyname, wszApplicationName, env, psei->lpParameters, wcmd, execfunc, psei, psei_out);
1774 else
1775 retval = execfunc(wszQuotedCmd, env, FALSE, psei, psei_out);
1776 HeapFree(GetProcessHeap(), 0, wszQuotedCmd);
1777 return retval;
1778}
1779
1781{
1782 UINT_PTR retval;
1783 WCHAR *lpstrProtocol;
1784 LPCWSTR lpstrRes;
1785 INT iSize;
1786 DWORD len;
1787
1788 lpstrRes = strchrW(lpFile, ':');
1789 if (lpstrRes)
1790 iSize = lpstrRes - lpFile;
1791 else
1792 iSize = strlenW(lpFile);
1793
1794 TRACE("Got URL: %s\n", debugstr_w(lpFile));
1795 /* Looking for ...<protocol>\shell<lpVerb>\command */
1796 len = iSize + lstrlenW(L"\\shell\\") + lstrlenW(L"\\command") + 1;
1797 if (psei->lpVerb && *psei->lpVerb)
1798 len += lstrlenW(psei->lpVerb);
1799 else
1800 len += lstrlenW(L"open");
1801 lpstrProtocol = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1802 memcpy(lpstrProtocol, lpFile, iSize * sizeof(WCHAR));
1803 lpstrProtocol[iSize] = '\0';
1804 strcatW(lpstrProtocol, L"\\shell\\");
1805 strcatW(lpstrProtocol, psei->lpVerb && *psei->lpVerb ? psei->lpVerb : L"open");
1806 strcatW(lpstrProtocol, L"\\command");
1807
1808 retval = execute_from_key(lpstrProtocol, lpFile, NULL, psei->lpParameters,
1809 wcmd, execfunc, psei, psei_out);
1810 HeapFree(GetProcessHeap(), 0, lpstrProtocol);
1811 return retval;
1812}
1813
1815{
1816 WCHAR msg[2048];
1817 DWORD_PTR msgArguments[3] = { (DWORD_PTR)filename, 0, 0 };
1819
1821 if (retval == SE_ERR_NOASSOC)
1823 else
1825 NULL,
1826 error_code,
1828 msg,
1829 ARRAY_SIZE(msg),
1830 (va_list*)msgArguments);
1831
1833}
1834
1836{
1837 WCHAR *buf;
1838 DWORD len;
1839
1841 if (!len) return NULL;
1842
1843 buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1844 if (!buf) return NULL;
1845
1847 if (!len)
1848 {
1850 return NULL;
1851 }
1852 return buf;
1853}
1854
1855/*************************************************************************
1856 * SHELL_execute [Internal]
1857 */
1859{
1860 static const DWORD unsupportedFlags =
1864
1865 WCHAR parametersBuffer[1024], dirBuffer[MAX_PATH], wcmdBuffer[1024];
1866 WCHAR *wszApplicationName, *wszParameters, *wszDir, *wcmd;
1867 DWORD dwApplicationNameLen = MAX_PATH + 2;
1868 DWORD parametersLen = ARRAY_SIZE(parametersBuffer);
1869 DWORD dirLen = ARRAY_SIZE(dirBuffer);
1870 DWORD wcmdLen = ARRAY_SIZE(wcmdBuffer);
1871 DWORD len;
1872 SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */
1873 WCHAR wfileName[MAX_PATH];
1874 WCHAR *env;
1875 WCHAR wszKeyname[256];
1876 LPCWSTR lpFile;
1877 UINT_PTR retval = SE_ERR_NOASSOC;
1878 BOOL appKnownSingular = FALSE;
1879
1880 /* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
1881 sei_tmp = *sei;
1882
1883 TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
1884 sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
1885 debugstr_w(sei_tmp.lpFile), debugstr_w(sei_tmp.lpParameters),
1886 debugstr_w(sei_tmp.lpDirectory), sei_tmp.nShow,
1887 ((sei_tmp.fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME) ?
1888 debugstr_w(sei_tmp.lpClass) : "not used");
1889
1890 sei->hProcess = NULL;
1891
1892 /* make copies of all path/command strings */
1893 if (!sei_tmp.lpFile)
1894 {
1895 wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR));
1896 *wszApplicationName = '\0';
1897 }
1898 else if (*sei_tmp.lpFile == '\"' && sei_tmp.lpFile[(len = strlenW(sei_tmp.lpFile))-1] == '\"')
1899 {
1900 if(len-1 >= dwApplicationNameLen)
1901 dwApplicationNameLen = len;
1902
1903 wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR));
1904 memcpy(wszApplicationName, sei_tmp.lpFile + 1, len * sizeof(WCHAR));
1905
1906 if(len > 2)
1907 wszApplicationName[len-2] = '\0';
1908 appKnownSingular = TRUE;
1909
1910 TRACE("wszApplicationName=%s\n", debugstr_w(wszApplicationName));
1911 }
1912 else
1913 {
1914 DWORD l = strlenW(sei_tmp.lpFile) + 1;
1915 if(l > dwApplicationNameLen) dwApplicationNameLen = l + 1;
1916 wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR));
1917 memcpy(wszApplicationName, sei_tmp.lpFile, l * sizeof(WCHAR));
1918
1919 if (wszApplicationName[2] == 0 && wszApplicationName[1] == L':' &&
1920 ((L'A' <= wszApplicationName[0] && wszApplicationName[0] <= L'Z') ||
1921 (L'a' <= wszApplicationName[0] && wszApplicationName[0] <= L'z')))
1922 {
1923 // 'C:' --> 'C:\'
1924 PathAddBackslashW(wszApplicationName);
1925 }
1926 }
1927
1928 wszParameters = parametersBuffer;
1929 if (sei_tmp.lpParameters)
1930 {
1931 len = lstrlenW(sei_tmp.lpParameters) + 1;
1932 if (len > parametersLen)
1933 {
1934 wszParameters = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1935 parametersLen = len;
1936 }
1937 strcpyW(wszParameters, sei_tmp.lpParameters);
1938 }
1939 else
1940 *wszParameters = L'\0';
1941
1942 wszDir = dirBuffer;
1943 if (sei_tmp.lpDirectory)
1944 {
1945 len = lstrlenW(sei_tmp.lpDirectory) + 1;
1946 if (len > dirLen)
1947 {
1948 wszDir = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1949 dirLen = len;
1950 }
1951 strcpyW(wszDir, sei_tmp.lpDirectory);
1952 }
1953 else
1954 *wszDir = L'\0';
1955
1956 /* adjust string pointers to point to the new buffers */
1957 sei_tmp.lpFile = wszApplicationName;
1958 sei_tmp.lpParameters = wszParameters;
1959 sei_tmp.lpDirectory = wszDir;
1960
1961 if (sei_tmp.fMask & unsupportedFlags)
1962 {
1963 FIXME("flags ignored: 0x%08x\n", sei_tmp.fMask & unsupportedFlags);
1964 }
1965
1966 /* process the IDList */
1967 if (sei_tmp.fMask & SEE_MASK_IDLIST &&
1969 {
1971
1973
1974 if (SUCCEEDED(hr))
1975 {
1976 hr = pSEH->Execute(&sei_tmp);
1977
1978 if (hr == S_OK)
1979 {
1980 HeapFree(GetProcessHeap(), 0, wszApplicationName);
1981 if (wszParameters != parametersBuffer)
1982 HeapFree(GetProcessHeap(), 0, wszParameters);
1983 if (wszDir != dirBuffer)
1984 HeapFree(GetProcessHeap(), 0, wszDir);
1985 return TRUE;
1986 }
1987 }
1988
1989 SHGetPathFromIDListW((LPCITEMIDLIST)sei_tmp.lpIDList, wszApplicationName);
1990 appKnownSingular = TRUE;
1991 TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName));
1992 }
1993
1994 if (sei_tmp.fMask & SEE_MASK_DOENVSUBST)
1995 {
1996 WCHAR *tmp;
1997
1998 tmp = expand_environment(sei_tmp.lpFile);
1999 if (!tmp)
2000 {
2001 return FALSE;
2002 }
2003 HeapFree(GetProcessHeap(), 0, wszApplicationName);
2004 sei_tmp.lpFile = wszApplicationName = tmp;
2005
2006 tmp = expand_environment(sei_tmp.lpDirectory);
2007 if (!tmp)
2008 {
2009 return FALSE;
2010 }
2011 if (wszDir != dirBuffer) HeapFree(GetProcessHeap(), 0, wszDir);
2012 sei_tmp.lpDirectory = wszDir = tmp;
2013 }
2014
2016 {
2018 if (SUCCEEDED(hr))
2019 {
2020 sei->hInstApp = (HINSTANCE)42;
2021 HeapFree(GetProcessHeap(), 0, wszApplicationName);
2022 if (wszParameters != parametersBuffer)
2023 HeapFree(GetProcessHeap(), 0, wszParameters);
2024 if (wszDir != dirBuffer)
2025 HeapFree(GetProcessHeap(), 0, wszDir);
2026 return TRUE;
2027 }
2028 }
2029
2030
2032 {
2033 sei->hInstApp = (HINSTANCE) 33;
2034 HeapFree(GetProcessHeap(), 0, wszApplicationName);
2035 if (wszParameters != parametersBuffer)
2036 HeapFree(GetProcessHeap(), 0, wszParameters);
2037 if (wszDir != dirBuffer)
2038 HeapFree(GetProcessHeap(), 0, wszDir);
2039 return TRUE;
2040 }
2041
2042 if (sei_tmp.fMask & SEE_MASK_CLASSALL)
2043 {
2044 retval = SHELL_execute_class(wszApplicationName, &sei_tmp, sei, execfunc);
2045 if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
2046 {
2048
2049 //FIXME
2050 // need full path
2051
2052 Info.pcszFile = wszApplicationName;
2053 Info.pcszClass = NULL;
2054 Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
2055
2056 //if (SHOpenWithDialog(sei_tmp.hwnd, &Info) != S_OK)
2058 do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName);
2059 }
2060 HeapFree(GetProcessHeap(), 0, wszApplicationName);
2061 if (wszParameters != parametersBuffer)
2062 HeapFree(GetProcessHeap(), 0, wszParameters);
2063 if (wszDir != dirBuffer)
2064 HeapFree(GetProcessHeap(), 0, wszDir);
2065 return retval > 32;
2066 }
2067
2068 /* Has the IDList not yet been translated? */
2069 if (sei_tmp.fMask & SEE_MASK_IDLIST)
2070 {
2071 appKnownSingular = SHELL_translate_idlist( &sei_tmp, wszParameters,
2072 parametersLen,
2073 wszApplicationName,
2074 dwApplicationNameLen );
2075 }
2076
2077 /* convert file URLs */
2078 if (UrlIsFileUrlW(sei_tmp.lpFile))
2079 {
2080 LPWSTR buf;
2081 DWORD size;
2082
2083 size = MAX_PATH;
2084 buf = static_cast<LPWSTR>(HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)));
2085 if (!buf || FAILED(PathCreateFromUrlW(sei_tmp.lpFile, buf, &size, 0)))
2086 {
2088 return SE_ERR_OOM;
2089 }
2090
2091 HeapFree(GetProcessHeap(), 0, wszApplicationName);
2092 wszApplicationName = buf;
2093 sei_tmp.lpFile = wszApplicationName;
2094 }
2095 else /* or expand environment strings (not both!) */
2096 {
2098 if (len > 0)
2099 {
2100 LPWSTR buf;
2101 buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
2102
2103 ExpandEnvironmentStringsW(sei_tmp.lpFile, buf, len + 1);
2104 HeapFree(GetProcessHeap(), 0, wszApplicationName);
2105 wszApplicationName = buf;
2106 /* appKnownSingular unmodified */
2107
2108 sei_tmp.lpFile = wszApplicationName;
2109 }
2110 }
2111
2112 if (*sei_tmp.lpDirectory)
2113 {
2115 if (len > 0)
2116 {
2117 LPWSTR buf;
2118 len++;
2119 buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2121 if (wszDir != dirBuffer)
2122 HeapFree(GetProcessHeap(), 0, wszDir);
2123 wszDir = buf;
2124 sei_tmp.lpDirectory = wszDir;
2125 }
2126 }
2127
2128 /* Else, try to execute the filename */
2129 TRACE("execute: %s,%s,%s\n", debugstr_w(wszApplicationName), debugstr_w(wszParameters), debugstr_w(wszDir));
2130
2131 /* separate out command line arguments from executable file name */
2132 if (!*sei_tmp.lpParameters && !appKnownSingular)
2133 {
2134 /* If the executable path is quoted, handle the rest of the command line as parameters. */
2135 if (sei_tmp.lpFile[0] == L'"')
2136 {
2137 LPWSTR src = wszApplicationName/*sei_tmp.lpFile*/ + 1;
2138 LPWSTR dst = wfileName;
2139 LPWSTR end;
2140
2141 /* copy the unquoted executable path to 'wfileName' */
2142 while(*src && *src != L'"')
2143 *dst++ = *src++;
2144
2145 *dst = L'\0';
2146
2147 if (*src == L'"')
2148 {
2149 end = ++src;
2150
2151 while(isspaceW(*src))
2152 ++src;
2153 }
2154 else
2155 end = src;
2156
2157 /* copy the parameter string to 'wszParameters' */
2158 strcpyW(wszParameters, src);
2159
2160 /* terminate previous command string after the quote character */
2161 *end = L'\0';
2162 lpFile = wfileName;
2163 }
2164 /* We have to test sei instead of sei_tmp because sei_tmp had its
2165 * input fMask modified above in SHELL_translate_idlist.
2166 * This code is needed to handle the case where we only have an
2167 * lpIDList with multiple CLSID/PIDL's (not 'My Computer' only) */
2168 else if ((sei->fMask & SEE_MASK_IDLIST) == SEE_MASK_IDLIST)
2169 {
2170 WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH];
2171 LPWSTR space, s;
2172
2173 LPWSTR beg = wszApplicationName;
2174 for(s = beg; (space = const_cast<LPWSTR>(strchrW(s, L' '))); s = space + 1)
2175 {
2176 int idx = space - sei_tmp.lpFile;
2177 memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
2178 buffer[idx] = '\0';
2179
2180 if (SearchPathW(*sei_tmp.lpDirectory ? sei_tmp.lpDirectory : NULL,
2181 buffer, L".exe", _countof(xlpFile), xlpFile, NULL))
2182 {
2183 /* separate out command from parameter string */
2184 LPCWSTR p = space + 1;
2185
2186 while(isspaceW(*p))
2187 ++p;
2188
2189 strcpyW(wszParameters, p);
2190 *space = L'\0';
2191
2192 break;
2193 }
2194 }
2195 lpFile = sei_tmp.lpFile;
2196 }
2197 else
2198 {
2199 lpFile = sei_tmp.lpFile;
2200 }
2201 }
2202 else
2203 lpFile = sei_tmp.lpFile;
2204
2205 wcmd = wcmdBuffer;
2206
2207 /* Only execute if it has an executable extension */
2208 if (PathIsExeW(lpFile))
2209 {
2210 len = lstrlenW(wszApplicationName) + 3;
2211 if (sei_tmp.lpParameters[0])
2212 len += 1 + lstrlenW(wszParameters);
2213 if (len > wcmdLen)
2214 {
2215 wcmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2216 wcmdLen = len;
2217 }
2218 swprintf(wcmd, L"\"%s\"", wszApplicationName);
2219 if (sei_tmp.lpParameters[0])
2220 {
2221 strcatW(wcmd, L" ");
2222 strcatW(wcmd, wszParameters);
2223 }
2224
2225 retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
2226 if (retval > 32)
2227 {
2228 HeapFree(GetProcessHeap(), 0, wszApplicationName);
2229 if (wszParameters != parametersBuffer)
2230 HeapFree(GetProcessHeap(), 0, wszParameters);
2231 if (wszDir != dirBuffer)
2232 HeapFree(GetProcessHeap(), 0, wszDir);
2233 if (wcmd != wcmdBuffer)
2234 HeapFree(GetProcessHeap(), 0, wcmd);
2235 return TRUE;
2236 }
2237 }
2238
2239 /* Else, try to find the executable */
2240 wcmd[0] = L'\0';
2241 retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, wcmdLen, wszKeyname, &env, (LPITEMIDLIST)sei_tmp.lpIDList, sei_tmp.lpParameters);
2242 if (retval > 32) /* Found */
2243 {
2244 retval = SHELL_quote_and_execute(wcmd, wszParameters, wszKeyname,
2245 wszApplicationName, env, &sei_tmp,
2246 sei, execfunc);
2248 }
2249 else if (PathIsDirectoryW(lpFile))
2250 {
2251 WCHAR wExec[MAX_PATH];
2252 WCHAR * lpQuotedFile = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * (strlenW(lpFile) + 3));
2253
2254 if (lpQuotedFile)
2255 {
2256 retval = SHELL_FindExecutable(sei_tmp.lpDirectory, L"explorer",
2257 L"open", wExec, MAX_PATH,
2258 NULL, &env, NULL, NULL);
2259 if (retval > 32)
2260 {
2261 swprintf(lpQuotedFile, L"\"%s\"", lpFile);
2262 retval = SHELL_quote_and_execute(wExec, lpQuotedFile,
2263 wszKeyname,
2264 wszApplicationName, env,
2265 &sei_tmp, sei, execfunc);
2267 }
2268 HeapFree(GetProcessHeap(), 0, lpQuotedFile);
2269 }
2270 else
2271 retval = 0; /* Out of memory */
2272 }
2273 else if (PathIsURLW(lpFile)) /* File not found, check for URL */
2274 {
2275 retval = SHELL_execute_url(lpFile, wcmd, &sei_tmp, sei, execfunc );
2276 }
2277 /* Check if file specified is in the form www.??????.*** */
2278 else if (!strncmpiW(lpFile, L"www", 3))
2279 {
2280 /* if so, prefix lpFile with http:// and call ShellExecute */
2281 WCHAR lpstrTmpFile[256];
2282 strcpyW(lpstrTmpFile, L"http://");
2283 strcatW(lpstrTmpFile, lpFile);
2284 retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
2285 }
2286
2287 TRACE("retval %lu\n", retval);
2288
2289 if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
2290 {
2292
2293 //FIXME
2294 // need full path
2295
2296 Info.pcszFile = wszApplicationName;
2297 Info.pcszClass = NULL;
2298 Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
2299
2300 //if (SHOpenWithDialog(sei_tmp.hwnd, &Info) != S_OK)
2302 do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName);
2303 }
2304
2305 HeapFree(GetProcessHeap(), 0, wszApplicationName);
2306 if (wszParameters != parametersBuffer)
2307 HeapFree(GetProcessHeap(), 0, wszParameters);
2308 if (wszDir != dirBuffer)
2309 HeapFree(GetProcessHeap(), 0, wszDir);
2310 if (wcmd != wcmdBuffer)
2311 HeapFree(GetProcessHeap(), 0, wcmd);
2312
2313 sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
2314
2315 return retval > 32;
2316}
2317
2318/*************************************************************************
2319 * ShellExecuteA [SHELL32.290]
2320 */
2322 LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
2323{
2325
2326 TRACE("%p,%s,%s,%s,%s,%d\n",
2327 hWnd, debugstr_a(lpVerb), debugstr_a(lpFile),
2328 debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
2329
2330 sei.cbSize = sizeof(sei);
2332 sei.hwnd = hWnd;
2333 sei.lpVerb = lpVerb;
2334 sei.lpFile = lpFile;
2335 sei.lpParameters = lpParameters;
2337 sei.nShow = iShowCmd;
2338 sei.lpIDList = 0;
2339 sei.lpClass = 0;
2340 sei.hkeyClass = 0;
2341 sei.dwHotKey = 0;
2342 sei.hProcess = 0;
2343
2344 ShellExecuteExA(&sei);
2345 return sei.hInstApp;
2346}
2347
2348static DWORD
2350{
2351 // FIXME
2353}
2354
2355static VOID
2357 _In_ const SHELLEXECUTEINFOW *ExecInfo,
2358 _In_opt_ LPCWSTR pszCaption,
2359 _In_ DWORD dwError)
2360{
2361 // FIXME: Show error message
2362}
2363
2364/*************************************************************************
2365 * ShellExecuteExA [SHELL32.292]
2366 */
2367BOOL
2368WINAPI
2371{
2372 SHELLEXECUTEINFOW seiW;
2373 BOOL ret;
2374 WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL, *wClass = NULL;
2375
2376 TRACE("%p\n", sei);
2377
2378 if (sei->cbSize != sizeof(SHELLEXECUTEINFOA))
2379 {
2382 return FALSE;
2383 }
2384
2385 memcpy(&seiW, sei, sizeof(SHELLEXECUTEINFOW));
2386
2387 seiW.cbSize = sizeof(SHELLEXECUTEINFOW);
2388
2389 if (sei->lpVerb)
2390 seiW.lpVerb = __SHCloneStrAtoW(&wVerb, sei->lpVerb);
2391
2392 if (sei->lpFile)
2393 seiW.lpFile = __SHCloneStrAtoW(&wFile, sei->lpFile);
2394
2395 if (sei->lpParameters)
2396 seiW.lpParameters = __SHCloneStrAtoW(&wParameters, sei->lpParameters);
2397
2398 if (sei->lpDirectory)
2399 seiW.lpDirectory = __SHCloneStrAtoW(&wDirectory, sei->lpDirectory);
2400
2401 if ((sei->fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME && sei->lpClass)
2402 seiW.lpClass = __SHCloneStrAtoW(&wClass, sei->lpClass);
2403 else
2404 seiW.lpClass = NULL;
2405
2406 ret = ShellExecuteExW(&seiW);
2407
2408 sei->hInstApp = seiW.hInstApp;
2409
2410 if (sei->fMask & SEE_MASK_NOCLOSEPROCESS)
2411 sei->hProcess = seiW.hProcess;
2412
2413 SHFree(wVerb);
2414 SHFree(wFile);
2415 SHFree(wParameters);
2416 SHFree(wDirectory);
2417 SHFree(wClass);
2418
2419 return ret;
2420}
2421
2422/*************************************************************************
2423 * ShellExecuteExW [SHELL32.293]
2424 */
2425BOOL
2426WINAPI
2429{
2430 HRESULT hrCoInit;
2431 DWORD dwError;
2432 ULONG fOldMask;
2433
2434 if (sei->cbSize != sizeof(SHELLEXECUTEINFOW))
2435 {
2438 return FALSE;
2439 }
2440
2441 hrCoInit = SHCoInitializeAnyApartment();
2442
2443 if (SHRegGetBoolUSValueW(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
2444 L"MaximizeApps", FALSE, FALSE))
2445 {
2446 switch (sei->nShow)
2447 {
2448 case SW_SHOW:
2449 case SW_SHOWDEFAULT:
2450 case SW_SHOWNORMAL:
2451 case SW_RESTORE:
2452 sei->nShow = SW_SHOWMAXIMIZED;
2453 break;
2454 default:
2455 break;
2456 }
2457 }
2458
2459 fOldMask = sei->fMask;
2460
2461 if (!(fOldMask & SEE_MASK_NOASYNC) && SHELL_InRunDllProcess())
2463
2464 dwError = ShellExecute_Normal(sei);
2465
2466 if (dwError && dwError != ERROR_DLL_NOT_FOUND && dwError != ERROR_CANCELLED)
2467 ShellExecute_ShowError(sei, NULL, dwError);
2468
2469 sei->fMask = fOldMask;
2470
2471 if (SUCCEEDED(hrCoInit))
2473
2474 if (dwError)
2475 SetLastError(dwError);
2476
2477 return dwError == ERROR_SUCCESS;
2478}
2479
2480/*************************************************************************
2481 * ShellExecuteW [SHELL32.294]
2482 * from shellapi.h
2483 * WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpVerb,
2484 * LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
2485 */
2487 LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
2488{
2490
2491 TRACE("\n");
2492 sei.cbSize = sizeof(sei);
2494 sei.hwnd = hwnd;
2495 sei.lpVerb = lpVerb;
2496 sei.lpFile = lpFile;
2497 sei.lpParameters = lpParameters;
2499 sei.nShow = nShowCmd;
2500 sei.lpIDList = 0;
2501 sei.lpClass = 0;
2502 sei.hkeyClass = 0;
2503 sei.dwHotKey = 0;
2504 sei.hProcess = 0;
2505
2507 return sei.hInstApp;
2508}
2509
2510/*************************************************************************
2511 * WOWShellExecute [SHELL32.@]
2512 *
2513 * FIXME: the callback function most likely doesn't work the same way on Windows.
2514 */
2516 LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd, void *callback)
2517{
2518 SHELLEXECUTEINFOW seiW;
2519 WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL;
2520 HANDLE hProcess = 0;
2521
2522 seiW.lpVerb = lpVerb ? __SHCloneStrAtoW(&wVerb, lpVerb) : NULL;
2523 seiW.lpFile = lpFile ? __SHCloneStrAtoW(&wFile, lpFile) : NULL;
2524 seiW.lpParameters = lpParameters ? __SHCloneStrAtoW(&wParameters, lpParameters) : NULL;
2525 seiW.lpDirectory = lpDirectory ? __SHCloneStrAtoW(&wDirectory, lpDirectory) : NULL;
2526
2527 seiW.cbSize = sizeof(seiW);
2528 seiW.fMask = 0;
2529 seiW.hwnd = hWnd;
2530 seiW.nShow = iShowCmd;
2531 seiW.lpIDList = 0;
2532 seiW.lpClass = 0;
2533 seiW.hkeyClass = 0;
2534 seiW.dwHotKey = 0;
2535 seiW.hProcess = hProcess;
2536
2538
2539 SHFree(wVerb);
2540 SHFree(wFile);
2541 SHFree(wParameters);
2542 SHFree(wDirectory);
2543 return seiW.hInstApp;
2544}
2545
2546/*************************************************************************
2547 * OpenAs_RunDLLW [SHELL32.@]
2548 */
2549EXTERN_C void WINAPI
2551{
2553 TRACE("%p, %p, %s, %d\n", hwnd, hinst, debugstr_w(cmdline), cmdshow);
2554
2555 ZeroMemory(&info, sizeof(info));
2556 info.pcszFile = cmdline;
2557 info.pcszClass = NULL;
2559
2561}
2562
2563/*************************************************************************
2564 * OpenAs_RunDLLA [SHELL32.@]
2565 */
2566EXTERN_C void WINAPI
2568{
2569 LPWSTR pszCmdLineW = NULL;
2570 TRACE("%p, %p, %s, %d\n", hwnd, hinst, debugstr_a(cmdline), cmdshow);
2571
2572 if (cmdline)
2573 __SHCloneStrAtoW(&pszCmdLineW, cmdline);
2574 OpenAs_RunDLLW(hwnd, hinst, pszCmdLineW, cmdshow);
2575 SHFree(pszCmdLineW);
2576}
2577
2578/*************************************************************************/
2579
2580static LPCWSTR
2581SplitParams(LPCWSTR psz, LPWSTR pszArg0, size_t cchArg0)
2582{
2583 LPCWSTR pch;
2584 size_t ich = 0;
2585 if (*psz == L'"')
2586 {
2587 // 1st argument is quoted. the string in quotes is quoted 1st argument.
2588 // [pch] --> [pszArg0+ich]
2589 for (pch = psz + 1; *pch && ich + 1 < cchArg0; ++ich, ++pch)
2590 {
2591 if (*pch == L'"' && pch[1] == L'"')
2592 {
2593 // doubled double quotations found!
2594 pszArg0[ich] = L'"';
2595 }
2596 else if (*pch == L'"')
2597 {
2598 // single double quotation found!
2599 ++pch;
2600 break;
2601 }
2602 else
2603 {
2604 // otherwise
2605 pszArg0[ich] = *pch;
2606 }
2607 }
2608 }
2609 else
2610 {
2611 // 1st argument is unquoted. non-space sequence is 1st argument.
2612 // [pch] --> [pszArg0+ich]
2613 for (pch = psz; *pch && !iswspace(*pch) && ich + 1 < cchArg0; ++ich, ++pch)
2614 {
2615 pszArg0[ich] = *pch;
2616 }
2617 }
2618 pszArg0[ich] = 0;
2619
2620 // skip space
2621 while (iswspace(*pch))
2622 ++pch;
2623
2624 return pch;
2625}
2626
2628 HWND hwnd,
2629 LPCWSTR pwszCommand,
2630 LPCWSTR pwszStartDir,
2631 int nShow,
2632 LPVOID pUnused,
2633 DWORD dwSeclFlags)
2634{
2637 LPCWSTR pszVerb = NULL;
2638 WCHAR szFile[MAX_PATH], szFile2[MAX_PATH];
2639 HRESULT hr;
2640 LPCWSTR pchParams;
2641 LPWSTR lpCommand = NULL;
2642
2643 if (pwszCommand == NULL)
2645 1, (ULONG_PTR*)pwszCommand);
2646
2647 __SHCloneStrW(&lpCommand, pwszCommand);
2648 StrTrimW(lpCommand, L" \t");
2649
2650 if (dwSeclFlags & SECL_NO_UI)
2652 if (dwSeclFlags & SECL_LOG_USAGE)
2654 if (dwSeclFlags & SECL_USE_IDLIST)
2656
2657 if (dwSeclFlags & SECL_RUNAS)
2658 {
2659 dwSize = 0;
2660 hr = AssocQueryStringW(ASSOCF_NONE, ASSOCSTR_COMMAND, lpCommand, L"RunAs", NULL, &dwSize);
2661 if (SUCCEEDED(hr) && dwSize != 0)
2662 {
2663 pszVerb = L"runas";
2664 }
2665 }
2666
2667 if (PathIsURLW(lpCommand) || UrlIsW(lpCommand, URLIS_APPLIABLE))
2668 {
2669 StringCchCopyW(szFile, _countof(szFile), lpCommand);
2670 pchParams = NULL;
2671 }
2672 else
2673 {
2674 PCWSTR apPathList[2];
2675
2676 pchParams = SplitParams(lpCommand, szFile, _countof(szFile));
2677 if (szFile[0] != UNICODE_NULL && szFile[1] == L':' &&
2678 szFile[2] == UNICODE_NULL)
2679 {
2680 PathAddBackslashW(szFile);
2681 }
2682
2683 WCHAR szCurDir[MAX_PATH];
2684 GetCurrentDirectoryW(_countof(szCurDir), szCurDir);
2685 if (pwszStartDir)
2686 {
2687 SetCurrentDirectoryW(pwszStartDir);
2688 }
2689
2690 if (PathIsRelativeW(szFile) &&
2691 GetFullPathNameW(szFile, _countof(szFile2), szFile2, NULL) &&
2692 PathFileExistsW(szFile2))
2693 {
2694 StringCchCopyW(szFile, _countof(szFile), szFile2);
2695 }
2696
2697 apPathList[0] = pwszStartDir;
2698 apPathList[1] = NULL;
2699 PathFindOnPathExW(szFile, apPathList, WHICH_DEFAULT);
2700
2701 if (!(dwSeclFlags & SECL_ALLOW_NONEXE))
2702 {
2703 if (!GetBinaryTypeW(szFile, &dwType))
2704 {
2705 SHFree(lpCommand);
2706
2707 if (!(dwSeclFlags & SECL_NO_UI))
2708 {
2709 WCHAR szText[128 + MAX_PATH], szFormat[128];
2711 StringCchPrintfW(szText, _countof(szText), szFormat, szFile);
2712 MessageBoxW(hwnd, szText, NULL, MB_ICONERROR);
2713 }
2714 return CO_E_APPNOTFOUND;
2715 }
2716 }
2717 else
2718 {
2720 {
2721 SHFree(lpCommand);
2722
2723 if (!(dwSeclFlags & SECL_NO_UI))
2724 {
2725 WCHAR szText[128 + MAX_PATH], szFormat[128];
2727 StringCchPrintfW(szText, _countof(szText), szFormat, szFile);
2728 MessageBoxW(hwnd, szText, NULL, MB_ICONERROR);
2729 }
2731 }
2732 }
2733 }
2734
2735 ZeroMemory(&info, sizeof(info));
2736 info.cbSize = sizeof(info);
2737 info.fMask = dwFlags;
2738 info.hwnd = hwnd;
2739 info.lpVerb = pszVerb;
2740 info.lpFile = szFile;
2741 info.lpParameters = (pchParams && *pchParams) ? pchParams : NULL;
2742 info.lpDirectory = pwszStartDir;
2743 info.nShow = nShow;
2744 if (ShellExecuteExW(&info))
2745 {
2746 if (info.lpIDList)
2747 CoTaskMemFree(info.lpIDList);
2748
2749 SHFree(lpCommand);
2750
2751 return S_OK;
2752 }
2753
2754 dwError = GetLastError();
2755
2756 SHFree(lpCommand);
2757
2758 return HRESULT_FROM_WIN32(dwError);
2759}
2760
2761/*************************************************************************
2762 * RealShellExecuteExA (SHELL32.266)
2763 */
2768 _In_opt_ LPCSTR lpOperation,
2769 _In_opt_ LPCSTR lpFile,
2770 _In_opt_ LPCSTR lpParameters,
2772 _In_opt_ LPSTR lpReturn,
2774 _In_opt_ LPVOID lpReserved,
2775 _In_ INT nCmdShow,
2776 _Out_opt_ PHANDLE lphProcess,
2778{
2779 SHELLEXECUTEINFOA ExecInfo;
2780
2781 TRACE("(%p, %s, %s, %s, %s, %p, %s, %p, %u, %p, %lu)\n",
2782 hwnd, debugstr_a(lpOperation), debugstr_a(lpFile), debugstr_a(lpParameters),
2784 lpReserved, nCmdShow, lphProcess, dwFlags);
2785
2786 ZeroMemory(&ExecInfo, sizeof(ExecInfo));
2787 ExecInfo.cbSize = sizeof(ExecInfo);
2789 ExecInfo.hwnd = hwnd;
2790 ExecInfo.lpVerb = lpOperation;
2791 ExecInfo.lpFile = lpFile;
2792 ExecInfo.lpParameters = lpParameters;
2793 ExecInfo.lpDirectory = lpDirectory;
2794 ExecInfo.nShow = (WORD)nCmdShow;
2795
2796 if (lpReserved)
2797 {
2798 ExecInfo.fMask |= SEE_MASK_USE_RESERVED;
2799 ExecInfo.hInstApp = (HINSTANCE)lpReserved;
2800 }
2801
2802 if (lpTitle)
2803 {
2804 ExecInfo.fMask |= SEE_MASK_HASTITLE;
2805 ExecInfo.lpClass = lpTitle;
2806 }
2807
2808 if (dwFlags & 1)
2809 ExecInfo.fMask |= SEE_MASK_FLAG_SEPVDM;
2810
2811 if (dwFlags & 2)
2812 ExecInfo.fMask |= SEE_MASK_NO_CONSOLE;
2813
2814 if (lphProcess == NULL)
2815 {
2816 ShellExecuteExA(&ExecInfo);
2817 }
2818 else
2819 {
2820 ExecInfo.fMask |= SEE_MASK_NOCLOSEPROCESS;
2821 ShellExecuteExA(&ExecInfo);
2822 *lphProcess = ExecInfo.hProcess;
2823 }
2824
2825 return ExecInfo.hInstApp;
2826}
2827
2828/*************************************************************************
2829 * RealShellExecuteExW (SHELL32.267)
2830 */
2835 _In_opt_ LPCWSTR lpOperation,
2836 _In_opt_ LPCWSTR lpFile,
2837 _In_opt_ LPCWSTR lpParameters,
2839 _In_opt_ LPWSTR lpReturn,
2841 _In_opt_ LPVOID lpReserved,
2842 _In_ INT nCmdShow,
2843 _Out_opt_ PHANDLE lphProcess,
2845{
2846 SHELLEXECUTEINFOW ExecInfo;
2847
2848 TRACE("(%p, %s, %s, %s, %s, %p, %s, %p, %u, %p, %lu)\n",
2849 hwnd, debugstr_w(lpOperation), debugstr_w(lpFile), debugstr_w(lpParameters),
2851 lpReserved, nCmdShow, lphProcess, dwFlags);
2852
2853 ZeroMemory(&ExecInfo, sizeof(ExecInfo));
2854 ExecInfo.cbSize = sizeof(ExecInfo);
2856 ExecInfo.hwnd = hwnd;
2857 ExecInfo.lpVerb = lpOperation;
2858 ExecInfo.lpFile = lpFile;
2859 ExecInfo.lpParameters = lpParameters;
2860 ExecInfo.lpDirectory = lpDirectory;
2861 ExecInfo.nShow = (WORD)nCmdShow;
2862
2863 if (lpReserved)
2864 {
2865 ExecInfo.fMask |= SEE_MASK_USE_RESERVED;
2866 ExecInfo.hInstApp = (HINSTANCE)lpReserved;
2867 }
2868
2869 if (lpTitle)
2870 {
2871 ExecInfo.fMask |= SEE_MASK_HASTITLE;
2872 ExecInfo.lpClass = lpTitle;
2873 }
2874
2875 if (dwFlags & 1)
2876 ExecInfo.fMask |= SEE_MASK_FLAG_SEPVDM;
2877
2878 if (dwFlags & 2)
2879 ExecInfo.fMask |= SEE_MASK_NO_CONSOLE;
2880
2881 if (lphProcess == NULL)
2882 {
2883 ShellExecuteExW(&ExecInfo);
2884 }
2885 else
2886 {
2887 ExecInfo.fMask |= SEE_MASK_NOCLOSEPROCESS;
2888 ShellExecuteExW(&ExecInfo);
2889 *lphProcess = ExecInfo.hProcess;
2890 }
2891
2892 return ExecInfo.hInstApp;
2893}
2894
2895/*************************************************************************
2896 * RealShellExecuteA (SHELL32.265)
2897 */
2902 _In_opt_ LPCSTR lpOperation,
2903 _In_opt_ LPCSTR lpFile,
2904 _In_opt_ LPCSTR lpParameters,
2906 _In_opt_ LPSTR lpReturn,
2908 _In_opt_ LPVOID lpReserved,
2909 _In_ INT nCmdShow,
2910 _Out_opt_ PHANDLE lphProcess)
2911{
2913 lpOperation,
2914 lpFile,
2915 lpParameters,
2917 lpReturn,
2918 lpTitle,
2919 lpReserved,
2920 nCmdShow,
2921 lphProcess,
2922 0);
2923}
2924
2925/*************************************************************************
2926 * RealShellExecuteW (SHELL32.268)
2927 */
2932 _In_opt_ LPCWSTR lpOperation,
2933 _In_opt_ LPCWSTR lpFile,
2934 _In_opt_ LPCWSTR lpParameters,
2936 _In_opt_ LPWSTR lpReturn,
2938 _In_opt_ LPVOID lpReserved,
2939 _In_ INT nCmdShow,
2940 _Out_opt_ PHANDLE lphProcess)
2941{
2943 lpOperation,
2944 lpFile,
2945 lpParameters,
2947 lpReturn,
2948 lpTitle,
2949 lpReserved,
2950 nCmdShow,
2951 lphProcess,
2952 0);
2953}
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 UlongToHandle(ul)
Definition: basetsd.h:97
#define EXTERN_C
Definition: basetyps.h:12
#define FIXME(fmt,...)
Definition: debug.h:114
#define WARN(fmt,...)
Definition: debug.h:115
#define ERR(fmt,...)
Definition: debug.h:113
#define RegCloseKey(hKey)
Definition: registry.h:49
r l[0]
Definition: byte_order.h:168
Definition: bufpool.h:45
void Attach(T *lp)
Definition: atlalloc.h:162
TCHAR lpTitle[80]
Definition: ctm.c:69
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:170
HDDEDATA WINAPI DdeClientTransaction(LPBYTE, DWORD, HCONV, HSZ, UINT, UINT, DWORD, LPDWORD)
Definition: ddeclient.c:1122
#define DMLERR_NO_ERROR
Definition: ddeml.h:242
BOOL WINAPI DdeUninitialize(DWORD)
Definition: ddemisc.c:1112
UINT WINAPI DdeInitializeW(LPDWORD, PFNCALLBACK, DWORD, DWORD)
Definition: ddemisc.c:1095
HCONV WINAPI DdeConnect(DWORD, HSZ, HSZ, PCONVCONTEXT)
Definition: ddeclient.c:84
UINT WINAPI DdeGetLastError(DWORD)
Definition: ddemisc.c:253
HSZ WINAPI DdeCreateStringHandleW(DWORD, LPCWSTR, INT)
Definition: ddemisc.c:608
BOOL WINAPI DdeDisconnect(HCONV)
Definition: ddeclient.c:1363
#define XTYP_EXECUTE
Definition: ddeml.h:185
#define CP_WINUNICODE
Definition: ddeml.h:33
BOOL WINAPI DdeFreeDataHandle(HDDEDATA)
Definition: ddemisc.c:1461
#define APPCMD_CLIENTONLY
Definition: ddeml.h:122
UINT WINAPI DdeInitializeA(LPDWORD, PFNCALLBACK, DWORD, DWORD)
Definition: ddemisc.c:1075
#define E_FAIL
Definition: ddrawi.h:102
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3268
LSTATUS WINAPI RegQueryValueW(HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count)
Definition: reg.c:4241
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
LONG WINAPI RegEnumKeyW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, DWORD cbName)
Definition: reg.c:2393
LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
Definition: string.c:384
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define wcsrchr
Definition: compat.h:16
#define CP_ACP
Definition: compat.h:109
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:755
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
#define WideCharToMultiByte
Definition: compat.h:111
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define wcsicmp
Definition: compat.h:15
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static const WCHAR *const ext[]
Definition: module.c:53
#define FAILED_UNEXPECTEDLY(hr)
Definition: precomp.h:121
BOOL WINAPI FreeEnvironmentStringsW(IN LPWSTR EnvironmentStrings)
Definition: environ.c:389
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
VOID WINAPI RaiseException(_In_ DWORD dwExceptionCode, _In_ DWORD dwExceptionFlags, _In_ DWORD nNumberOfArguments, _In_opt_ const ULONG_PTR *lpArguments)
Definition: except.c:700
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
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
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
HRESULT SHCoInitializeAnyApartment(VOID)
Definition: utils.cpp:270
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:326
BOOL WINAPI PathResolveW(_Inout_ LPWSTR path, _Inout_opt_ LPCWSTR *dirs, _In_ DWORD flags)
Definition: shellpath.c:883
HRESULT WINAPI AssocQueryStringW(ASSOCF cfFlags, ASSOCSTR str, LPCWSTR pszAssoc, LPCWSTR pszExtra, LPWSTR pszOut, DWORD *pcchOut)
Definition: assoc.c:436
HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
Definition: ordinal.c:165
PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
Definition: ordinal.c:255
BOOL WINAPI SHUnlockShared(LPVOID lpView)
Definition: ordinal.c:291
HRESULT WINAPI PathCreateFromUrlW(LPCWSTR pszUrl, LPWSTR pszPath, LPDWORD pcchPath, DWORD dwReserved)
Definition: path.c:3355
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:394
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
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:1392
HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
Definition: pidl.c:1348
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
Definition: pidl.c:1340
LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path)
Definition: pidl.c:995
static const WCHAR szName[]
Definition: powrprof.c:45
static const char topic[]
Definition: propsys.c:44
#define strncmpiW(s1, s2, n)
Definition: unicode.h: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:133
BOOL HCR_GetExecuteCommandW(HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len)
Definition: classes.c:197
static __inline void __SHCloneStrWtoA(char **target, const WCHAR *source)
Definition: shell32_main.h:157
static __inline LPWSTR __SHCloneStrAtoW(WCHAR **target, const char *source)
Definition: shell32_main.h:170
static __inline void __SHCloneStrW(WCHAR **target, const WCHAR *source)
Definition: shell32_main.h:164
#define SEE_MASK_FLAG_LOG_USAGE
Definition: shellapi.h:59
#define SEE_MASK_DOENVSUBST
Definition: shellapi.h:35
#define SEE_MASK_USE_RESERVED
Definition: shellapi.h:51
#define SEE_MASK_ICON
Definition: shellapi.h:29
#define SEE_MASK_FLAG_SEPVDM
Definition: shellapi.h:50
#define SEE_MASK_CLASSKEY
Definition: shellapi.h:26
#define SEE_MASK_HOTKEY
Definition: shellapi.h:30
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
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:1642
static HRESULT ShellExecute_ContextMenuVerb(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1545
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExA(LPSHELLEXECUTEINFOA sei)
Definition: shlexec.cpp:2370
HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpResult)
Definition: shlexec.cpp:1271
static HRESULT shellex_load_object_and_run(HKEY hkey, LPCGUID guid, LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1472
static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR lpstrProtocol, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
Definition: shlexec.cpp:1744
static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
Definition: shlexec.cpp:49
EXTERN_C void WINAPI OpenAs_RunDLLA(HWND hwnd, HINSTANCE hinst, LPCSTR cmdline, int cmdshow)
Definition: shlexec.cpp:2567
static LPCWSTR SplitParams(LPCWSTR psz, LPWSTR pszArg0, size_t cchArg0)
Definition: shlexec.cpp:2581
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:2833
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:1169
EXTERN_C void WINAPI OpenAs_RunDLLW(HWND hwnd, HINSTANCE hinst, LPCWSTR cmdline, int cmdshow)
Definition: shlexec.cpp:2550
static LONG ShellExecute_FromContextMenuHandlers(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1598
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:2349
EXTERN_C HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpVerb, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd, void *callback)
Definition: shlexec.cpp:2515
static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
Definition: shlexec.cpp:1858
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:1835
HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
Definition: shlexec.cpp:1228
static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
Definition: shlexec.cpp:1780
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:2356
EXTERN_C BOOL PathIsExeW(LPCWSTR lpszPath)
Definition: shellpath.c:539
static HRESULT shellex_run_context_menu_default(IShellExtInit *obj, LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:1403
static void do_error_dialog(UINT_PTR retval, HWND hwnd, WCHAR *filename)
Definition: shlexec.cpp:1814
HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpVerb, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
Definition: shlexec.cpp:2486
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:1698
static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei)
Definition: shlexec.cpp:1323
static HRESULT shellex_get_contextmenu(LPSHELLEXECUTEINFOW sei, CComPtr< IContextMenu > &cm)
Definition: shlexec.cpp:1506
EXTERN_C HINSTANCE WINAPI RealShellExecuteA(_In_opt_ HWND hwnd, _In_opt_ LPCSTR lpOperation, _In_opt_ LPCSTR lpFile, _In_opt_ LPCSTR lpParameters, _In_opt_ LPCSTR lpDirectory, _In_opt_ LPSTR lpReturn, _In_opt_ LPCSTR lpTitle, _In_opt_ LPVOID lpReserved, _In_ INT nCmdShow, _Out_opt_ PHANDLE lphProcess)
Definition: shlexec.cpp:2900
static HRESULT shellex_get_dataobj(LPSHELLEXECUTEINFOW sei, CComPtr< IDataObject > &dataObj)
Definition: shlexec.cpp:1371
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2428
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:2321
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:2766
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:2930
HRESULT hr
Definition: shlfolder.c:183
@ OAIF_EXEC
Definition: shlobj.h:2668
@ OAIF_REGISTER_EXT
Definition: shlobj.h:2667
@ OAIF_ALLOW_REGISTRATION
Definition: shlobj.h:2666
#define UrlIsFileUrlW(x)
Definition: shlwapi.h:1377
@ ASSOCSTR_COMMAND
Definition: shlwapi.h:603
@ ASSOCSTR_EXECUTABLE
Definition: shlwapi.h:604
@ URLIS_APPLIABLE
Definition: shlwapi.h:1195
@ ASSOCF_NONE
Definition: shlwapi.h:581
#define WHICH_DEFAULT
#define IDS_FILE_NOT_FOUND
Definition: shresdef.h:339
#define IDS_SHLEXEC_NOASSOC
Definition: shresdef.h:186
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define _countof(array)
Definition: sndvol32.h: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 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