Leaked source code of windows server 2003
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.

376 lines
9.7 KiB

  1. /****************************************************************************\
  2. MAIN.C / Mass Storage Device Installer Tool (MSDINST.EXE)
  3. Microsoft Confidential
  4. Copyright (c) Microsoft Corporation 2001
  5. All rights reserved
  6. Main source file for the MSD Installation stand alone tool.
  7. 07/2001 - Jason Cohen (JCOHEN)
  8. Added this new source file for the new MSD Isntallation project.
  9. \****************************************************************************/
  10. //
  11. // Include File(s):
  12. //
  13. #include "pch.h"
  14. #include "res.h"
  15. #include <winbom.h>
  16. #include <msdinst.h>
  17. #include <spapip.h>
  18. //
  19. // Local Define(s):
  20. //
  21. #define REG_KEY_WINPE _T("SYSTEM\\CurrentControlSet\\Control\\MiniNT")
  22. #define STR_MUTEX_MSDINST _T("{97e6e509-16e5-40b8-91fd-c767306853a9}")
  23. //
  24. // Local Type Definition(s):
  25. //
  26. typedef struct _GAPP
  27. {
  28. TCHAR szInfPath[MAX_PATH];
  29. TCHAR szWinDir[MAX_PATH];
  30. }
  31. GAPP, *LPGAPP;
  32. //
  33. // Internal Global Variable(s):
  34. //
  35. GAPP g_App = {0};
  36. //
  37. // Local Prototype(s):
  38. //
  39. static BOOL
  40. ParseCmdLine(
  41. LPGAPP lpgApp
  42. );
  43. //
  44. // Internal function(s):
  45. //
  46. static BOOL
  47. ParseCmdLine(
  48. LPGAPP lpgApp
  49. )
  50. {
  51. BOOL bRet = TRUE;
  52. DWORD dwArgs,
  53. dwArg,
  54. dwOption,
  55. dwOther = 0;
  56. LPTSTR *lpArgs,
  57. lpArg,
  58. lpOption,
  59. lpOptions[] =
  60. {
  61. _T("FORCE") // 0
  62. };
  63. // Call our function to process the command line and put it
  64. // into a nice list we can go through.
  65. //
  66. if ( (dwArgs = GetCommandLineArgs(&lpArgs) ) && lpArgs )
  67. {
  68. // We want to skip over the first argument (it is the path
  69. // to the command being executed).
  70. //
  71. if ( dwArgs > 1 )
  72. {
  73. dwArg = 1;
  74. lpArg = *(lpArgs + dwArg);
  75. }
  76. else
  77. {
  78. lpArg = NULL;
  79. }
  80. // Loop through all the arguments.
  81. //
  82. while ( lpArg && bRet )
  83. {
  84. // Now we check to see if the first char is a dash/slash or not.
  85. //
  86. if ( ( _T('-') == *lpArg ) ||
  87. ( _T('/') == *lpArg ) )
  88. {
  89. lpOption = CharNext(lpArg);
  90. for ( dwOption = 0;
  91. ( ( dwOption < AS(lpOptions) ) &&
  92. ( 0 != lstrcmpi(lpOption, lpOptions[dwOption]) ) );
  93. dwOption++ );
  94. // This is where you add command line options that start
  95. // with a dash (-) or a slash (/). You add them in the static
  96. // array of pointers at the top of the function declaration and
  97. // you case off the index it is in the array (0 for the first one,
  98. // 1 for the second and so on).
  99. //
  100. switch ( dwOption )
  101. {
  102. case 0: // -FORCE
  103. //
  104. // If the force switch is specified... set the flag.
  105. //
  106. SetOfflineInstallFlags( GetOfflineInstallFlags() | INSTALL_FLAG_FORCE );
  107. break;
  108. default:
  109. bRet = FALSE;
  110. }
  111. }
  112. // Otherwise if there is something there it is just another argument.
  113. //
  114. else if ( *lpArg )
  115. {
  116. // This is where you add any command line options that don't
  117. // start with anything special. We keep track of how many of
  118. // these guys we find, so just add a case for each one you want
  119. // to handle starting with 0.
  120. //
  121. switch ( dwOther++ )
  122. {
  123. case 0:
  124. lstrcpyn(lpgApp->szInfPath, lpArg, AS(lpgApp->szInfPath));
  125. break;
  126. case 1:
  127. lstrcpyn(lpgApp->szWinDir, lpArg, AS(lpgApp->szWinDir));
  128. break;
  129. default:
  130. bRet = FALSE;
  131. }
  132. }
  133. // Setup the pointer to the next argument in the command line.
  134. //
  135. if ( ++dwArg < dwArgs )
  136. {
  137. lpArg = *(lpArgs + dwArg);
  138. }
  139. else
  140. {
  141. lpArg = NULL;
  142. }
  143. }
  144. // Make sure to free the two buffers allocated by the GetCommandLineArgs() function.
  145. //
  146. FREE(*lpArgs);
  147. FREE(lpArgs);
  148. }
  149. // If there were no unrecognized arguments, then we return TRUE. Otherwise
  150. // we return FALSE.
  151. //
  152. return bRet;
  153. }
  154. //
  155. // Main Fuction:
  156. //
  157. int __cdecl wmain(DWORD dwArgs, LPTSTR lpszArgs[])
  158. {
  159. int nErr = 0;
  160. HANDLE hMutex;
  161. TCHAR szInfFile[MAX_PATH] = NULLSTR,
  162. szWindows[MAX_PATH] = NULLSTR;
  163. LPTSTR lpDontCare,
  164. lpszErr;
  165. HKEY hkeySoftware,
  166. hkeySystem;
  167. DWORD dwRet;
  168. // Initialize logging library.
  169. //
  170. OpkInitLogging(NULL, _T("MSDINST") );
  171. // Allways start with a line feed.
  172. //
  173. _tprintf(_T("\n"));
  174. // This tool is current only supported on WinPE.
  175. //
  176. if ( !RegExists(HKLM, REG_KEY_WINPE, NULL) )
  177. {
  178. if ( lpszErr = AllocateString(NULL, IDS_ERR_WINPE) )
  179. {
  180. _putts(lpszErr);
  181. _tprintf(_T("\n\n"));
  182. FREE(lpszErr);
  183. }
  184. return 1;
  185. }
  186. // Need to have two args, the full path to the inf file
  187. // with the controlers to install, and the path to the
  188. // windows direcotry of the offline image.
  189. //
  190. if ( (dwArgs < 3) || !ParseCmdLine( &g_App) )
  191. {
  192. if ( lpszErr = AllocateString(NULL, IDS_ARGS) )
  193. {
  194. _putts(lpszErr);
  195. _tprintf(_T("\n\n"));
  196. FREE(lpszErr);
  197. }
  198. return 1;
  199. }
  200. // Copy the command line parameters to our own buffers.
  201. //
  202. if ( !( GetFullPathName(g_App.szInfPath, AS(szInfFile), szInfFile, &lpDontCare) && szInfFile[0] ) ||
  203. !( GetFullPathName(g_App.szWinDir, AS(szWindows), szWindows, &lpDontCare) && szWindows[0] ) )
  204. {
  205. //
  206. // Get the system text for "The specified path is invalid."
  207. //
  208. lpszErr = NULL;
  209. dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  210. NULL,
  211. ERROR_BAD_PATHNAME,
  212. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  213. (LPTSTR) &lpszErr,
  214. 0,
  215. NULL );
  216. //
  217. // If the string was formatted, then let the user know something went wrong...
  218. //
  219. if ( dwRet && lpszErr )
  220. {
  221. _putts( lpszErr );
  222. _tprintf(_T("\n\n"));
  223. LocalFree( lpszErr );
  224. lpszErr = NULL;
  225. }
  226. return 1;
  227. }
  228. // Make sure the inf file exists.
  229. //
  230. if ( !FileExists(szInfFile) )
  231. {
  232. if ( lpszErr = AllocateString(NULL, IDS_ERR_MISSING_INF_FILE) )
  233. {
  234. _tprintf(lpszErr, szInfFile);
  235. _tprintf(_T("\n\n"));
  236. FREE(lpszErr);
  237. }
  238. return 1;
  239. }
  240. // Make sure the inf file contains the section we need.
  241. //
  242. if ( !IniSettingExists(szInfFile, INI_SEC_WBOM_SYSPREP_MSD, NULL, NULL) )
  243. {
  244. if ( lpszErr = AllocateString(NULL, IDS_ERR_MISSING_INF_SECTION) )
  245. {
  246. _tprintf(lpszErr, szInfFile, INI_SEC_WBOM_SYSPREP_MSD);
  247. _tprintf(_T("\n\n"));
  248. FREE(lpszErr);
  249. }
  250. return 1;
  251. }
  252. // Make sure the image directory exists.
  253. //
  254. if ( !DirectoryExists(szWindows) )
  255. {
  256. if ( lpszErr = AllocateString(NULL, IDS_ERR_NOWINDOWS) )
  257. {
  258. _tprintf(lpszErr, szWindows);
  259. _tprintf(_T("\n\n"));
  260. FREE(lpszErr);
  261. }
  262. return 1;
  263. }
  264. // Only let one of this guy run.
  265. //
  266. hMutex = CreateMutex(NULL, FALSE, STR_MUTEX_MSDINST);
  267. if ( hMutex == NULL )
  268. {
  269. if ( lpszErr = AllocateString(NULL, IDS_ERR_ONEONLY) )
  270. {
  271. _putts(lpszErr);
  272. _tprintf(_T("\n\n"));
  273. FREE(lpszErr);
  274. }
  275. return 1;
  276. }
  277. // We have to be able to load the offline image to do anything.
  278. //
  279. if ( !RegLoadOfflineImage(szWindows, &hkeySoftware, &hkeySystem) )
  280. {
  281. if ( lpszErr = AllocateString(NULL, IDS_ERR_LOADIMAGE) )
  282. {
  283. _tprintf(lpszErr, szWindows);
  284. _tprintf(_T("\n\n"));
  285. FREE(lpszErr);
  286. }
  287. CloseHandle(hMutex);
  288. return 1;
  289. }
  290. // Now try to install the MSD into the offline image.
  291. //
  292. if ( !SetupCriticalDevices(szInfFile, hkeySoftware, hkeySystem, szWindows) )
  293. {
  294. if ( lpszErr = AllocateString(NULL, IDS_ERR_CDD) )
  295. {
  296. _putts(lpszErr);
  297. _tprintf(_T("\n\n"));
  298. FREE(lpszErr);
  299. }
  300. nErr = 1;
  301. }
  302. // Unload the offline image.
  303. //
  304. RegUnloadOfflineImage(hkeySoftware, hkeySystem);
  305. // Release the mutex.
  306. //
  307. CloseHandle(hMutex);
  308. if ( 0 == nErr )
  309. {
  310. if ( lpszErr = AllocateString(NULL, IDS_ERR_SUCCESS) )
  311. {
  312. _putts(lpszErr);
  313. _tprintf(_T("\n\n"));
  314. FREE(lpszErr);
  315. }
  316. }
  317. return nErr;
  318. }