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.

325 lines
9.9 KiB

  1. #include <windows.h>
  2. #include <ntverp.h>
  3. #include <winbase.h> // for GetCommandLine
  4. #include "datasrc.h"
  5. #include "autorun.h"
  6. #include "util.h"
  7. #include "resource.h"
  8. //////////////////////////////////////////////////////////////////////
  9. // Construction/Destruction
  10. //////////////////////////////////////////////////////////////////////
  11. CDataSource::CDataSource()
  12. {
  13. m_iItems = 0;
  14. }
  15. CDataSource::~CDataSource()
  16. {
  17. }
  18. CDataItem & CDataSource::operator[](int i)
  19. {
  20. return m_data[m_piScreen[i]];
  21. }
  22. /*
  23. 10.05.96 Shunichi Kajisa (shunk) Support NEC PC-98
  24. 1. Determine if autorun is running on PC-98 or regular PC/AT by:
  25. bNEC98 = (HIBYTE(LOWORD(GetKeyboardType(1))) == 0x0D)? TRUE : FALSE;
  26. Following description is from KB Q130054, and this can be applied on NT and Win95:
  27. If an application uses the GetKeyboardType API, it can get OEM ID by
  28. specifying "1" (keyboard subtype) as argument of the function. Each OEM ID
  29. is listed here:
  30. OEM Windows OEM ID
  31. ------------------------------
  32. Microsoft 00H (DOS/V)
  33. ....
  34. NEC 0DH
  35. 2. If autorun is running on PC-98, replace every "I386" resource with "PC98" at runtime,
  36. regardless that autorun is running on NT or Win95.
  37. Notes:
  38. - NEC PC-98 is available only in Japan.
  39. - NEC PC-98 uses x86 processor, but the underlaying hardware architecture is different.
  40. The PC98 files is stored under CD:\pc98 directory instead of CD:\i386.
  41. - There was an idea that we should detect PC-98 in SHELL32.DLL, and treat PC98 as a different
  42. platform, like having [AutoRun.Pc98] section in NT CD's autorun.inf. We don't do this, since
  43. Win95 doesn't support this, and we don't want to introduce the apps incompatibility.
  44. In any case, if app has any dependency on the hardware and needs to do any special things,
  45. the app should detect the hardware and OS. This is separate issue from Autorun.exe.
  46. */
  47. BOOL CDataSource::IsNec98()
  48. {
  49. return ((GetKeyboardType(0) == 7) && ((GetKeyboardType(1) & 0xff00) == 0x0d00));
  50. }
  51. // Init
  52. //
  53. // For autorun we read all the items out of the resources.
  54. BOOL CDataSource::Init(LPSTR pszCommandLine)
  55. {
  56. // read the text for the items from the resources
  57. HINSTANCE hinst = GetModuleHandle(NULL);
  58. TCHAR szModuleName[MAX_PATH];
  59. szModuleName[0] = TEXT('\0'); // in case GetModuleFileName fails to initialize szModuleName
  60. GetModuleFileName(hinst, szModuleName, ARRAYSIZE(szModuleName)); // ex: "e:\i386\autorun.exe" or "e:\setup.exe"
  61. PathRemoveFilespec(szModuleName); // ex: "e:\i386\" or "e:\"
  62. PathAppend(szModuleName, TEXT("winnt32.exe")); //
  63. if ( PathFileExists(szModuleName) )
  64. {
  65. // we were launched from the platform directory, use szModuleName as the winnt32 path
  66. }
  67. else
  68. {
  69. // we were launched from the root. Append either "alpha", "i386", or "NEC98" to the path.
  70. SYSTEM_INFO si;
  71. PathRemoveFilespec(szModuleName);
  72. GetSystemInfo(&si);
  73. #if !(defined(_X86_) || defined(_AMD64_) || defined(_IA64_))
  74. #error New architecture must be added to switch statement.
  75. #endif
  76. switch (si.wProcessorArchitecture)
  77. {
  78. case PROCESSOR_ARCHITECTURE_AMD64:
  79. {
  80. PathAppend(szModuleName, TEXT("amd64\\winnt32.exe"));
  81. }
  82. break;
  83. case PROCESSOR_ARCHITECTURE_IA64:
  84. {
  85. PathAppend(szModuleName, TEXT("ia64\\winnt32.exe"));
  86. }
  87. break;
  88. case PROCESSOR_ARCHITECTURE_INTEL:
  89. default:
  90. {
  91. if (IsNec98())
  92. {
  93. PathAppend(szModuleName, TEXT("nec98\\winnt32.exe"));
  94. }
  95. else
  96. {
  97. PathAppend(szModuleName, TEXT("i386\\winnt32.exe"));
  98. }
  99. }
  100. break;
  101. }
  102. }
  103. for (int i=0; i<MAX_OPTIONS; i++)
  104. {
  105. TCHAR szTitle[256];
  106. TCHAR szConfig[MAX_PATH];
  107. TCHAR szArgs[MAX_PATH];
  108. LoadStringAuto(hinst, IDS_TITLE0+i, szTitle, ARRAYSIZE(szTitle));
  109. // for INSTALL_WINNT and COMPAT_LOCAL we prepend the correct path to winnt32 in front of the string
  110. if ( INSTALL_WINNT == i || COMPAT_LOCAL == i)
  111. {
  112. lstrcpy( szConfig, szModuleName );
  113. if ( !PathFileExists(szModuleName) )
  114. {
  115. // we can't run the item if it's not there. This will prevent an
  116. // alpha CD from trying to install on an x86 and vice versa.
  117. m_data[i].m_dwFlags |= WF_DISABLED|WF_ALTERNATECOLOR;
  118. }
  119. }
  120. else
  121. {
  122. LoadStringAuto(hinst, IDS_CONFIG0+i, szConfig, ARRAYSIZE(szConfig));
  123. }
  124. if (INSTALL_WINNT == i) // for INSTALL_WINNT we pass through the command line args to setup.exe
  125. {
  126. lstrcpy (szArgs, pszCommandLine);
  127. }
  128. else if (BROWSE_CD == i) // for BROWSE_CD we pass the directory as an argument to explorer.exe
  129. {
  130. lstrcpy( szArgs, szModuleName );
  131. PathRemoveFilespec( szArgs );
  132. PathRemoveFilespec( szArgs );
  133. }
  134. else
  135. {
  136. LoadStringAuto(hinst, IDS_ARGS0+i, szArgs, ARRAYSIZE(szArgs));
  137. }
  138. m_data[i].SetData( szTitle, szConfig, *szArgs?szArgs:NULL, 0, i);
  139. }
  140. // Should we display the "This CD contains a newer version" dialog?
  141. OSVERSIONINFO ovi;
  142. ovi.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO );
  143. if ( !GetVersionEx(&ovi) || ovi.dwPlatformId==VER_PLATFORM_WIN32s )
  144. {
  145. // We cannot upgrade win32s systems.
  146. m_Version = VER_INCOMPATIBLE;
  147. }
  148. else if ( ovi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS )
  149. {
  150. if (ovi.dwMajorVersion > 3)
  151. {
  152. // we can always upgrade win98+ systems to NT
  153. m_Version = VER_OLDER;
  154. // Disable ARP. ARP is only enabled if the CD and the OS are the same version
  155. m_data[LAUNCH_ARP].m_dwFlags |= WF_DISABLED|WF_ALTERNATECOLOR;
  156. }
  157. else
  158. {
  159. m_Version = VER_INCOMPATIBLE;
  160. }
  161. }
  162. else if ((MAJOR > ovi.dwMajorVersion) ||
  163. ((MAJOR == ovi.dwMajorVersion) && ((MINOR > ovi.dwMinorVersion) || ((MINOR == ovi.dwMinorVersion) && (BUILD > ovi.dwBuildNumber)))))
  164. {
  165. // For NT to NT upgrades, we only upgrade if the version is lower
  166. // For NT 3.51 we have some special case code
  167. if ( ovi.dwMajorVersion == 3 )
  168. {
  169. // must be at least NT 3.51
  170. if ( ovi.dwMinorVersion < 51 )
  171. {
  172. // On NT 3.1 we might be able to launch winnt32.exe
  173. STARTUPINFO sinfo =
  174. {
  175. sizeof(STARTUPINFO),
  176. };
  177. PROCESS_INFORMATION pinfo;
  178. BOOL b = CreateProcess(NULL,szModuleName,NULL,NULL,FALSE,0,NULL,NULL,&sinfo,&pinfo);
  179. if (b)
  180. {
  181. CloseHandle(pinfo.hProcess);
  182. CloseHandle(pinfo.hThread);
  183. }
  184. return FALSE;
  185. }
  186. }
  187. m_Version = VER_OLDER;
  188. // Disable ARP. ARP is only enabled if the CD and the OS are the same version
  189. m_data[LAUNCH_ARP].m_dwFlags |= WF_DISABLED|WF_ALTERNATECOLOR;
  190. }
  191. else if ((MAJOR < ovi.dwMajorVersion) || (MINOR < ovi.dwMinorVersion) || (BUILD < ovi.dwBuildNumber))
  192. {
  193. m_Version = VER_NEWER;
  194. // disable upgrade and ARP buttons and associated things
  195. m_data[INSTALL_WINNT].m_dwFlags |= WF_DISABLED|WF_ALTERNATECOLOR;
  196. m_data[COMPAT_LOCAL].m_dwFlags |= WF_DISABLED|WF_ALTERNATECOLOR;
  197. m_data[LAUNCH_ARP].m_dwFlags |= WF_DISABLED|WF_ALTERNATECOLOR;
  198. }
  199. else
  200. {
  201. m_Version = VER_SAME;
  202. }
  203. if (m_Version == VER_SAME)
  204. {
  205. m_piScreen = c_aiWhistler;
  206. m_iItems = c_cWhistler;
  207. }
  208. else
  209. {
  210. m_piScreen = c_aiMain;
  211. m_iItems = c_cMain;
  212. }
  213. return TRUE;
  214. }
  215. void CDataSource::Invoke( int i, HWND hwnd )
  216. {
  217. i = m_piScreen[i];
  218. // if this item is disalbled then do nothing
  219. if ( m_data[i].m_dwFlags & WF_DISABLED )
  220. {
  221. MessageBeep(0);
  222. return;
  223. }
  224. // otherwise we have already built the correct command and arg strings so just invoke them
  225. switch (i)
  226. {
  227. case INSTALL_WINNT:
  228. case LAUNCH_ARP:
  229. case BROWSE_CD:
  230. case COMPAT_WEB:
  231. case COMPAT_LOCAL:
  232. case HOMENET_WIZ:
  233. case MIGRATION_WIZ:
  234. case TS_CLIENT:
  235. case VIEW_RELNOTES:
  236. case INSTALL_CLR:
  237. m_data[i].Invoke(hwnd);
  238. break;
  239. case SUPPORT_TOOLS:
  240. m_piScreen = c_aiSupport;
  241. m_iItems = c_cSupport;
  242. PostMessage(m_hwndDlg, ARM_CHANGESCREEN, SCREEN_TOOLS, 0);
  243. break;
  244. case COMPAT_TOOLS:
  245. m_piScreen = c_aiCompat;
  246. m_iItems = c_cCompat;
  247. PostMessage(m_hwndDlg, ARM_CHANGESCREEN, SCREEN_COMPAT, 0);
  248. break;
  249. case BACK:
  250. if (m_Version == VER_SAME)
  251. {
  252. m_piScreen = c_aiWhistler;
  253. m_iItems = c_cWhistler;
  254. }
  255. else
  256. {
  257. m_piScreen = c_aiMain;
  258. m_iItems = c_cMain;
  259. }
  260. PostMessage(m_hwndDlg, ARM_CHANGESCREEN, SCREEN_MAIN, 0);
  261. break;
  262. default:
  263. // Assert? Debug trace message?
  264. break;
  265. }
  266. }
  267. // Uninit
  268. //
  269. // This is a chance to do any required shutdown stuff, such as persisting state information.
  270. void CDataSource::Uninit(DWORD dwData)
  271. {
  272. }
  273. // ShowSplashScreen
  274. //
  275. // This hook is provided to allow the display of additional UI right after the main window is diaplyed.
  276. // In our case we want to show a dialog asking if the user wants to upgrade.
  277. void CDataSource::ShowSplashScreen(HWND hwnd)
  278. {
  279. m_hwndDlg = hwnd;
  280. }