[ros-diffs] [rharabien] 54848: [SHELL32] - Fix few leaks and possible buffer overflows in New menu code - Add icons of folder and shortcut to New menu - Display message if file can't be created

rharabien at svn.reactos.org rharabien at svn.reactos.org
Thu Jan 5 23:04:06 UTC 2012


Author: rharabien
Date: Thu Jan  5 23:04:06 2012
New Revision: 54848

URL: http://svn.reactos.org/svn/reactos?rev=54848&view=rev
Log:
[SHELL32]
- Fix few leaks and possible buffer overflows in New menu code
- Add icons of folder and shortcut to New menu
- Display message if file can't be created

Modified:
    trunk/reactos/dll/win32/shell32/newmenu.cpp
    trunk/reactos/dll/win32/shell32/newmenu.h

Modified: trunk/reactos/dll/win32/shell32/newmenu.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/newmenu.cpp?rev=54848&r1=54847&r2=54848&view=diff
==============================================================================
--- trunk/reactos/dll/win32/shell32/newmenu.cpp [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/newmenu.cpp [iso-8859-1] Thu Jan  5 23:04:06 2012
@@ -23,172 +23,194 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
-static WCHAR szNew[MAX_PATH];
-
 CNewMenu::CNewMenu()
 {
-    szPath = NULL;
-    s_SnHead = NULL;
-    fSite = NULL;
-}
-
+    m_wszPath = NULL;
+    m_pShellItems = NULL;
+    m_pSite = NULL;
+}
 
 CNewMenu::~CNewMenu()
 {
     UnloadShellItems();
-}
-
-void CNewMenu::UnloadItem(SHELLNEW_ITEM *item)
+    if (m_hSubMenu)
+        CleanupMenu();
+}
+
+void CNewMenu::CleanupMenu()
+{
+    INT Count, Index;
+    MENUITEMINFOW mii;
+
+    /* get item count */
+    Count = GetMenuItemCount(m_hSubMenu);
+    if (Count == -1)
+        return;
+
+    /* setup menuitem info */
+    ZeroMemory(&mii, sizeof(mii));
+    mii.cbSize = sizeof(mii);
+    mii.fMask = MIIM_DATA | MIIM_FTYPE | MIIM_CHECKMARKS;
+
+    for(Index = 0; Index < Count; Index++)
+    {
+        if (GetMenuItemInfoW(m_hSubMenu, Index, TRUE, &mii))
+        {
+            if (mii.hbmpChecked)
+                DeleteObject(mii.hbmpChecked);
+        }
+    }
+}
+
+void CNewMenu::UnloadItem(SHELLNEW_ITEM *pItem)
 {
     // bail if the item is clearly invalid
-    if (NULL == item)
+    if (NULL == pItem)
         return;
 
-    if (NULL != item->szTarget)
-        free(item->szTarget);
-
-    free(item->szDesc);
-    free(item->szIcon);
-    free(item->szExt);
-
-    HeapFree(GetProcessHeap(), 0, item);
+    if (NULL != pItem->pwszTarget)
+        free(pItem->pwszTarget);
+
+    free(pItem->pwszDesc);
+    free(pItem->pwszIcon);
+    free(pItem->pwszExt);
+
+    HeapFree(GetProcessHeap(), 0, pItem);
 }
 
 void CNewMenu::UnloadShellItems()
 {
     SHELLNEW_ITEM *pCurItem;
 
-    while (s_SnHead)
-    {
-        pCurItem = s_SnHead;
-        s_SnHead = s_SnHead->Next;
+    while (m_pShellItems)
+    {
+        pCurItem = m_pShellItems;
+        m_pShellItems = m_pShellItems->pNext;
 
         UnloadItem(pCurItem);
     }
-
-    s_SnHead = NULL;
-}
-
-static
-BOOL
-GetKeyDescription(LPWSTR szKeyName, LPWSTR szResult)
+}
+
+BOOL CNewMenu::GetKeyDescription(LPCWSTR pwszExt, LPWSTR pwszResult)
 {
     HKEY hKey;
-    DWORD dwDesc, dwError;
-    WCHAR szDesc[100];
-
-    TRACE("GetKeyDescription: keyname %s\n", debugstr_w(szKeyName));
-
-    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szKeyName, 0, KEY_READ | KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
+    DWORD cbDesc;
+    WCHAR wszDesc[100];
+    LONG Result;
+
+    TRACE("GetKeyDescription: keyname %s\n", debugstr_w(pwszExt));
+
+    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pwszExt, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
         return FALSE;
 
-    if (RegLoadMUIStringW(hKey, L"\\FriendlyTypeName", szResult, MAX_PATH, &dwDesc, 0, NULL) == ERROR_SUCCESS)
-    {
-        TRACE("result %s\n", debugstr_w(szResult));
+    /* Get user friendly name */
+    if (RegLoadMUIStringW(hKey, L"\\FriendlyTypeName", pwszResult, MAX_PATH, &cbDesc, 0, NULL) == ERROR_SUCCESS)
+    {
+        TRACE("result %s\n", debugstr_w(pwszResult));
         RegCloseKey(hKey);
         return TRUE;
     }
-    /* fetch default value */
-    dwDesc = sizeof(szDesc);
-    dwError = RegGetValueW(hKey, NULL, NULL, RRF_RT_REG_SZ, NULL, szDesc, &dwDesc);
-    if(dwError == ERROR_SUCCESS)
-    {
-        if (wcsncmp(szKeyName, szDesc, dwDesc / sizeof(WCHAR)))
+
+    /* Fetch default value */
+    cbDesc = sizeof(wszDesc);
+    Result = RegGetValueW(hKey, NULL, L"", RRF_RT_REG_SZ, NULL, wszDesc, &cbDesc);
+    if(Result == ERROR_SUCCESS)
+    {
+        if (wcscmp(pwszExt, wszDesc) != 0)
         {
             /* recurse for to a linked key */
-            if (!GetKeyDescription(szDesc, szResult))
+            if (!GetKeyDescription(wszDesc, pwszResult))
             {
                 /* use description */
-                wcscpy(szResult, szDesc);
+                wcscpy(pwszResult, wszDesc);
             }
         }
         else
         {
             /* use default value as description */
-            wcscpy(szResult, szDesc);
+            wcscpy(pwszResult, wszDesc);
         }
     }
     else
     {
         /* registry key w/o default key?? */
-        TRACE("RegGetValue failed with %x\n", dwError);
-        wcscpy(szResult, szKeyName);
+        ERR("RegGetValue failed with %x\n", Result);
+        wcscpy(pwszResult, pwszExt);
     }
 
     RegCloseKey(hKey);
     return TRUE;
 }
 
-CNewMenu::SHELLNEW_ITEM *CNewMenu::LoadItem(LPWSTR szKeyName)
+CNewMenu::SHELLNEW_ITEM *CNewMenu::LoadItem(LPCWSTR pwszExt)
 {
     HKEY hKey;
     DWORD dwIndex = 0;
-    WCHAR szName[MAX_PATH];
-    WCHAR szCommand[MAX_PATH];
-    WCHAR szDesc[MAX_PATH] = L"";
-    WCHAR szIcon[MAX_PATH] = L"";
-    DWORD dwName, dwCommand;
-    LONG result;
+    WCHAR wszBuf[MAX_PATH];
+    WCHAR wszCommand[MAX_PATH];
+    WCHAR wszDesc[MAX_PATH] = L"";
+    WCHAR wszIcon[MAX_PATH] = L"";
+    DWORD cchName, cbCommand;
     SHELLNEW_ITEM *pNewItem = NULL;
 
-    wcscpy(szName, szKeyName);
-    GetKeyDescription(szKeyName, szDesc);
-    wcscat(szName, L"\\ShellNew");
-    result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szName, 0, KEY_READ, &hKey);
-
-    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));
-
-    if (result != ERROR_SUCCESS)
+    StringCbPrintfW(wszBuf, sizeof(wszBuf), L"%s\\ShellNew", pwszExt);
+
+    TRACE("LoadItem Keyname %s Name %s\n", debugstr_w(pwszExt), debugstr_w(wszBuf));
+
+    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszBuf, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
     {
         TRACE("Failed to open key\n");
         return NULL;
     }
 
-    do
-    {
-        dwName = MAX_PATH;
-        dwCommand = MAX_PATH;
-        result = RegEnumValueW(hKey, dwIndex, szName, &dwName, NULL, NULL, (LPBYTE)szCommand, &dwCommand);
-        if (result == ERROR_SUCCESS)
-        {
-            SHELLNEW_TYPE type = SHELLNEW_TYPE_INVALID;
-            LPWSTR szTarget = szCommand;
-
-            TRACE("szName %s szCommand %s\n", debugstr_w(szName), debugstr_w(szCommand));
-
-            if (!wcsicmp(szName, L"Command"))
-                type = SHELLNEW_TYPE_COMMAND;
-            else if (!wcsicmp(szName, L"Data"))
-                type = SHELLNEW_TYPE_DATA;
-            else if (!wcsicmp(szName, L"FileName"))
-                type = SHELLNEW_TYPE_FILENAME;
-            else if (!wcsicmp(szName, L"NullFile"))
-            {
-                type = SHELLNEW_TYPE_NULLFILE;
-                szTarget = NULL;
-            }
-
-            if (type != SHELLNEW_TYPE_INVALID)
-            {
-                pNewItem = (SHELLNEW_ITEM *)HeapAlloc(GetProcessHeap(), 0, sizeof(SHELLNEW_ITEM));
-                if (!pNewItem)
-                    break;
-
-                pNewItem->Type = type;
-                if (szTarget)
-                    pNewItem->szTarget = _wcsdup(szTarget);
-                else
-                    pNewItem->szTarget = NULL;
-
-                pNewItem->szDesc = _wcsdup(szDesc);
-                pNewItem->szIcon = _wcsdup(szIcon);
-                pNewItem->szExt = _wcsdup(szKeyName);
-                pNewItem->Next = NULL;
+    /* Find first valid value */
+    while (TRUE)
+    {
+        cchName = _countof(wszBuf);
+        cbCommand = sizeof(wszCommand);
+        if (RegEnumValueW(hKey, dwIndex++, wszBuf, &cchName, NULL, NULL, (LPBYTE)wszCommand, &cbCommand) != ERROR_SUCCESS)
+            break;
+
+        SHELLNEW_TYPE Type = SHELLNEW_TYPE_INVALID;
+        LPWSTR pwszTarget = wszCommand;
+
+        TRACE("wszBuf %s wszCommand %s\n", debugstr_w(wszBuf), debugstr_w(wszCommand));
+
+        /* Handle different types */
+        if (!wcsicmp(wszBuf, L"Command"))
+            Type = SHELLNEW_TYPE_COMMAND;
+        else if (!wcsicmp(wszBuf, L"Data"))
+            Type = SHELLNEW_TYPE_DATA;
+        else if (!wcsicmp(wszBuf, L"FileName"))
+            Type = SHELLNEW_TYPE_FILENAME;
+        else if (!wcsicmp(wszBuf, L"NullFile"))
+        {
+            Type = SHELLNEW_TYPE_NULLFILE;
+            pwszTarget = NULL;
+        }
+
+        /* Create new item */
+        if (Type != SHELLNEW_TYPE_INVALID)
+        {
+            pNewItem = (SHELLNEW_ITEM *)HeapAlloc(GetProcessHeap(), 0, sizeof(SHELLNEW_ITEM));
+            if (!pNewItem)
                 break;
-            }
-        }
-        dwIndex++;
-    } while(result != ERROR_NO_MORE_ITEMS);
+
+            pNewItem->Type = Type;
+            if (pwszTarget)
+                pNewItem->pwszTarget = _wcsdup(pwszTarget);
+            else
+                pNewItem->pwszTarget = NULL;
+
+            GetKeyDescription(pwszExt, wszDesc);
+            pNewItem->pwszDesc = _wcsdup(wszDesc);
+            pNewItem->pwszIcon = _wcsdup(wszIcon);
+            pNewItem->pwszExt = _wcsdup(pwszExt);
+            pNewItem->pNext = NULL;
+            break;
+        }
+    }
+
     RegCloseKey(hKey);
     return pNewItem;
 }
@@ -196,71 +218,87 @@
 BOOL
 CNewMenu::LoadShellNewItems()
 {
-    DWORD dwIndex;
-    WCHAR szName[MAX_PATH];
-    LONG result;
+    DWORD dwIndex = 0;
+    WCHAR wszName[MAX_PATH];
     SHELLNEW_ITEM *pNewItem;
     SHELLNEW_ITEM *pCurItem = NULL;
 
-    /* insert do new folder action */
-    if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEW, szNew, sizeof(szNew) / sizeof(WCHAR)))
-        szNew[0] = 0;
-
+    /* If there are any unload them */
     UnloadShellItems();
 
-    dwIndex = 0;
-    do
-    {
-        result = RegEnumKeyW(HKEY_CLASSES_ROOT, dwIndex, szName, MAX_PATH);
-        if (result == ERROR_SUCCESS)
-        {
-            pNewItem = LoadItem(szName);
-            if (pNewItem)
-            {
-                if (!wcsicmp(pNewItem->szExt, L".lnk"))
+    /* Enumerate all extesions */
+    while (RegEnumKeyW(HKEY_CLASSES_ROOT, dwIndex++, wszName, _countof(wszName)) == ERROR_SUCCESS)
+    {
+        if (wszName[0] != '.' || wcsicmp(wszName, L".lnk") == 0)
+            continue;
+
+        pNewItem = LoadItem(wszName);
+        if (pNewItem)
+        {
+            if (!wcsicmp(pNewItem->pwszExt, L".lnk"))
+            {
+                /* FIXME: Should we load them?
+                   Add lnk handlers to begin of the list */
+                if (m_pShellItems)
                 {
-                    if (s_SnHead)
-                    {
-                        pNewItem->Next = s_SnHead;
-                        s_SnHead = pNewItem;
-                    }
-                    else
-                    {
-                        s_SnHead = pCurItem = pNewItem;
-                    }
+                    pNewItem->pNext = m_pShellItems;
+                    m_pShellItems = pNewItem;
                 }
                 else
+                    m_pShellItems = pCurItem = pNewItem;
+            }
+            else
+            {
+                /* Add at the end of list */
+                if (pCurItem)
                 {
-                    if (pCurItem)
-                    {
-                        pCurItem->Next = pNewItem;
-                        pCurItem = pNewItem;
-                    }
-                    else
-                    {
-                        pCurItem = s_SnHead = pNewItem;
-                    }
+                    pCurItem->pNext = pNewItem;
+                    pCurItem = pNewItem;
                 }
-            }
-        }
-        dwIndex++;
-    } while(result != ERROR_NO_MORE_ITEMS);
-
-    if (s_SnHead == NULL)
+                else
+                    pCurItem = m_pShellItems = pNewItem;
+            }
+        }
+    }
+
+    if (m_pShellItems == NULL)
         return FALSE;
     else
         return TRUE;
 }
 
+static HBITMAP IconToBitmap(HICON hIcon)
+{
+    HDC hdc, hdcScr;
+    HBITMAP hbm, hbmOld;
+    RECT rc;
+
+    hdcScr = GetDC(NULL);
+    hdc = CreateCompatibleDC(hdcScr);
+    SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK));
+    hbm = CreateCompatibleBitmap(hdcScr, rc.right, rc.bottom);
+    ReleaseDC(NULL, hdcScr);
+
+    hbmOld = (HBITMAP)SelectObject(hdc, hbm);
+    FillRect(hdc, &rc, (HBRUSH)(COLOR_MENU + 1));
+    if (!DrawIconEx(hdc, 0, 0, hIcon, rc.right, rc.bottom, 0, NULL, DI_NORMAL))
+        ERR("DrawIcon failed: %x\n", GetLastError());
+    SelectObject(hdc, hbmOld);
+
+    DeleteDC(hdc);
+
+    return hbm;
+}
+
 UINT
-CNewMenu::InsertShellNewItems(HMENU hMenu, UINT idFirst, UINT idMenu)
+CNewMenu::InsertShellNewItems(HMENU hMenu, UINT idCmdFirst, UINT Pos)
 {
     MENUITEMINFOW mii;
-    SHELLNEW_ITEM *pCurItem;
-    UINT i;
-    WCHAR szBuffer[MAX_PATH];
-
-    if (s_SnHead == NULL)
+    WCHAR wszBuf[256];
+    HICON hIcon;
+    UINT idCmd = idCmdFirst;
+
+    if (m_pShellItems == NULL)
     {
         if (!LoadShellNewItems())
             return 0;
@@ -269,334 +307,279 @@
     ZeroMemory(&mii, sizeof(mii));
     mii.cbSize = sizeof(mii);
 
-    /* insert do new shortcut action */
-    if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWFOLDER, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0])))
-        szBuffer[0] = 0;
-    szBuffer[MAX_PATH-1] = 0;
+    /* Insert new folder action */
+    if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWFOLDER, wszBuf, _countof(wszBuf)))
+        wszBuf[0] = 0;
     mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
     mii.fType = MFT_STRING;
-    mii.dwTypeData = szBuffer;
+    mii.dwTypeData = wszBuf;
     mii.cch = wcslen(mii.dwTypeData);
-    mii.wID = idFirst++;
-    InsertMenuItemW(hMenu, idMenu++, TRUE, &mii);
-
-    /* insert do new shortcut action */
-    if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEWLINK, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0])))
-        szBuffer[0] = 0;
-    szBuffer[MAX_PATH-1] = 0;
-    mii.dwTypeData = szBuffer;
+    mii.wID = idCmd;
+    hIcon = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_FOLDER), IMAGE_ICON, 0, 0, 0);
+    if (hIcon)
+    {
+        mii.fMask |= MIIM_CHECKMARKS;
+        mii.hbmpChecked = mii.hbmpUnchecked = IconToBitmap(hIcon);
+    }
+    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 = idFirst++;
-    InsertMenuItemW(hMenu, idMenu++, TRUE, &mii);
-
-    /* insert seperator for custom new action */
+    mii.wID = idCmdFirst++;
+    hIcon = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_SHORTCUT), IMAGE_ICON, 0, 0, 0);
+    if (hIcon)
+    {
+        mii.fMask |= MIIM_CHECKMARKS;
+        mii.hbmpChecked = mii.hbmpUnchecked = IconToBitmap(hIcon);
+    }
+    if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii))
+        ++idCmd;
+
+    /* Insert seperator for custom new action */
     mii.fMask = MIIM_TYPE | MIIM_ID;
     mii.fType = MFT_SEPARATOR;
     mii.wID = -1;
-    InsertMenuItemW(hMenu, idMenu++, TRUE, &mii);
-
+    InsertMenuItemW(hMenu, Pos++, TRUE, &mii);
+
+    /* Insert rest of items */
     mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
     /*
-     * FIXME
+     * FIXME:
      * implement loading of icons
      * and using MFT_OWNERDRAWN
      */
     mii.fType = MFT_STRING;
     mii.fState = MFS_ENABLED;
 
-    pCurItem = s_SnHead;
-    i = 0;
-
-    while(pCurItem)
-    {
-        if (i >= 1)
-        {
-            TRACE("szDesc %s\n", debugstr_w(pCurItem->szDesc));
-            mii.dwTypeData = pCurItem->szDesc;
-            mii.cch = wcslen(mii.dwTypeData);
-            mii.wID = idFirst++;
-            InsertMenuItemW(hMenu, idMenu++, TRUE, &mii);
-        }
-        pCurItem = pCurItem->Next;
-        i++;
-    }
-    return (i + 2);
+    SHELLNEW_ITEM *pCurItem = m_pShellItems;
+    while (pCurItem)
+    {
+        TRACE("szDesc %s\n", debugstr_w(pCurItem->pwszDesc));
+        mii.dwTypeData = pCurItem->pwszDesc;
+        mii.cch = wcslen(mii.dwTypeData);
+        mii.wID = idCmd;
+        if (InsertMenuItemW(hMenu, Pos++, TRUE, &mii))
+            ++idCmd;
+        pCurItem = pCurItem->pNext;
+    }
+
+    return idCmd - idCmdFirst;
 }
 
 HRESULT
 CNewMenu::DoShellNewCmd(LPCMINVOKECOMMANDINFO lpcmi, IShellView *psv)
 {
-    SHELLNEW_ITEM *pCurItem = s_SnHead;
-    IPersistFolder3 * psf;
+    SHELLNEW_ITEM *pCurItem = m_pShellItems;
     LPITEMIDLIST pidl;
     STRRET strTemp;
-    WCHAR szTemp[MAX_PATH];
-    WCHAR szBuffer[MAX_PATH];
-    WCHAR szPath[MAX_PATH];
-    STARTUPINFOW sInfo;
-    PROCESS_INFORMATION pi;
-    UINT i, target;
-    HANDLE hFile;
-    DWORD dwWritten, dwError;
-    CComPtr<IFolderView> folderView;
-    CComPtr<IShellFolder> parentFolder;
-    HRESULT hResult;
-
-    i = 1;
-    target = LOWORD(lpcmi->lpVerb);
-
-    while(pCurItem)
-    {
-        if (i == target)
+    WCHAR wszBuf[MAX_PATH];
+    WCHAR wszPath[MAX_PATH];
+    UINT i, idCmd = LOWORD(lpcmi->lpVerb);
+    CComPtr<IFolderView> pFolderView;
+    CComPtr<IShellFolder> pParentFolder;
+    CComPtr<IPersistFolder3> psf;
+    HRESULT hr;
+
+    /* Find shell new item */
+    for (i = 1; pCurItem; ++i)
+    {
+        if (i == idCmd)
             break;
 
-        pCurItem = pCurItem->Next;
-        i++;
+        pCurItem = pCurItem->pNext;
     }
 
     if (!pCurItem)
         return E_UNEXPECTED;
-
-    //if (fSite == NULL)
+    //if (m_pSite == NULL)
     //    return E_FAIL;
-    hResult = IUnknown_QueryService(psv, SID_IFolderView, IID_IFolderView, (void **)&folderView);
-    if (FAILED(hResult))
-        return hResult;
-    hResult = folderView->GetFolder(IID_IShellFolder, (void **)&parentFolder);
-    if (FAILED(hResult))
-        return hResult;
-
-    if (parentFolder->QueryInterface(IID_IPersistFolder2, (LPVOID*)&psf) != S_OK)
+
+    /* Get current folder */
+    hr = IUnknown_QueryService(psv, SID_IFolderView, IID_IFolderView, (void **)&pFolderView);
+    if (FAILED(hr))
+        return hr;
+
+    hr = pFolderView->GetFolder(IID_IShellFolder, (void **)&pParentFolder);
+    if (FAILED(hr))
+        return hr;
+
+    if (pParentFolder->QueryInterface(IID_IPersistFolder2, (LPVOID*)&psf) != S_OK)
     {
         ERR("Failed to get interface IID_IPersistFolder2\n");
         return E_FAIL;
     }
+
     if (psf->GetCurFolder(&pidl) != S_OK)
     {
         ERR("IPersistFolder2_GetCurFolder failed\n");
         return E_FAIL;
     }
 
-    if (parentFolder == NULL || parentFolder->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strTemp) != S_OK)
+    /* 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, szPath, MAX_PATH);
-
-    switch(pCurItem->Type)
+    StrRetToBufW(&strTemp, pidl, wszPath, _countof(wszPath));
+
+    switch (pCurItem->Type)
     {
         case SHELLNEW_TYPE_COMMAND:
         {
-            LPWSTR ptr;
-            LPWSTR szCmd;
-
-            if (!ExpandEnvironmentStringsW(pCurItem->szTarget, szBuffer, MAX_PATH))
+            LPWSTR Ptr, pwszCmd;
+            WCHAR wszTemp[MAX_PATH];
+            STARTUPINFOW si;
+            PROCESS_INFORMATION pi;
+
+            if (!ExpandEnvironmentStringsW(pCurItem->pwszTarget, wszBuf, MAX_PATH))
             {
                 TRACE("ExpandEnvironmentStrings failed\n");
                 break;
             }
 
-            ptr = wcsstr(szBuffer, L"%1");
-            if (ptr)
-            {
-                ptr[1] = 's';
-                swprintf(szTemp, szBuffer, szPath);
-                ptr = szTemp;
+            /* Expand command parameter, FIXME: there can be more modifiers */
+            Ptr = wcsstr(wszBuf, L"%1");
+            if (Ptr)
+            {
+                Ptr[1] = 's';
+                StringCbPrintfW(wszTemp, sizeof(wszTemp), wszBuf, wszPath);
+                pwszCmd = wszTemp;
             }
             else
-            {
-                ptr = szBuffer;
-            }
-
-            ZeroMemory(&sInfo, sizeof(sInfo));
-            sInfo.cb = sizeof(sInfo);
-            szCmd = _wcsdup(ptr);
-            if (!szCmd)
-                break;
-            if (CreateProcessW(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pi))
-            {
-                CloseHandle( pi.hProcess );
-                CloseHandle( pi.hThread );
-            }
-            free(szCmd);
+                pwszCmd = wszBuf;
+
+            /* 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;
         }
         case SHELLNEW_TYPE_DATA:
         case SHELLNEW_TYPE_FILENAME:
         case SHELLNEW_TYPE_NULLFILE:
         {
-            i = 2;
-
-            PathAddBackslashW(szPath);
-            wcscat(szPath, szNew);
-            wcscat(szPath, L" ");
-            wcscat(szPath, pCurItem->szDesc);
-            wcscpy(szBuffer, szPath);
-            wcscat(szBuffer, pCurItem->szExt);
-            do
-            {
-                hFile = CreateFileW(szBuffer, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+            BOOL bSuccess = TRUE;
+            LPWSTR pwszFilename = NULL;
+            size_t cchFilenameMax = 0;
+
+            /* Build new file name */
+            LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEW, wszBuf, _countof(wszBuf));
+            StringCchCatExW(wszPath, _countof(wszPath), L"\\", &pwszFilename, &cchFilenameMax, 0);
+            StringCchPrintfW(pwszFilename, cchFilenameMax, L"%s %s%s", wszBuf, pCurItem->pwszDesc, pCurItem->pwszExt);
+
+            /* Find unique name */
+            for (i = 2; PathFileExistsW(wszPath); ++i)
+            {
+                StringCchPrintfW(pwszFilename, cchFilenameMax, L"%s %s (%u)%s", wszBuf, pCurItem->pwszDesc, i, pCurItem->pwszExt);
+                TRACE("New Filename %ls\n", pwszFilename);
+            }
+
+            if (pCurItem->Type == SHELLNEW_TYPE_DATA || pCurItem->Type == SHELLNEW_TYPE_NULLFILE)
+            {
+                /* Create new file */
+                HANDLE hFile = CreateFileW(wszPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
                 if (hFile != INVALID_HANDLE_VALUE)
-                    break;
-                dwError = GetLastError();
-
-                TRACE("FileName %s szBuffer %s i %u error %x\n", debugstr_w(szBuffer), debugstr_w(szPath), i, dwError);
-                swprintf(szBuffer, L"%s (%d)%s", szPath, i, pCurItem->szExt);
-                i++;
-            } while(hFile == INVALID_HANDLE_VALUE && dwError == ERROR_FILE_EXISTS);
-
-            if (hFile == INVALID_HANDLE_VALUE)
-                return E_FAIL;
-
-            if (pCurItem->Type == SHELLNEW_TYPE_DATA)
-            {
-                i = WideCharToMultiByte(CP_ACP, 0, pCurItem->szTarget, -1, (LPSTR)szTemp, MAX_PATH * 2, NULL, NULL);
-                if (i)
                 {
-                    WriteFile(hFile, (LPCVOID)szTemp, i, &dwWritten, NULL);
+                    if (pCurItem->Type == SHELLNEW_TYPE_DATA)
+                    {
+                        /* Write a content */
+                        CHAR szTemp[256];
+                        DWORD cbWritten, cbTemp = WideCharToMultiByte(CP_ACP, 0, pCurItem->pwszTarget, -1, szTemp, _countof(szTemp), NULL, NULL);
+                        if (cbTemp)
+                            WriteFile(hFile, (LPCVOID)szTemp, cbTemp, &cbWritten, NULL);
+                        else
+                            ERR("WideCharToMultiByte failed\n");
+                    }
+
+                    /* Close file now */
+                    CloseHandle(hFile);
                 }
-            }
-            CloseHandle(hFile);
-            if (pCurItem->Type == SHELLNEW_TYPE_FILENAME)
-            {
-                if (!CopyFileW(pCurItem->szTarget, szBuffer, FALSE))
-                    break;
-            }
-            TRACE("Notifying fs %s\n", debugstr_w(szBuffer));
-            SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, (LPCVOID)szBuffer, NULL);
+                else bSuccess = FALSE;
+            }
+            else if (pCurItem->Type == SHELLNEW_TYPE_FILENAME)
+            {
+                /* Copy file */
+                bSuccess = CopyFileW(pCurItem->pwszTarget, wszPath, FALSE);
+            }
+
+            /* Show message if we failed */
+            if (bSuccess)
+            {
+                TRACE("Notifying fs %s\n", debugstr_w(wszPath));
+                SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, (LPCVOID)wszPath, NULL);
+            }
+            else
+            {
+                StringCbPrintfW(wszBuf, sizeof(wszBuf), L"Cannot create file: %s", pwszFilename);
+                MessageBoxW(NULL, wszBuf, L"Cannot create file", MB_OK|MB_ICONERROR); // FIXME
+            }
             break;
-            case SHELLNEW_TYPE_INVALID:
-                break;
-            }
+        }
+        case SHELLNEW_TYPE_INVALID:
+            ERR("Invalid type\n");
+            break;
     }
     return S_OK;
 }
-/**************************************************************************
-* DoMeasureItem
-*/
-HRESULT
-CNewMenu::DoMeasureItem(HWND hWnd, MEASUREITEMSTRUCT * lpmis)
-{
-    SHELLNEW_ITEM *pCurItem;
-    SHELLNEW_ITEM *pItem;
-    UINT i;
-    HDC hDC;
-    SIZE size;
-
-    TRACE("DoMeasureItem entered with id %x\n", lpmis->itemID);
-
-    pCurItem = s_SnHead;
-
-    i = 1;
-    pItem = NULL;
-    while(pCurItem)
-    {
-        if (i == lpmis->itemID)
-        {
-            pItem = pCurItem;
-            break;
-        }
-        pCurItem = pCurItem->Next;
-        i++;
-    }
-
-    if (!pItem)
-    {
-        TRACE("DoMeasureItem no item found\n");
-        return E_FAIL;
-    }
-    hDC = GetDC(hWnd);
-    GetTextExtentPoint32W(hDC, pCurItem->szDesc, wcslen(pCurItem->szDesc), &size);
-    lpmis->itemWidth = size.cx + 32;
-    lpmis->itemHeight = max(size.cy, 20);
-    ReleaseDC (hWnd, hDC);
-    return S_OK;
-}
-/**************************************************************************
-* DoDrawItem
-*/
-HRESULT
-CNewMenu::DoDrawItem(HWND hWnd, DRAWITEMSTRUCT * drawItem)
-{
-    SHELLNEW_ITEM *pCurItem;
-    SHELLNEW_ITEM *pItem;
-    UINT i;
-    pCurItem = s_SnHead;
-
-    TRACE("DoDrawItem entered with id %x\n", drawItem->itemID);
-
-    i = 1;
-    pItem = NULL;
-    while(pCurItem)
-    {
-        if (i == drawItem->itemID)
-        {
-            pItem = pCurItem;
-            break;
-        }
-        pCurItem = pCurItem->Next;
-        i++;
-    }
-
-    if (!pItem)
-        return E_FAIL;
-
-    drawItem->rcItem.left += 20;
-
-    DrawTextW(drawItem->hDC, pCurItem->szDesc, wcslen(pCurItem->szDesc), &drawItem->rcItem, 0);
-    return S_OK;
-}
-
-/**************************************************************************
-* DoNewFolder
-*/
-void CNewMenu::DoNewFolder(
-    IShellView *psv)
-{
-    ISFHelper *psfhlp;
+
+void CNewMenu::CreateNewFolder(IShellView *psv)
+{
     WCHAR wszName[MAX_PATH];
-    CComPtr<IFolderView> folderView;
-    CComPtr<IShellFolder> parentFolder;
-    HRESULT hResult;
-
-    //if (fSite == NULL)
+    CComPtr<ISFHelper> psfhlp; 
+    CComPtr<IFolderView> pFolderView;
+    CComPtr<IShellFolder> pParentFolder;
+    HRESULT hr;
+
+    //if (m_pSite == NULL)
     //    return;
-    hResult = IUnknown_QueryService(psv, SID_IFolderView, IID_IFolderView, (void **)&folderView);
-    if (FAILED(hResult))
+
+    /* Get current folder */
+    hr = IUnknown_QueryService(psv, SID_IFolderView, IID_IFolderView, (void **)&pFolderView);
+    if (FAILED(hr))
         return;
-    hResult = folderView->GetFolder(IID_IShellFolder, (void **)&parentFolder);
-    if (FAILED(hResult))
+
+    hr = pFolderView->GetFolder(IID_IShellFolder, (void **)&pParentFolder);
+    if (FAILED(hr))
         return;
 
-    parentFolder->QueryInterface(IID_ISFHelper, (LPVOID*)&psfhlp);
-    if (psfhlp)
+    hr = pParentFolder->QueryInterface(IID_ISFHelper, (LPVOID*)&psfhlp);
+    if (SUCCEEDED(hr))
     {
         LPITEMIDLIST pidl;
 
-        if (psfhlp->GetUniqueName(wszName, MAX_PATH) != S_OK)
+        /* Get unique name and create a folder */
+        if (psfhlp->GetUniqueName(wszName, _countof(wszName)) != S_OK)
             return;
         if (psfhlp->AddFolder(0, wszName, &pidl) != 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;
-
-        if(psv)
-        {
-            psv->Refresh();
-            /* if we are in a shellview do labeledit */
-            psv->SelectItem(
-                pidl, (SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
-                       | SVSI_FOCUSED | SVSI_SELECT));
-            psv->Refresh();
-        }
+        }
+
+        /* Do a labeledit */
+        psv->Refresh();
+        psv->SelectItem(pidl, SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE |
+                              SVSI_FOCUSED | SVSI_SELECT);
+
         SHFree(pidl);
-
-        psfhlp->Release();
     }
 }
 
 HRESULT STDMETHODCALLTYPE CNewMenu::SetSite(IUnknown *pUnkSite)
 {
-    fSite = pUnkSite;
+    m_pSite = pUnkSite;
     return S_OK;
 }
 
@@ -604,52 +587,51 @@
 {
     if (ppvSite == NULL)
         return E_POINTER;
-    *ppvSite = fSite;
-    if (fSite != NULL)
-        fSite->AddRef();
+    *ppvSite = m_pSite;
+    if (m_pSite != NULL)
+        m_pSite->AddRef();
     return S_OK;
 }
 
 HRESULT
 WINAPI
-CNewMenu::QueryContextMenu(HMENU hmenu,
+CNewMenu::QueryContextMenu(HMENU hMenu,
                            UINT indexMenu,
                            UINT idCmdFirst,
                            UINT idCmdLast,
                            UINT uFlags)
 {
-    WCHAR szBuffer[200];
+    WCHAR wszNew[200];
     MENUITEMINFOW mii;
-    HMENU hSubMenu;
-    int id = 1;
+    UINT cItems = 0;
 
     TRACE("%p %p %u %u %u %u\n", this,
-          hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags );
-
-    if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEW, szBuffer, _countof(szBuffer)))
-        szBuffer[0] = 0;
-
-    hSubMenu = CreateMenu();
-    memset( &mii, 0, sizeof(mii) );
-    mii.cbSize = sizeof (mii);
+          hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
+
+    if (!LoadStringW(shell32_hInstance, FCIDM_SHVIEW_NEW, wszNew, _countof(wszNew)))
+        return E_FAIL;
+
+    m_hSubMenu = CreateMenu();
+    memset(&mii, 0, sizeof(mii));
+    mii.cbSize = sizeof(mii);
     mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
     mii.fType = MFT_STRING;
-    mii.wID = idCmdFirst + id++;
-    mii.dwTypeData = szBuffer;
+    mii.wID = -1;
+    mii.dwTypeData = wszNew;
     mii.cch = wcslen(mii.dwTypeData);
     mii.fState = MFS_ENABLED;
 
-    if (hSubMenu)
-    {
-        id += InsertShellNewItems(hSubMenu, idCmdFirst, 0);
+    if (m_hSubMenu)
+    {
+        cItems = InsertShellNewItems(m_hSubMenu, idCmdFirst, 0);
         mii.fMask |= MIIM_SUBMENU;
-        mii.hSubMenu = hSubMenu;
-    }
-
-    if (!InsertMenuItemW(hmenu, indexMenu, TRUE, &mii))
+        mii.hSubMenu = m_hSubMenu;
+    }
+
+    if (!InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
         return E_FAIL;
 
-    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, id);
+    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cItems);
 }
 
 HRESULT
@@ -660,24 +642,21 @@
     LPSHELLVIEW lpSV = NULL;
     HRESULT hr;
 
-    if((lpSB = (LPSHELLBROWSER)SendMessageA(lpici->hwnd, CWM_GETISHELLBROWSER, 0, 0)))
-    {
+    lpSB = (LPSHELLBROWSER)SendMessageA(lpici->hwnd, CWM_GETISHELLBROWSER, 0, 0);
+    if (lpSB)
         lpSB->QueryActiveShellView(&lpSV);
-    }
 
     if (LOWORD(lpici->lpVerb) == 0)
     {
-        DoNewFolder(lpSV);
+        CreateNewFolder(lpSV);
         return S_OK;
     }
 
     hr = DoShellNewCmd(lpici, lpSV);
     if (SUCCEEDED(hr) && lpSV)
-    {
         lpSV->Refresh();
-    }
-
-    TRACE("INewItem_IContextMenu_fnInvokeCommand %x\n", hr);
+
+    TRACE("CNewMenu::InvokeCommand %x\n", hr);
     return hr;
 }
 
@@ -685,7 +664,7 @@
 WINAPI
 CNewMenu::GetCommandString(UINT_PTR idCmd,
                            UINT uType,
-                           UINT* pwReserved,
+                           UINT *pwReserved,
                            LPSTR pszName,
                            UINT cchMax)
 {
@@ -701,29 +680,13 @@
                         WPARAM wParam,
                         LPARAM lParam)
 {
-    DRAWITEMSTRUCT *lpids = (DRAWITEMSTRUCT*) lParam;
-    MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*) lParam;
-
-    TRACE("INewItem_IContextMenu_fnHandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg, wParam, lParam);
-
-    switch(uMsg)
-    {
-        case WM_MEASUREITEM:
-            return DoMeasureItem((HWND)wParam, lpmis);
-            break;
-        case WM_DRAWITEM:
-            return DoDrawItem((HWND)wParam, lpids);
-            break;
-    }
+    UNIMPLEMENTED;
     return S_OK;
-
-    return E_UNEXPECTED;
 }
 
 HRESULT WINAPI
 CNewMenu::Initialize(LPCITEMIDLIST pidlFolder,
-                     IDataObject *pdtobj, HKEY hkeyProgID )
-{
-
+                     IDataObject *pdtobj, HKEY hkeyProgID)
+{
     return S_OK;
 }

Modified: trunk/reactos/dll/win32/shell32/newmenu.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/newmenu.h?rev=54848&r1=54847&r2=54848&view=diff
==============================================================================
--- trunk/reactos/dll/win32/shell32/newmenu.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/newmenu.h [iso-8859-1] Thu Jan  5 23:04:06 2012
@@ -41,29 +41,32 @@
 
 	struct SHELLNEW_ITEM
 	{
-		SHELLNEW_TYPE					Type;
-		LPWSTR							szExt;
-		LPWSTR							szTarget;
-		LPWSTR							szDesc;
-		LPWSTR							szIcon;
-		SHELLNEW_ITEM					*Next;
+		SHELLNEW_TYPE Type;
+		LPWSTR pwszExt;
+		LPWSTR pwszTarget;
+		LPWSTR pwszDesc;
+		LPWSTR pwszIcon;
+		SHELLNEW_ITEM *pNext;
 	};
 
-    LPWSTR szPath;
-    SHELLNEW_ITEM *s_SnHead;
-    IUnknown*	fSite;
+    LPWSTR m_wszPath;
+    SHELLNEW_ITEM *m_pShellItems;
+    IUnknown *m_pSite;
+    HMENU m_hSubMenu;
+
+    void CleanupMenu();
+    static BOOL GetKeyDescription(LPCWSTR pwszExt, LPWSTR pwszResult);
+    SHELLNEW_ITEM *LoadItem(LPCWSTR pwszExt);
+    void UnloadItem(SHELLNEW_ITEM *pItem);
+	void UnloadShellItems();
+	BOOL LoadShellNewItems();
+	UINT InsertShellNewItems(HMENU hMenu, UINT idFirst, UINT idMenu);
+	HRESULT DoShellNewCmd(LPCMINVOKECOMMANDINFO lpcmi, IShellView *psv);
+	void CreateNewFolder(IShellView *psv);
+
 public:
 	CNewMenu();
 	~CNewMenu();
-	SHELLNEW_ITEM *LoadItem(LPWSTR szKeyName);
-    void UnloadItem(SHELLNEW_ITEM *item);
-	void UnloadShellItems();
-	BOOL LoadShellNewItems();
-	UINT InsertShellNewItems(HMENU hMenu, UINT idFirst, UINT idMenu);
-	HRESULT DoShellNewCmd(LPCMINVOKECOMMANDINFO lpcmi, IShellView * psv);
-	HRESULT DoMeasureItem(HWND hWnd, MEASUREITEMSTRUCT *lpmis);
-	HRESULT DoDrawItem(HWND hWnd, DRAWITEMSTRUCT *drawItem);
-	void DoNewFolder(IShellView *psv);
 
 	// IObjectWithSite
 	virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
@@ -72,7 +75,7 @@
 	// IContextMenu
 	virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
 	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);
 
 	// IContextMenu2
 	virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);




More information about the Ros-diffs mailing list