- Implement ProtocolResetComplete
[reactos.git] / dll / win32 / shell32 / shv_item_cmenu.c
1 /*
2 * IContextMenu for items in the shellview
3 *
4 * Copyright 1998, 2000 Juergen Schmied <juergen.schmied@debitel.net>
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 <string.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #include "winerror.h"
27 #include "wine/debug.h"
28
29 #include "windef.h"
30 #include "wingdi.h"
31 #include "pidl.h"
32 #include "undocshell.h"
33 #include "shlobj.h"
34 #include "objbase.h"
35
36 #include "shlwapi.h"
37 #include "shell32_main.h"
38 #include "shellfolder.h"
39 #include "debughlp.h"
40 #include "shresdef.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(shell);
42
43 /* ugly hack for cut&paste files */
44 BOOL fileMoving = FALSE;
45
46 typedef struct _StaticShellEntry_
47 {
48 LPWSTR szVerb;
49 LPWSTR szClass;
50 struct _StaticShellEntry_ * Next;
51 }StaticShellEntry, *PStaticShellEntry;
52
53 typedef struct _DynamicShellEntry_
54 {
55 UINT iIdCmdFirst;
56 UINT NumIds;
57 IContextMenu * CMenu;
58 struct _DynamicShellEntry_ * Next;
59 }DynamicShellEntry, *PDynamicShellEntry;
60
61 /**************************************************************************
62 * IContextMenu Implementation
63 */
64
65 typedef struct
66 { const IContextMenu2Vtbl *lpVtbl;
67 LONG ref;
68 IShellFolder* pSFParent;
69 LPITEMIDLIST pidl; /* root pidl */
70 LPITEMIDLIST *apidl; /* array of child pidls */
71 UINT cidl;
72 BOOL bAllValues;
73 PDynamicShellEntry dhead;
74 PStaticShellEntry head;
75 UINT iIdSCMFirst;
76 UINT iIdSCMLast;
77 UINT iIdSHEFirst;
78 UINT iIdSHELast;
79 SFGAOF rfg;
80 } ItemCmImpl;
81
82 UINT
83 SH_EnumerateDynamicContextHandlerForKey(LPWSTR szFileClass, ItemCmImpl *This, IDataObject * pDataObj, DWORD bGroupPolicyActive);
84 WCHAR *build_paths_list(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls);
85 WCHAR *strdupW(LPWSTR str);
86 static const IContextMenu2Vtbl cmvt;
87
88 /**************************************************************************
89 * ISvItemCm_CanRenameItems()
90 */
91 static BOOL ISvItemCm_CanRenameItems(ItemCmImpl *This)
92 { UINT i;
93 DWORD dwAttributes;
94
95 TRACE("(%p)->()\n",This);
96
97 if(This->apidl)
98 {
99 for(i = 0; i < This->cidl; i++){}
100 if(i > 1) return FALSE; /* can't rename more than one item at a time*/
101 dwAttributes = SFGAO_CANRENAME;
102 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)This->apidl, &dwAttributes);
103 return dwAttributes & SFGAO_CANRENAME;
104 }
105 return FALSE;
106 }
107
108 /**************************************************************************
109 * ISvItemCm_Constructor()
110 */
111 IContextMenu2 *ISvItemCm_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, const LPCITEMIDLIST *apidl, UINT cidl)
112 { ItemCmImpl* cm;
113 UINT u;
114
115 cm = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ItemCmImpl));
116 cm->lpVtbl = &cmvt;
117 cm->ref = 1;
118 cm->pidl = ILClone(pidl);
119 cm->pSFParent = pSFParent;
120
121 if(pSFParent)
122 {
123 HRESULT hr;
124 IShellFolder_AddRef(pSFParent);
125 cm->rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET;
126 hr = IShellFolder_GetAttributesOf(pSFParent, cidl, (LPCITEMIDLIST *)apidl, &cm->rfg);
127 if (!SUCCEEDED(hr))
128 cm->rfg = 0; /* No action available */
129 }
130
131 cm->apidl = _ILCopyaPidl(apidl, cidl);
132 cm->cidl = cidl;
133
134 cm->bAllValues = 1;
135 for(u = 0; u < cidl; u++)
136 {
137 cm->bAllValues &= (_ILIsValue(apidl[u]) ? 1 : 0);
138 }
139
140 TRACE("(%p)->()\n",cm);
141
142 return (IContextMenu2*)cm;
143 }
144
145 /**************************************************************************
146 * ISvItemCm_fnQueryInterface
147 */
148 static HRESULT WINAPI ISvItemCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj)
149 {
150 ItemCmImpl *This = (ItemCmImpl *)iface;
151
152 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
153
154 *ppvObj = NULL;
155
156 if(IsEqualIID(riid, &IID_IUnknown) ||
157 IsEqualIID(riid, &IID_IContextMenu) ||
158 IsEqualIID(riid, &IID_IContextMenu2))
159 {
160 *ppvObj = This;
161 }
162 else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/
163 {
164 FIXME("-- LPSHELLEXTINIT pointer requested\n");
165 }
166
167 if(*ppvObj)
168 {
169 IUnknown_AddRef((IUnknown*)*ppvObj);
170 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
171 return S_OK;
172 }
173 TRACE("-- Interface: E_NOINTERFACE\n");
174 return E_NOINTERFACE;
175 }
176
177 /**************************************************************************
178 * ISvItemCm_fnAddRef
179 */
180 static ULONG WINAPI ISvItemCm_fnAddRef(IContextMenu2 *iface)
181 {
182 ItemCmImpl *This = (ItemCmImpl *)iface;
183 ULONG refCount = InterlockedIncrement(&This->ref);
184
185 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
186
187 return refCount;
188 }
189
190 /**************************************************************************
191 * ISvItemCm_fnRelease
192 */
193 static ULONG WINAPI ISvItemCm_fnRelease(IContextMenu2 *iface)
194 {
195 ItemCmImpl *This = (ItemCmImpl *)iface;
196 ULONG refCount = InterlockedDecrement(&This->ref);
197 PStaticShellEntry curEntry;
198 PStaticShellEntry nextEntry;
199
200
201 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
202
203 if (!refCount)
204 {
205 TRACE(" destroying IContextMenu(%p)\n",This);
206
207 curEntry = nextEntry = This->head;
208 while(nextEntry)
209 {
210 nextEntry = nextEntry->Next;
211 free(curEntry->szVerb);
212 free(curEntry->szClass);
213 free(curEntry);
214 curEntry = nextEntry;
215 }
216
217 if(This->pSFParent)
218 IShellFolder_Release(This->pSFParent);
219
220 SHFree(This->pidl);
221
222 /*make sure the pidl is freed*/
223 _ILFreeaPidl(This->apidl, This->cidl);
224
225 HeapFree(GetProcessHeap(),0,This);
226 }
227 return refCount;
228 }
229
230 /**************************************************************************
231 * ICM_InsertItem()
232 */
233 void WINAPI _InsertMenuItem (
234 HMENU hmenu,
235 UINT indexMenu,
236 BOOL fByPosition,
237 UINT wID,
238 UINT fType,
239 LPCSTR dwTypeData,
240 UINT fState)
241 {
242 MENUITEMINFOA mii;
243
244 ZeroMemory(&mii, sizeof(mii));
245 mii.cbSize = sizeof(mii);
246 if (fType == MFT_SEPARATOR)
247 {
248 mii.fMask = MIIM_ID | MIIM_TYPE;
249 }
250 else
251 {
252 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
253 mii.dwTypeData = (LPSTR) dwTypeData;
254 mii.fState = fState;
255 }
256 mii.wID = wID;
257 mii.fType = fType;
258 InsertMenuItemA( hmenu, indexMenu, fByPosition, &mii);
259 }
260
261 HRESULT
262 DoCustomItemAction(ItemCmImpl *This, LPARAM lParam, UINT uMsg)
263 {
264 IContextMenu2 * cmenu;
265 MEASUREITEMSTRUCT * lpmis = (MEASUREITEMSTRUCT *)lParam;
266 HRESULT hResult;
267 UINT i;
268 PDynamicShellEntry curEntry;
269
270 TRACE("DoCustomItemAction entered with uMsg %x lParam %p\n", uMsg, lParam);
271
272 curEntry = This->dhead;
273 i = This->iIdSHEFirst;
274
275
276 while(curEntry)
277 {
278 if (i == lpmis->itemID)
279 break;
280
281 i++;
282 curEntry = curEntry->Next;
283 }
284
285 if (!curEntry)
286 return E_FAIL;
287
288 hResult = IContextMenu_QueryInterface(curEntry->CMenu, &IID_IContextMenu2, (void**)&cmenu);
289 if (hResult != S_OK)
290 {
291 ERR("failed to get IID_IContextMenu2 interface\n");
292 return hResult;
293 }
294
295 hResult = IContextMenu2_HandleMenuMsg(cmenu, uMsg, (WPARAM)0, lParam);
296 IContextMenu2_Release(cmenu);
297
298 TRACE("returning hResult %x\n", hResult);
299 return hResult;
300 }
301
302 UINT
303 SH_LoadContextMenuHandlers(ItemCmImpl *This, IDataObject * pDataObj, HMENU hMenu, UINT indexMenu )
304 {
305 UINT i;
306 WCHAR buffer[111];
307 WCHAR szProgKey[20];
308 char ebuf[10];
309 HRESULT hr;
310 HRESULT hResult;
311 UINT idCmdFirst = 0x6000;
312 UINT idCmdLast = 0xFFF0;
313 PDynamicShellEntry curEntry;
314 DWORD bGroupPolicyActive = FALSE;
315 DWORD dwSize;
316 static WCHAR szAny[] = { '*',0};
317
318 dwSize = sizeof(DWORD);
319 RegGetValueW(HKEY_CURRENT_USER,
320 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
321 L"EnforceShellExtensionSecurity",
322 RRF_RT_DWORD,
323 NULL,
324 &bGroupPolicyActive,
325 &dwSize);
326
327 SH_EnumerateDynamicContextHandlerForKey(szAny, This, pDataObj, bGroupPolicyActive);
328
329 for (i = 0; i < This->cidl; i++)
330 {
331 GUID * guid = _ILGetGUIDPointer(This->apidl[i]);
332 if (guid)
333 {
334 LPOLESTR pwszCLSID;
335 static const WCHAR CLSID[] = { 'C','L','S','I','D','\\',0 };
336 wcscpy(buffer, CLSID);
337 hr = StringFromCLSID(guid, &pwszCLSID);
338 if (hr == S_OK)
339 {
340 wcscpy(&buffer[6], pwszCLSID);
341 TRACE("buffer %s\n", debugstr_w(buffer));
342 SH_EnumerateDynamicContextHandlerForKey(buffer, This, pDataObj, bGroupPolicyActive);
343 }
344 }
345
346 if (_ILGetExtension(This->apidl[i], &ebuf[1], sizeof(ebuf) / sizeof(char)))
347 {
348 ebuf[0] = L'.';
349 buffer[0] = L'\0';
350 if (MultiByteToWideChar(CP_ACP, 0, ebuf, -1, buffer, 111))
351 {
352 SH_EnumerateDynamicContextHandlerForKey(buffer, This, pDataObj, bGroupPolicyActive);
353 dwSize = sizeof(szProgKey);
354 if (RegGetValueW(HKEY_CLASSES_ROOT, buffer, NULL, RRF_RT_REG_SZ, NULL, szProgKey, &dwSize) == ERROR_SUCCESS)
355 {
356 szProgKey[(sizeof(szProgKey)/sizeof(WCHAR))-1] = L'\0';
357 SH_EnumerateDynamicContextHandlerForKey(szProgKey, This, pDataObj, bGroupPolicyActive);
358 }
359 }
360 }
361 }
362 TRACE("-- done loading\n");
363 if (!This->dhead)
364 {
365 This->iIdSHEFirst = 0;
366 This->iIdSHELast = 0;
367 return indexMenu;
368 }
369
370 curEntry = This->dhead;
371 This->iIdSHEFirst = idCmdFirst;
372 do
373 {
374
375 hResult = IContextMenu_QueryContextMenu(curEntry->CMenu, hMenu, indexMenu, idCmdFirst, idCmdLast, CMF_NORMAL);
376 if (SUCCEEDED(hResult))
377 {
378 curEntry->iIdCmdFirst = idCmdFirst;
379 curEntry->NumIds = LOWORD(hResult);
380 indexMenu += curEntry->NumIds;
381 idCmdFirst += curEntry->NumIds + 0x10;
382 }
383 TRACE("curEntry %p hresult %x contextmenu %p cmdfirst %x num ids %x\n", curEntry, hResult, curEntry->CMenu, curEntry->iIdCmdFirst, curEntry->NumIds);
384 curEntry = curEntry->Next;
385 }while(curEntry);
386
387 This->iIdSHELast = idCmdFirst;
388 TRACE("SH_LoadContextMenuHandlers first %x last %x\n", This->iIdSHEFirst, This->iIdSHELast);
389 return indexMenu;
390 }
391
392 void
393 SH_AddStaticEntry(ItemCmImpl * This, HKEY hKey, WCHAR *szVerb, WCHAR * szClass)
394 {
395 PStaticShellEntry curEntry;
396 PStaticShellEntry lastEntry = NULL;
397
398 curEntry = This->head;
399
400 while(curEntry)
401 {
402 if (!wcsicmp(curEntry->szVerb, szVerb))
403 {
404 /* entry already exists */
405 return;
406 }
407 lastEntry = curEntry;
408 curEntry = curEntry->Next;
409 }
410
411 TRACE("adding verb %s szClass %s\n", debugstr_w(szVerb), debugstr_w(szClass));
412
413 curEntry = malloc(sizeof(StaticShellEntry));
414 if (curEntry)
415 {
416 curEntry->Next = NULL;
417 curEntry->szVerb = wcsdup(szVerb);
418 curEntry->szClass = wcsdup(szClass);
419 }
420
421 if (lastEntry)
422 {
423 lastEntry->Next = curEntry;
424 }
425 else
426 {
427 This->head = curEntry;
428 }
429 }
430
431 void
432 SH_AddStaticEntryForKey(ItemCmImpl * This, HKEY hKey, WCHAR * szClass)
433 {
434 LONG result;
435 DWORD dwIndex;
436 WCHAR szName[40];
437 DWORD dwName;
438
439 dwIndex = 0;
440 do
441 {
442 szName[0] = 0;
443 dwName = sizeof(szName) / sizeof(WCHAR);
444 result = RegEnumKeyExW(hKey, dwIndex, szName, &dwName, NULL, NULL, NULL, NULL);
445 szName[39] = 0;
446 if (result == ERROR_SUCCESS)
447 {
448 SH_AddStaticEntry(This, hKey, szName, szClass);
449 }
450 dwIndex++;
451 }while(result == ERROR_SUCCESS);
452 }
453
454 void
455 SH_AddStaticEntryForFileClass(ItemCmImpl * This, WCHAR * szExt)
456 {
457 WCHAR szBuffer[100];
458 HKEY hKey;
459 LONG result;
460 DWORD dwBuffer;
461
462 TRACE("SH_AddStaticEntryForFileClass entered with %s\n", debugstr_w(szExt));
463
464 wcscpy(szBuffer, szExt);
465 wcscat(szBuffer, L"\\shell");
466 result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
467 if (result == ERROR_SUCCESS)
468 {
469 SH_AddStaticEntryForKey(This, hKey, szExt);
470 RegCloseKey(hKey);
471 }
472
473 dwBuffer = sizeof(szBuffer);
474 result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, NULL, RRF_RT_REG_SZ, NULL, (LPBYTE)szBuffer, &dwBuffer);
475 if (result == ERROR_SUCCESS)
476 {
477 UINT length = strlenW(szBuffer);
478 wcscat(szBuffer, L"\\shell");
479 TRACE("szBuffer %s\n", debugstr_w(szBuffer));
480
481 result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
482 if (result == ERROR_SUCCESS)
483 {
484 szBuffer[length] = 0;
485 SH_AddStaticEntryForKey(This, hKey, szBuffer);
486 RegCloseKey(hKey);
487 }
488 }
489
490 strcpyW(szBuffer, "SystemFileAssociations\\");
491 dwBuffer = sizeof(szBuffer) - strlenW(szBuffer) * sizeof(WCHAR);
492 result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, L"PerceivedType", RRF_RT_REG_SZ, NULL, (LPBYTE)&szBuffer[23], &dwBuffer);
493 if (result == ERROR_SUCCESS)
494 {
495 UINT length = strlenW(szBuffer);
496 wcscat(szBuffer, L"\\shell");
497 TRACE("szBuffer %s\n", debugstr_w(szBuffer));
498
499 result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
500 if (result == ERROR_SUCCESS)
501 {
502 szBuffer[length] = 0;
503 SH_AddStaticEntryForKey(This, hKey, szBuffer);
504 RegCloseKey(hKey);
505 }
506 }
507 RegCloseKey(hKey);
508 }
509
510 void
511 SH_AddStaticEntrySpecial(ItemCmImpl * This)
512 {
513 if (_ILIsFolder(This->apidl[0])) // && (This->rfg & SFGAO_BROWSABLE))
514 {
515 SH_AddStaticEntryForFileClass(This, L"Folder");
516 }
517 else if (_ILIsDrive(This->apidl[0]))
518 {
519 SH_AddStaticEntryForFileClass(This, L"Drive");
520 }
521 }
522
523
524 UINT
525 SH_AddStaticEntryToMenu(HMENU hMenu, UINT indexMenu, ItemCmImpl * This)
526 {
527 MENUITEMINFOW mii;
528 PStaticShellEntry curEntry;
529 WCHAR szVerb[20];
530 UINT idResource;
531
532 mii.cbSize = sizeof(mii);
533 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
534 mii.fType = MFT_STRING;
535 mii.fState = MFS_ENABLED | MFS_DEFAULT;
536 mii.wID = 0x4000;
537 This->iIdSCMFirst = mii.wID;
538
539 curEntry = This->head;
540
541 while(curEntry)
542 {
543 if (!wcsicmp(curEntry->szVerb, L"open"))
544 idResource = IDS_OPEN_VERB;
545 else if (!wcsicmp(curEntry->szVerb, L"runas"))
546 idResource = IDS_RUNAS_VERB;
547 else if (!wcsicmp(curEntry->szVerb, L"edit"))
548 idResource = IDS_EDIT_VERB;
549 else if (!wcsicmp(curEntry->szVerb, L"find"))
550 idResource = IDS_FIND_VERB;
551 else if (!wcsicmp(curEntry->szVerb, L"print"))
552 idResource = IDS_PRINT_VERB;
553 else if (!wcsicmp(curEntry->szVerb, L"play"))
554 idResource = IDS_PLAY_VERB;
555 else if (!wcsicmp(curEntry->szVerb, L"preview"))
556 idResource = IDS_PREVIEW_VERB;
557 else
558 idResource = 0;
559
560 if (idResource > 0)
561 {
562 if (LoadStringW(shell32_hInstance, idResource, szVerb, sizeof(szVerb)/sizeof(WCHAR)))
563 {
564 szVerb[(sizeof(szVerb)/sizeof(WCHAR))-1] = L'\0';
565 mii.dwTypeData = szVerb;
566 }
567 else
568 {
569 WARN("unknown verb %s\n", debugstr_w(curEntry->szVerb));
570 mii.dwTypeData = curEntry->szVerb;
571 }
572 }
573 else
574 {
575 WARN("unknown verb %s\n", debugstr_w(curEntry->szVerb));
576 mii.dwTypeData = curEntry->szVerb;
577 }
578
579 mii.cch = strlenW(mii.dwTypeData);
580 InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii);
581 mii.fState = MFS_ENABLED;
582 mii.wID++;
583 curEntry = curEntry->Next;
584 }
585 This->iIdSCMLast = mii.wID - 1;
586 return indexMenu;
587 }
588
589 const char * GetLocalizedString(HMENU hMenu, UINT wID, const char * sDefault, char * sResult)
590 {
591 MENUITEMINFOA mii;
592 if (!hMenu)
593 {
594 return sDefault;
595 }
596
597 mii.cbSize = sizeof(mii);
598 mii.fMask = MIIM_TYPE;
599 mii.fType = MFT_STRING;
600 mii.dwTypeData = sResult;
601 mii.cch = 100;
602
603 if (GetMenuItemInfoA(hMenu, wID, FALSE, &mii))
604 {
605 return sResult;
606 }
607 else
608 {
609 return sDefault;
610 }
611 }
612
613 /**************************************************************************
614 * ISvItemCm_fnQueryContextMenu()
615 * FIXME: load menu MENU_SHV_FILE out of resources instead if creating
616 * each menu item by calling _InsertMenuItem()
617 */
618 static HRESULT WINAPI ISvItemCm_fnQueryContextMenu(
619 IContextMenu2 *iface,
620 HMENU hmenu,
621 UINT indexMenu,
622 UINT idCmdFirst,
623 UINT idCmdLast,
624 UINT uFlags)
625 {
626 IDataObject * pDataObj;
627 ItemCmImpl *This = (ItemCmImpl *)iface;
628 USHORT lastindex = 0;
629 HMENU hLocalMenu;
630 char sBuffer[100];
631 WCHAR szExt[10];
632
633 static const char sCopy[] = { '&','C','o','p','y',0 };
634 static const char sCut[] = { '&','C','u','t',0 };
635 static const char sDelete[] = { '&','D','e','l','e','t','e',0 };
636 static const char sRename[] = { '&','R','e','n','a','m','e',0 };
637 static const char sProperties[] = { '&','P','r','o','p','e','r','t','i','e','s',0 };
638 static const WCHAR szSHVFile[] = { 'M','E','N','U','_','S','H','V','_','F','I','L','E',0 };
639
640
641 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
642
643 hLocalMenu = LoadMenuW(shell32_hInstance, szSHVFile);
644
645 if (_ILGetExtension(This->apidl[0], &sBuffer[1], sizeof(sBuffer)-1))
646 {
647 sBuffer[0] = '.';
648 MultiByteToWideChar( CP_ACP, 0, sBuffer, -1, (LPWSTR)szExt, 10);
649 SH_AddStaticEntryForFileClass(This, szExt);
650 }
651 else
652 {
653 SH_AddStaticEntrySpecial(This);
654
655 }
656 indexMenu = SH_AddStaticEntryToMenu(hmenu, indexMenu, This);
657
658 SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION);
659 pDataObj = IDataObject_Constructor(NULL, This->pidl, (LPCITEMIDLIST *)This->apidl, This->cidl);
660 if (pDataObj)
661 {
662 indexMenu = SH_LoadContextMenuHandlers(This, pDataObj, hmenu, indexMenu);
663 IDataObject_Release(pDataObj);
664 }
665
666 if(!(CMF_DEFAULTONLY & uFlags) && This->cidl>0)
667 {
668 if(!(uFlags & CMF_EXPLORE))
669 _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Select", MFS_ENABLED);
670
671 TRACE("rfg %x\n", This->rfg);
672
673
674 if (This->rfg & (SFGAO_CANCOPY | SFGAO_CANMOVE))
675 {
676 _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
677 if (This->rfg & SFGAO_CANCOPY)
678 _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_COPY, MFT_STRING, GetLocalizedString(hLocalMenu, FCIDM_SHVIEW_COPY, sCopy, sBuffer), MFS_ENABLED);
679 if (This->rfg & SFGAO_CANMOVE)
680 _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_CUT, MFT_STRING, GetLocalizedString(hLocalMenu, FCIDM_SHVIEW_CUT, sCut, sBuffer), MFS_ENABLED);
681 }
682
683 if (This->rfg & SFGAO_CANDELETE)
684 {
685 _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
686 _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_DELETE, MFT_STRING, GetLocalizedString(hLocalMenu, FCIDM_SHVIEW_DELETE, sDelete, sBuffer), MFS_ENABLED);
687 }
688
689 if ((uFlags & CMF_CANRENAME) && (This->rfg & SFGAO_CANRENAME))
690 _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_RENAME, MFT_STRING, GetLocalizedString(hLocalMenu, FCIDM_SHVIEW_RENAME, sRename, sBuffer), ISvItemCm_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED);
691
692 if (This->rfg & SFGAO_HASPROPSHEET)
693 {
694 _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
695 _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_PROPERTIES, MFT_STRING, GetLocalizedString(hLocalMenu, FCIDM_SHVIEW_PROPERTIES, sProperties, sBuffer), MFS_ENABLED);
696 }
697
698 lastindex = FCIDM_SHVIEWLAST;
699 }
700
701 if (hLocalMenu)
702 {
703 DestroyMenu(hLocalMenu);
704 }
705
706 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, lastindex);
707 }
708
709 /**************************************************************************
710 * DoRename
711 */
712 static void DoRename(
713 IContextMenu2 *iface,
714 HWND hwnd)
715 {
716 ItemCmImpl *This = (ItemCmImpl *)iface;
717
718 LPSHELLBROWSER lpSB;
719 LPSHELLVIEW lpSV;
720
721 TRACE("(%p)->(wnd=%p)\n",This, hwnd);
722
723 /* get the active IShellView */
724 if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0)))
725 {
726 if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
727 {
728 TRACE("(sv=%p)\n",lpSV);
729 IShellView_SelectItem(lpSV, This->apidl[0],
730 SVSI_DESELECTOTHERS|SVSI_EDIT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_SELECT);
731 IShellView_Release(lpSV);
732 }
733 }
734 }
735
736 /**************************************************************************
737 * DoDelete
738 *
739 * deletes the currently selected items
740 */
741 static void DoDelete(IContextMenu2 *iface, HWND hwnd)
742 {
743 WCHAR szPath[MAX_PATH];
744 WCHAR * szTarget;
745 SHFILEOPSTRUCTW op;
746 LPSHELLBROWSER lpSB;
747 LPSHELLVIEW lpSV;
748 IPersistFolder2 * psf;
749 LPITEMIDLIST pidl;
750 STRRET strTemp;
751 ItemCmImpl *This = (ItemCmImpl *)iface;
752
753 if (IShellFolder2_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&psf) != S_OK)
754 {
755 ERR("Failed to get interface IID_IPersistFolder2\n");
756 return;
757 }
758
759 if (IPersistFolder2_GetCurFolder(psf, &pidl) != S_OK)
760 {
761 ERR("IPersistFolder2_GetCurFolder failed\n");
762 IPersistFolder2_Release(psf);
763 return;
764 }
765
766 if (IShellFolder2_GetDisplayNameOf(This->pSFParent, pidl, SHGDN_FORPARSING, &strTemp) != S_OK)
767 {
768 ERR("IShellFolder_GetDisplayNameOf failed\n");
769 IPersistFolder2_Release(psf);
770 return;
771 }
772 szPath[MAX_PATH-1] = 0;
773 StrRetToBufW(&strTemp, pidl, szPath, MAX_PATH);
774 PathAddBackslashW(szPath);
775 IPersistFolder2_Release(psf);
776
777 szTarget = build_paths_list(szPath, This->cidl, (LPCITEMIDLIST *)This->apidl);
778
779 if (pidl)
780 {
781 if (SHGetPathFromIDListW(pidl, szPath))
782 {
783 ZeroMemory(&op, sizeof(op));
784 op.hwnd = GetActiveWindow();
785 op.wFunc = FO_DELETE;
786 op.pFrom = szTarget;
787 op.fFlags = FOF_ALLOWUNDO;
788 SHFileOperationW(&op);
789 }
790 ILFree(pidl);
791 }
792
793 if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0)))
794 {
795 if (SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
796 {
797 IShellView_Refresh(lpSV);
798 }
799 }
800 }
801
802 /**************************************************************************
803 * DoCopyOrCut
804 *
805 * copies the currently selected items into the clipboard
806 */
807 static BOOL DoCopyOrCut(
808 IContextMenu2 *iface,
809 HWND hwnd,
810 BOOL bCut)
811 {
812 ItemCmImpl *This = (ItemCmImpl *)iface;
813
814 LPSHELLBROWSER lpSB;
815 LPSHELLVIEW lpSV;
816 LPDATAOBJECT lpDo;
817
818 TRACE("(%p)->(wnd=%p,bCut=0x%08x)\n",This, hwnd, bCut);
819
820 /* get the active IShellView */
821 if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0)))
822 {
823 if (SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
824 {
825 if (SUCCEEDED(IShellView_GetItemObject(lpSV, SVGIO_SELECTION, &IID_IDataObject, (LPVOID*)&lpDo)))
826 {
827 OleSetClipboard(lpDo);
828 IDataObject_Release(lpDo);
829 }
830 IShellView_Release(lpSV);
831 }
832 }
833 return TRUE;
834 }
835 static void DoProperties(
836 IContextMenu2 *iface,
837 HWND hwnd)
838 {
839 ItemCmImpl *This = (ItemCmImpl *)iface;
840 LPITEMIDLIST pidlFQ = NULL;
841 SHELLEXECUTEINFOA sei;
842
843 /*
844 * FIXXME
845 *
846 * The IShellFolder interface GetUIObject should create the specific item and then query if it has an IContextMenu interface
847 * If yes return interface to it.
848 */
849
850 if (_ILIsMyComputer(This->apidl[0]))
851 {
852 ShellExecuteA(hwnd, "open", "rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL);
853 return;
854 }
855 else if (_ILIsDesktop(This->apidl[0]))
856 {
857 ShellExecuteA(hwnd, "open", "rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL);
858 return;
859 }
860 else if (_ILIsDrive(This->apidl[0]))
861 {
862 WCHAR buffer[111];
863 ILGetDisplayName(This->apidl[0], buffer);
864 SH_ShowDriveProperties(buffer);
865 return;
866 }
867 else if (_ILIsNetHood(This->apidl[0]))
868 {
869 /* FIXME
870 * implement nethood properties
871 */
872 FIXME("implement nethood property dialog\n");
873 return;
874 }
875 else if (_ILIsBitBucket(This->apidl[0]))
876 {
877 ///FIXME
878 WCHAR szDrive = 'C';
879 SH_ShowRecycleBinProperties(szDrive);
880 }
881 else
882 {
883 pidlFQ = ILCombine(This->pidl, This->apidl[0]);
884 }
885
886 ZeroMemory(&sei, sizeof(sei));
887 sei.cbSize = sizeof(sei);
888 sei.fMask = SEE_MASK_INVOKEIDLIST;
889 sei.lpIDList = pidlFQ;
890 sei.hwnd = hwnd;
891 sei.nShow = SW_SHOWNORMAL;
892 sei.lpVerb = "properties";
893
894 TRACE("DoProperties before ShellExecuteEx\n");
895 ShellExecuteExA(&sei);
896 TRACE("DoProperties after ShellExecuteEx\n");
897
898 if (pidlFQ)
899 {
900 SHFree(pidlFQ);
901 }
902 }
903 HRESULT
904 DoStaticShellExtensions(ItemCmImpl *This, LPCMINVOKECOMMANDINFO lpcmi)
905 {
906 UINT i;
907 PStaticShellEntry curEntry;
908 LPITEMIDLIST pidl;
909 UINT bFolderFound = FALSE;
910 SHELLEXECUTEINFOW sei;
911
912 TRACE("DoStaticShellExtensions entered with lpVerb %x first %x last %x\n", LOWORD(lpcmi->lpVerb), This->iIdSCMFirst, This->iIdSCMLast);
913
914 i = This->iIdSCMFirst;
915 curEntry = This->head;
916
917 while(curEntry)
918 {
919 if (i == LOWORD(lpcmi->lpVerb))
920 break;
921
922 i++;
923 curEntry = curEntry->Next;
924 }
925
926 if (!curEntry)
927 {
928 ERR("unexpected\n");
929 return E_UNEXPECTED;
930 }
931
932 for(i = 0; i<This->cidl; i++)
933 {
934 if(!_ILIsValue(This->apidl[i]))
935 {
936 bFolderFound = TRUE;
937 break;
938 }
939 }
940
941 if (bFolderFound && wcsicmp(curEntry->szClass, L"Folder"))
942 {
943 /* when there is a folder with item selected
944 * do nothing
945 */
946 return S_OK;
947 }
948
949 TRACE("curEntry %p verb %s szClass %s\n", curEntry, debugstr_w(curEntry->szVerb), debugstr_w(curEntry->szClass));
950
951 pidl = ILCombine(This->pidl, This->apidl[0]);
952
953 ZeroMemory(&sei, sizeof(sei));
954 sei.cbSize = sizeof(sei);
955 sei.fMask = SEE_MASK_CLASSNAME | SEE_MASK_IDLIST;
956 sei.lpIDList = pidl;
957 sei.lpClass = curEntry->szClass;
958 sei.hwnd = lpcmi->hwnd;
959 sei.nShow = SW_SHOWNORMAL;
960 sei.lpVerb = curEntry->szVerb;
961 ShellExecuteExW(&sei);
962 SHFree(pidl);
963 return S_OK;
964 }
965
966 HRESULT
967 DoDynamicShellExtensions(ItemCmImpl *This, LPCMINVOKECOMMANDINFO lpcmi)
968 {
969 HRESULT hResult = NOERROR;
970 PDynamicShellEntry curEntry;
971 UINT id;
972
973 curEntry = This->dhead;
974 id = LOWORD(lpcmi->lpVerb);
975
976 while(curEntry)
977 {
978 if (curEntry->iIdCmdFirst <= id && curEntry->iIdCmdFirst + curEntry->NumIds >= id)
979 break;
980
981 curEntry = curEntry->Next;
982 }
983
984 if (!curEntry)
985 return E_FAIL;
986
987 lpcmi->lpVerb -= curEntry->iIdCmdFirst;
988
989 hResult = IContextMenu_InvokeCommand(curEntry->CMenu, lpcmi);
990
991 TRACE("DoDynamicShellExtensions hResult %x verb %x first %x\n", hResult, lpcmi->lpVerb, curEntry->iIdCmdFirst);
992 return hResult;
993 }
994
995
996 /**************************************************************************
997 * ISvItemCm_fnInvokeCommand()
998 */
999 static HRESULT WINAPI ISvItemCm_fnInvokeCommand(
1000 IContextMenu2 *iface,
1001 LPCMINVOKECOMMANDINFO lpcmi)
1002 {
1003 ItemCmImpl *This = (ItemCmImpl *)iface;
1004
1005 if (lpcmi->cbSize != sizeof(CMINVOKECOMMANDINFO))
1006 FIXME("Is an EX structure\n");
1007
1008 TRACE("ISvItemCm_fnInvokeCommand (%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
1009
1010 if( HIWORD(lpcmi->lpVerb)==0 && LOWORD(lpcmi->lpVerb) > FCIDM_SHVIEWLAST)
1011 {
1012 TRACE("Invalid Verb %x\n",LOWORD(lpcmi->lpVerb));
1013 return E_INVALIDARG;
1014 }
1015
1016 if (HIWORD(lpcmi->lpVerb) == 0)
1017 {
1018 switch(LOWORD(lpcmi->lpVerb))
1019 {
1020 case FCIDM_SHVIEW_RENAME:
1021 TRACE("Verb FCIDM_SHVIEW_RENAME\n");
1022 DoRename(iface, lpcmi->hwnd);
1023 break;
1024 case FCIDM_SHVIEW_DELETE:
1025 TRACE("Verb FCIDM_SHVIEW_DELETE\n");
1026 DoDelete(iface, lpcmi->hwnd);
1027 break;
1028 case FCIDM_SHVIEW_COPY:
1029 TRACE("Verb FCIDM_SHVIEW_COPY\n");
1030 DoCopyOrCut(iface, lpcmi->hwnd, FALSE);
1031 break;
1032 case FCIDM_SHVIEW_CUT:
1033 TRACE("Verb FCIDM_SHVIEW_CUT\n");
1034 DoCopyOrCut(iface, lpcmi->hwnd, TRUE);
1035 break;
1036 case FCIDM_SHVIEW_PROPERTIES:
1037 TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n");
1038 DoProperties(iface, lpcmi->hwnd);
1039 break;
1040 default:
1041 TRACE("iIdSHEFirst %x iIdSHELast %x iIdSCMFirst %x iIdSCMLast %x\n", This->iIdSHEFirst, This->iIdSHELast, This->iIdSCMFirst, This->iIdSCMLast);
1042 if (This->iIdSHEFirst && This->iIdSHELast)
1043 {
1044 if (LOWORD(lpcmi->lpVerb) >= This->iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= This->iIdSHELast)
1045 {
1046 return DoDynamicShellExtensions(This, lpcmi);
1047 }
1048 }
1049 if (This->iIdSCMFirst && This->iIdSCMLast)
1050 {
1051 if (LOWORD(lpcmi->lpVerb) >= This->iIdSCMFirst && LOWORD(lpcmi->lpVerb) <= This->iIdSCMLast)
1052 {
1053 return DoStaticShellExtensions(This, lpcmi);
1054 }
1055 }
1056 FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb));
1057 }
1058 }
1059 else
1060 {
1061 TRACE("Verb is %s\n",debugstr_a(lpcmi->lpVerb));
1062 if (strcmp(lpcmi->lpVerb,"delete")==0)
1063 DoDelete(iface, lpcmi->hwnd);
1064 else
1065 FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi->lpVerb));
1066 }
1067 return NOERROR;
1068 }
1069
1070 /**************************************************************************
1071 * ISvItemCm_fnGetCommandString()
1072 */
1073 static HRESULT WINAPI ISvItemCm_fnGetCommandString(
1074 IContextMenu2 *iface,
1075 UINT_PTR idCommand,
1076 UINT uFlags,
1077 UINT* lpReserved,
1078 LPSTR lpszName,
1079 UINT uMaxNameLen)
1080 {
1081 ItemCmImpl *This = (ItemCmImpl *)iface;
1082
1083 HRESULT hr = E_INVALIDARG;
1084
1085 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
1086
1087 switch(uFlags)
1088 {
1089 case GCS_HELPTEXTA:
1090 case GCS_HELPTEXTW:
1091 hr = E_NOTIMPL;
1092 break;
1093
1094 case GCS_VERBA:
1095 switch(idCommand)
1096 {
1097 case FCIDM_SHVIEW_RENAME:
1098 strcpy((LPSTR)lpszName, "rename");
1099 hr = NOERROR;
1100 break;
1101 }
1102 break;
1103
1104 /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
1105 case, you need to do the lstrcpyW to the pointer passed.*/
1106 case GCS_VERBW:
1107 switch(idCommand)
1108 { case FCIDM_SHVIEW_RENAME:
1109 MultiByteToWideChar( CP_ACP, 0, "rename", -1, (LPWSTR)lpszName, uMaxNameLen );
1110 hr = NOERROR;
1111 break;
1112 }
1113 break;
1114
1115 case GCS_VALIDATEA:
1116 case GCS_VALIDATEW:
1117 hr = NOERROR;
1118 break;
1119 }
1120 TRACE("-- (%p)->(name=%s)\n",This, lpszName);
1121 return hr;
1122 }
1123
1124 /**************************************************************************
1125 * ISvItemCm_fnHandleMenuMsg()
1126 * NOTES
1127 * should be only in IContextMenu2 and IContextMenu3
1128 * is nevertheless called from word95
1129 */
1130 static HRESULT WINAPI ISvItemCm_fnHandleMenuMsg(
1131 IContextMenu2 *iface,
1132 UINT uMsg,
1133 WPARAM wParam,
1134 LPARAM lParam)
1135 {
1136 ItemCmImpl *This = (ItemCmImpl *)iface;
1137 LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam;
1138 TRACE("(%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam);
1139
1140 switch(uMsg)
1141 {
1142 case WM_MEASUREITEM:
1143 case WM_DRAWITEM:
1144 if (lpmis->itemID >= This->iIdSHEFirst && lpmis->itemID <= This->iIdSHELast)
1145 return DoCustomItemAction(This, lParam, uMsg);
1146 break;
1147
1148 }
1149
1150 return E_NOTIMPL;
1151 }
1152
1153 static const IContextMenu2Vtbl cmvt =
1154 {
1155 ISvItemCm_fnQueryInterface,
1156 ISvItemCm_fnAddRef,
1157 ISvItemCm_fnRelease,
1158 ISvItemCm_fnQueryContextMenu,
1159 ISvItemCm_fnInvokeCommand,
1160 ISvItemCm_fnGetCommandString,
1161 ISvItemCm_fnHandleMenuMsg
1162 };
1163
1164 HRESULT
1165 SH_LoadDynamicContextMenuHandler(HKEY hKey, const CLSID * szClass, ItemCmImpl *This, IDataObject * pDataObj)
1166 {
1167 HRESULT hr;
1168 IContextMenu * cmobj;
1169 IShellExtInit *shext;
1170 PDynamicShellEntry curEntry;
1171 TRACE("SH_LoadDynamicContextMenuHandler entered with %s\n",wine_dbgstr_guid(szClass));
1172
1173 hr = SHCoCreateInstance(NULL, szClass, NULL, &IID_IContextMenu, (void**)&cmobj);
1174 if (hr != S_OK)
1175 {
1176 TRACE("SHCoCreateInstance failed %x\n", GetLastError());
1177 return hr;
1178 }
1179 hr = cmobj->lpVtbl->QueryInterface(cmobj, &IID_IShellExtInit, (void**)&shext);
1180 if (hr != S_OK)
1181 {
1182 TRACE("Failed to query for interface IID_IShellExtInit\n");
1183 cmobj->lpVtbl->Release(cmobj);
1184 return FALSE;
1185 }
1186 hr = shext->lpVtbl->Initialize(shext, NULL, pDataObj, hKey);
1187 if (hr != S_OK)
1188 {
1189 TRACE("Failed to initialize shell extension error %x\n", hr);
1190 shext->lpVtbl->Release(shext);
1191 cmobj->lpVtbl->Release(cmobj);
1192 return hr;
1193 }
1194 curEntry = malloc(sizeof(DynamicShellEntry));
1195 if(!curEntry)
1196 {
1197 return E_OUTOFMEMORY;
1198 }
1199
1200 curEntry->iIdCmdFirst = 0;
1201 curEntry->Next = NULL;
1202 curEntry->NumIds = 0;
1203 curEntry->CMenu = cmobj;
1204
1205 if (This->dhead)
1206 {
1207 PDynamicShellEntry pEntry = This->dhead;
1208
1209 while(pEntry->Next)
1210 {
1211 pEntry = pEntry->Next;
1212 }
1213
1214 pEntry->Next = curEntry;
1215 }
1216 else
1217 {
1218 This->dhead = curEntry;
1219 }
1220
1221 return hr;
1222 }
1223
1224 UINT
1225 SH_EnumerateDynamicContextHandlerForKey(const LPWSTR szFileClass, ItemCmImpl *This, IDataObject * pDataObj, DWORD bGroupPolicyActive)
1226 {
1227 HKEY hKey;
1228 WCHAR szKey[MAX_PATH] = {0};
1229 WCHAR szName[MAX_PATH] = {0};
1230 DWORD dwIndex, dwName;
1231 LONG res;
1232 HRESULT hResult;
1233 UINT index;
1234 CLSID clsid;
1235 static const WCHAR szShellEx[] = { '\\','s','h','e','l','l','e','x','\\','C','o','n','t','e','x','t','M','e','n','u','H','a','n','d','l','e','r','s',0 };
1236
1237 wcscpy(szKey, szFileClass);
1238 wcscat(szKey, szShellEx);
1239
1240 TRACE("SH_EnumerateDynamicContextHandlerForKey key %s\n", debugstr_w(szFileClass));
1241
1242 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
1243 {
1244 TRACE("RegOpenKeyExW failed for key %s\n", debugstr_w(szKey));
1245 return 0;
1246 }
1247
1248 dwIndex = 0;
1249 index = 0;
1250 do
1251 {
1252 dwName = MAX_PATH;
1253 res = RegEnumKeyExW(hKey, dwIndex, szName, &dwName, NULL, NULL, NULL, NULL);
1254 if (res == ERROR_SUCCESS)
1255 {
1256 hResult = CLSIDFromString(szName, &clsid);
1257 if (hResult != S_OK)
1258 {
1259 dwName = MAX_PATH;
1260 if (RegGetValueW(hKey, szName, NULL, RRF_RT_REG_SZ, NULL, szKey, &dwName) == ERROR_SUCCESS)
1261 {
1262 if (CLSIDFromString(szKey, &clsid) == S_OK)
1263 {
1264 if (bGroupPolicyActive)
1265 {
1266 if (RegGetValueW(HKEY_LOCAL_MACHINE,
1267 L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
1268 szKey,
1269 RRF_RT_REG_SZ,
1270 NULL,
1271 NULL,
1272 &dwName) == ERROR_SUCCESS)
1273 {
1274 SH_LoadDynamicContextMenuHandler(hKey, &clsid, This, pDataObj);
1275 }
1276
1277 }
1278 else
1279 {
1280 SH_LoadDynamicContextMenuHandler(hKey, &clsid, This, pDataObj);
1281 }
1282 }
1283 }
1284 }
1285 if (hResult == S_OK)
1286 {
1287 if (bGroupPolicyActive)
1288 {
1289 if (RegGetValueW(HKEY_LOCAL_MACHINE,
1290 L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
1291 szKey,
1292 RRF_RT_REG_SZ,
1293 NULL,
1294 NULL,
1295 &dwName) == ERROR_SUCCESS)
1296 {
1297 SH_LoadDynamicContextMenuHandler(hKey, &clsid, This, pDataObj);
1298 }
1299 }
1300 else
1301 {
1302 SH_LoadDynamicContextMenuHandler(hKey, &clsid, This, pDataObj);
1303 }
1304 }
1305 }
1306 dwIndex++;
1307 }while(res == ERROR_SUCCESS);
1308
1309 RegCloseKey(hKey);
1310 return index;
1311 }
1312
1313 /*************************************************************************
1314 * SHCreateDefaultContextMenu [SHELL32.325] Vista API
1315 *
1316 */
1317
1318 HRESULT WINAPI SHCreateDefaultContextMenu(
1319 const DEFCONTEXTMENU *pdcm,
1320 REFIID riid,
1321 void **ppv)
1322 {
1323 HRESULT hr;
1324 IContextMenu2 * pcm;
1325
1326 if (pdcm->cidl > 0)
1327 pcm = ISvItemCm_Constructor( pdcm->psf, pdcm->pidlFolder, pdcm->apidl, pdcm->cidl );
1328 else
1329 pcm = ISvBgCm_Constructor( pdcm->psf, TRUE );
1330
1331 hr = S_OK;
1332 *ppv = pcm;
1333
1334 return hr;
1335 }
1336
1337 /*************************************************************************
1338 * CDefFolderMenu_Create2 [SHELL32.701]
1339 *
1340 */
1341
1342 INT
1343 WINAPI
1344 CDefFolderMenu_Create2(
1345 LPCITEMIDLIST pidlFolder,
1346 HWND hwnd,
1347 UINT cidl,
1348 LPCITEMIDLIST *apidl,
1349 IShellFolder *psf,
1350 LPFNDFMCALLBACK lpfn,
1351 UINT nKeys,
1352 HKEY *ahkeyClsKeys,
1353 IContextMenu **ppcm)
1354 {
1355 DEFCONTEXTMENU pdcm;
1356 HRESULT hr;
1357
1358 pdcm.hwnd = hwnd;
1359 pdcm.pcmcb = NULL; //FIXME
1360 pdcm.pidlFolder = pidlFolder;
1361 pdcm.psf = psf;
1362 pdcm.cidl = cidl;
1363 pdcm.apidl = apidl;
1364 pdcm.punkAssociationInfo = NULL;
1365 pdcm.cKeys = nKeys;
1366 pdcm.aKeys = ahkeyClsKeys;
1367
1368 hr = SHCreateDefaultContextMenu(&pdcm, &IID_IContextMenu, (void**)ppcm);
1369 return hr;
1370 }