WINE_DEFAULT_DEBUG_CHANNEL(shell);
-CNewMenu::CNewMenu()
+CNewMenu::CNewMenu() :
+ m_pidlFolder(NULL),
+ m_wszPath(NULL),
+ m_pItems(NULL),
+ m_pLinkItem(NULL),
+ m_pSite(NULL),
+ m_hiconFolder(NULL),
+ m_hiconLink(NULL),
+ m_idCmdFirst(0)
{
- m_wszPath = NULL;
- m_pItems = NULL;
- m_pLinkItem = NULL;
- m_pSite = NULL;
- m_hiconFolder = NULL;
- m_hiconLink = NULL;
- m_idCmdFirst = 0;
}
CNewMenu::~CNewMenu()
{
UnloadAllItems();
+
+ if (m_pidlFolder)
+ ILFree(m_pidlFolder);
}
void CNewMenu::UnloadItem(SHELLNEW_ITEM *pItem)
if (!Types[i].pszName)
return NULL;
- SHFILEINFO fi;
+ SHFILEINFOW fi;
if (!SHGetFileInfoW(pwszExt, FILE_ATTRIBUTE_NORMAL, &fi, sizeof(fi), SHGFI_USEFILEATTRIBUTES|SHGFI_TYPENAME|SHGFI_ICON|SHGFI_SMALLICON))
return NULL;
}
BOOL
-CNewMenu::LoadAllItems()
+CNewMenu::CacheItems()
{
+ HKEY hKey;
+ DWORD dwSize = 0;
DWORD dwIndex = 0;
+ LPWSTR lpValue;
+ LPWSTR lpValues;
WCHAR wszName[MAX_PATH];
SHELLNEW_ITEM *pNewItem;
SHELLNEW_ITEM *pCurItem = NULL;
- /* If there are any unload them */
- UnloadAllItems();
-
- /* Enumerate all extesions */
+ /* Enumerate all extensions */
while (RegEnumKeyW(HKEY_CLASSES_ROOT, dwIndex++, wszName, _countof(wszName)) == ERROR_SUCCESS)
{
if (wszName[0] != L'.')
continue;
+ pNewItem = LoadItem(wszName);
+ if (pNewItem)
+ {
+ dwSize += wcslen(wszName) + 1;
+ if (wcsicmp(pNewItem->pwszExt, L".lnk") == 0)
+ {
+ /* Link handler */
+ m_pLinkItem = pNewItem;
+ }
+ else
+ {
+ /* Add at the end of list */
+ if (pCurItem)
+ {
+ pCurItem->pNext = pNewItem;
+ pCurItem = pNewItem;
+ }
+ else
+ pCurItem = m_pItems = pNewItem;
+ }
+ }
+ }
+
+ dwSize++;
+
+ lpValues = (LPWSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize * sizeof(WCHAR));
+ if (!lpValues)
+ return FALSE;
+
+ lpValue = lpValues;
+ pCurItem = m_pItems;
+ while (pCurItem)
+ {
+ 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)
+ {
+ HeapFree(GetProcessHeap(), 0, lpValues);
+ return FALSE;
+ }
+
+ if (RegSetValueExW(hKey, L"Classes", NULL, REG_MULTI_SZ, (LPBYTE)lpValues, dwSize * sizeof(WCHAR)) != ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, lpValues);
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+ HeapFree(GetProcessHeap(), 0, lpValues);
+ RegCloseKey(hKey);
+
+ return TRUE;
+}
+
+BOOL
+CNewMenu::LoadCachedItems()
+{
+ LPWSTR wszName;
+ LPWSTR lpValues;
+ DWORD dwSize;
+ HKEY hKey;
+ SHELLNEW_ITEM *pNewItem;
+ SHELLNEW_ITEM *pCurItem = NULL;
+
+ if (RegOpenKeyExW(HKEY_CURRENT_USER, ShellNewKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
+ return FALSE;
+
+ if (RegQueryValueExW(hKey, L"Classes", NULL, NULL, NULL, &dwSize) != ERROR_SUCCESS)
+ return FALSE;
+
+ lpValues = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, dwSize);
+ if (!lpValues)
+ return FALSE;
+
+ if (RegQueryValueExW(hKey, L"Classes", NULL, NULL, (LPBYTE)lpValues, &dwSize) != ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, lpValues);
+ return FALSE;
+ }
+
+ wszName = lpValues;
+
+ for (; '\0' != *wszName; wszName += wcslen(wszName) + 1)
+ {
pNewItem = LoadItem(wszName);
if (pNewItem)
{
}
}
}
+
+ HeapFree(GetProcessHeap(), 0, lpValues);
+ RegCloseKey(hKey);
+
+ return TRUE;
+}
+BOOL
+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)));
return pItem;
}
-HRESULT CNewMenu::CreateNewFolder(IShellView *psv)
+HRESULT CNewMenu::SelectNewItem(LPCMINVOKECOMMANDINFO lpici, LONG wEventId, UINT uFlags, LPWSTR pszName)
{
- WCHAR wszName[MAX_PATH];
- CComPtr<ISFHelper> psfhlp;
- CComPtr<IFolderView> pFolderView;
- CComPtr<IShellFolder> pParentFolder;
- HRESULT hr;
+ CComPtr<IShellBrowser> lpSB;
+ CComPtr<IShellView> lpSV;
+ HRESULT hr = E_FAIL;
+ LPITEMIDLIST pidl;
+ PITEMID_CHILD pidlNewItem;
- //if (m_pSite == NULL)
- // return E_FAIL;
+ /* Notify the view object about the new item */
+ SHChangeNotify(wEventId, uFlags, (LPCVOID) pszName, NULL);
- /* Get current folder */
- hr = IUnknown_QueryService(psv, SID_IFolderView, IID_PPV_ARG(IFolderView, &pFolderView));
- if (FAILED(hr))
- return hr;
+ /* FIXME: I think that this can be implemented using callbacks to the shell folder */
- hr = pFolderView->GetFolder(IID_PPV_ARG(IShellFolder, &pParentFolder));
- if (FAILED(hr))
- return hr;
+ /* Note: CWM_GETISHELLBROWSER returns shell browser without adding reference */
+ lpSB = (LPSHELLBROWSER)SendMessageA(lpici->hwnd, CWM_GETISHELLBROWSER, 0, 0);
+ if (!lpSB)
+ return E_FAIL;
- hr = pParentFolder->QueryInterface(IID_PPV_ARG(ISFHelper, &psfhlp));
+ hr = lpSB->QueryActiveShellView(&lpSV);
if (FAILED(hr))
return hr;
- LPITEMIDLIST pidl;
-
- /* Get unique name and create a folder */
- hr = psfhlp->GetUniqueName(wszName, _countof(wszName));
- if (hr != S_OK)
+ /* Attempt to get the pidl of the new item */
+ hr = SHILCreateFromPathW(pszName, &pidl, NULL);
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- hr = psfhlp->AddFolder(0, wszName, &pidl);
- if (hr != S_OK)
- {
- WCHAR wszBuf[256];
- StringCbPrintfW(wszBuf, sizeof(wszBuf), L"Cannot create folder: %s", wszName);
- MessageBoxW(NULL, wszBuf, L"Cannot create folder", MB_OK|MB_ICONERROR);
- return hr;
- }
- /* Do a labeledit */
- psv->Refresh();
- psv->SelectItem(pidl, SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE |
- SVSI_FOCUSED | SVSI_SELECT);
+ pidlNewItem = ILFindLastID(pidl);
+
+ hr = lpSV->SelectItem(pidlNewItem, SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE |
+ SVSI_FOCUSED | SVSI_SELECT);
SHFree(pidl);
- return S_OK;
+
+ return hr;
}
-HRESULT CNewMenu::CreateNewItem(SHELLNEW_ITEM *pItem, LPCMINVOKECOMMANDINFO lpcmi, IShellView *psv)
+// Code is duplicated in CDefaultContextMenu
+HRESULT CNewMenu::CreateNewFolder(LPCMINVOKECOMMANDINFO lpici)
{
- LPITEMIDLIST pidl;
- STRRET strTemp;
- WCHAR wszBuf[MAX_PATH];
WCHAR wszPath[MAX_PATH];
- CComPtr<IFolderView> pFolderView;
- CComPtr<IShellFolder> pParentFolder;
- CComPtr<IPersistFolder2> psf;
+ WCHAR wszName[MAX_PATH];
+ WCHAR wszNewFolder[25];
HRESULT hr;
-
- /* Get current folder */
- hr = IUnknown_QueryService(psv, SID_IFolderView, IID_PPV_ARG(IFolderView, &pFolderView));
- if (FAILED(hr))
+
+ /* Get folder path */
+ hr = SHGetPathFromIDListW(m_pidlFolder, wszPath);
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- hr = pFolderView->GetFolder(IID_PPV_ARG(IShellFolder, &pParentFolder));
- if (FAILED(hr))
- return hr;
+ if (!LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, _countof(wszNewFolder)))
+ return E_FAIL;
- if (pParentFolder->QueryInterface(IID_PPV_ARG(IPersistFolder2, &psf)) != S_OK)
- {
- ERR("Failed to get interface IID_IPersistFolder2\n");
+ /* Create the name of the new directory */
+ if (!PathYetAnotherMakeUniqueName(wszName, wszPath, NULL, wszNewFolder))
return E_FAIL;
- }
- if (psf->GetCurFolder(&pidl) != S_OK)
- {
- ERR("IPersistFolder2_GetCurFolder failed\n");
+ /* Create the new directory and show the appropriate dialog in case of error */
+ if (SHCreateDirectory (lpici->hwnd, wszName) != ERROR_SUCCESS)
return E_FAIL;
- }
+
+ /* Show and select the new item in the def view */
+ SelectNewItem(lpici, SHCNE_MKDIR, SHCNF_PATHW, wszName);
+
+ return S_OK;
+}
+
+HRESULT CNewMenu::CreateNewItem(SHELLNEW_ITEM *pItem, LPCMINVOKECOMMANDINFO lpcmi)
+{
+ WCHAR wszBuf[MAX_PATH];
+ WCHAR wszPath[MAX_PATH];
+ HRESULT hr;
/* Get folder path */
- if (pParentFolder == NULL || pParentFolder->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strTemp) != S_OK)
- {
- ERR("IShellFolder_GetDisplayNameOf failed\n");
- return E_FAIL;
- }
- StrRetToBufW(&strTemp, pidl, wszPath, _countof(wszPath));
+ hr = SHGetPathFromIDListW(m_pidlFolder, wszPath);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
switch (pItem->Type)
{
if (bSuccess)
{
TRACE("Notifying fs %s\n", debugstr_w(wszPath));
- SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, (LPCVOID)wszPath, NULL);
- psv->Refresh();
-
- LPITEMIDLIST pidl;
- hr = _ILCreateFromPathW(wszPath, &pidl);
- if (SUCCEEDED(hr))
- {
- psv->SelectItem(pidl, SVSI_DESELECTOTHERS|SVSI_EDIT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_SELECT);
- ILFree(pidl);
- }
+ SelectNewItem(lpcmi, SHCNE_CREATE, SHCNF_PATHW, wszPath);
}
else
{
WINAPI
CNewMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
{
- CComPtr<IShellBrowser> lpSB;
- CComPtr<IShellView> lpSV;
HRESULT hr = E_FAIL;
- /* Note: CWM_GETISHELLBROWSER returns shell browser without adding reference */
- lpSB = (LPSHELLBROWSER)SendMessageA(lpici->hwnd, CWM_GETISHELLBROWSER, 0, 0);
- if (lpSB)
- lpSB->QueryActiveShellView(&lpSV);
-
if (LOWORD(lpici->lpVerb) == 0)
- hr = CreateNewFolder(lpSV);
+ hr = CreateNewFolder(lpici);
else
{
SHELLNEW_ITEM *pItem = FindItemFromIdOffset(LOWORD(lpici->lpVerb));
if (pItem)
- hr = CreateNewItem(pItem, lpici, lpSV);
+ hr = CreateNewItem(pItem, lpici);
}
TRACE("CNewMenu::InvokeCommand %x\n", hr);
CNewMenu::Initialize(LPCITEMIDLIST pidlFolder,
IDataObject *pdtobj, HKEY hkeyProgID)
{
+ m_pidlFolder = ILClone(pidlFolder);
+
/* Load folder and shortcut icons */
m_hiconFolder = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_FOLDER), IMAGE_ICON, 16, 16, LR_SHARED);
m_hiconLink = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_SHORTCUT), IMAGE_ICON, 16, 16, LR_SHARED);