Revert an unwanted change from r66575.
[reactos.git] / reactos / dll / win32 / shell32 / shv_item_new.c
1 /*
2 * PROJECT: shell32
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/shell32/shv_item_new.c
5 * PURPOSE: provides new shell item service
6 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
7 */
8
9 #include <precomp.h>
10
11 WINE_DEFAULT_DEBUG_CHANNEL(shell);
12
13 typedef enum
14 {
15 SHELLNEW_TYPE_COMMAND = 1,
16 SHELLNEW_TYPE_DATA = 2,
17 SHELLNEW_TYPE_FILENAME = 4,
18 SHELLNEW_TYPE_NULLFILE = 8
19 }SHELLNEW_TYPE;
20
21
22 typedef struct __SHELLNEW_ITEM__
23 {
24 SHELLNEW_TYPE Type;
25 LPWSTR szExt;
26 LPWSTR szTarget;
27 LPWSTR szDesc;
28 LPWSTR szIcon;
29 struct __SHELLNEW_ITEM__ * Next;
30 }SHELLNEW_ITEM, *PSHELLNEW_ITEM;
31
32 typedef struct
33 {
34 const IContextMenu2Vtbl *lpVtblContextMenu;
35 const IShellExtInitVtbl *lpvtblShellExtInit;
36 LPWSTR szPath;
37 IShellFolder *pSFParent;
38 PSHELLNEW_ITEM s_SnHead;
39 }INewMenuImpl, *LPINewMenuImpl;
40
41 //static const IContextMenu2Vtbl cmvt;
42 //static const IShellExtInitVtbl sei;
43 static WCHAR szNew[MAX_PATH];
44
45
46 static
47 BOOL
48 GetKeyDescription(LPWSTR szKeyName, LPWSTR szResult)
49 {
50 HKEY hKey;
51 DWORD dwDesc, dwError;
52 WCHAR szDesc[100];
53
54 static const WCHAR szFriendlyTypeName[] = { '\\','F','r','i','e','n','d','l','y','T','y','p','e','N','a','m','e',0 };
55
56 TRACE("GetKeyDescription: keyname %s\n", debugstr_w(szKeyName));
57
58 if (RegOpenKeyExW(HKEY_CLASSES_ROOT,szKeyName,0, KEY_READ | KEY_QUERY_VALUE,&hKey) != ERROR_SUCCESS)
59 return FALSE;
60
61 if (RegLoadMUIStringW(hKey,szFriendlyTypeName,szResult,MAX_PATH,&dwDesc,0,NULL) == ERROR_SUCCESS)
62 {
63 TRACE("result %s\n", debugstr_w(szResult));
64 RegCloseKey(hKey);
65 return TRUE;
66 }
67 /* fetch default value */
68 dwDesc = sizeof(szDesc);
69 dwError = RegGetValueW(hKey,NULL,NULL, RRF_RT_REG_SZ,NULL,szDesc,&dwDesc);
70 if(dwError == ERROR_SUCCESS)
71 {
72 if (wcsncmp(szKeyName, szDesc, dwDesc / sizeof(WCHAR)))
73 {
74 /* recurse for to a linked key */
75 if (!GetKeyDescription(szDesc, szResult))
76 {
77 /* use description */
78 wcscpy(szResult, szDesc);
79 }
80 }
81 else
82 {
83 /* use default value as description */
84 wcscpy(szResult, szDesc);
85 }
86 }
87 else
88 {
89 /* registry key w/o default key?? */
90 TRACE("RegGetValue failed with %x\n", dwError);
91 wcscpy(szResult, szKeyName);
92 }
93
94 RegCloseKey(hKey);
95 return TRUE;
96 }
97
98
99 PSHELLNEW_ITEM LoadItem(LPWSTR szKeyName)
100 {
101 HKEY hKey;
102 DWORD dwIndex;
103 WCHAR szName[MAX_PATH];
104 WCHAR szCommand[MAX_PATH];
105 WCHAR szDesc[MAX_PATH] = {0};
106 WCHAR szIcon[MAX_PATH] = {0};
107 DWORD dwName, dwCommand;
108 LONG result;
109 PSHELLNEW_ITEM pNewItem;
110
111 static const WCHAR szShellNew[] = { '\\','S','h','e','l','l','N','e','w',0 };
112 static const WCHAR szCmd[] = { 'C','o','m','m','a','n','d',0 };
113 static const WCHAR szData[] = { 'D','a','t','a',0 };
114 static const WCHAR szFileName[] = { 'F','i','l','e','N','a','m','e', 0 };
115 static const WCHAR szNullFile[] = { 'N','u','l','l','F','i','l','e', 0 };
116
117
118 wcscpy(szName, szKeyName);
119 GetKeyDescription(szKeyName, szDesc);
120 wcscat(szName, szShellNew);
121 result = RegOpenKeyExW(HKEY_CLASSES_ROOT,szName,0,KEY_READ,&hKey);
122
123 //TRACE("LoadItem dwName %d keyname %s szName %s szDesc %s szIcon %s\n", dwName, debugstr_w(szKeyName), debugstr_w(szName), debugstr_w(szDesc), debugstr_w(szIcon));
124
125 if (result != ERROR_SUCCESS)
126 {
127 return NULL;
128 }
129
130 dwIndex = 0;
131 pNewItem = NULL;
132
133 do
134 {
135 dwName = MAX_PATH;
136 dwCommand = MAX_PATH;
137 result = RegEnumValueW(hKey,dwIndex,szName,&dwName,NULL,NULL,(LPBYTE)szCommand, &dwCommand);
138 if (result == ERROR_SUCCESS)
139 {
140 long type = -1;
141 LPWSTR szTarget = szCommand;
142 //TRACE("szName %s szCommand %s\n", debugstr_w(szName), debugstr_w(szCommand));
143 if (!wcsicmp(szName, szCmd))
144 {
145 type = SHELLNEW_TYPE_COMMAND;
146 }else if (!wcsicmp(szName, szData))
147 {
148 type = SHELLNEW_TYPE_DATA;
149 }
150 else if (!wcsicmp(szName, szFileName))
151 {
152 type = SHELLNEW_TYPE_FILENAME;
153 }
154 else if (!wcsicmp(szName, szNullFile))
155 {
156 type = SHELLNEW_TYPE_NULLFILE;
157 szTarget = NULL;
158 }
159 if (type != -1)
160 {
161 pNewItem = HeapAlloc(GetProcessHeap(), 0, sizeof(SHELLNEW_ITEM));
162 pNewItem->Type = type;
163 if (szTarget)
164 pNewItem->szTarget = _wcsdup(szTarget);
165 else
166 pNewItem->szTarget = NULL;
167
168 pNewItem->szDesc = _wcsdup(szDesc);
169 pNewItem->szIcon = _wcsdup(szIcon);
170 pNewItem->szExt = _wcsdup(szKeyName);
171 pNewItem->Next = NULL;
172 break;
173 }
174 }
175 dwIndex++;
176 }while(result != ERROR_NO_MORE_ITEMS);
177 RegCloseKey(hKey);
178 return pNewItem;
179 }
180
181
182 BOOL
183 LoadShellNewItems(INewMenuImpl * This)
184 {
185 DWORD dwIndex;
186 WCHAR szName[MAX_PATH];
187 LONG result;
188 PSHELLNEW_ITEM pNewItem;
189 PSHELLNEW_ITEM pCurItem = NULL;
190 static WCHAR szLnk[] = { '.','l','n','k',0 };
191
192 /* insert do new folder action */
193 if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEW, szNew, sizeof(szNew) / sizeof(WCHAR)))
194 szNew[0] = 0;
195 szNew[MAX_PATH-1] = 0;
196
197 dwIndex = 0;
198 do
199 {
200 result = RegEnumKeyW(HKEY_CLASSES_ROOT,dwIndex,szName,MAX_PATH);
201 if (result == ERROR_SUCCESS)
202 {
203 pNewItem = LoadItem(szName);
204 if (pNewItem)
205 {
206 if (!wcsicmp(pNewItem->szExt, szLnk))
207 {
208 if (This->s_SnHead)
209 {
210 pNewItem->Next = This->s_SnHead;
211 This->s_SnHead = pNewItem;
212 }
213 else
214 {
215 This->s_SnHead = pCurItem = pNewItem;
216 }
217 }
218 else
219 {
220 if (pCurItem)
221 {
222 pCurItem->Next = pNewItem;
223 pCurItem = pNewItem;
224 }
225 else
226 {
227 pCurItem = This->s_SnHead = pNewItem;
228 }
229 }
230 }
231 }
232 dwIndex++;
233 }while(result != ERROR_NO_MORE_ITEMS);
234
235 if (This->s_SnHead == NULL)
236 return FALSE;
237 else
238 return TRUE;
239 }
240
241 UINT
242 InsertShellNewItems(HMENU hMenu, UINT idFirst, UINT idMenu, INewMenuImpl * This)
243 {
244 MENUITEMINFOW mii;
245 PSHELLNEW_ITEM pCurItem;
246 UINT i;
247 WCHAR szBuffer[MAX_PATH];
248
249 if (This->s_SnHead == NULL)
250 {
251 if (!LoadShellNewItems(This))
252 return 0;
253 }
254
255 ZeroMemory(&mii, sizeof(mii));
256 mii.cbSize = sizeof(mii);
257
258 /* insert do new shortcut action */
259 if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWFOLDER, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0])))
260 szBuffer[0] = 0;
261 szBuffer[MAX_PATH-1] = 0;
262 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
263 mii.fType = MFT_STRING;
264 mii.dwTypeData = szBuffer;
265 mii.cch = wcslen(mii.dwTypeData);
266 mii.wID = idFirst++;
267 InsertMenuItemW(hMenu, idMenu++, TRUE, &mii);
268
269 /* insert do new shortcut action */
270 if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWLINK, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0])))
271 szBuffer[0] = 0;
272 szBuffer[MAX_PATH-1] = 0;
273 mii.dwTypeData = szBuffer;
274 mii.cch = wcslen(mii.dwTypeData);
275 mii.wID = idFirst++;
276 InsertMenuItemW(hMenu, idMenu++, TRUE, &mii);
277
278 /* insert seperator for custom new action */
279 mii.fMask = MIIM_TYPE | MIIM_ID;
280 mii.fType = MFT_SEPARATOR;
281 mii.wID = -1;
282 InsertMenuItemW(hMenu, idMenu++, TRUE, &mii);
283
284 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
285 /*
286 * FIXME
287 * implement loading of icons
288 * and using MFT_OWNERDRAWN
289 */
290 mii.fType = MFT_STRING;
291 mii.fState = MFS_ENABLED;
292
293 pCurItem = This->s_SnHead;
294 i = 0;
295
296 while(pCurItem)
297 {
298 if (i >= 1)
299 {
300 TRACE("szDesc %s\n", debugstr_w(pCurItem->szDesc));
301 mii.dwTypeData = pCurItem->szDesc;
302 mii.cch = wcslen(mii.dwTypeData);
303 mii.wID = idFirst++;
304 InsertMenuItemW(hMenu, idMenu++, TRUE, &mii);
305 }
306 pCurItem = pCurItem->Next;
307 i++;
308 }
309 return (i+2);
310 }
311
312 HRESULT
313 DoShellNewCmd(INewMenuImpl * This, LPCMINVOKECOMMANDINFO lpcmi)
314 {
315 PSHELLNEW_ITEM pCurItem = This->s_SnHead;
316 IPersistFolder3 * psf;
317 LPITEMIDLIST pidl;
318 STRRET strTemp;
319 WCHAR szTemp[MAX_PATH];
320 WCHAR szBuffer[MAX_PATH];
321 WCHAR szPath[MAX_PATH];
322 STARTUPINFOW sInfo;
323 PROCESS_INFORMATION pi;
324 UINT i, target;
325 HANDLE hFile;
326 DWORD dwWritten, dwError;
327
328 static const WCHAR szP1[] = { '%', '1', 0 };
329 static const WCHAR szFormat[] = {'%','s',' ','(','%','d',')','%','s',0 };
330
331 i = 1;
332 target = LOWORD(lpcmi->lpVerb);
333
334 while(pCurItem)
335 {
336 if (i == target)
337 break;
338
339 pCurItem = pCurItem->Next;
340 i++;
341 }
342
343 if (!pCurItem)
344 return E_UNEXPECTED;
345
346 if (IShellFolder2_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&psf) != S_OK)
347 {
348 ERR("Failed to get interface IID_IPersistFolder2\n");
349 return E_FAIL;
350 }
351 if (IPersistFolder2_GetCurFolder(psf, &pidl) != S_OK)
352 {
353 ERR("IPersistFolder2_GetCurFolder failed\n");
354 return E_FAIL;
355 }
356
357 if (IShellFolder2_GetDisplayNameOf(This->pSFParent, pidl, SHGDN_FORPARSING, &strTemp) != S_OK)
358 {
359 ERR("IShellFolder_GetDisplayNameOf failed\n");
360 return E_FAIL;
361 }
362 StrRetToBufW(&strTemp, pidl, szPath, MAX_PATH);
363
364 switch(pCurItem->Type)
365 {
366 case SHELLNEW_TYPE_COMMAND:
367 {
368 LPWSTR ptr;
369 LPWSTR szCmd;
370
371 if (!ExpandEnvironmentStringsW(pCurItem->szTarget, szBuffer, MAX_PATH))
372 {
373 TRACE("ExpandEnvironmentStrings failed\n");
374 break;
375 }
376
377 ptr = wcsstr(szBuffer, szP1);
378 if (ptr)
379 {
380 ptr[1] = 's';
381 swprintf(szTemp, szBuffer, szPath);
382 ptr = szTemp;
383 }
384 else
385 {
386 ptr = szBuffer;
387 }
388
389 ZeroMemory(&sInfo, sizeof(sInfo));
390 sInfo.cb = sizeof(sInfo);
391 szCmd = _wcsdup(ptr);
392 if (!szCmd)
393 break;
394 if (CreateProcessW(NULL, szCmd, NULL, NULL,FALSE,0,NULL,NULL,&sInfo, &pi))
395 {
396 CloseHandle( pi.hProcess );
397 CloseHandle( pi.hThread );
398 }
399 free(szCmd);
400 break;
401 }
402 case SHELLNEW_TYPE_DATA:
403 case SHELLNEW_TYPE_FILENAME:
404 case SHELLNEW_TYPE_NULLFILE:
405 {
406 i = 2;
407
408 PathAddBackslashW(szPath);
409 wcscat(szPath, szNew);
410 wcscat(szPath, L" ");
411 wcscat(szPath, pCurItem->szDesc);
412 wcscpy(szBuffer, szPath);
413 wcscat(szBuffer, pCurItem->szExt);
414 do
415 {
416 hFile = CreateFileW(szBuffer, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
417 if (hFile != INVALID_HANDLE_VALUE)
418 break;
419 dwError = GetLastError();
420
421 TRACE("FileName %s szBuffer %s i %u error %x\n", debugstr_w(szBuffer), debugstr_w(szPath), i, dwError);
422 swprintf(szBuffer, szFormat, szPath, i, pCurItem->szExt);
423 i++;
424 }while(hFile == INVALID_HANDLE_VALUE && dwError == ERROR_FILE_EXISTS);
425
426 if (hFile == INVALID_HANDLE_VALUE)
427 return E_FAIL;
428
429 if (pCurItem->Type == SHELLNEW_TYPE_DATA)
430 {
431 i = WideCharToMultiByte(CP_ACP, 0, pCurItem->szTarget, -1, (LPSTR)szTemp, MAX_PATH*2, NULL, NULL);
432 if (i)
433 {
434 WriteFile(hFile, (LPCVOID)szTemp, i, &dwWritten, NULL);
435 }
436 }
437 CloseHandle(hFile);
438 if (pCurItem->Type == SHELLNEW_TYPE_FILENAME)
439 {
440 if (!CopyFileW(pCurItem->szTarget, szBuffer, FALSE))
441 break;
442 }
443 TRACE("Notifying fs %s\n", debugstr_w(szBuffer));
444 SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, (LPCVOID)szBuffer, NULL);
445 break;
446 }
447 }
448 return S_OK;
449 }
450 /**************************************************************************
451 * DoMeasureItem
452 */
453 HRESULT
454 DoMeasureItem(INewMenuImpl *This, HWND hWnd, MEASUREITEMSTRUCT * lpmis)
455 {
456 PSHELLNEW_ITEM pCurItem;
457 PSHELLNEW_ITEM pItem;
458 UINT i;
459 HDC hDC;
460 SIZE size;
461
462 TRACE("DoMeasureItem entered with id %x\n", lpmis->itemID);
463
464 pCurItem = This->s_SnHead;
465
466 i = 1;
467 pItem = NULL;
468 while(pCurItem)
469 {
470 if (i == lpmis->itemID)
471 {
472 pItem = pCurItem;
473 break;
474 }
475 pCurItem = pCurItem->Next;
476 i++;
477 }
478
479 if (!pItem)
480 {
481 TRACE("DoMeasureItem no item found\n");
482 return E_FAIL;
483 }
484 hDC = GetDC(hWnd);
485 GetTextExtentPoint32W(hDC, pCurItem->szDesc, wcslen(pCurItem->szDesc), &size);
486 lpmis->itemWidth = size.cx + 32;
487 lpmis->itemHeight = max(size.cy, 20);
488 ReleaseDC (hWnd, hDC);
489 return S_OK;
490 }
491 /**************************************************************************
492 * DoDrawItem
493 */
494 HRESULT
495 DoDrawItem(INewMenuImpl *This, HWND hWnd, DRAWITEMSTRUCT * drawItem)
496 {
497 PSHELLNEW_ITEM pCurItem;
498 PSHELLNEW_ITEM pItem;
499 UINT i;
500 pCurItem = This->s_SnHead;
501
502 TRACE("DoDrawItem entered with id %x\n", drawItem->itemID);
503
504 i = 1;
505 pItem = NULL;
506 while(pCurItem)
507 {
508 if (i == drawItem->itemID)
509 {
510 pItem = pCurItem;
511 break;
512 }
513 pCurItem = pCurItem->Next;
514 i++;
515 }
516
517 if (!pItem)
518 return E_FAIL;
519
520 drawItem->rcItem.left += 20;
521
522 DrawTextW(drawItem->hDC, pCurItem->szDesc, wcslen(pCurItem->szDesc), &drawItem->rcItem, 0);
523 return S_OK;
524 }
525
526 /**************************************************************************
527 * DoNewFolder
528 */
529 static void DoNewFolder(
530 INewMenuImpl *This,
531 IShellView *psv)
532 {
533 ISFHelper * psfhlp;
534 WCHAR wszName[MAX_PATH];
535
536 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlp);
537 if (psfhlp)
538 {
539 LPITEMIDLIST pidl;
540
541 if (ISFHelper_GetUniqueName(psfhlp, wszName, MAX_PATH) != S_OK)
542 return;
543 if (ISFHelper_AddFolder(psfhlp, 0, wszName, &pidl) != S_OK)
544 return;
545
546 if(psv)
547 {
548 IShellView_Refresh(psv);
549 /* if we are in a shellview do labeledit */
550 IShellView_SelectItem(psv,
551 pidl,(SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
552 |SVSI_FOCUSED|SVSI_SELECT));
553 IShellView_Refresh(psv);
554 }
555 SHFree(pidl);
556
557 ISFHelper_Release(psfhlp);
558 }
559 }
560
561
562 static LPINewMenuImpl __inline impl_from_IShellExtInit( IShellExtInit *iface )
563 {
564 return (INewMenuImpl *)((char*)iface - FIELD_OFFSET(INewMenuImpl, lpvtblShellExtInit));
565 }
566
567 static LPINewMenuImpl __inline impl_from_IContextMenu( IContextMenu2 *iface )
568 {
569 return (INewMenuImpl *)((char*)iface - FIELD_OFFSET(INewMenuImpl, lpVtblContextMenu));
570 }
571
572 static HRESULT WINAPI INewItem_fnQueryInterface(INewMenuImpl * This, REFIID riid, LPVOID *ppvObj)
573 {
574 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
575
576 *ppvObj = NULL;
577
578 if(IsEqualIID(riid, &IID_IUnknown) ||
579 IsEqualIID(riid, &IID_IContextMenu) ||
580 IsEqualIID(riid, &IID_IContextMenu2))
581 {
582 *ppvObj = (void *)&This->lpVtblContextMenu;
583 }
584 else if(IsEqualIID(riid, &IID_IShellExtInit))
585 {
586 *ppvObj = (void *)&This->lpvtblShellExtInit;
587 }
588
589
590 if(*ppvObj)
591 {
592 IUnknown_AddRef((IUnknown*)*ppvObj);
593 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
594 return S_OK;
595 }
596 TRACE("-- Interface: E_NOINTERFACE\n");
597 return E_NOINTERFACE;
598 }
599
600 static ULONG WINAPI INewItem_fnAddRef(INewMenuImpl *iface)
601 {
602 /* INewItem service is singleton */
603 return 2;
604 }
605
606 static ULONG WINAPI INewItem_fnRelease(INewMenuImpl *This)
607 {
608 /* INewItem service is singleton */
609 return 1;
610 }
611
612 static
613 HRESULT
614 WINAPI
615 INewItem_IContextMenu_fnQueryInterface( IContextMenu2* iface, REFIID riid, void** ppvObject )
616 {
617 INewMenuImpl *This = impl_from_IContextMenu(iface);
618 return INewItem_fnQueryInterface(This, riid, ppvObject);
619 }
620
621 static
622 ULONG
623 WINAPI
624 INewItem_IContextMenu_fnAddRef(IContextMenu2 *iface)
625 {
626 INewMenuImpl *This = impl_from_IContextMenu(iface);
627 return INewItem_fnAddRef(This);
628 }
629
630 static
631 ULONG
632 WINAPI
633 INewItem_IContextMenu_fnRelease(IContextMenu2 *iface)
634 {
635 INewMenuImpl *This = impl_from_IContextMenu(iface);
636 return INewItem_fnRelease(This);
637 }
638
639 static
640 HRESULT
641 WINAPI
642 INewItem_IContextMenu_fnQueryContextMenu(IContextMenu2 *iface,
643 HMENU hmenu,
644 UINT indexMenu,
645 UINT idCmdFirst,
646 UINT idCmdLast,
647 UINT uFlags)
648 {
649 WCHAR szBuffer[200];
650 MENUITEMINFOW mii;
651 HMENU hSubMenu;
652 int id = 1;
653 INewMenuImpl *This = impl_from_IContextMenu(iface);
654
655 TRACE("%p %p %u %u %u %u\n", This,
656 hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags );
657
658 if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEW, szBuffer, 200))
659 {
660 szBuffer[0] = 0;
661 }
662 szBuffer[199] = 0;
663
664 hSubMenu = CreateMenu();
665 memset( &mii, 0, sizeof(mii) );
666 mii.cbSize = sizeof (mii);
667 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
668 mii.fType = MFT_STRING;
669 mii.wID = idCmdFirst + id++;
670 mii.dwTypeData = szBuffer;
671 mii.cch = wcslen( mii.dwTypeData );
672 mii.fState = MFS_ENABLED;
673
674 if (hSubMenu)
675 {
676 id += InsertShellNewItems( hSubMenu, idCmdFirst, 0, This);
677 mii.fMask |= MIIM_SUBMENU;
678 mii.hSubMenu = hSubMenu;
679 }
680
681
682 if (!InsertMenuItemW( hmenu, indexMenu, TRUE, &mii ))
683 return E_FAIL;
684
685 return MAKE_HRESULT( SEVERITY_SUCCESS, 0, id );
686 }
687
688 static
689 HRESULT
690 WINAPI
691 INewItem_IContextMenu_fnInvokeCommand( IContextMenu2* iface,
692 LPCMINVOKECOMMANDINFO lpici )
693 {
694 LPSHELLBROWSER lpSB;
695 LPSHELLVIEW lpSV = NULL;
696 HRESULT hr;
697 INewMenuImpl *This = impl_from_IContextMenu(iface);
698
699 if((lpSB = (LPSHELLBROWSER)SendMessageA(lpici->hwnd, CWM_GETISHELLBROWSER,0,0)))
700 {
701 IShellBrowser_QueryActiveShellView(lpSB, &lpSV);
702 }
703
704 if (LOWORD(lpici->lpVerb) == 0)
705 {
706 DoNewFolder(This, lpSV);
707 return S_OK;
708 }
709
710 hr = DoShellNewCmd(This, lpici);
711 if (SUCCEEDED(hr) && lpSV)
712 {
713 IShellView_Refresh(lpSV);
714 }
715
716 TRACE("INewItem_IContextMenu_fnInvokeCommand %x\n", hr);
717 return hr;
718 }
719
720 static
721 HRESULT
722 WINAPI
723 INewItem_IContextMenu_fnGetCommandString( IContextMenu2* iface,
724 UINT_PTR idCmd,
725 UINT uType,
726 UINT* pwReserved,
727 LPSTR pszName,
728 UINT cchMax )
729 {
730 INewMenuImpl *This = impl_from_IContextMenu(iface);
731
732 FIXME("%p %lu %u %p %p %u\n", This,
733 idCmd, uType, pwReserved, pszName, cchMax );
734
735 return E_NOTIMPL;
736 }
737
738 static
739 HRESULT
740 WINAPI
741 INewItem_IContextMenu_fnHandleMenuMsg(IContextMenu2 *iface,
742 UINT uMsg,
743 WPARAM wParam,
744 LPARAM lParam)
745 {
746 INewMenuImpl *This = impl_from_IContextMenu(iface);
747 DRAWITEMSTRUCT * lpids = (DRAWITEMSTRUCT*) lParam;
748 MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*) lParam;
749
750 TRACE("INewItem_IContextMenu_fnHandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam);
751
752
753 switch(uMsg)
754 {
755 case WM_MEASUREITEM:
756 return DoMeasureItem(This, (HWND)wParam, lpmis);
757 break;
758 case WM_DRAWITEM:
759 return DoDrawItem(This, (HWND)wParam, lpids);
760 break;
761 }
762 return S_OK;
763
764 return E_UNEXPECTED;
765 }
766
767 static const IContextMenu2Vtbl cmvt =
768 {
769 INewItem_IContextMenu_fnQueryInterface,
770 INewItem_IContextMenu_fnAddRef,
771 INewItem_IContextMenu_fnRelease,
772 INewItem_IContextMenu_fnQueryContextMenu,
773 INewItem_IContextMenu_fnInvokeCommand,
774 INewItem_IContextMenu_fnGetCommandString,
775 INewItem_IContextMenu_fnHandleMenuMsg
776 };
777
778 static HRESULT WINAPI
779 INewItem_ExtInit_fnQueryInterface( IShellExtInit* iface, REFIID riid, void** ppvObject )
780 {
781 return INewItem_fnQueryInterface(impl_from_IShellExtInit(iface), riid, ppvObject);
782 }
783
784 static ULONG WINAPI
785 INewItem_ExtInit_AddRef( IShellExtInit* iface )
786 {
787 return INewItem_fnAddRef(impl_from_IShellExtInit(iface));
788 }
789
790 static ULONG WINAPI
791 INewItem_ExtInit_Release( IShellExtInit* iface )
792 {
793 return INewItem_fnRelease(impl_from_IShellExtInit(iface));
794 }
795
796 static HRESULT WINAPI
797 INewItem_ExtInit_Initialize( IShellExtInit* iface, LPCITEMIDLIST pidlFolder,
798 IDataObject *pdtobj, HKEY hkeyProgID )
799 {
800
801 return S_OK;
802 }
803
804 static const IShellExtInitVtbl sei =
805 {
806 INewItem_ExtInit_fnQueryInterface,
807 INewItem_ExtInit_AddRef,
808 INewItem_ExtInit_Release,
809 INewItem_ExtInit_Initialize
810 };
811 static INewMenuImpl *cached_ow = NULL;
812
813 VOID
814 INewItem_SetCurrentShellFolder(IShellFolder * psfParent)
815 {
816 if (cached_ow)
817 cached_ow->pSFParent = psfParent;
818 }
819
820 HRESULT WINAPI INewItem_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID *ppv)
821 {
822 INewMenuImpl * ow;
823 HRESULT res;
824
825 if (!cached_ow)
826 {
827 ow = LocalAlloc(LMEM_ZEROINIT, sizeof(INewMenuImpl));
828 if (!ow)
829 {
830 return E_OUTOFMEMORY;
831 }
832
833 ow->lpVtblContextMenu = &cmvt;
834 ow->lpvtblShellExtInit = &sei;
835 ow->s_SnHead = NULL;
836 ow->szPath = NULL;
837
838 if (InterlockedCompareExchangePointer((void *)&cached_ow, ow, NULL) != NULL)
839 {
840 /* some other thread already been here */
841 LocalFree( ow );
842 }
843 }
844
845 res = INewItem_fnQueryInterface( cached_ow, riid, ppv );
846 return res;
847 }