ReactOS 0.4.15-dev-8235-gcd88a97
xcopy.c
Go to the documentation of this file.
1/*
2 * XCOPY - Wine-compatible xcopy program
3 *
4 * Copyright (C) 2007 J. Edmeades
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21/*
22 * FIXME:
23 * This should now support all options listed in the xcopy help from
24 * windows XP except:
25 * /Z - Copy from network drives in restartable mode
26 * /X - Copy file audit settings (sets /O)
27 * /O - Copy file ownership + ACL info
28 * /G - Copy encrypted files to unencrypted destination
29 * /V - Verifies files
30 */
31
32/*
33 * Notes:
34 * Documented valid return codes are:
35 * 0 - OK
36 * 1 - No files found to copy (*1)
37 * 2 - CTRL+C during copy
38 * 4 - Initialization error, or invalid source specification
39 * 5 - Disk write error
40 *
41 * (*1) Testing shows return code 1 is never returned
42 */
43
44
45#include <stdio.h>
46#include <stdlib.h>
47#include <windows.h>
48#include <wine/debug.h>
49#include <wine/unicode.h>
50#include "xcopy.h"
51
53
54
55/* Typedefs */
56typedef struct _EXCLUDELIST
57{
61
62
63/* Global variables */
64static ULONG filesCopied = 0; /* Number of files copied */
65static EXCLUDELIST *excludeList = NULL; /* Excluded strings list */
66static FILETIME dateRange; /* Date range to copy after*/
67static const WCHAR wchr_slash[] = {'\\', 0};
68static const WCHAR wchr_star[] = {'*', 0};
69static const WCHAR wchr_dot[] = {'.', 0};
70static const WCHAR wchr_dotdot[] = {'.', '.', 0};
71
72
73/* To minimize stack usage during recursion, some temporary variables
74 made global */
77
78
79/* =========================================================================
80 * Load a string from the resource file, handling any error
81 * Returns string retrieved from resource file
82 * ========================================================================= */
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}
93
94/* =========================================================================
95 * Output a formatted unicode string. Ideally this will go to the console
96 * and hence required WriteConsoleW to output it, however if file i/o is
97 * redirected, it needs to be WriteFile'd using OEM (not ANSI) format
98 * ========================================================================= */
99static int WINAPIV XCOPY_wprintf(const WCHAR *format, ...) {
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}
174
175/* =========================================================================
176 * Load a string for a system error and writes it to the screen
177 * Returns string retrieved from resource file
178 * ========================================================================= */
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}
196
197
198/* =========================================================================
199 * Routine copied from cmd.exe md command -
200 * This works recursively. so creating dir1\dir2\dir3 will create dir1 and
201 * dir2 if they do not already exist.
202 * ========================================================================= */
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}
246
247/* =========================================================================
248 * Process a single file from the /EXCLUDE: file list, building up a list
249 * of substrings to avoid copying
250 * Returns TRUE on any failure
251 * ========================================================================= */
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}
303
304/* =========================================================================
305 * Process the /EXCLUDE: file list, building up a list of substrings to
306 * avoid copying
307 * Returns TRUE on any failure
308 * ========================================================================= */
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}
336
337/* =========================================================================
338 XCOPY_DoCopy - Recursive function to copy files based on input parms
339 of a stem and a spec
340
341 This works by using FindFirstFile supplying the source stem and spec.
342 If results are found, any non-directory ones are processed
343 Then, if /S or /E is supplied, another search is made just for
344 directories, and this function is called again for that directory
345
346 ========================================================================= */
347static int XCOPY_DoCopy(WCHAR *srcstem, WCHAR *srcspec,
348 WCHAR *deststem, WCHAR *destspec,
349 DWORD flags)
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}
654
655
656/* =========================================================================
657 XCOPY_ParseCommandLine - Parses the command line
658 ========================================================================= */
659static inline BOOL is_whitespace(WCHAR c)
660{
661 return c == ' ' || c == '\t';
662}
663
665{
666 for (; *p && is_whitespace(*p); p++);
667 return p;
668}
669
670static inline BOOL is_digit(WCHAR c)
671{
672 return c >= '0' && c <= '9';
673}
674
675/* Windows XCOPY uses a simplified command line parsing algorithm
676 that lacks the escaped-quote logic of build_argv(), because
677 literal double quotes are illegal in any of its arguments.
678 Example: 'XCOPY "c:\DIR A" "c:DIR B\"' is OK. */
679static int find_end_of_word(const WCHAR *word, WCHAR **end)
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}
699
700/* Remove all double quotes from a word */
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}
714
715static int XCOPY_ParseCommandLine(WCHAR *suppliedsource,
716 WCHAR *supplieddestination, DWORD *pflags)
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}
903
904
905/* =========================================================================
906 XCOPY_ProcessSourceParm - Takes the supplied source parameter, and
907 converts it into a stem and a filespec
908 ========================================================================= */
909static int XCOPY_ProcessSourceParm(WCHAR *suppliedsource, WCHAR *stem,
910 WCHAR *spec, DWORD flags)
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}
1000
1001/* =========================================================================
1002 XCOPY_ProcessDestParm - Takes the supplied destination parameter, and
1003 converts it into a stem
1004 ========================================================================= */
1005static int XCOPY_ProcessDestParm(WCHAR *supplieddestination, WCHAR *stem, WCHAR *spec,
1006 WCHAR *srcspec, DWORD flags)
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}
1084
1085
1086/* =========================================================================
1087 main - Main entrypoint for the xcopy command
1088
1089 Processes the args, and drives the actual copying
1090 ========================================================================= */
1091int wmain (int argc, WCHAR *argvW[])
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 int argc
Definition: ServiceArgs.c:12
int toupper(int c)
Definition: utclib.c:881
unsigned int dir
Definition: maze.c:112
#define is_digit(c)
Definition: astoll.c:39
#define skip(...)
Definition: atltest.h:64
#define msg(x)
Definition: auth_time.c:54
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define MAX_WRITECONSOLE_SIZE
static WCHAR * XCOPY_LoadMessage(UINT id)
Definition: xcopy.c:83
static BOOL XCOPY_ProcessExcludeFile(WCHAR *filename, WCHAR *endOfName)
Definition: xcopy.c:252
static BOOL XCOPY_ProcessExcludeList(WCHAR *parms)
Definition: xcopy.c:309
struct _EXCLUDELIST EXCLUDELIST
static FILETIME dateRange
Definition: xcopy.c:66
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 WCHAR copyFrom[MAX_PATH]
Definition: xcopy.c:75
static int find_end_of_word(const WCHAR *word, WCHAR **end)
Definition: xcopy.c:679
static WCHAR copyTo[MAX_PATH]
Definition: xcopy.c:76
static BOOL XCOPY_CreateDirectory(const WCHAR *path)
Definition: xcopy.c:203
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 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 const WCHAR wchr_dot[]
Definition: xcopy.c:69
static void strip_quotes(WCHAR *word, WCHAR **end)
Definition: xcopy.c:701
static const WCHAR wchr_dotdot[]
Definition: xcopy.c:70
static BOOL is_whitespace(WCHAR c)
Definition: xcopy.c:659
static int XCOPY_ParseCommandLine(WCHAR *suppliedsource, WCHAR *supplieddestination, DWORD *pflags)
Definition: xcopy.c:715
#define ARRAY_SIZE(A)
Definition: main.h:33
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
#define NO_ERROR
Definition: dderror.h:5
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define wcsrchr
Definition: compat.h:16
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:755
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define FILE_SHARE_READ
Definition: compat.h:136
#define lstrlenW
Definition: compat.h:750
static const WCHAR *const ext[]
Definition: module.c:53
static void cleanup(void)
Definition: main.c:1335
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 CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
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
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
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
LONG WINAPI CompareFileTime(IN CONST FILETIME *lpFileTime1, IN CONST FILETIME *lpFileTime2)
Definition: time.c:106
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4242
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4013
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
const GLint * first
Definition: glext.h:5794
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
const GLint * attribs
Definition: glext.h:10538
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
_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)
_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)
_Check_return_ _CRTIMP long __cdecl _wtol(_In_z_ const wchar_t *_Str)
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
const char * filename
Definition: ioapi.h:137
const WCHAR * word
Definition: lex.c:36
#define wine_dbgstr_w
Definition: kernel32.h:34
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
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define error(str)
Definition: mkdosfs.c:1605
#define EXCLUDE
Definition: match.h:22
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
static PVOID ptr
Definition: dispmode.c:27
unsigned int UINT
Definition: ndis.h:50
#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
#define LOCALE_USER_DEFAULT
static unsigned __int64 next
Definition: rand_nt.c:6
int wmain()
#define err(...)
static FILE * out
Definition: regtests2xml.c:44
static void skip_whitespace()
Definition: regtests2xml.c:188
#define WINAPIV
Definition: sdbpapi.h:64
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_Check_return_ _CRTIMP wchar_t *__cdecl _wcsdup(_In_z_ const wchar_t *_Str)
#define WINE_TRACE
Definition: debug.h:354
#define WINE_FIXME
Definition: debug.h:366
#define memset(x, y, z)
Definition: compat.h:39
TCHAR * cmdline
Definition: stretchblt.cpp:32
struct _EXCLUDELIST * next
Definition: xcopy.c:58
WCHAR * name
Definition: xcopy.c:59
WORD wYear
Definition: winbase.h:905
WORD wMonth
Definition: winbase.h:906
WORD wDay
Definition: winbase.h:908
Definition: ps.c:97
uint32_t ULONG
Definition: typedefs.h:59
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
int ret
#define STD_OUTPUT_HANDLE
Definition: winbase.h:268
#define STD_INPUT_HANDLE
Definition: winbase.h:267
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FORMAT_MESSAGE_FROM_STRING
Definition: winbase.h:421
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:423
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:419
#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
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#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
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
DWORD WINAPI CharUpperBuffW(_Inout_updates_(cchLength) LPWSTR lpsz, _In_ DWORD cchLength)
wchar_t * fgetws(wchar_t *buf, int bufsize, FILE *file)
Definition: wmain.c:22
#define STRING_QISDIR
Definition: xcopy.h:63
#define OPT_FULL
Definition: xcopy.h:37
#define STRING_READFAIL
Definition: xcopy.h:68
#define STRING_COPY
Definition: xcopy.h:62
#define MAXSTRING
Definition: xcopy.h:55
#define OPT_DATENEWER
Definition: xcopy.h:52
#define OPT_REMOVEARCH
Definition: xcopy.h:49
#define OPT_COPYHIDSYS
Definition: xcopy.h:45
#define OPT_NOPROMPT
Definition: xcopy.h:41
#define STRING_SIMCOPY
Definition: xcopy.h:61
#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 STRING_FILE_CHAR
Definition: xcopy.h:72
#define OPT_DATERANGE
Definition: xcopy.h:51
#define OPT_SIMULATE
Definition: xcopy.h:38
#define RC_INITERROR
Definition: xcopy.h:29
#define OPT_PAUSE
Definition: xcopy.h:39
#define OPT_MUSTEXIST
Definition: xcopy.h:43
#define OPT_KEEPATTRS
Definition: xcopy.h:53
#define OPT_ARCHIVEONLY
Definition: xcopy.h:48
#define STRING_HELP
Definition: xcopy.h:74
#define STRING_INVPARMS
Definition: xcopy.h:58
#define OPT_NOCOPY
Definition: xcopy.h:40
#define OPT_ASSUMEDIR
Definition: xcopy.h:33
#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 RC_HELP
Definition: xcopy.h:31
#define STRING_OVERWRITE
Definition: xcopy.h:65
#define RC_OK
Definition: xcopy.h:26
#define STRING_INVPARM
Definition: xcopy.h:59
#define STRING_PAUSE
Definition: xcopy.h:60
#define RC_WRITEERROR
Definition: xcopy.h:30
#define OPT_SHORTNAME
Definition: xcopy.h:42
#define STRING_OPENFAIL
Definition: xcopy.h:67
#define STRING_DIR_CHAR
Definition: xcopy.h:73
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184