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
)
605 StringCbPrintfW(wszBuf2
, sizeof(wszBuf2
), L
"SystemFileAssociations\\%s", wszBuf
);
606 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszBuf2
, 0, KEY_READ
| KEY_WRITE
, &hSubkey
) == ERROR_SUCCESS
)
608 /* Load from OpenWithList key */
609 LoadAppList(hSubkey
);
610 RegCloseKey(hSubkey
);
618 VOID
COpenWithList::LoadRecommendedFromHKCU(LPCWSTR pwszExt
)
620 WCHAR wszBuf
[MAX_PATH
];
623 StringCbPrintfW(wszBuf
, sizeof(wszBuf
),
624 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%s",
626 if (RegOpenKeyExW(HKEY_CURRENT_USER
, wszBuf
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
628 /* Load MRU and ProgId lists */
630 LoadProgIdList(hKey
, pwszExt
);
632 /* Handle "Aplication" value */
633 DWORD cbBuf
= sizeof(wszBuf
);
634 if (RegGetValueW(hKey
, NULL
, L
"Application", RRF_RT_REG_SZ
, NULL
, wszBuf
, &cbBuf
) == ERROR_SUCCESS
)
636 SApp
*pApp
= Find(wszBuf
);
638 SetRecommended(pApp
);
646 BOOL
COpenWithList::AddAppToMRUList(SApp
*pApp
, LPCWSTR pwszFilename
)
653 /* Get file extension */
654 pwszExt
= PathFindExtensionW(pwszFilename
);
658 /* Build registry key */
659 if (FAILED(StringCbPrintfW(wszBuf
, sizeof(wszBuf
),
660 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%s",
663 ERR("insufficient buffer\n");
667 /* Open base key for this file extension */
668 if (RegCreateKeyExW(HKEY_CURRENT_USER
, wszBuf
, 0, NULL
, 0, KEY_WRITE
| KEY_READ
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
672 hList
= OpenMRUList(hKey
);
675 /* Insert the entry */
676 AddMRUStringW(hList
, pApp
->wszFilename
);
686 BOOL
COpenWithList::SetDefaultHandler(SApp
*pApp
, LPCWSTR pwszFilename
)
688 HKEY hKey
, hSrcKey
, hDestKey
;
692 TRACE("SetDefaultHandler %ls %ls", pApp
->wszFilename
, pwszFilename
);
694 /* Extract file extension */
695 LPCWSTR pwszExt
= PathFindExtensionW(pwszFilename
);
696 if (!pwszExt
[0] || !pwszExt
[1])
699 /* Create file extension key */
700 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, pwszExt
, 0, NULL
, 0, KEY_READ
|KEY_WRITE
, NULL
, &hKey
, &dwDisposition
) != ERROR_SUCCESS
)
702 ERR("Cannot open ext key");
706 if (dwDisposition
== REG_CREATED_NEW_KEY
)
708 /* A new entry was created create the prog key id */
709 StringCbPrintfW(wszBuf
, sizeof(wszBuf
), L
"%s_auto_file", pwszExt
+ 1);
710 if (RegSetValueExW(hKey
, L
"", 0, REG_SZ
, (const BYTE
*)wszBuf
, (wcslen(wszBuf
) + 1) * sizeof(WCHAR
)) != ERROR_SUCCESS
)
713 ERR("RegSetValueExW failed\n");
719 /* Entry already exists fetch prog key id */
720 DWORD dwSize
= sizeof(wszBuf
);
721 if (RegGetValueW(hKey
, NULL
, L
"", RRF_RT_REG_SZ
, NULL
, wszBuf
, &dwSize
) != ERROR_SUCCESS
)
723 ERR("RegGetValueW failed: %lu\n", GetLastError());
729 /* Close file extension key */
732 /* Create prog id key */
733 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, wszBuf
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hKey
, NULL
) != ERROR_SUCCESS
)
735 ERR("RegCreateKeyExW failed\n");
739 /* Check if there already verbs existing for that app */
740 StringCbPrintfW(wszBuf
, sizeof(wszBuf
), L
"Applications\\%s\\shell", pApp
->wszFilename
);
741 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszBuf
, 0, KEY_READ
, &hSrcKey
) != ERROR_SUCCESS
)
743 ERR("RegOpenKeyExW %ls failed\n", wszBuf
);
748 /* Open destination key */
749 if (RegCreateKeyExW(hKey
, L
"shell", 0, NULL
, 0, KEY_WRITE
, NULL
, &hDestKey
, NULL
) != ERROR_SUCCESS
)
751 ERR("RegCreateKeyExW failed\n");
752 RegCloseKey(hSrcKey
);
757 /* Copy static verbs from Classes\Applications key */
758 /* FIXME: SHCopyKey does not copy the security attributes of the keys */
759 LSTATUS Result
= SHCopyKeyW(hSrcKey
, NULL
, hDestKey
, 0);
760 RegCloseKey(hDestKey
);
761 RegCloseKey(hSrcKey
);
764 if (Result
!= ERROR_SUCCESS
)
766 ERR("SHCopyKeyW failed\n");
773 class COpenWithDialog
776 COpenWithDialog(const OPENASINFO
*pInfo
, COpenWithList
*pAppList
);
778 static INT_PTR CALLBACK
DialogProc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
779 BOOL
IsNoOpen(HWND hwnd
);
782 VOID
Init(HWND hwnd
);
783 VOID
AddApp(COpenWithList::SApp
*pApp
, BOOL bSelected
);
786 static INT_PTR CALLBACK
NoOpenDlgProc(HWND hwnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
);
787 COpenWithList::SApp
*GetCurrentApp();
789 const OPENASINFO
*m_pInfo
;
790 COpenWithList
*m_pAppList
;
791 BOOL m_bListAllocated
;
792 HWND m_hDialog
, m_hTreeView
;
793 HTREEITEM m_hRecommend
;
795 HIMAGELIST m_hImgList
;
799 COpenWithDialog::COpenWithDialog(const OPENASINFO
*pInfo
, COpenWithList
*pAppList
= NULL
):
800 m_pInfo(pInfo
), m_pAppList(pAppList
), m_hImgList(NULL
), m_bNoOpen(FALSE
)
804 m_pAppList
= new COpenWithList
;
805 m_bListAllocated
= TRUE
;
808 m_bListAllocated
= FALSE
;
811 COpenWithDialog::~COpenWithDialog()
813 if (m_bListAllocated
&& m_pAppList
)
816 ImageList_Destroy(m_hImgList
);
819 INT_PTR CALLBACK
COpenWithDialog::NoOpenDlgProc(HWND hwnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
)
828 EndDialog(hwnd
, IDNO
);
831 switch(LOWORD(wParam
))
834 EndDialog(hwnd
, IDYES
);
837 EndDialog(hwnd
, IDNO
);
847 BOOL
COpenWithDialog::IsNoOpen(HWND hwnd
)
849 /* Only do the actual check if the file type has the 'NoOpen' flag. */
852 int dReturnValue
= DialogBox(shell32_hInstance
, MAKEINTRESOURCE(IDD_NOOPEN
), hwnd
, NoOpenDlgProc
);
854 if (dReturnValue
== IDNO
)
856 else if (dReturnValue
== -1)
858 ERR("IsNoOpen failed to load the dialog box.");
866 VOID
COpenWithDialog::AddApp(COpenWithList::SApp
*pApp
, BOOL bSelected
)
868 LPCWSTR pwszName
= m_pAppList
->GetName(pApp
);
869 HICON hIcon
= m_pAppList
->GetIcon(pApp
);
871 TRACE("AddApp Cmd %ls Name %ls\n", pApp
->wszCmd
, pwszName
);
873 /* Add item to the list */
874 TVINSERTSTRUCT tvins
;
876 if (pApp
->bRecommended
)
877 tvins
.hParent
= tvins
.hInsertAfter
= m_hRecommend
;
879 tvins
.hParent
= tvins
.hInsertAfter
= m_hOther
;
881 tvins
.item
.mask
= TVIF_TEXT
|TVIF_PARAM
;
882 tvins
.item
.pszText
= (LPWSTR
)pwszName
;
883 tvins
.item
.lParam
= (LPARAM
)pApp
;
887 tvins
.item
.mask
|= TVIF_IMAGE
| TVIF_SELECTEDIMAGE
;
888 tvins
.item
.iImage
= tvins
.item
.iSelectedImage
= ImageList_AddIcon(m_hImgList
, hIcon
);
891 HTREEITEM hItem
= TreeView_InsertItem(m_hTreeView
, &tvins
);
894 TreeView_SelectItem(m_hTreeView
, hItem
);
897 VOID
COpenWithDialog::Browse()
900 WCHAR wszFilter
[256];
901 WCHAR wszPath
[MAX_PATH
];
904 /* Initialize OPENFILENAMEW structure */
905 ZeroMemory(&ofn
, sizeof(OPENFILENAMEW
));
906 ofn
.lStructSize
= sizeof(OPENFILENAMEW
);
907 ofn
.hInstance
= shell32_hInstance
;
908 ofn
.hwndOwner
= m_hDialog
;
909 ofn
.Flags
= OFN_PATHMUSTEXIST
| OFN_FILEMUSTEXIST
;
910 ofn
.nMaxFile
= (sizeof(wszPath
) / sizeof(WCHAR
));
911 ofn
.lpstrFile
= wszPath
;
914 if (LoadStringW(shell32_hInstance
, IDS_OPEN_WITH
, wszTitle
, sizeof(wszTitle
) / sizeof(WCHAR
)))
916 ofn
.lpstrTitle
= wszTitle
;
917 ofn
.nMaxFileTitle
= wcslen(wszTitle
);
920 /* Init the filter string */
921 if (LoadStringW(shell32_hInstance
, IDS_OPEN_WITH_FILTER
, wszFilter
, sizeof(wszFilter
) / sizeof(WCHAR
)))
922 ofn
.lpstrFilter
= wszFilter
;
923 ZeroMemory(wszPath
, sizeof(wszPath
));
925 /* Create OpenFile dialog */
926 if (!GetOpenFileNameW(&ofn
))
929 /* Setup context for insert proc */
930 COpenWithList::SApp
*pApp
= m_pAppList
->Add(wszPath
);
934 COpenWithList::SApp
*COpenWithDialog::GetCurrentApp()
937 tvi
.hItem
= TreeView_GetSelection(m_hTreeView
);
941 tvi
.mask
= TVIF_PARAM
;
942 if (!TreeView_GetItem(m_hTreeView
, &tvi
))
945 return (COpenWithList::SApp
*)tvi
.lParam
;
948 VOID
COpenWithDialog::Init(HWND hwnd
)
950 TRACE("COpenWithDialog::Init hwnd %p\n", hwnd
);
953 SetWindowLongPtr(hwnd
, DWLP_USER
, (LONG_PTR
)this);
955 /* Handle register checkbox */
956 HWND hRegisterCheckbox
= GetDlgItem(hwnd
, 14003);
957 if (!(m_pInfo
->oaifInFlags
& OAIF_ALLOW_REGISTRATION
))
958 EnableWindow(hRegisterCheckbox
, FALSE
);
959 if (m_pInfo
->oaifInFlags
& OAIF_FORCE_REGISTRATION
)
960 SendMessage(hRegisterCheckbox
, BM_SETCHECK
, BST_CHECKED
, 0);
961 if (m_pInfo
->oaifInFlags
& OAIF_HIDE_REGISTRATION
)
962 ShowWindow(hRegisterCheckbox
, SW_HIDE
);
964 if (m_pInfo
->pcszFile
)
966 WCHAR wszBuf
[MAX_PATH
];
969 /* Add filename to label */
970 cchBuf
= GetDlgItemTextW(hwnd
, 14001, wszBuf
, _countof(wszBuf
));
971 StringCchCopyW(wszBuf
+ cchBuf
, _countof(wszBuf
) - cchBuf
, PathFindFileNameW(m_pInfo
->pcszFile
));
972 SetDlgItemTextW(hwnd
, 14001, wszBuf
);
974 /* Load applications from registry */
976 m_pAppList
->LoadRecommended(m_pInfo
->pcszFile
);
978 /* Determine if the type of file can be opened directly from the shell */
979 if (m_pAppList
->IsNoOpen() != FALSE
)
983 m_hTreeView
= GetDlgItem(hwnd
, 14002);
984 m_hImgList
= ImageList_Create(16, 16, ILC_COLOR32
| ILC_MASK
, m_pAppList
->GetCount() + 1, m_pAppList
->GetCount() + 1);
985 (void)TreeView_SetImageList(m_hTreeView
, m_hImgList
, TVSIL_NORMAL
);
987 /* If there are some recommendations add parent nodes: Recommended and Others */
988 UINT cRecommended
= m_pAppList
->GetRecommendedCount();
989 if (cRecommended
> 0)
991 TVINSERTSTRUCT tvins
;
994 tvins
.hParent
= tvins
.hInsertAfter
= TVI_ROOT
;
995 tvins
.item
.mask
= TVIF_TEXT
|TVIF_STATE
|TVIF_IMAGE
|TVIF_SELECTEDIMAGE
;
996 tvins
.item
.pszText
= (LPWSTR
)wszBuf
;
997 tvins
.item
.state
= tvins
.item
.stateMask
= TVIS_EXPANDED
;
998 hFolderIcon
= (HICON
)LoadImage(shell32_hInstance
, MAKEINTRESOURCE(IDI_SHELL_FOLDER
), IMAGE_ICON
, 0, 0, 0);
999 tvins
.item
.iImage
= tvins
.item
.iSelectedImage
= ImageList_AddIcon(m_hImgList
, hFolderIcon
);
1001 LoadStringW(shell32_hInstance
, IDS_OPEN_WITH_RECOMMENDED
, wszBuf
, _countof(wszBuf
));
1002 m_hRecommend
= TreeView_InsertItem(m_hTreeView
, &tvins
);
1004 LoadStringW(shell32_hInstance
, IDS_OPEN_WITH_OTHER
, wszBuf
, _countof(wszBuf
));
1005 m_hOther
= TreeView_InsertItem(m_hTreeView
, &tvins
);
1008 m_hRecommend
= m_hOther
= TVI_ROOT
;
1010 /* Add all applications */
1011 BOOL bNoAppSelected
= TRUE
;
1012 COpenWithList::SApp
*pAppList
= m_pAppList
->GetList();
1013 for (UINT i
= 0; i
< m_pAppList
->GetCount(); ++i
)
1015 if (!COpenWithList::IsHidden(&pAppList
[i
]))
1017 if (bNoAppSelected
&& (pAppList
[i
].bRecommended
|| !cRecommended
))
1019 AddApp(&pAppList
[i
], TRUE
);
1020 bNoAppSelected
= FALSE
;
1023 AddApp(&pAppList
[i
], FALSE
);
1029 VOID
COpenWithDialog::Accept()
1031 COpenWithList::SApp
*pApp
= GetCurrentApp();
1034 /* Set programm as default handler */
1035 if (SendDlgItemMessage(m_hDialog
, 14003, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
1036 m_pAppList
->SetDefaultHandler(pApp
, m_pInfo
->pcszFile
);
1038 /* Execute program */
1039 if (m_pInfo
->oaifInFlags
& OAIF_EXEC
)
1040 m_pAppList
->Execute(pApp
, m_pInfo
->pcszFile
);
1042 DestroyWindow(m_hDialog
);
1046 INT_PTR CALLBACK
COpenWithDialog::DialogProc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1048 COpenWithDialog
*pThis
= reinterpret_cast<COpenWithDialog
*>(GetWindowLongPtr(hwndDlg
, DWLP_USER
));
1054 COpenWithDialog
*pThis
= reinterpret_cast<COpenWithDialog
*>(lParam
);
1056 pThis
->Init(hwndDlg
);
1060 switch(LOWORD(wParam
))
1062 case 14004: /* browse */
1072 case IDCANCEL
: /* cancel */
1073 DestroyWindow(hwndDlg
);
1080 switch (((LPNMHDR
)lParam
)->code
)
1082 case TVN_SELCHANGED
:
1083 EnableWindow(GetDlgItem(hwndDlg
, IDOK
), pThis
->GetCurrentApp() ? TRUE
: FALSE
);
1092 DestroyWindow(hwndDlg
);
1100 COpenWithMenu::COpenWithMenu()
1104 m_pAppList
= new COpenWithList
;
1107 COpenWithMenu::~COpenWithMenu()
1109 TRACE("Destroying COpenWithMenu(%p)\n", this);
1116 /* get item count */
1117 Count
= GetMenuItemCount(m_hSubMenu
);
1121 /* setup menuitem info */
1122 ZeroMemory(&mii
, sizeof(mii
));
1123 mii
.cbSize
= sizeof(mii
);
1124 mii
.fMask
= MIIM_DATA
| MIIM_FTYPE
| MIIM_CHECKMARKS
;
1126 for(Index
= 0; Index
< Count
; Index
++)
1128 if (GetMenuItemInfoW(m_hSubMenu
, Index
, TRUE
, &mii
))
1130 if (mii
.hbmpChecked
)
1131 DeleteObject(mii
.hbmpChecked
);
1140 HBITMAP
COpenWithMenu::IconToBitmap(HICON hIcon
)
1143 HBITMAP hbm
, hbmOld
;
1146 hdcScr
= GetDC(NULL
);
1147 hdc
= CreateCompatibleDC(hdcScr
);
1148 SetRect(&rc
, 0, 0, GetSystemMetrics(SM_CXMENUCHECK
), GetSystemMetrics(SM_CYMENUCHECK
));
1149 hbm
= CreateCompatibleBitmap(hdcScr
, rc
.right
, rc
.bottom
);
1150 ReleaseDC(NULL
, hdcScr
);
1152 hbmOld
= (HBITMAP
)SelectObject(hdc
, hbm
);
1153 FillRect(hdc
, &rc
, (HBRUSH
)(COLOR_MENU
+ 1));
1154 if (!DrawIconEx(hdc
, 0, 0, hIcon
, rc
.right
, rc
.bottom
, 0, NULL
, DI_NORMAL
))
1155 ERR("DrawIcon failed: %x\n", GetLastError());
1156 SelectObject(hdc
, hbmOld
);
1163 VOID
COpenWithMenu::AddChooseProgramItem()
1168 ZeroMemory(&mii
, sizeof(mii
));
1169 mii
.cbSize
= sizeof(mii
);
1170 mii
.fMask
= MIIM_TYPE
| MIIM_ID
;
1171 mii
.fType
= MFT_SEPARATOR
;
1173 InsertMenuItemW(m_hSubMenu
, -1, TRUE
, &mii
);
1175 if (!LoadStringW(shell32_hInstance
, IDS_OPEN_WITH_CHOOSE
, wszBuf
, _countof(wszBuf
)))
1177 ERR("Failed to load string\n");
1181 mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
1182 mii
.fType
= MFT_STRING
;
1183 mii
.fState
= MFS_ENABLED
;
1184 mii
.wID
= m_idCmdLast
;
1185 mii
.dwTypeData
= (LPWSTR
)wszBuf
;
1186 mii
.cch
= wcslen(wszBuf
);
1188 InsertMenuItemW(m_hSubMenu
, -1, TRUE
, &mii
);
1191 VOID
COpenWithMenu::AddApp(PVOID pApp
)
1194 LPCWSTR pwszName
= m_pAppList
->GetName((COpenWithList::SApp
*)pApp
);
1196 ZeroMemory(&mii
, sizeof(mii
));
1197 mii
.cbSize
= sizeof(mii
);
1198 mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
| MIIM_DATA
;
1199 mii
.fType
= MFT_STRING
;
1200 mii
.fState
= MFS_ENABLED
;
1201 mii
.wID
= m_idCmdLast
;
1202 mii
.dwTypeData
= (LPWSTR
)pwszName
;
1203 mii
.cch
= wcslen(mii
.dwTypeData
);
1204 mii
.dwItemData
= (ULONG_PTR
)pApp
;
1206 HICON hIcon
= m_pAppList
->GetIcon((COpenWithList::SApp
*)pApp
);
1209 mii
.fMask
|= MIIM_CHECKMARKS
;
1210 mii
.hbmpChecked
= mii
.hbmpUnchecked
= IconToBitmap(hIcon
);
1213 if (InsertMenuItemW(m_hSubMenu
, -1, TRUE
, &mii
))
1217 HRESULT WINAPI
COpenWithMenu::QueryContextMenu(
1224 TRACE("hMenu %p indexMenu %u idFirst %u idLast %u uFlags %u\n", hMenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
1226 INT DefaultPos
= GetMenuDefaultItem(hMenu
, TRUE
, 0);
1229 UINT NameId
= (DefaultPos
== -1 ? IDS_OPEN
: IDS_OPEN_WITH
);
1230 if (!LoadStringW(shell32_hInstance
, NameId
, wszName
, _countof(wszName
)))
1232 ERR("Failed to load string\n");
1236 /* Init first cmd id and submenu */
1237 m_idCmdFirst
= m_idCmdLast
= idCmdFirst
;
1240 /* If we are going to be default item, we shouldn't be submenu */
1241 if (DefaultPos
!= -1)
1243 /* Load applications list */
1245 m_pAppList
->LoadRecommended(m_wszPath
);
1247 /* Create submenu only if there is more than one application and menu has a default item */
1248 if (m_pAppList
->GetRecommendedCount() > 1)
1250 m_hSubMenu
= CreatePopupMenu();
1252 for(UINT i
= 0; i
< m_pAppList
->GetCount(); ++i
)
1254 COpenWithList::SApp
*pApp
= m_pAppList
->GetList() + i
;
1255 if (pApp
->bRecommended
)
1259 AddChooseProgramItem();
1263 /* Insert menu item */
1265 ZeroMemory(&mii
, sizeof(mii
));
1266 mii
.cbSize
= sizeof(mii
);
1267 mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
1270 mii
.fMask
|= MIIM_SUBMENU
;
1271 mii
.hSubMenu
= m_hSubMenu
;
1275 mii
.wID
= m_idCmdLast
;
1277 mii
.fType
= MFT_STRING
;
1278 mii
.dwTypeData
= (LPWSTR
)wszName
;
1279 mii
.cch
= wcslen(wszName
);
1281 mii
.fState
= MFS_ENABLED
;
1282 if (DefaultPos
== -1)
1283 mii
.fState
|= MFS_DEFAULT
;
1285 if (!InsertMenuItemW(hMenu
, DefaultPos
+ 1, TRUE
, &mii
))
1288 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, m_idCmdLast
- m_idCmdFirst
+ 1);
1292 COpenWithMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici
)
1294 HRESULT hr
= E_FAIL
;
1296 TRACE("This %p idFirst %u idLast %u idCmd %u\n", this, m_idCmdFirst
, m_idCmdLast
, m_idCmdFirst
+ LOWORD(lpici
->lpVerb
));
1298 if (HIWORD(lpici
->lpVerb
) == 0 && m_idCmdFirst
+ LOWORD(lpici
->lpVerb
) <= m_idCmdLast
)
1300 if (m_idCmdFirst
+ LOWORD(lpici
->lpVerb
) == m_idCmdLast
)
1303 LPCWSTR pwszExt
= PathFindExtensionW(m_wszPath
);
1305 info
.pcszFile
= m_wszPath
;
1306 info
.oaifInFlags
= OAIF_EXEC
;
1308 info
.oaifInFlags
|= OAIF_REGISTER_EXT
| OAIF_ALLOW_REGISTRATION
;
1309 info
.pcszClass
= NULL
;
1310 hr
= SHOpenWithDialog(lpici
->hwnd
, &info
);
1314 /* retrieve menu item info */
1316 ZeroMemory(&mii
, sizeof(mii
));
1317 mii
.cbSize
= sizeof(mii
);
1318 mii
.fMask
= MIIM_DATA
| MIIM_FTYPE
;
1320 if (GetMenuItemInfoW(m_hSubMenu
, LOWORD(lpici
->lpVerb
), TRUE
, &mii
) && mii
.dwItemData
)
1322 /* launch item with specified app */
1323 COpenWithList::SApp
*pApp
= (COpenWithList::SApp
*)mii
.dwItemData
;
1324 COpenWithList::Execute(pApp
, m_wszPath
);
1334 COpenWithMenu::GetCommandString(UINT_PTR idCmd
, UINT uType
,
1335 UINT
* pwReserved
, LPSTR pszName
, UINT cchMax
)
1337 FIXME("%p %lu %u %p %p %u\n", this,
1338 idCmd
, uType
, pwReserved
, pszName
, cchMax
);
1343 HRESULT WINAPI
COpenWithMenu::HandleMenuMsg(
1348 TRACE("This %p uMsg %x\n", this, uMsg
);
1354 COpenWithMenu::Initialize(LPCITEMIDLIST pidlFolder
,
1355 IDataObject
*pdtobj
,
1362 LPCITEMIDLIST pidlFolder2
;
1363 LPCITEMIDLIST pidlChild
;
1367 TRACE("This %p\n", this);
1370 return E_INVALIDARG
;
1372 fmt
.cfFormat
= RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
1374 fmt
.dwAspect
= DVASPECT_CONTENT
;
1376 fmt
.tymed
= TYMED_HGLOBAL
;
1378 hr
= pdtobj
->GetData(&fmt
, &medium
);
1382 ERR("pdtobj->GetData failed with 0x%x\n", hr
);
1386 pida
= (LPIDA
)GlobalLock(medium
.hGlobal
);
1387 ASSERT(pida
->cidl
>= 1);
1389 pidlFolder2
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+ pida
->aoffset
[0]);
1390 pidlChild
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+ pida
->aoffset
[1]);
1392 if (!_ILIsValue(pidlChild
))
1394 TRACE("pidl is not a file\n");
1395 GlobalUnlock(medium
.hGlobal
);
1396 GlobalFree(medium
.hGlobal
);
1400 pidl
= ILCombine(pidlFolder2
, pidlChild
);
1402 GlobalUnlock(medium
.hGlobal
);
1403 GlobalFree(medium
.hGlobal
);
1408 return E_OUTOFMEMORY
;
1411 if (!SHGetPathFromIDListW(pidl
, m_wszPath
))
1413 SHFree((void*)pidl
);
1414 ERR("SHGetPathFromIDListW failed\n");
1418 SHFree((void*)pidl
);
1419 TRACE("szPath %s\n", debugstr_w(m_wszPath
));
1421 pwszExt
= PathFindExtensionW(m_wszPath
);
1422 if (PathIsExeW(pwszExt
) || !_wcsicmp(pwszExt
, L
".lnk"))
1424 TRACE("file is a executable or shortcut\n");
1432 SHOpenWithDialog(HWND hwndParent
, const OPENASINFO
*poainfo
)
1437 TRACE("SHOpenWithDialog hwndParent %p poainfo %p\n", hwndParent
, poainfo
);
1439 InitCommonControls();
1441 if (poainfo
->pcszClass
== NULL
&& poainfo
->pcszFile
== NULL
)
1444 COpenWithDialog
pDialog(poainfo
);
1446 hwnd
= CreateDialogParam(shell32_hInstance
, MAKEINTRESOURCE(IDD_OPEN_WITH
), hwndParent
, COpenWithDialog::DialogProc
, (LPARAM
)&pDialog
);
1449 ERR("Failed to create dialog\n");
1453 if (pDialog
.IsNoOpen(hwndParent
))
1456 ShowWindow(hwnd
, SW_SHOWNORMAL
);
1458 while (GetMessage(&msg
, NULL
, 0, 0) && IsWindow(hwnd
))
1460 if (!IsDialogMessage(hwnd
, &msg
))
1462 TranslateMessage(&msg
);
1463 DispatchMessage(&msg
);