#define _PORTABLE_32BIT_CONTEXT


#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <ctype.h>

#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <commdlg.h>
#include <shellapi.h>
#include <stdarg.h>
#include <memory.h>
#include <mmreg.h>
#include <msacm.h>
#include <winuser.h>

extern int optind;
void merror(char *msg, int quit);
void usage(char *msg);
extern char getopt( int	argc, char	*argv[], char *format );

void usage(char *msg)
{
	fprintf(stderr, "usage: %s [-b] [-s skip] drive\n\n", msg);
	fprintf(stderr, "Try %s \\\\.\\PHYSICALDRIVE2\n", msg);
	fprintf(stderr, "Try %s \\\\.\\C:\n", msg);
	exit(1);
}

void merror(char *msg, int quit)
{
 	char * lpMsgBuf;

	FormatMessage(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			(LPTSTR) &lpMsgBuf,
			0,
			NULL
		);

	/* Display the string.	*/
//	MessageBox( NULL, lpMsgBuf,
//		msg, MB_OK|MB_ICONINFORMATION );

	fprintf( stderr, "%s: %s", msg, lpMsgBuf );

	LocalFree( lpMsgBuf );

	if (quit) exit(1);
}


int main( int argc, char **argv )
{
	extern char     *optarg;
	extern int      optind,opterr;

	HANDLE	hf;
	char	buffer[512], *b;
	LPVOID	lpBuffer=buffer;
	DWORD	i,n;
	int		option;
	int		binary=0;
	LONG	skip=0;
	BOOL	err;


	while(( option = getopt(argc, argv, "bhs:"))!=EOF )
	{
		switch(option)
		{
			case 's':
				skip = strtol(optarg, NULL, 0);
				break;

			case 'b':
				binary=1;
				break;

			default:
				usage(argv[0]);
				break;
		}
	}

	if ( argv[optind] )
	{

		hf = CreateFile(
			(LPCTSTR) argv[optind],
			GENERIC_READ,
			0, /* Not shared */
			NULL, /* Not inherited by child processes */
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
			NULL
			);

		if ( hf == INVALID_HANDLE_VALUE )
		{
			fprintf(stderr,"%s\n", argv[optind]);
			merror("CreateFile", 1);
		}
		else
		{
			if ( skip != 0 )
			{
				fprintf(stderr,"lseek: %d\n",skip);
				if ( 0xFFFFFFFF == SetFilePointer(
				hf,
				skip,
				NULL,
				FILE_BEGIN))
				{
					merror("lseek",1);
				}
			}

			if ( binary )
			{
				/*
				 * braindamage all over
				 */

				if( -1 == _setmode( _fileno( stdout ), _O_BINARY ))
					merror("Can't set stdout mode to binary", 1);

				while ( (err = ReadFile(	hf,
									lpBuffer,
									sizeof(buffer),
									(LPDWORD)&n,
									NULL ))
						&& n!=0
					)
					fwrite( buffer, 1, (size_t)n, stdout );
			}
			else
			{
				while ( (err = ReadFile(	hf,
									lpBuffer,
									sizeof(buffer),
									(LPDWORD)&n,
									NULL ))
						&& n!=0
					)
				for ( i=0, b=buffer; b < buffer + n ; i = (i++)%16, b++ )
				{
					printf( i == 15 ? "%c\n" : "%c", isprint(*b) ? *b : '?' );
				}
			}

			if ( err && (n==0) )
			{
				fprintf(stderr,"EOF\n");
			}
			else
			{
				merror("end", FALSE);
				CloseHandle(hf);
			}
		}

	}
	else
		usage(argv[0]);

	return 0;
}