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.

306 lines
9.9 KiB

  1. #include "diskcopy.h"
  2. #include "ids.h"
  3. #include "help.h"
  4. #include "makeboot.h"
  5. // todo: add check that we can only make boot disks on 3.5 disks
  6. UINT _GetClassFromCP (UINT iOEMCP)
  7. {
  8. for (int i = 0; i < ARRAYSIZE(rgCPtoClassMap); i++)
  9. {
  10. if (iOEMCP == rgCPtoClassMap[i].iCP)
  11. {
  12. return rgCPtoClassMap[i].iClass;
  13. }
  14. }
  15. return 0; // default
  16. }
  17. UINT _GetKBFromLangId(WORD wLangId)
  18. {
  19. for (int i = 0; i < ARRAYSIZE(rgLangIdtoKBMap); i++)
  20. {
  21. if (wLangId == rgLangIdtoKBMap[i].wLangId)
  22. {
  23. return rgLangIdtoKBMap[i].iKB;
  24. }
  25. }
  26. // if we don't get an exact match, try to match just the primary lang id
  27. for (int i = 0; i < ARRAYSIZE(rgLangIdtoKBMap); i++)
  28. {
  29. if (PRIMARYLANGID(wLangId) == PRIMARYLANGID(rgLangIdtoKBMap[i].wLangId))
  30. {
  31. return rgLangIdtoKBMap[i].iKB;
  32. }
  33. }
  34. // if all else fails, default to US keyboard
  35. return KEYBOARD_US;
  36. }
  37. UINT _GetClassFromKB (UINT iKB)
  38. {
  39. for (int i = 0; i < ARRAYSIZE(rgKBtoClassMap); i++)
  40. {
  41. if (iKB == rgKBtoClassMap[i].iKB)
  42. {
  43. return rgKBtoClassMap[i].iClass;
  44. }
  45. }
  46. return KBCLASS_1; // default
  47. }
  48. BOOL _GetKeyboardID(UINT iKB, UINT* piID)
  49. {
  50. BOOL fRet = FALSE;
  51. switch (iKB)
  52. {
  53. case KEYBOARD_HE:
  54. *piID = 400;
  55. fRet = TRUE;
  56. break;
  57. case KEYBOARD_TR:
  58. *piID = 179;
  59. fRet = TRUE;
  60. break;
  61. }
  62. return fRet;
  63. }
  64. typedef struct {
  65. UINT OEMCP;
  66. UINT KB;
  67. } LANGSETTINGS;
  68. HRESULT _GetAutoexecOEMCP(HINSTANCE hInstance, LANGSETTINGS* pls, LPSTR pszBuffer, UINT cchBuffer)
  69. {
  70. wsprintfA(pszBuffer, "%d", pls->OEMCP);
  71. return S_OK;
  72. }
  73. HRESULT _GetAutoexecEGAFname(HINSTANCE hInstance, LANGSETTINGS* pls, LPSTR pszBuffer, UINT cchBuffer)
  74. {
  75. LoadStringA(hInstance, IDS_DOSBOOTDISK_AUTOEXEC_EGA_1 + _GetClassFromCP(pls->OEMCP), pszBuffer, cchBuffer);
  76. return S_OK;
  77. }
  78. HRESULT _GetConfigSysEGA(HINSTANCE hInstance, LANGSETTINGS* pls, LPSTR pszBuffer, UINT cchBuffer)
  79. {
  80. LoadStringA(hInstance, IDS_DOSBOOTDISK_CONFIG_EGA_1 + _GetClassFromCP(pls->OEMCP), pszBuffer, cchBuffer);
  81. return S_OK;
  82. }
  83. HRESULT _GetAutoexecKeybCode(HINSTANCE hInstance, LANGSETTINGS* pls, LPSTR pszBuffer, UINT cchBuffer)
  84. {
  85. LoadStringA(hInstance, IDS_DOSBOOTDISK_KEYBOARD_CODE_US + pls->KB, pszBuffer, cchBuffer);
  86. return S_OK;
  87. }
  88. HRESULT _GetAutoexecKeybFname(HINSTANCE hInstance, LANGSETTINGS* pls, LPSTR pszBuffer, UINT cchBuffer)
  89. {
  90. LoadStringA(hInstance, IDS_DOSBOOTDISK_KEYBOARD_FNAME_1 + _GetClassFromKB(pls->KB), pszBuffer, cchBuffer);
  91. return S_OK;
  92. }
  93. HRESULT _GetConfigKeybID(HINSTANCE hInstance, LANGSETTINGS* pls, LPSTR pszBuffer, UINT cchBuffer)
  94. {
  95. HRESULT hr = E_FAIL;
  96. UINT iID;
  97. if (_GetKeyboardID(pls->KB, &iID))
  98. {
  99. wsprintfA(pszBuffer, "%d", iID);
  100. hr = S_OK;
  101. }
  102. return hr;
  103. }
  104. HANDLE _CreateSystemFile(HINSTANCE hInstance, UINT iDrive, UINT id)
  105. {
  106. TCHAR szFname[MAX_PATH];
  107. LoadString(hInstance, id, szFname, ARRAYSIZE(szFname));
  108. TCHAR szPath[MAX_PATH];
  109. PathBuildRoot(szPath, iDrive);
  110. PathAppend(szPath, szFname);
  111. return CreateFile(szPath, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  112. }
  113. HRESULT _WriteAutoexec(HINSTANCE hInstance, UINT iDrive, LANGSETTINGS* pls)
  114. {
  115. HRESULT hr = E_FAIL;
  116. HANDLE hFile = _CreateSystemFile(hInstance, iDrive, IDS_DOSBOOTDISK_AUTOEXEC_FNAME);
  117. if (INVALID_HANDLE_VALUE != hFile)
  118. {
  119. if (437 != pls->OEMCP && // use empty autoexec.bat on US locale
  120. 932 != pls->OEMCP && // use empty autoexec.bat on Japanese locale
  121. 949 != pls->OEMCP && // use empty autoexec.bat on Korean locale
  122. 936 != pls->OEMCP && // use empty autoexec.bat on CHS locale
  123. 950 != pls->OEMCP) // use empty autoexec.bat on CHT locale
  124. {
  125. CHAR aszBufferOEMCP[4];
  126. CHAR aszBufferEGAFname[13];
  127. CHAR aszBufferKeybCode[3];
  128. CHAR aszBufferKeybFname[13];
  129. if (SUCCEEDED(_GetAutoexecOEMCP(hInstance, pls, aszBufferOEMCP, ARRAYSIZE(aszBufferOEMCP))) &&
  130. SUCCEEDED(_GetAutoexecEGAFname(hInstance, pls, aszBufferEGAFname, ARRAYSIZE(aszBufferEGAFname))) &&
  131. SUCCEEDED(_GetAutoexecKeybCode(hInstance, pls, aszBufferKeybCode, ARRAYSIZE(aszBufferKeybCode))) &&
  132. SUCCEEDED(_GetAutoexecKeybFname(hInstance, pls, aszBufferKeybFname, ARRAYSIZE(aszBufferKeybFname))))
  133. {
  134. CHAR aszTemplate[1000];
  135. CHAR aszKeyboardID[5];
  136. if (SUCCEEDED(_GetConfigKeybID(hInstance, pls, aszKeyboardID, ARRAYSIZE(aszKeyboardID))))
  137. {
  138. LoadStringA(hInstance, IDS_DOSBOOTDISK_AUTOEXEC_TEMPLATE_WITH_CODE, aszTemplate, ARRAYSIZE(aszTemplate));
  139. }
  140. else
  141. {
  142. LoadStringA(hInstance, IDS_DOSBOOTDISK_AUTOEXEC_TEMPLATE, aszTemplate, ARRAYSIZE(aszTemplate));
  143. }
  144. CHAR aszBuffer[1000];
  145. wsprintfA(aszBuffer, aszTemplate,
  146. aszBufferOEMCP, aszBufferEGAFname, aszBufferOEMCP, aszBufferKeybCode, aszBufferKeybFname, aszKeyboardID);
  147. DWORD cbWritten;
  148. WriteFile(hFile, aszBuffer, sizeof(CHAR) * lstrlenA(aszBuffer), &cbWritten, NULL);
  149. hr = S_OK;
  150. }
  151. }
  152. CloseHandle(hFile);
  153. }
  154. return hr;
  155. }
  156. HRESULT _WriteConfigSys(HINSTANCE hInstance, UINT iDrive, LANGSETTINGS* pls)
  157. {
  158. HRESULT hr = E_FAIL;
  159. HANDLE hFile = _CreateSystemFile(hInstance, iDrive, IDS_DOSBOOTDISK_CONFIG_FNAME);
  160. if (INVALID_HANDLE_VALUE != hFile)
  161. {
  162. if (437 != pls->OEMCP && // use empty config.sys on US locale
  163. 932 != pls->OEMCP && // use empty config.sys on Japanese locale
  164. 949 != pls->OEMCP && // use empty config.sys on Korean locale
  165. 936 != pls->OEMCP && // use empty config.sys on CHS locale
  166. 950 != pls->OEMCP) // use empty config.sys on CHT locale
  167. {
  168. CHAR aszTemplate[1000];
  169. CHAR aszBufferEGA[64];
  170. if (LoadStringA(hInstance, IDS_DOSBOOTDISK_CONFIG_TEMPLATE, aszTemplate, ARRAYSIZE(aszTemplate)) &&
  171. SUCCEEDED(_GetConfigSysEGA(hInstance, pls, aszBufferEGA, ARRAYSIZE(aszBufferEGA))))
  172. {
  173. CHAR aszBuffer[1000];
  174. wsprintfA(aszBuffer, aszTemplate, aszBufferEGA);
  175. DWORD cbWritten;
  176. WriteFile(hFile, aszBuffer, sizeof(CHAR) * lstrlenA(aszBuffer), &cbWritten, NULL);
  177. hr = S_OK;
  178. }
  179. }
  180. CloseHandle(hFile);
  181. }
  182. return hr;
  183. }
  184. HRESULT _LoadUISettings (LANGSETTINGS* pls)
  185. {
  186. pls->OEMCP = GetOEMCP();
  187. pls->KB = _GetKBFromLangId(LOWORD(GetKeyboardLayout(0)));
  188. if (KBCLASS_BLANK == _GetClassFromKB(pls->KB))
  189. {
  190. pls->KB = _GetKBFromLangId(GetSystemDefaultUILanguage());
  191. }
  192. return S_OK;
  193. }
  194. HRESULT _WriteDiskImage(HINSTANCE hInstance, UINT iDrive, BOOL* pfCancelled, FMIFS_CALLBACK pCallback)
  195. {
  196. HRESULT hr = E_FAIL;
  197. HRSRC hrsrc = FindResourceW(hInstance, MAKEINTRESOURCEW(IDX_DOSBOOTDISK), L"BINFILE");
  198. if (hrsrc)
  199. {
  200. HGLOBAL hglob = LoadResource(hInstance, hrsrc);
  201. if (hglob)
  202. {
  203. BYTE* pbPtr = (BYTE*)hglob;
  204. DWORD cbGlob = SizeofResource(hInstance, hrsrc);
  205. TCHAR szDrive[] = TEXT("\\\\.\\a:");
  206. szDrive[4] += (TCHAR)iDrive;
  207. HANDLE hFloppyDrive = CreateFile(szDrive, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  208. OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_WRITE_THROUGH, NULL );
  209. if (INVALID_HANDLE_VALUE == hFloppyDrive)
  210. {
  211. pCallback(FmIfsAccessDenied, 0, NULL);
  212. }
  213. else
  214. {
  215. hr = S_OK;
  216. CHAR TrackBuffer[TRACK_SIZE];
  217. DWORD cBytesRead = 0;
  218. DWORD cBytesWritten = 0;
  219. INT iCurrentTrack;
  220. for( iCurrentTrack = 0; iCurrentTrack < TRACKS_ON_DISK && SUCCEEDED(hr) && !*pfCancelled; iCurrentTrack++ )
  221. {
  222. DWORD cbRead;
  223. cbRead = (cbGlob > TRACK_SIZE) ? TRACK_SIZE : cbGlob;
  224. memcpy(TrackBuffer, pbPtr, cbRead);
  225. pbPtr += cbRead;
  226. cbGlob -= cbRead;
  227. if( ! WriteFile( hFloppyDrive, TrackBuffer, cbRead, &cBytesWritten, NULL ) )
  228. {
  229. pCallback(FmIfsIoError, 0, NULL);
  230. hr = E_FAIL;
  231. }
  232. else
  233. {
  234. FMIFS_PERCENT_COMPLETE_INFORMATION pci;
  235. pci.PercentCompleted = (100 * iCurrentTrack) / TRACKS_ON_DISK;
  236. pCallback(FmIfsPercentCompleted, sizeof(FMIFS_PERCENT_COMPLETE_INFORMATION), &pci);
  237. }
  238. }
  239. CloseHandle(hFloppyDrive);
  240. }
  241. FreeResource(hglob);
  242. }
  243. }
  244. return hr;
  245. }
  246. HRESULT MakeBootDisk(HINSTANCE hInstance, UINT iDrive, BOOL* pfCancelled, FMIFS_CALLBACK pCallback)
  247. {
  248. HRESULT hr = _WriteDiskImage(hInstance, iDrive, pfCancelled, pCallback);
  249. // if we didn't cancel or fail, then place autoexec.bat and config.sys on the disk as well
  250. if (SUCCEEDED(hr) && !*pfCancelled)
  251. {
  252. LANGSETTINGS ls;
  253. _LoadUISettings(&ls);
  254. _WriteAutoexec(hInstance, iDrive, &ls);
  255. _WriteConfigSys(hInstance, iDrive, &ls);
  256. FMIFS_FINISHED_INFORMATION pfi;
  257. pfi.Success = TRUE;
  258. pCallback(FmIfsFinished, sizeof(FMIFS_FINISHED_INFORMATION), &pfi);
  259. }
  260. return hr;
  261. }