ReactOS 0.4.15-dev-7953-g1f49173
xcopy.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <wine/debug.h>
#include <wine/unicode.h>
#include "xcopy.h"
Include dependency graph for xcopy.c:

Go to the source code of this file.

Classes

struct  _EXCLUDELIST
 

Macros

#define MAX_WRITECONSOLE_SIZE   65535
 

Typedefs

typedef struct _EXCLUDELIST EXCLUDELIST
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (xcopy)
 
static WCHARXCOPY_LoadMessage (UINT id)
 
static int WINAPIV XCOPY_wprintf (const WCHAR *format,...)
 
static void XCOPY_FailMessage (DWORD err)
 
static BOOL XCOPY_CreateDirectory (const WCHAR *path)
 
static BOOL XCOPY_ProcessExcludeFile (WCHAR *filename, WCHAR *endOfName)
 
static BOOL XCOPY_ProcessExcludeList (WCHAR *parms)
 
static int XCOPY_DoCopy (WCHAR *srcstem, WCHAR *srcspec, WCHAR *deststem, WCHAR *destspec, DWORD flags)
 
static BOOL is_whitespace (WCHAR c)
 
static WCHARskip_whitespace (WCHAR *p)
 
static BOOL is_digit (WCHAR c)
 
static int find_end_of_word (const WCHAR *word, WCHAR **end)
 
static void strip_quotes (WCHAR *word, WCHAR **end)
 
static int XCOPY_ParseCommandLine (WCHAR *suppliedsource, WCHAR *supplieddestination, DWORD *pflags)
 
static int XCOPY_ProcessSourceParm (WCHAR *suppliedsource, WCHAR *stem, WCHAR *spec, DWORD flags)
 
static int XCOPY_ProcessDestParm (WCHAR *supplieddestination, WCHAR *stem, WCHAR *spec, WCHAR *srcspec, DWORD flags)
 
int wmain (int argc, WCHAR *argvW[])
 

Variables

static ULONG filesCopied = 0
 
static EXCLUDELISTexcludeList = NULL
 
static FILETIME dateRange
 
static const WCHAR wchr_slash [] = {'\\', 0}
 
static const WCHAR wchr_star [] = {'*', 0}
 
static const WCHAR wchr_dot [] = {'.', 0}
 
static const WCHAR wchr_dotdot [] = {'.', '.', 0}
 
static WCHAR copyFrom [MAX_PATH]
 
static WCHAR copyTo [MAX_PATH]
 

Macro Definition Documentation

◆ MAX_WRITECONSOLE_SIZE

#define MAX_WRITECONSOLE_SIZE   65535

Typedef Documentation

◆ EXCLUDELIST

Function Documentation

◆ find_end_of_word()

static int find_end_of_word ( const WCHAR word,
WCHAR **  end 
)
static

Definition at line 679 of file xcopy.c.

680{
681 BOOL in_quotes = FALSE;
682 const WCHAR *ptr = word;
683 for (;;) {
684 for (; *ptr != '\0' && *ptr != '"' &&
685 (in_quotes || !is_whitespace(*ptr)); ptr++);
686 if (*ptr == '"') {
687 in_quotes = !in_quotes;
688 ptr++;
689 }
690 /* Odd number of double quotes is illegal for XCOPY */
691 if (in_quotes && *ptr == '\0')
692 return RC_INITERROR;
693 if (*ptr == '\0' || (!in_quotes && is_whitespace(*ptr)))
694 break;
695 }
696 *end = (WCHAR*)ptr;
697 return RC_OK;
698}
static BOOL is_whitespace(WCHAR c)
Definition: xcopy.c:659
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint GLuint end
Definition: gl.h:1545
const WCHAR * word
Definition: lex.c:36
static PVOID ptr
Definition: dispmode.c:27
#define RC_INITERROR
Definition: xcopy.h:29
#define RC_OK
Definition: xcopy.h:26
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by XCOPY_ParseCommandLine().

◆ is_digit()

static BOOL is_digit ( WCHAR  c)
inlinestatic

Definition at line 670 of file xcopy.c.

671{
672 return c >= '0' && c <= '9';
673}
const GLubyte * c
Definition: glext.h:8905

◆ is_whitespace()

static BOOL is_whitespace ( WCHAR  c)
inlinestatic

Definition at line 659 of file xcopy.c.

660{
661 return c == ' ' || c == '\t';
662}

Referenced by find_end_of_word(), and skip_whitespace().

◆ skip_whitespace()

static WCHAR * skip_whitespace ( WCHAR p)
static

Definition at line 664 of file xcopy.c.

665{
666 for (; *p && is_whitespace(*p); p++);
667 return p;
668}
GLfloat GLfloat p
Definition: glext.h:8902

◆ strip_quotes()

static void strip_quotes ( WCHAR word,
WCHAR **  end 
)
static

Definition at line 701 of file xcopy.c.

702{
703 WCHAR *rp, *wp;
704 for (rp = word, wp = word; *rp != '\0'; rp++) {
705 if (*rp == '"')
706 continue;
707 if (wp < rp)
708 *wp = *rp;
709 wp++;
710 }
711 *wp = '\0';
712 *end = wp;
713}

Referenced by next_part(), trim(), and XCOPY_ParseCommandLine().

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( xcopy  )

◆ wmain()

int wmain ( int  argc,
WCHAR argvW[] 
)

Definition at line 1091 of file xcopy.c.

1092{
1093 int rc = 0;
1094 WCHAR suppliedsource[MAX_PATH] = {0}; /* As supplied on the cmd line */
1095 WCHAR supplieddestination[MAX_PATH] = {0};
1096 WCHAR sourcestem[MAX_PATH] = {0}; /* Stem of source */
1097 WCHAR sourcespec[MAX_PATH] = {0}; /* Filespec of source */
1098 WCHAR destinationstem[MAX_PATH] = {0}; /* Stem of destination */
1099 WCHAR destinationspec[MAX_PATH] = {0}; /* Filespec of destination */
1100 WCHAR copyCmd[MAXSTRING]; /* COPYCMD env var */
1101 DWORD flags = 0; /* Option flags */
1102 const WCHAR PROMPTSTR1[] = {'/', 'Y', 0};
1103 const WCHAR PROMPTSTR2[] = {'/', 'y', 0};
1104 const WCHAR COPYCMD[] = {'C', 'O', 'P', 'Y', 'C', 'M', 'D', 0};
1105
1106 /* Preinitialize flags based on COPYCMD */
1107 if (GetEnvironmentVariableW(COPYCMD, copyCmd, MAXSTRING)) {
1108 if (wcsstr(copyCmd, PROMPTSTR1) != NULL ||
1109 wcsstr(copyCmd, PROMPTSTR2) != NULL) {
1111 }
1112 }
1113
1114 /* FIXME: On UNIX, files starting with a '.' are treated as hidden under
1115 wine, but on windows these can be normal files. At least one installer
1116 uses files such as .packlist and (validly) expects them to be copied.
1117 Under wine, if we do not copy hidden files by default then they get
1118 lose */
1120
1121 /*
1122 * Parse the command line
1123 */
1124 if ((rc = XCOPY_ParseCommandLine(suppliedsource, supplieddestination,
1125 &flags)) != RC_OK) {
1126 if (rc == RC_HELP)
1127 return RC_OK;
1128 else
1129 return rc;
1130 }
1131
1132 /* Trace out the supplied information */
1133 WINE_TRACE("Supplied parameters:\n");
1134 WINE_TRACE("Source : '%s'\n", wine_dbgstr_w(suppliedsource));
1135 WINE_TRACE("Destination : '%s'\n", wine_dbgstr_w(supplieddestination));
1136
1137 /* Extract required information from source specification */
1138 rc = XCOPY_ProcessSourceParm(suppliedsource, sourcestem, sourcespec, flags);
1139 if (rc != RC_OK) return rc;
1140
1141 /* Extract required information from destination specification */
1142 rc = XCOPY_ProcessDestParm(supplieddestination, destinationstem,
1143 destinationspec, sourcespec, flags);
1144 if (rc != RC_OK) return rc;
1145
1146 /* Trace out the resulting information */
1147 WINE_TRACE("Resolved parameters:\n");
1148 WINE_TRACE("Source Stem : '%s'\n", wine_dbgstr_w(sourcestem));
1149 WINE_TRACE("Source Spec : '%s'\n", wine_dbgstr_w(sourcespec));
1150 WINE_TRACE("Dest Stem : '%s'\n", wine_dbgstr_w(destinationstem));
1151 WINE_TRACE("Dest Spec : '%s'\n", wine_dbgstr_w(destinationspec));
1152
1153 /* Pause if necessary */
1154 if (flags & OPT_PAUSE) {
1155 DWORD count;
1156 char pausestr[10];
1157
1159 ReadFile (GetStdHandle(STD_INPUT_HANDLE), pausestr, sizeof(pausestr),
1160 &count, NULL);
1161 }
1162
1163 /* Now do the hard work... */
1164 rc = XCOPY_DoCopy(sourcestem, sourcespec,
1165 destinationstem, destinationspec,
1166 flags);
1167
1168 /* Clear up exclude list allocated memory */
1169 while (excludeList) {
1172 HeapFree(GetProcessHeap(), 0, pos->name);
1174 }
1175
1176 /* Finished - print trailer and exit */
1177 if (flags & OPT_SIMULATE) {
1179 } else if (!(flags & OPT_NOCOPY)) {
1181 }
1182 return rc;
1183
1184}
static WCHAR * XCOPY_LoadMessage(UINT id)
Definition: xcopy.c:83
static int XCOPY_ProcessDestParm(WCHAR *supplieddestination, WCHAR *stem, WCHAR *spec, WCHAR *srcspec, DWORD flags)
Definition: xcopy.c:1005
static int XCOPY_ProcessSourceParm(WCHAR *suppliedsource, WCHAR *stem, WCHAR *spec, DWORD flags)
Definition: xcopy.c:909
static int XCOPY_DoCopy(WCHAR *srcstem, WCHAR *srcspec, WCHAR *deststem, WCHAR *destspec, DWORD flags)
Definition: xcopy.c:347
static EXCLUDELIST * excludeList
Definition: xcopy.c:65
static ULONG filesCopied
Definition: xcopy.c:64
static int WINAPIV XCOPY_wprintf(const WCHAR *format,...)
Definition: xcopy.c:99
static int XCOPY_ParseCommandLine(WCHAR *suppliedsource, WCHAR *supplieddestination, DWORD *pflags)
Definition: xcopy.c:715
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
#define NULL
Definition: types.h:112
#define GetProcessHeap()
Definition: compat.h:736
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:755
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLbitfield flags
Definition: glext.h:7161
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
#define wine_dbgstr_w
Definition: kernel32.h:34
static unsigned __int64 next
Definition: rand_nt.c:6
#define WINE_TRACE
Definition: debug.h:354
#define STD_INPUT_HANDLE
Definition: winbase.h:267
#define STRING_COPY
Definition: xcopy.h:62
#define MAXSTRING
Definition: xcopy.h:55
#define OPT_COPYHIDSYS
Definition: xcopy.h:45
#define OPT_NOPROMPT
Definition: xcopy.h:41
#define STRING_SIMCOPY
Definition: xcopy.h:61
#define OPT_SIMULATE
Definition: xcopy.h:38
#define OPT_PAUSE
Definition: xcopy.h:39
#define OPT_NOCOPY
Definition: xcopy.h:40
#define RC_HELP
Definition: xcopy.h:31
#define STRING_PAUSE
Definition: xcopy.h:60

◆ XCOPY_CreateDirectory()

static BOOL XCOPY_CreateDirectory ( const WCHAR path)
static

Definition at line 203 of file xcopy.c.

204{
205 int len;
206 WCHAR *new_path;
207 BOOL ret = TRUE;
208
209 new_path = HeapAlloc(GetProcessHeap(),0, sizeof(WCHAR) * (lstrlenW(path)+1));
210 lstrcpyW(new_path,path);
211
212 while ((len = lstrlenW(new_path)) && new_path[len - 1] == '\\')
213 new_path[len - 1] = 0;
214
215 while (!CreateDirectoryW(new_path,NULL))
216 {
217 WCHAR *slash;
220 break;
221
223 {
224 ret = FALSE;
225 break;
226 }
227
228 if (!(slash = wcsrchr(new_path,'\\')) && ! (slash = wcsrchr(new_path,'/')))
229 {
230 ret = FALSE;
231 break;
232 }
233
234 len = slash - new_path;
235 new_path[len] = 0;
236 if (!XCOPY_CreateDirectory(new_path))
237 {
238 ret = FALSE;
239 break;
240 }
241 new_path[len] = '\\';
242 }
243 HeapFree(GetProcessHeap(),0,new_path);
244 return ret;
245}
static BOOL XCOPY_CreateDirectory(const WCHAR *path)
Definition: xcopy.c:203
#define TRUE
Definition: types.h:120
#define wcsrchr
Definition: compat.h:16
#define HeapAlloc
Definition: compat.h:733
#define lstrcpyW
Definition: compat.h:749
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
GLenum GLsizei len
Definition: glext.h:6722
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
int ret
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106

Referenced by XCOPY_CreateDirectory(), and XCOPY_DoCopy().

◆ XCOPY_DoCopy()

static int XCOPY_DoCopy ( WCHAR srcstem,
WCHAR srcspec,
WCHAR deststem,
WCHAR destspec,
DWORD  flags 
)
static

Definition at line 347 of file xcopy.c.

350{
351 WIN32_FIND_DATAW *finddata;
352 HANDLE h;
353 BOOL findres = TRUE;
354 WCHAR *inputpath, *outputpath;
355 BOOL copiedFile = FALSE;
356 DWORD destAttribs, srcAttribs;
357 BOOL skipFile;
358 int ret = 0;
359
360 /* Allocate some working memory on heap to minimize footprint */
361 finddata = HeapAlloc(GetProcessHeap(), 0, sizeof(WIN32_FIND_DATAW));
362 inputpath = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
363 outputpath = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
364
365 /* Build the search info into a single parm */
366 lstrcpyW(inputpath, srcstem);
367 lstrcatW(inputpath, srcspec);
368
369 /* Search 1 - Look for matching files */
370 h = FindFirstFileW(inputpath, finddata);
371 while (h != INVALID_HANDLE_VALUE && findres) {
372
373 skipFile = FALSE;
374
375 /* Ignore . and .. */
376 if (lstrcmpW(finddata->cFileName, wchr_dot)==0 ||
377 lstrcmpW(finddata->cFileName, wchr_dotdot)==0 ||
378 finddata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
379
380 WINE_TRACE("Skipping directory, . or .. (%s)\n", wine_dbgstr_w(finddata->cFileName));
381 } else {
382
383 /* Get the filename information */
384 lstrcpyW(copyFrom, srcstem);
385 if (flags & OPT_SHORTNAME) {
386 lstrcatW(copyFrom, finddata->cAlternateFileName);
387 } else {
388 lstrcatW(copyFrom, finddata->cFileName);
389 }
390
391 lstrcpyW(copyTo, deststem);
392 if (*destspec == 0x00) {
393 if (flags & OPT_SHORTNAME) {
394 lstrcatW(copyTo, finddata->cAlternateFileName);
395 } else {
396 lstrcatW(copyTo, finddata->cFileName);
397 }
398 } else {
399 lstrcatW(copyTo, destspec);
400 }
401
402 /* Do the copy */
403 WINE_TRACE("ACTION: Copy '%s' -> '%s'\n", wine_dbgstr_w(copyFrom),
405 if (!copiedFile && !(flags & OPT_SIMULATE)) XCOPY_CreateDirectory(deststem);
406
407 /* See if allowed to copy it */
408 srcAttribs = GetFileAttributesW(copyFrom);
409 WINE_TRACE("Source attribs: %d\n", srcAttribs);
410
411 if ((srcAttribs & FILE_ATTRIBUTE_HIDDEN) ||
412 (srcAttribs & FILE_ATTRIBUTE_SYSTEM)) {
413
414 if (!(flags & OPT_COPYHIDSYS)) {
415 skipFile = TRUE;
416 }
417 }
418
419 if (!(srcAttribs & FILE_ATTRIBUTE_ARCHIVE) &&
421 skipFile = TRUE;
422 }
423
424 /* See if file exists */
425 destAttribs = GetFileAttributesW(copyTo);
426 WINE_TRACE("Dest attribs: %d\n", srcAttribs);
427
428 /* Check date ranges if a destination file already exists */
429 if (!skipFile && (flags & OPT_DATERANGE) &&
430 (CompareFileTime(&finddata->ftLastWriteTime, &dateRange) < 0)) {
431 WINE_TRACE("Skipping file as modified date too old\n");
432 skipFile = TRUE;
433 }
434
435 /* If just /D supplied, only overwrite if src newer than dest */
436 if (!skipFile && (flags & OPT_DATENEWER) &&
437 (destAttribs != INVALID_FILE_ATTRIBUTES)) {
440 NULL);
441 if (h != INVALID_HANDLE_VALUE) {
442 FILETIME writeTime;
443 GetFileTime(h, NULL, NULL, &writeTime);
444
445 if (CompareFileTime(&finddata->ftLastWriteTime, &writeTime) <= 0) {
446 WINE_TRACE("Skipping file as dest newer or same date\n");
447 skipFile = TRUE;
448 }
449 CloseHandle(h);
450 }
451 }
452
453 /* See if exclude list provided. Note since filenames are case
454 insensitive, need to uppercase the filename before doing
455 strstr */
456 if (!skipFile && (flags & OPT_EXCLUDELIST)) {
458 WCHAR copyFromUpper[MAX_PATH];
459
460 /* Uppercase source filename */
461 lstrcpyW(copyFromUpper, copyFrom);
462 CharUpperBuffW(copyFromUpper, lstrlenW(copyFromUpper));
463
464 /* Loop through testing each exclude line */
465 while (pos) {
466 if (wcsstr(copyFromUpper, pos->name) != NULL) {
467 WINE_TRACE("Skipping file as matches exclude '%s'\n",
468 wine_dbgstr_w(pos->name));
469 skipFile = TRUE;
470 pos = NULL;
471 } else {
472 pos = pos->next;
473 }
474 }
475 }
476
477 /* Prompt each file if necessary */
478 if (!skipFile && (flags & OPT_SRCPROMPT)) {
479 DWORD count;
480 char answer[10];
481 BOOL answered = FALSE;
482 WCHAR yesChar[2];
483 WCHAR noChar[2];
484
485 /* Read the Y and N characters from the resource file */
488
489 while (!answered) {
491 ReadFile (GetStdHandle(STD_INPUT_HANDLE), answer, sizeof(answer),
492 &count, NULL);
493
494 answered = TRUE;
495 if (toupper(answer[0]) == noChar[0])
496 skipFile = TRUE;
497 else if (toupper(answer[0]) != yesChar[0])
498 answered = FALSE;
499 }
500 }
501
502 if (!skipFile &&
503 destAttribs != INVALID_FILE_ATTRIBUTES && !(flags & OPT_NOPROMPT)) {
504 DWORD count;
505 char answer[10];
506 BOOL answered = FALSE;
507 WCHAR yesChar[2];
508 WCHAR allChar[2];
509 WCHAR noChar[2];
510
511 /* Read the A,Y and N characters from the resource file */
515
516 while (!answered) {
518 ReadFile (GetStdHandle(STD_INPUT_HANDLE), answer, sizeof(answer),
519 &count, NULL);
520
521 answered = TRUE;
522 if (toupper(answer[0]) == allChar[0])
524 else if (toupper(answer[0]) == noChar[0])
525 skipFile = TRUE;
526 else if (toupper(answer[0]) != yesChar[0])
527 answered = FALSE;
528 }
529 }
530
531 /* See if it has to exist! */
532 if (destAttribs == INVALID_FILE_ATTRIBUTES && (flags & OPT_MUSTEXIST)) {
533 skipFile = TRUE;
534 }
535
536 /* Output a status message */
537 if (!skipFile) {
538 if (flags & OPT_QUIET) {
539 /* Skip message */
540 } else if (flags & OPT_FULL) {
541 const WCHAR infostr[] = {'%', '1', ' ', '-', '>', ' ',
542 '%', '2', '\n', 0};
543
544 XCOPY_wprintf(infostr, copyFrom, copyTo);
545 } else {
546 const WCHAR infostr[] = {'%', '1', '\n', 0};
547 XCOPY_wprintf(infostr, copyFrom);
548 }
549
550 /* If allowing overwriting of read only files, remove any
551 write protection */
552 if ((destAttribs & FILE_ATTRIBUTE_READONLY) &&
555 }
556
557 copiedFile = TRUE;
558 if (flags & OPT_SIMULATE || flags & OPT_NOCOPY) {
559 /* Skip copy */
560 } else if (CopyFileW(copyFrom, copyTo, FALSE) == 0) {
561
566
567 if (flags & OPT_IGNOREERRORS) {
568 skipFile = TRUE;
569 } else {
571 goto cleanup;
572 }
573 } else {
574
575 if (!skipFile) {
576 /* If keeping attributes, update the destination attributes
577 otherwise remove the read only attribute */
578 if (flags & OPT_KEEPATTRS) {
580 } else {
583 }
584
585 /* If /M supplied, remove the archive bit after successful copy */
586 if ((srcAttribs & FILE_ATTRIBUTE_ARCHIVE) &&
587 (flags & OPT_REMOVEARCH)) {
589 }
590 filesCopied++;
591 }
592 }
593 }
594 }
595
596 /* Find next file */
597 findres = FindNextFileW(h, finddata);
598 }
599 FindClose(h);
600
601 /* Search 2 - do subdirs */
602 if (flags & OPT_RECURSIVE) {
603
604 /* If /E is supplied, create the directory now */
605 if ((flags & OPT_EMPTYDIR) &&
606 !(flags & OPT_SIMULATE)) {
607 XCOPY_CreateDirectory(deststem);
608 }
609
610 lstrcpyW(inputpath, srcstem);
611 lstrcatW(inputpath, wchr_star);
612 findres = TRUE;
613 WINE_TRACE("Processing subdirs with spec: %s\n", wine_dbgstr_w(inputpath));
614
615 h = FindFirstFileW(inputpath, finddata);
616 while (h != INVALID_HANDLE_VALUE && findres) {
617
618 /* Only looking for dirs */
619 if ((finddata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
620 (lstrcmpW(finddata->cFileName, wchr_dot) != 0) &&
621 (lstrcmpW(finddata->cFileName, wchr_dotdot) != 0)) {
622
623 WINE_TRACE("Handling subdir: %s\n", wine_dbgstr_w(finddata->cFileName));
624
625 /* Make up recursive information */
626 lstrcpyW(inputpath, srcstem);
627 lstrcatW(inputpath, finddata->cFileName);
628 lstrcatW(inputpath, wchr_slash);
629
630 lstrcpyW(outputpath, deststem);
631 if (*destspec == 0x00) {
632 lstrcatW(outputpath, finddata->cFileName);
633 lstrcatW(outputpath, wchr_slash);
634 }
635
636 XCOPY_DoCopy(inputpath, srcspec, outputpath, destspec, flags);
637 }
638
639 /* Find next one */
640 findres = FindNextFileW(h, finddata);
641 }
642 FindClose(h);
643 }
644
645cleanup:
646
647 /* free up memory */
648 HeapFree(GetProcessHeap(), 0, finddata);
649 HeapFree(GetProcessHeap(), 0, inputpath);
650 HeapFree(GetProcessHeap(), 0, outputpath);
651
652 return ret;
653}
int toupper(int c)
Definition: utclib.c:881
static FILETIME dateRange
Definition: xcopy.c:66
static WCHAR copyFrom[MAX_PATH]
Definition: xcopy.c:75
static WCHAR copyTo[MAX_PATH]
Definition: xcopy.c:76
static void XCOPY_FailMessage(DWORD err)
Definition: xcopy.c:179
static const WCHAR wchr_star[]
Definition: xcopy.c:68
static const WCHAR wchr_slash[]
Definition: xcopy.c:67
static const WCHAR wchr_dot[]
Definition: xcopy.c:69
static const WCHAR wchr_dotdot[]
Definition: xcopy.c:70
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
static void cleanup(void)
Definition: main.c:1335
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:794
BOOL WINAPI GetFileTime(IN HANDLE hFile, OUT LPFILETIME lpCreationTime OPTIONAL, OUT LPFILETIME lpLastAccessTime OPTIONAL, OUT LPFILETIME lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:896
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
LONG WINAPI CompareFileTime(IN CONST FILETIME *lpFileTime1, IN CONST FILETIME *lpFileTime2)
Definition: time.c:106
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
#define error(str)
Definition: mkdosfs.c:1605
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
DWORD WINAPI CharUpperBuffW(_Inout_updates_(cchLength) LPWSTR lpsz, _In_ DWORD cchLength)
#define OPT_FULL
Definition: xcopy.h:37
#define OPT_DATENEWER
Definition: xcopy.h:52
#define OPT_REMOVEARCH
Definition: xcopy.h:49
#define OPT_QUIET
Definition: xcopy.h:36
#define OPT_REPLACEREAD
Definition: xcopy.h:44
#define OPT_EXCLUDELIST
Definition: xcopy.h:50
#define OPT_EMPTYDIR
Definition: xcopy.h:35
#define OPT_DATERANGE
Definition: xcopy.h:51
#define OPT_MUSTEXIST
Definition: xcopy.h:43
#define OPT_KEEPATTRS
Definition: xcopy.h:53
#define OPT_ARCHIVEONLY
Definition: xcopy.h:48
#define OPT_SRCPROMPT
Definition: xcopy.h:47
#define STRING_ALL_CHAR
Definition: xcopy.h:71
#define STRING_NO_CHAR
Definition: xcopy.h:70
#define STRING_COPYFAIL
Definition: xcopy.h:66
#define OPT_IGNOREERRORS
Definition: xcopy.h:46
#define STRING_YES_CHAR
Definition: xcopy.h:69
#define STRING_SRCPROMPT
Definition: xcopy.h:64
#define OPT_RECURSIVE
Definition: xcopy.h:34
#define STRING_OVERWRITE
Definition: xcopy.h:65
#define RC_WRITEERROR
Definition: xcopy.h:30
#define OPT_SHORTNAME
Definition: xcopy.h:42

Referenced by wmain(), and XCOPY_DoCopy().

◆ XCOPY_FailMessage()

static void XCOPY_FailMessage ( DWORD  err)
static

Definition at line 179 of file xcopy.c.

179 {
180 LPWSTR lpMsgBuf;
181 int status;
182
185 NULL, err, 0,
186 (LPWSTR) &lpMsgBuf, 0, NULL);
187 if (!status) {
188 WINE_FIXME("FIXME: Cannot display message for error %d, status %d\n",
189 err, GetLastError());
190 } else {
191 const WCHAR infostr[] = {'%', '1', '\n', 0};
192 XCOPY_wprintf(infostr, lpMsgBuf);
193 LocalFree ((HLOCAL)lpMsgBuf);
194 }
195}
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
#define err(...)
#define WINE_FIXME
Definition: debug.h:366
Definition: ps.c:97
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:423
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:419
WCHAR * LPWSTR
Definition: xmlstorage.h:184

Referenced by XCOPY_DoCopy(), XCOPY_ParseCommandLine(), and XCOPY_ProcessSourceParm().

◆ XCOPY_LoadMessage()

static WCHAR * XCOPY_LoadMessage ( UINT  id)
static

Definition at line 83 of file xcopy.c.

83 {
84 static WCHAR msg[MAXSTRING];
85 const WCHAR failedMsg[] = {'F', 'a', 'i', 'l', 'e', 'd', '!', 0};
86
88 WINE_FIXME("LoadString failed with %d\n", GetLastError());
89 lstrcpyW(msg, failedMsg);
90 }
91 return msg;
92}
#define msg(x)
Definition: auth_time.c:54
#define ARRAY_SIZE(A)
Definition: main.h:33
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)

Referenced by wmain(), XCOPY_DoCopy(), XCOPY_ParseCommandLine(), XCOPY_ProcessDestParm(), and XCOPY_ProcessExcludeFile().

◆ XCOPY_ParseCommandLine()

static int XCOPY_ParseCommandLine ( WCHAR suppliedsource,
WCHAR supplieddestination,
DWORD pflags 
)
static

Definition at line 715 of file xcopy.c.

717{
718 const WCHAR EXCLUDE[] = {'E', 'X', 'C', 'L', 'U', 'D', 'E', ':', 0};
719 DWORD flags = *pflags;
720 WCHAR *cmdline, *word, *end, *next;
721 int rc = RC_INITERROR;
722
724 if (cmdline == NULL)
725 return rc;
726
727 /* Skip first arg, which is the program name */
728 if ((rc = find_end_of_word(cmdline, &word)) != RC_OK)
729 goto out;
731
732 while (*word)
733 {
734 WCHAR first;
735 if ((rc = find_end_of_word(word, &end)) != RC_OK)
736 goto out;
737
739 first = word[0];
740 *end = '\0';
742 WINE_TRACE("Processing Arg: '%s'\n", wine_dbgstr_w(word));
743
744 /* First non-switch parameter is source, second is destination */
745 if (first != '/') {
746 if (suppliedsource[0] == 0x00) {
747 lstrcpyW(suppliedsource, word);
748 } else if (supplieddestination[0] == 0x00) {
749 lstrcpyW(supplieddestination, word);
750 } else {
752 goto out;
753 }
754 } else {
755 /* Process all the switch options
756 Note: Windows docs say /P prompts when dest is created
757 but tests show it is done for each src file
758 regardless of the destination */
759 int skip=0;
760 WCHAR *rest;
761
762 while (word[0]) {
763 rest = NULL;
764
765 switch (toupper(word[1])) {
766 case 'I': flags |= OPT_ASSUMEDIR; break;
767 case 'S': flags |= OPT_RECURSIVE; break;
768 case 'Q': flags |= OPT_QUIET; break;
769 case 'F': flags |= OPT_FULL; break;
770 case 'L': flags |= OPT_SIMULATE; break;
771 case 'W': flags |= OPT_PAUSE; break;
772 case 'T': flags |= OPT_NOCOPY | OPT_RECURSIVE; break;
773 case 'Y': flags |= OPT_NOPROMPT; break;
774 case 'N': flags |= OPT_SHORTNAME; break;
775 case 'U': flags |= OPT_MUSTEXIST; break;
776 case 'R': flags |= OPT_REPLACEREAD; break;
777 case 'K': flags |= OPT_KEEPATTRS; break;
778 case 'H': flags |= OPT_COPYHIDSYS; break;
779 case 'C': flags |= OPT_IGNOREERRORS; break;
780 case 'P': flags |= OPT_SRCPROMPT; break;
781 case 'A': flags |= OPT_ARCHIVEONLY; break;
782 case 'M': flags |= OPT_ARCHIVEONLY |
783 OPT_REMOVEARCH; break;
784
785 /* E can be /E or /EXCLUDE */
788 &word[1], 8,
789 EXCLUDE, -1) == CSTR_EQUAL) {
792 goto out;
793 } else {
795
796 /* Do not support concatenated switches onto exclude lists yet */
797 rest = end;
798 }
799 } else {
801 }
802 break;
803
804 /* D can be /D or /D: */
805 case 'D': if (word[2]==':' && is_digit(word[3])) {
806 SYSTEMTIME st;
807 WCHAR *pos = &word[3];
808 BOOL isError = FALSE;
809 memset(&st, 0x00, sizeof(st));
810
811 /* Microsoft xcopy's usage message implies that the date
812 * format depends on the locale, but that is false.
813 * It is hardcoded to month-day-year.
814 */
815 st.wMonth = _wtol(pos);
816 while (*pos && is_digit(*pos)) pos++;
817 if (*pos++ != '-') isError = TRUE;
818
819 if (!isError) {
820 st.wDay = _wtol(pos);
821 while (*pos && is_digit(*pos)) pos++;
822 if (*pos++ != '-') isError = TRUE;
823 }
824
825 if (!isError) {
826 st.wYear = _wtol(pos);
827 while (*pos && is_digit(*pos)) pos++;
828 if (st.wYear < 100) st.wYear+=2000;
829 }
830
831 /* Handle switches straight after the supplied date */
832 rest = pos;
833
834 if (!isError && SystemTimeToFileTime(&st, &dateRange)) {
835 SYSTEMTIME st;
836 WCHAR datestring[32], timestring[32];
837
839
840 /* Debug info: */
842 GetDateFormatW(0, DATE_SHORTDATE, &st, NULL, datestring,
843 ARRAY_SIZE(datestring));
845 NULL, timestring, ARRAY_SIZE(timestring));
846
847 WINE_TRACE("Date being used is: %s %s\n",
848 wine_dbgstr_w(datestring), wine_dbgstr_w(timestring));
849 } else {
851 goto out;
852 }
853 } else {
855 }
856 break;
857
858 case '-': if (toupper(word[2])=='Y') {
859 flags &= ~OPT_NOPROMPT;
860 rest = &word[3]; /* Skip over 3 characters */
861 }
862 break;
864 rc = RC_HELP;
865 goto out;
866 case 'V':
867 WINE_FIXME("ignoring /V\n");
868 break;
869 default:
870 WINE_TRACE("Unhandled parameter '%s'\n", wine_dbgstr_w(word));
872 goto out;
873 }
874
875 /* Unless overridden above, skip over the '/' and the first character */
876 if (rest == NULL) rest = &word[2];
877
878 /* By now, rest should point either to the null after the
879 switch, or the beginning of the next switch if there
880 was no whitespace between them */
881 if (!skip && *rest && *rest != '/') {
882 WINE_FIXME("Unexpected characters found and ignored '%s'\n", wine_dbgstr_w(rest));
883 skip=1;
884 } else {
885 word = rest;
886 }
887 }
888 }
889 word = next;
890 }
891
892 /* Default the destination if not supplied */
893 if (supplieddestination[0] == 0x00)
894 lstrcpyW(supplieddestination, wchr_dot);
895
896 *pflags = flags;
897 rc = RC_OK;
898
899 out:
900 free(cmdline);
901 return rc;
902}
#define is_digit(c)
Definition: astoll.c:39
#define skip(...)
Definition: atltest.h:64
static BOOL XCOPY_ProcessExcludeList(WCHAR *parms)
Definition: xcopy.c:309
static int find_end_of_word(const WCHAR *word, WCHAR **end)
Definition: xcopy.c:679
static void strip_quotes(WCHAR *word, WCHAR **end)
Definition: xcopy.c:701
#define free
Definition: debug_ros.c:5
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
LPWSTR WINAPI GetCommandLineW(VOID)
Definition: proc.c:2013
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:158
const GLint * first
Definition: glext.h:5794
_Check_return_ _CRTIMP long __cdecl _wtol(_In_z_ const wchar_t *_Str)
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: lang.c:2671
INT WINAPI GetTimeFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpTimeStr, INT cchOut)
Definition: lcformat.c:1093
INT WINAPI GetDateFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpDateStr, INT cchOut)
Definition: lcformat.c:993
#define EXCLUDE
Definition: match.h:22
#define LOCALE_USER_DEFAULT
static FILE * out
Definition: regtests2xml.c:44
static void skip_whitespace()
Definition: regtests2xml.c:188
_Check_return_ _CRTIMP wchar_t *__cdecl _wcsdup(_In_z_ const wchar_t *_Str)
#define memset(x, y, z)
Definition: compat.h:39
TCHAR * cmdline
Definition: stretchblt.cpp:32
WORD wYear
Definition: winbase.h:905
WORD wMonth
Definition: winbase.h:906
WORD wDay
Definition: winbase.h:908
#define NORM_IGNORECASE
Definition: winnls.h:176
#define SORT_STRINGSORT
Definition: winnls.h:183
#define CSTR_EQUAL
Definition: winnls.h:456
#define TIME_NOSECONDS
Definition: winnls.h:278
#define DATE_SHORTDATE
Definition: winnls.h:196
#define STRING_HELP
Definition: xcopy.h:74
#define STRING_INVPARMS
Definition: xcopy.h:58
#define OPT_ASSUMEDIR
Definition: xcopy.h:33
#define STRING_INVPARM
Definition: xcopy.h:59

Referenced by wmain().

◆ XCOPY_ProcessDestParm()

static int XCOPY_ProcessDestParm ( WCHAR supplieddestination,
WCHAR stem,
WCHAR spec,
WCHAR srcspec,
DWORD  flags 
)
static

Definition at line 1005 of file xcopy.c.

1007{
1008 WCHAR actualdestination[MAX_PATH];
1009 DWORD attribs;
1010 BOOL isDir = FALSE;
1011
1012 /*
1013 * Validate the source, expanding to full path ensuring it exists
1014 */
1015 if (GetFullPathNameW(supplieddestination, MAX_PATH, actualdestination, NULL) == 0) {
1016 WINE_FIXME("Unexpected failure expanding source path (%d)\n", GetLastError());
1017 return RC_INITERROR;
1018 }
1019
1020 /* Destination is either a directory or a file */
1021 attribs = GetFileAttributesW(actualdestination);
1022
1024
1025 /* If /I supplied and wildcard copy, assume directory */
1026 /* Also if destination ends with backslash */
1027 if ((flags & OPT_ASSUMEDIR &&
1028 (wcschr(srcspec, '?') || wcschr(srcspec, '*'))) ||
1029 (supplieddestination[lstrlenW(supplieddestination)-1] == '\\')) {
1030
1031 isDir = TRUE;
1032
1033 } else {
1034 DWORD count;
1035 char answer[10] = "";
1036 WCHAR fileChar[2];
1037 WCHAR dirChar[2];
1038
1039 /* Read the F and D characters from the resource file */
1042
1043 while (answer[0] != fileChar[0] && answer[0] != dirChar[0]) {
1044 XCOPY_wprintf(XCOPY_LoadMessage(STRING_QISDIR), supplieddestination);
1045
1046 ReadFile(GetStdHandle(STD_INPUT_HANDLE), answer, sizeof(answer), &count, NULL);
1047 WINE_TRACE("User answer %c\n", answer[0]);
1048
1049 answer[0] = toupper(answer[0]);
1050 }
1051
1052 if (answer[0] == dirChar[0]) {
1053 isDir = TRUE;
1054 } else {
1055 isDir = FALSE;
1056 }
1057 }
1058 } else {
1060 }
1061
1062 if (isDir) {
1063 lstrcpyW(stem, actualdestination);
1064 *spec = 0x00;
1065
1066 /* Ensure ends with a '\' */
1067 if (stem[lstrlenW(stem)-1] != '\\') {
1068 lstrcatW(stem, wchr_slash);
1069 }
1070
1071 } else {
1074 WCHAR fname[MAX_PATH];
1076 _wsplitpath(actualdestination, drive, dir, fname, ext);
1077 lstrcpyW(stem, drive);
1078 lstrcatW(stem, dir);
1079 lstrcpyW(spec, fname);
1080 lstrcatW(spec, ext);
1081 }
1082 return RC_OK;
1083}
unsigned int dir
Definition: maze.c:112
#define wcschr
Definition: compat.h:17
static const WCHAR *const ext[]
Definition: module.c:53
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
const GLint * attribs
Definition: glext.h:10538
_CRTIMP void __cdecl _wsplitpath(_In_z_ const wchar_t *_FullPath, _Pre_maybenull_ _Post_z_ wchar_t *_Drive, _Pre_maybenull_ _Post_z_ wchar_t *_Dir, _Pre_maybenull_ _Post_z_ wchar_t *_Filename, _Pre_maybenull_ _Post_z_ wchar_t *_Ext)
#define STRING_QISDIR
Definition: xcopy.h:63
#define STRING_FILE_CHAR
Definition: xcopy.h:72
#define STRING_DIR_CHAR
Definition: xcopy.h:73

Referenced by wmain().

◆ XCOPY_ProcessExcludeFile()

static BOOL XCOPY_ProcessExcludeFile ( WCHAR filename,
WCHAR endOfName 
)
static

Definition at line 252 of file xcopy.c.

252 {
253
254 WCHAR endChar = *endOfName;
256 FILE *inFile = NULL;
257 const WCHAR readTextMode[] = {'r', 't', 0};
258
259 /* Null terminate the filename (temporarily updates the filename hence
260 parms not const) */
261 *endOfName = 0x00;
262
263 /* Open the file */
264 inFile = _wfopen(filename, readTextMode);
265 if (inFile == NULL) {
267 *endOfName = endChar;
268 return TRUE;
269 }
270
271 /* Process line by line */
272 while (fgetws(buffer, ARRAY_SIZE(buffer), inFile) != NULL) {
273 EXCLUDELIST *thisEntry;
274 int length = lstrlenW(buffer);
275
276 /* If more than CRLF */
277 if (length > 1) {
278 buffer[length-1] = 0; /* strip CRLF */
279 thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCLUDELIST));
280 thisEntry->next = excludeList;
281 excludeList = thisEntry;
282 thisEntry->name = HeapAlloc(GetProcessHeap(), 0,
283 (length * sizeof(WCHAR))+1);
284 lstrcpyW(thisEntry->name, buffer);
285 CharUpperBuffW(thisEntry->name, length);
286 WINE_TRACE("Read line : '%s'\n", wine_dbgstr_w(thisEntry->name));
287 }
288 }
289
290 /* See if EOF or error occurred */
291 if (!feof(inFile)) {
293 *endOfName = endChar;
294 fclose(inFile);
295 return TRUE;
296 }
297
298 /* Revert the input string to original form, and cleanup + return */
299 *endOfName = endChar;
300 fclose(inFile);
301 return FALSE;
302}
GLuint buffer
Definition: glext.h:5915
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
_Check_return_ _CRTIMP int __cdecl feof(_In_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl _wfopen(_In_z_ const wchar_t *_Filename, _In_z_ const wchar_t *_Mode)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
const char * filename
Definition: ioapi.h:137
struct _EXCLUDELIST * next
Definition: xcopy.c:58
WCHAR * name
Definition: xcopy.c:59
wchar_t * fgetws(wchar_t *buf, int bufsize, FILE *file)
Definition: wmain.c:22
#define STRING_READFAIL
Definition: xcopy.h:68
#define STRING_OPENFAIL
Definition: xcopy.h:67

Referenced by XCOPY_ProcessExcludeList().

◆ XCOPY_ProcessExcludeList()

static BOOL XCOPY_ProcessExcludeList ( WCHAR parms)
static

Definition at line 309 of file xcopy.c.

309 {
310
311 WCHAR *filenameStart = parms;
312
313 WINE_TRACE("/EXCLUDE parms: '%s'\n", wine_dbgstr_w(parms));
315
316 while (*parms && *parms != ' ' && *parms != '/') {
317
318 /* If found '+' then process the file found so far */
319 if (*parms == '+') {
320 if (XCOPY_ProcessExcludeFile(filenameStart, parms)) {
321 return TRUE;
322 }
323 filenameStart = parms+1;
324 }
325 parms++;
326 }
327
328 if (filenameStart != parms) {
329 if (XCOPY_ProcessExcludeFile(filenameStart, parms)) {
330 return TRUE;
331 }
332 }
333
334 return FALSE;
335}
static BOOL XCOPY_ProcessExcludeFile(WCHAR *filename, WCHAR *endOfName)
Definition: xcopy.c:252

Referenced by XCOPY_ParseCommandLine().

◆ XCOPY_ProcessSourceParm()

static int XCOPY_ProcessSourceParm ( WCHAR suppliedsource,
WCHAR stem,
WCHAR spec,
DWORD  flags 
)
static

Definition at line 909 of file xcopy.c.

911{
912 WCHAR actualsource[MAX_PATH];
913 WCHAR *starPos;
914 WCHAR *questPos;
916
917 /*
918 * Validate the source, expanding to full path ensuring it exists
919 */
920 if (GetFullPathNameW(suppliedsource, MAX_PATH, actualsource, NULL) == 0) {
921 WINE_FIXME("Unexpected failure expanding source path (%d)\n", GetLastError());
922 return RC_INITERROR;
923 }
924
925 /* If full names required, convert to using the full path */
926 if (flags & OPT_FULL) {
927 lstrcpyW(suppliedsource, actualsource);
928 }
929
930 /*
931 * Work out the stem of the source
932 */
933
934 /* If a directory is supplied, use that as-is (either fully or
935 partially qualified)
936 If a filename is supplied + a directory or drive path, use that
937 as-is
938 Otherwise
939 If no directory or path specified, add eg. C:
940 stem is Drive/Directory is bit up to last \ (or first :)
941 spec is bit after that */
942
943 starPos = wcschr(suppliedsource, '*');
944 questPos = wcschr(suppliedsource, '?');
945 if (starPos || questPos) {
946 attribs = 0x00; /* Ensures skips invalid or directory check below */
947 } else {
948 attribs = GetFileAttributesW(actualsource);
949 }
950
953 return RC_INITERROR;
954
955 /* Directory:
956 stem should be exactly as supplied plus a '\', unless it was
957 eg. C: in which case no slash required */
958 } else if (attribs & FILE_ATTRIBUTE_DIRECTORY) {
959 WCHAR lastChar;
960
961 WINE_TRACE("Directory supplied\n");
962 lstrcpyW(stem, suppliedsource);
963 lastChar = stem[lstrlenW(stem)-1];
964 if (lastChar != '\\' && lastChar != ':') {
965 lstrcatW(stem, wchr_slash);
966 }
967 lstrcpyW(spec, wchr_star);
968
969 /* File or wildcard search:
970 stem should be:
971 Up to and including last slash if directory path supplied
972 If c:filename supplied, just the c:
973 Otherwise stem should be the current drive letter + ':' */
974 } else {
975 WCHAR *lastDir;
976
977 WINE_TRACE("Filename supplied\n");
978 lastDir = wcsrchr(suppliedsource, '\\');
979
980 if (lastDir) {
981 lstrcpyW(stem, suppliedsource);
982 stem[(lastDir-suppliedsource) + 1] = 0x00;
983 lstrcpyW(spec, (lastDir+1));
984 } else if (suppliedsource[1] == ':') {
985 lstrcpyW(stem, suppliedsource);
986 stem[2] = 0x00;
987 lstrcpyW(spec, suppliedsource+2);
988 } else {
989 WCHAR curdir[MAXSTRING];
990 GetCurrentDirectoryW(ARRAY_SIZE(curdir), curdir);
991 stem[0] = curdir[0];
992 stem[1] = curdir[1];
993 stem[2] = 0x00;
994 lstrcpyW(spec, suppliedsource);
995 }
996 }
997
998 return RC_OK;
999}
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756

Referenced by wmain().

◆ XCOPY_wprintf()

static int WINAPIV XCOPY_wprintf ( const WCHAR format,
  ... 
)
static

Definition at line 99 of file xcopy.c.

99 {
100
101 static WCHAR *output_bufW = NULL;
102 static char *output_bufA = NULL;
103 static BOOL toConsole = TRUE;
104 static BOOL traceOutput = FALSE;
105#define MAX_WRITECONSOLE_SIZE 65535
106
107 __ms_va_list parms;
108 DWORD nOut;
109 int len;
110 DWORD res = 0;
111
112 /*
113 * Allocate buffer to use when writing to console
114 * Note: Not freed - memory will be allocated once and released when
115 * xcopy ends
116 */
117
118 if (!output_bufW) output_bufW = HeapAlloc(GetProcessHeap(), 0,
120 if (!output_bufW) {
121 WINE_FIXME("Out of memory - could not allocate 2 x 64K buffers\n");
122 return 0;
123 }
124
125 __ms_va_start(parms, format);
128 MAX_WRITECONSOLE_SIZE/sizeof(*output_bufW), &parms);
129 __ms_va_end(parms);
130 if (len == 0 && GetLastError() != NO_ERROR) {
131 WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(format));
132 return 0;
133 }
134
135 /* Try to write as unicode whenever we think it's a console */
136 if (toConsole) {
138 output_bufW, len, &nOut, NULL);
139 }
140
141 /* If writing to console has failed (ever) we assume it's file
142 i/o so convert to OEM codepage and output */
143 if (!res) {
144 BOOL usedDefaultChar = FALSE;
145 DWORD convertedChars;
146
147 toConsole = FALSE;
148
149 /*
150 * Allocate buffer to use when writing to file. Not freed, as above
151 */
152 if (!output_bufA) output_bufA = HeapAlloc(GetProcessHeap(), 0,
154 if (!output_bufA) {
155 WINE_FIXME("Out of memory - could not allocate 2 x 64K buffers\n");
156 return 0;
157 }
158
159 /* Convert to OEM, then output */
160 convertedChars = WideCharToMultiByte(GetConsoleOutputCP(), 0, output_bufW,
161 len, output_bufA, MAX_WRITECONSOLE_SIZE,
162 "?", &usedDefaultChar);
163 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), output_bufA, convertedChars,
164 &nOut, FALSE);
165 }
166
167 /* Trace whether screen or console */
168 if (!traceOutput) {
169 WINE_TRACE("Writing to console? (%d)\n", toConsole);
170 traceOutput = TRUE;
171 }
172 return nOut;
173}
#define MAX_WRITECONSOLE_SIZE
#define NO_ERROR
Definition: dderror.h:5
#define SetLastError(x)
Definition: compat.h:752
#define WideCharToMultiByte
Definition: compat.h:111
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2451
BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleW(IN HANDLE hConsoleOutput, IN CONST VOID *lpBuffer, IN DWORD nNumberOfCharsToWrite, OUT LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved)
Definition: readwrite.c:1447
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLuint res
Definition: glext.h:9613
#define STD_OUTPUT_HANDLE
Definition: winbase.h:268
#define FORMAT_MESSAGE_FROM_STRING
Definition: winbase.h:421
#define __ms_va_list
Definition: windef.h:456
#define __ms_va_end(list)
Definition: windef.h:458
#define __ms_va_start(list, arg)
Definition: windef.h:457

Referenced by wmain(), XCOPY_DoCopy(), XCOPY_FailMessage(), XCOPY_ParseCommandLine(), XCOPY_ProcessDestParm(), and XCOPY_ProcessExcludeFile().

Variable Documentation

◆ copyFrom

WCHAR copyFrom[MAX_PATH]
static

Definition at line 75 of file xcopy.c.

Referenced by XCOPY_DoCopy().

◆ copyTo

WCHAR copyTo[MAX_PATH]
static

Definition at line 76 of file xcopy.c.

Referenced by XCOPY_DoCopy().

◆ dateRange

FILETIME dateRange
static

Definition at line 66 of file xcopy.c.

Referenced by XCOPY_DoCopy(), and XCOPY_ParseCommandLine().

◆ excludeList

EXCLUDELIST* excludeList = NULL
static

Definition at line 65 of file xcopy.c.

Referenced by wmain(), XCOPY_DoCopy(), XCOPY_ProcessExcludeFile(), and XCOPY_ProcessExcludeList().

◆ filesCopied

ULONG filesCopied = 0
static

Definition at line 64 of file xcopy.c.

Referenced by wmain(), and XCOPY_DoCopy().

◆ wchr_dot

const WCHAR wchr_dot[] = {'.', 0}
static

Definition at line 69 of file xcopy.c.

Referenced by XCOPY_DoCopy(), and XCOPY_ParseCommandLine().

◆ wchr_dotdot

const WCHAR wchr_dotdot[] = {'.', '.', 0}
static

Definition at line 70 of file xcopy.c.

Referenced by XCOPY_DoCopy().

◆ wchr_slash

const WCHAR wchr_slash[] = {'\\', 0}
static

Definition at line 67 of file xcopy.c.

Referenced by XCOPY_DoCopy(), XCOPY_ProcessDestParm(), and XCOPY_ProcessSourceParm().

◆ wchr_star

const WCHAR wchr_star[] = {'*', 0}
static

Definition at line 68 of file xcopy.c.

Referenced by XCOPY_DoCopy(), and XCOPY_ProcessSourceParm().