Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

272 lines
6.2 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. dskimage.cpp
  5. Abstract:
  6. Tool to create images of floppy disks.
  7. NOTE: Currently used by WinPE image creation
  8. script for IA64 ISO CD image
  9. Author:
  10. Vijay Jayaseelan (vijayj) 12 March 2001
  11. Revision History:
  12. None.
  13. --*/
  14. #include <iostream>
  15. #include <string>
  16. #include <windows.h>
  17. #include "msg.h"
  18. #include <libmsg.h>
  19. //
  20. // Global variables used to get formatted message for this program.
  21. //
  22. HMODULE ThisModule = NULL;
  23. WCHAR Message[4096];
  24. //
  25. // Helper dump operators
  26. //
  27. inline
  28. std::ostream& operator<<(std::ostream &os, const std::wstring &str) {
  29. FILE *OutStream = (&os == &std::cerr) ? stderr : stdout;
  30. fputws(str.c_str(), OutStream);
  31. return os;
  32. }
  33. inline
  34. std::ostream& operator<<(std::ostream &os, PCTSTR str) {
  35. return os << std::wstring(str);
  36. }
  37. //
  38. // Exceptions
  39. //
  40. struct ProgramException : public std::exception {
  41. virtual void Dump(std::ostream &os) = 0;
  42. };
  43. //
  44. // Abstracts a Win32 error
  45. //
  46. struct W32Error : public ProgramException {
  47. DWORD ErrorCode;
  48. W32Error(DWORD ErrCode = GetLastError()) : ErrorCode(ErrCode){}
  49. void Dump(std::ostream &os) {
  50. WCHAR MsgBuffer[4096];
  51. MsgBuffer[0] = UNICODE_NULL;
  52. if (GetFormattedMessage(ThisModule,
  53. FALSE,
  54. MsgBuffer,
  55. sizeof(MsgBuffer)/sizeof(MsgBuffer[0]),
  56. ErrorCode)){
  57. std::wstring Msg(MsgBuffer);
  58. os << Msg;
  59. } else {
  60. os << std::hex << ErrorCode;
  61. }
  62. }
  63. };
  64. //
  65. // Invalid arguments
  66. //
  67. struct ProgramUsage : public ProgramException {
  68. std::wstring PrgUsage;
  69. ProgramUsage(const std::wstring &Usg) : PrgUsage(Usg) {}
  70. const char *what() const throw() {
  71. return "Program Usage exception";
  72. }
  73. void Dump(std::ostream &os) {
  74. os << PrgUsage << std::endl;
  75. }
  76. };
  77. //
  78. // Argument cracker
  79. //
  80. struct ProgramArguments {
  81. std::wstring DriveLetter;
  82. std::wstring ImageName;
  83. ProgramArguments(int Argc, wchar_t *Argv[]) {
  84. bool ValidArgs = false;
  85. bool ShowUsage = false;
  86. for (ULONG Index = 1; !ShowUsage && (Index < Argc); Index++) {
  87. ShowUsage = !_wcsicmp(Argv[Index], TEXT("/?"));
  88. }
  89. if (!ShowUsage && (Argc > 2)) {
  90. DriveLetter = Argv[1];
  91. ImageName = Argv[2];
  92. ValidArgs = ((DriveLetter.length() == 2) &&
  93. (DriveLetter[1] == TEXT(':')));
  94. }
  95. if (!ValidArgs) {
  96. throw new ProgramUsage(GetFormattedMessage( ThisModule,
  97. FALSE,
  98. Message,
  99. sizeof(Message)/sizeof(Message[0]),
  100. MSG_PGM_USAGE));
  101. }
  102. DriveLetter = TEXT("\\\\.\\") + DriveLetter;
  103. }
  104. friend std::ostream& operator<<(std::ostream &os, const ProgramArguments &Args) {
  105. os << GetFormattedMessage( ThisModule,
  106. FALSE,
  107. Message,
  108. sizeof(Message)/sizeof(Message[0]),
  109. MSG_DRVLETTER_AND_IMGNAME,
  110. Args.DriveLetter,
  111. Args.ImageName) << std::endl;
  112. return os;
  113. }
  114. };
  115. //
  116. // Prototypes
  117. //
  118. VOID
  119. CreateImage(
  120. IN const ProgramArguments &Args
  121. )
  122. {
  123. DWORD Error = ERROR_SUCCESS;
  124. //
  125. // Open the source file
  126. //
  127. HANDLE SourceHandle = CreateFile(Args.DriveLetter.c_str(),
  128. GENERIC_READ,
  129. FILE_SHARE_READ | FILE_SHARE_WRITE,
  130. NULL,
  131. OPEN_EXISTING,
  132. FILE_ATTRIBUTE_NORMAL,
  133. NULL);
  134. if (SourceHandle == INVALID_HANDLE_VALUE) {
  135. throw new W32Error();
  136. }
  137. //
  138. // Open the destination file
  139. //
  140. HANDLE DestHandle = CreateFile(Args.ImageName.c_str(),
  141. GENERIC_WRITE,
  142. 0,
  143. NULL,
  144. CREATE_ALWAYS,
  145. FILE_ATTRIBUTE_NORMAL,
  146. NULL);
  147. if (DestHandle == INVALID_HANDLE_VALUE) {
  148. Error = GetLastError();
  149. CloseHandle(SourceHandle);
  150. throw new W32Error(Error);
  151. }
  152. //
  153. // Read contents of the source and write it to destination
  154. //
  155. LPBYTE lpBuffer = NULL;
  156. DWORD BufferSize = 64 * 1024;
  157. DWORD BytesRead = 0, BytesWritten = 0;
  158. LONGLONG TotalBytesWritten = 0;
  159. lpBuffer = (LPBYTE) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, BufferSize );
  160. if ( lpBuffer )
  161. {
  162. while (ReadFile(SourceHandle, lpBuffer, BufferSize, &BytesRead, NULL) &&
  163. BytesRead &&
  164. WriteFile(DestHandle, lpBuffer, BytesRead, &BytesWritten, NULL) &&
  165. (BytesRead == BytesWritten))
  166. {
  167. TotalBytesWritten += BytesWritten;
  168. BytesRead = BytesWritten = 0;
  169. }
  170. HeapFree( GetProcessHeap(), 0, lpBuffer);
  171. }
  172. //
  173. // Cleanup
  174. //
  175. Error = GetLastError();
  176. CloseHandle(SourceHandle);
  177. CloseHandle(DestHandle);
  178. //
  179. // Check, if the operation was successful ?
  180. //
  181. if (!TotalBytesWritten || (BytesRead != BytesWritten)) {
  182. throw new W32Error(Error);
  183. }
  184. }
  185. //
  186. // Main entry point
  187. //
  188. INT
  189. __cdecl
  190. wmain(
  191. IN INT Argc,
  192. IN WCHAR *Argv[]
  193. )
  194. {
  195. INT Result = 0;
  196. ThisModule = GetModuleHandle(NULL);
  197. try {
  198. ProgramArguments Args(Argc, Argv);
  199. CreateImage(Args);
  200. }
  201. catch(W32Error *Error) {
  202. if (Error) {
  203. Result = (INT)(Error->ErrorCode);
  204. Error->Dump(std::cout);
  205. delete Error;
  206. }
  207. }
  208. catch(ProgramException *Exp) {
  209. if (Exp) {
  210. Exp->Dump(std::cout);
  211. delete Exp;
  212. }
  213. }
  214. catch(...) {
  215. Result = 1;
  216. }
  217. return Result;
  218. }