ReactOS  0.4.15-dev-5137-g826bd41
copy.c
Go to the documentation of this file.
1 /*
2  * COPY.C -- copy internal command.
3  *
4  *
5  * History:
6  *
7  * 01-Aug-98 (Rob Lake z63rrl@morgan.ucs.mun.ca)
8  * started
9  *
10  * 13-Aug-1998 (John P. Price)
11  * fixed memory leak problem in copy function.
12  * fixed copy function so it would work with wildcards in the source
13  *
14  * 13-Dec-1998 (Eric Kohl)
15  * Added COPY command to CMD.
16  *
17  * 26-Jan-1998 (Eric Kohl)
18  * Replaced CRT io functions by Win32 io functions.
19  *
20  * 27-Oct-1998 (Eric Kohl)
21  * Disabled prompting when used in batch mode.
22  *
23  * 03-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
24  * Remove all hardcode string to En.rc
25  *
26  * 13-Jul-2005 (Brandon Turner <turnerb7@msu.edu>)
27  * Rewrite to clean up copy and support wildcard.
28  *
29  * 20-Jul-2005 (Brandon Turner <turnerb7@msu.edu>)
30  * Add touch syntax. "copy arp.exe+,,"
31  * Copy command is now completed.
32  */
33 
34 #include "precomp.h"
35 
36 #ifdef INCLUDE_CMD_COPY
37 
38 enum
39 {
40  COPY_ASCII = 0x001, /* /A */
41  COPY_DECRYPT = 0x004, /* /D */
42  COPY_VERIFY = 0x008, /* /V : Dummy, Never will be Implemented */
43  COPY_SHORTNAME = 0x010, /* /N : Dummy, Never will be Implemented */
44  COPY_NO_PROMPT = 0x020, /* /Y */
45  COPY_PROMPT = 0x040, /* /-Y */
46  COPY_RESTART = 0x080, /* /Z */
47  COPY_BINARY = 0x100, /* /B */
48 };
49 
50 INT
53  INT append,
54  DWORD lpdwFlags,
55  BOOL bTouch)
56 {
57  FILETIME srctime,NewFileTime;
58  HANDLE hFileSrc;
59  HANDLE hFileDest;
60  LPBYTE buffer;
61  DWORD dwAttrib;
62  DWORD dwRead;
63  DWORD dwWritten;
64  BOOL bEof = FALSE;
65  TCHAR TrueDest[MAX_PATH];
66  TCHAR TempSrc[MAX_PATH];
67  TCHAR * FileName;
68  SYSTEMTIME CurrentTime;
69 
70  /* Check Breaker */
72  return 0;
73 
74  TRACE ("checking mode\n");
75 
76  if (bTouch)
77  {
79  NULL, OPEN_EXISTING, 0, NULL);
80  if (hFileSrc == INVALID_HANDLE_VALUE)
81  {
83  nErrorLevel = 1;
84  return 0;
85  }
86 
87  GetSystemTime(&CurrentTime);
88  SystemTimeToFileTime(&CurrentTime, &NewFileTime);
89  if (SetFileTime(hFileSrc,(LPFILETIME) NULL, (LPFILETIME) NULL, &NewFileTime))
90  {
91  CloseHandle(hFileSrc);
92  nErrorLevel = 1;
93  return 1;
94 
95  }
96  else
97  {
98  CloseHandle(hFileSrc);
99  return 0;
100  }
101  }
102 
103  dwAttrib = GetFileAttributes (source);
104 
106  NULL, OPEN_EXISTING, 0, NULL);
107  if (hFileSrc == INVALID_HANDLE_VALUE)
108  {
110  nErrorLevel = 1;
111  return 0;
112  }
113 
114  TRACE ("getting time\n");
115 
116  GetFileTime (hFileSrc, &srctime, NULL, NULL);
117 
118  TRACE ("copy: flags has %s\n",
119  lpdwFlags & COPY_ASCII ? "ASCII" : "BINARY");
120 
121  /* Check to see if /D or /Z are true, if so we need a middle
122  man to copy the file too to allow us to use CopyFileEx later */
123  if (lpdwFlags & COPY_DECRYPT)
124  {
125  GetEnvironmentVariable(_T("TEMP"),TempSrc,MAX_PATH);
126  _tcscat(TempSrc,_T("\\"));
127  FileName = _tcsrchr(source,_T('\\'));
128  FileName++;
129  _tcscat(TempSrc,FileName);
130  /* This is needed to be on the end to prevent an error
131  if the user did "copy /D /Z foo bar then it would be copied
132  too %TEMP%\foo here and when %TEMP%\foo when it sets it up
133  for COPY_RESTART, this would mean it is copying to itself
134  which would error when it tried to open the handles for ReadFile
135  and WriteFile */
136  _tcscat(TempSrc,_T(".decrypt"));
138  {
139  CloseHandle (hFileSrc);
140  nErrorLevel = 1;
141  return 0;
142  }
143  _tcscpy(source, TempSrc);
144  }
145 
146 
147  if (lpdwFlags & COPY_RESTART)
148  {
149  _tcscpy(TrueDest, dest);
151  _tcscat(dest,_T("\\"));
152  FileName = _tcsrchr(TrueDest,_T('\\'));
153  FileName++;
155  }
156 
157 
158  if (!IsExistingFile (dest))
159  {
160  TRACE ("opening/creating\n");
161  hFileDest =
163  }
164  else if (!append)
165  {
166  TRACE ("SetFileAttributes (%s, FILE_ATTRIBUTE_NORMAL);\n", debugstr_aw(dest));
168 
169  TRACE ("DeleteFile (%s);\n", debugstr_aw(dest));
170  DeleteFile (dest);
171 
172  hFileDest = CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
173  }
174  else
175  {
176  LONG lFilePosHigh = 0;
177 
178  if (!_tcscmp (dest, source))
179  {
180  CloseHandle (hFileSrc);
181  return 0;
182  }
183 
184  TRACE ("opening/appending\n");
186 
187  hFileDest =
189 
190  /* Move to end of file to start writing */
191  SetFilePointer (hFileDest, 0, &lFilePosHigh,FILE_END);
192  }
193 
194 
195  if (hFileDest == INVALID_HANDLE_VALUE)
196  {
197  CloseHandle (hFileSrc);
199  nErrorLevel = 1;
200  return 0;
201  }
202 
203  /* A page-aligned buffer usually give more speed */
205  if (buffer == NULL)
206  {
207  CloseHandle (hFileDest);
208  CloseHandle (hFileSrc);
210  nErrorLevel = 1;
211  return 0;
212  }
213 
214  do
215  {
216  ReadFile (hFileSrc, buffer, BUFF_SIZE, &dwRead, NULL);
217  if (lpdwFlags & COPY_ASCII)
218  {
219  LPBYTE pEof = memchr(buffer, 0x1A, dwRead);
220  if (pEof != NULL)
221  {
222  bEof = TRUE;
223  dwRead = pEof-buffer+1;
224  break;
225  }
226  }
227 
228  if (dwRead == 0)
229  break;
230 
231  WriteFile (hFileDest, buffer, dwRead, &dwWritten, NULL);
232  if (dwWritten != dwRead || CheckCtrlBreak(BREAK_INPUT))
233  {
235 
237  CloseHandle (hFileDest);
238  CloseHandle (hFileSrc);
239  nErrorLevel = 1;
240  return 0;
241  }
242  }
243  while (!bEof);
244 
245  TRACE ("setting time\n");
246  SetFileTime (hFileDest, &srctime, NULL, NULL);
247 
248  if ((lpdwFlags & COPY_ASCII) && !bEof)
249  {
250  /* we're dealing with ASCII files! */
251  buffer[0] = 0x1A;
252  TRACE ("appending ^Z\n");
253  WriteFile (hFileDest, buffer, sizeof(CHAR), &dwWritten, NULL);
254  }
255 
257  CloseHandle (hFileDest);
258  CloseHandle (hFileSrc);
259 
260  TRACE ("setting mode\n");
261  /* For MS-DOS backwards-compatibility, always remove the read-only attribute */
263 
264  /* Now finish off the copy if needed with CopyFileEx */
265  if (lpdwFlags & COPY_RESTART)
266  {
267  if (!CopyFileEx(dest, TrueDest, NULL, NULL, FALSE, COPY_FILE_RESTARTABLE))
268  {
269  nErrorLevel = 1;
270  DeleteFile(dest);
271  return 0;
272  }
273  /* Take care of file in the temp folder */
274  DeleteFile(dest);
275 
276  }
277 
278  if (lpdwFlags & COPY_DECRYPT)
279  DeleteFile(TempSrc);
280 
281  return 1;
282 }
283 
284 
286 {
287  /*ask the user if they want to override*/
288  INT res;
290  res = FilePromptYNA (0);
291  return res;
292 }
293 
294 /* The following lines of copy were written by someone else
295 (most likely Eric Kohl) and it was taken from ren.c */
296 static void
298  LPTSTR pszSource,
299  LPTSTR pszTarget,
300  LPTSTR pszOutput)
301 {
302  /* build destination file name */
303  while (*pszTarget != 0)
304  {
305  if (*pszTarget == _T('*'))
306  {
307  pszTarget++;
308  while ((*pszSource != 0) && (*pszSource != *pszTarget))
309  {
310  *pszOutput++ = *pszSource++;
311  }
312  }
313  else if (*pszTarget == _T('?'))
314  {
315  pszTarget++;
316  if (*pszSource != 0)
317  {
318  *pszOutput++ = *pszSource++;
319  }
320  }
321  else
322  {
323  *pszOutput++ = *pszTarget++;
324  if (*pszSource != 0)
325  pszSource++;
326  }
327  }
328 
329  *pszOutput = 0;
330 }
331 
333 {
334  LPTSTR *arg;
335  INT argc, i, nFiles, nOverwrite = 0, nSrc = -1, nDes = -1;
336  /* this is the path up to the folder of the src and dest ie C:\windows\ */
337  TCHAR szDestPath[MAX_PATH];
338  TCHAR szSrcPath[MAX_PATH];
339  DWORD dwFlags = 0;
340  /* If this is the type of copy where we are adding files */
341  BOOL bAppend = FALSE;
342  WIN32_FIND_DATA findBuffer;
343  HANDLE hFile = NULL;
344  BOOL bTouch = FALSE;
345  /* Pointer to keep track of how far through the append input(file1+file2+file3) we are */
346  TCHAR * appendPointer = _T("\0");
347  /* The full path to src and dest. This has drive letter, folders, and filename */
348  TCHAR tmpDestPath[MAX_PATH];
349  TCHAR tmpSrcPath[MAX_PATH];
350  /* A bool to know whether or not the destination name will be taken from the input */
351  BOOL bSrcName = FALSE;
352  /* Seems like a waste but it is a pointer used to copy from input to PreserveName */
353  TCHAR * UseThisName;
354  /* for CMDCOPY env */
355  TCHAR *evar;
356  int size;
357  TCHAR * szTouch;
358  BOOL bHasWildcard, bDone = FALSE, bMoreFiles = FALSE;
359  /* Used for something like "copy c*.exe d*.exe" */
360  BOOL bMultipleSource = FALSE, bMultipleDest = FALSE;
361 
362 
363  /* Show help/usage info */
364  if (!_tcsncmp(param, _T("/?"), 2))
365  {
367  return 0;
368  }
369 
370  nErrorLevel = 0;
371 
372  /* Get the env variable value if it exists */
373  evar = cmd_alloc(512 * sizeof(TCHAR));
374  if (evar == NULL)
375  size = 0;
376  else
377  size = GetEnvironmentVariable (_T("COPYCMD"), evar, 512);
378 
379  if (size > 512)
380  {
381  TCHAR *old_evar = evar;
382  evar = cmd_realloc(evar,size * sizeof(TCHAR) );
383  if (evar!=NULL)
384  size = GetEnvironmentVariable (_T("COPYCMD"), evar, size);
385  else
386  {
387  size=0;
388  evar = old_evar;
389  }
390  }
391 
392  /* check see if we did get any env variable */
393  if (size != 0)
394  {
395  int t = 0;
396 
397  /* scan and set the flags */
398  for (t = 0; t < size; t++)
399  {
400  if (_tcsncicmp(_T("/A"),&evar[t],2) == 0)
401  {
403  t++;
404  }
405  else if (_tcsncicmp(_T("/B"),&evar[t],2) == 0)
406  {
407  dwFlags |= COPY_BINARY;
408  t++;
409  }
410  else if (_tcsncicmp(_T("/D"),&evar[t],2) == 0)
411  {
413  t++;
414  }
415  else if (_tcsncicmp(_T("/V"),&evar[t],2) == 0)
416  {
417  dwFlags |= COPY_VERIFY;
418  t++;
419  }
420  else if (_tcsncicmp(_T("/N"),&evar[t],2) == 0)
421  {
423  t++;
424  }
425  else if (_tcsncicmp(_T("/Y"),&evar[t],2) == 0)
426  {
428  t++;
429  }
430  else if (_tcsncicmp(_T("/-Y"),&evar[t],3) == 0)
431  {
432  dwFlags |= COPY_PROMPT;
433  t+=2;
434  }
435  else if (_tcsncicmp(_T("/Z"),&evar[t],2) == 0)
436  {
437  dwFlags |= COPY_PROMPT;
438  t++;
439  }
440  }
441  }
442  cmd_free(evar);
443 
444 
445  /* Split the user input into array */
446  arg = split(param, &argc, FALSE, TRUE);
447  nFiles = argc;
448 
449  /* Read switches and count files */
450  for (i = 0; i < argc; i++)
451  {
452  if (*arg[i] == _T('/'))
453  {
454  if (_tcslen(arg[i]) >= 2)
455  {
456  switch (_totupper(arg[i][1]))
457  {
458  case _T('A'):
459  dwFlags |= COPY_ASCII;
460  break;
461 
462  case _T('B'):
463  dwFlags |= COPY_BINARY;
464  break;
465 
466  case _T('D'):
468  break;
469 
470  case _T('V'):
471  dwFlags |= COPY_VERIFY;
472  break;
473 
474  case _T('N'):
476  break;
477 
478  case _T('Y'):
480  dwFlags &= ~COPY_PROMPT;
481  break;
482 
483  case _T('-'):
484  if (_tcslen(arg[i]) >= 3)
485  {
486  if (_totupper(arg[i][2]) == _T('Y'))
487  {
489  dwFlags |= COPY_PROMPT;
490  }
491  }
492 
493  break;
494 
495  case _T('Z'):
497  break;
498 
499  default:
500  /* Invalid switch */
502  nErrorLevel = 1;
503  freep (arg);
504  return 1;
505  break;
506  }
507  }
508  /* If it was a switch, subtract from total arguments */
509  nFiles--;
510  }
511  else
512  {
513  /* If it isn't a switch then it is the source or destination */
514  if (nSrc == -1)
515  {
516  nSrc = i;
517  }
518  else if (*arg[i] == _T('+'))
519  {
520  /* Next file should be appended */
521  bMoreFiles = TRUE;
522  nFiles -= 1;
523  }
524  else if (bMoreFiles)
525  {
526  /* Add this file to the source string
527  this way we can do all checks
528  directly on source string later on */
529  TCHAR * ptr;
530  int length = (_tcslen(arg[nSrc]) + _tcslen(arg[i]) + 2) * sizeof(TCHAR);
531  ptr = cmd_alloc(length);
532  if (ptr)
533  {
534  _tcscpy(ptr, arg[nSrc]);
535  _tcscat(ptr, _T("|"));
536  _tcscat(ptr, arg[i]);
537  cmd_free(arg[nSrc]);
538  arg[nSrc] = ptr;
539  nFiles -= 1;
540  }
541 
542  bMoreFiles = FALSE;
543  }
544  else if (nDes == -1)
545  {
546  nDes = i;
547  }
548  }
549  }
550 
551  /* keep quiet within batch files */
552  if (bc != NULL)
553  {
555  dwFlags &= ~COPY_PROMPT;
556  }
557 
558  if (nFiles < 1)
559  {
560  /* There are not enough files, there has to be at least 1 */
562  freep(arg);
563  return 1;
564  }
565 
566  if (nFiles > 2)
567  {
568  /* There are too many file names in command */
570  nErrorLevel = 1;
571  freep(arg);
572  return 1;
573  }
574 
575  if ((_tcschr(arg[nSrc], _T('|')) != NULL) ||
576  (_tcschr(arg[nSrc], _T('*')) != NULL) ||
577  (_tcschr(arg[nSrc], _T('?')) != NULL) ||
578  IsExistingDirectory(arg[nSrc]))
579  {
580  bMultipleSource = TRUE;
581  }
582 
583  /* Reuse the number of files variable */
584  nFiles = 0;
585 
586  /* Check if no destination argument is passed */
587  if (nDes == -1)
588  {
589  /* If no destination was entered then just use
590  the current directory as the destination */
591  GetCurrentDirectory(ARRAYSIZE(szDestPath), szDestPath);
592  }
593  else
594  {
595  /* Check if the destination is 'x:' */
596  if ((arg[nDes][1] == _T(':')) && (arg[nDes][2] == _T('\0')))
597  {
598  GetRootPath(arg[nDes], szDestPath, ARRAYSIZE(szDestPath));
599  }
600  else
601  {
602  /* If the user entered two file names then form the full string path */
603  GetFullPathName(arg[nDes], ARRAYSIZE(szDestPath), szDestPath, NULL);
604  }
605 
606  /* Make sure there is an ending slash to the path if the dest is a folder */
607  if ((_tcschr(szDestPath, _T('*')) == NULL) &&
608  IsExistingDirectory(szDestPath))
609  {
610  bMultipleDest = TRUE;
611  if (szDestPath[_tcslen(szDestPath) - 1] != _T('\\'))
612  _tcscat(szDestPath, _T("\\"));
613  }
614 
615  /* Check if the destination uses wildcards */
616  if ((_tcschr(arg[nDes], _T('*')) != NULL) ||
617  (_tcschr(arg[nDes], _T('?')) != NULL))
618  {
619  bMultipleDest = TRUE;
620  }
621  }
622 
623  if (nDes != -1) /* Append files only when there is a destination */
624  {
625  if (bMultipleSource && !bMultipleDest)
626  {
627  /* We have multiple source files, but not multiple destination
628  files. This means we are appending the source files. */
629  bAppend = TRUE;
630  if (_tcschr(arg[nSrc], _T('|')) != NULL)
631  appendPointer = arg[nSrc];
632  }
633  }
634 
635  /* Save the name the user entered */
636  UseThisName = _tcsrchr(szDestPath,_T('\\'));
637  if (UseThisName)
638  {
639  /* Split the name from the path */
640  *UseThisName++ = _T('\0');
641 
642  /* Check if the dest path ends with '\*' or '\' */
643  if (((UseThisName[0] == _T('*')) && (UseThisName[1] == _T('\0'))) ||
644  (UseThisName[0] == _T('\0')))
645  {
646  /* In this case we will be using the same name as the source file
647  for the destination file because destination is a folder */
648  bSrcName = TRUE;
649  UseThisName = NULL;
650  }
651  }
652  else
653  {
654  /* Something's seriously wrong! */
655  UseThisName = szDestPath;
656  }
657 
658  do
659  {
660  /* Get the full string of the path to the source file */
661  if (_tcschr(arg[nSrc], _T('|')) != NULL)
662  {
663  /* Reset the source path */
664  szSrcPath[0] = _T('\0');
665 
666  /* Loop through the source file name and copy all
667  the chars one at a time until we reach the separator */
668  while(TRUE)
669  {
670  if (appendPointer[0] == _T('|'))
671  {
672  /* Skip the | and go to the next file name */
673  appendPointer++;
674  break;
675  }
676  else if (appendPointer[0] == _T('\0'))
677  {
678  bDone = TRUE;
679  break;
680  }
681 
682  _tcsncat(szSrcPath, appendPointer, 1);
683  appendPointer++;
684  }
685 
686  if (_tcschr(arg[nSrc], _T(',')) != NULL)
687  {
688  /* Only time there is a , in the source is when they are using touch
689  Cant have a destination and can only have on ,, at the end of the string
690  Cant have more than one file name */
691  szTouch = _tcsstr(arg[nSrc], _T("|"));
692  if (_tcsncmp(szTouch,_T("|,,\0"), 4) || (nDes != -1))
693  {
695  nErrorLevel = 1;
696  freep (arg);
697  return 1;
698  }
699  bTouch = TRUE;
700  bDone = TRUE;
701  }
702  }
703  else
704  {
705  bDone = TRUE;
706  _tcscpy(szSrcPath, arg[nSrc]);
707  }
708 
709  /* "x:" is not a valid source path format. */
710  if ((szSrcPath[1] == _T(':')) && (szSrcPath[2] == _T('\0')))
711  {
712  ConOutPrintf(_T("%s\n"), szSrcPath);
714  nErrorLevel = 1;
715  break;
716  }
717 
718 
719  /* From this point on, we can assume that the shortest path is
720  3 letters long and that would be [DriveLetter]:\ */
721 
722  /* Check if the path has a wildcard */
723  bHasWildcard = (_tcschr(szSrcPath, _T('*')) != NULL);
724 
725  /* If there is no * in the path name and it is a folder then we will
726  need to add a wildcard to the pathname so FindFirstFile comes up
727  with all the files in that folder */
728  if (!bHasWildcard && IsExistingDirectory(szSrcPath))
729  {
730  /* If it doesnt have a \ at the end already then on needs to be added */
731  if (szSrcPath[_tcslen(szSrcPath) - 1] != _T('\\'))
732  _tcscat(szSrcPath, _T("\\"));
733  _tcscat(szSrcPath, _T("*"));
734  bHasWildcard = TRUE;
735  }
736 
737  /* If the path ends with '\' add a wildcard at the end */
738  if (szSrcPath[_tcslen(szSrcPath) - 1] == _T('\\'))
739  {
740  _tcscat(szSrcPath, _T("*"));
741  bHasWildcard = TRUE;
742  }
743 
744  /* Get a list of all the files */
745  hFile = FindFirstFile(szSrcPath, &findBuffer);
746 
747  /* If we could not open the file handle, print out the error */
749  {
750  /* only print source name when more than one file */
751  if (bMultipleSource)
752  ConOutPrintf(_T("%s\n"), szSrcPath);
753 
754  ConOutFormatMessage(GetLastError(), szSrcPath);
755  freep(arg);
756  nErrorLevel = 1;
757  return 1;
758  }
759 
760  /* Strip the paths back to the folder they are in */
761  for (i = (_tcslen(szSrcPath) - 1); i > -1; i--)
762  {
763  if (szSrcPath[i] != _T('\\'))
764  szSrcPath[i] = _T('\0');
765  else
766  break;
767  }
768 
769  do
770  {
771  /* Check Breaker */
773  {
774  FindClose(hFile);
775  freep(arg);
776  return 1;
777  }
778 
779  /* Set the override to yes each new file */
780  nOverwrite = 1;
781 
782  /* Ignore the . and .. files */
783  if (!_tcscmp(findBuffer.cFileName, _T(".")) ||
784  !_tcscmp(findBuffer.cFileName, _T("..")) ||
785  findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
786  {
787  continue;
788  }
789 
790  /* Copy the base folder over to a tmp string */
791  _tcscpy(tmpDestPath, szDestPath);
792  _tcscat(tmpDestPath, _T("\\"));
793 
794  /* Can't put a file into a folder that isn't there */
795  if (_tcscmp(tmpDestPath, _T("\\\\.\\")) &&
796  !IsExistingDirectory(tmpDestPath))
797  {
798  FindClose(hFile);
799  ConOutFormatMessage(GetLastError(), szSrcPath);
800  freep(arg);
801  nErrorLevel = 1;
802  return 1;
803  }
804 
805  /* Copy over the destination path name */
806  if (bSrcName)
807  _tcscat(tmpDestPath, findBuffer.cFileName);
808  else
809  {
810  /* If there is no wildcard, use the name the user entered */
811  if ((_tcschr(UseThisName, _T('*')) == NULL) &&
812  (_tcschr(UseThisName, _T('?')) == NULL))
813  {
814  _tcscat(tmpDestPath, UseThisName);
815  }
816  else
817  {
818  TCHAR DoneFile[MAX_PATH];
819 
820  BuildFileName(findBuffer.cFileName,
821  UseThisName,
822  DoneFile);
823 
824 
825  /* Add the filename to the tmp string path */
826  _tcscat(tmpDestPath, DoneFile);
827  }
828  }
829 
830  /* Build the string path to the source file */
831  _tcscpy(tmpSrcPath,szSrcPath);
832  _tcscat (tmpSrcPath, findBuffer.cFileName);
833 
834  /* Check to see if the file is the same file */
835  if (!bTouch && !_tcscmp(tmpSrcPath, tmpDestPath))
836  {
838 
839  nErrorLevel = 1;
840  break;
841  }
842 
843  /* only print source name when more than one file */
844  if (bMultipleSource)
845  ConOutPrintf(_T("%s\n"), tmpSrcPath);
846 
847  /* Handle any overriding / prompting that needs to be done */
848  if (((!(dwFlags & COPY_NO_PROMPT) && IsExistingFile (tmpDestPath)) || dwFlags & COPY_PROMPT) && !bTouch)
849  nOverwrite = CopyOverwrite(tmpDestPath);
850  if (nOverwrite == PROMPT_NO || nOverwrite == PROMPT_BREAK)
851  continue;
852  if (nOverwrite == PROMPT_ALL || (nOverwrite == PROMPT_YES && bAppend))
854 
855  /* Tell whether the copy was successful or not */
856  if (copy(tmpSrcPath,tmpDestPath, bAppend, dwFlags, bTouch))
857  {
858  nFiles++;
859  }
860  else
861  {
862  /* print out the error message */
864  ConOutFormatMessage (GetLastError(), szSrcPath);
865  nErrorLevel = 1;
866  }
867 
868  /* Loop through all wildcard files */
869  } while (FindNextFile(hFile, &findBuffer));
870 
871  FindClose(hFile);
872 
873  /* Loop through all files in src string with a + */
874  } while (!bDone);
875 
876  /* print out the number of files copied */
877  ConOutResPrintf(STRING_COPY_FILE, bAppend ? 1 : nFiles);
878 
879  if (arg != NULL)
880  freep(arg);
881 
882  return 0;
883 }
884 
885 #endif /* INCLUDE_CMD_COPY */
INT nErrorLevel
Definition: cmd.c:158
#define STRING_COPY_ERROR2
Definition: resource.h:36
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
#define ConOutFormatMessage(MessageId,...)
Definition: console.h:54
static int argc
Definition: ServiceArgs.c:12
BOOL CheckCtrlBreak(INT)
Definition: misc.c:132
#define CloseHandle
Definition: compat.h:598
#define BREAK_INPUT
Definition: cmd.h:36
#define memchr(s, c, n)
Definition: mkisofs.h:875
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
int _tcscmp(const _TCHAR *s1, const _TCHAR *s2)
Definition: tcscmp.h:8
#define TRUE
Definition: types.h:120
char CHAR
Definition: xmlstorage.h:175
#define debugstr_aw
Definition: precomp.h:43
BOOL IsExistingFile(IN LPCTSTR pszPath)
Definition: misc.c:498
GLdouble GLdouble t
Definition: gl.h:2047
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
_TCHAR * _tcscpy(_TCHAR *to, const _TCHAR *from)
Definition: tcscpy.h:8
#define PROMPT_BREAK
Definition: cmd.h:333
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
GLuint buffer
Definition: glext.h:5915
#define STRING_ERROR_REQ_PARAM_MISSING
Definition: resource.h:10
#define ConOutPrintf(szStr,...)
Definition: console.h:42
void * arg
Definition: msvc.h:10
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
#define PROMPT_NO
Definition: cmd.h:330
#define _totupper
Definition: tchar.h:1509
static void append(struct dump_context *dc, const void *data, unsigned size)
Definition: minidump.c:397
#define DeleteFile
Definition: winbase.h:3625
#define MEM_COMMIT
Definition: nt_native.h:1313
#define COPY_FILE_RESTARTABLE
Definition: winbase.h:206
#define PROMPT_ALL
Definition: cmd.h:332
#define CopyFileEx
Definition: winbase.h:3603
int32_t INT
Definition: typedefs.h:58
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define FILE_SHARE_READ
Definition: compat.h:136
BOOL WINAPI SetFileTime(IN HANDLE hFile, CONST FILETIME *lpCreationTime OPTIONAL, CONST FILETIME *lpLastAccessTime OPTIONAL, CONST FILETIME *lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:948
LPVOID NTAPI VirtualAlloc(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
Definition: virtmem.c:74
unsigned char * LPBYTE
Definition: typedefs.h:53
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define _tcsncicmp
Definition: tchar.h:1429
long LONG
Definition: pedump.c:60
#define ConErrResPrintf(uID,...)
Definition: console.h:51
#define GENERIC_WRITE
Definition: nt_native.h:90
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static PVOID ptr
Definition: dispmode.c:27
#define GetCurrentDirectory
Definition: winbase.h:3666
#define STRING_ERROR_INVALID_PARAM_FORMAT
Definition: resource.h:5
static INT CopyOverwrite(LPTSTR fn)
Definition: copy.c:285
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
#define STRING_COPY_FILE
Definition: resource.h:208
static VOID freep(LPSTR *p)
Definition: cmdcons.c:98
#define FindFirstFile
Definition: winbase.h:3643
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
_TCHAR * _tcschr(const _TCHAR *s, _XINT c)
Definition: tcschr.h:4
#define OPEN_EXISTING
Definition: compat.h:634
#define STRING_ERROR_OUT_OF_MEMORY
Definition: resource.h:14
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define _tcsstr
Definition: xmlstorage.h:199
#define STRING_COPY_ERROR1
Definition: resource.h:35
INT FilePromptYNA(UINT)
Definition: misc.c:623
char TCHAR
Definition: xmlstorage.h:189
VOID WINAPI GetSystemTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:327
#define _T(x)
Definition: vfdio.h:22
_TCHAR * _tcsncat(_TCHAR *dst, const _TCHAR *src, size_t n)
Definition: tcsncat.h:5
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define FILE_END
Definition: winbase.h:114
#define SetFileAttributes
Definition: winbase.h:3770
#define FindNextFile
Definition: winbase.h:3649
GLfloat param
Definition: glext.h:5796
#define MAX_PATH
Definition: compat.h:34
static LPSTR * split(LPSTR s, LPINT args)
Definition: cmdcons.c:163
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define ConOutResPrintf(uID,...)
Definition: console.h:48
unsigned long DWORD
Definition: ntddk_ex.h:95
static void BuildFileName(LPTSTR pszSource, LPTSTR pszTarget, LPTSTR pszOutput)
Definition: copy.c:297
#define cmd_realloc(ptr, size)
Definition: cmddbg.h:30
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define GetFullPathName
Definition: winbase.h:3682
#define COPY_FILE_ALLOW_DECRYPTED_DESTINATION
Definition: winbase.h:204
#define STRING_ERROR_PATH_NOT_FOUND
Definition: resource.h:8
#define GENERIC_READ
Definition: compat.h:135
_In_ HANDLE hFile
Definition: mswsock.h:90
#define GetFileAttributes
Definition: winbase.h:3676
INT GetRootPath(IN LPCTSTR InPath, OUT LPTSTR OutPath, IN INT size)
Definition: internal.c:152
#define cmd_alloc(size)
Definition: cmddbg.h:29
#define PROMPT_YES
Definition: cmd.h:331
struct _FileName FileName
Definition: fatprocs.h:893
#define CREATE_ALWAYS
Definition: disk.h:72
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:158
#define cmd_free(ptr)
Definition: cmddbg.h:31
#define STRING_ERROR_INVALID_SWITCH
Definition: resource.h:6
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
IN OUT PVCB OUT PDIRENT OUT PBCB IN BOOLEAN CreateFile
Definition: fatprocs.h:913
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
#define ReadFile(a, b, c, d, e)
Definition: compat.h:601
#define NULL
Definition: types.h:112
#define STRING_COPY_HELP1
Definition: resource.h:93
#define STRING_ERROR_TOO_MANY_PARAMETERS
Definition: resource.h:7
#define ConOutResPuts(uID)
Definition: console.h:36
#define STRING_COPY_HELP2
Definition: resource.h:94
#define MEM_RELEASE
Definition: nt_native.h:1316
_TCHAR * _tcsrchr(const _TCHAR *s, _XINT c)
Definition: tcsrchr.h:4
_TCHAR * _tcscat(_TCHAR *s, const _TCHAR *append)
Definition: tcscat.h:8
GLuint res
Definition: glext.h:9613
INT cmd_copy(LPTSTR param)
Definition: copy.c:332
#define GetEnvironmentVariable
Definition: winbase.h:3675
PBATCH_CONTEXT bc
Definition: batch.c:67
static char * dest
Definition: rtl.c:135
BOOL NTAPI VirtualFree(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD dwFreeType)
Definition: virtmem.c:128
#define STRING_COPY_ERROR3
Definition: resource.h:37
BOOL WINAPI GetFileTime(IN HANDLE hFile, OUT LPFILETIME lpCreationTime OPTIONAL, OUT LPFILETIME lpLastAccessTime OPTIONAL, OUT LPFILETIME lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:896
int _tcsncmp(const _TCHAR *s1, const _TCHAR *s2, size_t n)
Definition: tcsncmp.h:9
#define SetFilePointer
Definition: compat.h:602
#define BUFF_SIZE
Definition: cmd.h:47
BOOL IsExistingDirectory(IN LPCTSTR pszPath)
Definition: misc.c:504
#define PAGE_READWRITE
Definition: nt_native.h:1304
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502