Rolf Kalbermatter <rolf.kalbermatter@citeng.com>
authorGé van Geldorp <ge@gse.nl>
Tue, 19 Oct 2004 10:17:53 +0000 (10:17 +0000)
committerGé van Geldorp <ge@gse.nl>
Tue, 19 Oct 2004 10:17:53 +0000 (10:17 +0000)
- Added SHFreeNameMappings implementation.
- Modify ANSI functions to allocate intermediate Unicode strings on the
heap instead of stack.
Mike McCormack <mike@codeweavers.com>
- Convert the shellmenu code to use unicode.

svn path=/trunk/; revision=11328

reactos/lib/shell32/shell32.spec
reactos/lib/shell32/shlfileop.c
reactos/lib/shell32/shlmenu.c

index 11966ab..273f95b 100644 (file)
 @ stdcall SHFileOperationA(ptr)
 @ stdcall SHFileOperationW(ptr)
 @ stub SHFormatDrive
-@ stub SHFreeNameMappings
+@ stdcall SHFreeNameMappings(ptr)
 @ stdcall SHGetDesktopFolder(ptr)
 @ stdcall SHGetFileInfo(ptr long ptr long long)SHGetFileInfoAW
 @ stdcall SHGetFileInfoA(ptr long ptr long long)
index 3891b37..40fa76e 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
-#define IsAttribFile(x) (!(x == -1) && !(x & FILE_ATTRIBUTE_DIRECTORY))
-#define IsAttribDir(x)  (!(x == -1) && (x & FILE_ATTRIBUTE_DIRECTORY))
-
+#define IsAttrib(x, y)  ((INVALID_FILE_ATTRIBUTES != (x)) && ((x) & (y)))
+#define IsAttribFile(x) (!((x) & FILE_ATTRIBUTE_DIRECTORY))
+#define IsAttribDir(x)  IsAttrib(x, FILE_ATTRIBUTE_DIRECTORY)
 #define IsDotDir(x)     ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
 
 #define FO_MASK         0xF
 
-static const CHAR aWildcardFile[] = {'*','.','*',0};
-static const WCHAR wWildcardFile[] = {'*','.','*',0};
+static const WCHAR wWildcardFile[] = {'*',0};
 static const WCHAR wWildcardChars[] = {'*','?',0};
 static const WCHAR wBackslash[] = {'\\',0};
 
+static BOOL SHELL_DeleteDirectoryW(LPCWSTR pszDir, BOOL bShowUI);
 static DWORD SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec);
 static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec);
 static DWORD SHNotifyRemoveDirectoryA(LPCSTR path);
@@ -130,6 +130,27 @@ BOOL SHELL_ConfirmDialogW(int nKindOfDialog, LPCWSTR szDir)
        return (IDOK == MessageBoxW(GetActiveWindow(), szBuffer, szCaption, MB_OKCANCEL | MB_ICONEXCLAMATION));
 }
 
+static DWORD SHELL32_AnsiToUnicodeBuf(LPCSTR aPath, LPWSTR *wPath, DWORD minlen)
+{
+       DWORD len = MultiByteToWideChar(CP_ACP, 0, aPath, -1, NULL, 0);
+
+       if (len < minlen)
+         len = minlen;
+
+       *wPath = HeapAlloc(GetProcessHeap(), 0, len);
+       if (*wPath)
+       {
+         MultiByteToWideChar(CP_ACP, 0, aPath, -1, *wPath, len);
+         return NO_ERROR;
+       }
+       return E_OUTOFMEMORY;
+}
+
+static void SHELL32_FreeUnicodeBuf(LPWSTR wPath)
+{
+       HeapFree(GetProcessHeap(), 0, wPath);
+}
+
 /**************************************************************************
  * SHELL_DeleteDirectoryA()  [internal]
  *
@@ -137,40 +158,18 @@ BOOL SHELL_ConfirmDialogW(int nKindOfDialog, LPCWSTR szDir)
  */
 BOOL SHELL_DeleteDirectoryA(LPCSTR pszDir, BOOL bShowUI)
 {
-       BOOL    ret = TRUE;
-       HANDLE  hFind;
-       WIN32_FIND_DATAA wfd;
-       char    szTemp[MAX_PATH];
+       LPWSTR wPath;
+       BOOL ret = FALSE;
 
-       /* Make sure the directory exists before eventually prompting the user */
-       PathCombineA(szTemp, pszDir, aWildcardFile);
-       hFind = FindFirstFileA(szTemp, &wfd);
-       if (hFind == INVALID_HANDLE_VALUE)
-         return FALSE;
-
-       if (!bShowUI || (ret = SHELL_ConfirmDialog(ASK_DELETE_FOLDER, pszDir)))
+       if (!SHELL32_AnsiToUnicodeBuf(pszDir, &wPath, 0))
        {
-         do
-         {
-           LPSTR lp = wfd.cAlternateFileName;
-           if (!lp[0])
-             lp = wfd.cFileName;
-           if (IsDotDir(lp))
-             continue;
-           PathCombineA(szTemp, pszDir, lp);
-           if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
-             ret = SHELL_DeleteDirectoryA(szTemp, FALSE);
-           else
-             ret = (SHNotifyDeleteFileA(szTemp) == ERROR_SUCCESS);
-         } while (ret && FindNextFileA(hFind, &wfd));
+         ret = SHELL_DeleteDirectoryW(wPath, bShowUI);
+         SHELL32_FreeUnicodeBuf(wPath);
        }
-       FindClose(hFind);
-       if (ret)
-         ret = (SHNotifyRemoveDirectoryA(pszDir) == ERROR_SUCCESS);
        return ret;
 }
 
-BOOL SHELL_DeleteDirectoryW(LPCWSTR pszDir, BOOL bShowUI)
+static BOOL SHELL_DeleteDirectoryW(LPCWSTR pszDir, BOOL bShowUI)
 {
        BOOL    ret = TRUE;
        HANDLE  hFind;
@@ -241,11 +240,18 @@ BOOL SHELL_DeleteFileW(LPCWSTR pszFile, BOOL bShowUI)
  */
 static DWORD SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec)
 {
-       WCHAR wPath[MAX_PATH];
+       LPWSTR wPath;
+       DWORD retCode;
+
        TRACE("(%s, %p)\n", debugstr_a(path), sec);
 
-       MultiByteToWideChar(CP_ACP, 0, path, -1, wPath, MAX_PATH);
-       return SHNotifyCreateDirectoryW(wPath, sec);
+       retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0);
+       if (!retCode)
+       {
+         retCode = SHNotifyCreateDirectoryW(wPath, sec);
+         SHELL32_FreeUnicodeBuf(wPath);
+       }
+       return retCode;
 }
 
 /**********************************************************************/
@@ -254,19 +260,6 @@ static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec)
 {
        TRACE("(%s, %p)\n", debugstr_w(path), sec);
 
-       if (StrPBrkW(path, wWildcardChars))
-       {
-         /* FIXME: This test is currently necessary since our CreateDirectory
-            implementation does create directories with wildcard characters
-            without objection!! Once this is fixed, this here can go away. */
-         SetLastError(ERROR_INVALID_NAME);
-#ifdef W98_FO_FUNCTION /* W98 */
-         return ERROR_FILE_NOT_FOUND;
-#else
-         return ERROR_INVALID_NAME;
-#endif
-       }
-
        if (CreateDirectoryW(path, sec))
        {
          SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW, path, NULL);
@@ -302,11 +295,18 @@ BOOL WINAPI Win32CreateDirectoryAW(LPCVOID path, LPSECURITY_ATTRIBUTES sec)
 
 static DWORD SHNotifyRemoveDirectoryA(LPCSTR path)
 {
-       WCHAR wPath[MAX_PATH];
+       LPWSTR wPath;
+       DWORD retCode;
+
        TRACE("(%s)\n", debugstr_a(path));
 
-       MultiByteToWideChar(CP_ACP, 0, path, -1, wPath, MAX_PATH);
-       return SHNotifyRemoveDirectoryW(wPath);
+       retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0);
+       if (!retCode)
+       {
+         retCode = SHNotifyRemoveDirectoryW(wPath);
+         SHELL32_FreeUnicodeBuf(wPath);
+       }
+       return retCode;
 }
 
 /***********************************************************************/
@@ -321,7 +321,7 @@ static DWORD SHNotifyRemoveDirectoryW(LPCWSTR path)
        {
          /* Directory may be write protected */
          DWORD dwAttr = GetFileAttributesW(path);
-         if (dwAttr != -1 && dwAttr & FILE_ATTRIBUTE_READONLY)
+         if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY))
            if (SetFileAttributesW(path, dwAttr & ~FILE_ATTRIBUTE_READONLY))
              ret = RemoveDirectoryW(path);
        }
@@ -360,11 +360,18 @@ BOOL WINAPI Win32RemoveDirectoryAW(LPCVOID path)
 
 static DWORD SHNotifyDeleteFileA(LPCSTR path)
 {
-       WCHAR wPath[MAX_PATH];
+       LPWSTR wPath;
+       DWORD retCode;
+
        TRACE("(%s)\n", debugstr_a(path));
 
-       MultiByteToWideChar(CP_ACP, 0, path, -1, wPath, MAX_PATH);
-       return SHNotifyDeleteFileW(wPath);
+       retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0);
+       if (!retCode)
+       {
+         retCode = SHNotifyDeleteFileW(wPath);
+         SHELL32_FreeUnicodeBuf(wPath);
+       }
+       return retCode;
 }
 
 /***********************************************************************/
@@ -380,7 +387,7 @@ static DWORD SHNotifyDeleteFileW(LPCWSTR path)
        {
          /* File may be write protected or a system file */
          DWORD dwAttr = GetFileAttributesW(path);
-         if ((dwAttr != -1) && (dwAttr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
+         if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))
            if (SetFileAttributesW(path, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
              ret = DeleteFileW(path);
        }
@@ -421,25 +428,12 @@ static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest, BOOL bRename)
 
        TRACE("(%s %s %s)\n", debugstr_w(src), debugstr_w(dest), bRename ? "renameIfExists" : "");
 
-       if (StrPBrkW(dest, wWildcardChars))
-       {
-         /* FIXME: This test is currently necessary since our MoveFile
-            implementation does create files with wildcard characters
-            without objection!! Once this is fixed, this here can go away. */
-         SetLastError(ERROR_INVALID_NAME);
-#ifdef W98_FO_FUNCTION /* W98 */
-         return ERROR_FILE_NOT_FOUND;
-#else
-         return ERROR_INVALID_NAME;
-#endif
-       }
-
        ret = MoveFileW(src, dest);
        if (!ret)
        {
          /* Source file may be write protected or a system file */
          DWORD dwAttr = GetFileAttributesW(src);
-         if ((dwAttr != -1) && (dwAttr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
+         if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))
            if (SetFileAttributesW(src, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
              ret = MoveFileW(src, dest);
 
@@ -447,7 +441,7 @@ static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest, BOOL bRename)
          {
            /* Destination file probably exists */
            dwAttr = GetFileAttributesW(dest);
-           if (dwAttr != -1)
+           if (dwAttr != INVALID_FILE_ATTRIBUTES)
            {
              FIXME("Rename on move to existing file not implemented!\n");
            }
@@ -486,7 +480,7 @@ static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bRename)
        {
          /* Destination file probably exists */
          DWORD dwAttr = GetFileAttributesW(dest);
-         if (dwAttr != -1)
+         if (dwAttr != INVALID_FILE_ATTRIBUTES)
          {
            FIXME("Rename on copy to existing file not implemented!\n");
          }
@@ -502,7 +496,9 @@ static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bRename)
 /*************************************************************************
  * SHCreateDirectory         [SHELL32.165]
  *
- * Create a directory at the specified location
+ * This function creates a file system folder whose fully qualified path is
+ * given by path. If one or more of the intermediate folders do not exist,
+ * they will be created as well.
  *
  * PARAMS
  *  hWnd       [I]
@@ -512,6 +508,8 @@ static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bRename)
  *  ERRROR_SUCCESS or one of the following values:
  *  ERROR_BAD_PATHNAME if the path is relative
  *  ERROR_FILE_EXISTS when a file with that name exists
+ *  ERROR_PATH_NOT_FOUND can't find the path, probably invalid
+ *  ERROR_INVLID_NAME if the path contains invalid chars
  *  ERROR_ALREADY_EXISTS when the directory already exists
  *  ERROR_FILENAME_EXCED_RANGE if the filename was to long to process
  *
@@ -530,28 +528,47 @@ DWORD WINAPI SHCreateDirectory(HWND hWnd, LPCVOID path)
 /*************************************************************************
  * SHCreateDirectoryExA      [SHELL32.@]
  *
- * Create a directory at the specified location
+ * This function creates a file system folder whose fully qualified path is
+ * given by path. If one or more of the intermediate folders do not exist,
+ * they will be created as well.
  *
  * PARAMS
- *  hWnd       [I]   
- *  path       [I]   path of directory to create 
+ *  hWnd       [I]
+ *  path       [I]   path of directory to create
  *  sec        [I]   security attributes to use or NULL
  *
  * RETURNS
  *  ERRROR_SUCCESS or one of the following values:
- *  ERROR_BAD_PATHNAME if the path is relative
- *  ERORO_INVALID_NAME if the path contains invalid chars
+ *  ERROR_BAD_PATHNAME or ERROR_PATH_NOT_FOUND if the path is relative
+ *  ERROR_INVLID_NAME if the path contains invalid chars
  *  ERROR_FILE_EXISTS when a file with that name exists
  *  ERROR_ALREADY_EXISTS when the directory already exists
  *  ERROR_FILENAME_EXCED_RANGE if the filename was to long to process
+ *
+ *  FIXME: Not implemented yet;
+ *  SHCreateDirectoryEx also verifies that the files will be visible. If not:
+ *
+ *  If hWnd is set to a valid window handle, a message box is displayed warning
+ *  the user that the files may not be accessible. If the user chooses not to
+ *  proceed, the function returns ERROR_CANCELLED.
+ *
+ *  If hWnd is set to NULL, no user interface is displayed and the function
+ *  returns ERROR_CANCELLED.
  */
 int WINAPI SHCreateDirectoryExA(HWND hWnd, LPCSTR path, LPSECURITY_ATTRIBUTES sec)
 {
-       WCHAR wPath[MAX_PATH];
-       TRACE("(%p, %s, %p)\n",hWnd, debugstr_a(path), sec);
+       LPWSTR wPath;
+       DWORD retCode;
+
+       TRACE("(%s, %p)\n", debugstr_a(path), sec);
 
-       MultiByteToWideChar(CP_ACP, 0, path, -1, wPath, MAX_PATH);
-       return SHCreateDirectoryExW(hWnd, wPath, sec);
+       retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0);
+       if (!retCode)
+       {
+         retCode = SHCreateDirectoryExW(hWnd, wPath, sec);
+         SHELL32_FreeUnicodeBuf(wPath);
+       }
+       return retCode;
 }
 
 /*************************************************************************
@@ -560,7 +577,7 @@ int WINAPI SHCreateDirectoryExA(HWND hWnd, LPCSTR path, LPSECURITY_ATTRIBUTES se
 int WINAPI SHCreateDirectoryExW(HWND hWnd, LPCWSTR path, LPSECURITY_ATTRIBUTES sec)
 {
        int ret = ERROR_BAD_PATHNAME;
-       TRACE("(%p, %s, %p)\n",hWnd, debugstr_w(path), sec);
+       TRACE("(%p, %s, %p)\n", hWnd, debugstr_w(path), sec);
 
        if (PathIsRelativeW(path))
        {
@@ -569,6 +586,7 @@ int WINAPI SHCreateDirectoryExW(HWND hWnd, LPCWSTR path, LPSECURITY_ATTRIBUTES s
        else
        {
          ret = SHNotifyCreateDirectoryW(path, sec);
+         /* Refuse to work on certain error codes before trying to create directories recursively */
          if (ret != ERROR_FILE_EXISTS &&
              ret != ERROR_ALREADY_EXISTS &&
              ret != ERROR_FILENAME_EXCED_RANGE)
@@ -1293,6 +1311,35 @@ DWORD WINAPI SHFileOperationAW(LPVOID lpFileOp)
        return SHFileOperationA(lpFileOp);
 }
 
+#define SHDSA_GetItemCount(hdsa) (*(int*)(hdsa))
+
+/*************************************************************************
+ * SHFreeNameMappings      [shell32.246]
+ *
+ * Free the mapping handle returned by SHFileoperation if FOF_WANTSMAPPINGHANDLE
+ * was specified.
+ *
+ * PARAMS
+ *  hNameMapping [I] handle to the name mappings used during renaming of files
+ *
+ */
+void WINAPI SHFreeNameMappings(HANDLE hNameMapping)
+{
+       if (hNameMapping)
+       {
+         int i = SHDSA_GetItemCount((HDSA)hNameMapping) - 1;
+
+         for (; i>= 0; i--)
+         {
+           LPSHNAMEMAPPINGW lp = DSA_GetItemPtr((HDSA)hNameMapping, i);
+
+           SHFree(lp->pszOldPath);
+           SHFree(lp->pszNewPath);
+         }
+         DSA_Destroy((HDSA)hNameMapping);
+       }
+}
+
 /*************************************************************************
  * SheGetDirW [SHELL32.281]
  *
index 0f5a76f..6c2b149 100644 (file)
 #include "shlobj.h"
 #include "undocshell.h"
 #include "shlwapi.h"
-#include "heap.h"
 #include "shell32_main.h"
 #include "shlguid.h"
 
 #include "pidl.h"
 #include "wine/debug.h"
 
-static BOOL FileMenu_AppendItemA(HMENU hMenu, LPCSTR lpText, UINT uID, int icon,
+#ifdef FM_SEPARATOR
+#undef FM_SEPARATOR
+#endif
+#define FM_SEPARATOR (LPCWSTR)1
+
+static BOOL FileMenu_AppendItemW(HMENU hMenu, LPCWSTR lpText, UINT uID, int icon,
                                  HMENU hMenuPopup, int nItemHeight);
 
 typedef struct
@@ -62,7 +66,7 @@ typedef struct
 {      int     cchItemText;
        int     iIconIndex;
        HMENU   hMenu;
-       char    szItemText[1];
+       WCHAR   szItemText[1];
 } FMITEM, * LPFMITEM;
 
 static BOOL bAbortInit;
@@ -133,7 +137,7 @@ static int FM_InitMenuPopup(HMENU hmenu, LPCITEMIDLIST pAlternatePidl)
        UINT            uID, uFlags, uEnumFlags;
        LPFNFMCALLBACK  lpfnCallback;
        LPCITEMIDLIST   pidl;
-       char            sTemp[MAX_PATH];
+       WCHAR           sTemp[MAX_PATH];
        int             NumberOfItems = 0, iIcon;
        MENUINFO        MenuInfo;
        LPFMINFO        menudata;
@@ -185,7 +189,7 @@ static int FM_InitMenuPopup(HMENU hmenu, LPCITEMIDLIST pAlternatePidl)
              {
                if (SUCCEEDED (IShellFolder_GetAttributesOf(lpsf, 1, (LPCITEMIDLIST*)&pidlTemp, &ulItemAttr)))
                {
-                 ILGetDisplayNameExA(NULL, pidlTemp, sTemp, ILGDN_FORPARSING);
+                 ILGetDisplayNameExW(NULL, pidlTemp, sTemp, ILGDN_FORPARSING);
                  if (! (PidlToSicIndex(lpsf, pidlTemp, FALSE, 0, &iIcon)))
                    iIcon = FM_BLANK_ICON;
                  if ( SFGAO_FOLDER & ulItemAttr)
@@ -204,12 +208,14 @@ static int FM_InitMenuPopup(HMENU hmenu, LPCITEMIDLIST pAlternatePidl)
                    MenuInfo.dwMenuData = (DWORD) lpFmMi;
                    SetMenuInfo (hMenuPopup, &MenuInfo);
 
-                   FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, hMenuPopup, FM_DEFAULT_HEIGHT);
+                   FileMenu_AppendItemW (hmenu, sTemp, uID, iIcon, hMenuPopup, FM_DEFAULT_HEIGHT);
                  }
                  else
                  {
-                   ((LPSTR)PathFindExtensionA(sTemp))[0] = 0x00;
-                   FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, 0, FM_DEFAULT_HEIGHT);
+                   LPWSTR pExt = PathFindExtensionW(sTemp);
+                   if (pExt)
+                     *pExt = 0;
+                   FileMenu_AppendItemW (hmenu, sTemp, uID, iIcon, 0, FM_DEFAULT_HEIGHT);
                  }
                }
 
@@ -230,7 +236,9 @@ static int FM_InitMenuPopup(HMENU hmenu, LPCITEMIDLIST pAlternatePidl)
        }
 
        if ( GetMenuItemCount (hmenu) == 0 )
-       { FileMenu_AppendItemA (hmenu, "(empty)", uID, FM_BLANK_ICON, 0, FM_DEFAULT_HEIGHT);
+       {
+          static const WCHAR szEmpty[] = { '(','e','m','p','t','y',')',0 };
+         FileMenu_AppendItemW (hmenu, szEmpty, uID, FM_BLANK_ICON, 0, FM_DEFAULT_HEIGHT);
          NumberOfItems++;
        }
 
@@ -302,33 +310,33 @@ void WINAPI FileMenu_Destroy (HMENU hmenu)
  * FileMenu_AppendItem                 [SHELL32.115]
  *
  */
-static BOOL FileMenu_AppendItemA(
+static BOOL FileMenu_AppendItemW(
        HMENU hMenu,
-       LPCSTR lpText,
+       LPCWSTR lpText,
        UINT uID,
        int icon,
        HMENU hMenuPopup,
        int nItemHeight)
 {
-       LPSTR lpszText = (LPSTR)lpText;
-       MENUITEMINFOA   mii;
+       MENUITEMINFOW   mii;
        LPFMITEM        myItem;
        LPFMINFO        menudata;
        MENUINFO        MenuInfo;
 
 
        TRACE("%p %s 0x%08x 0x%08x %p 0x%08x\n",
-       hMenu, (lpszText!=FM_SEPARATOR) ? lpText: NULL,
-       uID, icon, hMenuPopup, nItemHeight);
+         hMenu, (lpText!=FM_SEPARATOR) ? debugstr_w(lpText) : NULL,
+         uID, icon, hMenuPopup, nItemHeight);
 
-       ZeroMemory (&mii, sizeof(MENUITEMINFOA));
+       ZeroMemory (&mii, sizeof(MENUITEMINFOW));
 
-       mii.cbSize = sizeof(MENUITEMINFOA);
+       mii.cbSize = sizeof(MENUITEMINFOW);
 
        if (lpText != FM_SEPARATOR)
-       { int len = strlen (lpText);
-         myItem = (LPFMITEM) SHAlloc( sizeof(FMITEM) + len);
-         strcpy (myItem->szItemText, lpText);
+       {
+         int len = strlenW (lpText);
+         myItem = (LPFMITEM) SHAlloc( sizeof(FMITEM) + len*sizeof(WCHAR));
+         strcpyW (myItem->szItemText, lpText);
          myItem->cchItemText = len;
          myItem->iIconIndex = icon;
          myItem->hMenu = hMenu;
@@ -354,7 +362,7 @@ static BOOL FileMenu_AppendItemA(
        }
        mii.wID = uID;
 
-       InsertMenuItemA (hMenu, (UINT)-1, TRUE, &mii);
+       InsertMenuItemW (hMenu, (UINT)-1, TRUE, &mii);
 
        /* set bFixedItems to true */
        MenuInfo.cbSize = sizeof(MENUINFO);
@@ -388,15 +396,17 @@ BOOL WINAPI FileMenu_AppendItemAW(
        int nItemHeight)
 {
        BOOL ret;
-       LPSTR lpszText=NULL;
-
-       if (SHELL_OsIsUnicode() && (lpText!=FM_SEPARATOR))
-         lpszText = HEAP_strdupWtoA ( GetProcessHeap(),0, lpText);
 
-       ret = FileMenu_AppendItemA(hMenu, (lpszText) ? lpszText : lpText, uID, icon, hMenuPopup, nItemHeight);
-
-       if (lpszText)
+       if ((SHELL_OsIsUnicode() && (lpText!=FM_SEPARATOR)) || (lpText == NULL))
+         ret = FileMenu_AppendItemW(hMenu, lpText, uID, icon, hMenuPopup, nItemHeight);
+        else
+       {
+         DWORD len = MultiByteToWideChar( CP_ACP, 0, lpText, -1, NULL, 0 );
+         LPWSTR lpszText = HeapAlloc ( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+         MultiByteToWideChar( CP_ACP, 0, lpText, -1, lpszText, len );
+         ret = FileMenu_AppendItemW(hMenu, lpszText, uID, icon, hMenuPopup, nItemHeight);
          HeapFree( GetProcessHeap(), 0, lpszText );
+       }
 
        return ret;
 }
@@ -484,7 +494,7 @@ int WINAPI FileMenu_AppendFilesForPidl(
        FM_InitMenuPopup(hmenu, pidl);
 
        if (bAddSeperator)
-         FileMenu_AppendItemA (hmenu, FM_SEPARATOR, 0, 0, 0, FM_DEFAULT_HEIGHT);
+         FileMenu_AppendItemW (hmenu, FM_SEPARATOR, 0, 0, 0, FM_DEFAULT_HEIGHT);
 
        TRACE("%p %p 0x%08x\n",hmenu, pidl,bAddSeperator);
 
@@ -559,9 +569,9 @@ LRESULT WINAPI FileMenu_MeasureItem(
        SIZE size;
        LPFMINFO menuinfo;
 
-       TRACE("%p %p %s\n", hWnd, lpmis, pMyItem->szItemText);
+       TRACE("%p %p %s\n", hWnd, lpmis, debugstr_w(pMyItem->szItemText));
 
-       GetTextExtentPoint32A(hdc, pMyItem->szItemText, pMyItem->cchItemText, &size);
+       GetTextExtentPoint32W(hdc, pMyItem->szItemText, pMyItem->cchItemText, &size);
 
        lpmis->itemWidth = size.cx + FM_LEFTBORDER + FM_ICON_SIZE + FM_SPACE1 + FM_SPACE2 + FM_RIGHTBORDER;
        lpmis->itemHeight = (size.cy > (FM_ICON_SIZE + FM_Y_SPACE)) ? size.cy : (FM_ICON_SIZE + FM_Y_SPACE);
@@ -589,7 +599,7 @@ LRESULT WINAPI FileMenu_DrawItem(
        RECT TextRect, BorderRect;
        LPFMINFO menuinfo;
 
-       TRACE("%p %p %s\n", hWnd, lpdis, pMyItem->szItemText);
+       TRACE("%p %p %s\n", hWnd, lpdis, debugstr_w(pMyItem->szItemText));
 
        if (lpdis->itemState & ODS_SELECTED)
        {
@@ -620,7 +630,7 @@ LRESULT WINAPI FileMenu_DrawItem(
        xt = xi + FM_ICON_SIZE + FM_SPACE2;
        yt = yi;
 
-       ExtTextOutA (lpdis->hDC, xt , yt, ETO_OPAQUE, &TextRect, pMyItem->szItemText, pMyItem->cchItemText, NULL);
+       ExtTextOutW (lpdis->hDC, xt , yt, ETO_OPAQUE, &TextRect, pMyItem->szItemText, pMyItem->cchItemText, NULL);
 
        Shell_GetImageList(0, &hImageList);
        ImageList_Draw(hImageList, pMyItem->iIconIndex, lpdis->hDC, xi, yi, ILD_NORMAL);
@@ -666,19 +676,19 @@ LRESULT WINAPI FileMenu_HandleMenuChar(
  */
 BOOL WINAPI FileMenu_DeleteAllItems (HMENU hmenu)
 {
-       MENUITEMINFOA   mii;
+       MENUITEMINFOW   mii;
        LPFMINFO        menudata;
 
        int i;
 
        TRACE("%p\n", hmenu);
 
-       ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
-       mii.cbSize = sizeof(MENUITEMINFOA);
+       ZeroMemory ( &mii, sizeof(MENUITEMINFOW));
+       mii.cbSize = sizeof(MENUITEMINFOW);
        mii.fMask = MIIM_SUBMENU|MIIM_DATA;
 
        for (i = 0; i < GetMenuItemCount( hmenu ); i++)
-       { GetMenuItemInfoA(hmenu, i, TRUE, &mii );
+       { GetMenuItemInfoW(hmenu, i, TRUE, &mii );
 
          if (mii.dwItemData)
            SHFree((LPFMINFO)mii.dwItemData);
@@ -702,15 +712,15 @@ BOOL WINAPI FileMenu_DeleteAllItems (HMENU hmenu)
  */
 BOOL WINAPI FileMenu_DeleteItemByCmd (HMENU hMenu, UINT uID)
 {
-       MENUITEMINFOA mii;
+       MENUITEMINFOW mii;
 
        TRACE("%p 0x%08x\n", hMenu, uID);
 
-       ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
-       mii.cbSize = sizeof(MENUITEMINFOA);
+       ZeroMemory ( &mii, sizeof(MENUITEMINFOW));
+       mii.cbSize = sizeof(MENUITEMINFOW);
        mii.fMask = MIIM_SUBMENU;
 
-       GetMenuItemInfoA(hMenu, uID, FALSE, &mii );
+       GetMenuItemInfoW(hMenu, uID, FALSE, &mii );
        if ( mii.hSubMenu )
        {
          /* FIXME: Do what? */
@@ -725,15 +735,15 @@ BOOL WINAPI FileMenu_DeleteItemByCmd (HMENU hMenu, UINT uID)
  */
 BOOL WINAPI FileMenu_DeleteItemByIndex ( HMENU hMenu, UINT uPos)
 {
-       MENUITEMINFOA mii;
+       MENUITEMINFOW mii;
 
        TRACE("%p 0x%08x\n", hMenu, uPos);
 
-       ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
-       mii.cbSize = sizeof(MENUITEMINFOA);
+       ZeroMemory ( &mii, sizeof(MENUITEMINFOW));
+       mii.cbSize = sizeof(MENUITEMINFOW);
        mii.fMask = MIIM_SUBMENU;
 
-       GetMenuItemInfoA(hMenu, uPos, TRUE, &mii );
+       GetMenuItemInfoW(hMenu, uPos, TRUE, &mii );
        if ( mii.hSubMenu )
        {
          /* FIXME: Do what? */
@@ -829,12 +839,12 @@ LPVOID WINAPI SHFind_InitMenuPopup (HMENU hMenu, HWND hWndParent, DWORD w, DWORD
  */
 BOOL _SHIsMenuSeparator(HMENU hm, int i)
 {
-       MENUITEMINFOA mii;
+       MENUITEMINFOW mii;
 
-       mii.cbSize = sizeof(MENUITEMINFOA);
+       mii.cbSize = sizeof(MENUITEMINFOW);
        mii.fMask = MIIM_TYPE;
        mii.cch = 0;    /* WARNING: We MUST initialize it to 0*/
-       if (!GetMenuItemInfoA(hm, i, TRUE, &mii))
+       if (!GetMenuItemInfoW(hm, i, TRUE, &mii))
        {
          return(FALSE);
        }
@@ -853,8 +863,8 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI
 {      int             nItem;
        HMENU           hmSubMenu;
        BOOL            bAlreadySeparated;
-       MENUITEMINFOA   miiSrc;
-       char            szName[256];
+       MENUITEMINFOW   miiSrc;
+       WCHAR           szName[256];
        UINT            uTemp, uIDMax = uIDAdjust;
 
        TRACE("hmenu1=%p hmenu2=%p 0x%04x 0x%04x 0x%04x  0x%04lx\n",
@@ -887,16 +897,16 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI
        /* Go through the menu items and clone them*/
        for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--)
        {
-         miiSrc.cbSize = sizeof(MENUITEMINFOA);
+         miiSrc.cbSize = sizeof(MENUITEMINFOW);
          miiSrc.fMask =  MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
 
          /* We need to reset this every time through the loop in case menus DON'T have IDs*/
          miiSrc.fType = MFT_STRING;
          miiSrc.dwTypeData = szName;
          miiSrc.dwItemData = 0;
-         miiSrc.cch = sizeof(szName);
+         miiSrc.cch = sizeof(szName)/sizeof(WCHAR);
 
-         if (!GetMenuItemInfoA(hmSrc, nItem, TRUE, &miiSrc))
+         if (!GetMenuItemInfoW(hmSrc, nItem, TRUE, &miiSrc))
          {
            continue;
          }
@@ -955,7 +965,7 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI
 
 /*       TRACE("inserting menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmDst, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu);
 */
-         if (!InsertMenuItemA(hmDst, uInsert, TRUE, &miiSrc))
+         if (!InsertMenuItemW(hmDst, uInsert, TRUE, &miiSrc))
          {
            return(uIDMax);
          }
@@ -984,7 +994,7 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI
            if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
            {
              /* Add a separator between the menus*/
-             InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
+             InsertMenuW(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
            }
          }
        }