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.

303 lines
6.8 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. sys.cpp
  5. Abstract:
  6. Writes WinME boot sector to local hard disk.
  7. Author:
  8. Adrian Cosma (acosma)
  9. Revision History:
  10. July 11, 2001 - Created
  11. --*/
  12. #include <new.h> // for MyNewHandler
  13. #include <iostream>
  14. #include <string>
  15. #include <vector>
  16. #include <9xboot32.h>
  17. #include <bootf32.h>
  18. #include "sys.h"
  19. //
  20. // Define a function to be called if new fails to allocate memory.
  21. //
  22. int __cdecl MyNewHandler( size_t size )
  23. {
  24. wprintf(L"Memory allocation failed. Exiting program.\n");
  25. // Exit program
  26. //
  27. throw new W32Error();
  28. }
  29. //
  30. // usage
  31. //
  32. std::wstring Usage = TEXT("sys.exe [/?] [/xp] drive-letter:\nExample: sys.exe c:");
  33. //
  34. // Invalid arguments
  35. //
  36. struct ProgramUsage : public ProgramException {
  37. std::wstring PrgUsage;
  38. ProgramUsage(const std::wstring &Usg) : PrgUsage(Usg) {}
  39. const char *what() const throw() {
  40. return "Program Usage exception";
  41. }
  42. void Dump(std::ostream &os) {
  43. os << Usage << std::endl;
  44. }
  45. };
  46. //
  47. // Missing files
  48. //
  49. struct FileMissing : public ProgramException {
  50. std::wstring Message;
  51. FileMissing(std::wstring Msg) : Message(Msg) {}
  52. const char *what() const throw() {
  53. return "File missing exception";
  54. }
  55. void Dump(std::ostream &os) {
  56. os << TEXT("Error: ") << Message << std::endl;
  57. }
  58. };
  59. //
  60. // Wrong filesystem.
  61. //
  62. struct FileSystem : public ProgramException {
  63. std::wstring Message;
  64. FileSystem(std::wstring Msg) : Message(Msg) {}
  65. const char *what() const throw() {
  66. return "Unsupported filesystem exception";
  67. }
  68. void Dump(std::ostream &os) {
  69. os << Message << std::endl;
  70. }
  71. };
  72. //
  73. // Argument cracker
  74. //
  75. struct ProgramArguments
  76. {
  77. std::wstring DriveLetter;
  78. bool bXPBootSector; // TRUE for XP boot sector, FALSE for 9x boot sector.
  79. ProgramArguments(int Argc, wchar_t *Argv[])
  80. {
  81. bool ValidArgs = true;
  82. bXPBootSector = false;
  83. for (ULONG Index = 1; ValidArgs && (Index < Argc); Index++)
  84. {
  85. ValidArgs = false;
  86. // Find all the arguments that start with "/"
  87. //
  88. if ( TEXT('/') == Argv[Index][0] )
  89. {
  90. if ( !bXPBootSector && !_wcsicmp(Argv[Index], TEXT("/xp")) )
  91. {
  92. bXPBootSector = true;
  93. ValidArgs = true;
  94. }
  95. }
  96. else // Process arguments without the "/". Must be the drive letter.
  97. {
  98. DriveLetter = Argv[Index];
  99. ValidArgs = ((DriveLetter.length() == 2) &&
  100. (DriveLetter[1] == TEXT(':')));
  101. }
  102. }
  103. if (!ValidArgs)
  104. {
  105. throw new ProgramUsage(Usage);
  106. }
  107. DriveLetter = TEXT("\\\\.\\") + DriveLetter;
  108. }
  109. friend std::ostream& operator<<(std::ostream &os, const ProgramArguments &Args)
  110. {
  111. os << TEXT("DriveLetter : ") << Args.DriveLetter << std::endl;
  112. return os;
  113. }
  114. };
  115. // Verify that this partition is ready to be sys-ed.
  116. //
  117. VOID VerifyPartition(CDrive &Disk, ProgramArguments Args)
  118. {
  119. TCHAR szFileSystemNameBuffer[20] = TEXT("");
  120. std::vector<LPTSTR> FileNames;
  121. std::vector<LPTSTR>::iterator i;
  122. if ( Args.bXPBootSector )
  123. {
  124. FileNames.push_back(TEXT("ntdetect.com"));
  125. FileNames.push_back(TEXT("ntldr"));
  126. }
  127. else
  128. {
  129. FileNames.push_back(TEXT("io.sys"));
  130. FileNames.push_back(TEXT("msdos.sys"));
  131. FileNames.push_back(TEXT("command.com"));
  132. }
  133. // Make sure that io.sys and msdos.sys and command.com are there on the root.
  134. //
  135. std::wstring Temp;
  136. for (i = FileNames.begin(); i < FileNames.end(); i++)
  137. {
  138. Temp = Args.DriveLetter + TEXT("\\");
  139. Temp += *i;
  140. if ( 0xFFFFFFFF == GetFileAttributes(Temp.c_str()) )
  141. {
  142. // Re-use the Temp string to put the error message in.
  143. //
  144. Temp = *i;
  145. Temp += TEXT(" is not present on the root of the drive specified.");
  146. throw new FileMissing(Temp);
  147. }
  148. }
  149. // Verify that this partition is FAT32. Only handling FAT32 partitions at this point.
  150. //
  151. Temp = Args.DriveLetter + TEXT("\\");
  152. // If the filesystem is not FAT32 then trow an exception.
  153. //
  154. if ( !(GetVolumeInformation(Temp.c_str(), NULL, 0, NULL, NULL, NULL, szFileSystemNameBuffer, sizeof (szFileSystemNameBuffer)/sizeof (szFileSystemNameBuffer[0])) &&
  155. (CSTR_EQUAL == CompareString( LOCALE_INVARIANT,
  156. NORM_IGNORECASE,
  157. szFileSystemNameBuffer,
  158. -1,
  159. TEXT("FAT32"),
  160. -1 ))) )
  161. {
  162. throw new FileSystem(TEXT("The target filesystem is not formatted FAT32."));
  163. }
  164. }
  165. VOID Sys(CDrive &Disk, ProgramArguments &Args)
  166. {
  167. PBYTE pBuffer = NULL;
  168. PBYTE pBootRecord = NULL; // Need a pointer to the boot record.
  169. if ( Args.bXPBootSector )
  170. {
  171. pBootRecord = Fat32BootCode;
  172. }
  173. else
  174. {
  175. pBootRecord = Fat32BootCode9x;
  176. }
  177. // Read the 1st sector of the disk in order to get the BPB
  178. //
  179. Disk.ReadBootRecord(Args.DriveLetter.c_str(), 1, &pBuffer);
  180. // Copy the old BPB to our boot record.
  181. //
  182. memcpy(&pBootRecord[11], &pBuffer[11], 79);
  183. // Delete the buffer allocated by ReadBootRecord.
  184. //
  185. delete [] pBuffer;
  186. // Write out the boot record.
  187. //
  188. if ( Args.bXPBootSector )
  189. {
  190. Disk.WriteBootRecordXP(Args.DriveLetter.c_str(), sizeof(Fat32BootCode9x) / SECTOR_SIZE, &pBootRecord);
  191. }
  192. else
  193. {
  194. Disk.WriteBootRecord(Args.DriveLetter.c_str(), sizeof(Fat32BootCode9x) / SECTOR_SIZE, &pBootRecord);
  195. }
  196. std::cout << TEXT("Done.") << std::endl;
  197. }
  198. //
  199. // wmain() entry point
  200. //
  201. int
  202. _cdecl
  203. wmain(
  204. int Argc,
  205. wchar_t *Argv[]
  206. )
  207. {
  208. INT Result = 0;
  209. _set_new_handler( MyNewHandler ); // handles PREFIX issues
  210. try
  211. {
  212. CDrive Disk;
  213. ProgramArguments Args(Argc, Argv);
  214. if ( S_OK != Disk.Initialize(Args.DriveLetter.c_str()))
  215. {
  216. throw new W32Error();
  217. }
  218. VerifyPartition(Disk, Args);
  219. Sys(Disk, Args);
  220. }
  221. catch(W32Error *Error)
  222. {
  223. if (Error)
  224. {
  225. Result = (INT)(Error->ErrorCode);
  226. Error->Dump(std::cout);
  227. delete Error;
  228. }
  229. }
  230. catch(ProgramException *Exp)
  231. {
  232. if (Exp)
  233. {
  234. Exp->Dump(std::cout);
  235. delete Exp;
  236. }
  237. }
  238. catch(...)
  239. {
  240. Result = 1;
  241. return Result;
  242. }
  243. return Result;
  244. }