windows-nt/Source/XPSP1/NT/base/ntsetup/opktools/dskimage/dskimage.cpp
2020-09-26 16:20:57 +08:00

273 lines
6.2 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
dskimage.cpp
Abstract:
Tool to create images of floppy disks.
NOTE: Currently used by WinPE image creation
script for IA64 ISO CD image
Author:
Vijay Jayaseelan (vijayj) 12 March 2001
Revision History:
None.
--*/
#include <iostream>
#include <string>
#include <windows.h>
#include "msg.h"
#include <libmsg.h>
//
// Global variables used to get formatted message for this program.
//
HMODULE ThisModule = NULL;
WCHAR Message[4096];
//
// Helper dump operators
//
inline
std::ostream& operator<<(std::ostream &os, const std::wstring &str) {
FILE *OutStream = (&os == &std::cerr) ? stderr : stdout;
fputws(str.c_str(), OutStream);
return os;
}
inline
std::ostream& operator<<(std::ostream &os, PCTSTR str) {
return os << std::wstring(str);
}
//
// Exceptions
//
struct ProgramException : public std::exception {
virtual void Dump(std::ostream &os) = 0;
};
//
// Abstracts a Win32 error
//
struct W32Error : public ProgramException {
DWORD ErrorCode;
W32Error(DWORD ErrCode = GetLastError()) : ErrorCode(ErrCode){}
void Dump(std::ostream &os) {
WCHAR MsgBuffer[4096];
MsgBuffer[0] = UNICODE_NULL;
if (GetFormattedMessage(ThisModule,
FALSE,
MsgBuffer,
sizeof(MsgBuffer)/sizeof(MsgBuffer[0]),
ErrorCode)){
std::wstring Msg(MsgBuffer);
os << Msg;
} else {
os << std::hex << ErrorCode;
}
}
};
//
// Invalid arguments
//
struct ProgramUsage : public ProgramException {
std::wstring PrgUsage;
ProgramUsage(const std::wstring &Usg) : PrgUsage(Usg) {}
const char *what() const throw() {
return "Program Usage exception";
}
void Dump(std::ostream &os) {
os << PrgUsage << std::endl;
}
};
//
// Argument cracker
//
struct ProgramArguments {
std::wstring DriveLetter;
std::wstring ImageName;
ProgramArguments(int Argc, wchar_t *Argv[]) {
bool ValidArgs = false;
bool ShowUsage = false;
for (ULONG Index = 1; !ShowUsage && (Index < Argc); Index++) {
ShowUsage = !_wcsicmp(Argv[Index], TEXT("/?"));
}
if (!ShowUsage && (Argc > 2)) {
DriveLetter = Argv[1];
ImageName = Argv[2];
ValidArgs = ((DriveLetter.length() == 2) &&
(DriveLetter[1] == TEXT(':')));
}
if (!ValidArgs) {
throw new ProgramUsage(GetFormattedMessage( ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_PGM_USAGE));
}
DriveLetter = TEXT("\\\\.\\") + DriveLetter;
}
friend std::ostream& operator<<(std::ostream &os, const ProgramArguments &Args) {
os << GetFormattedMessage( ThisModule,
FALSE,
Message,
sizeof(Message)/sizeof(Message[0]),
MSG_DRVLETTER_AND_IMGNAME,
Args.DriveLetter,
Args.ImageName) << std::endl;
return os;
}
};
//
// Prototypes
//
VOID
CreateImage(
IN const ProgramArguments &Args
)
{
DWORD Error = ERROR_SUCCESS;
//
// Open the source file
//
HANDLE SourceHandle = CreateFile(Args.DriveLetter.c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (SourceHandle == INVALID_HANDLE_VALUE) {
throw new W32Error();
}
//
// Open the destination file
//
HANDLE DestHandle = CreateFile(Args.ImageName.c_str(),
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (DestHandle == INVALID_HANDLE_VALUE) {
Error = GetLastError();
CloseHandle(SourceHandle);
throw new W32Error(Error);
}
//
// Read contents of the source and write it to destination
//
LPBYTE lpBuffer = NULL;
DWORD BufferSize = 64 * 1024;
DWORD BytesRead = 0, BytesWritten = 0;
LONGLONG TotalBytesWritten = 0;
lpBuffer = (LPBYTE) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, BufferSize );
if ( lpBuffer )
{
while (ReadFile(SourceHandle, lpBuffer, BufferSize, &BytesRead, NULL) &&
BytesRead &&
WriteFile(DestHandle, lpBuffer, BytesRead, &BytesWritten, NULL) &&
(BytesRead == BytesWritten))
{
TotalBytesWritten += BytesWritten;
BytesRead = BytesWritten = 0;
}
HeapFree( GetProcessHeap(), 0, lpBuffer);
}
//
// Cleanup
//
Error = GetLastError();
CloseHandle(SourceHandle);
CloseHandle(DestHandle);
//
// Check, if the operation was successful ?
//
if (!TotalBytesWritten || (BytesRead != BytesWritten)) {
throw new W32Error(Error);
}
}
//
// Main entry point
//
INT
__cdecl
wmain(
IN INT Argc,
IN WCHAR *Argv[]
)
{
INT Result = 0;
ThisModule = GetModuleHandle(NULL);
try {
ProgramArguments Args(Argc, Argv);
CreateImage(Args);
}
catch(W32Error *Error) {
if (Error) {
Result = (INT)(Error->ErrorCode);
Error->Dump(std::cout);
delete Error;
}
}
catch(ProgramException *Exp) {
if (Exp) {
Exp->Dump(std::cout);
delete Exp;
}
}
catch(...) {
Result = 1;
}
return Result;
}