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.

769 lines
27 KiB

  1. /****************************************************************************\
  2. MAIN.C / OPK Wizard (OPKWIZ.EXE)
  3. Microsoft Confidential
  4. Copyright (c) Microsoft Corporation 1999
  5. All rights reserved
  6. Main source file for the OPK Wizard. Contains WinMain() and global
  7. variable declarations.
  8. 4/99 - Jason Cohen (JCOHEN)
  9. Added this new main source file for the OPK Wizard as part of the
  10. Millennium rewrite.
  11. 09/2000 - Stephen Lodwick (STELO)
  12. Ported OPK Wizard to Whistler
  13. \****************************************************************************/
  14. //
  15. // Pre-include Defined Value(s):
  16. //
  17. // Needed to define this so we don't include
  18. // the extern declarations of the globals that
  19. // are declared in this file.
  20. //
  21. #define _MAIN_C_
  22. //
  23. // Include File(s):
  24. //
  25. #include "setupmgr.h"
  26. #include "allres.h"
  27. //
  28. // Global Variable(s):
  29. //
  30. GAPP g_App;
  31. //
  32. // Internal Defined Value(s):
  33. //
  34. // Tag files
  35. //
  36. #ifndef DBCS
  37. #define FILE_DBCS_TAG _T("dbcs.tag")
  38. #endif // DBCS
  39. // Directories off the root of the tool instal location.
  40. //
  41. #define DIR_LANG _T("lang")
  42. #define DIR_CONFIGSETS _T("cfgsets")
  43. #define DIR_DOCS _T("docs")
  44. #define FILE_HELPCONTENT_CHM _T("opk.chm")
  45. #define STR_TAGFILE _T("HIJPP 1.0")
  46. #define STR_VERSION _T("Version")
  47. #define REGSTR_IEXPLORER _T("Software\\Microsoft\\Internet Explorer")
  48. // Unique string.
  49. //
  50. #define OPKWIZ_MUTEX _T("OPKWIZ-MUTEX-5c9fbbd0-ee0e-11d2-9a21-0000f81edacc")
  51. //
  52. // Internal Function Prototype(s):
  53. //
  54. static BOOL ParseCmdLine(LPTSTR);
  55. static BOOL FileWritable(LPTSTR lpszFile);
  56. BOOL CALLBACK HelpDlgProc(HWND, UINT, WPARAM, LPARAM);
  57. static BOOL CheckIEVersion();
  58. static BOOL ParseVersionString(TCHAR* pszVersion, DWORD* pdwMajor, DWORD* pdwMinor,
  59. DWORD* pdwBuild, DWORD* pdwSubbuild);
  60. static VOID SetWizardHelpFile(LPTSTR lpszHelpFilePath);
  61. //
  62. // Main Function:
  63. //
  64. int StartWizard(HINSTANCE hInstance, LPSTR lpCmdLine)
  65. {
  66. HANDLE hMutex = NULL;
  67. int nReturn = 0;
  68. TCHAR szCmdLine[MAX_PATH] = NULLSTR;
  69. // Convert cmdline from char to wchar
  70. //
  71. MultiByteToWideChar(CP_ACP, 0, lpCmdLine, -1, szCmdLine, AS(szCmdLine));
  72. // Check for another instance of the OPK wizard.
  73. //
  74. SetLastError(ERROR_SUCCESS);
  75. if ( ( hMutex = CreateMutex(NULL, TRUE, OPKWIZ_MUTEX) ) &&
  76. ( GetLastError() == ERROR_ALREADY_EXISTS ) )
  77. {
  78. HWND hwndWizard;
  79. LPTSTR lpAppName = AllocateString(NULL, IDS_APPNAME);
  80. // Find the window, set it to the forground, and return.
  81. //
  82. if ( ( lpAppName ) && ( hwndWizard = FindWindow(NULL, lpAppName) ) )
  83. SetForegroundWindow(hwndWizard);
  84. FREE(lpAppName);
  85. }
  86. else if ( CheckIEVersion() )
  87. {
  88. TCHAR szBuffer[MAX_PATH];
  89. LPTSTR lpBuffer;
  90. // Init some more of the global data.
  91. //
  92. g_App.hInstance = hInstance;
  93. // Get the path to where the EXE is.
  94. //
  95. szBuffer[0] = NULLCHR;
  96. lpBuffer = NULL;
  97. // ISSUE-2002/02/27-stelo,swamip - Check return Value and make sure that szBuffer has data in it.
  98. GetModuleFileName(hInstance, szBuffer, STRSIZE(szBuffer));
  99. if ( GetFullPathName(szBuffer, STRSIZE(g_App.szOpkDir), g_App.szOpkDir, &lpBuffer) &&
  100. g_App.szOpkDir[0] &&
  101. lpBuffer )
  102. {
  103. // Chop off the exe name from the path we want.
  104. //
  105. *lpBuffer = NULLCHR;
  106. StrRTrm(g_App.szOpkDir, CHR_BACKSLASH);
  107. }
  108. // Setup the full path to the ini file for the wizard.
  109. //
  110. lstrcpyn(g_App.szSetupMgrIniFile, g_App.szOpkDir,AS(g_App.szSetupMgrIniFile));
  111. AddPathN(g_App.szSetupMgrIniFile, FILE_SETUPMGR_INI,AS(g_App.szSetupMgrIniFile));
  112. // Need to know where the root of the folder where wizard files are installed.
  113. //
  114. lstrcpyn(g_App.szWizardDir, g_App.szOpkDir,AS(g_App.szWizardDir));
  115. AddPathN(g_App.szWizardDir, DIR_WIZARDFILES,AS(g_App.szWizardDir));
  116. // Need to know where the configuration set folder is.
  117. //
  118. lstrcpyn(g_App.szConfigSetsDir, g_App.szOpkDir, AS(g_App.szConfigSetsDir));
  119. AddPathN(g_App.szConfigSetsDir, DIR_CONFIGSETS,AS(g_App.szConfigSetsDir));
  120. // Need to know where the lang directory is.
  121. //
  122. lstrcpyn(g_App.szLangDir, g_App.szOpkDir,AS(g_App.szLangDir));
  123. AddPathN(g_App.szLangDir, DIR_LANG,AS(g_App.szLangDir));
  124. // Setup the full paths to the help files.
  125. //
  126. SetWizardHelpFile(g_App.szHelpFile);
  127. lstrcpyn(g_App.szHelpContentFile, g_App.szOpkDir,AS(g_App.szHelpContentFile));
  128. AddPathN(g_App.szHelpContentFile, DIR_DOCS,AS(g_App.szHelpContentFile));
  129. AddPathN(g_App.szHelpContentFile, FILE_HELPCONTENT_CHM,AS(g_App.szHelpContentFile));
  130. // Setup the full path to the OPK input file.
  131. //
  132. lstrcpyn(g_App.szOpkInputInfFile, g_App.szWizardDir,AS(g_App.szOpkInputInfFile));
  133. AddPathN(g_App.szOpkInputInfFile, FILE_OPKINPUT_INF,AS(g_App.szOpkInputInfFile));
  134. // First check for the OEM tag file in the same folder
  135. // as the exe, just in case they are running it right
  136. // off the CD or network share. We need to catch this
  137. // case so we can stop them from running in corp mode
  138. // by accidentally.
  139. //
  140. lstrcpyn(szBuffer, g_App.szOpkDir,AS(szBuffer));
  141. AddPathN(szBuffer, FILE_OEM_TAG,AS(szBuffer));
  142. if ( FileExists(szBuffer) )
  143. SET_FLAG(OPK_OEM, TRUE);
  144. // Get a pointer to the end of a buffer with the wizard
  145. // directory in it.
  146. //
  147. lstrcpyn(szBuffer, g_App.szWizardDir,AS(szBuffer));
  148. AddPathN(szBuffer, NULLSTR,AS(szBuffer));
  149. lpBuffer = szBuffer + lstrlen(szBuffer);
  150. // Check to see if this is the DBCS version.
  151. //
  152. // NTRAID#NTBUG9-547380-2002/02/27-stelo,swamip - We need to base the DBCS descisions (conditions) at runtime not at compile time. Since an English OPK
  153. // can deploy a variety of languages, the compile time tag does not make sense.
  154. #ifdef DBCS
  155. SET_FLAG(OPK_DBCS, TRUE);
  156. #else // DBCS
  157. lstrcpyn(lpBuffer, FILE_DBCS_TAG, (AS(szBuffer)-lstrlen(szBuffer)));
  158. SET_FLAG(OPK_DBCS, FileExists(szBuffer));
  159. #endif // DBCS
  160. // Check for the OEM tag file.
  161. //
  162. lstrcpyn(lpBuffer, FILE_OEM_TAG, (AS(szBuffer)-lstrlen(szBuffer)));
  163. if ( FileExists(szBuffer) )
  164. SET_FLAG(OPK_OEM, TRUE);
  165. //
  166. // Make sure that szBuffer is pointing to the OEM tag file at this point,
  167. // because we are going to try and write to it in the next check.
  168. //
  169. // The OPK input file must exist to run the wizard if this
  170. // is running in OEM mode.
  171. //
  172. if ( ( g_App.szOpkDir[0] ) &&
  173. ( ( !GET_FLAG(OPK_OEM) ) ||
  174. ( FileExists(g_App.szOpkInputInfFile) && FileWritable(szBuffer) ) ) )
  175. {
  176. // Check out the command line options.
  177. //
  178. if ( ParseCmdLine(szCmdLine) )
  179. {
  180. // Set this so on the very first wizard page, we can cancel with
  181. // out getting the confirmation dialog.
  182. //
  183. SET_FLAG(OPK_EXIT, TRUE);
  184. // Now create the wizard.
  185. //
  186. nReturn = CreateMaintenanceWizard(hInstance, NULL);
  187. // Clean up the temporary directory used if we didn't finish.
  188. //
  189. if ( g_App.szTempDir[0] )
  190. {
  191. // Make sure the temp dir and the wizard dir have trailing backslashes.
  192. //
  193. AddPathN(g_App.szWizardDir, NULLSTR,AS(g_App.szWizardDir));
  194. AddPathN(g_App.szTempDir, NULLSTR,AS(g_App.szTempDir));
  195. if ( lstrcmpi(g_App.szWizardDir, g_App.szTempDir) != 0 )
  196. DeletePath(g_App.szTempDir);
  197. #ifdef DBG
  198. else
  199. {
  200. DBGOUT(NULL, _T("OPKWIZ: Temp and Wizard directory are the same on exit (%s).\n"), g_App.szTempDir);
  201. DBGMSGBOX(NULL, _T("Temp and Wizard directory are the same on exit (%s)."), _T("OPKWIZ Debug Message"), MB_ERRORBOX, g_App.szTempDir);
  202. }
  203. #endif // DBG
  204. }
  205. }
  206. }
  207. else
  208. MsgBox(NULL, IDS_ERR_WIZBAD, IDS_APPNAME, MB_ERRORBOX);
  209. }
  210. else
  211. MsgBox(NULL, IDS_ERR_IE5, IDS_APPNAME, MB_ERRORBOX);
  212. // Do the final cleanup before exiting.
  213. //
  214. if ( hMutex )
  215. CloseHandle(hMutex);
  216. return nReturn;
  217. }
  218. //
  219. // Internal Function(s):
  220. //
  221. static BOOL ParseCmdLine(LPTSTR lpszCmdLineOrg)
  222. {
  223. DWORD dwArgs;
  224. LPTSTR *lpArgs;
  225. BOOL bRet = TRUE,
  226. bError = FALSE;
  227. // ISSUE-2002/02/27-stelo,swamip - lpszCmdLineOrg is not being used any where, and before calling this function we are
  228. // doing some MultibytetoWideChar stuff on the buffer, those can be removed as well.
  229. if ( (dwArgs = GetCommandLineArgs(&lpArgs) ) && lpArgs )
  230. {
  231. LPTSTR lpArg;
  232. DWORD dwArg;
  233. // We want to skip over the first argument (it is the path
  234. // to the command being executed.
  235. //
  236. if ( dwArgs > 1 )
  237. {
  238. dwArg = 1;
  239. lpArg = *(lpArgs + dwArg);
  240. }
  241. else
  242. lpArg = NULL;
  243. // Loop through all the arguments.
  244. //
  245. while ( lpArg && !bError )
  246. {
  247. // Now we check to see if the first char is a dash or not.
  248. //
  249. if ( ( *lpArg == _T('-') ) ||
  250. ( *lpArg == _T('/') ) )
  251. {
  252. LPTSTR lpOption = CharNext(lpArg);
  253. BOOL bOption;
  254. //
  255. // This is where you add command line options that start with a dash (-).
  256. //
  257. // Set bError if you don't recognize the command line option (unless you
  258. // want to just ignore it and continue).
  259. //
  260. switch( UPPER(*lpOption) )
  261. {
  262. case _T('M'):
  263. // Maintanence mode.
  264. //
  265. if ( ( *(++lpOption) == _T(':') ) && *(++lpOption) )
  266. {
  267. LPTSTR lpConfigName;
  268. lstrcpyn(g_App.szTempDir, g_App.szConfigSetsDir,AS(g_App.szTempDir));
  269. AddPathN(g_App.szTempDir, NULLSTR,AS(g_App.szTempDir));
  270. lpConfigName = g_App.szTempDir + lstrlen(g_App.szTempDir);
  271. // ISSUE-2002/02/27-stelo,swamip - will never hit this conditional code?
  272. //
  273. if ( *lpOption == _T('"') )
  274. lpOption++;
  275. lstrcpyn(lpConfigName, lpOption, (AS(g_App.szTempDir)-lstrlen(g_App.szTempDir)));
  276. StrTrm(lpConfigName, CHR_SPACE);
  277. StrTrm(lpConfigName, CHR_QUOTE);
  278. lstrcpyn(g_App.szConfigName, lpConfigName,AS(g_App.szConfigName));
  279. AddPathN(g_App.szTempDir, NULLSTR,AS(g_App.szTempDir));
  280. SET_FLAG(OPK_MAINTMODE, TRUE);
  281. SET_FLAG(OPK_CMDMM, TRUE);
  282. // Now make sure that the directory actually exists.
  283. //
  284. if ( !DirectoryExists(g_App.szTempDir) )
  285. {
  286. MsgBox(NULL, IDS_ERR_BADCONFIG, IDS_APPNAME, MB_ERRORBOX, g_App.szConfigName);
  287. bRet = FALSE;
  288. }
  289. }
  290. else
  291. bError = TRUE;
  292. break;
  293. case _T('?'):
  294. // Help.
  295. //
  296. DialogBox(g_App.hInstance, MAKEINTRESOURCE(IDD_HELP), NULL, (DLGPROC) HelpDlgProc);
  297. bRet = FALSE;
  298. break;
  299. case _T('A'):
  300. // Set the flag for the autorun feature
  301. //
  302. SET_FLAG(OPK_AUTORUN, TRUE);
  303. break;
  304. case _T('B'):
  305. case _T('I'):
  306. //Going into batch/INS mode
  307. // Set bOption if it is a batch file, otherwise it
  308. // is the install ins file.
  309. //
  310. bOption = ( _T('B') == UPPER(*lpOption) );
  311. //Check to see that there's a file name
  312. if ( ( *(++lpOption) == _T(':') ) && *(++lpOption) )
  313. {
  314. LPTSTR lpFileName,
  315. lpFilePart = NULL;
  316. TCHAR szFullPath[MAX_PATH] = NULLSTR,
  317. szBuf[MAX_URL];
  318. // Set the lpFileName based on the command line
  319. //
  320. // ISSUE-2002/02/27-stelo,swamip - will never hit this conditional code?
  321. //
  322. if ( *lpOption == _T('"') )
  323. lpOption++;
  324. // Strip off the spaces and quotes from parameter
  325. //
  326. StrTrm(lpOption, CHR_SPACE);
  327. StrTrm(lpOption, CHR_QUOTE);
  328. // Grab the full path of the batch/INS file
  329. //
  330. if (( GetFullPathName(lpOption, STRSIZE(szFullPath), szFullPath, &lpFilePart) ))
  331. {
  332. // Verify the the batch/INS file exists
  333. //
  334. if ( !FileExists(szFullPath))
  335. {
  336. MsgBox(NULL, bOption ? IDS_ERR_BADBATCH : IDS_ERR_BADINS, IDS_APPNAME, MB_ERRORBOX, szFullPath);
  337. bRet = FALSE;
  338. }
  339. else
  340. {
  341. // The file exists, we're ready to start, Set the batch/INS mode flag to TRUE
  342. // Set the global batch file to the given batch/INS file name
  343. if (bOption)
  344. lstrcpyn(g_App.szOpkWizIniFile, szFullPath, AS(g_App.szOpkWizIniFile));
  345. else
  346. lstrcpyn(g_App.szInstallInsFile, szFullPath, AS(g_App.szInstallInsFile));
  347. SET_FLAG(bOption ? OPK_BATCHMODE : OPK_INSMODE, TRUE);
  348. bRet = TRUE;
  349. }
  350. // Set the configuration set name
  351. //
  352. szBuf[0] = NULLCHR;
  353. // ISSUE-2002/02/27-stelo,swamip - Need to check the return value of GetPrivateProfileString. Also check for possible buffer overflow
  354. // as szBuf is MAX_URL and ConfigName is MAX_PATH
  355. GetPrivateProfileString( INI_SEC_CONFIGSET, INI_SEC_CONFIG, NULLSTR, szBuf, STRSIZE(szBuf), g_App.szOpkWizIniFile );
  356. lstrcpyn(g_App.szConfigName, szBuf, AS(g_App.szConfigName));
  357. }
  358. else
  359. bRet = FALSE;
  360. }
  361. else
  362. bError = TRUE;
  363. break;
  364. default:
  365. bError = TRUE;
  366. break;
  367. }
  368. }
  369. else if ( *lpArg )
  370. {
  371. //
  372. // This is where you would read any command line parameters that are just passed
  373. // in on the command line w/o any proceeding characters (like - or /).
  374. //
  375. // Set bError if you don't have any of these types of parameters (unless you
  376. // want to just ignore it and continue).
  377. //
  378. bError = TRUE;
  379. }
  380. // Setup the pointer to the next argument in the command line.
  381. //
  382. if ( ++dwArg < dwArgs )
  383. lpArg = *(lpArgs + dwArg);
  384. else
  385. lpArg = NULL;
  386. }
  387. // Make sure to free the two buffers allocated by the GetCommandLineArgs() function.
  388. //
  389. FREE(*lpArgs);
  390. FREE(lpArgs);
  391. }
  392. //Check to see if the arguments provided are valid and that we have not already hit an error
  393. if (((GET_FLAG(OPK_BATCHMODE) && GET_FLAG(OPK_MAINTMODE)) ||
  394. (!(GET_FLAG(OPK_BATCHMODE)) && GET_FLAG(OPK_INSMODE)) ||
  395. (!(GET_FLAG(OPK_BATCHMODE)) && GET_FLAG(OPK_AUTORUN)) ||
  396. (GET_FLAG(OPK_MAINTMODE) && GET_FLAG(OPK_INSMODE))) && bRet && !bError)
  397. {
  398. MsgBox(NULL, IDS_ERR_INVCMD, IDS_APPNAME, MB_OK);
  399. bRet = FALSE;
  400. }
  401. // If we hit an error, display the error and show the help.
  402. //
  403. if ( bError )
  404. {
  405. MsgBox(NULL, IDS_ERR_BADCMDLINE, IDS_APPNAME, MB_ERRORBOX);
  406. bRet = FALSE;
  407. }
  408. return bRet;
  409. }
  410. static BOOL FileWritable(LPTSTR lpszFile)
  411. {
  412. BOOL bRet = TRUE;
  413. DWORD dwAttr = GetFileAttributes(lpszFile);
  414. // ISSUE-2002/02/27-stelo,swamip - The logic appears to incorrect, we should check READ_ONLY attribute
  415. if ( ( dwAttr != 0xFFFFFFFF ) &&
  416. ( SetFileAttributes(lpszFile, dwAttr) == 0 ) )
  417. {
  418. bRet = FALSE;
  419. }
  420. return bRet;
  421. }
  422. void SetConfigPath(LPCTSTR lpDirectory)
  423. {
  424. HINF hInf;
  425. INFCONTEXT InfContext;
  426. BOOL bLoop;
  427. DWORD dwErr;
  428. // ISSUE-2002/02/27-stelo,swamip - Make sure lpdirectory is a valid pointer
  429. if ( (hInf = SetupOpenInfFile(g_App.szOpkInputInfFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, &dwErr)) != INVALID_HANDLE_VALUE )
  430. {
  431. for ( bLoop = SetupFindFirstLine(hInf, INF_SEC_COPYFILES, NULL, &InfContext);
  432. bLoop;
  433. bLoop = SetupFindNextLine(&InfContext, &InfContext) )
  434. {
  435. TCHAR szFile[MAX_PATH] = NULLSTR,
  436. szSubDir[MAX_PATH] = NULLSTR;
  437. LPTSTR lpBuffer;
  438. int iBufferLen;
  439. // Get the source filename.
  440. //
  441. if ( SetupGetStringField(&InfContext, 1, szFile, AS(szFile), NULL) && szFile[0] )
  442. {
  443. // Now find out if this is a file we care about.
  444. //
  445. if ( LSTRCMPI(szFile, FILE_INSTALL_INS) == 0 ) {
  446. lpBuffer = g_App.szInstallInsFile;
  447. iBufferLen= AS(g_App.szInstallInsFile);
  448. } else if ( LSTRCMPI(szFile, FILE_OPKWIZ_INI) == 0 ) {
  449. lpBuffer = g_App.szOpkWizIniFile;
  450. iBufferLen= AS(g_App.szOpkWizIniFile);
  451. } else if ( LSTRCMPI(szFile, FILE_OOBEINFO_INI) == 0 ) {
  452. lpBuffer = g_App.szOobeInfoIniFile;
  453. iBufferLen= AS(g_App.szOobeInfoIniFile);
  454. } else if ( LSTRCMPI(szFile, FILE_OEMINFO_INI) == 0 ) {
  455. lpBuffer = g_App.szOemInfoIniFile;
  456. iBufferLen= AS(g_App.szOemInfoIniFile);
  457. } else if ( LSTRCMPI(szFile, FILE_WINBOM_INI) == 0 ) {
  458. lpBuffer = g_App.szWinBomIniFile;
  459. iBufferLen= AS(g_App.szWinBomIniFile);
  460. } else if ( LSTRCMPI(szFile, FILE_UNATTEND_TXT) == 0 ) {
  461. lpBuffer = g_App.szUnattendTxtFile;
  462. iBufferLen= AS(g_App.szUnattendTxtFile);
  463. } else {
  464. lpBuffer = NULL;
  465. iBufferLen=0;
  466. }
  467. // Get the full path to the file if this is one we are saving.
  468. //
  469. if ( lpBuffer )
  470. {
  471. lstrcpyn(lpBuffer, lpDirectory,iBufferLen);
  472. // Get the optional destination sub directory and add it
  473. // if it is there.
  474. //
  475. if ( SetupGetStringField(&InfContext, 3, szSubDir, AS(szSubDir), NULL) && szSubDir[0] )
  476. {
  477. AddPathN(lpBuffer, szSubDir, iBufferLen);
  478. if ( !DirectoryExists(lpBuffer) )
  479. {
  480. // ISSUE-2002/02/27-stelo,swamip - We should check the return value of CreatePath and pass up to SetConfigPath
  481. CreatePath(lpBuffer);
  482. }
  483. }
  484. AddPathN(lpBuffer, szFile, iBufferLen);
  485. }
  486. }
  487. }
  488. }
  489. }
  490. BOOL CALLBACK HelpDlgProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  491. {
  492. switch (uMsg)
  493. {
  494. case WM_COMMAND:
  495. switch ( LOWORD(wParam) )
  496. {
  497. case IDOK:
  498. EndDialog(hwnd, LOWORD(wParam));
  499. break;
  500. }
  501. return FALSE;
  502. default:
  503. return FALSE;
  504. }
  505. return FALSE;
  506. }
  507. // Get the IE version from the registry, return TRUE if IE > 5
  508. BOOL CheckIEVersion()
  509. {
  510. DWORD dwSize = 255;
  511. TCHAR szVersion[255];
  512. HKEY hKey = 0;
  513. DWORD dwType = 0;
  514. BOOL bRet = FALSE;
  515. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_IEXPLORER, &hKey))
  516. {
  517. // Version for IE
  518. DWORD dwMajor, dwMinor, dwBuild, dwSubbuild;
  519. if (ERROR_SUCCESS == RegQueryValueEx(hKey, STR_VERSION, 0, &dwType, (LPBYTE)szVersion, &dwSize))
  520. {
  521. // Get the major version number
  522. if (ParseVersionString(szVersion, &dwMajor, &dwMinor, &dwBuild, &dwSubbuild) &&
  523. (dwMajor >= 5))
  524. {
  525. bRet = TRUE;
  526. }
  527. }
  528. RegCloseKey(hKey);
  529. }
  530. return bRet;
  531. }
  532. // Parses 5.00.0518.10 into dwMajor = 5, dwMinor = 0
  533. // <major version>.<minor version>.<build number>.<sub-build number>
  534. BOOL ParseVersionString(TCHAR* pszVersion, DWORD* pdwMajor, DWORD* pdwMinor,
  535. DWORD* pdwBuild, DWORD* pdwSubbuild)
  536. {
  537. TCHAR szTemp[255];
  538. int i = 0;
  539. if (!pdwMajor || !pdwMinor || !pdwBuild || !pdwSubbuild)
  540. return FALSE;
  541. // ISSUE-2002/02/27-stelo,swamip - Check for the end of the string condition during while loops.
  542. // Major version
  543. while (pszVersion && *pszVersion != TEXT('.'))
  544. szTemp[i++] = *pszVersion++;
  545. *pdwMajor = _tcstoul(szTemp, 0, 10);
  546. pszVersion++;
  547. // Minor version
  548. i = 0;
  549. while (pszVersion && *pszVersion != TEXT('.'))
  550. szTemp[i++] = *pszVersion++;
  551. *pdwMinor = _tcstoul(szTemp, 0, 10);
  552. pszVersion++;
  553. // Build version
  554. i = 0;
  555. while (pszVersion && *pszVersion != TEXT('.'))
  556. szTemp[i++] = *pszVersion++;
  557. *pdwBuild = _tcstoul(szTemp, 0, 10);
  558. pszVersion++;
  559. // Sub build version
  560. i = 0;
  561. while (pszVersion && *pszVersion != TEXT('\0'))
  562. szTemp[i++] = *pszVersion++;
  563. *pdwSubbuild = _tcstoul(szTemp, 0, 10);
  564. return TRUE;
  565. }
  566. // Saves us from making sure we check if we use this function we always check if batch mode
  567. //
  568. BOOL OpkGetPrivateProfileSection(LPCTSTR pszAppName, LPTSTR pszSection, INT cchSectionMax, LPCTSTR pszFileName)
  569. {
  570. if (!pszAppName || !pszSection || !pszFileName)
  571. return FALSE;
  572. return GetPrivateProfileSection(pszAppName, pszSection, cchSectionMax,
  573. GET_FLAG(OPK_BATCHMODE) ? g_App.szOpkWizIniFile : pszFileName);
  574. }
  575. // Saves us from making two calls when writing and also so we don't forget about
  576. // writing to batch mode inf
  577. //
  578. BOOL OpkWritePrivateProfileSection(LPCTSTR pszAppName, LPCTSTR pszKeyName, LPCTSTR pszFileName)
  579. {
  580. if (!pszAppName || !pszFileName)
  581. return FALSE;
  582. // Write to batch inf
  583. //
  584. if (FALSE == WritePrivateProfileSection(pszAppName, pszKeyName, g_App.szOpkWizIniFile))
  585. return FALSE;
  586. // Write to user inf
  587. //
  588. return WritePrivateProfileSection(pszAppName, pszKeyName, pszFileName);
  589. }
  590. // Saves us from making two calls when writing and also so we don't forget about
  591. // writing to batch mode inf
  592. //
  593. BOOL OpkWritePrivateProfileString(LPCTSTR pszAppName, LPCTSTR pszKeyName, LPCTSTR pszValue,
  594. LPCTSTR pszFileName)
  595. {
  596. BOOL fRet = FALSE;
  597. if (!pszAppName || !pszFileName)
  598. return FALSE;
  599. // Write to batch inf
  600. //
  601. if (FALSE == WritePrivateProfileString(pszAppName, pszKeyName, pszValue, g_App.szOpkWizIniFile))
  602. return FALSE;
  603. // Write to user inf
  604. //
  605. return WritePrivateProfileString(pszAppName, pszKeyName, pszValue, pszFileName);
  606. }
  607. // Saves us from making sure we check if we use this function we always check if batch mode
  608. //
  609. BOOL OpkGetPrivateProfileString(LPCTSTR pszAppName, LPCTSTR pszKeyName, LPCTSTR pszDefault, LPTSTR pszValue,
  610. INT cchValue, LPCTSTR pszFileName)
  611. {
  612. if (!pszAppName || !pszKeyName || !pszDefault || !pszValue || !pszFileName)
  613. return FALSE;
  614. return GetPrivateProfileString(pszAppName, pszKeyName, pszDefault, pszValue, cchValue,
  615. GET_FLAG(OPK_BATCHMODE) ? g_App.szOpkWizIniFile : pszFileName);
  616. }
  617. // Note: pszHelpFilePath must be at least size MAX_PATH
  618. VOID SetWizardHelpFile(LPTSTR pszHelpFilePath)
  619. {
  620. // The help file can be in two location, in the docs folder or
  621. // the current directory. Check the docs folder first.
  622. //
  623. TCHAR szDocsFolder[MAX_PATH] = NULLSTR;
  624. // Build the docs folder path
  625. //
  626. lstrcpyn(szDocsFolder, g_App.szOpkDir,AS(szDocsFolder));
  627. AddPathN(szDocsFolder, DIR_DOCS,AS(szDocsFolder));
  628. // Test if help file exists in docs folder
  629. //
  630. if (pszHelpFilePath) {
  631. if (DirectoryExists(szDocsFolder)) {
  632. lstrcpyn(pszHelpFilePath, szDocsFolder, MAX_PATH);
  633. AddPathN(pszHelpFilePath, FILE_OPKWIZ_HLP, MAX_PATH);
  634. if (!FileExists(pszHelpFilePath)) {
  635. lstrcpyn(pszHelpFilePath, g_App.szOpkDir, MAX_PATH);
  636. AddPathN(pszHelpFilePath, FILE_OPKWIZ_HLP, MAX_PATH);
  637. }
  638. }
  639. else {
  640. lstrcpyn(pszHelpFilePath, g_App.szOpkDir, MAX_PATH);
  641. AddPathN(pszHelpFilePath, FILE_OPKWIZ_HLP, MAX_PATH);
  642. }
  643. }
  644. }