https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8e60c2efeefbb2a4d93894...
commit 8e60c2efeefbb2a4d93894c8300c0244bf54fea6 Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Tue Apr 23 10:48:34 2019 +0900 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org CommitDate: Wed Apr 24 03:28:17 2019 +0200
[SHELL32] Implement 'New Link' (Retrial of #1510), CORE-15511 (#1518)
Correctly create cache about ".lnk" and handling in the member functions.
Co-authored-by: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org --- dll/win32/shell32/CNewMenu.cpp | 309 +++++++++++++++++++++-------------------- dll/win32/shell32/CNewMenu.h | 7 +- 2 files changed, 164 insertions(+), 152 deletions(-)
diff --git a/dll/win32/shell32/CNewMenu.cpp b/dll/win32/shell32/CNewMenu.cpp index 4a17e9b58b..d4b86863f3 100644 --- a/dll/win32/shell32/CNewMenu.cpp +++ b/dll/win32/shell32/CNewMenu.cpp @@ -4,6 +4,7 @@ * Copyright 2007 Johannes Anderwald (johannes.anderwald@reactos.org) * Copyright 2009 Andrew Hill * Copyright 2012 Rafal Harabien + * Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -60,18 +61,14 @@ void CNewMenu::UnloadAllItems() { SHELLNEW_ITEM *pCurItem;
- /* Unload normal items */ + /* Unload the handler items, including the link item */ while (m_pItems) { pCurItem = m_pItems; m_pItems = m_pItems->pNext; - UnloadItem(pCurItem); } - - /* Unload link item */ - if (m_pLinkItem) - UnloadItem(m_pLinkItem); + m_pItems = NULL; m_pLinkItem = NULL; }
@@ -183,21 +180,21 @@ CNewMenu::CacheItems() if (pNewItem) { dwSize += wcslen(wszName) + 1; - if (wcsicmp(pNewItem->pwszExt, L".lnk") == 0) + if (!m_pLinkItem && wcsicmp(pNewItem->pwszExt, L".lnk") == 0) { - /* Link handler */ + /* The unique link handler */ m_pLinkItem = pNewItem; } + + /* Add at the end of the list */ + if (pCurItem) + { + pCurItem->pNext = pNewItem; + pCurItem = pNewItem; + } else { - /* Add at the end of list */ - if (pCurItem) - { - pCurItem->pNext = pNewItem; - pCurItem = pNewItem; - } - else - pCurItem = m_pItems = pNewItem; + pCurItem = m_pItems = pNewItem; } } } @@ -208,13 +205,10 @@ CNewMenu::CacheItems() if (!lpValues) return FALSE;
- lpValue = lpValues; - pCurItem = m_pItems; - while (pCurItem) + for (pCurItem = m_pItems, lpValue = lpValues; pCurItem; pCurItem = pCurItem->pNext) { memcpy(lpValue, pCurItem->pwszExt, (wcslen(pCurItem->pwszExt) + 1) * sizeof(WCHAR)); lpValue += wcslen(pCurItem->pwszExt) + 1; - pCurItem = pCurItem->pNext; }
if (RegCreateKeyEx(HKEY_CURRENT_USER, ShellNewKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) @@ -269,21 +263,21 @@ CNewMenu::LoadCachedItems() pNewItem = LoadItem(wszName); if (pNewItem) { - if (wcsicmp(pNewItem->pwszExt, L".lnk") == 0) + if (!m_pLinkItem && wcsicmp(pNewItem->pwszExt, L".lnk") == 0) { - /* Link handler */ + /* The unique link handler */ m_pLinkItem = pNewItem; } + + /* Add at the end of the list */ + if (pCurItem) + { + pCurItem->pNext = pNewItem; + pCurItem = pNewItem; + } else { - /* Add at the end of list */ - if (pCurItem) - { - pCurItem->pNext = pNewItem; - pCurItem = pNewItem; - } - else - pCurItem = m_pItems = pNewItem; + pCurItem = m_pItems = pNewItem; } } } @@ -299,27 +293,13 @@ CNewMenu::LoadAllItems() { /* If there are any unload them */ UnloadAllItems(); - + if (!LoadCachedItems()) { CacheItems(); } - - if (!m_pLinkItem) - { - m_pLinkItem = static_cast<SHELLNEW_ITEM *>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SHELLNEW_ITEM))); - if (m_pLinkItem) - { - m_pLinkItem->Type = SHELLNEW_TYPE_NULLFILE; - m_pLinkItem->pwszDesc = _wcsdup(L"Link"); - m_pLinkItem->pwszExt = _wcsdup(L".lnk"); - } - }
- if (m_pItems == NULL) - return FALSE; - else - return TRUE; + return (m_pItems != NULL); }
UINT @@ -349,14 +329,17 @@ CNewMenu::InsertShellNewItems(HMENU hMenu, UINT idCmdFirst, UINT Pos) if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii)) ++idCmd;
- /* Insert new shortcut action */ - if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWLINK, wszBuf, _countof(wszBuf))) - wszBuf[0] = 0; - mii.dwTypeData = wszBuf; - mii.cch = wcslen(mii.dwTypeData); - mii.wID = idCmd; - if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii)) - ++idCmd; + /* Insert the new shortcut action */ + if (m_pLinkItem) + { + if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWLINK, wszBuf, _countof(wszBuf))) + wszBuf[0] = 0; + mii.dwTypeData = wszBuf; + mii.cch = wcslen(mii.dwTypeData); + mii.wID = idCmd; + if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii)) + ++idCmd; + }
/* Insert seperator for custom new action */ mii.fMask = MIIM_TYPE | MIIM_ID; @@ -371,6 +354,10 @@ CNewMenu::InsertShellNewItems(HMENU hMenu, UINT idCmdFirst, UINT Pos) SHELLNEW_ITEM *pCurItem = m_pItems; while (pCurItem) { + /* Skip shortcut item */ + if (pCurItem == m_pLinkItem) + continue; + TRACE("szDesc %s\n", debugstr_w(pCurItem->pwszDesc)); mii.dwTypeData = pCurItem->pwszDesc; mii.cch = wcslen(mii.dwTypeData); @@ -404,13 +391,18 @@ CNewMenu::SHELLNEW_ITEM *CNewMenu::FindItemFromIdOffset(UINT IdOffset) return pItem; }
-HRESULT CNewMenu::SelectNewItem(LONG wEventId, UINT uFlags, LPWSTR pszName) +HRESULT CNewMenu::SelectNewItem(LONG wEventId, UINT uFlags, LPWSTR pszName, BOOL bRename) { CComPtr<IShellBrowser> lpSB; CComPtr<IShellView> lpSV; HRESULT hr = E_FAIL; LPITEMIDLIST pidl; PITEMID_CHILD pidlNewItem; + DWORD dwSelectFlags; + + dwSelectFlags = SVSI_DESELECTOTHERS | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT; + if (bRename) + dwSelectFlags |= SVSI_EDIT;
/* Notify the view object about the new item */ SHChangeNotify(wEventId, uFlags, (LPCVOID) pszName, NULL); @@ -430,8 +422,7 @@ HRESULT CNewMenu::SelectNewItem(LONG wEventId, UINT uFlags, LPWSTR pszName)
pidlNewItem = ILFindLastID(pidl);
- hr = lpSV->SelectItem(pidlNewItem, SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | - SVSI_FOCUSED | SVSI_SELECT); + hr = lpSV->SelectItem(pidlNewItem, dwSelectFlags);
SHFree(pidl);
@@ -463,121 +454,139 @@ HRESULT CNewMenu::CreateNewFolder(LPCMINVOKECOMMANDINFO lpici) return E_FAIL;
/* Show and select the new item in the def view */ - SelectNewItem(SHCNE_MKDIR, SHCNF_PATHW, wszName); + SelectNewItem(SHCNE_MKDIR, SHCNF_PATHW, wszName, TRUE);
return S_OK; }
-HRESULT CNewMenu::CreateNewItem(SHELLNEW_ITEM *pItem, LPCMINVOKECOMMANDINFO lpcmi) +HRESULT CNewMenu::NewItemByCommand(SHELLNEW_ITEM *pItem, LPCWSTR wszPath) { WCHAR wszBuf[MAX_PATH]; - WCHAR wszPath[MAX_PATH]; - HRESULT hr; + LPWSTR Ptr, pwszCmd; + WCHAR wszTemp[MAX_PATH]; + STARTUPINFOW si; + PROCESS_INFORMATION pi;
- /* Get folder path */ - hr = SHGetPathFromIDListW(m_pidlFolder, wszPath); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; + if (!ExpandEnvironmentStringsW((LPWSTR)pItem->pData, wszBuf, _countof(wszBuf))) + { + TRACE("ExpandEnvironmentStrings failed\n"); + return E_FAIL; + }
- switch (pItem->Type) + /* Expand command parameter, FIXME: there can be more modifiers */ + Ptr = wcsstr(wszBuf, L"%1"); + if (Ptr) { - case SHELLNEW_TYPE_COMMAND: - { - LPWSTR Ptr, pwszCmd; - WCHAR wszTemp[MAX_PATH]; - STARTUPINFOW si; - PROCESS_INFORMATION pi; + Ptr[1] = L's'; + StringCbPrintfW(wszTemp, sizeof(wszTemp), wszBuf, wszPath); + pwszCmd = wszTemp; + } + else + { + pwszCmd = wszBuf; + }
- if (!ExpandEnvironmentStringsW((LPWSTR)pItem->pData, wszBuf, _countof(wszBuf))) - { - TRACE("ExpandEnvironmentStrings failed\n"); - break; - } + /* Create process */ + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + if (CreateProcessW(NULL, pwszCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return S_OK; + } + else + { + ERR("Failed to create process\n"); + return E_FAIL; + } +}
- /* Expand command parameter, FIXME: there can be more modifiers */ - Ptr = wcsstr(wszBuf, L"%1"); - if (Ptr) - { - Ptr[1] = L's'; - StringCbPrintfW(wszTemp, sizeof(wszTemp), wszBuf, wszPath); - pwszCmd = wszTemp; - } - else - { - pwszCmd = wszBuf; - } +HRESULT CNewMenu::NewItemByNonCommand(SHELLNEW_ITEM *pItem, LPWSTR wszName, + DWORD cchNameMax, LPCWSTR wszPath) +{ + WCHAR wszBuf[MAX_PATH]; + WCHAR wszNewFile[MAX_PATH]; + BOOL bSuccess = TRUE;
- /* Create process */ - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - if (CreateProcessW(NULL, pwszCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) - { - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } - else - { - ERR("Failed to create process\n"); - } - break; - } + if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEW, wszBuf, _countof(wszBuf))) + return E_FAIL;
- case SHELLNEW_TYPE_DATA: - case SHELLNEW_TYPE_FILENAME: - case SHELLNEW_TYPE_NULLFILE: + StringCchPrintfW(wszNewFile, _countof(wszNewFile), L"%s %s%s", wszBuf, pItem->pwszDesc, pItem->pwszExt); + + /* Create the name of the new file */ + if (!PathYetAnotherMakeUniqueName(wszName, wszPath, NULL, wszNewFile)) + return E_FAIL; + + /* Create new file */ + HANDLE hFile = CreateFileW(wszName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + if (pItem->Type == SHELLNEW_TYPE_DATA) { - BOOL bSuccess = TRUE; - WCHAR wszName[MAX_PATH]; - WCHAR wszNewFile[MAX_PATH]; + /* Write a content */ + DWORD cbWritten; + WriteFile(hFile, pItem->pData, pItem->cbData, &cbWritten, NULL); + }
- if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEW, wszBuf, _countof(wszBuf))) - return E_FAIL; + /* Close file now */ + CloseHandle(hFile); + } + else + { + bSuccess = FALSE; + }
- StringCchPrintfW(wszNewFile, _countof(wszNewFile), L"%s %s%s", wszBuf, pItem->pwszDesc, pItem->pwszExt); + if (pItem->Type == SHELLNEW_TYPE_FILENAME) + { + /* Copy file */ + if (!CopyFileW((LPWSTR)pItem->pData, wszName, FALSE)) + ERR("Copy file failed: %ls\n", (LPWSTR)pItem->pData); + }
- /* Create the name of the new file */ - if (!PathYetAnotherMakeUniqueName(wszName, wszPath, NULL, wszNewFile)) - return E_FAIL; + /* Show message if we failed */ + if (bSuccess) + { + TRACE("Notifying fs %s\n", debugstr_w(wszName)); + SelectNewItem(SHCNE_CREATE, SHCNF_PATHW, wszName, pItem != m_pLinkItem); + } + else + { + StringCbPrintfW(wszBuf, sizeof(wszBuf), L"Cannot create file: %s", wszName); + MessageBoxW(NULL, wszBuf, L"Cannot create file", MB_OK|MB_ICONERROR); // FIXME load localized error msg + }
- /* Create new file */ - HANDLE hFile = CreateFileW(wszName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile != INVALID_HANDLE_VALUE) - { - if (pItem->Type == SHELLNEW_TYPE_DATA) - { - /* Write a content */ - DWORD cbWritten; - WriteFile(hFile, pItem->pData, pItem->cbData, &cbWritten, NULL); - } + return S_OK; +}
- /* Close file now */ - CloseHandle(hFile); - } - else - { - bSuccess = FALSE; - } +HRESULT CNewMenu::CreateNewItem(SHELLNEW_ITEM *pItem, LPCMINVOKECOMMANDINFO lpcmi) +{ + HRESULT hr; + WCHAR wszPath[MAX_PATH], wszName[MAX_PATH];
- if (pItem->Type == SHELLNEW_TYPE_FILENAME) - { - /* Copy file */ - if (!CopyFileW((LPWSTR)pItem->pData, wszName, FALSE)) - ERR("Copy file failed: %ls\n", (LPWSTR)pItem->pData); - } + /* Get folder path */ + hr = SHGetPathFromIDListW(m_pidlFolder, wszPath); + if (FAILED_UNEXPECTEDLY(hr)) + return hr;
- /* Show message if we failed */ - if (bSuccess) - { - TRACE("Notifying fs %s\n", debugstr_w(wszName)); - SelectNewItem(SHCNE_CREATE, SHCNF_PATHW, wszName); - } - else - { - StringCbPrintfW(wszBuf, sizeof(wszBuf), L"Cannot create file: %s", wszName); - MessageBoxW(NULL, wszBuf, L"Cannot create file", MB_OK|MB_ICONERROR); // FIXME load localized error msg - } + if (pItem == m_pLinkItem) + { + NewItemByNonCommand(pItem, wszName, _countof(wszName), wszPath); + NewItemByCommand(pItem, wszName); + return S_OK; + } + + switch (pItem->Type) + { + case SHELLNEW_TYPE_COMMAND: + NewItemByCommand(pItem, wszPath); + break; + + case SHELLNEW_TYPE_DATA: + case SHELLNEW_TYPE_FILENAME: + case SHELLNEW_TYPE_NULLFILE: + NewItemByNonCommand(pItem, wszName, _countof(wszName), wszPath); break; - }
case SHELLNEW_TYPE_INVALID: ERR("Invalid type\n"); diff --git a/dll/win32/shell32/CNewMenu.h b/dll/win32/shell32/CNewMenu.h index 2475e725a9..a0c62eb86e 100644 --- a/dll/win32/shell32/CNewMenu.h +++ b/dll/win32/shell32/CNewMenu.h @@ -56,7 +56,7 @@ private: LPITEMIDLIST m_pidlFolder; LPWSTR m_wszPath; SHELLNEW_ITEM *m_pItems; - SHELLNEW_ITEM *m_pLinkItem; + SHELLNEW_ITEM *m_pLinkItem; // Points to the link handler item in the m_pItems list. CComPtr<IUnknown> m_pSite; HMENU m_hSubMenu; HICON m_hiconFolder, m_hiconLink; @@ -71,7 +71,10 @@ private: SHELLNEW_ITEM *FindItemFromIdOffset(UINT IdOffset); HRESULT CreateNewFolder(LPCMINVOKECOMMANDINFO lpici); HRESULT CreateNewItem(SHELLNEW_ITEM *pItem, LPCMINVOKECOMMANDINFO lpcmi); - HRESULT SelectNewItem(LONG wEventId, UINT uFlags, LPWSTR pszName); + HRESULT SelectNewItem(LONG wEventId, UINT uFlags, LPWSTR pszName, BOOL bRename); + HRESULT NewItemByCommand(SHELLNEW_ITEM *pItem, LPCWSTR wszPath); + HRESULT NewItemByNonCommand(SHELLNEW_ITEM *pItem, LPWSTR wszName, + DWORD cchNameMax, LPCWSTR wszPath);
public: CNewMenu();