shell32: shlfilop modifications, patch 1

Rolf Kalbermatter rolf.kalbermatter at citeng.com
Thu Oct 14 07:13:33 CDT 2004


Changelog
  dlls/shell32/shlfileop.c
    Modify ANSI functions to allocate intermediate Unicode strings on the heap instead of stack

Rolf Kalbermatter

Index: shlfileop.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlfileop.c,v
retrieving revision 1.43
diff -u -r1.43 shlfileop.c
--- shlfileop.c	6 Oct 2004 00:04:39 -0000	1.43
+++ shlfileop.c	14 Oct 2004 10:58:22 -0000
@@ -45,18 +45,18 @@
 
 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 @@
 	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_DeleteDirectoryA(LPCSTR pszDir, BOOL bShowUI)
 {
-	BOOL    ret = TRUE;
-	HANDLE  hFind;
-	WIN32_FIND_DATAA wfd;
-	char    szTemp[MAX_PATH];
-
-	/* 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;
+	LPWSTR wPath;
+	BOOL ret = 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;
@@ -225,6 +224,25 @@
 }
 
 /**************************************************************************
+ * SHTestPathForWildcards      [internal]
+ *
+ * Tests the path to not contain wildcards
+ *
+ * FIXME: This test is necessary since our CreateDirectory and MoveFile
+ *        implementation does create directories with wildcard chars
+ *        without objection. Once this is fixed, this can go away.
+ */
+static DWORD SHTestPathForWildcards(LPCWSTR name)
+{
+	if (StrPBrkW(name, wWildcardChars))
+	{
+	  SetLastError(ERROR_INVALID_NAME);
+	  return ERROR_INVALID_NAME;
+	}
+	return ERROR_SUCCESS;
+}
+
+/**************************************************************************
  * Win32CreateDirectory      [SHELL32.93]
  *
  * Creates a directory. Also triggers a change notify if one exists.
@@ -241,31 +259,31 @@
  */
 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;
 }
 
 /**********************************************************************/
 
 static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec)
 {
+	DWORD retCode;
+
 	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
-	}
+	retCode = SHTestPathForWildcards(path);
+	if (retCode)
+	  return retCode;
 
 	if (CreateDirectoryW(path, sec))
 	{
@@ -302,11 +320,18 @@
 
 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 +346,7 @@
 	{
 	  /* 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 +385,18 @@
 
 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 +412,7 @@
 	{
 	  /* 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);
 	}
@@ -418,28 +450,20 @@
 static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest, BOOL bRename)
 {
 	BOOL ret;
+	DWORD retCode;
 
 	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
-	}
+	retCode = SHTestPathForWildcards(dest);
+	if (retCode)
+	  return retCode;
 
 	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 +471,7 @@
 	  {
 	    /* 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 +510,7 @@
 	{
 	  /* 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 +526,9 @@
 /*************************************************************************
  * 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 +538,8 @@
  *  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 +558,47 @@
 /*************************************************************************
  * 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 +607,7 @@
 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 +616,7 @@
 	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)





More information about the wine-patches mailing list