xref: /reactos/base/shell/cmd/move.c (revision 3b960a1c)
1c2c66affSColin Finck /*
2c2c66affSColin Finck *  MOVE.C - move internal command.
3c2c66affSColin Finck *
4c2c66affSColin Finck *
5c2c66affSColin Finck *  History:
6c2c66affSColin Finck *
7c2c66affSColin Finck *    14-Dec-1998 (Eric Kohl)
8c2c66affSColin Finck *        Started.
9c2c66affSColin Finck *
10c2c66affSColin Finck *    18-Jan-1999 (Eric Kohl)
11c2c66affSColin Finck *        Unicode safe!
12c2c66affSColin Finck *        Preliminary version!!!
13c2c66affSColin Finck *
14c2c66affSColin Finck *    20-Jan-1999 (Eric Kohl)
15c2c66affSColin Finck *        Redirection safe!
16c2c66affSColin Finck *
17c2c66affSColin Finck *    27-Jan-1999 (Eric Kohl)
18c2c66affSColin Finck *        Added help text ("/?").
19c2c66affSColin Finck *        Added more error checks.
20c2c66affSColin Finck *
21c2c66affSColin Finck *    03-Feb-1999 (Eric Kohl)
22c2c66affSColin Finck *        Added "/N" option.
23c2c66affSColin Finck *
24c2c66affSColin Finck *    30-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
25c2c66affSColin Finck *        Remove all hardcoded strings in En.rc
26c2c66affSColin Finck *
27c2c66affSColin Finck *    24-Jun-2005 (Brandon Turner <turnerb7@msu.edu>)
28c2c66affSColin Finck *        Fixed bug to allow MS style wildcards + code clean up
29c2c66affSColin Finck *        added /y and /-y
30c2c66affSColin Finck */
31c2c66affSColin Finck 
32c2c66affSColin Finck #include "precomp.h"
33c2c66affSColin Finck 
34c2c66affSColin Finck #ifdef INCLUDE_CMD_MOVE
35c2c66affSColin Finck 
36c2c66affSColin Finck enum
37c2c66affSColin Finck {
38c2c66affSColin Finck     MOVE_NOTHING  = 0x001,   /* /N  */
39c2c66affSColin Finck     MOVE_OVER_YES = 0x002,   /* /Y  */
40c2c66affSColin Finck     MOVE_OVER_NO  = 0x004,   /* /-Y */
41c2c66affSColin Finck };
42c2c66affSColin Finck 
43c2c66affSColin Finck enum
44c2c66affSColin Finck {
45c2c66affSColin Finck     /* Move status flags */
46c2c66affSColin Finck     MOVE_SOURCE_IS_DIR      = 0x001,
47c2c66affSColin Finck     MOVE_SOURCE_IS_FILE     = 0x002,
48c2c66affSColin Finck     MOVE_DEST_IS_DIR        = 0x004,
49c2c66affSColin Finck     MOVE_DEST_IS_FILE       = 0x008,
50c2c66affSColin Finck     MOVE_SOURCE_HAS_WILD    = 0x010, /* source has wildcard */
51c2c66affSColin Finck     MOVE_SRC_CURRENT_IS_DIR = 0x020, /* source is file but at the current round we found a directory */
52c2c66affSColin Finck     MOVE_DEST_EXISTS        = 0x040,
53c2c66affSColin Finck     MOVE_PATHS_ON_DIF_VOL   = 0x080  /* source and destination paths are on different volume */
54c2c66affSColin Finck };
55c2c66affSColin Finck 
MoveOverwrite(LPTSTR fn)56c2c66affSColin Finck static INT MoveOverwrite (LPTSTR fn)
57c2c66affSColin Finck {
58c2c66affSColin Finck     /* ask the user if they want to override */
59c2c66affSColin Finck     INT res;
60c2c66affSColin Finck     ConOutResPrintf(STRING_MOVE_HELP1, fn);
61c2c66affSColin Finck     res = FilePromptYNA (0);
62c2c66affSColin Finck     return res;
63c2c66affSColin Finck }
64c2c66affSColin Finck 
GetDirectory(LPTSTR wholepath,LPTSTR directory,BOOL CheckExisting)65c2c66affSColin Finck void GetDirectory (LPTSTR wholepath, LPTSTR directory, BOOL CheckExisting)
66c2c66affSColin Finck {
67c2c66affSColin Finck     /* returns only directory part of path with backslash */
68c2c66affSColin Finck     /* TODO: make code unc aware */
69c2c66affSColin Finck     /* Is there a better alternative to this? */
70c2c66affSColin Finck     LPTSTR last;
71c2c66affSColin Finck     if (CheckExisting && IsExistingDirectory(wholepath))
72c2c66affSColin Finck     {
73c2c66affSColin Finck         _tcscpy(directory, wholepath);
74c2c66affSColin Finck     }
75c2c66affSColin Finck     else if ((last = _tcsrchr(wholepath,_T('\\'))) != NULL)
76c2c66affSColin Finck     {
77c2c66affSColin Finck         _tcsncpy(directory, wholepath, last - wholepath + 1);
78c2c66affSColin Finck         directory[last - wholepath + 1] = 0;
79c2c66affSColin Finck     }
80c2c66affSColin Finck     else
81c2c66affSColin Finck     {
82c2c66affSColin Finck         GetRootPath(wholepath,directory, MAX_PATH);
83c2c66affSColin Finck     }
84c2c66affSColin Finck }
85c2c66affSColin Finck 
86c2c66affSColin Finck 
cmd_move(LPTSTR param)87c2c66affSColin Finck INT cmd_move (LPTSTR param)
88c2c66affSColin Finck {
89c2c66affSColin Finck     LPTSTR *arg;
90c2c66affSColin Finck     INT argc, i, nFiles;
91c2c66affSColin Finck     LPTSTR pszDest;
92c2c66affSColin Finck     TCHAR szDestPath[MAX_PATH];
93c2c66affSColin Finck     TCHAR szFullDestPath[MAX_PATH];
94c2c66affSColin Finck     TCHAR szSrcDirPath[MAX_PATH];
95c2c66affSColin Finck     TCHAR szSrcPath[MAX_PATH];
96c2c66affSColin Finck     TCHAR szFullSrcPath[MAX_PATH];
97c2c66affSColin Finck     DWORD dwFlags = 0;
98c2c66affSColin Finck     INT nOverwrite = 0;
99c2c66affSColin Finck     WIN32_FIND_DATA findBuffer;
100c2c66affSColin Finck     HANDLE hFile;
101c2c66affSColin Finck 
102c2c66affSColin Finck     /* used only when source and destination  directories are on different volume */
103c2c66affSColin Finck     HANDLE hDestFile = NULL;
104c2c66affSColin Finck     WIN32_FIND_DATA findDestBuffer;
105c2c66affSColin Finck     TCHAR szMoveDest[MAX_PATH];
106c2c66affSColin Finck     TCHAR szMoveSrc[MAX_PATH];
107c2c66affSColin Finck     LPTSTR pszDestDirPointer;
108c2c66affSColin Finck     LPTSTR pszSrcDirPointer;
109c2c66affSColin Finck     INT nDirLevel = 0;
110c2c66affSColin Finck 
111c2c66affSColin Finck     LPTSTR pszFile;
112c2c66affSColin Finck     BOOL OnlyOneFile;
113c2c66affSColin Finck     BOOL FoundFile;
114c2c66affSColin Finck     BOOL MoveStatus;
115c2c66affSColin Finck     DWORD dwMoveFlags = 0;
116c2c66affSColin Finck     DWORD dwMoveStatusFlags = 0;
117c2c66affSColin Finck 
118c2c66affSColin Finck     if (!_tcsncmp (param, _T("/?"), 2))
119c2c66affSColin Finck     {
120c2c66affSColin Finck #if 0
121c2c66affSColin Finck         ConOutPuts (_T("Moves files and renames files and directories.\n\n"
122c2c66affSColin Finck             "To move one or more files:\n"
123c2c66affSColin Finck             "MOVE [/N][/Y|/-Y][drive:][path]filename1[,...] destination\n"
124c2c66affSColin Finck             "\n"
125c2c66affSColin Finck             "To rename a directory:\n"
126c2c66affSColin Finck             "MOVE [/N][/Y|/-Y][drive:][path]dirname1 dirname2\n"
127c2c66affSColin Finck             "\n"
128c2c66affSColin Finck             "  [drive:][path]filename1  Specifies the location and name of the file\n"
129c2c66affSColin Finck             "                           or files you want to move.\n"
130c2c66affSColin Finck             "  /N                       Nothing. Don everthing but move files or directories.\n"
131c2c66affSColin Finck             "  /Y\n"
132c2c66affSColin Finck             "  /-Y\n"
133c2c66affSColin Finck             "..."));
134c2c66affSColin Finck #else
135c2c66affSColin Finck         ConOutResPaging(TRUE,STRING_MOVE_HELP2);
136c2c66affSColin Finck #endif
137c2c66affSColin Finck         return 0;
138c2c66affSColin Finck     }
139c2c66affSColin Finck 
140c2c66affSColin Finck     nErrorLevel = 0;
141c2c66affSColin Finck     arg = splitspace(param, &argc);
142c2c66affSColin Finck 
143c2c66affSColin Finck     /* read options */
144c2c66affSColin Finck     for (i = 0; i < argc; i++)
145c2c66affSColin Finck     {
146c2c66affSColin Finck         if (!_tcsicmp(arg[i], _T("/N")))
147c2c66affSColin Finck             dwFlags |= MOVE_NOTHING;
148c2c66affSColin Finck         else if (!_tcsicmp(arg[i], _T("/Y")))
149c2c66affSColin Finck             dwFlags |= MOVE_OVER_YES;
150c2c66affSColin Finck         else if (!_tcsicmp(arg[i], _T("/-Y")))
151c2c66affSColin Finck             dwFlags |= MOVE_OVER_NO;
152c2c66affSColin Finck         else
153c2c66affSColin Finck             break;
154c2c66affSColin Finck     }
155c2c66affSColin Finck     nFiles = argc - i;
156c2c66affSColin Finck 
157c2c66affSColin Finck     if (nFiles < 1)
158c2c66affSColin Finck     {
159c2c66affSColin Finck         /* there must be at least one pathspec */
160c2c66affSColin Finck         error_req_param_missing();
161*3b960a1cSHermès Bélusca-Maïto         nErrorLevel = 1;
162*3b960a1cSHermès Bélusca-Maïto         goto Quit;
163c2c66affSColin Finck     }
164c2c66affSColin Finck 
165c2c66affSColin Finck     if (nFiles > 2)
166c2c66affSColin Finck     {
167c2c66affSColin Finck         /* there are more than two pathspecs */
168c2c66affSColin Finck         error_too_many_parameters(param);
169*3b960a1cSHermès Bélusca-Maïto         nErrorLevel = 1;
170*3b960a1cSHermès Bélusca-Maïto         goto Quit;
171c2c66affSColin Finck     }
172c2c66affSColin Finck 
173c2c66affSColin Finck     /* If no destination is given, default to current directory */
174c2c66affSColin Finck     pszDest = (nFiles == 1) ? _T(".") : arg[i + 1];
175c2c66affSColin Finck 
176c2c66affSColin Finck     /* check for wildcards in source and destination */
177c2c66affSColin Finck     if (_tcschr(pszDest, _T('*')) != NULL || _tcschr(pszDest, _T('?')) != NULL)
178c2c66affSColin Finck     {
179c2c66affSColin Finck         /* '*'/'?' in dest, this doesnt happen.  give folder name instead*/
180c2c66affSColin Finck         error_invalid_parameter_format(pszDest);
181*3b960a1cSHermès Bélusca-Maïto         nErrorLevel = 1;
182*3b960a1cSHermès Bélusca-Maïto         goto Quit;
183c2c66affSColin Finck     }
184c2c66affSColin Finck     if (_tcschr(arg[i], _T('*')) != NULL || _tcschr(arg[i], _T('?')) != NULL)
185c2c66affSColin Finck     {
186c2c66affSColin Finck         dwMoveStatusFlags |= MOVE_SOURCE_HAS_WILD;
187c2c66affSColin Finck     }
188c2c66affSColin Finck 
189c2c66affSColin Finck     /* get destination */
190c2c66affSColin Finck     GetFullPathName (pszDest, MAX_PATH, szDestPath, NULL);
191c2c66affSColin Finck     TRACE ("Destination: %s\n", debugstr_aw(szDestPath));
192c2c66affSColin Finck 
193c2c66affSColin Finck     /* get source folder */
194c2c66affSColin Finck     GetFullPathName(arg[i], MAX_PATH, szSrcDirPath, &pszFile);
195c2c66affSColin Finck     if (pszFile != NULL)
196c2c66affSColin Finck         *pszFile = _T('\0');
197c2c66affSColin Finck     TRACE ("Source Folder: %s\n", debugstr_aw(szSrcDirPath));
198c2c66affSColin Finck 
199c2c66affSColin Finck     hFile = FindFirstFile (arg[i], &findBuffer);
200c2c66affSColin Finck     if (hFile == INVALID_HANDLE_VALUE)
201c2c66affSColin Finck     {
202c2c66affSColin Finck         ErrorMessage(GetLastError(), arg[i]);
203*3b960a1cSHermès Bélusca-Maïto         nErrorLevel = 1;
204*3b960a1cSHermès Bélusca-Maïto         goto Quit;
205c2c66affSColin Finck     }
206c2c66affSColin Finck 
207c2c66affSColin Finck     /* check for special cases "." and ".." and if found skip them */
208c2c66affSColin Finck     FoundFile = TRUE;
209c2c66affSColin Finck     while(FoundFile &&
210c2c66affSColin Finck           (_tcscmp(findBuffer.cFileName,_T(".")) == 0 ||
211c2c66affSColin Finck            _tcscmp(findBuffer.cFileName,_T("..")) == 0))
212c2c66affSColin Finck         FoundFile = FindNextFile (hFile, &findBuffer);
213c2c66affSColin Finck 
214c2c66affSColin Finck     if (!FoundFile)
215c2c66affSColin Finck     {
216c2c66affSColin Finck         /* what? we don't have anything to move? */
217c2c66affSColin Finck         error_file_not_found();
218c2c66affSColin Finck         FindClose(hFile);
219*3b960a1cSHermès Bélusca-Maïto         nErrorLevel = 1;
220*3b960a1cSHermès Bélusca-Maïto         goto Quit;
221c2c66affSColin Finck     }
222c2c66affSColin Finck 
223c2c66affSColin Finck     OnlyOneFile = TRUE;
224c2c66affSColin Finck     /* check if there can be found files as files have first priority */
225c2c66affSColin Finck     if (findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
226c2c66affSColin Finck         dwMoveStatusFlags |= MOVE_SOURCE_IS_DIR;
227c2c66affSColin Finck     else
228c2c66affSColin Finck         dwMoveStatusFlags |= MOVE_SOURCE_IS_FILE;
229c2c66affSColin Finck     while(OnlyOneFile && FindNextFile(hFile,&findBuffer))
230c2c66affSColin Finck     {
231c2c66affSColin Finck         if (!(findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
232c2c66affSColin Finck         {
233c2c66affSColin Finck             ConOutPrintf(_T(""));
234c2c66affSColin Finck             if (dwMoveStatusFlags & MOVE_SOURCE_IS_FILE) OnlyOneFile = FALSE;
235c2c66affSColin Finck             else
236c2c66affSColin Finck             {	/* this has been done this way so that we don't disturb other settings if they have been set before this */
237c2c66affSColin Finck                 dwMoveStatusFlags |= MOVE_SOURCE_IS_FILE;
238c2c66affSColin Finck                 dwMoveStatusFlags &= ~MOVE_SOURCE_IS_DIR;
239c2c66affSColin Finck             }
240c2c66affSColin Finck         }
241c2c66affSColin Finck     }
242c2c66affSColin Finck     FindClose(hFile);
243c2c66affSColin Finck 
244c2c66affSColin Finck     TRACE ("Do we have only one file: %s\n", OnlyOneFile ? "TRUE" : "FALSE");
245c2c66affSColin Finck 
246c2c66affSColin Finck     /* we have to start again to be sure we don't miss any files or folders*/
247c2c66affSColin Finck     hFile = FindFirstFile (arg[i], &findBuffer);
248c2c66affSColin Finck     if (hFile == INVALID_HANDLE_VALUE)
249c2c66affSColin Finck     {
250c2c66affSColin Finck         ErrorMessage(GetLastError(), arg[i]);
251*3b960a1cSHermès Bélusca-Maïto         nErrorLevel = 1;
252*3b960a1cSHermès Bélusca-Maïto         goto Quit;
253c2c66affSColin Finck     }
254c2c66affSColin Finck 
255c2c66affSColin Finck     /* check for special cases "." and ".." and if found skip them */
256c2c66affSColin Finck     FoundFile = TRUE;
257c2c66affSColin Finck     while(FoundFile &&
258c2c66affSColin Finck           (_tcscmp(findBuffer.cFileName,_T(".")) == 0 ||
259c2c66affSColin Finck            _tcscmp(findBuffer.cFileName,_T("..")) == 0))
260c2c66affSColin Finck         FoundFile = FindNextFile (hFile, &findBuffer);
261c2c66affSColin Finck 
262c2c66affSColin Finck     if (!FoundFile)
263c2c66affSColin Finck     {
264c2c66affSColin Finck         /* huh? somebody removed files and/or folders which were there */
265c2c66affSColin Finck         error_file_not_found();
266c2c66affSColin Finck         FindClose(hFile);
267*3b960a1cSHermès Bélusca-Maïto         nErrorLevel = 1;
268*3b960a1cSHermès Bélusca-Maïto         goto Quit;
269c2c66affSColin Finck     }
270c2c66affSColin Finck 
271c2c66affSColin Finck     /* check if source and destination paths are on different volumes */
272c2c66affSColin Finck     if (szSrcDirPath[0] != szDestPath[0])
273c2c66affSColin Finck         dwMoveStatusFlags |= MOVE_PATHS_ON_DIF_VOL;
274c2c66affSColin Finck 
275c2c66affSColin Finck     /* move it */
276c2c66affSColin Finck     do
277c2c66affSColin Finck     {
278c2c66affSColin Finck         TRACE ("Found file/directory: %s\n", debugstr_aw(findBuffer.cFileName));
279c2c66affSColin Finck         nOverwrite = 1;
280c2c66affSColin Finck         dwMoveFlags = 0;
281c2c66affSColin Finck         dwMoveStatusFlags &= ~MOVE_DEST_IS_FILE &
282c2c66affSColin Finck                             ~MOVE_DEST_IS_DIR &
283c2c66affSColin Finck                             ~MOVE_SRC_CURRENT_IS_DIR &
284c2c66affSColin Finck                             ~MOVE_DEST_EXISTS;
285c2c66affSColin Finck         _tcscpy(szFullSrcPath,szSrcDirPath);
286c2c66affSColin Finck         if (szFullSrcPath[_tcslen(szFullSrcPath) -  1] != _T('\\'))
287c2c66affSColin Finck             _tcscat (szFullSrcPath, _T("\\"));
288c2c66affSColin Finck         _tcscat(szFullSrcPath,findBuffer.cFileName);
289c2c66affSColin Finck         _tcscpy(szSrcPath, szFullSrcPath);
290c2c66affSColin Finck 
291c2c66affSColin Finck         if (IsExistingDirectory(szSrcPath))
292c2c66affSColin Finck         {
293c2c66affSColin Finck             /* source is directory */
294c2c66affSColin Finck             if (dwMoveStatusFlags & MOVE_SOURCE_IS_FILE)
295c2c66affSColin Finck             {
296c2c66affSColin Finck                 dwMoveStatusFlags |= MOVE_SRC_CURRENT_IS_DIR; /* source is file but at the current round we found a directory */
297c2c66affSColin Finck                 continue;
298c2c66affSColin Finck             }
299c2c66affSColin Finck             TRACE ("Source is dir: %s\n", debugstr_aw(szSrcPath));
300c2c66affSColin Finck             dwMoveFlags = MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED;
301c2c66affSColin Finck         }
302c2c66affSColin Finck 
303c2c66affSColin Finck         /* if source is file we don't need to do anything special */
304c2c66affSColin Finck         if (IsExistingDirectory(szDestPath))
305c2c66affSColin Finck         {
306c2c66affSColin Finck             /* destination is existing directory */
307c2c66affSColin Finck             TRACE ("Destination is directory: %s\n", debugstr_aw(szDestPath));
308c2c66affSColin Finck 
309c2c66affSColin Finck             dwMoveStatusFlags |= MOVE_DEST_IS_DIR;
310c2c66affSColin Finck 
311c2c66affSColin Finck             /*build the dest string(accounts for *)*/
312c2c66affSColin Finck             _tcscpy (szFullDestPath, szDestPath);
313c2c66affSColin Finck             /*check to see if there is an ending slash, if not add one*/
314c2c66affSColin Finck             if (szFullDestPath[_tcslen(szFullDestPath) -  1] != _T('\\'))
315c2c66affSColin Finck                 _tcscat (szFullDestPath, _T("\\"));
316c2c66affSColin Finck             _tcscat (szFullDestPath, findBuffer.cFileName);
317c2c66affSColin Finck 
318c2c66affSColin Finck             if (IsExistingFile(szFullDestPath) || IsExistingDirectory(szFullDestPath))
319c2c66affSColin Finck                 dwMoveStatusFlags |= MOVE_DEST_EXISTS;
320c2c66affSColin Finck 
321c2c66affSColin Finck             dwMoveFlags |= MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED;
322c2c66affSColin Finck         }
323c2c66affSColin Finck         if (IsExistingFile(szDestPath))
324c2c66affSColin Finck         {
325c2c66affSColin Finck             /* destination is a file */
326c2c66affSColin Finck             TRACE ("Destination is file: %s\n", debugstr_aw(szDestPath));
327c2c66affSColin Finck 
328c2c66affSColin Finck             dwMoveStatusFlags |= MOVE_DEST_IS_FILE | MOVE_DEST_EXISTS;
329c2c66affSColin Finck             _tcscpy (szFullDestPath, szDestPath);
330c2c66affSColin Finck 
331c2c66affSColin Finck             dwMoveFlags |= MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED;
332c2c66affSColin Finck         }
333c2c66affSColin Finck 
334c2c66affSColin Finck         TRACE ("Move Status Flags: 0x%X\n",dwMoveStatusFlags);
335c2c66affSColin Finck 
336c2c66affSColin Finck         if (dwMoveStatusFlags & MOVE_SOURCE_IS_DIR &&
337c2c66affSColin Finck             dwMoveStatusFlags & MOVE_DEST_IS_DIR &&
338c2c66affSColin Finck             dwMoveStatusFlags & MOVE_SOURCE_HAS_WILD)
339c2c66affSColin Finck         {
340c2c66affSColin Finck             /* We are not allowed to have existing source and destination dir when there is wildcard in source */
341c2c66affSColin Finck             error_syntax(NULL);
342c2c66affSColin Finck             FindClose(hFile);
343*3b960a1cSHermès Bélusca-Maïto             nErrorLevel = 1;
344*3b960a1cSHermès Bélusca-Maïto             goto Quit;
345c2c66affSColin Finck         }
346c2c66affSColin Finck         if (!(dwMoveStatusFlags & (MOVE_DEST_IS_FILE | MOVE_DEST_IS_DIR)))
347c2c66affSColin Finck         {
348c2c66affSColin Finck             /* destination doesn't exist */
349c2c66affSColin Finck             _tcscpy (szFullDestPath, szDestPath);
350c2c66affSColin Finck             if (dwMoveStatusFlags & MOVE_SOURCE_IS_FILE) dwMoveStatusFlags |= MOVE_DEST_IS_FILE;
351c2c66affSColin Finck             if (dwMoveStatusFlags & MOVE_SOURCE_IS_DIR) dwMoveStatusFlags |= MOVE_DEST_IS_DIR;
352c2c66affSColin Finck 
353c2c66affSColin Finck             dwMoveFlags |= MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED;
354c2c66affSColin Finck         }
355c2c66affSColin Finck 
356c2c66affSColin Finck         if (dwMoveStatusFlags & MOVE_SOURCE_IS_FILE &&
357c2c66affSColin Finck             dwMoveStatusFlags & MOVE_DEST_IS_FILE &&
358c2c66affSColin Finck             !OnlyOneFile)
359c2c66affSColin Finck         {
360c2c66affSColin Finck             /*source has many files but there is only one destination file*/
361c2c66affSColin Finck             error_invalid_parameter_format(pszDest);
362c2c66affSColin Finck             FindClose(hFile);
363*3b960a1cSHermès Bélusca-Maïto             nErrorLevel = 1;
364*3b960a1cSHermès Bélusca-Maïto             goto Quit;
365c2c66affSColin Finck         }
366c2c66affSColin Finck 
367c2c66affSColin Finck         /*checks to make sure user wanted/wants the override*/
368c2c66affSColin Finck         if ((dwFlags & MOVE_OVER_NO) &&
369c2c66affSColin Finck            (dwMoveStatusFlags & MOVE_DEST_EXISTS))
370c2c66affSColin Finck             continue;
371c2c66affSColin Finck         if (!(dwFlags & MOVE_OVER_YES) &&
372c2c66affSColin Finck             (dwMoveStatusFlags & MOVE_DEST_EXISTS))
373c2c66affSColin Finck             nOverwrite = MoveOverwrite (szFullDestPath);
374c2c66affSColin Finck         if (nOverwrite == PROMPT_NO || nOverwrite == PROMPT_BREAK)
375c2c66affSColin Finck             continue;
376c2c66affSColin Finck         if (nOverwrite == PROMPT_ALL)
377c2c66affSColin Finck             dwFlags |= MOVE_OVER_YES;
378c2c66affSColin Finck 
379c2c66affSColin Finck         ConOutPrintf (_T("%s => %s "), szSrcPath, szFullDestPath);
380c2c66affSColin Finck 
381c2c66affSColin Finck         /* are we really supposed to do something */
382c2c66affSColin Finck         if (dwFlags & MOVE_NOTHING)
383c2c66affSColin Finck             continue;
384c2c66affSColin Finck 
385c2c66affSColin Finck         /*move the file*/
386c2c66affSColin Finck         if (!(dwMoveStatusFlags & MOVE_SOURCE_IS_DIR &&
387c2c66affSColin Finck             dwMoveStatusFlags & MOVE_PATHS_ON_DIF_VOL))
388c2c66affSColin Finck             /* we aren't moving source folder to different drive */
389c2c66affSColin Finck             MoveStatus = MoveFileEx (szSrcPath, szFullDestPath, dwMoveFlags);
390c2c66affSColin Finck         else
391c2c66affSColin Finck         {	/* we are moving source folder to different drive */
392c2c66affSColin Finck             _tcscpy(szMoveDest, szFullDestPath);
393c2c66affSColin Finck             _tcscpy(szMoveSrc, szSrcPath);
394c2c66affSColin Finck             DeleteFile(szMoveDest);
395c2c66affSColin Finck             MoveStatus = CreateDirectory(szMoveDest, NULL); /* we use default security settings */
396c2c66affSColin Finck             if (MoveStatus)
397c2c66affSColin Finck             {
398c2c66affSColin Finck                 _tcscat(szMoveDest,_T("\\"));
399c2c66affSColin Finck                 _tcscat(szMoveSrc,_T("\\"));
400c2c66affSColin Finck                 nDirLevel = 0;
401c2c66affSColin Finck                 pszDestDirPointer = szMoveDest + _tcslen(szMoveDest);
402c2c66affSColin Finck                 pszSrcDirPointer = szMoveSrc + _tcslen(szMoveSrc);
403c2c66affSColin Finck                 _tcscpy(pszSrcDirPointer,_T("*.*"));
404c2c66affSColin Finck                 hDestFile = FindFirstFile(szMoveSrc, &findDestBuffer);
405c2c66affSColin Finck                 if (hDestFile == INVALID_HANDLE_VALUE)
406c2c66affSColin Finck                     MoveStatus = FALSE;
407c2c66affSColin Finck                 else
408c2c66affSColin Finck                 {
409c2c66affSColin Finck                     BOOL FirstTime = TRUE;
410c2c66affSColin Finck                     FoundFile = TRUE;
411c2c66affSColin Finck                     MoveStatus = FALSE;
412c2c66affSColin Finck                     while(FoundFile)
413c2c66affSColin Finck                     {
414c2c66affSColin Finck                         if (FirstTime)
415c2c66affSColin Finck                             FirstTime = FALSE;
416c2c66affSColin Finck                         else
417c2c66affSColin Finck                             FoundFile = FindNextFile (hDestFile, &findDestBuffer);
418c2c66affSColin Finck 
419c2c66affSColin Finck                         if (!FoundFile)
420c2c66affSColin Finck                         {
421c2c66affSColin Finck                             /* Nothing to do in this folder so we stop working on it */
422c2c66affSColin Finck                             FindClose(hDestFile);
423c2c66affSColin Finck                             (pszSrcDirPointer)--;
424c2c66affSColin Finck                             (pszDestDirPointer)--;
425c2c66affSColin Finck                             _tcscpy(pszSrcDirPointer,_T(""));
426c2c66affSColin Finck                             _tcscpy(pszDestDirPointer,_T(""));
427c2c66affSColin Finck                             if (nDirLevel > 0)
428c2c66affSColin Finck                             {
429c2c66affSColin Finck                                 TCHAR szTempPath[MAX_PATH];
430c2c66affSColin Finck                                 INT_PTR nDiff;
431c2c66affSColin Finck 
432c2c66affSColin Finck                                 FoundFile = TRUE; /* we need to continue our seek for files */
433c2c66affSColin Finck                                 nDirLevel--;
434c2c66affSColin Finck                                 RemoveDirectory(szMoveSrc);
435c2c66affSColin Finck                                 GetDirectory(szMoveSrc,szTempPath,0);
436c2c66affSColin Finck                                 nDiff = _tcslen(szMoveSrc) - _tcslen(szTempPath);
437c2c66affSColin Finck                                 pszSrcDirPointer = pszSrcDirPointer - nDiff;
438c2c66affSColin Finck                                 _tcscpy(pszSrcDirPointer,_T(""));
439c2c66affSColin Finck                                 GetDirectory(szMoveDest,szTempPath,0);
440c2c66affSColin Finck                                 nDiff = _tcslen(szMoveDest) - _tcslen(szTempPath);
441c2c66affSColin Finck                                 pszDestDirPointer = pszDestDirPointer - nDiff;
442c2c66affSColin Finck                                 _tcscpy(pszDestDirPointer,_T(""));
443c2c66affSColin Finck                                 if (szMoveSrc[_tcslen(szMoveSrc) -  1] != _T('\\'))
444c2c66affSColin Finck                                     _tcscat (szMoveSrc, _T("\\"));
445c2c66affSColin Finck                                 if (szMoveDest[_tcslen(szMoveDest) -  1] != _T('\\'))
446c2c66affSColin Finck                                     _tcscat (szMoveDest, _T("\\"));
447c2c66affSColin Finck                                 pszDestDirPointer = szMoveDest + _tcslen(szMoveDest);
448c2c66affSColin Finck                                 pszSrcDirPointer = szMoveSrc + _tcslen(szMoveSrc);
449c2c66affSColin Finck                                 _tcscpy(pszSrcDirPointer,_T("*.*"));
450c2c66affSColin Finck                                 hDestFile = FindFirstFile(szMoveSrc, &findDestBuffer);
451c2c66affSColin Finck                                 if (hDestFile == INVALID_HANDLE_VALUE)
452c2c66affSColin Finck                                     continue;
453c2c66affSColin Finck                                 FirstTime = TRUE;
454c2c66affSColin Finck                             }
455c2c66affSColin Finck                             else
456c2c66affSColin Finck                             {
457c2c66affSColin Finck                                 MoveStatus = TRUE; /* we moved everything so lets tell user about it */
458c2c66affSColin Finck                                 RemoveDirectory(szMoveSrc);
459c2c66affSColin Finck                             }
460c2c66affSColin Finck                             continue;
461c2c66affSColin Finck                         }
462c2c66affSColin Finck 
463c2c66affSColin Finck                         /* if we find "." or ".." we'll skip them */
464c2c66affSColin Finck                         if (_tcscmp(findDestBuffer.cFileName,_T(".")) == 0 ||
465c2c66affSColin Finck                             _tcscmp(findDestBuffer.cFileName,_T("..")) == 0)
466c2c66affSColin Finck                             continue;
467c2c66affSColin Finck 
468c2c66affSColin Finck                         _tcscpy(pszSrcDirPointer, findDestBuffer.cFileName);
469c2c66affSColin Finck                         _tcscpy(pszDestDirPointer, findDestBuffer.cFileName);
470c2c66affSColin Finck                         if (IsExistingFile(szMoveSrc))
471c2c66affSColin Finck                         {
472c2c66affSColin Finck                             FoundFile = CopyFile(szMoveSrc, szMoveDest, FALSE);
473c2c66affSColin Finck                             if (!FoundFile) continue;
474c2c66affSColin Finck                             DeleteFile(szMoveSrc);
475c2c66affSColin Finck                         }
476c2c66affSColin Finck                         else
477c2c66affSColin Finck                         {
478c2c66affSColin Finck                             FindClose(hDestFile);
479c2c66affSColin Finck                             CreateDirectory(szMoveDest, NULL);
480c2c66affSColin Finck                             _tcscat(szMoveDest,_T("\\"));
481c2c66affSColin Finck                             _tcscat(szMoveSrc,_T("\\"));
482c2c66affSColin Finck                             nDirLevel++;
483c2c66affSColin Finck                             pszDestDirPointer = szMoveDest + _tcslen(szMoveDest);
484c2c66affSColin Finck                             pszSrcDirPointer = szMoveSrc + _tcslen(szMoveSrc);
485c2c66affSColin Finck                             _tcscpy(pszSrcDirPointer,_T("*.*"));
486c2c66affSColin Finck                             hDestFile = FindFirstFile(szMoveSrc, &findDestBuffer);
487c2c66affSColin Finck                             if (hDestFile == INVALID_HANDLE_VALUE)
488c2c66affSColin Finck                             {
489c2c66affSColin Finck                                 FoundFile = FALSE;
490c2c66affSColin Finck                                 continue;
491c2c66affSColin Finck                             }
492c2c66affSColin Finck                             FirstTime = TRUE;
493c2c66affSColin Finck                         }
494c2c66affSColin Finck                     }
495c2c66affSColin Finck                 }
496c2c66affSColin Finck             }
497c2c66affSColin Finck         }
498*3b960a1cSHermès Bélusca-Maïto 
499c2c66affSColin Finck         if (MoveStatus)
500*3b960a1cSHermès Bélusca-Maïto         {
501c2c66affSColin Finck             ConOutResPrintf(STRING_MOVE_ERROR1);
502*3b960a1cSHermès Bélusca-Maïto         }
503c2c66affSColin Finck         else
504*3b960a1cSHermès Bélusca-Maïto         {
505c2c66affSColin Finck             ConOutResPrintf(STRING_MOVE_ERROR2);
506*3b960a1cSHermès Bélusca-Maïto             nErrorLevel = 1;
507*3b960a1cSHermès Bélusca-Maïto         }
508c2c66affSColin Finck     }
509c2c66affSColin Finck     while ((!OnlyOneFile || dwMoveStatusFlags & MOVE_SRC_CURRENT_IS_DIR ) &&
510c2c66affSColin Finck             !(dwMoveStatusFlags & MOVE_SOURCE_IS_DIR) &&
511c2c66affSColin Finck             FindNextFile (hFile, &findBuffer));
512c2c66affSColin Finck     FindClose (hFile);
513c2c66affSColin Finck 
514c2c66affSColin Finck     if(hDestFile && hDestFile != INVALID_HANDLE_VALUE)
515c2c66affSColin Finck         FindClose(hDestFile);
516c2c66affSColin Finck 
517*3b960a1cSHermès Bélusca-Maïto Quit:
518c2c66affSColin Finck     freep(arg);
519*3b960a1cSHermès Bélusca-Maïto     return nErrorLevel;
520c2c66affSColin Finck }
521c2c66affSColin Finck 
522c2c66affSColin Finck #endif /* INCLUDE_CMD_MOVE */
523