shell32: some new functions in shlfileop

Rolf Kalbermatter rolf.kalbermatter at citeng.com
Fri Mar 21 04:09:28 CST 2003


Changelog
  * dlls/shell32/shell32.spec
    Implement some more Win API functions.
  * dlls/shell32/shlfileop.c
    Implement some more Win API functions and add support functions for coming changes 
    to SHFileOperation.

Rolf Kalbermatter

License: X11, LGPL 

Index: dlls/shell32/shell32.spec
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32.spec,v
retrieving revision 1.65
diff -u -r1.65 shell32.spec
--- dlls/shell32/shell32.spec	20 Mar 2003 03:53:13 -0000	1.65
+++ dlls/shell32/shell32.spec	21 Mar 2003 09:02:10 -0000
@@ -84,8 +84,8 @@
   90 stub SHFindFiles
   91 stub SHFindComputer
   92 stdcall PathGetShortPath (ptr) PathGetShortPathAW
-  93 stub Win32CreateDirectory
-  94 stub Win32RemoveDirectory
+  93 stdcall Win32CreateDirectory (wstr, ptr) Win32CreateDirectoryAW
+  94 stdcall Win32RemoveDirectory (wstr) Win32RemoveDirectoryAW
   95 stdcall SHLogILFromFSIL (ptr)
   96 stdcall StrRetToStrN (ptr long ptr ptr) StrRetToStrNAW
   97 stdcall SHWaitForFileToOpen (long long long)
@@ -410,6 +410,9 @@
 # version 5.00 (Win2K)
 # _WIN32_IE >= 0x0500
 #
+@ forward SHGetDiskFreeSpaceA kernel32.GetDiskFreeSpaceExA
+@ stdcall SHGetDiskFreeSpaceExA kernel32.GetDiskFreeSpaceExA
+@ stdcall SHGetDiskFreeSpaceExW kernel32.GetDiskFreeSpaceExW
 @ stdcall SHGetFolderPathA(long long long long ptr)
 @ stdcall SHGetFolderPathW(long long long long ptr)
 @ stdcall SHGetFolderLocation(long long long long ptr)

Index: dlls/shell32/shlfileop.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlfileop.c,v
retrieving revision 1.25
diff -u -r1.25 shlfileop.c
--- dlls/shell32/shlfileop.c	18 Mar 2003 18:35:49 -0000	1.25
+++ dlls/shell32/shlfileop.c	21 Mar 2003 09:59:53 -0000
@@ -23,6 +23,7 @@
 #include "wine/port.h"
 
 #include <string.h>
+#include <ctype.h>
 
 #include "winreg.h"
 #include "shellapi.h"
@@ -35,177 +36,505 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
-BOOL SHELL_ConfirmDialog (int nKindOfDialog, LPCSTR szDir)
+#define IsAttribFile(x) (!(x == -1) && !(x & FILE_ATTRIBUTE_DIRECTORY))
+#define IsAttribDir(x)  (!(x == -1) && (x & FILE_ATTRIBUTE_DIRECTORY))
+
+#define IsDotDir(x)     ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
+
+CHAR aWildcardFile[] = {'*','.','*',0};
+WCHAR wWildcardFile[] = {'*','.','*',0};
+WCHAR wWildcardChars[] = {'*','?',0};
+WCHAR wBackslash[] = {'\\',0};
+
+static BOOL SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec);
+static BOOL SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec);
+static BOOL SHNotifyRemoveDirectoryA(LPCSTR path);
+static BOOL SHNotifyRemoveDirectoryW(LPCWSTR path);
+static BOOL SHNotifyDeleteFileA(LPCSTR path);
+static BOOL SHNotifyDeleteFileW(LPCWSTR path);
+static BOOL SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest);
+static BOOL SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bRenameIfExists);
+
+typedef struct
 {
-	char szCaption[255], szText[255], szBuffer[MAX_PATH + 256];
 	UINT caption_resource_id, text_resource_id;
+} SHELL_ConfirmIDstruc;
 
-	switch(nKindOfDialog) {
+static BOOL SHELL_ConfirmIDs(int nKindOfDialog, SHELL_ConfirmIDstruc *ids)
+{
+	switch (nKindOfDialog) {
+	  case ASK_DELETE_FILE:
+	    ids->caption_resource_id  = IDS_DELETEITEM_CAPTION;
+	    ids->text_resource_id  = IDS_DELETEITEM_TEXT;
+	    return TRUE;
+	  case ASK_DELETE_FOLDER:
+	    ids->caption_resource_id  = IDS_DELETEFOLDER_CAPTION;
+	    ids->text_resource_id  = IDS_DELETEITEM_TEXT;
+	    return TRUE;
+	  case ASK_DELETE_MULTIPLE_ITEM:
+	    ids->caption_resource_id  = IDS_DELETEITEM_CAPTION;
+	    ids->text_resource_id  = IDS_DELETEMULTIPLE_TEXT;
+	    return TRUE;
+	  case ASK_OVERWRITE_FILE:
+	    ids->caption_resource_id  = IDS_OVERWRITEFILE_CAPTION;
+	    ids->text_resource_id  = IDS_OVERWRITEFILE_TEXT;
+	    return TRUE;
+	  default:
+	    FIXME(" Unhandled nKindOfDialog %d stub\n", nKindOfDialog);
+	}
+	return FALSE;
+}
 
-	case ASK_DELETE_FILE:
-	  caption_resource_id	= IDS_DELETEITEM_CAPTION;
-	  text_resource_id	= IDS_DELETEITEM_TEXT;
-	  break;
-	case ASK_DELETE_FOLDER:
-	  caption_resource_id	= IDS_DELETEFOLDER_CAPTION;
-	  text_resource_id	= IDS_DELETEITEM_TEXT;
-	  break;
-	case ASK_DELETE_MULTIPLE_ITEM:
-	  caption_resource_id	= IDS_DELETEITEM_CAPTION;
-	  text_resource_id	= IDS_DELETEMULTIPLE_TEXT;
-	  break;
-	case ASK_OVERWRITE_FILE:
-	  caption_resource_id	= IDS_OVERWRITEFILE_CAPTION;
-	  text_resource_id	= IDS_OVERWRITEFILE_TEXT;
-	  break;
-	default:
-	  FIXME(" Unhandled nKindOfDialog %d stub\n", nKindOfDialog);
+BOOL SHELL_ConfirmDialog(int nKindOfDialog, LPCSTR szDir)
+{
+	CHAR szCaption[255], szText[255], szBuffer[MAX_PATH + 256];
+	SHELL_ConfirmIDstruc ids;
+
+	if (!SHELL_ConfirmIDs(nKindOfDialog, &ids))
 	  return FALSE;
-	}
 
-	LoadStringA(shell32_hInstance, caption_resource_id, szCaption, sizeof(szCaption));
-	LoadStringA(shell32_hInstance, text_resource_id, szText, sizeof(szText));
+	LoadStringA(shell32_hInstance, ids.caption_resource_id, szCaption, sizeof(szCaption));
+	LoadStringA(shell32_hInstance, ids.text_resource_id, szText, sizeof(szText));
 
-	FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+	FormatMessageA(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
 	               szText, 0, 0, szBuffer, sizeof(szBuffer), (va_list*)&szDir);
 
 	return (IDOK == MessageBoxA(GetActiveWindow(), szBuffer, szCaption, MB_OKCANCEL | MB_ICONEXCLAMATION));
 }
 
+BOOL SHELL_ConfirmDialogW(int nKindOfDialog, LPCWSTR szDir)
+{
+	WCHAR szCaption[255], szText[255], szBuffer[MAX_PATH + 256];
+	SHELL_ConfirmIDstruc ids;
+
+	if (!SHELL_ConfirmIDs(nKindOfDialog, &ids))
+	  return FALSE;
+
+	LoadStringW(shell32_hInstance, ids.caption_resource_id, szCaption, sizeof(szCaption));
+	LoadStringW(shell32_hInstance, ids.text_resource_id, szText, sizeof(szText));
+
+	FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
+	               szText, 0, 0, szBuffer, sizeof(szBuffer), (va_list*)&szDir);
+
+	return (IDOK == MessageBoxW(GetActiveWindow(), szBuffer, szCaption, MB_OKCANCEL | MB_ICONEXCLAMATION));
+}
+
 /**************************************************************************
- *	SHELL_DeleteDirectoryA()
+ * SHELL_DeleteDirectoryA()  [internal]
  *
  * like rm -r
  */
-
 BOOL SHELL_DeleteDirectoryA(LPCSTR pszDir, BOOL bShowUI)
 {
-	BOOL		ret = FALSE;
-	HANDLE		hFind;
+	BOOL    ret = TRUE;
+	HANDLE  hFind;
 	WIN32_FIND_DATAA wfd;
-	char		szTemp[MAX_PATH];
-
-	strcpy(szTemp, pszDir);
-	PathAddBackslashA(szTemp);
-	strcat(szTemp, "*.*");
+	char    szTemp[MAX_PATH];
 
-	if (bShowUI && !SHELL_ConfirmDialog(ASK_DELETE_FOLDER, pszDir))
+	/* 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(INVALID_HANDLE_VALUE != (hFind = FindFirstFileA(szTemp, &wfd)))
+	if (!bShowUI || SHELL_ConfirmDialog(ASK_DELETE_FOLDER, pszDir))
 	{
 	  do
 	  {
-	    if(strcasecmp(wfd.cFileName, ".") && strcasecmp(wfd.cFileName, ".."))
-	    {
-	      strcpy(szTemp, pszDir);
-	      PathAddBackslashA(szTemp);
-	      strcat(szTemp, wfd.cFileName);
-
-	      if(FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
-	        SHELL_DeleteDirectoryA(szTemp, FALSE);
-	      else
-	        DeleteFileA(szTemp);
-	    }
-	  } while(FindNextFileA(hFind, &wfd));
-
-	  FindClose(hFind);
-	  ret = RemoveDirectoryA(pszDir);
+	    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);
+	  } while (ret && FindNextFileA(hFind, &wfd));
 	}
+	FindClose(hFind);
+	if (ret)
+	  ret = SHNotifyRemoveDirectoryA(pszDir);
+	return ret;
+}
+
+BOOL SHELL_DeleteDirectoryW(LPCWSTR pszDir, BOOL bShowUI)
+{
+	BOOL    ret = TRUE;
+	HANDLE  hFind;
+	WIN32_FIND_DATAW wfd;
+	WCHAR   szTemp[MAX_PATH];
+
+	/* Make sure the directory exists before eventually prompting the user */
+	PathCombineW(szTemp, pszDir, wWildcardFile);
+	hFind = FindFirstFileW(szTemp, &wfd);
+	if (hFind == INVALID_HANDLE_VALUE)
+	  return FALSE;
 
+	if (!bShowUI || SHELL_ConfirmDialogW(ASK_DELETE_FOLDER, pszDir))
+	{
+	  do
+	  {
+	    LPWSTR lp = wfd.cAlternateFileName;
+	    if (!lp[0])
+	      lp = wfd.cFileName;
+	    if (IsDotDir(lp))
+	      continue;
+	    PathCombineW(szTemp, pszDir, lp);
+	    if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
+	      ret = SHELL_DeleteDirectoryW(szTemp, FALSE);
+	    else
+	      ret = SHNotifyDeleteFileW(szTemp);
+	  } while (ret && FindNextFileW(hFind, &wfd));
+	}
+	FindClose(hFind);
+	if (ret)
+	  ret = SHNotifyRemoveDirectoryW(pszDir);
 	return ret;
 }
 
 /**************************************************************************
- *	SHELL_DeleteFileA()
+ *  SHELL_DeleteFileA()      [internal]
  */
-
 BOOL SHELL_DeleteFileA(LPCSTR pszFile, BOOL bShowUI)
 {
 	if (bShowUI && !SHELL_ConfirmDialog(ASK_DELETE_FILE, pszFile))
-		return FALSE;
+	  return FALSE;
 
-        return DeleteFileA(pszFile);
+	return SHNotifyDeleteFileA(pszFile);
 }
 
-/*************************************************************************
- * SHCreateDirectory                       [SHELL32.165]
+BOOL SHELL_DeleteFileW(LPCWSTR pszFile, BOOL bShowUI)
+{
+	if (bShowUI && !SHELL_ConfirmDialogW(ASK_DELETE_FILE, pszFile))
+	  return FALSE;
+
+	return SHNotifyDeleteFileW(pszFile);
+}
+
+/**************************************************************************
+ * Win32CreateDirectory      [SHELL32.93]
  *
- * NOTES
- *  exported by ordinal
- *  WinNT/2000 exports Unicode
+ * Creates a directory. Also triggers a change notify if one exists.
+ *
+ * PARAMS
+ *  path       [I]   path to directory to create
+ *
+ * RETURNS
+ *  TRUE if successful, FALSE otherwise
+ *
+ * NOTES:
+ *  Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI.
+ *  This is Unicode on NT/2000
  */
-DWORD WINAPI SHCreateDirectory(HWND hWnd, LPCVOID path)
+
+static BOOL SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec)
+{
+	BOOL ret;
+	TRACE("(%s, %p)\n", debugstr_a(path), sec);
+
+	ret = CreateDirectoryA(path, sec);
+	if (ret)
+	{
+	  SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHA, path, NULL);
+	}
+	return ret;
+}
+
+static BOOL SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec)
+{
+	BOOL ret;
+	TRACE("(%s, %p)\n", debugstr_w(path), sec);
+
+	ret = CreateDirectoryW(path, sec);
+	if (ret)
+	{
+	  SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW, path, NULL);
+	}
+	return ret;
+}
+
+BOOL WINAPI Win32CreateDirectoryAW(LPCVOID path, LPSECURITY_ATTRIBUTES sec)
 {
 	if (SHELL_OsIsUnicode())
-	  return SHCreateDirectoryExW(hWnd, path, NULL);
-	return SHCreateDirectoryExA(hWnd, path, NULL);
+	  return SHNotifyCreateDirectoryW(path, sec);
+	return SHNotifyCreateDirectoryA(path, sec);
 }
 
-/*************************************************************************
- * SHCreateDirectoryExA                     [SHELL32.@]
+/************************************************************************
+ * Win32RemoveDirectory      [SHELL32.94]
+ *
+ * Deletes a directory. Also triggers a change notify if one exists.
+ *
+ * PARAMS
+ *  path       [I]   path to directory to delete
+ *
+ * RETURNS
+ *  TRUE if successful, FALSE otherwise
+ *
+ * NOTES:
+ *  Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI.
+ *  This is Unicode on NT/2000
  */
-DWORD WINAPI SHCreateDirectoryExA(HWND hWnd, LPCSTR path, LPSECURITY_ATTRIBUTES sec)
+static BOOL SHNotifyRemoveDirectoryA(LPCSTR path)
 {
-	DWORD ret;
-	TRACE("(%p, %s, %p)\n",hWnd, path, sec);
-	if ((ret = CreateDirectoryA(path, sec)))
+	BOOL ret;
+	TRACE("(%s)\n", debugstr_a(path));
+
+	ret = RemoveDirectoryA(path);
+	if (!ret)
 	{
-	  SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHA, path, NULL);
+	  /* Directory may be write protected */
+	  DWORD dwAttr = GetFileAttributesA(path);
+	  if (dwAttr != -1 && dwAttr & FILE_ATTRIBUTE_READONLY)
+	    if (SetFileAttributesA(path, dwAttr & ~FILE_ATTRIBUTE_READONLY))
+	      ret = RemoveDirectoryA(path);
 	}
-	else if (hWnd)
-	  FIXME("Semi-stub, non zero hWnd should be used as parent for error dialog!");
+	if (ret)
+	  SHChangeNotify(SHCNE_RMDIR, SHCNF_PATHA, path, NULL);
 	return ret;
 }
 
-/*************************************************************************
- * SHCreateDirectoryExW                     [SHELL32.@]
- */
-DWORD WINAPI SHCreateDirectoryExW(HWND hWnd, LPCWSTR path, LPSECURITY_ATTRIBUTES sec)
+static BOOL SHNotifyRemoveDirectoryW(LPCWSTR path)
 {
-	DWORD ret;
-	TRACE("(%p, %s, %p)\n",hWnd, debugstr_w(path), sec);
-	if ((ret = CreateDirectoryW(path, sec)))
+	BOOL ret;
+	TRACE("(%s)\n", debugstr_w(path));
+
+	ret = RemoveDirectoryW(path);
+	if (!ret)
 	{
-	  SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW, path, NULL);
+	  /* Directory may be write protected */
+	  DWORD dwAttr = GetFileAttributesW(path);
+	  if (dwAttr != -1 && dwAttr & FILE_ATTRIBUTE_READONLY)
+	    if (SetFileAttributesW(path, dwAttr & ~FILE_ATTRIBUTE_READONLY))
+	      ret = RemoveDirectoryW(path);
 	}
-	else if (hWnd)
-	  FIXME("Semi-stub, non zero hWnd should be used as parent for error dialog!");
+	if (ret)
+	  SHChangeNotify(SHCNE_RMDIR, SHCNF_PATHW, path, NULL);
 	return ret;
 }
 
+BOOL WINAPI Win32RemoveDirectoryAW(LPCVOID path)
+{
+	if (SHELL_OsIsUnicode())
+	  return SHNotifyRemoveDirectoryW(path);
+	return SHNotifyRemoveDirectoryA(path);
+}
+
 /************************************************************************
- * Win32DeleteFile                         [SHELL32.164]
+ * Win32DeleteFile           [SHELL32.164]
  *
  * Deletes a file. Also triggers a change notify if one exists.
  *
- * NOTES
+ * PARAMS
+ *  path       [I]   path to file to delete
+ *
+ * RETURNS
+ *  TRUE if successful, FALSE otherwise
+ *
+ * NOTES:
  *  Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI.
  *  This is Unicode on NT/2000
  */
-static BOOL Win32DeleteFileA(LPCSTR fName)
+static BOOL SHNotifyDeleteFileA(LPCSTR path)
 {
-	TRACE("%p(%s)\n", fName, fName);
+	BOOL ret;
+
+	TRACE("(%s)\n", debugstr_a(path));
 
-	DeleteFileA(fName);
-	SHChangeNotify(SHCNE_DELETE, SHCNF_PATHA, fName, NULL);
-	return TRUE;
+	ret = DeleteFileA(path);
+	if (!ret)
+	{
+	  /* File may be write protected or a system file */
+	  DWORD dwAttr = GetFileAttributesA(path);
+	  if ((dwAttr != -1) && (dwAttr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
+	    if (SetFileAttributesA(path, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
+	      ret = DeleteFileA(path);
+	}
+	if (ret)
+	  SHChangeNotify(SHCNE_DELETE, SHCNF_PATHA, path, NULL);
+	return ret;
 }
 
-static BOOL Win32DeleteFileW(LPCWSTR fName)
+static BOOL SHNotifyDeleteFileW(LPCWSTR path)
 {
-	TRACE("%p(%s)\n", fName, debugstr_w(fName));
+	BOOL ret;
+
+	TRACE("(%s)\n", debugstr_w(path));
 
-	DeleteFileW(fName);
-	SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, fName, NULL);
-	return TRUE;
+	ret = DeleteFileW(path);
+	if (!ret)
+	{
+	  /* File may be write protected or a system file */
+	  DWORD dwAttr = GetFileAttributesW(path);
+	  if ((dwAttr != -1) && (dwAttr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
+	    if (SetFileAttributesW(path, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
+	      ret = DeleteFileW(path);
+	}
+	if (ret)
+	  SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, path, NULL);
+	return ret;
 }
 
-DWORD WINAPI Win32DeleteFileAW(LPCVOID fName)
+DWORD WINAPI Win32DeleteFileAW(LPCVOID path)
 {
 	if (SHELL_OsIsUnicode())
-	  return Win32DeleteFileW(fName);
-	return Win32DeleteFileA(fName);
+	  return SHNotifyDeleteFileW(path);
+	return SHNotifyDeleteFileA(path);
+}
+
+/************************************************************************
+ * SHNotifyMoveFile          [internal]
+ *
+ * Moves a file. Also triggers a change notify if one exists.
+ *
+ * PARAMS
+ *  src        [I]   path to source file to move
+ *  dest       [I]   path to target file to move to
+ *
+ * RETURNS
+ *  TRUE if successful, FALSE otherwise
+ */
+static BOOL SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest)
+{
+	BOOL ret;
+
+	TRACE("(%s %s)\n", debugstr_w(src), debugstr_w(dest));
+
+	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 (SetFileAttributesW(src, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
+	      ret = MoveFileW(src, dest);
+	}
+	if (ret)
+	  SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATHW, src, dest);
+	return ret;
+}
+
+/************************************************************************
+ * SHNotifyCopyFile          [internal]
+ *
+ * Copies a file. Also triggers a change notify if one exists.
+ *
+ * PARAMS
+ *  src        [I]   path to source file to move
+ *  dest       [I]   path to target file to move to
+ *  bRename    [I]   if TRUE, the target file will be renamed if a
+ *                   file with this name already exists
+ *
+ * RETURNS
+ *  TRUE if successful, FALSE otherwise
+ */
+static BOOL SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bRename)
+{
+	BOOL ret;
+
+	TRACE("(%s %s %s)\n", debugstr_w(src), debugstr_w(dest), bRename ? "renameIfExists" : "");
+
+	ret = CopyFileW(src, dest, TRUE);
+	if (!ret && bRename)
+	{
+	  /* Destination file probably exists */
+	  DWORD dwAttr = GetFileAttributesW(dest);
+	  if (dwAttr != -1)
+	  {
+	    FIXME("Rename on copy to existing file not implemented!");
+	  }
+	}
+	if (ret)
+	  SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, dest, NULL);
+	return ret;
+}
+
+/*************************************************************************
+ * SHCreateDirectory         [SHELL32.165]
+ *
+ * Create a directory at the specified location
+ *
+ * PARAMS
+ *  hWnd       [I]   
+ *  path       [I]   path of directory to create 
+ *
+ * RETURNS
+ *  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_ALREADY_EXISTS when the directory already exists
+ *  ERROR_FILENAME_EXCED_RANGE if the filename was to long to process
+ *
+ * NOTES
+ *  exported by ordinal
+ *  Win9x exports ANSI
+ *  WinNT/2000 exports Unicode
+ */
+DWORD WINAPI SHCreateDirectory(HWND hWnd, LPCVOID path)
+{
+	if (SHELL_OsIsUnicode())
+	  return SHCreateDirectoryExW(hWnd, path, NULL);
+	return SHCreateDirectoryExA(hWnd, path, NULL);
+}
+
+/*************************************************************************
+ * SHCreateDirectoryExA      [SHELL32.@]
+ *
+ * Create a directory at the specified location
+ *
+ * PARAMS
+ *  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
+ *  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
+ */
+DWORD WINAPI SHCreateDirectoryExA(HWND hWnd, LPCSTR path, LPSECURITY_ATTRIBUTES sec)
+{
+	WCHAR wPath[MAX_PATH];
+	TRACE("(%p, %s, %p)\n",hWnd, debugstr_a(path), sec);
+
+	MultiByteToWideChar(CP_ACP, 0, path, -1, wPath, MAX_PATH);
+	return SHCreateDirectoryExW(hWnd, wPath, sec);
+}
+
+/*************************************************************************
+ * SHCreateDirectoryExW      [SHELL32.@]
+ */
+DWORD WINAPI SHCreateDirectoryExW(HWND hWnd, LPCWSTR path, LPSECURITY_ATTRIBUTES sec)
+{
+	DWORD ret = ERROR_SUCCESS;
+	TRACE("(%p, %s, %p)\n",hWnd, debugstr_w(path), sec);
+
+	if (PathIsRelativeW(path))
+	{
+	  ret = ERROR_BAD_PATHNAME;
+	  SetLastError(ERROR_BAD_PATHNAME);
+	}
+	else
+	{
+	  if (!SHNotifyCreateDirectoryW(path, sec))
+	  {
+	    ret = GetLastError();
+	    if (ret != ERROR_FILE_EXISTS &&
+	        ret != ERROR_ALREADY_EXISTS &&
+	        ret != ERROR_FILENAME_EXCED_RANGE)
+	    {
+	    /* handling network file names?
+	      lstrcpynW(pathName, path, MAX_PATH);
+	      lpStr = PathAddBackslashW(pathName);*/
+	      FIXME("Semi-stub, non zero hWnd should be used somehow?");
+	    }
+	  }
+	}
+	return ret;
 }
 
 /**************************************************************************




More information about the wine-patches mailing list