2 * Open With Context Menu extension
4 * Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org>
5 * Copyright 2009 Andrew Hill
6 * Copyright 2012 Rafal Harabien
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.
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.
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
25 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
28 // [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system]
29 // "NoInternetOpenWith"=dword:00000001
32 EXTERN_C BOOL
PathIsExeW(LPCWSTR lpszPath
);
39 WCHAR wszFilename
[MAX_PATH
];
40 WCHAR wszCmd
[MAX_PATH
];
41 //WCHAR wszManufacturer[256];
53 SApp
*Add(LPCWSTR pwszPath
);
54 static BOOL
SaveApp(SApp
*pApp
);
55 SApp
*Find(LPCWSTR pwszFilename
);
56 static LPCWSTR
GetName(SApp
*pApp
);
57 static HICON
GetIcon(SApp
*pApp
);
58 static BOOL
Execute(SApp
*pApp
, LPCWSTR pwszFilePath
);
59 static BOOL
IsHidden(SApp
*pApp
);
60 inline BOOL
IsNoOpen(VOID
) { return m_bNoOpen
; }
61 BOOL
LoadRecommended(LPCWSTR pwszFilePath
);
62 BOOL
SetDefaultHandler(SApp
*pApp
, LPCWSTR pwszFilename
);
64 inline SApp
*GetList() { return m_pApp
; }
65 inline UINT
GetCount() { return m_cApp
; }
66 inline UINT
GetRecommendedCount() { return m_cRecommended
; }
69 typedef struct _LANGANDCODEPAGE
73 } LANGANDCODEPAGE
, *LPLANGANDCODEPAGE
;
76 UINT m_cApp
, m_cRecommended
;
79 SApp
*AddInternal(LPCWSTR pwszFilename
);
80 static BOOL
LoadInfo(SApp
*pApp
);
81 static VOID
GetPathFromCmd(LPWSTR pwszAppPath
, LPCWSTR pwszCmd
);
82 BOOL
LoadProgIdList(HKEY hKey
, LPCWSTR pwszExt
);
83 static HANDLE
OpenMRUList(HKEY hKey
);
84 BOOL
LoadMRUList(HKEY hKey
);
85 BOOL
LoadAppList(HKEY hKey
);
86 VOID
LoadFromProgIdKey(HKEY hKey
, LPCWSTR pwszExt
);
87 VOID
LoadRecommendedFromHKCR(LPCWSTR pwszExt
);
88 VOID
LoadRecommendedFromHKCU(LPCWSTR pwszExt
);
89 static BOOL
AddAppToMRUList(SApp
*pApp
, LPCWSTR pwszFilename
);
91 inline VOID
SetRecommended(SApp
*pApp
)
93 if (!pApp
->bRecommended
)
95 pApp
->bRecommended
= TRUE
;
99 COpenWithList::COpenWithList():
100 m_pApp(NULL
), m_cApp(0), m_cRecommended(0), m_bNoOpen(FALSE
) {}
102 COpenWithList::~COpenWithList()
104 for (UINT i
= 0; i
< m_cApp
; ++i
)
106 DestroyIcon(m_pApp
[i
].hIcon
);
108 HeapFree(GetProcessHeap(), 0, m_pApp
);
111 BOOL
COpenWithList::Load()
114 WCHAR wszName
[256], wszBuf
[100];;
115 DWORD i
= 0, cchName
, dwSize
;
118 if (RegOpenKeyEx(HKEY_CLASSES_ROOT
, L
"Applications", 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
120 ERR("RegOpenKeyEx HKCR\\Applications failed!\n");
126 cchName
= _countof(wszName
);
127 if (RegEnumKeyEx(hKey
, i
++, wszName
, &cchName
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
130 pApp
= AddInternal(wszName
);
134 StringCbPrintfW(wszBuf
, sizeof(wszBuf
), L
"%s\\shell\\open\\command", wszName
);
135 dwSize
= sizeof(pApp
->wszCmd
);
136 if (RegGetValueW(hKey
, wszBuf
, L
"", RRF_RT_REG_SZ
, NULL
, pApp
->wszCmd
, &dwSize
) != ERROR_SUCCESS
)
138 ERR("Failed to add app %ls\n", wszName
);
139 pApp
->bHidden
= TRUE
;
142 TRACE("App added %ls\n", pApp
->wszCmd
);
145 ERR("AddInternal failed\n");
152 COpenWithList::SApp
*COpenWithList::Add(LPCWSTR pwszPath
)
154 SApp
*pApp
= AddInternal(PathFindFileNameW(pwszPath
));
158 StringCbPrintfW(pApp
->wszCmd
, sizeof(pApp
->wszCmd
), L
"\"%s\" %%1", pwszPath
);
165 BOOL
COpenWithList::SaveApp(SApp
*pApp
)
170 StringCbPrintfW(wszBuf
, sizeof(wszBuf
), L
"Applications\\%s\\shell\\open\\command", pApp
->wszFilename
);
171 if (RegCreateKeyEx(HKEY_CLASSES_ROOT
, wszBuf
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
173 ERR("RegOpenKeyEx failed\n");
177 if (RegSetValueEx(hKey
, L
"", 0, REG_SZ
, (PBYTE
)pApp
->wszCmd
, (wcslen(pApp
->wszCmd
)+1)*sizeof(WCHAR
)) != ERROR_SUCCESS
)
178 ERR("Cannot add app to registry\n");
184 COpenWithList::SApp
*COpenWithList::Find(LPCWSTR pwszFilename
)
186 for (UINT i
= 0; i
< m_cApp
; ++i
)
187 if (wcsicmp(m_pApp
[i
].wszFilename
, pwszFilename
) == 0)
192 LPCWSTR
COpenWithList::GetName(SApp
*pApp
)
194 if (!pApp
->wszName
[0])
198 WARN("Failed to load %ls info\n", pApp
->wszFilename
);
199 StringCbCopyW(pApp
->wszName
, sizeof(pApp
->wszName
), pApp
->wszFilename
);
203 TRACE("%ls name: %ls\n", pApp
->wszFilename
, pApp
->wszName
);
204 return pApp
->wszName
;
207 HICON
COpenWithList::GetIcon(SApp
*pApp
)
211 WCHAR wszPath
[MAX_PATH
];
213 GetPathFromCmd(wszPath
, pApp
->wszCmd
);
214 ExtractIconExW(wszPath
, 0, NULL
, &pApp
->hIcon
, 1);
217 TRACE("%ls icon: %p\n", pApp
->wszFilename
, pApp
->hIcon
);
222 BOOL
COpenWithList::Execute(COpenWithList::SApp
*pApp
, LPCWSTR pwszFilePath
)
225 PROCESS_INFORMATION pi
;
226 WCHAR wszBuf
[MAX_PATH
* 2 + 8], *pszEnd
= wszBuf
;
227 size_t cchRemaining
= _countof(wszBuf
);
229 /* setup path with argument */
230 ZeroMemory(&si
, sizeof(STARTUPINFOW
));
231 si
.cb
= sizeof(STARTUPINFOW
);
233 /* Build the command line */
234 for (UINT i
= 0; pApp
->wszCmd
[i
] && cchRemaining
> 1; ++i
)
236 if (pApp
->wszCmd
[i
] != '%')
238 *(pszEnd
++) = pApp
->wszCmd
[i
];
241 else if (pApp
->wszCmd
[++i
] == '1')
243 if (StrChrW(pwszFilePath
, L
' ') && cchRemaining
> 3)
244 StringCchPrintfExW(pszEnd
, cchRemaining
, &pszEnd
, &cchRemaining
, 0, L
"\"%ls\"", pwszFilePath
);
246 StringCchCopyExW(pszEnd
, cchRemaining
, pwszFilePath
, &pszEnd
, &cchRemaining
, 0);
249 /* NULL-terminate the command string */
250 if (cchRemaining
> 0)
253 /* Start the application now */
254 TRACE("Starting process %ls\n", wszBuf
);
255 if (!CreateProcessW(NULL
, wszBuf
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
257 ERR("CreateProcessW %ls failed\n", wszBuf
);
261 /* Add app to registry if it wasnt there before */
264 AddAppToMRUList(pApp
, pwszFilePath
);
266 CloseHandle(pi
.hThread
);
267 CloseHandle(pi
.hProcess
);
271 BOOL
COpenWithList::IsHidden(SApp
*pApp
)
277 return pApp
->bHidden
;
279 if (FAILED(StringCbPrintfW(wszBuf
, sizeof(wszBuf
), L
"Applications\\%s", pApp
->wszFilename
)))
281 ERR("insufficient buffer\n");
285 if (RegGetValueW(HKEY_CLASSES_ROOT
, wszBuf
, L
"NoOpenWith", RRF_RT_REG_SZ
, NULL
, NULL
, &dwSize
) != ERROR_SUCCESS
)
288 pApp
->bHidden
= TRUE
;
292 COpenWithList::SApp
*COpenWithList::AddInternal(LPCWSTR pwszFilename
)
294 /* Check for duplicate */
295 SApp
*pApp
= Find(pwszFilename
);
299 /* Create new item */
301 m_pApp
= static_cast<SApp
*>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(m_pApp
[0])));
303 m_pApp
= static_cast<SApp
*>(HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, m_pApp
, (m_cApp
+ 1)*sizeof(m_pApp
[0])));
306 ERR("Allocation failed\n");
310 pApp
= &m_pApp
[m_cApp
++];
311 wcscpy(pApp
->wszFilename
, pwszFilename
);
315 BOOL
COpenWithList::LoadInfo(COpenWithList::SApp
*pApp
)
319 WORD wLang
= 0, wCode
= 0;
320 LPLANGANDCODEPAGE lpLangCode
;
323 WCHAR wszPath
[MAX_PATH
];
325 GetPathFromCmd(wszPath
, pApp
->wszCmd
);
326 TRACE("LoadInfo %ls\n", wszPath
);
328 /* query version info size */
329 cbSize
= GetFileVersionInfoSizeW(wszPath
, NULL
);
332 ERR("GetFileVersionInfoSizeW %ls failed: %lu\n", wszPath
, GetLastError());
336 /* allocate buffer */
337 pBuf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbSize
+ 200);
340 ERR("HeapAlloc failed\n");
344 /* query version info */
345 if (!GetFileVersionInfoW(wszPath
, 0, cbSize
, pBuf
))
347 ERR("GetFileVersionInfoW %ls failed: %lu\n", wszPath
, GetLastError());
348 HeapFree(GetProcessHeap(), 0, pBuf
);
352 /* query lang code */
353 if (VerQueryValueW(pBuf
, L
"VarFileInfo\\Translation", (LPVOID
*)&lpLangCode
, &cbSize
))
355 /* FIXME: find language from current locale / if not available,
357 * for now default to first available language
359 wLang
= lpLangCode
->lang
;
360 wCode
= lpLangCode
->code
;
364 swprintf(wszBuf
, L
"\\StringFileInfo\\%04x%04x\\FileDescription", wLang
, wCode
);
365 if (VerQueryValueW(pBuf
, wszBuf
, (LPVOID
*)&pResult
, &cchLen
))
366 StringCchCopyNW(pApp
->wszName
, _countof(pApp
->wszName
), pResult
, cchLen
);
368 ERR("Cannot get app name\n");
370 /* Query manufacturer */
371 /*swprintf(wszBuf, L"\\StringFileInfo\\%04x%04x\\CompanyName", wLang, wCode);
373 if (VerQueryValueW(pBuf, wszBuf, (LPVOID *)&pResult, &cchLen))
374 StringCchCopyNW(pApp->wszManufacturer, _countof(pApp->wszManufacturer), pResult, cchLen);*/
375 HeapFree(GetProcessHeap(), 0, pBuf
);
379 VOID
COpenWithList::GetPathFromCmd(LPWSTR pwszAppPath
, LPCWSTR pwszCmd
)
381 WCHAR wszBuf
[MAX_PATH
], *pwszDest
= wszBuf
;
383 /* Remove arguments */
384 if (pwszCmd
[0] == '"')
386 for(LPCWSTR pwszSrc
= pwszCmd
+ 1; *pwszSrc
&& *pwszSrc
!= '"'; ++pwszSrc
)
387 *(pwszDest
++) = *pwszSrc
;
391 for(LPCWSTR pwszSrc
= pwszCmd
; *pwszSrc
&& *pwszSrc
!= ' '; ++pwszSrc
)
392 *(pwszDest
++) = *pwszSrc
;
397 /* Expand evn vers and optionally search for path */
398 ExpandEnvironmentStrings(wszBuf
, pwszAppPath
, MAX_PATH
);
399 if (!PathFileExists(pwszAppPath
))
400 SearchPath(NULL
, pwszAppPath
, NULL
, MAX_PATH
, pwszAppPath
, NULL
);
403 BOOL
COpenWithList::LoadRecommended(LPCWSTR pwszFilePath
)
407 pwszExt
= PathFindExtensionW(pwszFilePath
);
411 /* load programs directly associated from HKCU */
412 LoadRecommendedFromHKCU(pwszExt
);
414 /* load programs associated from HKCR\Extension */
415 LoadRecommendedFromHKCR(pwszExt
);
420 BOOL
COpenWithList::LoadProgIdList(HKEY hKey
, LPCWSTR pwszExt
)
422 HKEY hSubkey
, hSubkey2
;
423 WCHAR wszProgId
[256];
424 DWORD i
= 0, cchProgId
;
426 if (RegOpenKeyExW(hKey
, L
"OpenWithProgIDs", 0, KEY_READ
, &hSubkey
) != ERROR_SUCCESS
)
431 /* Enumerate values - value name is ProgId */
432 cchProgId
= _countof(wszProgId
);
433 if (RegEnumValue(hSubkey
, i
++, wszProgId
, &cchProgId
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
436 /* If ProgId exists load it */
437 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszProgId
, 0, KEY_READ
, &hSubkey2
) == ERROR_SUCCESS
)
439 LoadFromProgIdKey(hSubkey2
, pwszExt
);
440 RegCloseKey(hSubkey2
);
444 RegCloseKey(hSubkey
);
448 HANDLE
COpenWithList::OpenMRUList(HKEY hKey
)
452 /* Initialize mru list info */
453 Info
.cbSize
= sizeof(Info
);
455 Info
.dwFlags
= MRU_STRING
;
457 Info
.lpszSubKey
= L
"OpenWithList";
458 Info
.lpfnCompare
= NULL
;
460 return CreateMRUListW(&Info
);
463 BOOL
COpenWithList::LoadMRUList(HKEY hKey
)
466 int nItem
, nCount
, nResult
;
467 WCHAR wszAppFilename
[MAX_PATH
];
470 hList
= OpenMRUList(hKey
);
473 TRACE("OpenMRUList failed\n");
478 nCount
= EnumMRUListW(hList
, -1, NULL
, 0);
480 for(nItem
= 0; nItem
< nCount
; nItem
++)
482 nResult
= EnumMRUListW(hList
, nItem
, wszAppFilename
, _countof(wszAppFilename
));
487 SApp
*pApp
= Find(wszAppFilename
);
489 TRACE("Recommended app %ls: %p\n", wszAppFilename
, pApp
);
492 pApp
->bMRUList
= TRUE
;
493 SetRecommended(pApp
);
497 /* Free the MRU list */
502 BOOL
COpenWithList::LoadAppList(HKEY hKey
)
504 WCHAR wszAppFilename
[MAX_PATH
];
506 DWORD i
= 0, cchAppFilename
;
508 if (RegOpenKeyExW(hKey
, L
"OpenWithList", 0, KEY_READ
, &hSubkey
) != ERROR_SUCCESS
)
513 /* Enum registry keys - each of them is app name */
514 cchAppFilename
= _countof(wszAppFilename
);
515 if (RegEnumKeyExW(hSubkey
, i
++, wszAppFilename
, &cchAppFilename
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
518 /* Set application as recommended */
519 SApp
*pApp
= Find(wszAppFilename
);
521 TRACE("Recommended app %ls: %p\n", wszAppFilename
, pApp
);
523 SetRecommended(pApp
);
526 RegCloseKey(hSubkey
);
530 VOID
COpenWithList::LoadFromProgIdKey(HKEY hKey
, LPCWSTR pwszExt
)
532 WCHAR wszCmd
[MAX_PATH
], wszPath
[MAX_PATH
];
535 /* Check if NoOpen value exists */
536 if (RegGetValueW(hKey
, NULL
, L
"NoOpen", RRF_RT_REG_SZ
, NULL
, NULL
, &dwSize
) == ERROR_SUCCESS
)
538 /* Display warning dialog */
542 /* Check if there is a directly available execute key */
543 dwSize
= sizeof(wszCmd
);
544 if (RegGetValueW(hKey
, L
"shell\\open\\command", NULL
, RRF_RT_REG_SZ
, NULL
, (PVOID
)wszCmd
, &dwSize
) == ERROR_SUCCESS
)
546 /* Erase extra arguments */
547 GetPathFromCmd(wszPath
, wszCmd
);
549 /* Add application */
550 SApp
*pApp
= AddInternal(PathFindFileNameW(wszPath
));
551 TRACE("Add app %ls: %p\n", wszPath
, pApp
);
555 StringCbCopyW(pApp
->wszCmd
, sizeof(pApp
->wszCmd
), wszCmd
);
556 SetRecommended(pApp
);
558 AddAppToMRUList(pApp
, pwszExt
);
563 VOID
COpenWithList::LoadRecommendedFromHKCR(LPCWSTR pwszExt
)
566 WCHAR wszBuf
[MAX_PATH
], wszBuf2
[MAX_PATH
];
569 /* Check if extension exists */
570 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, pwszExt
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
572 /* Load items from SystemFileAssociations\Ext key */
573 StringCbPrintfW(wszBuf
, sizeof(wszBuf
), L
"SystemFileAssociations\\%s", pwszExt
);
574 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszBuf
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
578 /* Load programs referenced from HKCR\ProgId */
579 dwSize
= sizeof(wszBuf
);
580 if (RegGetValueW(hKey
, NULL
, L
"", RRF_RT_REG_SZ
, NULL
, wszBuf
, &dwSize
) == ERROR_SUCCESS
&&
581 RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszBuf
, 0, KEY_READ
, &hSubkey
) == ERROR_SUCCESS
)
583 LoadFromProgIdKey(hSubkey
, pwszExt
);
584 RegCloseKey(hSubkey
);
587 LoadFromProgIdKey(hKey
, pwszExt
);
589 /* Load items from HKCR\Ext\OpenWithList */
592 /* Load items from HKCR\Ext\OpenWithProgIDs */
593 if (RegOpenKeyExW(hKey
, L
"OpenWithProgIDs", 0, KEY_READ
, &hSubkey
) == ERROR_SUCCESS
)
595 LoadProgIdList(hSubkey
, pwszExt
);
596 RegCloseKey(hSubkey
);
599 /* Load additional items from referenced PerceivedType */
600 dwSize
= sizeof(wszBuf
);
601 if (RegGetValueW(hKey
, NULL
, L
"PerceivedType", RRF_RT_REG_SZ
, NULL
, wszBuf
, &dwSize
) == ERROR_SUCCESS
)
603 StringCbPrintfW(wszBuf2
, sizeof(wszBuf2
), L
"SystemFileAssociations\\%s", wszBuf
);
604 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszBuf2
, 0, KEY_READ
| KEY_WRITE
, &hSubkey
) == ERROR_SUCCESS
)
606 /* Load from OpenWithList key */
607 LoadAppList(hSubkey
);
608 RegCloseKey(hSubkey
);
616 VOID
COpenWithList::LoadRecommendedFromHKCU(LPCWSTR pwszExt
)
618 WCHAR wszBuf
[MAX_PATH
];
621 StringCbPrintfW(wszBuf
, sizeof(wszBuf
),
622 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%s",
624 if (RegOpenKeyExW(HKEY_CURRENT_USER
, wszBuf
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
626 /* Load MRU and ProgId lists */
628 LoadProgIdList(hKey
, pwszExt
);
630 /* Handle "Aplication" value */
631 DWORD cbBuf
= sizeof(wszBuf
);
632 if (RegGetValueW(hKey
, NULL
, L
"Application", RRF_RT_REG_SZ
, NULL
, wszBuf
, &cbBuf
) == ERROR_SUCCESS
)
634 SApp
*pApp
= Find(wszBuf
);
636 SetRecommended(pApp
);
644 BOOL
COpenWithList::AddAppToMRUList(SApp
*pApp
, LPCWSTR pwszFilename
)
651 /* Get file extension */
652 pwszExt
= PathFindExtensionW(pwszFilename
);
656 /* Build registry key */
657 if (FAILED(StringCbPrintfW(wszBuf
, sizeof(wszBuf
),
658 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%s",
661 ERR("insufficient buffer\n");
665 /* Open base key for this file extension */
666 if (RegCreateKeyExW(HKEY_CURRENT_USER
, wszBuf
, 0, NULL
, 0, KEY_WRITE
| KEY_READ
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
670 hList
= OpenMRUList(hKey
);
673 /* Insert the entry */
674 AddMRUStringW(hList
, pApp
->wszFilename
);
684 BOOL
COpenWithList::SetDefaultHandler(SApp
*pApp
, LPCWSTR pwszFilename
)
686 HKEY hKey
, hSrcKey
, hDestKey
;
690 TRACE("SetDefaultHandler %ls %ls", pApp
->wszFilename
, pwszFilename
);
692 /* Extract file extension */
693 LPCWSTR pwszExt
= PathFindExtensionW(pwszFilename
);
694 if (!pwszExt
[0] || !pwszExt
[1])
697 /* Create file extension key */
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, pwszExt
, 0, NULL
, 0, KEY_READ
|KEY_WRITE
, NULL
, &hKey
, &dwDisposition
) != ERROR_SUCCESS
)
700 ERR("Cannot open ext key");
704 if (dwDisposition
== REG_CREATED_NEW_KEY
)
706 /* A new entry was created create the prog key id */
707 StringCbPrintfW(wszBuf
, sizeof(wszBuf
), L
"%s_auto_file", pwszExt
+ 1);
708 if (RegSetValueExW(hKey
, L
"", 0, REG_SZ
, (const BYTE
*)wszBuf
, (wcslen(wszBuf
) + 1) * sizeof(WCHAR
)) != ERROR_SUCCESS
)
711 ERR("RegSetValueExW failed\n");
717 /* Entry already exists fetch prog key id */
718 DWORD dwSize
= sizeof(wszBuf
);
719 if (RegGetValueW(hKey
, NULL
, L
"", RRF_RT_REG_SZ
, NULL
, wszBuf
, &dwSize
) != ERROR_SUCCESS
)
721 ERR("RegGetValueW failed: %lu\n", GetLastError());
727 /* Close file extension key */
730 /* Create prog id key */
731 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, wszBuf
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
733 ERR("RegCreateKeyExW failed\n");
737 /* Check if there already verbs existing for that app */
738 StringCbPrintfW(wszBuf
, sizeof(wszBuf
), L
"Applications\\%s\\shell", pApp
->wszFilename
);
739 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszBuf
, 0, KEY_READ
, &hSrcKey
) != ERROR_SUCCESS
)
741 ERR("RegOpenKeyExW %ls failed\n", wszBuf
);
746 /* Open destination key */
747 if (RegCreateKeyExW(hKey
, L
"shell", 0, NULL
, 0, KEY_WRITE
, NULL
, &hDestKey
, NULL
) != ERROR_SUCCESS
)
749 ERR("RegCreateKeyExW failed\n");
750 RegCloseKey(hSrcKey
);
755 /* Copy static verbs from Classes\Applications key */
756 /* FIXME: SHCopyKey does not copy the security attributes of the keys */
757 LSTATUS Result
= SHCopyKeyW(hSrcKey
, NULL
, hDestKey
, 0);
758 RegCloseKey(hDestKey
);
759 RegCloseKey(hSrcKey
);
762 if (Result
!= ERROR_SUCCESS
)
764 ERR("SHCopyKeyW failed\n");
771 class COpenWithDialog
774 COpenWithDialog(const OPENASINFO
*pInfo
, COpenWithList
*pAppList
);
776 static INT_PTR CALLBACK
DialogProc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
777 BOOL
IsNoOpen(HWND hwnd
);
780 VOID
Init(HWND hwnd
);
781 VOID
AddApp(COpenWithList::SApp
*pApp
, BOOL bSelected
);
784 static INT_PTR CALLBACK
NoOpenDlgProc(HWND hwnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
);
785 COpenWithList::SApp
*GetCurrentApp();
787 const OPENASINFO
*m_pInfo
;
788 COpenWithList
*m_pAppList
;
789 BOOL m_bListAllocated
;
790 HWND m_hDialog
, m_hTreeView
;
791 HTREEITEM m_hRecommend
;
793 HIMAGELIST m_hImgList
;
797 COpenWithDialog::COpenWithDialog(const OPENASINFO
*pInfo
, COpenWithList
*pAppList
= NULL
):
798 m_pInfo(pInfo
), m_pAppList(pAppList
), m_hImgList(NULL
), m_bNoOpen(FALSE
)
802 m_pAppList
= new COpenWithList
;
803 m_bListAllocated
= TRUE
;
806 m_bListAllocated
= FALSE
;
809 COpenWithDialog::~COpenWithDialog()
811 if (m_bListAllocated
&& m_pAppList
)
814 ImageList_Destroy(m_hImgList
);
817 INT_PTR CALLBACK
COpenWithDialog::NoOpenDlgProc(HWND hwnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
)
826 EndDialog(hwnd
, IDNO
);
829 switch(LOWORD(wParam
))
832 EndDialog(hwnd
, IDYES
);
835 EndDialog(hwnd
, IDNO
);
845 BOOL
COpenWithDialog::IsNoOpen(HWND hwnd
)
847 /* Only do the actual check if the file type has the 'NoOpen' flag. */
850 int dReturnValue
= DialogBox(shell32_hInstance
, MAKEINTRESOURCE(IDD_NOOPEN
), hwnd
, NoOpenDlgProc
);
852 if (dReturnValue
== IDNO
)
854 else if (dReturnValue
== -1)
856 ERR("IsNoOpen failed to load the dialog box.");
864 VOID
COpenWithDialog::AddApp(COpenWithList::SApp
*pApp
, BOOL bSelected
)
866 LPCWSTR pwszName
= m_pAppList
->GetName(pApp
);
867 HICON hIcon
= m_pAppList
->GetIcon(pApp
);
869 TRACE("AddApp Cmd %ls Name %ls\n", pApp
->wszCmd
, pwszName
);
871 /* Add item to the list */
872 TVINSERTSTRUCT tvins
;
874 if (pApp
->bRecommended
)
875 tvins
.hParent
= tvins
.hInsertAfter
= m_hRecommend
;
877 tvins
.hParent
= tvins
.hInsertAfter
= m_hOther
;
879 tvins
.item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
880 tvins
.item
.pszText
= (LPWSTR
)pwszName
;
881 tvins
.item
.lParam
= (LPARAM
)pApp
;
885 tvins
.item
.mask
|= TVIF_IMAGE
| TVIF_SELECTEDIMAGE
;
886 tvins
.item
.iImage
= tvins
.item
.iSelectedImage
= ImageList_AddIcon(m_hImgList
, hIcon
);
889 HTREEITEM hItem
= TreeView_InsertItem(m_hTreeView
, &tvins
);
892 TreeView_SelectItem(m_hTreeView
, hItem
);
895 VOID
COpenWithDialog::Browse()
898 WCHAR wszFilter
[256];
899 WCHAR wszPath
[MAX_PATH
];
902 /* Initialize OPENFILENAMEW structure */
903 ZeroMemory(&ofn
, sizeof(OPENFILENAMEW
));
904 ofn
.lStructSize
= sizeof(OPENFILENAMEW
);
905 ofn
.hInstance
= shell32_hInstance
;
906 ofn
.hwndOwner
= m_hDialog
;
907 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_FILEMUSTEXIST
;
908 ofn
.nMaxFile
= (sizeof(wszPath
) / sizeof(WCHAR
));
909 ofn
.lpstrFile
= wszPath
;
912 if (LoadStringW(shell32_hInstance
, IDS_OPEN_WITH
, wszTitle
, sizeof(wszTitle
) / sizeof(WCHAR
)))
914 ofn
.lpstrTitle
= wszTitle
;
915 ofn
.nMaxFileTitle
= wcslen(wszTitle
);
918 /* Init the filter string */
919 if (LoadStringW(shell32_hInstance
, IDS_OPEN_WITH_FILTER
, wszFilter
, sizeof(wszFilter
) / sizeof(WCHAR
)))
920 ofn
.lpstrFilter
= wszFilter
;
921 ZeroMemory(wszPath
, sizeof(wszPath
));
923 /* Create OpenFile dialog */
924 if (!GetOpenFileNameW(&ofn
))
927 /* Setup context for insert proc */
928 COpenWithList::SApp
*pApp
= m_pAppList
->Add(wszPath
);
932 COpenWithList::SApp
*COpenWithDialog::GetCurrentApp()
935 tvi
.hItem
= TreeView_GetSelection(m_hTreeView
);
939 tvi
.mask
= TVIF_PARAM
;
940 if (!TreeView_GetItem(m_hTreeView
, &tvi
))
943 return (COpenWithList::SApp
*)tvi
.lParam
;
946 VOID
COpenWithDialog::Init(HWND hwnd
)
948 TRACE("COpenWithDialog::Init hwnd %p\n", hwnd
);
951 SetWindowLongPtr(hwnd
, DWLP_USER
, (LONG_PTR
)this);
953 /* Handle register checkbox */
954 HWND hRegisterCheckbox
= GetDlgItem(hwnd
, 14003);
955 if (!(m_pInfo
->oaifInFlags
& OAIF_ALLOW_REGISTRATION
))
956 EnableWindow(hRegisterCheckbox
, FALSE
);
957 if (m_pInfo
->oaifInFlags
& OAIF_FORCE_REGISTRATION
)
958 SendMessage(hRegisterCheckbox
, BM_SETCHECK
, BST_CHECKED
, 0);
959 if (m_pInfo
->oaifInFlags
& OAIF_HIDE_REGISTRATION
)
960 ShowWindow(hRegisterCheckbox
, SW_HIDE
);
962 if (m_pInfo
->pcszFile
)
964 WCHAR wszBuf
[MAX_PATH
];
967 /* Add filename to label */
968 cchBuf
= GetDlgItemTextW(hwnd
, 14001, wszBuf
, _countof(wszBuf
));
969 StringCchCopyW(wszBuf
+ cchBuf
, _countof(wszBuf
) - cchBuf
, PathFindFileNameW(m_pInfo
->pcszFile
));
970 SetDlgItemTextW(hwnd
, 14001, wszBuf
);
972 /* Load applications from registry */
974 m_pAppList
->LoadRecommended(m_pInfo
->pcszFile
);
976 /* Determine if the type of file can be opened directly from the shell */
977 if (m_pAppList
->IsNoOpen() != FALSE
)
981 m_hTreeView
= GetDlgItem(hwnd
, 14002);
982 m_hImgList
= ImageList_Create(16, 16, ILC_COLOR32
| ILC_MASK
, m_pAppList
->GetCount() + 1, m_pAppList
->GetCount() + 1);
983 (void)TreeView_SetImageList(m_hTreeView
, m_hImgList
, TVSIL_NORMAL
);
985 /* If there are some recommendations add parent nodes: Recommended and Others */
986 UINT cRecommended
= m_pAppList
->GetRecommendedCount();
987 if (cRecommended
> 0)
989 TVINSERTSTRUCT tvins
;
992 tvins
.hParent
= tvins
.hInsertAfter
= TVI_ROOT
;
993 tvins
.item
.mask
= TVIF_TEXT
|TVIF_STATE
|TVIF_IMAGE
|TVIF_SELECTEDIMAGE
;
994 tvins
.item
.pszText
= (LPWSTR
)wszBuf
;
995 tvins
.item
.state
= tvins
.item
.stateMask
= TVIS_EXPANDED
;
996 hFolderIcon
= (HICON
)LoadImage(shell32_hInstance
, MAKEINTRESOURCE(IDI_SHELL_PROGRAMS_FOLDER
), IMAGE_ICON
, 0, 0, 0);
997 tvins
.item
.iImage
= tvins
.item
.iSelectedImage
= ImageList_AddIcon(m_hImgList
, hFolderIcon
);
999 LoadStringW(shell32_hInstance
, IDS_OPEN_WITH_RECOMMENDED
, wszBuf
, _countof(wszBuf
));
1000 m_hRecommend
= TreeView_InsertItem(m_hTreeView
, &tvins
);
1002 LoadStringW(shell32_hInstance
, IDS_OPEN_WITH_OTHER
, wszBuf
, _countof(wszBuf
));
1003 m_hOther
= TreeView_InsertItem(m_hTreeView
, &tvins
);
1006 m_hRecommend
= m_hOther
= TVI_ROOT
;
1008 /* Add all applications */
1009 BOOL bNoAppSelected
= TRUE
;
1010 COpenWithList::SApp
*pAppList
= m_pAppList
->GetList();
1011 for (UINT i
= 0; i
< m_pAppList
->GetCount(); ++i
)
1013 if (!COpenWithList::IsHidden(&pAppList
[i
]))
1015 if (bNoAppSelected
&& (pAppList
[i
].bRecommended
|| !cRecommended
))
1017 AddApp(&pAppList
[i
], TRUE
);
1018 bNoAppSelected
= FALSE
;
1021 AddApp(&pAppList
[i
], FALSE
);
1027 VOID
COpenWithDialog::Accept()
1029 COpenWithList::SApp
*pApp
= GetCurrentApp();
1032 /* Set programm as default handler */
1033 if (SendDlgItemMessage(m_hDialog
, 14003, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
1034 m_pAppList
->SetDefaultHandler(pApp
, m_pInfo
->pcszFile
);
1036 /* Execute program */
1037 if (m_pInfo
->oaifInFlags
& OAIF_EXEC
)
1038 m_pAppList
->Execute(pApp
, m_pInfo
->pcszFile
);
1040 DestroyWindow(m_hDialog
);
1044 INT_PTR CALLBACK
COpenWithDialog::DialogProc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1046 COpenWithDialog
*pThis
= reinterpret_cast<COpenWithDialog
*>(GetWindowLongPtr(hwndDlg
, DWLP_USER
));
1052 COpenWithDialog
*pThis
= reinterpret_cast<COpenWithDialog
*>(lParam
);
1054 pThis
->Init(hwndDlg
);
1058 switch(LOWORD(wParam
))
1060 case 14004: /* browse */
1070 case IDCANCEL
: /* cancel */
1071 DestroyWindow(hwndDlg
);
1078 switch (((LPNMHDR
)lParam
)->code
)
1080 case TVN_SELCHANGED
:
1081 EnableWindow(GetDlgItem(hwndDlg
, IDOK
), pThis
->GetCurrentApp() ? TRUE
: FALSE
);
1090 DestroyWindow(hwndDlg
);
1098 COpenWithMenu::COpenWithMenu()
1102 m_pAppList
= new COpenWithList
;
1105 COpenWithMenu::~COpenWithMenu()
1107 TRACE("Destroying COpenWithMenu(%p)\n", this);
1114 /* get item count */
1115 Count
= GetMenuItemCount(m_hSubMenu
);
1119 /* setup menuitem info */
1120 ZeroMemory(&mii
, sizeof(mii
));
1121 mii
.cbSize
= sizeof(mii
);
1122 mii
.fMask
= MIIM_DATA
| MIIM_FTYPE
| MIIM_CHECKMARKS
;
1124 for(Index
= 0; Index
< Count
; Index
++)
1126 if (GetMenuItemInfoW(m_hSubMenu
, Index
, TRUE
, &mii
))
1128 if (mii
.hbmpChecked
)
1129 DeleteObject(mii
.hbmpChecked
);
1138 HBITMAP
COpenWithMenu::IconToBitmap(HICON hIcon
)
1141 HBITMAP hbm
, hbmOld
;
1144 hdcScr
= GetDC(NULL
);
1145 hdc
= CreateCompatibleDC(hdcScr
);
1146 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXMENUCHECK
), GetSystemMetrics(SM_CYMENUCHECK
));
1147 hbm
= CreateCompatibleBitmap(hdcScr
, rc
.right
, rc
.bottom
);
1148 ReleaseDC(NULL
, hdcScr
);
1150 hbmOld
= (HBITMAP
)SelectObject(hdc
, hbm
);
1151 FillRect(hdc
, &rc
, (HBRUSH
)(COLOR_MENU
+ 1));
1152 if (!DrawIconEx(hdc
, 0, 0, hIcon
, rc
.right
, rc
.bottom
, 0, NULL
, DI_NORMAL
))
1153 ERR("DrawIcon failed: %x\n", GetLastError());
1154 SelectObject(hdc
, hbmOld
);
1161 VOID
COpenWithMenu::AddChooseProgramItem()
1166 ZeroMemory(&mii
, sizeof(mii
));
1167 mii
.cbSize
= sizeof(mii
);
1168 mii
.fMask
= MIIM_TYPE
| MIIM_ID
;
1169 mii
.fType
= MFT_SEPARATOR
;
1171 InsertMenuItemW(m_hSubMenu
, -1, TRUE
, &mii
);
1173 if (!LoadStringW(shell32_hInstance
, IDS_OPEN_WITH_CHOOSE
, wszBuf
, _countof(wszBuf
)))
1175 ERR("Failed to load string\n");
1179 mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
1180 mii
.fType
= MFT_STRING
;
1181 mii
.fState
= MFS_ENABLED
;
1182 mii
.wID
= m_idCmdLast
;
1183 mii
.dwTypeData
= (LPWSTR
)wszBuf
;
1184 mii
.cch
= wcslen(wszBuf
);
1186 InsertMenuItemW(m_hSubMenu
, -1, TRUE
, &mii
);
1189 VOID
COpenWithMenu::AddApp(PVOID pApp
)
1192 LPCWSTR pwszName
= m_pAppList
->GetName((COpenWithList::SApp
*)pApp
);
1194 ZeroMemory(&mii
, sizeof(mii
));
1195 mii
.cbSize
= sizeof(mii
);
1196 mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
| MIIM_DATA
;
1197 mii
.fType
= MFT_STRING
;
1198 mii
.fState
= MFS_ENABLED
;
1199 mii
.wID
= m_idCmdLast
;
1200 mii
.dwTypeData
= (LPWSTR
)pwszName
;
1201 mii
.cch
= wcslen(mii
.dwTypeData
);
1202 mii
.dwItemData
= (ULONG_PTR
)pApp
;
1204 HICON hIcon
= m_pAppList
->GetIcon((COpenWithList::SApp
*)pApp
);
1207 mii
.fMask
|= MIIM_CHECKMARKS
;
1208 mii
.hbmpChecked
= mii
.hbmpUnchecked
= IconToBitmap(hIcon
);
1211 if (InsertMenuItemW(m_hSubMenu
, -1, TRUE
, &mii
))
1215 HRESULT WINAPI
COpenWithMenu::QueryContextMenu(
1222 TRACE("hMenu %p indexMenu %u idFirst %u idLast %u uFlags %u\n", hMenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
1224 INT DefaultPos
= GetMenuDefaultItem(hMenu
, TRUE
, 0);
1227 UINT NameId
= (DefaultPos
== -1 ? IDS_OPEN
: IDS_OPEN_WITH
);
1228 if (!LoadStringW(shell32_hInstance
, NameId
, wszName
, _countof(wszName
)))
1230 ERR("Failed to load string\n");
1234 /* Init first cmd id and submenu */
1235 m_idCmdFirst
= m_idCmdLast
= idCmdFirst
;
1238 /* If we are going to be default item, we shouldn't be submenu */
1239 if (DefaultPos
!= -1)
1241 /* Load applications list */
1243 m_pAppList
->LoadRecommended(m_wszPath
);
1245 /* Create submenu only if there is more than one application and menu has a default item */
1246 if (m_pAppList
->GetRecommendedCount() > 1)
1248 m_hSubMenu
= CreatePopupMenu();
1250 for(UINT i
= 0; i
< m_pAppList
->GetCount(); ++i
)
1252 COpenWithList::SApp
*pApp
= m_pAppList
->GetList() + i
;
1253 if (pApp
->bRecommended
)
1257 AddChooseProgramItem();
1261 /* Insert menu item */
1263 ZeroMemory(&mii
, sizeof(mii
));
1264 mii
.cbSize
= sizeof(mii
);
1265 mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
1268 mii
.fMask
|= MIIM_SUBMENU
;
1269 mii
.hSubMenu
= m_hSubMenu
;
1273 mii
.wID
= m_idCmdLast
;
1275 mii
.fType
= MFT_STRING
;
1276 mii
.dwTypeData
= (LPWSTR
)wszName
;
1277 mii
.cch
= wcslen(wszName
);
1279 mii
.fState
= MFS_ENABLED
;
1280 if (DefaultPos
== -1)
1281 mii
.fState
|= MFS_DEFAULT
;
1283 if (!InsertMenuItemW(hMenu
, DefaultPos
+ 1, TRUE
, &mii
))
1286 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, m_idCmdLast
- m_idCmdFirst
+ 1);
1290 COpenWithMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici
)
1292 HRESULT hr
= E_FAIL
;
1294 TRACE("This %p idFirst %u idLast %u idCmd %u\n", this, m_idCmdFirst
, m_idCmdLast
, m_idCmdFirst
+ LOWORD(lpici
->lpVerb
));
1296 if (HIWORD(lpici
->lpVerb
) == 0 && m_idCmdFirst
+ LOWORD(lpici
->lpVerb
) <= m_idCmdLast
)
1298 if (m_idCmdFirst
+ LOWORD(lpici
->lpVerb
) == m_idCmdLast
)
1301 LPCWSTR pwszExt
= PathFindExtensionW(m_wszPath
);
1303 info
.pcszFile
= m_wszPath
;
1304 info
.oaifInFlags
= OAIF_EXEC
;
1306 info
.oaifInFlags
|= OAIF_REGISTER_EXT
| OAIF_ALLOW_REGISTRATION
;
1307 info
.pcszClass
= NULL
;
1308 hr
= SHOpenWithDialog(lpici
->hwnd
, &info
);
1312 /* retrieve menu item info */
1314 ZeroMemory(&mii
, sizeof(mii
));
1315 mii
.cbSize
= sizeof(mii
);
1316 mii
.fMask
= MIIM_DATA
| MIIM_FTYPE
;
1318 if (GetMenuItemInfoW(m_hSubMenu
, LOWORD(lpici
->lpVerb
), TRUE
, &mii
) && mii
.dwItemData
)
1320 /* launch item with specified app */
1321 COpenWithList::SApp
*pApp
= (COpenWithList::SApp
*)mii
.dwItemData
;
1322 COpenWithList::Execute(pApp
, m_wszPath
);
1332 COpenWithMenu::GetCommandString(UINT_PTR idCmd
, UINT uType
,
1333 UINT
* pwReserved
, LPSTR pszName
, UINT cchMax
)
1335 FIXME("%p %lu %u %p %p %u\n", this,
1336 idCmd
, uType
, pwReserved
, pszName
, cchMax
);
1341 HRESULT WINAPI
COpenWithMenu::HandleMenuMsg(
1346 TRACE("This %p uMsg %x\n", this, uMsg
);
1352 COpenWithMenu::Initialize(LPCITEMIDLIST pidlFolder
,
1353 IDataObject
*pdtobj
,
1360 LPCITEMIDLIST pidlFolder2
;
1361 LPCITEMIDLIST pidlChild
;
1365 TRACE("This %p\n", this);
1368 return E_INVALIDARG
;
1370 fmt
.cfFormat
= RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
1372 fmt
.dwAspect
= DVASPECT_CONTENT
;
1374 fmt
.tymed
= TYMED_HGLOBAL
;
1376 hr
= pdtobj
->GetData(&fmt
, &medium
);
1380 ERR("pdtobj->GetData failed with 0x%x\n", hr
);
1384 pida
= (LPIDA
)GlobalLock(medium
.hGlobal
);
1385 ASSERT(pida
->cidl
>= 1);
1387 pidlFolder2
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+ pida
->aoffset
[0]);
1388 pidlChild
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+ pida
->aoffset
[1]);
1390 if (!_ILIsValue(pidlChild
))
1392 TRACE("pidl is not a file\n");
1393 GlobalUnlock(medium
.hGlobal
);
1394 GlobalFree(medium
.hGlobal
);
1398 pidl
= ILCombine(pidlFolder2
, pidlChild
);
1400 GlobalUnlock(medium
.hGlobal
);
1401 GlobalFree(medium
.hGlobal
);
1406 return E_OUTOFMEMORY
;
1409 if (!SHGetPathFromIDListW(pidl
, m_wszPath
))
1411 SHFree((void*)pidl
);
1412 ERR("SHGetPathFromIDListW failed\n");
1416 SHFree((void*)pidl
);
1417 TRACE("szPath %s\n", debugstr_w(m_wszPath
));
1419 pwszExt
= PathFindExtensionW(m_wszPath
);
1420 if (PathIsExeW(pwszExt
) || !_wcsicmp(pwszExt
, L
".lnk"))
1422 TRACE("file is a executable or shortcut\n");
1430 SHOpenWithDialog(HWND hwndParent
, const OPENASINFO
*poainfo
)
1435 TRACE("SHOpenWithDialog hwndParent %p poainfo %p\n", hwndParent
, poainfo
);
1437 InitCommonControls();
1439 if (poainfo
->pcszClass
== NULL
&& poainfo
->pcszFile
== NULL
)
1442 COpenWithDialog
pDialog(poainfo
);
1444 hwnd
= CreateDialogParam(shell32_hInstance
, MAKEINTRESOURCE(IDD_OPEN_WITH
), hwndParent
, COpenWithDialog::DialogProc
, (LPARAM
)&pDialog
);
1447 ERR("Failed to create dialog\n");
1451 if (pDialog
.IsNoOpen(hwndParent
))
1454 ShowWindow(hwnd
, SW_SHOWNORMAL
);
1456 while (GetMessage(&msg
, NULL
, 0, 0) && IsWindow(hwnd
))
1458 if (!IsDialogMessage(hwnd
, &msg
))
1460 TranslateMessage(&msg
);
1461 DispatchMessage(&msg
);