Brandon Turner turnerb7@msu.edu Rewrite to clean up copy and support wildcard. and alot of other small bugfix, like does not crash when a file does not exists.
Modified: trunk/reactos/subsys/system/cmd/copy.c

Modified: trunk/reactos/subsys/system/cmd/copy.c
--- trunk/reactos/subsys/system/cmd/copy.c	2005-07-14 00:27:53 UTC (rev 16560)
+++ trunk/reactos/subsys/system/cmd/copy.c	2005-07-14 14:51:35 UTC (rev 16561)
@@ -22,321 +22,32 @@
  *
  *    03-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
  *        Remove all hardcode string to En.rc
+ *
+ *    13-Jul-2005 (Brandon Turner) <turnerb7@msu.edu>)
+ *        Rewrite to clean up copy and support wildcard.
  */
-
+ 
 #include <precomp.h>
 #include "resource.h"
-
+ 
 #ifdef INCLUDE_CMD_COPY
-
-
-#define VERIFY  1               /* VERIFY Switch */
-#define BINARY  2               /* File is to be copied as BINARY */
-#define ASCII   4               /* File is to be copied as ASCII */
-#define PROMPT  8               /* Prompt before overwriting files */
-#define NPROMPT 16              /* Do not prompt before overwriting files */
-#define HELP    32              /* Help was asked for */
-#define SOURCE  128             /* File is a source */
-
-
-typedef struct tagFILES
+ 
+enum
 {
-	struct tagFILES *next;
-	TCHAR szFile[MAX_PATH];
-	DWORD dwFlag;			/* BINARY -xor- ASCII */
-} FILES, *LPFILES;
-
-
-static BOOL DoSwitches (LPTSTR, LPDWORD);
-static BOOL AddFile (LPFILES, TCHAR *, int *, int *, LPDWORD);
-static BOOL AddFiles (LPFILES, TCHAR *, int *, int *, int *, LPDWORD);
-static BOOL GetDestination (LPFILES, LPFILES);
-static INT  ParseCommand (LPFILES, int, TCHAR **, LPDWORD);
-static VOID DeleteFileList (LPFILES);
-static INT  Overwrite (LPTSTR);
-
-
-static BOOL
-DoSwitches (LPTSTR arg, LPDWORD lpdwFlags)
-{
-	if (!_tcsicmp (arg, _T("/-Y")))
-	{
-		*lpdwFlags |= PROMPT;
-		*lpdwFlags &= ~NPROMPT;
-		return TRUE;
-	}
-	else if (_tcslen (arg) > 2)
-	{
-		error_too_many_parameters (_T(""));
-		return FALSE;
-	}
-
-	switch (_totupper (arg[1]))
-	{
-		case _T('V'):
-			*lpdwFlags |= VERIFY;
-			break;
-
-		case _T('A'):
-			*lpdwFlags |= ASCII;
-			*lpdwFlags &= ~BINARY;
-			break;
-
-		case _T('B'):
-			*lpdwFlags |= BINARY;
-			*lpdwFlags &= ~ASCII;
-			break;
-
-		case _T('Y'):
-			*lpdwFlags &= ~PROMPT;
-			*lpdwFlags |= NPROMPT;
-			break;
-
-		default:
-			error_invalid_switch (arg[1]);
-			return FALSE;
-	}
-	return TRUE;
-}
-
-
-static BOOL
-AddFile (LPFILES f, TCHAR *arg, int *source, int *dest, LPDWORD flags)
-{
-	if (*dest)
-	{
-		error_too_many_parameters (_T(""));
-		return FALSE;
-	}
-	if (*source)
-	{
-		*dest = 1;
-		f->dwFlag = 0;
-	}
-	else
-	{
-		*source = 1;
-		f->dwFlag = SOURCE;
-	}
-	_tcscpy(f->szFile, arg);
-	f->dwFlag |= *flags & ASCII ? ASCII : BINARY;
-	if ((f->next = (LPFILES)malloc (sizeof (FILES))) == NULL)
-	{
-		error_out_of_memory ();
-		return FALSE;
-	}
-	f = f->next;
-	f->dwFlag = 0;
-	f->next = NULL;
-	return TRUE;
-}
-
-
-static BOOL
-AddFiles (LPFILES f, TCHAR *arg, int *source, int *dest,
-		  int *count, LPDWORD flags)
-{
-	TCHAR t[128];
-	int j;
-	int k;
-
-	if (*dest)
-	{
-		error_too_many_parameters (_T(""));
-		return FALSE;
-	}
-
-	j = 0;
-	k = 0;
-
-	while (arg[j] == _T('+'))
-		j++;
-
-	while (arg[j] != _T('\0'))
-	{
-		t[k] = arg[j++];
-		if (t[k] == '+' || arg[j] == _T('\0'))
-		{
-			if (!k)
-				continue;
-			if (arg[j] == _T('\0') && t[k] != _T('+'))
-				k++;
-			t[k] = _T('\0');
-			*count += 1;
-			_tcscpy (f->szFile, t);
-			*source = 1;
-			if (*flags & ASCII)
-				f->dwFlag |= *flags | SOURCE | ASCII;
-			else
-				f->dwFlag |= *flags | BINARY | SOURCE;
-
-			if ((f->next = (LPFILES)malloc (sizeof (FILES))) == NULL)
-			{
-				error_out_of_memory ();
-				return FALSE;
-			}
-			f = f->next;
-			f->next = NULL;
-			k = 0;
-			f->dwFlag = 0;
-			continue;
-		}
-		k++;
-	}
-
-	if (arg[--j] == _T('+'))
-		*source = 0;
-
-	return 1;
-}
-
-
-static BOOL
-GetDestination (LPFILES f, LPFILES dest)
-{
-	LPFILES p = NULL;
-	LPFILES start = f;
-
-	while (f->next != NULL)
-	{
-		p = f;
-		f = f->next;
-	}
-
-	f = p;
-
-	if ((f->dwFlag & SOURCE) == 0)
-	{
-		free (p->next);
-		p->next = NULL;
-		_tcscpy (dest->szFile, f->szFile);
-		dest->dwFlag = f->dwFlag;
-		dest->next = NULL;
-		f = start;
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-
-static INT
-ParseCommand (LPFILES f, int argc, TCHAR **arg, LPDWORD lpdwFlags)
-{
-	INT i;
-	INT dest;
-	INT source;
-	INT count;
-	TCHAR temp[128];
-	dest = 0;
-	source = 0;
-	count = 0;
-
-
-
-  /* hack geting pipe 1>null working */
-  for (i = 0; i < argc; i++)
-	{
-    if (arg[i][0] != _T('/')) 
-        count++;
-  }
-  if (count==3) argc=2;
-  /* end hack */
-
-  
-
-	for (i = 0; i < argc; i++)
-	{     
-
-		if (arg[i][0] == _T('/'))
-		{
-			if (!DoSwitches (arg[i], lpdwFlags))
-				return -1;
-		}
-		else
-		{
-			if (!_tcscmp(arg[i], _T("+")))
-				source = 0;
-			else if (!_tcschr(arg[i], _T('+')) && source)
-			{
-
-//				Make sure we have a clean workable path
-
-				GetFullPathName( arg[i], 128, (LPTSTR) &temp, NULL);
-//				printf("A Input %s, Output %s\n", arg[i], temp);
-
-				if (!AddFile(f, (TCHAR *) &temp, &source, &dest, lpdwFlags))
-					return -1;
-				f = f->next;
-				count++;
-			}
-			else
-			{
-
-				GetFullPathName( arg[i], 128, (LPTSTR) &temp, NULL);
-//				printf("B Input %s, Output %s\n", arg[i], temp);
-
-				if (!AddFiles(f, (TCHAR *) &temp, &source, &dest, &count, lpdwFlags))
-					return -1;
-				while (f->next != NULL)
-					f = f->next;
-			}
-		}
-	}
-
-#ifdef _DEBUG
-	DebugPrintf (_T("ParseCommand: flags has %s\n"),
-				 *lpdwFlags & ASCII ? _T("ASCII") : _T("BINARY"));
-#endif
-	return count;
-}
-
-
-static VOID
-DeleteFileList (LPFILES f)
-{
-	LPFILES temp;
-
-	while (f != NULL)
-	{
-		temp = f;
-		f = f->next;
-		free (temp);
-	}
-}
-
-
-static INT
-Overwrite (LPTSTR fn)
-{
-	TCHAR inp[10];
-	LPTSTR p;
-	TCHAR szOptions[4];
-
-	LoadString( CMD_ModuleHandle, STRING_COPY_OPTION, szOptions, sizeof(szOptions) / sizeof(szOptions[0]) );
-
-	ConOutResPuts(STRING_COPY_HELP1);
-
-	ConInString(inp, 10);
-	ConOutPuts(_T(""));
-
-	_tcsupr (inp);
-	for (p = inp; _istspace (*p); p++)
-		;
-
-	if (*p != szOptions[0] && *p != szOptions[2])
-		return 0;
-	if (*p == szOptions[2])
-		return 2;
-
-	return 1;
-}
-
-
+	COPY_ASCII   = 0x001,   /* /A  */
+	COPY_DECRYPT     = 0x004,   /* /D  : Not Impleneted */
+	COPY_VERIFY      = 0x008,   /* /V  : Dummy, Never will be Impleneted */
+	COPY_SHORTNAME   = 0x010,   /* /N  : Not Impleneted */
+	COPY_NO_PROMPT   = 0x020,   /* /Y  */
+	COPY_PROMPT      = 0x040,   /* /-Y */
+	COPY_RESTART     = 0x080,   /* /Z  : Not Impleneted */
+	COPY_BINARY     = 0x100,    /* /B  */
+};
+ 
 #define BUFF_SIZE 16384         /* 16k = max buffer size */
-
-
-int copy (LPTSTR source, LPTSTR dest, int append, LPDWORD lpdwFlags)
+ 
+ 
+int copy (LPTSTR source, LPTSTR dest, int append, DWORD lpdwFlags)
 {
 	TCHAR szMsg[RC_STRING_MAX_SIZE];
 	FILETIME srctime;
@@ -348,33 +59,33 @@
 	DWORD  dwWritten;
 	DWORD  i;
 	BOOL   bEof = FALSE;
-
+ 
 #ifdef _DEBUG
 	DebugPrintf (_T("checking mode\n"));
 #endif
-
+ 
 	dwAttrib = GetFileAttributes (source);
-
+ 
 	hFileSrc = CreateFile (source, GENERIC_READ, FILE_SHARE_READ,
-						   NULL, OPEN_EXISTING, 0, NULL);
+		NULL, OPEN_EXISTING, 0, NULL);
 	if (hFileSrc == INVALID_HANDLE_VALUE)
 	{
 		LoadString(CMD_ModuleHandle, STRING_COPY_ERROR1, szMsg, RC_STRING_MAX_SIZE);
-		ConErrPrintf(szMsg, source);
+		ConOutPrintf(szMsg, source);
 		return 0;
 	}
-
+ 
 #ifdef _DEBUG
 	DebugPrintf (_T("getting time\n"));
 #endif
-
+ 
 	GetFileTime (hFileSrc, &srctime, NULL, NULL);
-
+ 
 #ifdef _DEBUG
 	DebugPrintf (_T("copy: flags has %s\n"),
-				 *lpdwFlags & ASCII ? "ASCII" : "BINARY");
+		*lpdwFlags & ASCII ? "ASCII" : "BINARY");
 #endif
-
+ 
 	if (!IsExistingFile (dest))
 	{
 #ifdef _DEBUG
@@ -388,50 +99,53 @@
 		if (!_tcscmp (dest, source))
 		{
 			LoadString(CMD_ModuleHandle, STRING_COPY_ERROR2, szMsg, RC_STRING_MAX_SIZE);
-			ConErrPrintf(szMsg, source);
-
+			ConOutPrintf(szMsg, source);
+ 
 			CloseHandle (hFileSrc);
 			return 0;
 		}
-
+ 
 #ifdef _DEBUG
 		DebugPrintf (_T("SetFileAttributes (%s, FILE_ATTRIBUTE_NORMAL);\n"), dest);
 #endif
 		SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);
-
+ 
 #ifdef _DEBUG
 		DebugPrintf (_T("DeleteFile (%s);\n"), dest);
 #endif
 		DeleteFile (dest);
-
-		hFileDest =
-			CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ 
+		hFileDest =	CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
 	}
 	else
 	{
 		LONG lFilePosHigh = 0;
-
+ 
 		if (!_tcscmp (dest, source))
 		{
 			CloseHandle (hFileSrc);
 			return 0;
 		}
-
+ 
 #ifdef _DEBUG
 		DebugPrintf (_T("opening/appending\n"));
 #endif
+		SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);
+ 
 		hFileDest =
 			CreateFile (dest, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+ 
+		/* Move to end of file to start writing */
 		SetFilePointer (hFileDest, 0, &lFilePosHigh,FILE_END);
 	}
-
-	if (hFileDest == INVALID_HANDLE_VALUE)
+ 
+ 
+		if (hFileDest == INVALID_HANDLE_VALUE)
 	{
 		CloseHandle (hFileSrc);
 		error_path_not_found ();
 		return 0;
 	}
-
 	buffer = (LPBYTE)malloc (BUFF_SIZE);
 	if (buffer == NULL)
 	{
@@ -440,11 +154,11 @@
 		error_out_of_memory ();
 		return 0;
 	}
-
+ 
 	do
 	{
 		ReadFile (hFileSrc, buffer, BUFF_SIZE, &dwRead, NULL);
-		if (*lpdwFlags & ASCII)
+		if (lpdwFlags & COPY_ASCII)
 		{
 			for (i = 0; i < dwRead; i++)
 			{
@@ -456,15 +170,15 @@
 			}
 			dwRead = i;
 		}
-
+ 
 		if (dwRead == 0)
 			break;
-
+ 
 		WriteFile (hFileDest, buffer, dwRead, &dwWritten, NULL);
 		if (dwWritten != dwRead)
 		{
-			ConErrResPuts(STRING_COPY_ERROR3);
-
+			ConOutResPuts(STRING_COPY_ERROR3);
+ 
 			free (buffer);
 			CloseHandle (hFileDest);
 			CloseHandle (hFileSrc);
@@ -472,13 +186,13 @@
 		}
 	}
 	while (dwRead && !bEof);
-
+ 
 #ifdef _DEBUG
 	DebugPrintf (_T("setting time\n"));
 #endif
 	SetFileTime (hFileDest, &srctime, NULL, NULL);
-
-	if (*lpdwFlags & ASCII)
+ 
+	if (lpdwFlags & COPY_ASCII)
 	{
 		((LPTSTR)buffer)[0] = 0x1A;
 		((LPTSTR)buffer)[1] = _T('\0');
@@ -487,298 +201,448 @@
 #endif
 		WriteFile (hFileDest, buffer, sizeof(TCHAR), &dwWritten, NULL);
 	}
-
+ 
 	free (buffer);
 	CloseHandle (hFileDest);
 	CloseHandle (hFileSrc);
-
+ 
 #ifdef _DEBUG
 	DebugPrintf (_T("setting mode\n"));
 #endif
 	SetFileAttributes (dest, dwAttrib);
-
+ 
 	return 1;
 }
-
-
-static INT
-SetupCopy (LPFILES sources, TCHAR **p, BOOL bMultiple,
-           TCHAR *drive_d, TCHAR *dir_d, TCHAR *file_d,
-           TCHAR *ext_d, int *append, LPDWORD lpdwFlags)
+ 
+ 
+static INT Overwrite (LPTSTR fn)
 {
-	WIN32_FIND_DATA find;
-	TCHAR drive_s[_MAX_DRIVE];
-	TCHAR dir_s[_MAX_DIR];
-	TCHAR file_s[_MAX_FNAME];
-	TCHAR ext_s[_MAX_EXT];
-	TCHAR from_merge[_MAX_PATH];
-
-	LPTSTR real_source;
-	LPTSTR real_dest;
-
-	INT  nCopied = 0;
-	BOOL bAll = FALSE;
-	BOOL bDone;
-	HANDLE hFind;
-	TCHAR temp[128];
-
-#ifdef _DEBUG
-	DebugPrintf (_T("SetupCopy\n"));
-#endif
-
-	real_source = (LPTSTR)malloc (MAX_PATH * sizeof(TCHAR));
-	real_dest = (LPTSTR)malloc (MAX_PATH * sizeof(TCHAR));
-
-	if (!real_source || !real_dest)
+	/*ask the user if they want to override*/
+	TCHAR szMsg[RC_STRING_MAX_SIZE];
+	INT res;
+	LoadString(CMD_ModuleHandle, STRING_COPY_HELP1, szMsg, RC_STRING_MAX_SIZE);
+	ConOutPrintf(szMsg,fn);
+	res = FilePromptYNA ("");
+	return res;
+}
+ 
+ 
+INT cmd_copy (LPTSTR cmd, LPTSTR param)
+{
+	TCHAR szMsg[RC_STRING_MAX_SIZE];
+	LPTSTR *arg;
+	INT argc, i, nFiles, nOverwrite = 0, nSrc = -1, nDes = -1;
+	/* this is the path up to the folder of the src and dest ie C:\windows\ */
+	TCHAR szDestPath[MAX_PATH];
+	TCHAR szSrcPath[MAX_PATH];
+	DWORD dwFlags = 0;
+	/* If this is the type of copy where we are adding files */
+	BOOL bAppend = FALSE;
+	WIN32_FIND_DATA findBuffer;
+	HANDLE hFile;
+	/* Used when something like "copy c*.exe d*.exe" during the process of
+	   figuring out the new name */
+	TCHAR tmpName[MAX_PATH] = _T("");
+	/* Pointer to keep track of how far through the append input(file1+file2+file3) we are */
+	TCHAR  * appendPointer = _T("\0");
+	/* The full path to src and dest.  This has drive letter, folders, and filename */
+	TCHAR tmpDestPath[MAX_PATH];
+	TCHAR tmpSrcPath[MAX_PATH];
+	/* A bool on weather or not the destination name will be taking from the input */
+	BOOL bSrcName = FALSE;
+	/* Seems like a waste but it is a pointer used to copy from input to PreserveName */
+	TCHAR * UseThisName;
+	/* Stores the name( i.e. blah.txt or blah*.txt) which later we might need */
+	TCHAR PreserveName[MAX_PATH];
+ 
+	/*Show help/usage info*/
+	if (!_tcsncmp (param, _T("/?"), 2))
 	{
-		error_out_of_memory ();
-		DeleteFileList (sources);
-		free (real_source);
-		free (real_dest);
-		freep (p);
+		ConOutResPaging(TRUE, STRING_COPY_HELP2);
 		return 0;
 	}
-
-	while (sources->next != NULL)
+ 
+	/*Split the user input into array*/
+	arg = split (param, &argc, FALSE);
+	nFiles = argc;
+ 
+	/*Read switches and count files*/
+	for (i = 0; i < argc; i++)
 	{
-
-/*		Force a clean full path
-*/
-		GetFullPathName( sources->szFile, 128, (LPTSTR) &temp, NULL);
-		if (IsExistingDirectory(temp))
+		if (*arg[i] == _T('/'))
 		{
-			_tcscat(temp, _T("\\*"));
-		}
-
-		_tsplitpath (temp, drive_s, dir_s, file_s, ext_s);
-
-		hFind = FindFirstFile ((TCHAR*)&temp, &find);
-		if (hFind == INVALID_HANDLE_VALUE)
-		{
-			error_file_not_found();
-			freep(p);
-			free(real_source);
-			free(real_dest);
-			return 0;
-		}
-
-		do
-		{
-			if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-				goto next;
-
-			_tmakepath(from_merge, drive_d, dir_d, file_d, ext_d);
-
-			if (from_merge[_tcslen(from_merge) - 1] == _T('\\'))
-				from_merge[_tcslen(from_merge) - 1] = 0;
-
-//			printf("Merge %s, filename %s\n", from_merge, find.cFileName);
-
-			if (IsExistingDirectory (from_merge))
+			if (_tcslen(arg[i]) >= 2)
 			{
-
-//			printf("Merge DIR\n");
-
-				bMultiple = FALSE;
-				_tcscat (from_merge, _T("\\"));
-				_tcscat (from_merge, find.cFileName);
-			}
-			else
-				bMultiple = TRUE;
-
-			_tcscpy (real_dest, from_merge);
-			_tmakepath (real_source, drive_s, dir_s, find.cFileName, NULL);
-
-#ifdef _DEBUG
-			DebugPrintf(_T("copying %S -> %S (%Sappending%S)\n"),
-						 real_source, real_dest,
-						 *append ? _T("") : _T("not "),
-						 sources->dwFlag & ASCII ? _T(", ASCII") : _T(", BINARY"));
-#endif
-
-			if (IsExistingFile (real_dest) && !bAll)
-			{
-				/* Don't prompt in a batch file */
-				if (bc != NULL)
+				switch (_totupper(arg[i][1]))
 				{
-					bAll = TRUE;
+ 
+				case _T('A'):
+					dwFlags |= COPY_ASCII;
+					break;
+ 
+				case _T('B'):
+					dwFlags |= COPY_DECRYPT;
+					break;
+ 
+				case _T('D'):
+					dwFlags |= COPY_DECRYPT;
+					break;
+ 
+				case _T('V'):
+					dwFlags |= COPY_VERIFY;
+					break;
+ 
+				case _T('N'):
+					dwFlags |= COPY_SHORTNAME;
+					break;
+ 
+				case _T('Y'):
+					dwFlags |= COPY_NO_PROMPT;
+					dwFlags &= ~COPY_PROMPT;
+					break;
+ 
+				case _T('-'):
+					if(_tcslen(arg[i]) >= 3)
+						if(_totupper(arg[i][2]) == _T('Y'))
+						{
+							dwFlags &= ~COPY_NO_PROMPT;
+							dwFlags |= COPY_PROMPT;
+						}
+ 
+						break;
+ 
+				case _T('Z'):
+					dwFlags |= COPY_RESTART;
+					break;
+ 
+				default:
+					/* invaild switch */
+					error_invalid_switch(_totupper(arg[i][1]));
+					return 1;
+					break;
 				}
-				else
-				{
-					int over;
-
-					over = Overwrite (real_dest);
-					if (over == 2)
-						bAll = TRUE;
-					else if (over == 0)
-						goto next;
-					else if (bMultiple)
-						bAll = TRUE;
-				}
 			}
-			if (copy (real_source, real_dest, *append, lpdwFlags))
-				nCopied++;
-		next:
-			bDone = FindNextFile (hFind, &find);
-
-			if (bMultiple)
-				*append = 1;
+			/*If it was a switch, subtract from total arguments*/
+			nFiles--;
 		}
-		while (bDone);
-
-		FindClose (hFind);
-		sources = sources->next;
-
+		else
+		{
+			/*if it isnt a switch then it is the source or destination*/
+			if(nSrc == -1)
+				nSrc = i;
+			else if(nDes == -1)
+				nDes = i;
+ 
+		}
 	}
-	free (real_source);
-	free (real_dest);
-
-	return nCopied;
-}
-
-
-INT cmd_copy (LPTSTR first, LPTSTR rest)
-{
-	TCHAR **p;
-	TCHAR drive_d[_MAX_DRIVE];
-	TCHAR dir_d[_MAX_DIR];
-	TCHAR file_d[_MAX_FNAME];
-	TCHAR ext_d[_MAX_EXT];
-	TCHAR szMsg[RC_STRING_MAX_SIZE];
-
-	int argc;
-	int append;
-	int files;
-	int copied;
-
-	LPFILES sources = NULL;
-	LPFILES start = NULL;
-	FILES dest;
-	BOOL bMultiple;
-	BOOL bWildcards;
-	BOOL bDestFound;
-	DWORD dwFlags = 0;
-  
-	if (!_tcsncmp (rest, _T("/?"), 2))
+ 
+	if(nFiles < 1)
 	{
-		ConOutResPaging(TRUE,STRING_COPY_HELP2);
+		/* There is not enough files, there has to be at least 1 */
+		error_req_param_missing();
 		return 1;
 	}
-
-	p = split (rest, &argc, FALSE);
-
-	if (argc == 0)
+ 
+	if(nFiles > 2)
 	{
-		error_req_param_missing ();
-		return 0;
+		/* there is too many file names in command */
+		error_too_many_parameters("");
+		return 1;
 	}
-
-	sources = (LPFILES)malloc (sizeof (FILES));
-	if (!sources)
+ 
+	if((nDes != -1) &&
+		((_tcschr (arg[nSrc], _T('+')) != NULL) ||
+		(_tcschr (arg[nSrc], _T('*')) != NULL && _tcschr (arg[nDes], _T('*')) == NULL) ||
+		(IsExistingDirectory (arg[nSrc]) && (_tcschr (arg[nDes], _T('*')) == NULL && !IsExistingDirectory (arg[nDes])))
+		))
 	{
-		error_out_of_memory ();
-		return 0;
+		/* There is a + in the source filename, this means
+		that there is more then one file being put into
+		one file. */
+		bAppend = TRUE;
+		if(_tcschr (arg[nSrc], _T('+')) != NULL)
+		   appendPointer = arg[nSrc];
 	}
-	sources->next = NULL;
-	sources->dwFlag = 0;
-
-	if ((files = ParseCommand (sources, argc, p, &dwFlags)) == -1)
+ 
+	/* Reusing the number of files variable */
+	nFiles = 0;
+ 
+	do
 	{
-		DeleteFileList (sources);
-		freep (p);
-		return 0;
+ 
+	/* Set up the string that is the path to the destination */
+	if(nDes != -1)
+	{
+		/* Check to make sure if they entered c:, if they do then GFPN 
+		return current directory even though msdn says it will return c:\ */
+		if(_tcslen(arg[nDes]) == 2)
+		{
+			if(arg[nDes][1] == _T(':'))
+			{
+				_tcscpy (szDestPath, arg[nDes]);
+				_tcscat (szDestPath, _T("\\"));
+			}
+		}
+		else
+		/* If the user entered two file names then form the full string path*/
+		GetFullPathName (arg[nDes], MAX_PATH, szDestPath, NULL);
+ 
 	}
-	else if (files == 0)
+	else
 	{
-		error_req_param_missing();
-		DeleteFileList (sources);
-		freep (p);
-		return 0;
+		/* If no destination was entered then just use 
+		the current directory as the destination */
+		GetCurrentDirectory (MAX_PATH, szDestPath);
 	}
-	start = sources;
-
-	bDestFound = GetDestination (sources, &dest);
-	if (bDestFound)
+ 
+ 
+	/* Get the full string of the path to the source file*/
+	if(_tcschr (arg[nSrc], _T('+')) != NULL)
 	{
-		_tsplitpath (dest.szFile, drive_d, dir_d, file_d, ext_d);
-		if (IsExistingDirectory (dest.szFile))
+ 
+		_tcscpy(tmpName,_T("\0"));
+		/* Loop through the source file name and copy all
+		the chars one at a time until it gets too + */
+		while(TRUE)
 		{
-//		printf("A szFile= %s, Dir = %s, File = %s, Ext = %s\n", dest.szFile, dir_d, file_d, ext_d);
-			_tcscat (dir_d, file_d);
-			_tcscat (dir_d, ext_d);
-			file_d[0] = _T('\0');
-			ext_d[0] = _T('\0');
+ 
+			if(!_tcsncmp (appendPointer,_T("+"),1) || !_tcsncmp (appendPointer,_T("\0"),1))
+			{
+				/* Now that the pointer is on the + we 
+				   need to go to the start of the next filename */
+				if(!_tcsncmp (appendPointer,_T("+"),1))
+				   appendPointer++;
+				break;
+			}
+			_tcsncat(tmpName,appendPointer,1);
+			appendPointer++;
 		}
+		/* Finish the string off with a null char */
+		_tcsncat(tmpName,_T("\0"),1);
+		/* Check to make sure if they entered c:, if they do then GFPN 
+		return current directory even though msdn says it will return c:\ */
+		if(_tcslen(tmpName) == 2)
+		{
+			if(tmpName[1] == _T(':'))
+			{
+				_tcscpy (szSrcPath, tmpName);
+				_tcscat (szSrcPath, _T("\\"));
+			}
+		}
+		else
+		/* Get the full path to first file in the string of file names */
+		GetFullPathName (tmpName, MAX_PATH, szSrcPath, NULL);	
 	}
-
-	if (_tcschr (dest.szFile, _T('*')) || _tcschr (dest.szFile, _T('?')))
-		bWildcards = TRUE;
 	else
-		bWildcards = FALSE;
-
-	if (_tcschr(rest, _T('+')))
-		bMultiple = TRUE;
-	else
-		bMultiple = FALSE;
-
-	append = 0;
-	copied = 0;
-
-	if (bDestFound && !bWildcards)
 	{
-
-//		_tcscpy(sources->szFile, dest.szFile);
-
-		copied = SetupCopy (sources, p, bMultiple, drive_d, dir_d, file_d, ext_d, &append, &dwFlags);
+		/* Check to make sure if they entered c:, if they do then GFPN 
+		return current directory even though msdn says it will return c:\ */
+		if(_tcslen(arg[nSrc]) == 2)
+		{
+			if(arg[nSrc][1] == _T(':'))
+			{
+				_tcscpy (szSrcPath, arg[nSrc]);
+				_tcscat (szSrcPath, _T("\\"));
+			}
+		}
+		else
+		/* Get the full path of the source file */
+		GetFullPathName (arg[nSrc], MAX_PATH, szSrcPath, NULL);
+ 
 	}
-	else if (bDestFound && bWildcards)
+ 
+	/* From this point on, we can assume that the shortest path is 3 letters long
+	and that would be [DriveLetter]:\ */
+ 
+	/* If there is no * in the path name and it is a folder
+	then we will need to add a wildcard to the pathname
+	so FindFirstFile comes up with all the files in that
+	folder */
+	if(_tcschr (szSrcPath, _T('*')) == NULL && 
+		IsExistingDirectory (szSrcPath))
 	{
-		ConErrResPuts(STRING_COPY_ERROR4);
-
-		DeleteFileList (sources);
-		freep (p);
-		return 0;
+		/* If it doesnt have a \ at the end already then on needs to be added */
+		if(szSrcPath[_tcslen(szSrcPath) -  1] != _T('\\'))
+			_tcscat (szSrcPath, _T("\\"));
+		/* Add a wildcard after the \ */
+		_tcscat (szSrcPath, _T("*"));
 	}
-	else if (!bDestFound && !bMultiple)
+	/* Make sure there is an ending slash to the path if the dest is a folder */
+	if(_tcschr (szDestPath, _T('*')) == NULL && 
+		IsExistingDirectory(szDestPath))
 	{
-		_tsplitpath (sources->szFile, drive_d, dir_d, file_d, ext_d);
-		if (IsExistingDirectory (sources->szFile))
-		{
-//		printf("B File = %s, Ext = %s\n", file_d, ext_d);
-
-			_tcscat (dir_d, file_d);
-			_tcscat (dir_d, ext_d);
[truncated at 1000 lines; 203 more skipped]