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