#include	<windows.h>
#include	<iostream.h>
#include	<iomanip.h>
#include	<fstream.h>
#include	<string.h>

ofstream	CERR("results.out", ios::app);
int	BUFLEN = 0x10000;

ostream	& operator << (ostream & os, SYSTEMTIME & r)
{
	static	const char	* const rgszDayNames[] =
		{
		"Sunday",
		"Monday",
		"Tuesday",
		"Wednesday",
		"Thursday",
		"Friday",
		"Saturday",
		0
		};
	char	chFill = os.fill();
	os.fill('0');
	os //--------------------------------- << rgszDayNames[r.wDayOfWeek] << ' '
		<< setw(2) << r.wMonth << '/'
		<< setw(2) << r.wDay << '/'
		<< setw(2) << r.wYear << ' '
		<< setw(2) << r.wHour << ':'
		<< setw(2) << r.wMinute << ':'
		//------------------- << setw(2) << r.wSecond
		;
	os.fill(chFill);
	return	os;
}

//****************************************************************
void	cat2(HANDLE h, HANDLE hOut)
{
	HANDLE	hOutMap = 0;
	LPVOID	pOut = 0;
	DWORD	dwMapFirst = 0;
	DWORD	dwMapOffset = 0;
	DWORD	dwOutSize = 0;
	//----------------------------------------------------------------
	HANDLE	hMap = CreateFileMapping(h, 0, PAGE_READONLY, 0,0, 0);
	if (0 == hMap)
		{
		CERR << GetLastError() << ": error in CreateFileMapping."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		return;
		}
	LPVOID	pView = MapViewOfFile(hMap, FILE_MAP_READ, 0,0, 0);
	if (0 == pView)
		{
		CERR << GetLastError() << ": error in MapViewOfFile()."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		CloseHandle(hMap);
		return;
		}
	DWORD	dwFileSizeHigh, dwFileSizeLo = GetFileSize(h, &dwFileSizeHigh);
	//----------------------------------------------------------------
	DWORD	dwHere = SetFilePointer(hOut, 0, 0, FILE_END);
	if ((DWORD)-1 == dwHere)
		{
		CERR << GetLastError() << ": error getting file pos."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		goto Cleanup;
		}
	dwOutSize = SetFilePointer(hOut, dwFileSizeLo, 0, FILE_CURRENT);
	if ((DWORD)-1 == dwOutSize)
		{
		CERR << GetLastError() << ": error extending file end."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		goto Cleanup;
		}
	if (!SetEndOfFile(hOut) )
		{
		CERR << GetLastError() << ": error setting new end of file."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		goto Cleanup;
		}
	//----------------------------------------------------------------
	dwMapFirst = dwHere & ~(0xffff);
	dwMapOffset = dwHere - dwMapFirst;

	hOutMap = CreateFileMapping(hOut, 0, PAGE_READWRITE,
						0, dwOutSize, 0);
	if (0 == hOutMap)
		{
		CERR << GetLastError() << ": error mapping output file."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		}
	pOut = MapViewOfFile(hOutMap, FILE_MAP_WRITE, 0, dwMapFirst,
		dwFileSizeLo + dwMapOffset);
	if (0 == pOut)
		{
		CERR << GetLastError() << ": error mapping view of output."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		goto CleanupWrite;
		}
	if (!WriteProcessMemory(GetCurrentProcess(),
		(void *)((char *)pOut + dwMapOffset),
		pView, dwFileSizeLo, 0) )
		{
		CERR << GetLastError() << ": error in WriteProcessMemory()."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		}
	if (!UnmapViewOfFile(pOut) )
		{
		CERR << GetLastError() << ": error unmapping output."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		}
	//----------------------------------------------------------------
CleanupWrite:
	CloseHandle(hOutMap);
Cleanup:
	UnmapViewOfFile(pView);
	CloseHandle(hMap);
}
//****************************************************************
void cat(HANDLE h, HANDLE hOut)
{
	char	szBuf[8192];
	DWORD	nBytes;
	while (ReadFile(h, szBuf, sizeof(szBuf), &nBytes, 0) && nBytes)
		{
		DWORD	nWritten;
		if (!WriteFile(hOut, szBuf, nBytes, &nWritten, 0) )
			{
			CERR << GetLastError() << ": error in WriteFile. "
				<< nBytes << " read, " << nWritten << " written."
				<< "Line " << __LINE__ << ", file " << __FILE__
				<< endl;
			// return;
			}
		}
}
//****************************************************************
int main(int argc, char **argv)
{
	if (argc < 2)
		{
		cat(GetStdHandle(STD_INPUT_HANDLE), GetStdHandle(STD_OUTPUT_HANDLE));
		return	0;
		}
	//----------------------------------------------------------------
	SYSTEMTIME	sNow;
	GetLocalTime(&sNow);
	CERR << sNow << "===> " << GetCommandLine() << endl;
	//----------------------------------------------------------------
	HANDLE	hStdout = CreateFile("testme.out",
		GENERIC_READ | GENERIC_WRITE,
		0,
		0,
		CREATE_ALWAYS,
		0,
		0);
	if (INVALID_HANDLE_VALUE == hStdout)
		{
		CERR << GetLastError() << ": error opening testme.out for writing."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		return	4;
		}
	if (FILE_TYPE_DISK != GetFileType(hStdout) )
		{
		CERR << "Can't use " << argv[0] << " for console i/o."
			<< "Line " << __LINE__ << ", file " << __FILE__
			<< endl;
		return	2;
		}
	if ((DWORD) -1 == SetFilePointer(hStdout, 0, 0, FILE_BEGIN) )
		{
		CERR << GetLastError() << ": error seeking to beginning of output."
			<< endl;
		return	4;
		}
	if (!SetEndOfFile(hStdout))
		{
		CERR	<< GetLastError() << ": error truncating output file."
			<< endl;
		return	4;
		}
	//----------------------------------------------------------------
	DWORD	dwStart = GetTickCount();
	for (int iArg = 1; iArg < argc; iArg++)
		{
		HANDLE	fp = CreateFile(argv[iArg], GENERIC_READ,
			FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
			OPEN_EXISTING, 0, 0);
		if (INVALID_HANDLE_VALUE == fp)
			{
			CERR << GetLastError() << ": error opening file "
				<< argv[iArg] << " for reading." << endl;
			continue;
			}

		cat2(fp, hStdout);
		CloseHandle(fp);
		}
	dwStart = GetTickCount( ) - dwStart;
 	CERR << "**** Total time: " << (dwStart / 1000)
		<< '.' << (dwStart % 1000) << " seconds."
		<< endl;
	return	0;
}


