1 /* 2 * provides new shell item service 3 * 4 * Copyright 2007 Johannes Anderwald (johannes.anderwald@reactos.org) 5 * Copyright 2009 Andrew Hill 6 * Copyright 2012 Rafal Harabien 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include "precomp.h" 24 25 WINE_DEFAULT_DEBUG_CHANNEL(shell); 26 27 CNewMenu::CNewMenu() : 28 m_pidlFolder(NULL), 29 m_wszPath(NULL), 30 m_pItems(NULL), 31 m_pLinkItem(NULL), 32 m_pSite(NULL), 33 m_hiconFolder(NULL), 34 m_hiconLink(NULL) 35 { 36 } 37 38 CNewMenu::~CNewMenu() 39 { 40 UnloadAllItems(); 41 42 if (m_pidlFolder) 43 ILFree(m_pidlFolder); 44 } 45 46 void CNewMenu::UnloadItem(SHELLNEW_ITEM *pItem) 47 { 48 /* Note: free allows NULL as argument */ 49 free(pItem->pData); 50 free(pItem->pwszDesc); 51 free(pItem->pwszExt); 52 53 if (pItem->hIcon) 54 DestroyIcon(pItem->hIcon); 55 56 HeapFree(GetProcessHeap(), 0, pItem); 57 } 58 59 void CNewMenu::UnloadAllItems() 60 { 61 SHELLNEW_ITEM *pCurItem; 62 63 /* Unload normal items */ 64 while (m_pItems) 65 { 66 pCurItem = m_pItems; 67 m_pItems = m_pItems->pNext; 68 69 UnloadItem(pCurItem); 70 } 71 72 /* Unload link item */ 73 if (m_pLinkItem) 74 UnloadItem(m_pLinkItem); 75 m_pLinkItem = NULL; 76 } 77 78 CNewMenu::SHELLNEW_ITEM *CNewMenu::LoadItem(LPCWSTR pwszExt) 79 { 80 HKEY hKey; 81 WCHAR wszBuf[MAX_PATH]; 82 BYTE *pData = NULL; 83 DWORD cbData; 84 85 StringCbPrintfW(wszBuf, sizeof(wszBuf), L"%s\\ShellNew", pwszExt); 86 87 TRACE("LoadItem Keyname %s Name %s\n", debugstr_w(pwszExt), debugstr_w(wszBuf)); 88 89 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszBuf, 0, KEY_READ, &hKey) != ERROR_SUCCESS) 90 { 91 TRACE("Failed to open key\n"); 92 return NULL; 93 } 94 95 /* Find first valid value */ 96 struct 97 { 98 LPCWSTR pszName; 99 SHELLNEW_TYPE Type; 100 BOOL bNeedData; 101 BOOL bStr; 102 } Types[] = { 103 {L"FileName", SHELLNEW_TYPE_FILENAME, TRUE, TRUE}, 104 {L"Command", SHELLNEW_TYPE_COMMAND, TRUE, TRUE}, 105 {L"Data", SHELLNEW_TYPE_DATA, TRUE, FALSE}, 106 {L"NullFile", SHELLNEW_TYPE_NULLFILE, FALSE}, 107 {NULL} 108 }; 109 UINT i; 110 111 for (i = 0; Types[i].pszName; ++i) 112 { 113 /* Note: We are using ANSI function because strings can be treated as data */ 114 cbData = 0; 115 DWORD dwFlags = Types[i].bStr ? RRF_RT_REG_SZ : RRF_RT_ANY; 116 DWORD dwType; 117 if (RegGetValueW(hKey, NULL, Types[i].pszName, dwFlags, NULL, NULL, &cbData) == ERROR_SUCCESS) 118 { 119 if (Types[i].bNeedData && cbData > 0) 120 { 121 pData = (BYTE*)malloc(cbData); 122 RegGetValueW(hKey, NULL, Types[i].pszName, dwFlags, &dwType, pData, &cbData); 123 if (!Types[i].bStr && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) 124 { 125 PBYTE pData2 = (PBYTE)malloc(cbData); 126 cbData = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)pData, -1, (LPSTR)pData2, cbData, NULL, NULL); 127 free(pData); 128 pData = pData2; 129 } 130 } 131 break; 132 } 133 } 134 RegCloseKey(hKey); 135 136 /* Was any key found? */ 137 if (!Types[i].pszName) 138 return NULL; 139 140 SHFILEINFOW fi; 141 if (!SHGetFileInfoW(pwszExt, FILE_ATTRIBUTE_NORMAL, &fi, sizeof(fi), SHGFI_USEFILEATTRIBUTES|SHGFI_TYPENAME|SHGFI_ICON|SHGFI_SMALLICON)) 142 return NULL; 143 144 /* Create new item */ 145 SHELLNEW_ITEM *pNewItem = static_cast<SHELLNEW_ITEM *>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SHELLNEW_ITEM))); 146 if (!pNewItem) 147 { 148 free(pData); 149 return NULL; 150 } 151 152 TRACE("new item %ls\n", fi.szTypeName); 153 pNewItem->Type = Types[i].Type; 154 pNewItem->pData = pData; 155 pNewItem->cbData = pData ? cbData : 0; 156 pNewItem->pwszExt = _wcsdup(pwszExt); 157 pNewItem->pwszDesc = _wcsdup(fi.szTypeName); 158 if (fi.hIcon) 159 pNewItem->hIcon = fi.hIcon; 160 161 return pNewItem; 162 } 163 164 BOOL 165 CNewMenu::CacheItems() 166 { 167 HKEY hKey; 168 DWORD dwSize = 0; 169 DWORD dwIndex = 0; 170 LPWSTR lpValue; 171 LPWSTR lpValues; 172 WCHAR wszName[MAX_PATH]; 173 SHELLNEW_ITEM *pNewItem; 174 SHELLNEW_ITEM *pCurItem = NULL; 175 176 /* Enumerate all extensions */ 177 while (RegEnumKeyW(HKEY_CLASSES_ROOT, dwIndex++, wszName, _countof(wszName)) == ERROR_SUCCESS) 178 { 179 if (wszName[0] != L'.') 180 continue; 181 182 pNewItem = LoadItem(wszName); 183 if (pNewItem) 184 { 185 dwSize += wcslen(wszName) + 1; 186 if (wcsicmp(pNewItem->pwszExt, L".lnk") == 0) 187 { 188 /* Link handler */ 189 m_pLinkItem = pNewItem; 190 } 191 else 192 { 193 /* Add at the end of list */ 194 if (pCurItem) 195 { 196 pCurItem->pNext = pNewItem; 197 pCurItem = pNewItem; 198 } 199 else 200 pCurItem = m_pItems = pNewItem; 201 } 202 } 203 } 204 205 dwSize++; 206 207 lpValues = (LPWSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize * sizeof(WCHAR)); 208 if (!lpValues) 209 return FALSE; 210 211 lpValue = lpValues; 212 pCurItem = m_pItems; 213 while (pCurItem) 214 { 215 memcpy(lpValue, pCurItem->pwszExt, (wcslen(pCurItem->pwszExt) + 1) * sizeof(WCHAR)); 216 lpValue += wcslen(pCurItem->pwszExt) + 1; 217 pCurItem = pCurItem->pNext; 218 } 219 220 if (RegCreateKeyEx(HKEY_CURRENT_USER, ShellNewKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) 221 { 222 HeapFree(GetProcessHeap(), 0, lpValues); 223 return FALSE; 224 } 225 226 if (RegSetValueExW(hKey, L"Classes", NULL, REG_MULTI_SZ, (LPBYTE)lpValues, dwSize * sizeof(WCHAR)) != ERROR_SUCCESS) 227 { 228 HeapFree(GetProcessHeap(), 0, lpValues); 229 RegCloseKey(hKey); 230 return FALSE; 231 } 232 233 HeapFree(GetProcessHeap(), 0, lpValues); 234 RegCloseKey(hKey); 235 236 return TRUE; 237 } 238 239 BOOL 240 CNewMenu::LoadCachedItems() 241 { 242 LPWSTR wszName; 243 LPWSTR lpValues; 244 DWORD dwSize; 245 HKEY hKey; 246 SHELLNEW_ITEM *pNewItem; 247 SHELLNEW_ITEM *pCurItem = NULL; 248 249 if (RegOpenKeyExW(HKEY_CURRENT_USER, ShellNewKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS) 250 return FALSE; 251 252 if (RegQueryValueExW(hKey, L"Classes", NULL, NULL, NULL, &dwSize) != ERROR_SUCCESS) 253 return FALSE; 254 255 lpValues = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, dwSize); 256 if (!lpValues) 257 return FALSE; 258 259 if (RegQueryValueExW(hKey, L"Classes", NULL, NULL, (LPBYTE)lpValues, &dwSize) != ERROR_SUCCESS) 260 { 261 HeapFree(GetProcessHeap(), 0, lpValues); 262 return FALSE; 263 } 264 265 wszName = lpValues; 266 267 for (; '\0' != *wszName; wszName += wcslen(wszName) + 1) 268 { 269 pNewItem = LoadItem(wszName); 270 if (pNewItem) 271 { 272 if (wcsicmp(pNewItem->pwszExt, L".lnk") == 0) 273 { 274 /* Link handler */ 275 m_pLinkItem = pNewItem; 276 } 277 else 278 { 279 /* Add at the end of list */ 280 if (pCurItem) 281 { 282 pCurItem->pNext = pNewItem; 283 pCurItem = pNewItem; 284 } 285 else 286 pCurItem = m_pItems = pNewItem; 287 } 288 } 289 } 290 291 HeapFree(GetProcessHeap(), 0, lpValues); 292 RegCloseKey(hKey); 293 294 return TRUE; 295 } 296 297 BOOL 298 CNewMenu::LoadAllItems() 299 { 300 /* If there are any unload them */ 301 UnloadAllItems(); 302 303 if (!LoadCachedItems()) 304 { 305 CacheItems(); 306 } 307 308 if (!m_pLinkItem) 309 { 310 m_pLinkItem = static_cast<SHELLNEW_ITEM *>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SHELLNEW_ITEM))); 311 if (m_pLinkItem) 312 { 313 m_pLinkItem->Type = SHELLNEW_TYPE_NULLFILE; 314 m_pLinkItem->pwszDesc = _wcsdup(L"Link"); 315 m_pLinkItem->pwszExt = _wcsdup(L".lnk"); 316 } 317 } 318 319 if (m_pItems == NULL) 320 return FALSE; 321 else 322 return TRUE; 323 } 324 325 UINT 326 CNewMenu::InsertShellNewItems(HMENU hMenu, UINT idCmdFirst, UINT Pos) 327 { 328 MENUITEMINFOW mii; 329 WCHAR wszBuf[256]; 330 UINT idCmd = idCmdFirst; 331 332 if (m_pItems == NULL) 333 { 334 if (!LoadAllItems()) 335 return 0; 336 } 337 338 ZeroMemory(&mii, sizeof(mii)); 339 mii.cbSize = sizeof(mii); 340 341 /* Insert new folder action */ 342 if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWFOLDER, wszBuf, _countof(wszBuf))) 343 wszBuf[0] = 0; 344 mii.fMask = MIIM_ID | MIIM_BITMAP | MIIM_STRING; 345 mii.dwTypeData = wszBuf; 346 mii.cch = wcslen(mii.dwTypeData); 347 mii.wID = idCmd; 348 mii.hbmpItem = HBMMENU_CALLBACK; 349 if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii)) 350 ++idCmd; 351 352 /* Insert new shortcut action */ 353 if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWLINK, wszBuf, _countof(wszBuf))) 354 wszBuf[0] = 0; 355 mii.dwTypeData = wszBuf; 356 mii.cch = wcslen(mii.dwTypeData); 357 mii.wID = idCmd; 358 if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii)) 359 ++idCmd; 360 361 /* Insert seperator for custom new action */ 362 mii.fMask = MIIM_TYPE | MIIM_ID; 363 mii.fType = MFT_SEPARATOR; 364 mii.wID = -1; 365 InsertMenuItemW(hMenu, Pos++, TRUE, &mii); 366 367 /* Insert rest of items */ 368 mii.fMask = MIIM_ID | MIIM_BITMAP | MIIM_STRING; 369 mii.fType = 0; 370 371 SHELLNEW_ITEM *pCurItem = m_pItems; 372 while (pCurItem) 373 { 374 TRACE("szDesc %s\n", debugstr_w(pCurItem->pwszDesc)); 375 mii.dwTypeData = pCurItem->pwszDesc; 376 mii.cch = wcslen(mii.dwTypeData); 377 mii.wID = idCmd; 378 if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii)) 379 ++idCmd; 380 pCurItem = pCurItem->pNext; 381 } 382 383 return idCmd - idCmdFirst; 384 } 385 386 CNewMenu::SHELLNEW_ITEM *CNewMenu::FindItemFromIdOffset(UINT IdOffset) 387 { 388 if (IdOffset == 0) 389 return NULL; /* Folder */ 390 391 if (IdOffset == 1) 392 return m_pLinkItem; /* shortcut */ 393 394 /* Find shell new item */ 395 SHELLNEW_ITEM *pItem = m_pItems; 396 for (UINT i = 2; pItem; ++i) 397 { 398 if (i == IdOffset) 399 break; 400 401 pItem = pItem->pNext; 402 } 403 404 return pItem; 405 } 406 407 HRESULT CNewMenu::SelectNewItem(LONG wEventId, UINT uFlags, LPWSTR pszName) 408 { 409 CComPtr<IShellBrowser> lpSB; 410 CComPtr<IShellView> lpSV; 411 HRESULT hr = E_FAIL; 412 LPITEMIDLIST pidl; 413 PITEMID_CHILD pidlNewItem; 414 415 /* Notify the view object about the new item */ 416 SHChangeNotify(wEventId, uFlags, (LPCVOID) pszName, NULL); 417 418 if (!m_pSite) 419 return S_OK; 420 421 /* Get a pointer to the shell view */ 422 hr = IUnknown_QueryService(m_pSite, SID_IFolderView, IID_PPV_ARG(IShellView, &lpSV)); 423 if (FAILED_UNEXPECTEDLY(hr)) 424 return S_OK; 425 426 /* Attempt to get the pidl of the new item */ 427 hr = SHILCreateFromPathW(pszName, &pidl, NULL); 428 if (FAILED_UNEXPECTEDLY(hr)) 429 return hr; 430 431 pidlNewItem = ILFindLastID(pidl); 432 433 hr = lpSV->SelectItem(pidlNewItem, SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | 434 SVSI_FOCUSED | SVSI_SELECT); 435 436 SHFree(pidl); 437 438 return hr; 439 } 440 441 // Code is duplicated in CDefaultContextMenu 442 HRESULT CNewMenu::CreateNewFolder(LPCMINVOKECOMMANDINFO lpici) 443 { 444 WCHAR wszPath[MAX_PATH]; 445 WCHAR wszName[MAX_PATH]; 446 WCHAR wszNewFolder[25]; 447 HRESULT hr; 448 449 /* Get folder path */ 450 hr = SHGetPathFromIDListW(m_pidlFolder, wszPath); 451 if (FAILED_UNEXPECTEDLY(hr)) 452 return hr; 453 454 if (!LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, _countof(wszNewFolder))) 455 return E_FAIL; 456 457 /* Create the name of the new directory */ 458 if (!PathYetAnotherMakeUniqueName(wszName, wszPath, NULL, wszNewFolder)) 459 return E_FAIL; 460 461 /* Create the new directory and show the appropriate dialog in case of error */ 462 if (SHCreateDirectory(lpici->hwnd, wszName) != ERROR_SUCCESS) 463 return E_FAIL; 464 465 /* Show and select the new item in the def view */ 466 SelectNewItem(SHCNE_MKDIR, SHCNF_PATHW, wszName); 467 468 return S_OK; 469 } 470 471 HRESULT CNewMenu::CreateNewItem(SHELLNEW_ITEM *pItem, LPCMINVOKECOMMANDINFO lpcmi) 472 { 473 WCHAR wszBuf[MAX_PATH]; 474 WCHAR wszPath[MAX_PATH]; 475 HRESULT hr; 476 477 /* Get folder path */ 478 hr = SHGetPathFromIDListW(m_pidlFolder, wszPath); 479 if (FAILED_UNEXPECTEDLY(hr)) 480 return hr; 481 482 switch (pItem->Type) 483 { 484 case SHELLNEW_TYPE_COMMAND: 485 { 486 LPWSTR Ptr, pwszCmd; 487 WCHAR wszTemp[MAX_PATH]; 488 STARTUPINFOW si; 489 PROCESS_INFORMATION pi; 490 491 if (!ExpandEnvironmentStringsW((LPWSTR)pItem->pData, wszBuf, _countof(wszBuf))) 492 { 493 TRACE("ExpandEnvironmentStrings failed\n"); 494 break; 495 } 496 497 /* Expand command parameter, FIXME: there can be more modifiers */ 498 Ptr = wcsstr(wszBuf, L"%1"); 499 if (Ptr) 500 { 501 Ptr[1] = L's'; 502 StringCbPrintfW(wszTemp, sizeof(wszTemp), wszBuf, wszPath); 503 pwszCmd = wszTemp; 504 } 505 else 506 { 507 pwszCmd = wszBuf; 508 } 509 510 /* Create process */ 511 ZeroMemory(&si, sizeof(si)); 512 si.cb = sizeof(si); 513 if (CreateProcessW(NULL, pwszCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) 514 { 515 CloseHandle(pi.hProcess); 516 CloseHandle(pi.hThread); 517 } 518 else 519 { 520 ERR("Failed to create process\n"); 521 } 522 break; 523 } 524 525 case SHELLNEW_TYPE_DATA: 526 case SHELLNEW_TYPE_FILENAME: 527 case SHELLNEW_TYPE_NULLFILE: 528 { 529 BOOL bSuccess = TRUE; 530 WCHAR wszName[MAX_PATH]; 531 WCHAR wszNewFile[MAX_PATH]; 532 533 if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEW, wszBuf, _countof(wszBuf))) 534 return E_FAIL; 535 536 StringCchPrintfW(wszNewFile, _countof(wszNewFile), L"%s %s%s", wszBuf, pItem->pwszDesc, pItem->pwszExt); 537 538 /* Create the name of the new file */ 539 if (!PathYetAnotherMakeUniqueName(wszName, wszPath, NULL, wszNewFile)) 540 return E_FAIL; 541 542 /* Create new file */ 543 HANDLE hFile = CreateFileW(wszName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); 544 if (hFile != INVALID_HANDLE_VALUE) 545 { 546 if (pItem->Type == SHELLNEW_TYPE_DATA) 547 { 548 /* Write a content */ 549 DWORD cbWritten; 550 WriteFile(hFile, pItem->pData, pItem->cbData, &cbWritten, NULL); 551 } 552 553 /* Close file now */ 554 CloseHandle(hFile); 555 } 556 else 557 { 558 bSuccess = FALSE; 559 } 560 561 if (pItem->Type == SHELLNEW_TYPE_FILENAME) 562 { 563 /* Copy file */ 564 if (!CopyFileW((LPWSTR)pItem->pData, wszName, FALSE)) 565 ERR("Copy file failed: %ls\n", (LPWSTR)pItem->pData); 566 } 567 568 /* Show message if we failed */ 569 if (bSuccess) 570 { 571 TRACE("Notifying fs %s\n", debugstr_w(wszName)); 572 SelectNewItem(SHCNE_CREATE, SHCNF_PATHW, wszName); 573 } 574 else 575 { 576 StringCbPrintfW(wszBuf, sizeof(wszBuf), L"Cannot create file: %s", wszName); 577 MessageBoxW(NULL, wszBuf, L"Cannot create file", MB_OK|MB_ICONERROR); // FIXME load localized error msg 578 } 579 break; 580 } 581 582 case SHELLNEW_TYPE_INVALID: 583 ERR("Invalid type\n"); 584 break; 585 } 586 587 return S_OK; 588 } 589 590 HRESULT STDMETHODCALLTYPE CNewMenu::SetSite(IUnknown *pUnkSite) 591 { 592 m_pSite = pUnkSite; 593 return S_OK; 594 } 595 596 HRESULT STDMETHODCALLTYPE CNewMenu::GetSite(REFIID riid, void **ppvSite) 597 { 598 return m_pSite->QueryInterface(riid, ppvSite); 599 } 600 601 HRESULT 602 WINAPI 603 CNewMenu::QueryContextMenu(HMENU hMenu, 604 UINT indexMenu, 605 UINT idCmdFirst, 606 UINT idCmdLast, 607 UINT uFlags) 608 { 609 WCHAR wszNew[200]; 610 MENUITEMINFOW mii; 611 UINT cItems = 0; 612 613 TRACE("%p %p %u %u %u %u\n", this, 614 hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); 615 616 if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEW, wszNew, _countof(wszNew))) 617 return E_FAIL; 618 619 m_hSubMenu = CreateMenu(); 620 if (!m_hSubMenu) 621 return E_FAIL; 622 623 cItems = InsertShellNewItems(m_hSubMenu, idCmdFirst, 0); 624 625 memset(&mii, 0, sizeof(mii)); 626 mii.cbSize = sizeof(mii); 627 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE | MIIM_SUBMENU; 628 mii.fType = MFT_STRING; 629 mii.wID = -1; 630 mii.dwTypeData = wszNew; 631 mii.cch = wcslen(mii.dwTypeData); 632 mii.fState = MFS_ENABLED; 633 mii.hSubMenu = m_hSubMenu; 634 635 if (!InsertMenuItemW(hMenu, indexMenu, TRUE, &mii)) 636 return E_FAIL; 637 638 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cItems); 639 } 640 641 HRESULT 642 WINAPI 643 CNewMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) 644 { 645 HRESULT hr = E_FAIL; 646 647 if (LOWORD(lpici->lpVerb) == 0) 648 hr = CreateNewFolder(lpici); 649 else 650 { 651 SHELLNEW_ITEM *pItem = FindItemFromIdOffset(LOWORD(lpici->lpVerb)); 652 if (pItem) 653 hr = CreateNewItem(pItem, lpici); 654 } 655 656 TRACE("CNewMenu::InvokeCommand %x\n", hr); 657 return hr; 658 } 659 660 HRESULT 661 WINAPI 662 CNewMenu::GetCommandString(UINT_PTR idCmd, 663 UINT uType, 664 UINT *pwReserved, 665 LPSTR pszName, 666 UINT cchMax) 667 { 668 FIXME("%p %lu %u %p %p %u\n", this, 669 idCmd, uType, pwReserved, pszName, cchMax ); 670 671 return E_NOTIMPL; 672 } 673 674 HRESULT 675 WINAPI 676 CNewMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) 677 { 678 return S_OK; 679 } 680 681 HRESULT 682 WINAPI 683 CNewMenu::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult) 684 { 685 switch (uMsg) 686 { 687 case WM_MEASUREITEM: 688 { 689 MEASUREITEMSTRUCT* lpmis = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam); 690 if (!lpmis || lpmis->CtlType != ODT_MENU) 691 break; 692 693 if (lpmis->itemWidth < (UINT)GetSystemMetrics(SM_CXMENUCHECK)) 694 lpmis->itemWidth = GetSystemMetrics(SM_CXMENUCHECK); 695 if (lpmis->itemHeight < 16) 696 lpmis->itemHeight = 16; 697 698 if (plResult) 699 *plResult = TRUE; 700 break; 701 } 702 case WM_DRAWITEM: 703 { 704 DRAWITEMSTRUCT* lpdis = reinterpret_cast<DRAWITEMSTRUCT*>(lParam); 705 if (!lpdis || lpdis->CtlType != ODT_MENU) 706 break; 707 708 DWORD id = LOWORD(lpdis->itemID); 709 HICON hIcon = 0; 710 if (id == 0) 711 hIcon = m_hiconFolder; 712 else if (id == 1) 713 hIcon = m_hiconLink; 714 else 715 { 716 SHELLNEW_ITEM *pItem = FindItemFromIdOffset(id); 717 if (pItem) 718 hIcon = pItem->hIcon; 719 } 720 721 if (!hIcon) 722 break; 723 724 DrawIconEx(lpdis->hDC, 725 2, 726 lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top - 16) / 2, 727 hIcon, 728 16, 729 16, 730 0, NULL, DI_NORMAL); 731 732 if(plResult) 733 *plResult = TRUE; 734 } 735 } 736 737 return S_OK; 738 } 739 740 HRESULT WINAPI 741 CNewMenu::Initialize(LPCITEMIDLIST pidlFolder, 742 IDataObject *pdtobj, HKEY hkeyProgID) 743 { 744 m_pidlFolder = ILClone(pidlFolder); 745 746 /* Load folder and shortcut icons */ 747 m_hiconFolder = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_FOLDER), IMAGE_ICON, 16, 16, LR_SHARED); 748 m_hiconLink = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_SHORTCUT), IMAGE_ICON, 16, 16, LR_SHARED); 749 return S_OK; 750 } 751