[shell32]
[reactos.git] / reactos / dll / win32 / shell32 / she_ocmenu.c
1 /*
2 * Open With Context Menu extension
3 *
4 * Copyright 2007 Johannes Anderwald <janderwald@reactos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <precomp.h>
22
23 WINE_DEFAULT_DEBUG_CHANNEL (shell);
24
25 ///
26 /// [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system]
27 /// "NoInternetOpenWith"=dword:00000001
28 ///
29
30 // TODO
31 // implement duplicate checks in list box
32 // implement duplicate checks for MRU!
33 // implement owner drawn menu
34
35 typedef struct
36 {
37 const IContextMenu2Vtbl *lpVtblContextMenu;
38 const IShellExtInitVtbl *lpvtblShellExtInit;
39 LONG wId;
40 volatile LONG ref;
41 BOOL NoOpen;
42 UINT count;
43 WCHAR szPath[MAX_PATH];
44 HMENU hSubMenu;
45 } SHEOWImpl, *LPSHEOWImpl;
46
47 typedef struct
48 {
49 BOOL bMenu;
50 HMENU hMenu;
51 HWND hDlgCtrl;
52 UINT Count;
53 BOOL NoOpen;
54 UINT idCmdFirst;
55 }OPEN_WITH_CONTEXT, *POPEN_WITH_CONTEXT;
56
57 #define MANUFACTURER_NAME_SIZE 100
58
59 typedef struct
60 {
61 HICON hIcon;
62 WCHAR szAppName[MAX_PATH];
63 WCHAR szManufacturer[MANUFACTURER_NAME_SIZE];
64 }OPEN_ITEM_CONTEXT, *POPEN_ITEM_CONTEXT;
65
66
67 typedef struct _LANGANDCODEPAGE_
68 {
69 WORD lang;
70 WORD code;
71 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
72
73 typedef struct {
74 DWORD cbSize;
75 DWORD uMax;
76 DWORD fFlags;
77 HKEY hKey;
78 LPWSTR lpszSubKey;
79 PROC lpfnCompare;
80 } MRUINFO, *LPMRUINFO;
81
82 #define MRUF_STRING_LIST 0
83
84 typedef HANDLE (WINAPI *CREATEMRULISTPROCW)(
85 LPMRUINFO lpmi
86 );
87
88 typedef int (WINAPI *ENUMMRULISTW)(
89 HANDLE hMRU,
90 int nItem,
91 void *lpData,
92 UINT uLen
93 );
94
95 typedef int (WINAPI *ADDMRUSTRINGW)(
96 HANDLE hMRU,
97 LPCWSTR szString
98 );
99
100 typedef void (WINAPI *FREEMRULIST)(
101 HANDLE hList);
102
103 static const IShellExtInitVtbl eivt;
104 static const IContextMenu2Vtbl cmvt;
105 static HRESULT WINAPI SHEOWCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj);
106 static ULONG WINAPI SHEOWCm_fnRelease(IContextMenu2 *iface);
107
108 HANDLE OpenMRUList(HKEY hKey);
109 void LoadItemFromHKCU(POPEN_WITH_CONTEXT pContext, WCHAR * szExt);
110 void LoadItemFromHKCR(POPEN_WITH_CONTEXT pContext, WCHAR * szExt);
111 void InsertOpenWithItem(POPEN_WITH_CONTEXT pContext, WCHAR * szAppName);
112
113 static HMODULE hModule = NULL;
114 static CREATEMRULISTPROCW CreateMRUListProcW = NULL;
115 static ENUMMRULISTW EnumMRUListW = NULL;
116 static FREEMRULIST FreeMRUListProc = NULL;
117 static ADDMRUSTRINGW AddMRUStringW = NULL;
118
119
120 HRESULT WINAPI SHEOW_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID *ppv)
121 {
122 SHEOWImpl * ow;
123 HRESULT res;
124
125 ow = LocalAlloc(LMEM_ZEROINIT, sizeof(SHEOWImpl));
126 if (!ow)
127 {
128 return E_OUTOFMEMORY;
129 }
130
131 ow->ref = 1;
132 ow->lpVtblContextMenu = &cmvt;
133 ow->lpvtblShellExtInit = &eivt;
134
135 TRACE("(%p)->()\n",ow);
136
137 res = SHEOWCm_fnQueryInterface( (IContextMenu2*)&ow->lpVtblContextMenu, riid, ppv );
138 SHEOWCm_fnRelease( (IContextMenu2*)&ow->lpVtblContextMenu );
139 return res;
140 }
141
142 static LPSHEOWImpl __inline impl_from_IShellExtInit( IShellExtInit *iface )
143 {
144 return (SHEOWImpl *)((char*)iface - FIELD_OFFSET(SHEOWImpl, lpvtblShellExtInit));
145 }
146
147 static LPSHEOWImpl __inline impl_from_IContextMenu( IContextMenu2 *iface )
148 {
149 return (SHEOWImpl *)((char*)iface - FIELD_OFFSET(SHEOWImpl, lpVtblContextMenu));
150 }
151
152 static HRESULT WINAPI SHEOWCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj)
153 {
154 SHEOWImpl *This = impl_from_IContextMenu(iface);
155
156 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
157
158 *ppvObj = NULL;
159
160 if(IsEqualIID(riid, &IID_IUnknown) ||
161 IsEqualIID(riid, &IID_IContextMenu) ||
162 IsEqualIID(riid, &IID_IContextMenu2))
163 {
164 *ppvObj = (void *)&This->lpVtblContextMenu;
165 }
166 else if(IsEqualIID(riid, &IID_IShellExtInit))
167 {
168 *ppvObj = (void *)&This->lpvtblShellExtInit;
169 }
170
171 if(*ppvObj)
172 {
173 IUnknown_AddRef((IUnknown*)*ppvObj);
174 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
175 return S_OK;
176 }
177 TRACE("-- Interface: E_NOINTERFACE\n");
178 return E_NOINTERFACE;
179 }
180
181 static ULONG WINAPI SHEOWCm_fnAddRef(IContextMenu2 *iface)
182 {
183 SHEOWImpl *This = impl_from_IContextMenu(iface);
184 ULONG refCount = InterlockedIncrement(&This->ref);
185
186 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
187
188 return refCount;
189 }
190
191 static ULONG WINAPI SHEOWCm_fnRelease(IContextMenu2 *iface)
192 {
193 SHEOWImpl *This = impl_from_IContextMenu(iface);
194 ULONG refCount = InterlockedDecrement(&This->ref);
195
196 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
197
198 if (!refCount)
199 {
200 TRACE(" destroying IContextMenu(%p)\n",This);
201 HeapFree(GetProcessHeap(),0,This);
202 }
203 return refCount;
204 }
205
206 VOID
207 AddItem(HMENU hMenu, UINT idCmdFirst)
208 {
209 MENUITEMINFOW mii;
210 WCHAR szBuffer[MAX_PATH];
211 static const WCHAR szChoose[] = { 'C','h','o','o','s','e',' ','P','r','o','g','r','a','m','.','.','.',0 };
212
213 ZeroMemory(&mii, sizeof(mii));
214 mii.cbSize = sizeof(mii);
215 mii.fMask = MIIM_TYPE | MIIM_ID;
216 mii.fType = MFT_SEPARATOR;
217 mii.wID = -1;
218 InsertMenuItemW(hMenu, -1, TRUE, &mii);
219
220 if (!LoadStringW(shell32_hInstance, IDS_OPEN_WITH_CHOOSE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
221 wcscpy(szBuffer, szChoose);
222
223 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
224
225 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
226 mii.fType = MFT_STRING;
227 mii.fState = MFS_ENABLED;
228 mii.wID = idCmdFirst;
229 mii.dwTypeData = (LPWSTR)szBuffer;
230 mii.cch = wcslen(szBuffer);
231
232 InsertMenuItemW(hMenu, -1, TRUE, &mii);
233 }
234
235 static
236 void
237 LoadOWItems(POPEN_WITH_CONTEXT pContext, LPCWSTR szName)
238 {
239 WCHAR * szExt;
240 WCHAR szPath[100];
241 DWORD dwPath;
242
243 szExt = wcsrchr(szName, '.');
244 if (!szExt)
245 {
246 /* FIXME
247 * show default list of available programs
248 */
249 return;
250 }
251
252 /* load programs directly associated from HKCU */
253 LoadItemFromHKCU(pContext, szExt);
254
255 /* load programs associated from HKCR\Extension */
256 LoadItemFromHKCR(pContext, szExt);
257
258 /* load programs referenced from HKCR\ProgId */
259 dwPath = sizeof(szPath);
260 szPath[0] = 0;
261 if (RegGetValueW(HKEY_CLASSES_ROOT, szExt, NULL, RRF_RT_REG_SZ, NULL, szPath, &dwPath) == ERROR_SUCCESS)
262 {
263 szPath[(sizeof(szPath)/sizeof(WCHAR))-1] = L'\0';
264 LoadItemFromHKCR(pContext, szPath);
265 }
266 }
267
268
269
270 static HRESULT WINAPI SHEOWCm_fnQueryContextMenu(
271 IContextMenu2 *iface,
272 HMENU hmenu,
273 UINT indexMenu,
274 UINT idCmdFirst,
275 UINT idCmdLast,
276 UINT uFlags)
277 {
278 MENUITEMINFOW mii;
279 WCHAR szBuffer[100] = {0};
280 INT pos;
281 HMENU hSubMenu = NULL;
282 OPEN_WITH_CONTEXT Context;
283 SHEOWImpl *This = impl_from_IContextMenu(iface);
284
285 if (LoadStringW(shell32_hInstance, IDS_OPEN_WITH, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)) < 0)
286 {
287 TRACE("failed to load string\n");
288 return E_FAIL;
289 }
290 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
291
292 hSubMenu = CreatePopupMenu();
293
294 /* set up context */
295 ZeroMemory(&Context, sizeof(OPEN_WITH_CONTEXT));
296 Context.bMenu = TRUE;
297 Context.Count = 0;
298 Context.hMenu = hSubMenu;
299 Context.idCmdFirst = idCmdFirst;
300 /* load items */
301 LoadOWItems(&Context, This->szPath);
302 if (!Context.Count)
303 {
304 DestroyMenu(hSubMenu);
305 hSubMenu = NULL;
306 This->wId = 0;
307 This->count = 0;
308 }
309 else
310 {
311 AddItem(hSubMenu, Context.idCmdFirst++);
312 This->count = Context.idCmdFirst - idCmdFirst;
313 /* verb start at index zero */
314 This->wId = This->count -1;
315 This->hSubMenu = hSubMenu;
316 }
317
318 pos = GetMenuDefaultItem(hmenu, TRUE, 0) + 1;
319
320 ZeroMemory(&mii, sizeof(mii));
321 mii.cbSize = sizeof(mii);
322 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
323 if (hSubMenu)
324 {
325 mii.fMask |= MIIM_SUBMENU;
326 mii.hSubMenu = hSubMenu;
327 }
328 mii.dwTypeData = (LPWSTR) szBuffer;
329 mii.fState = MFS_ENABLED;
330 if (!pos)
331 {
332 mii.fState |= MFS_DEFAULT;
333 }
334
335 mii.wID = Context.idCmdFirst;
336 mii.fType = MFT_STRING;
337 if (InsertMenuItemW( hmenu, pos, TRUE, &mii))
338 Context.Count++;
339
340 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Context.Count);
341 }
342
343 void
344 FreeListItems(HWND hwndDlg)
345 {
346 HWND hList;
347 LRESULT iIndex, iCount;
348 POPEN_ITEM_CONTEXT pContext;
349
350 hList = GetDlgItem(hwndDlg, 14002);
351 iCount = SendMessageW(hList, LB_GETCOUNT, 0, 0);
352 if (iCount == LB_ERR)
353 return;
354
355 for (iIndex = 0; iIndex < iCount; iIndex++)
356 {
357 pContext = (POPEN_ITEM_CONTEXT)SendMessageW(hList, LB_GETITEMDATA, iIndex, 0);
358 if (pContext)
359 {
360 DestroyIcon(pContext->hIcon);
361 SendMessageW(hList, LB_SETITEMDATA, iIndex, (LPARAM)0);
362 HeapFree(GetProcessHeap(), 0, pContext);
363 }
364 }
365 }
366
367 BOOL HideApplicationFromList(WCHAR * pFileName)
368 {
369 WCHAR szBuffer[100] = {'A','p','p','l','i','c','a','t','i','o','n','s','\\',0};
370 DWORD dwSize = 0;
371 LONG result;
372
373 if (wcslen(pFileName) > (sizeof(szBuffer)/sizeof(WCHAR)) - 14)
374 {
375 ERR("insufficient buffer\n");
376 return FALSE;
377 }
378 wcscpy(&szBuffer[13], pFileName);
379
380 result = RegGetValueW(HKEY_CLASSES_ROOT, szBuffer, L"NoOpenWith", RRF_RT_REG_SZ, NULL, NULL, &dwSize);
381
382 TRACE("result %d szBuffer %s\n", result, debugstr_w(szBuffer));
383
384 if (result == ERROR_SUCCESS)
385 return TRUE;
386 else
387 return FALSE;
388 }
389
390 VOID
391 WriteStaticShellExtensionKey(HKEY hRootKey, WCHAR * pVerb, WCHAR *pFullPath)
392 {
393 HKEY hShell;
394 LONG result;
395 WCHAR szBuffer[MAX_PATH+10] = {'s','h','e','l','l','\\', 0 };
396
397 if (wcslen(pVerb) > (sizeof(szBuffer)/sizeof(WCHAR)) - 15 ||
398 wcslen(pFullPath) > (sizeof(szBuffer)/sizeof(WCHAR)) - 4)
399 {
400 ERR("insufficient buffer\n");
401 return;
402 }
403
404 /* construct verb reg path */
405 wcscpy(&szBuffer[6], pVerb);
406 wcscat(szBuffer, L"\\command");
407
408 /* create verb reg key */
409 if (RegCreateKeyExW(hRootKey, szBuffer, 0, NULL, 0, KEY_WRITE, NULL, &hShell, NULL) != ERROR_SUCCESS)
410 return;
411
412 /* build command buffer */
413 wcscpy(szBuffer, pFullPath);
414 wcscat(szBuffer, L" %1");
415
416 result = RegSetValueExW(hShell, NULL, 0, REG_SZ, (const BYTE*)szBuffer, (wcslen(szBuffer)+1)* sizeof(WCHAR));
417 RegCloseKey(hShell);
418 }
419
420 VOID
421 StoreNewSettings(LPCWSTR szFileName, WCHAR *szAppName)
422 {
423 WCHAR szBuffer[100] = { L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\"};
424 WCHAR * pFileExt;
425 HKEY hKey;
426 LONG result;
427 HANDLE hList;
428
429 /* get file extension */
430 pFileExt = wcsrchr(szFileName, L'.');
431 if (wcslen(pFileExt) > (sizeof(szBuffer)/sizeof(WCHAR)) - 60)
432 {
433 ERR("insufficient buffer\n");
434 return;
435 }
436 wcscpy(&szBuffer[60], pFileExt);
437 /* open base key for this file extension */
438 if (RegCreateKeyExW(HKEY_CURRENT_USER, szBuffer, 0, NULL, 0, KEY_WRITE | KEY_READ, NULL, &hKey, NULL) != ERROR_SUCCESS)
439 return;
440
441 /* open mru list */
442 hList = OpenMRUList(hKey);
443
444 if (!hList)
445 {
446 RegCloseKey(hKey);
447 return;
448 }
449
450 /* insert the entry */
451 result = (*AddMRUStringW)(hList, szAppName);
452
453 /* close mru list */
454 (*FreeMRUListProc)((HANDLE)hList);
455 /* create mru list key */
456 RegCloseKey(hKey);
457 }
458
459 VOID
460 SetProgrammAsDefaultHandler(LPCWSTR szFileName, WCHAR * szAppName)
461 {
462 HKEY hKey;
463 HKEY hAppKey;
464 DWORD dwDisposition;
465 WCHAR szBuffer[100];
466 DWORD dwSize;
467 BOOL result;
468 WCHAR * pFileExt;
469 WCHAR * pFileName;
470
471 /* extract file extension */
472 pFileExt = wcsrchr(szFileName, L'.');
473 if (!pFileExt)
474 return;
475
476 /* create file extension key */
477 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, pFileExt, 0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS)
478 return;
479
480 if (dwDisposition & REG_CREATED_NEW_KEY)
481 {
482 /* a new entry was created create the prog key id */
483 wcscpy(szBuffer, &pFileExt[1]);
484 wcscat(szBuffer, L"_auto_file");
485 if (RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)szBuffer, (wcslen(szBuffer)+1) * sizeof(WCHAR)) != ERROR_SUCCESS)
486 {
487 RegCloseKey(hKey);
488 return;
489 }
490 }
491 else
492 {
493 /* entry already exists fetch prog key id */
494 dwSize = sizeof(szBuffer);
495 if (RegGetValueW(hKey, NULL, NULL, RRF_RT_REG_SZ, NULL, szBuffer, &dwSize) != ERROR_SUCCESS)
496 {
497 RegCloseKey(hKey);
498 return;
499 }
500 }
501 /* close file extension key */
502 RegCloseKey(hKey);
503
504 /* create prog id key */
505 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS)
506 return;
507
508
509 /* check if there already verbs existing for that app */
510 pFileName = wcsrchr(szAppName, L'\\');
511 wcscpy(szBuffer, L"Classes\\Applications\\");
512 wcscat(szBuffer, pFileName);
513 wcscat(szBuffer, L"\\shell");
514 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ, &hAppKey) == ERROR_SUCCESS)
515 {
516 /* copy static verbs from Classes\Applications key */
517 HKEY hTemp;
518 if (RegCreateKeyExW(hKey, L"shell", 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hTemp, &dwDisposition) == ERROR_SUCCESS)
519 {
520 result = RegCopyTreeW(hAppKey, NULL, hTemp);
521 RegCloseKey(hTemp);
522 if (result == ERROR_SUCCESS)
523 {
524 /* copied all subkeys, we are done */
525 RegCloseKey(hKey);
526 RegCloseKey(hAppKey);
527 return;
528 }
529 }
530 RegCloseKey(hAppKey);
531 }
532 /* write standard static shell extension */
533 WriteStaticShellExtensionKey(hKey, L"open", szAppName);
534 RegCloseKey(hKey);
535 }
536
537 void
538 BrowseForApplication(HWND hwndDlg)
539 {
540 WCHAR szBuffer[64] = {0};
541 WCHAR szFilter[256] = {0};
542 WCHAR szPath[MAX_PATH];
543 OPENFILENAMEW ofn;
544 OPEN_WITH_CONTEXT Context;
545 INT count;
546
547 /* load resource open with */
548 if (LoadStringW(shell32_hInstance, IDS_OPEN_WITH, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
549 {
550 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
551 ofn.lpstrTitle = szBuffer;
552 ofn.nMaxFileTitle = wcslen(szBuffer);
553 }
554
555 ZeroMemory(&ofn, sizeof(OPENFILENAMEW));
556 ofn.lStructSize = sizeof(OPENFILENAMEW);
557 ofn.hInstance = shell32_hInstance;
558 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
559 ofn.nMaxFile = (sizeof(szPath) / sizeof(WCHAR));
560 ofn.lpstrFile = szPath;
561
562 /* load the filter resource string */
563 if (LoadStringW(shell32_hInstance, IDS_OPEN_WITH_FILTER, szFilter, sizeof(szFilter) / sizeof(WCHAR)))
564 {
565 szFilter[(sizeof(szFilter)/sizeof(WCHAR))-1] = 0;
566 ofn.lpstrFilter = szFilter;
567 }
568 ZeroMemory(szPath, sizeof(szPath));
569
570 /* call openfilename */
571 if (!GetOpenFileNameW(&ofn))
572 return;
573
574 /* setup context for insert proc */
575 ZeroMemory(&Context, sizeof(OPEN_WITH_CONTEXT));
576 Context.hDlgCtrl = GetDlgItem(hwndDlg, 14002);
577 count = SendMessage(Context.hDlgCtrl, LB_GETCOUNT, 0, 0);
578 InsertOpenWithItem(&Context, szPath);
579 /* select new item */
580 SendMessage(Context.hDlgCtrl, LB_SETCURSEL, count, 0);
581 }
582
583 POPEN_ITEM_CONTEXT
584 GetCurrentOpenItemContext(HWND hwndDlg)
585 {
586 LRESULT result;
587
588 /* get current item */
589 result = SendDlgItemMessage(hwndDlg, 14002, LB_GETCURSEL, 0, 0);
590 if(result == LB_ERR)
591 return NULL;
592
593 /* get item context */
594 result = SendDlgItemMessage(hwndDlg, 14002, LB_GETITEMDATA, result, 0);
595 if (result == LB_ERR)
596 return NULL;
597
598 return (POPEN_ITEM_CONTEXT)result;
599 }
600
601 void
602 ExecuteOpenItem(POPEN_ITEM_CONTEXT pItemContext, LPCWSTR FileName)
603 {
604 STARTUPINFOW si;
605 PROCESS_INFORMATION pi;
606 WCHAR szPath[(MAX_PATH * 2)];
607
608 /* setup path with argument */
609 ZeroMemory(&si, sizeof(STARTUPINFOW));
610 si.cb = sizeof(STARTUPINFOW);
611 wcscpy(szPath, pItemContext->szAppName);
612 wcscat(szPath, L" ");
613 wcscat(szPath, FileName);
614
615 ERR("path %s\n", debugstr_w(szPath));
616
617 if (CreateProcessW(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
618 {
619 CloseHandle(pi.hThread);
620 CloseHandle(pi.hProcess);
621 SHAddToRecentDocs(SHARD_PATHW, FileName);
622 }
623 }
624
625
626 static INT_PTR CALLBACK OpenWithProgrammDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
627 {
628 LPMEASUREITEMSTRUCT lpmis;
629 LPDRAWITEMSTRUCT lpdis;
630 INT index;
631 WCHAR szBuffer[MAX_PATH + 30] = { 0 };
632 OPENASINFO *poainfo;
633 TEXTMETRIC mt;
634 COLORREF preColor, preBkColor;
635 POPEN_ITEM_CONTEXT pItemContext;
636 LONG YOffset;
637 OPEN_WITH_CONTEXT Context;
638
639 poainfo = (OPENASINFO*) GetWindowLongPtr(hwndDlg, DWLP_USER);
640
641 switch(uMsg)
642 {
643 case WM_INITDIALOG:
644 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG)lParam);
645 poainfo = (OPENASINFO*)lParam;
646 if (!(poainfo->oaifInFlags & OAIF_ALLOW_REGISTRATION))
647 EnableWindow(GetDlgItem(hwndDlg, 14003), FALSE);
648 if (poainfo->oaifInFlags & OAIF_FORCE_REGISTRATION)
649 SendDlgItemMessage(hwndDlg, 14003, BM_SETCHECK, BST_CHECKED, 0);
650 if (poainfo->oaifInFlags & OAIF_HIDE_REGISTRATION)
651 ShowWindow(GetDlgItem(hwndDlg, 14003), SW_HIDE);
652 if (poainfo->pcszFile)
653 {
654 szBuffer[0] = L'\0';
655 SendDlgItemMessageW(hwndDlg, 14001, WM_GETTEXT, sizeof(szBuffer), (LPARAM)szBuffer);
656 index = wcslen(szBuffer);
657 if (index + wcslen(poainfo->pcszFile) + 1 < sizeof(szBuffer)/sizeof(szBuffer[0]))
658 wcscat(szBuffer, poainfo->pcszFile);
659 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
660 SendDlgItemMessageW(hwndDlg, 14001, WM_SETTEXT, 0, (LPARAM)szBuffer);
661 ZeroMemory(&Context, sizeof(OPEN_WITH_CONTEXT));
662 Context.hDlgCtrl = GetDlgItem(hwndDlg, 14002);
663 LoadOWItems(&Context, poainfo->pcszFile);
664 SendMessage(Context.hDlgCtrl, LB_SETCURSEL, 0, 0);
665 }
666 return TRUE;
667 case WM_MEASUREITEM:
668 lpmis = (LPMEASUREITEMSTRUCT) lParam;
669 lpmis->itemHeight = 64;
670 return TRUE;
671 case WM_COMMAND:
672 switch(LOWORD(wParam))
673 {
674 case 14004: /* browse */
675 BrowseForApplication(hwndDlg);
676 return TRUE;
677 case 14002:
678 if (HIWORD(wParam) == LBN_SELCHANGE)
679 InvalidateRect((HWND)lParam, NULL, TRUE); // FIXME USE UPDATE RECT
680 break;
681 case 14005: /* ok */
682 pItemContext = GetCurrentOpenItemContext(hwndDlg);
683 if (pItemContext)
684 {
685 /* store settings in HKCU path */
686 StoreNewSettings(poainfo->pcszFile, pItemContext->szAppName);
687
688 if (SendDlgItemMessage(hwndDlg, 14003, BM_GETCHECK, 0, 0) == BST_CHECKED)
689 {
690 /* set programm as default handler */
691 SetProgrammAsDefaultHandler(poainfo->pcszFile, pItemContext->szAppName);
692 }
693
694 if (poainfo->oaifInFlags & OAIF_EXEC)
695 ExecuteOpenItem(pItemContext, poainfo->pcszFile);
696 }
697 FreeListItems(hwndDlg);
698 EndDialog(hwndDlg, 1);
699 return TRUE;
700 case 14006: /* cancel */
701 FreeListItems(hwndDlg);
702 EndDialog(hwndDlg, 0);
703 return TRUE;
704 default:
705 break;
706 }
707 break;
708 case WM_DRAWITEM:
709 lpdis = (LPDRAWITEMSTRUCT) lParam;
710 if (lpdis->itemID == -1)
711 break;
712
713 switch (lpdis->itemAction)
714 {
715 case ODA_SELECT:
716 case ODA_DRAWENTIRE:
717 index = SendMessageW(lpdis->hwndItem, LB_GETCURSEL, 0, 0);
718 pItemContext =(POPEN_ITEM_CONTEXT)SendMessage(lpdis->hwndItem, LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0);
719
720 if (lpdis->itemID == index)
721 {
722 /* paint focused item with standard background colour */
723 HBRUSH hBrush;
724 hBrush = CreateSolidBrush(RGB(46, 104, 160));
725 FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
726 DeleteObject(hBrush);
727 preBkColor = SetBkColor(lpdis->hDC, RGB(46, 104, 160));
728 }
729 else
730 {
731 /* paint non focused item with white background */
732 HBRUSH hBrush;
733 hBrush = CreateSolidBrush(RGB(255, 255, 255));
734 FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
735 DeleteObject(hBrush);
736 preBkColor = SetBkColor(lpdis->hDC, RGB(255, 255, 255));
737 }
738
739 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, (LPARAM) szBuffer);
740 /* paint the icon */
741 DrawIconEx(lpdis->hDC, lpdis->rcItem.left,lpdis->rcItem.top, pItemContext->hIcon, 0, 0, 0, NULL, DI_NORMAL);
742 /* get text size */
743 GetTextMetrics(lpdis->hDC, &mt);
744 /* paint app name */
745 YOffset = lpdis->rcItem.top + mt.tmHeight/2;
746 TextOutW(lpdis->hDC, 45, YOffset, szBuffer, wcslen(szBuffer));
747 /* paint manufacturer description */
748 YOffset += mt.tmHeight + 2;
749 preColor = SetTextColor(lpdis->hDC, RGB(192, 192, 192));
750 if (pItemContext->szManufacturer[0])
751 TextOutW(lpdis->hDC, 45, YOffset, pItemContext->szManufacturer, wcslen(pItemContext->szManufacturer));
752 else
753 TextOutW(lpdis->hDC, 45, YOffset, pItemContext->szAppName, wcslen(pItemContext->szAppName));
754 SetTextColor(lpdis->hDC, preColor);
755 SetBkColor(lpdis->hDC, preBkColor);
756 break;
757 }
758 break;
759 case WM_CLOSE:
760 FreeListItems(hwndDlg);
761 EndDialog(hwndDlg, 0);
762 return TRUE;
763 default:
764 break;
765 }
766 return FALSE;
767 }
768
769 void
770 FreeMenuItemContext(HMENU hMenu)
771 {
772 INT Count;
773 INT Index;
774 MENUITEMINFOW mii;
775
776 /* get item count */
777 Count = GetMenuItemCount(hMenu);
778 if (Count == -1)
779 return;
780
781 /* setup menuitem info */
782 ZeroMemory(&mii, sizeof(mii));
783 mii.cbSize = sizeof(mii);
784 mii.fMask = MIIM_DATA | MIIM_FTYPE;
785
786 for(Index = 0; Index < Count; Index++)
787 {
788 if (GetMenuItemInfoW(hMenu, Index, TRUE, &mii))
789 {
790 if ((mii.fType & MFT_SEPARATOR) || mii.dwItemData == 0)
791 continue;
792 HeapFree(GetProcessHeap(), 0, (LPVOID)mii.dwItemData);
793 }
794 }
795 }
796
797
798 static HRESULT WINAPI
799 SHEOWCm_fnInvokeCommand( IContextMenu2* iface, LPCMINVOKECOMMANDINFO lpici )
800 {
801 MENUITEMINFOW mii;
802 SHEOWImpl *This = impl_from_IContextMenu(iface);
803
804 ERR("This %p wId %x count %u verb %x\n", This, This->wId, This->count, LOWORD(lpici->lpVerb));
805
806 if (This->wId < LOWORD(lpici->lpVerb))
807 return E_FAIL;
808
809 if (This->wId == LOWORD(lpici->lpVerb))
810 {
811 OPENASINFO info;
812
813 info.pcszFile = This->szPath;
814 info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT | OAIF_EXEC;
815 info.pcszClass = NULL;
816 FreeMenuItemContext(This->hSubMenu);
817 return SHOpenWithDialog(lpici->hwnd, &info);
818 }
819
820 /* retrieve menu item info */
821 ZeroMemory(&mii, sizeof(mii));
822 mii.cbSize = sizeof(mii);
823 mii.fMask = MIIM_DATA | MIIM_FTYPE;
824
825 if (GetMenuItemInfoW(This->hSubMenu, LOWORD(lpici->lpVerb), TRUE, &mii))
826 {
827 POPEN_ITEM_CONTEXT pItemContext = (POPEN_ITEM_CONTEXT)mii.dwItemData;
828 if (pItemContext)
829 {
830 /* launch item with specified app */
831 ExecuteOpenItem(pItemContext, This->szPath);
832 }
833 }
834 /* free menu item context */
835 FreeMenuItemContext(This->hSubMenu);
836 return S_OK;
837 }
838
839 static HRESULT WINAPI
840 SHEOWCm_fnGetCommandString( IContextMenu2* iface, UINT_PTR idCmd, UINT uType,
841 UINT* pwReserved, LPSTR pszName, UINT cchMax )
842 {
843 SHEOWImpl *This = impl_from_IContextMenu(iface);
844
845 FIXME("%p %lu %u %p %p %u\n", This,
846 idCmd, uType, pwReserved, pszName, cchMax );
847
848 return E_NOTIMPL;
849 }
850
851 static HRESULT WINAPI SHEOWCm_fnHandleMenuMsg(
852 IContextMenu2 *iface,
853 UINT uMsg,
854 WPARAM wParam,
855 LPARAM lParam)
856 {
857 SHEOWImpl *This = impl_from_IContextMenu(iface);
858
859 TRACE("This %p uMsg %x\n",This, uMsg);
860
861 return E_NOTIMPL;
862 }
863
864 static const IContextMenu2Vtbl cmvt =
865 {
866 SHEOWCm_fnQueryInterface,
867 SHEOWCm_fnAddRef,
868 SHEOWCm_fnRelease,
869 SHEOWCm_fnQueryContextMenu,
870 SHEOWCm_fnInvokeCommand,
871 SHEOWCm_fnGetCommandString,
872 SHEOWCm_fnHandleMenuMsg
873 };
874
875 VOID
876 GetManufacturer(WCHAR * szAppName, POPEN_ITEM_CONTEXT pContext)
877 {
878 UINT VerSize;
879 DWORD DummyHandle;
880 LPVOID pBuf;
881 WORD lang = 0;
882 WORD code = 0;
883 LPLANGANDCODEPAGE lplangcode;
884 WCHAR szBuffer[100];
885 WCHAR * pResult;
886 BOOL bResult;
887
888 static const WCHAR wFormat[] = L"\\StringFileInfo\\%04x%04x\\CompanyName";
889 static const WCHAR wTranslation[] = L"VarFileInfo\\Translation";
890
891 /* query version info size */
892 VerSize = GetFileVersionInfoSizeW(szAppName, &DummyHandle);
893 if (!VerSize)
894 {
895 pContext->szManufacturer[0] = 0;
896 return;
897 }
898
899 /* allocate buffer */
900 pBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, VerSize);
901 if (!pBuf)
902 {
903 pContext->szManufacturer[0] = 0;
904 return;
905 }
906
907 /* query version info */
908 if(!GetFileVersionInfoW(szAppName, 0, VerSize, pBuf))
909 {
910 pContext->szManufacturer[0] = 0;
911 HeapFree(GetProcessHeap(), 0, pBuf);
912 return;
913 }
914
915 /* query lang code */
916 if(VerQueryValueW(pBuf, wTranslation, (LPVOID *)&lplangcode, &VerSize))
917 {
918 /* FIXME find language from current locale / if not available,
919 * default to english
920 * for now default to first available language
921 */
922 lang = lplangcode->lang;
923 code = lplangcode->code;
924 }
925 /* set up format */
926 swprintf(szBuffer, wFormat, lang, code);
927 /* query manufacturer */
928 pResult = NULL;
929 bResult = VerQueryValueW(pBuf, szBuffer, (LPVOID *)&pResult, &VerSize);
930
931 if (VerSize && bResult && pResult)
932 wcscpy(pContext->szManufacturer, pResult);
933 else
934 pContext->szManufacturer[0] = 0;
935 HeapFree(GetProcessHeap(), 0, pBuf);
936 }
937
938
939
940
941 void
942 InsertOpenWithItem(POPEN_WITH_CONTEXT pContext, WCHAR * szAppName)
943 {
944 MENUITEMINFOW mii;
945 POPEN_ITEM_CONTEXT pItemContext;
946 LRESULT index;
947 WCHAR * Offset;
948 WCHAR Buffer[_MAX_FNAME];
949
950 pItemContext = HeapAlloc(GetProcessHeap(), 0, sizeof(OPEN_ITEM_CONTEXT));
951 if (!pItemContext)
952 return;
953
954 /* store app path */
955 wcscpy(pItemContext->szAppName, szAppName);
956 /* null terminate it */
957 pItemContext->szAppName[MAX_PATH-1] = 0;
958 /* extract path name */
959 _wsplitpath(szAppName, NULL, NULL, Buffer, NULL);
960 Offset = wcsrchr(Buffer, '.');
961 if (Offset)
962 Offset[0] = L'\0';
963 Buffer[0] = towupper(Buffer[0]);
964
965 if (pContext->bMenu)
966 {
967 ZeroMemory(&mii, sizeof(mii));
968 mii.cbSize = sizeof(mii);
969 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
970 mii.fType = MFT_STRING; //MFT_OWNERDRAW;
971 mii.fState = MFS_ENABLED;
972 mii.wID = pContext->idCmdFirst;
973 mii.dwTypeData = Buffer;
974 mii.cch = wcslen(Buffer);
975 mii.dwItemData = (ULONG_PTR)pItemContext;
976 wcscpy(pItemContext->szManufacturer, Buffer);
977 if (InsertMenuItemW(pContext->hMenu, -1, TRUE, &mii))
978 {
979 pContext->idCmdFirst++;
980 pContext->Count++;
981 }
982 }
983 else
984 {
985 /* get default icon */
986 pItemContext->hIcon = ExtractIconW(shell32_hInstance, szAppName, 0);
987 /* get manufacturer */
988 GetManufacturer(pItemContext->szAppName, pItemContext);
989 index = SendMessageW(pContext->hDlgCtrl, LB_ADDSTRING, 0, (LPARAM)Buffer);
990 if (index != LB_ERR)
991 SendMessageW(pContext->hDlgCtrl, LB_SETITEMDATA, index, (LPARAM)pItemContext);
992 }
993 }
994
995 void
996 AddItemFromProgIDList(POPEN_WITH_CONTEXT pContext, HKEY hKey)
997 {
998 FIXME("implement me :)))\n");
999 }
1000
1001 HANDLE
1002 OpenMRUList(HKEY hKey)
1003 {
1004 MRUINFO info;
1005
1006 if (!hModule)
1007 {
1008 WCHAR szPath[MAX_PATH];
1009 if (!GetSystemDirectoryW(szPath, MAX_PATH))
1010 return 0;
1011 PathAddBackslashW(szPath);
1012 wcscat(szPath, L"comctl32.dll");
1013 hModule = LoadLibraryExW(szPath, NULL, 0);
1014 }
1015 CreateMRUListProcW = (CREATEMRULISTPROCW)GetProcAddress(hModule, MAKEINTRESOURCEA(400));
1016 EnumMRUListW = (ENUMMRULISTW)GetProcAddress(hModule, MAKEINTRESOURCEA(403));
1017 FreeMRUListProc = (FREEMRULIST)GetProcAddress(hModule, MAKEINTRESOURCEA(152));
1018 AddMRUStringW = (ADDMRUSTRINGW)GetProcAddress(hModule, MAKEINTRESOURCEA(401));
1019
1020 if (!CreateMRUListProcW || !EnumMRUListW || !FreeMRUListProc || !AddMRUStringW)
1021 return 0;
1022
1023 /* initialize mru list info */
1024 info.cbSize = sizeof(MRUINFO);
1025 info.uMax = 32;
1026 info.fFlags = MRUF_STRING_LIST;
1027 info.hKey = hKey;
1028 info.lpszSubKey = L"OpenWithList";
1029 info.lpfnCompare = NULL;
1030
1031 /* load list */
1032 return (*CreateMRUListProcW)(&info);
1033 }
1034
1035 void
1036 AddItemFromMRUList(POPEN_WITH_CONTEXT pContext, HKEY hKey)
1037 {
1038 HANDLE hList;
1039 int nItem, nCount, nResult;
1040 WCHAR szBuffer[MAX_PATH];
1041
1042 /* open mru list */
1043 hList = OpenMRUList(hKey);
1044 if (!hList)
1045 return;
1046
1047 /* get list count */
1048 nCount = (*EnumMRUListW)((HANDLE)hList, -1, NULL, 0);
1049
1050 for(nItem = 0; nItem < nCount; nItem++)
1051 {
1052 nResult = (*EnumMRUListW)((HANDLE)hList, nItem, szBuffer, MAX_PATH);
1053 if (nResult <= 0)
1054 continue;
1055 /* make sure its zero terminated */
1056 szBuffer[min(MAX_PATH-1, nResult)] = '\0';
1057 /* insert item */
1058 if (!HideApplicationFromList(szBuffer))
1059 InsertOpenWithItem(pContext, szBuffer);
1060 }
1061
1062 /* free the mru list */
1063 (*FreeMRUList)((HANDLE)hList);
1064 }
1065
1066
1067
1068 void
1069 LoadItemFromHKCR(POPEN_WITH_CONTEXT pContext, WCHAR * szExt)
1070 {
1071 HKEY hKey;
1072 HKEY hSubKey;
1073 WCHAR szBuffer[MAX_PATH+10];
1074 WCHAR szResult[100];
1075 DWORD dwSize;
1076
1077 static const WCHAR szOpenWithList[] = L"OpenWithList";
1078 static const WCHAR szOpenWithProgIds[] = L"OpenWithProgIDs";
1079 static const WCHAR szPerceivedType[] = L"PerceivedType";
1080 static const WCHAR szSysFileAssoc[] = L"SystemFileAssociations\\%s";
1081
1082 /* check if extension exists */
1083 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szExt, 0, KEY_READ | KEY_WRITE, &hKey) != ERROR_SUCCESS)
1084 return;
1085
1086 if (RegGetValueW(hKey, NULL, L"NoOpen", RRF_RT_REG_SZ, NULL, NULL, &dwSize) == ERROR_SUCCESS)
1087 {
1088 /* display warning dialog */
1089 pContext->NoOpen = TRUE;
1090 }
1091
1092 /* check if there is a directly available execute key */
1093 if (RegOpenKeyExW(hKey, L"shell\\open\\command", 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
1094 {
1095 DWORD dwBuffer = sizeof(szBuffer);
1096
1097 if (RegGetValueW(hSubKey, NULL, NULL, RRF_RT_REG_SZ, NULL, (PVOID)szBuffer, &dwBuffer) == ERROR_SUCCESS)
1098 {
1099 WCHAR * Ext = wcsrchr(szBuffer, ' ');
1100 if (Ext)
1101 {
1102 /* erase %1 or extra arguments */
1103 Ext[0] = 0;
1104 }
1105 if(!HideApplicationFromList(szBuffer))
1106 InsertOpenWithItem(pContext, szBuffer);
1107 }
1108 RegCloseKey(hSubKey);
1109 }
1110
1111 /* load items from HKCR\Ext\OpenWithList */
1112 if (RegOpenKeyExW(hKey, szOpenWithList, 0, KEY_READ | KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
1113 {
1114 AddItemFromMRUList(pContext, hKey);
1115 RegCloseKey(hSubKey);
1116 }
1117
1118 /* load items from HKCR\Ext\OpenWithProgIDs */
1119 if (RegOpenKeyExW(hKey, szOpenWithProgIds, 0, KEY_READ | KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS)
1120 {
1121 AddItemFromProgIDList(pContext, hSubKey);
1122 RegCloseKey(hSubKey);
1123 }
1124
1125 /* load items from SystemFileAssociations\Ext key */
1126 swprintf(szResult, szSysFileAssoc, szExt);
1127 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szResult, 0, KEY_READ | KEY_WRITE, &hSubKey) == ERROR_SUCCESS)
1128 {
1129 AddItemFromMRUList(pContext, hSubKey);
1130 RegCloseKey(hSubKey);
1131 }
1132
1133 /* load additional items from referenced PerceivedType*/
1134 dwSize = sizeof(szBuffer);
1135 if (RegGetValueW(hKey, NULL, szPerceivedType, RRF_RT_REG_SZ, NULL, szBuffer, &dwSize) != ERROR_SUCCESS)
1136 {
1137 RegCloseKey(hKey);
1138 return;
1139 }
1140 RegCloseKey(hKey);
1141
1142 /* terminate it explictely */
1143 szBuffer[29] = 0;
1144 swprintf(szResult, szSysFileAssoc, szBuffer);
1145 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szResult, 0, KEY_READ | KEY_WRITE, &hSubKey) == ERROR_SUCCESS)
1146 {
1147 AddItemFromMRUList(pContext, hSubKey);
1148 RegCloseKey(hSubKey);
1149 }
1150 }
1151
1152 void
1153 LoadItemFromHKCU(POPEN_WITH_CONTEXT pContext, WCHAR * szExt)
1154 {
1155 WCHAR szBuffer[MAX_PATH];
1156 HKEY hKey;
1157
1158 static const WCHAR szOpenWithProgIDs[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%s\\OpenWithProgIDs";
1159 static const WCHAR szOpenWithList[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%s";
1160
1161 /* handle first progid lists */
1162 swprintf(szBuffer, szOpenWithProgIDs, szExt);
1163 if (RegOpenKeyExW(HKEY_CURRENT_USER, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
1164 {
1165 AddItemFromProgIDList(pContext, hKey);
1166 RegCloseKey(hKey);
1167 }
1168
1169 /* now handle mru lists */
1170 swprintf(szBuffer, szOpenWithList, szExt);
1171 if (RegOpenKeyExW(HKEY_CURRENT_USER, szBuffer, 0, KEY_READ | KEY_WRITE, &hKey) == ERROR_SUCCESS)
1172 {
1173 AddItemFromMRUList(pContext, hKey);
1174 RegCloseKey(hKey);
1175 }
1176 }
1177
1178 HRESULT
1179 SHEOW_LoadOpenWithItems(SHEOWImpl *This, IDataObject *pdtobj)
1180 {
1181 STGMEDIUM medium;
1182 FORMATETC fmt;
1183 HRESULT hr;
1184 LPIDA pida;
1185 LPCITEMIDLIST pidl_folder;
1186 LPCITEMIDLIST pidl_child;
1187 LPCITEMIDLIST pidl;
1188 DWORD dwPath;
1189 LPWSTR szPtr;
1190 static const WCHAR szShortCut[] = { '.','l','n','k', 0 };
1191
1192 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
1193 fmt.ptd = NULL;
1194 fmt.dwAspect = DVASPECT_CONTENT;
1195 fmt.lindex = -1;
1196 fmt.tymed = TYMED_HGLOBAL;
1197
1198 hr = IDataObject_GetData(pdtobj, &fmt, &medium);
1199
1200 if (FAILED(hr))
1201 {
1202 ERR("IDataObject_GetData failed with 0x%x\n", hr);
1203 return hr;
1204 }
1205
1206 /*assert(pida->cidl==1);*/
1207 pida = (LPIDA)GlobalLock(medium.u.hGlobal);
1208
1209 pidl_folder = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
1210 pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]);
1211
1212 pidl = ILCombine(pidl_folder, pidl_child);
1213
1214 GlobalUnlock(medium.u.hGlobal);
1215 GlobalFree(medium.u.hGlobal);
1216
1217 if (!pidl)
1218 {
1219 ERR("no mem\n");
1220 return E_OUTOFMEMORY;
1221 }
1222 if (_ILIsDesktop(pidl) || _ILIsMyDocuments(pidl) || _ILIsControlPanel(pidl) || _ILIsNetHood(pidl) ||
1223 _ILIsBitBucket(pidl) || _ILIsDrive(pidl) || _ILIsCPanelStruct(pidl) || _ILIsFolder(pidl) || _ILIsControlPanel(pidl))
1224 {
1225 TRACE("pidl is a folder\n");
1226 SHFree((void*)pidl);
1227 return E_FAIL;
1228 }
1229
1230 if (!SHGetPathFromIDListW(pidl, This->szPath))
1231 {
1232 SHFree((void*)pidl);
1233 ERR("SHGetPathFromIDListW failed\n");
1234 return E_FAIL;
1235 }
1236
1237 SHFree((void*)pidl);
1238 TRACE("szPath %s\n", debugstr_w(This->szPath));
1239
1240 if (GetBinaryTypeW(This->szPath, &dwPath))
1241 {
1242 TRACE("path is a executable %x\n", dwPath);
1243 return E_FAIL;
1244 }
1245
1246 szPtr = wcsrchr(This->szPath, '.');
1247 if (szPtr)
1248 {
1249 if (!_wcsicmp(szPtr, szShortCut))
1250 {
1251 FIXME("pidl is a shortcut\n");
1252 return E_FAIL;
1253 }
1254 }
1255 return S_OK;
1256 }
1257
1258 static HRESULT WINAPI
1259 SHEOW_ExtInit_Initialize( IShellExtInit* iface, LPCITEMIDLIST pidlFolder,
1260 IDataObject *pdtobj, HKEY hkeyProgID )
1261 {
1262 SHEOWImpl *This = impl_from_IShellExtInit(iface);
1263
1264 TRACE("This %p\n", This);
1265
1266 return SHEOW_LoadOpenWithItems(This, pdtobj);
1267 }
1268
1269 static ULONG WINAPI SHEOW_ExtInit_AddRef(IShellExtInit *iface)
1270 {
1271 SHEOWImpl *This = impl_from_IShellExtInit(iface);
1272 ULONG refCount = InterlockedIncrement(&This->ref);
1273
1274 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1275
1276 return refCount;
1277 }
1278
1279 static ULONG WINAPI SHEOW_ExtInit_Release(IShellExtInit *iface)
1280 {
1281 SHEOWImpl *This = impl_from_IShellExtInit(iface);
1282 ULONG refCount = InterlockedDecrement(&This->ref);
1283
1284 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1285
1286 if (!refCount)
1287 {
1288 HeapFree(GetProcessHeap(),0,This);
1289 }
1290 return refCount;
1291 }
1292
1293 static HRESULT WINAPI
1294 SHEOW_ExtInit_QueryInterface( IShellExtInit* iface, REFIID riid, void** ppvObject )
1295 {
1296 SHEOWImpl *This = impl_from_IShellExtInit(iface);
1297 return SHEOWCm_fnQueryInterface((IContextMenu2*)This, riid, ppvObject);
1298 }
1299
1300 static const IShellExtInitVtbl eivt =
1301 {
1302 SHEOW_ExtInit_QueryInterface,
1303 SHEOW_ExtInit_AddRef,
1304 SHEOW_ExtInit_Release,
1305 SHEOW_ExtInit_Initialize
1306 };
1307
1308
1309 HRESULT WINAPI SHOpenWithDialog(
1310 HWND hwndParent,
1311 const OPENASINFO *poainfo
1312 )
1313 {
1314 MSG msg;
1315 BOOL bRet;
1316 HWND hwnd;
1317
1318 if (poainfo->pcszClass == NULL && poainfo->pcszFile == NULL)
1319 return E_FAIL;
1320
1321
1322 hwnd = CreateDialogParam(shell32_hInstance, MAKEINTRESOURCE(OPEN_WITH_PROGRAMM_DLG), hwndParent, OpenWithProgrammDlg, (LPARAM)poainfo);
1323 if (hwnd == NULL)
1324 {
1325 ERR("Failed to create dialog\n");
1326 return E_FAIL;
1327 }
1328 ShowWindow(hwnd, SW_SHOWNORMAL);
1329
1330 while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
1331 {
1332 if (!IsWindow(hwnd) || !IsDialogMessage(hwnd, &msg))
1333 {
1334 TranslateMessage(&msg);
1335 DispatchMessage(&msg);
1336 }
1337 }
1338 return S_OK;
1339 }