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