[SHELL32] cache entries of "New" menu

CORE-10439 

svn path=/trunk/; revision=71980
This commit is contained in:
Christoph von Wittich 2016-07-23 12:31:30 +00:00
parent 73e04c0cd1
commit 7541633310
2 changed files with 162 additions and 54 deletions

View file

@ -163,22 +163,109 @@ CNewMenu::SHELLNEW_ITEM *CNewMenu::LoadItem(LPCWSTR pwszExt)
} }
BOOL BOOL
CNewMenu::LoadAllItems() CNewMenu::CacheItems()
{ {
HKEY hKey;
DWORD dwSize = 0;
DWORD dwIndex = 0; DWORD dwIndex = 0;
LPWSTR lpValue;
LPWSTR lpValues;
WCHAR wszName[MAX_PATH]; WCHAR wszName[MAX_PATH];
SHELLNEW_ITEM *pNewItem; SHELLNEW_ITEM *pNewItem;
SHELLNEW_ITEM *pCurItem = NULL; SHELLNEW_ITEM *pCurItem = NULL;
/* If there are any unload them */ /* Enumerate all extensions */
UnloadAllItems();
/* Enumerate all extesions */
while (RegEnumKeyW(HKEY_CLASSES_ROOT, dwIndex++, wszName, _countof(wszName)) == ERROR_SUCCESS) while (RegEnumKeyW(HKEY_CLASSES_ROOT, dwIndex++, wszName, _countof(wszName)) == ERROR_SUCCESS)
{ {
if (wszName[0] != L'.') if (wszName[0] != L'.')
continue; 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) != ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, lpValues);
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); pNewItem = LoadItem(wszName);
if (pNewItem) if (pNewItem)
{ {
@ -200,7 +287,24 @@ CNewMenu::LoadAllItems()
} }
} }
} }
HeapFree(GetProcessHeap(), 0, lpValues);
RegCloseKey(hKey);
return TRUE;
}
BOOL
CNewMenu::LoadAllItems()
{
/* If there are any unload them */
UnloadAllItems();
if (!LoadCachedItems())
{
CacheItems();
}
if (!m_pLinkItem) if (!m_pLinkItem)
{ {
m_pLinkItem = static_cast<SHELLNEW_ITEM *>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SHELLNEW_ITEM))); m_pLinkItem = static_cast<SHELLNEW_ITEM *>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SHELLNEW_ITEM)));

View file

@ -23,33 +23,35 @@
#ifndef _SHV_ITEM_NEW_H_ #ifndef _SHV_ITEM_NEW_H_
#define _SHV_ITEM_NEW_H_ #define _SHV_ITEM_NEW_H_
const WCHAR ShellNewKey[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Discardable\\PostSetup\\ShellNew";
class CNewMenu : class CNewMenu :
public CComCoClass<CNewMenu, &CLSID_NewMenu>, public CComCoClass<CNewMenu, &CLSID_NewMenu>,
public CComObjectRootEx<CComMultiThreadModelNoCS>, public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IObjectWithSite, public IObjectWithSite,
public IContextMenu3, public IContextMenu3,
public IShellExtInit public IShellExtInit
{ {
private: private:
enum SHELLNEW_TYPE enum SHELLNEW_TYPE
{ {
SHELLNEW_TYPE_INVALID = -1, SHELLNEW_TYPE_INVALID = -1,
SHELLNEW_TYPE_COMMAND = 1, SHELLNEW_TYPE_COMMAND = 1,
SHELLNEW_TYPE_DATA = 2, SHELLNEW_TYPE_DATA = 2,
SHELLNEW_TYPE_FILENAME = 4, SHELLNEW_TYPE_FILENAME = 4,
SHELLNEW_TYPE_NULLFILE = 8 SHELLNEW_TYPE_NULLFILE = 8
}; };
struct SHELLNEW_ITEM struct SHELLNEW_ITEM
{ {
SHELLNEW_TYPE Type; SHELLNEW_TYPE Type;
LPWSTR pwszExt; LPWSTR pwszExt;
PBYTE pData; PBYTE pData;
ULONG cbData; ULONG cbData;
LPWSTR pwszDesc; LPWSTR pwszDesc;
HICON hIcon; HICON hIcon;
SHELLNEW_ITEM *pNext; SHELLNEW_ITEM *pNext;
}; };
LPITEMIDLIST m_pidlFolder; LPITEMIDLIST m_pidlFolder;
LPWSTR m_wszPath; LPWSTR m_wszPath;
@ -62,35 +64,37 @@ private:
SHELLNEW_ITEM *LoadItem(LPCWSTR pwszExt); SHELLNEW_ITEM *LoadItem(LPCWSTR pwszExt);
void UnloadItem(SHELLNEW_ITEM *pItem); void UnloadItem(SHELLNEW_ITEM *pItem);
void UnloadAllItems(); void UnloadAllItems();
BOOL LoadAllItems(); BOOL CacheItems();
UINT InsertShellNewItems(HMENU hMenu, UINT idFirst, UINT idMenu); BOOL LoadCachedItems();
SHELLNEW_ITEM *FindItemFromIdOffset(UINT IdOffset); BOOL LoadAllItems();
HRESULT CreateNewFolder(LPCMINVOKECOMMANDINFO lpici); UINT InsertShellNewItems(HMENU hMenu, UINT idFirst, UINT idMenu);
HRESULT CreateNewItem(SHELLNEW_ITEM *pItem, LPCMINVOKECOMMANDINFO lpcmi); SHELLNEW_ITEM *FindItemFromIdOffset(UINT IdOffset);
HRESULT CreateNewFolder(LPCMINVOKECOMMANDINFO lpici);
HRESULT CreateNewItem(SHELLNEW_ITEM *pItem, LPCMINVOKECOMMANDINFO lpcmi);
HRESULT SelectNewItem(LPCMINVOKECOMMANDINFO lpici, LONG wEventId, UINT uFlags, LPWSTR pszName); HRESULT SelectNewItem(LPCMINVOKECOMMANDINFO lpici, LONG wEventId, UINT uFlags, LPWSTR pszName);
public: public:
CNewMenu(); CNewMenu();
~CNewMenu(); ~CNewMenu();
// IObjectWithSite // IObjectWithSite
virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite); virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite); virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
// IContextMenu // IContextMenu
virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi); virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);
virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen); virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen);
// IContextMenu3 // IContextMenu3
virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult); virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
// IContextMenu2 // IContextMenu2
virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam); virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
// IShellExtInit // IShellExtInit
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID); virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID);
DECLARE_REGISTRY_RESOURCEID(IDR_NEWMENU) DECLARE_REGISTRY_RESOURCEID(IDR_NEWMENU)
DECLARE_NOT_AGGREGATABLE(CNewMenu) DECLARE_NOT_AGGREGATABLE(CNewMenu)
@ -98,11 +102,11 @@ DECLARE_NOT_AGGREGATABLE(CNewMenu)
DECLARE_PROTECT_FINAL_CONSTRUCT() DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CNewMenu) BEGIN_COM_MAP(CNewMenu)
COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3) COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2) COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit) COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit)
END_COM_MAP() END_COM_MAP()
}; };