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.

6346 lines
231 KiB

  1. //***************************************************************************
  2. //* Copyright (c) Microsoft Corporation 1995-1996. All rights reserved. *
  3. //***************************************************************************
  4. //* *
  5. //* ADVPACK.C - Advanced helper-dll for WExtract. *
  6. //* *
  7. //***************************************************************************
  8. //***************************************************************************
  9. //* INCLUDE FILES *
  10. //***************************************************************************
  11. #include <io.h>
  12. #include <windows.h>
  13. #include <winerror.h>
  14. #include <ole2.h>
  15. #include "resource.h"
  16. #include "cpldebug.h"
  17. #include "ntapi.h"
  18. #include "advpub.h"
  19. #include "w95pub32.h"
  20. #include "advpack.h"
  21. #include "regstr.h"
  22. #include "globals.h"
  23. #include "sfp.h"
  24. //***************************************************************************
  25. //* GLOBAL VARIABLES *
  26. //***************************************************************************
  27. GETSETUPXERRORTEXT32 pfGetSETUPXErrorText32 = NULL;
  28. CTLSETLDDPATH32 pfCtlSetLddPath32 = NULL;
  29. GENINSTALL32 pfGenInstall32 = NULL;
  30. GENFORMSTRWITHOUTPLACEHOLDERS32 pfGenFormStrWithoutPlaceHolders32 = NULL;
  31. typedef HRESULT (*DLLINSTALL)(BOOL bInstall, LPCWSTR pszCmdLine);
  32. HFONT g_hFont = NULL;
  33. LPCSTR c_szAdvDlls[3] = { "advpack.dll",
  34. "w95inf16.dll",
  35. "w95inf32.dll", };
  36. LPCSTR c_szSetupAPIDlls[2] = { "setupapi.dll",
  37. "cfgmgr32.dll" };
  38. LPCSTR c_szSetupXDlls[1] = { "setupx.dll" };
  39. #define UPDHLPDLLS_FORCED 0x00000001
  40. #define UPDHLPDLLS_ALERTREBOOT 0x00000002
  41. #define MAX_NUM_DRIVES 26
  42. const CHAR c_szQRunPreSetupCommands[] = "QRunPreSetupCommands";
  43. const CHAR c_szQRunPostSetupCommands[] = "QRunPostSetupCommands";
  44. const CHAR c_szRunPreSetupCommands[] = "RunPreSetupCommands";
  45. const CHAR c_szRunPostSetupCommands[] = "RunPostSetupCommands";
  46. BOOL IsDrvChecked( char chDrv );
  47. void SetControlFont();
  48. void SetFontForControl(HWND hwnd, UINT uiID);
  49. void MyGetPlatformSection(LPCSTR lpSec, LPCSTR lpInfFile, LPSTR szNewSection);
  50. //***************************************************************************
  51. //* *
  52. //* NAME: DllMain *
  53. //* *
  54. //* SYNOPSIS: Main entry point for the DLL. *
  55. //* *
  56. //* REQUIRES: hInst: Handle to the DLL instance. *
  57. //* dwReason: Reason for calling this entry point. *
  58. //* dwReserved: Nothing *
  59. //* *
  60. //* RETURNS: BOOL: TRUE if DLL loaded OK, FALSE otherwise. *
  61. //* *
  62. //***************************************************************************
  63. BOOL WINAPI DllMain( HINSTANCE hInst, DWORD dwReason, LPVOID dwReserved )
  64. {
  65. switch (dwReason)
  66. {
  67. case DLL_PROCESS_ATTACH:
  68. // The DLL is being loaded for the first time by a given process.
  69. // Perform per-process initialization here. If the initialization
  70. // is successful, return TRUE; if unsuccessful, return FALSE.
  71. //Initialize the global variable holding the hinstance:
  72. g_hInst = hInst;
  73. // check if need to start the logging file.
  74. if ( g_hAdvLogFile == INVALID_HANDLE_VALUE)
  75. {
  76. AdvStartLogging();
  77. }
  78. AdvWriteToLog("-------------------- advpack.dll is loaded or Attached ------------------------------\r\n");
  79. AdvLogDateAndTime();
  80. break;
  81. case DLL_PROCESS_DETACH:
  82. // The DLL is being unloaded by a given process. Do any
  83. // per-process clean up here, such as undoing what was done in
  84. // DLL_PROCESS_ATTACH. The return value is ignored.
  85. // if logging is turned on, close here.
  86. AdvWriteToLog("-------------------- advpack.dll is unloaded or Detached ----------------------------\r\n");
  87. AdvStopLogging();
  88. break ;
  89. case DLL_THREAD_ATTACH:
  90. // A thread is being created in a process that has already loaded
  91. // this DLL. Perform any per-thread initialization here. The
  92. // return value is ignored.
  93. //Initialize the global variable holding the hinstance --
  94. //NOTE: this is probably taken care of already by DLL_PROCESS_ATTACH.
  95. break;
  96. case DLL_THREAD_DETACH:
  97. // A thread is exiting cleanly in a process that has already
  98. // loaded this DLL. Perform any per-thread clean up here. The
  99. // return value is ignored.
  100. break;
  101. }
  102. return TRUE;
  103. }
  104. //***************************************************************************
  105. //* *
  106. //* NAME: DoInfInstall *
  107. //* *
  108. //* SYNOPSIS: Installs an (advanced) INF file on Win95 or WinNT. *
  109. //* *
  110. //* REQUIRES: AdvPackArgs: Structure containing required info. See *
  111. //* AdvPack.H. *
  112. //* *
  113. //* RETURNS: BOOL: TRUE if successful, FALSE otherwise. *
  114. //* *
  115. //***************************************************************************
  116. HRESULT WINAPI DoInfInstall( ADVPACKARGS *AdvPackArgs )
  117. {
  118. BOOL fSavedContext = FALSE;
  119. HRESULT hr = E_FAIL;
  120. DWORD dwFlags;
  121. AdvWriteToLog("DoInfInstall: InfFile=%1\r\n", AdvPackArgs->lpszInfFilename);
  122. if (!SaveGlobalContext())
  123. {
  124. hr = E_OUTOFMEMORY;
  125. goto done;
  126. }
  127. fSavedContext = TRUE;
  128. ctx.hWnd = AdvPackArgs->hWnd;
  129. ctx.lpszTitle = AdvPackArgs->lpszTitle;
  130. ctx.wOSVer = AdvPackArgs->wOSVer;
  131. ctx.wQuietMode = (WORD) (0xFFFF & AdvPackArgs->dwFlags);
  132. ctx.bCompressed = (AdvPackArgs->dwFlags & ADVFLAGS_COMPRESSED ) ? TRUE : FALSE;
  133. ctx.bUpdHlpDlls = (AdvPackArgs->dwFlags & ADVFLAGS_UPDHLPDLLS) ? TRUE : FALSE;
  134. dwFlags = (AdvPackArgs->dwFlags & ADVFLAGS_NGCONV) ? 0 : COREINSTALL_GRPCONV;
  135. dwFlags |= (AdvPackArgs->dwFlags & ADVFLAGS_DELAYREBOOT) ? COREINSTALL_DELAYREBOOT : 0;
  136. dwFlags |= (AdvPackArgs->dwFlags & ADVFLAGS_DELAYPOSTCMD) ? COREINSTALL_DELAYPOSTCMD : 0;
  137. hr = CoreInstall( AdvPackArgs->lpszInfFilename, AdvPackArgs->lpszInstallSection,
  138. AdvPackArgs->lpszSourceDir, AdvPackArgs->dwPackInstSize,
  139. dwFlags,
  140. NULL );
  141. done:
  142. if (fSavedContext)
  143. {
  144. RestoreGlobalContext();
  145. }
  146. AdvWriteToLog("DoInfInstall: %1 End hr=0x%2!x!\r\n", AdvPackArgs->lpszInfFilename, hr);
  147. return hr;
  148. }
  149. //***************************************************************************
  150. //* *
  151. //* NAME: LaunchINFSection *
  152. //* *
  153. //* SYNOPSIS: Entry point for RunDLL. Takes string parameter and parses *
  154. //* it, then performs GenInstall. *
  155. //* *
  156. //* REQUIRES: *
  157. //* *
  158. //* RETURNS: *
  159. //* *
  160. //***************************************************************************
  161. INT WINAPI LaunchINFSection( HWND hwndOwner, HINSTANCE hInstance,
  162. PSTR pszParms, INT nShow )
  163. {
  164. CHAR szTitle[256] = "Advanced INF Install";
  165. PSTR pszInfFilename = NULL;
  166. PSTR pszSection = NULL;
  167. PSTR pszFlags = NULL;
  168. PSTR pszSmartReboot = NULL;
  169. DWORD dwFlags = 0;
  170. LPSTR pszTemp = NULL;
  171. CHAR chTempChar = '\0';
  172. CHAR szSourceDir[MAX_PATH];
  173. CHAR szFilename[MAX_PATH];
  174. UINT uiErrid = 0;
  175. PSTR pszErrParm1 = NULL;
  176. int iRet = 1; // meaningless return
  177. BOOL fSavedContext = FALSE;
  178. AdvWriteToLog("LaunchINFSection: Param=%1\r\n", pszParms);
  179. if (!SaveGlobalContext())
  180. {
  181. goto done;
  182. }
  183. fSavedContext = TRUE;
  184. ctx.lpszTitle = szTitle;
  185. // Parse the arguments, the last param to GetStringField to ask what quote char to check
  186. pszInfFilename = GetStringField( &pszParms, ",", '\"', TRUE );
  187. pszSection = GetStringField( &pszParms, ",", '\"', TRUE );
  188. pszFlags = GetStringField( &pszParms, ",", '\"', TRUE );
  189. pszSmartReboot = GetStringField( &pszParms, ",", '\"', TRUE );
  190. if ( pszFlags != NULL ) {
  191. dwFlags = My_atol(pszFlags);
  192. }
  193. if ( dwFlags & LIS_QUIET ) {
  194. ctx.wQuietMode = QUIETMODE_ALL;
  195. }
  196. if ( pszInfFilename == NULL || *pszInfFilename == '\0' ) {
  197. uiErrid = IDS_ERR_BAD_SYNTAX;
  198. goto done;
  199. }
  200. if ( ! GetFullPathName( pszInfFilename, sizeof(szFilename), szFilename, &pszTemp ) )
  201. {
  202. uiErrid = IDS_ERR_GET_PATH;
  203. pszErrParm1 = pszInfFilename;
  204. goto done;
  205. }
  206. if ( GetFileAttributes( szFilename ) == 0xFFFFFFFF ) {
  207. // If the file doesn't exist in the current directory, check the
  208. // Windows\inf directory
  209. if ( !GetWindowsDirectory( szFilename, sizeof( szFilename ) ) )
  210. {
  211. uiErrid = IDS_ERR_GET_WIN_DIR;
  212. goto done;
  213. }
  214. AddPath( szFilename, "inf" );
  215. lstrcpy( szSourceDir, szFilename );
  216. if ( (lstrlen(szFilename)+lstrlen(pszInfFilename)+2) > MAX_PATH )
  217. {
  218. uiErrid = IDS_ERR_CANT_FIND_FILE;
  219. pszErrParm1 = pszInfFilename;
  220. goto done;
  221. }
  222. AddPath( szFilename, pszInfFilename );
  223. if ( GetFileAttributes( szFilename ) == 0xFFFFFFFF )
  224. {
  225. uiErrid = IDS_ERR_CANT_FIND_FILE;
  226. pszErrParm1 = pszInfFilename;
  227. goto done;
  228. }
  229. }
  230. else
  231. {
  232. // Generate the source directory from the inf path.
  233. chTempChar = *pszTemp;
  234. *pszTemp = '\0';
  235. lstrcpy( szSourceDir, szFilename );
  236. *pszTemp = chTempChar;
  237. }
  238. if ( !FAILED( CoreInstall( szFilename, pszSection, szSourceDir, 0,
  239. COREINSTALL_PROMPT |
  240. ((dwFlags & LIS_NOGRPCONV)?0:COREINSTALL_GRPCONV) |
  241. COREINSTALL_SMARTREBOOT,
  242. pszSmartReboot ) ) )
  243. {
  244. if (fSavedContext)
  245. {
  246. RestoreGlobalContext();
  247. }
  248. AdvWriteToLog("LaunchINFSection: %1 End Succeed\r\n", szFilename);
  249. return 0;
  250. }
  251. done:
  252. if ( uiErrid != 0 )
  253. ErrorMsg1Param( ctx.hWnd, uiErrid, pszErrParm1 );
  254. if (fSavedContext)
  255. {
  256. RestoreGlobalContext();
  257. }
  258. AdvWriteToLog("LaunchINFSection: %1 End Failed\r\n", szFilename);
  259. return 1;
  260. }
  261. //***************************************************************************
  262. //* *
  263. //* NAME: RunSetupCommand *
  264. //* *
  265. //* SYNOPSIS: Download Component entry point. Runs a setup command. *
  266. //* *
  267. //* REQUIRES: hWnd: Handle to parent window. *
  268. //* szCmdName: Name of command to run (INF or EXE) *
  269. //* szInfSection: INF section to install with. NULL=default *
  270. //* szDir: Directory containing source files *
  271. //* lpszTitle: Name to attach to windows. *
  272. //* phEXE: Handle of EXE to wait on. *
  273. //* dwFlags: Various flags to control behavior (advpub.h)*
  274. //* pvReserved: Reserved for future use. *
  275. //* *
  276. //* RETURNS: HRESULT: See advpub.h *
  277. //* *
  278. //***************************************************************************
  279. HRESULT WINAPI RunSetupCommand( HWND hWnd, LPCSTR szCmdName,
  280. LPCSTR szInfSection, LPCSTR szDir,
  281. LPCSTR lpszTitle, HANDLE *phEXE,
  282. DWORD dwFlags, LPVOID pvReserved )
  283. {
  284. HRESULT hReturnCode = S_OK;
  285. DWORD dwRebootCheck = 0;
  286. DWORD dwCoreInstallFlags = 0;
  287. BOOL fSavedContext = FALSE;
  288. AdvWriteToLog("RunSetupCommand:");
  289. if (!SaveGlobalContext())
  290. {
  291. hReturnCode = E_OUTOFMEMORY;
  292. goto done;
  293. }
  294. fSavedContext = TRUE;
  295. // Validate parameters:
  296. if ( szCmdName == NULL || szDir == NULL ) {
  297. return E_INVALIDARG;
  298. }
  299. AdvWriteToLog(" Cmd=%1\r\n", szCmdName);
  300. ctx.hWnd = hWnd;
  301. ctx.lpszTitle = (LPSTR) lpszTitle;
  302. // If caller passes invalid HWND, we will silently turn off UI.
  303. // NULL uses Desktop as window and passing INVALID_HANDLE sets quiet mode.
  304. if ( hWnd && !IsWindow(hWnd) ) {
  305. dwFlags |= RSC_FLAG_QUIET;
  306. hWnd = NULL;
  307. }
  308. if ( dwFlags & RSC_FLAG_QUIET ) {
  309. ctx.wQuietMode = QUIETMODE_ALL;
  310. }
  311. else
  312. {
  313. ctx.wQuietMode = 0;
  314. }
  315. ctx.bUpdHlpDlls = ( dwFlags & RSC_FLAG_UPDHLPDLLS ) ? TRUE : FALSE;
  316. // Check flags to see if it's an INF command
  317. if ( dwFlags & RSC_FLAG_INF )
  318. {
  319. if(!(dwFlags & RSC_FLAG_NGCONV))
  320. dwCoreInstallFlags |= COREINSTALL_GRPCONV;
  321. if (dwFlags & RSC_FLAG_DELAYREGISTEROCX)
  322. dwCoreInstallFlags |= COREINSTALL_DELAYREGISTEROCX;
  323. if (dwFlags & RSC_FLAG_SETUPAPI )
  324. dwCoreInstallFlags |= COREINSTALL_SETUPAPI;
  325. hReturnCode = CoreInstall( (PSTR) szCmdName, szInfSection,
  326. (PSTR) szDir, 0, dwCoreInstallFlags,
  327. NULL );
  328. if ( FAILED( hReturnCode ) ) {
  329. goto done;
  330. }
  331. } else {
  332. if ( ! CheckOSVersion() ) {
  333. hReturnCode = HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION);
  334. goto done;
  335. }
  336. dwRebootCheck = InternalNeedRebootInit( ctx.wOSVer );
  337. hReturnCode = LaunchAndWait( (LPSTR)szCmdName, (LPSTR)szDir, phEXE, INFINITE, 0 );
  338. if ( hReturnCode == S_OK )
  339. {
  340. if ( phEXE )
  341. hReturnCode = S_ASYNCHRONOUS;
  342. }
  343. else
  344. {
  345. hReturnCode = HRESULT_FROM_WIN32(GetLastError());
  346. goto done;
  347. }
  348. if ( hReturnCode == S_OK
  349. && InternalNeedReboot( dwRebootCheck, ctx.wOSVer ) )
  350. {
  351. hReturnCode = ERROR_SUCCESS_REBOOT_REQUIRED;
  352. }
  353. }
  354. done:
  355. if (fSavedContext)
  356. {
  357. RestoreGlobalContext();
  358. }
  359. AdvWriteToLog("RunSetupCommand: Cmd=%1 End hr=0x%2!x!\r\n", szCmdName, hReturnCode);
  360. return hReturnCode;
  361. }
  362. //***************************************************************************
  363. //* *
  364. //* NAME: GetInfInstallSectionName *
  365. //* *
  366. //* SYNOPSIS: Gets the name of the section to install with. *
  367. //* *
  368. //* REQUIRES: szInfFilename: Name of INF to find install section in. *
  369. //* szInfSection: Name of INF section to install with. If *
  370. //* NULL, then return required size of string. *
  371. //* If "\0", use DefaultInstall. If *
  372. //* "DefaultInstall" and running NT, then check *
  373. //* for "DefaultInstall.NT section. Anything *
  374. //* else will leave the section name alone. *
  375. //* dwSize: Size of szInfSection buffer. If not big *
  376. //* enough to hold string, then required size *
  377. //* is returned. *
  378. //* *
  379. //* RETURNS: DWORD: 0 if error, otherwise size of section name. *
  380. //* *
  381. //***************************************************************************
  382. DWORD WINAPI GetInfInstallSectionName( LPCSTR pszInfFilename,
  383. LPSTR pszInfSection, DWORD dwSize )
  384. {
  385. CHAR achTemp[5];
  386. char szGivenInfSection[MAX_PATH];
  387. char szNewInfSection[MAX_PATH];
  388. DWORD dwStringLength;
  389. DWORD dwRequiredSize;
  390. static const CHAR achDefaultInstall[] = "DefaultInstall";
  391. //static const CHAR achDefaultInstallNT[] = "DefaultInstall.NT";
  392. // On NTx86:
  393. //(1) if [<Sec>.NTx86] present, this section get GenInstall, exit.
  394. //(2) if (1) is not present, [<sec>.NT] present and get GenInstal, exitl;
  395. //(3) if both [<sec>.NTx86] and [<Sec>.NT] not present, [<Sec>] section get GenInstall;
  396. //(4) if none of the sections in (1), (2), (3) exist, do nothing.
  397. // the same logic apply to NTAlpha as well.
  398. // On win9x:
  399. //(1) if [<sec>.Win] present, GetInstall it.
  400. //(2) if (1) is not present, GenInstall [<Sec>]
  401. // otherwise, do nothing.
  402. if ( ! CheckOSVersion() ) {
  403. return 0;
  404. }
  405. // If we were passed a NULL for the install section, then assume
  406. // they want the "DefaultInstall" section.
  407. if ( pszInfSection == NULL || (*pszInfSection) == '\0' )
  408. lstrcpy(szGivenInfSection, achDefaultInstall);
  409. else
  410. lstrcpy(szGivenInfSection, pszInfSection);
  411. MyGetPlatformSection(szGivenInfSection, pszInfFilename, szNewInfSection);
  412. dwRequiredSize = lstrlen( szNewInfSection ) + 1;
  413. if ( pszInfSection != NULL && (dwRequiredSize <= dwSize) )
  414. {
  415. lstrcpy( pszInfSection, szNewInfSection );
  416. }
  417. return dwRequiredSize;
  418. }
  419. //***************************************************************************
  420. //* *
  421. //* NAME: NeedRebootInit *
  422. //* *
  423. //* SYNOPSIS: Self-registers the OCX. *
  424. //* *
  425. //* REQUIRES: *
  426. //* *
  427. //* RETURNS: *
  428. //* *
  429. //***************************************************************************
  430. DWORD WINAPI NeedRebootInit( VOID )
  431. {
  432. if ( ! CheckOSVersion() ) {
  433. return 0;
  434. }
  435. return InternalNeedRebootInit( ctx.wOSVer );
  436. }
  437. //***************************************************************************
  438. //* *
  439. //* NAME: NeedReboot *
  440. //* *
  441. //* SYNOPSIS: Self-registers the OCX. *
  442. //* *
  443. //* REQUIRES: *
  444. //* *
  445. //* RETURNS: *
  446. //* *
  447. //***************************************************************************
  448. BOOL WINAPI NeedReboot( DWORD dwRebootCheck )
  449. {
  450. if ( ! CheckOSVersion() ) {
  451. return 0;
  452. }
  453. return InternalNeedReboot( dwRebootCheck, ctx.wOSVer );
  454. }
  455. //***************************************************************************
  456. //* *
  457. //* NAME: TranslateInfString *
  458. //* *
  459. //* SYNOPSIS: Translates a string in an Advanced inf file -- replaces *
  460. //* LDIDs with the directory. *
  461. //* *
  462. //* REQUIRES: *
  463. //* *
  464. //* RETURNS: *
  465. //* *
  466. //***************************************************************************
  467. HRESULT WINAPI TranslateInfString( PCSTR pszInfFilename, PCSTR pszInstallSection,
  468. PCSTR pszTranslateSection, PCSTR pszTranslateKey,
  469. PSTR pszBuffer, DWORD dwBufferSize,
  470. PDWORD pdwRequiredSize, PVOID pvReserved )
  471. {
  472. HRESULT hReturnCode = S_OK;
  473. CHAR szRealInstallSection[256];
  474. BOOL fSavedContext = FALSE;
  475. DWORD dwFlags = 0;
  476. AdvWriteToLog("TranslateInfString:" );
  477. if (!SaveGlobalContext())
  478. {
  479. hReturnCode = E_OUTOFMEMORY;
  480. goto done;
  481. }
  482. fSavedContext = TRUE;
  483. ctx.wQuietMode = QUIETMODE_ALL;
  484. // Validate parameters
  485. if ( pszInfFilename == NULL || pszTranslateSection == NULL
  486. || pszTranslateKey == NULL || pdwRequiredSize == NULL )
  487. {
  488. hReturnCode = E_INVALIDARG;
  489. goto done;
  490. }
  491. AdvWriteToLog("Inf=%1 Sec=%2 Key=%3\r\n", pszInfFilename, pszTranslateSection, pszTranslateKey);
  492. if ((ULONG_PTR)pvReserved & (ULONG_PTR)RSC_FLAG_SETUPAPI )
  493. dwFlags |= COREINSTALL_SETUPAPI;
  494. hReturnCode = CommonInstallInit( pszInfFilename, pszInstallSection,
  495. szRealInstallSection, sizeof(szRealInstallSection), NULL, FALSE, dwFlags );
  496. if ( FAILED( hReturnCode ) ) {
  497. goto done;
  498. }
  499. hReturnCode = SetLDIDs( (LPSTR) pszInfFilename, szRealInstallSection, 0, NULL );
  500. if ( FAILED( hReturnCode ) ) {
  501. goto done;
  502. }
  503. hReturnCode = GetTranslatedString( pszInfFilename, pszTranslateSection, pszTranslateKey,
  504. pszBuffer, dwBufferSize, pdwRequiredSize );
  505. if ( FAILED( hReturnCode ) ) {
  506. goto done;
  507. }
  508. done:
  509. CommonInstallCleanup();
  510. if (fSavedContext)
  511. {
  512. RestoreGlobalContext();
  513. }
  514. AdvWriteToLog("TranslateInfString: End hr=0x%1!x!\r\n",hReturnCode);
  515. return hReturnCode;
  516. }
  517. //***************************************************************************
  518. //* *
  519. //* NAME: RegisterOCX *
  520. //* *
  521. //* SYNOPSIS: *
  522. //* *
  523. //* REQUIRES: *
  524. //* *
  525. //* RETURNS: *
  526. //* *
  527. //***************************************************************************
  528. INT WINAPI RegisterOCX( HWND hwndOwner, HINSTANCE hInstance, PSTR pszParms, INT nShow )
  529. {
  530. CHAR szTitle[] = "Advpack RegisterOCX()";
  531. BOOL fOleInitialized = TRUE;
  532. INT nReturnCode = 0;
  533. REGOCXDATA RegOCX = { 0 };
  534. AdvWriteToLog("RegisterOCX: Param=%1\r\n", pszParms);
  535. ctx.lpszTitle = szTitle;
  536. // Parse the arguments, SETUP engine has processed \" so we only need to check on \'
  537. RegOCX.pszOCX = GetStringField( &pszParms, ",", '\"', TRUE );
  538. RegOCX.pszSwitch = GetStringField( &pszParms, ",", '\"', TRUE );
  539. RegOCX.pszParam = GetStringField( &pszParms, ",", '\"', TRUE );
  540. if ( RegOCX.pszOCX == NULL || *(RegOCX.pszOCX) == '\0' ) {
  541. ErrorMsg( ctx.hWnd, IDS_ERR_BAD_SYNTAX2 );
  542. nReturnCode = 1;
  543. goto done;
  544. }
  545. if ( FAILED( OleInitialize( NULL ) ) ) {
  546. fOleInitialized = FALSE;
  547. }
  548. // single OCX register, use 0, 0 for last params
  549. //
  550. if ( ! InstallOCX( &RegOCX, TRUE, TRUE, 0 ) ) {
  551. ErrorMsg1Param( ctx.hWnd, IDS_ERR_REG_OCX, RegOCX.pszOCX );
  552. nReturnCode = 1;
  553. }
  554. done:
  555. if ( fOleInitialized ) {
  556. OleUninitialize();
  557. }
  558. AdvWriteToLog("RegisterOCX: Param=%1 End status=%2\r\n", RegOCX.pszOCX, (nReturnCode==0)?"Succeed":"Failed");
  559. return nReturnCode;
  560. }
  561. //***************************************************************************
  562. //* *
  563. //* NAME: CommonInstallInit *
  564. //* *
  565. //* SYNOPSIS: *
  566. //* *
  567. //* *
  568. //* REQUIRES: *
  569. //* *
  570. //* RETURNS: *
  571. //* *
  572. //***************************************************************************
  573. HRESULT CommonInstallInit( PCSTR c_pszInfFilename, PCSTR c_pszSection,
  574. PSTR pszRealSection, DWORD dwRealSectionSize,
  575. PCSTR c_pszSourceDir, BOOL fUpdDlls, DWORD dwFlags )
  576. {
  577. HRESULT hReturnCode = S_OK;
  578. DWORD dwSize = 0;
  579. if ( ! CheckOSVersion() ) {
  580. hReturnCode = HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION);
  581. goto done;
  582. }
  583. if ( ! ctx.fOSSupportsINFInstalls ) {
  584. ErrorMsg( ctx.hWnd, IDS_ERR_NO_INF_INSTALLS );
  585. hReturnCode = HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION);
  586. goto done;
  587. }
  588. if ( c_pszSection == NULL ) {
  589. *pszRealSection = '\0';
  590. } else {
  591. lstrcpy( pszRealSection, c_pszSection );
  592. }
  593. dwSize = GetInfInstallSectionName( c_pszInfFilename, pszRealSection, dwRealSectionSize );
  594. if ( dwSize == 0 || dwSize > dwRealSectionSize ) {
  595. hReturnCode = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  596. goto done;
  597. }
  598. if ( ! LoadSetupLib( c_pszInfFilename, pszRealSection, fUpdDlls, dwFlags ) ) {
  599. hReturnCode = HRESULT_FROM_WIN32(GetLastError());
  600. goto done;
  601. }
  602. if ( ctx.dwSetupEngine == ENGINE_SETUPAPI ) {
  603. if ( FAILED(hReturnCode = MySetupOpenInfFile( c_pszInfFilename)) )
  604. goto done;
  605. }
  606. if ( c_pszSourceDir != NULL ) {
  607. hReturnCode = SetLDIDs( c_pszInfFilename, pszRealSection,
  608. 0, c_pszSourceDir );
  609. if ( FAILED(hReturnCode) ) {
  610. goto done;
  611. }
  612. }
  613. if ( ! IsGoodAdvancedInfVersion( c_pszInfFilename ) ) {
  614. hReturnCode = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND);
  615. goto done;
  616. }
  617. done:
  618. return hReturnCode;
  619. }
  620. //***************************************************************************
  621. //* *
  622. //* NAME: CommonInstallCleanup *
  623. //* *
  624. //* SYNOPSIS: *
  625. //* *
  626. //* *
  627. //* REQUIRES: *
  628. //* *
  629. //* RETURNS: *
  630. //* *
  631. //***************************************************************************
  632. VOID CommonInstallCleanup( VOID )
  633. {
  634. if ( ctx.dwSetupEngine == ENGINE_SETUPAPI ) {
  635. MySetupCloseInfFile();
  636. }
  637. UnloadSetupLib();
  638. }
  639. //***************************************************************************
  640. //* *
  641. //* NAME: CoreInstall *
  642. //* *
  643. //* SYNOPSIS: Installs an (advanced) INF file on Win95 or WinNT. *
  644. //* *
  645. //* REQUIRES: *
  646. //* *
  647. //* RETURNS: *
  648. //* *
  649. //***************************************************************************
  650. HRESULT CoreInstall( PCSTR c_pszInfFilename, PCSTR c_pszSection,
  651. PCSTR c_pszSourceDir, DWORD dwInstallSize, DWORD dwFlags,
  652. PCSTR pcszSmartRebootOverride )
  653. {
  654. static const CHAR c_szSmartReboot[] = "SmartReboot";
  655. static const CHAR c_szSmartRebootDefault[] = "I";
  656. HRESULT hReturnCode = S_OK;
  657. DWORD dwRebootCheck = 0;
  658. BOOL fNeedReboot = FALSE;
  659. HKEY hkey = NULL;
  660. CHAR szInstallSection[256];
  661. CHAR szTitle[256];
  662. PSTR pszOldTitle = NULL;
  663. UINT id = IDCANCEL;
  664. BOOL fRebootCheck = TRUE;
  665. CHAR szSmartRebootValue[4]; // Allocate 4 chars for SmartReboot value
  666. BOOL fRealNeedReboot = FALSE;
  667. CHAR szCatalogName[512] = "";
  668. #define GRPCONV "grpconv.exe -o"
  669. AdvWriteToLog("CoreInstall: InfFile=%1 ", c_pszInfFilename);
  670. lstrcpy( szSmartRebootValue, c_szSmartRebootDefault );
  671. hReturnCode = CommonInstallInit( c_pszInfFilename, c_pszSection,
  672. szInstallSection, sizeof(szInstallSection),
  673. c_pszSourceDir, TRUE, dwFlags );
  674. if ( FAILED( hReturnCode ) ) {
  675. goto done;
  676. }
  677. AdvWriteToLog("InstallSection=%1\r\n", szInstallSection);
  678. // check Admin right if INF specified
  679. if (GetTranslatedInt(c_pszInfFilename, szInstallSection, ADVINF_CHKADMIN, 0))
  680. {
  681. if ( (ctx.wOSVer != _OSVER_WIN95) && !IsNTAdmin( 0, NULL) )
  682. {
  683. WORD wSav = ctx.wQuietMode;
  684. ctx.wQuietMode |= QUIETMODE_SHOWMSG;
  685. hReturnCode = E_ABORT;
  686. ErrorMsg( ctx.hWnd, IDS_ERR_NONTADMIN );
  687. ctx.wQuietMode = wSav;
  688. goto done;
  689. }
  690. }
  691. if ( (dwFlags & COREINSTALL_PROMPT) && !(dwFlags & COREINSTALL_ROLLBACK) )
  692. {
  693. pszOldTitle = ctx.lpszTitle;
  694. if ( BeginPrompt( c_pszInfFilename, szInstallSection, szTitle, sizeof(szTitle) )
  695. == IDCANCEL )
  696. {
  697. hReturnCode = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  698. goto done;
  699. }
  700. }
  701. if ( !(dwFlags & COREINSTALL_DELAYREBOOT) )
  702. dwRebootCheck = InternalNeedRebootInit( ctx.wOSVer );
  703. // the flag is so far used to control the post setup commands, so pre setup command pass flag 0, NeedReboot FALSE
  704. hReturnCode = RunCommandsSections( c_pszInfFilename, szInstallSection, c_szRunPreSetupCommands, c_pszSourceDir, 0, FALSE );
  705. if ( FAILED( hReturnCode ) )
  706. goto done;
  707. // first set LDID, then all the INF processing can use LDIDs
  708. hReturnCode = SetLDIDs( (PSTR) c_pszInfFilename, szInstallSection, dwInstallSize, NULL );
  709. if ( FAILED( hReturnCode ) )
  710. {
  711. goto done;
  712. }
  713. hReturnCode = RunPatchingCommands( c_pszInfFilename, szInstallSection, c_pszSourceDir);
  714. if ( FAILED( hReturnCode ) )
  715. {
  716. goto done;
  717. }
  718. // Remove Old backup if needed; based on the ComponentVersion stamp in INF install section
  719. //
  720. if (!(dwFlags & COREINSTALL_ROLLBACK) )
  721. RemoveBackupBaseOnVer( c_pszInfFilename, szInstallSection );
  722. // get the catalog name, if specified
  723. // BUGBUG: (pritobla): if not on Millen, where should we copy the catalog for migration scenario?
  724. ZeroMemory(szCatalogName, sizeof(szCatalogName));
  725. // if ROLLBKDOALL is specified, try to get the catalog name from the registry;
  726. // if not found, get it from the inf
  727. if (dwFlags & COREINSTALL_ROLLBKDOALL)
  728. {
  729. CHAR szModule[MAX_PATH];
  730. *szModule = '\0';
  731. GetTranslatedString(c_pszInfFilename, szInstallSection, ADVINF_MODNAME, szModule, sizeof(szModule), NULL);
  732. if (*szModule)
  733. {
  734. CHAR szKey[MAX_PATH];
  735. HKEY hkCatalogKey;
  736. lstrcpy(szKey, REGKEY_SAVERESTORE);
  737. AddPath(szKey, szModule);
  738. AddPath(szKey, REGSUBK_CATALOGS);
  739. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hkCatalogKey) == ERROR_SUCCESS)
  740. {
  741. PSTR pszCatalog;
  742. DWORD dwIndex, dwSize;
  743. DWORD dwSizeSoFar;
  744. dwSizeSoFar = 0;
  745. // build the list of catalogs
  746. pszCatalog = szCatalogName;
  747. dwIndex = 0;
  748. dwSize = sizeof(szCatalogName) - 1;
  749. while (RegEnumValue(hkCatalogKey, dwIndex, pszCatalog, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  750. {
  751. dwSizeSoFar += dwSize + 1;
  752. pszCatalog += dwSize + 1;
  753. dwIndex++;
  754. dwSize = sizeof(szCatalogName) - 1 - dwSizeSoFar;
  755. }
  756. RegCloseKey(hkCatalogKey);
  757. }
  758. }
  759. }
  760. if (*szCatalogName == '\0')
  761. GetTranslatedString(c_pszInfFilename, szInstallSection, ADVINF_CATALOG_NAME, szCatalogName, sizeof(szCatalogName), NULL);
  762. if (*szCatalogName)
  763. {
  764. // load sfc.dll and the relevant proc's
  765. if (!LoadSfcDLL())
  766. {
  767. // couldn't load -- so empty out CatalogName
  768. *szCatalogName = '\0';
  769. }
  770. }
  771. // before we start doing any work, we need to know if this is backup install mode. If it is,
  772. // we will have to backup the Reg data and file data before continuing.
  773. if ( (dwFlags & COREINSTALL_BKINSTALL) || ( dwFlags & COREINSTALL_ROLLBACK ) )
  774. {
  775. // if it is rollback case, we don't need to do real GenInstall. We need to unregister the previous
  776. // register section first
  777. //
  778. if ( dwFlags & COREINSTALL_ROLLBACK )
  779. {
  780. RegisterOCXs( (PSTR) c_pszInfFilename, szInstallSection, FALSE, FALSE, dwFlags );
  781. }
  782. hReturnCode = SaveRestoreInfo( c_pszInfFilename, szInstallSection, c_pszSourceDir, szCatalogName, dwFlags );
  783. if ( FAILED( hReturnCode ) )
  784. goto done;
  785. // if it is rollback case, we don't need to do real GenInstall. All needed are registering OCXs
  786. if ( dwFlags & COREINSTALL_ROLLBACK )
  787. {
  788. // here is very tricky, if the reboot needed and old file can not be registerred,
  789. // if we just add entries blindly to the RunOnce(ex), it will cause the fault at reboot
  790. // time. So we have to make sure if we need to do this re-register thing or just use
  791. // DelReg and AddReg take care it. Need revisit here!!!
  792. //
  793. fRealNeedReboot = InternalNeedReboot( dwRebootCheck, ctx.wOSVer );
  794. RegisterOCXs( (PSTR) c_pszInfFilename, szInstallSection, fRealNeedReboot, TRUE, dwFlags );
  795. if ( fRealNeedReboot )
  796. {
  797. hReturnCode = ERROR_SUCCESS_REBOOT_REQUIRED;
  798. }
  799. // process DelDirs INF line
  800. DelDirs( c_pszInfFilename, szInstallSection );
  801. goto done;
  802. }
  803. }
  804. // No error handling because it's an uninstall. If unregistering fails, we
  805. // should continue with the uninstall.
  806. // BUGBUG: if it is COREINSTALL_BKINSTALL case, do we need to unregister the Existing OCXs
  807. // get ready for registering the new once. Maybe have foll. call do it based on flags
  808. //
  809. if ( ctx.wOSVer != _OSVER_WINNT3X )
  810. RegisterOCXs( (PSTR) c_pszInfFilename, szInstallSection, FALSE, FALSE, dwFlags );
  811. // if a catalog is specified, try to install it before calling GenInstall()
  812. if (*szCatalogName)
  813. {
  814. DWORD dwRet;
  815. CHAR szFullCatalogName[MAX_PATH];
  816. lstrcpy(szFullCatalogName, c_pszSourceDir);
  817. AddPath(szFullCatalogName, szCatalogName);
  818. dwRet = g_pfSfpInstallCatalog(szFullCatalogName, NULL);
  819. AdvWriteToLog("CoreInstall: SfpInstallCatalog returned=%1!lu!\r\n", dwRet);
  820. UnloadSfcDLL();
  821. if (dwRet != ERROR_SUCCESS && dwRet != ERROR_FILE_NOT_FOUND)
  822. {
  823. // if SfpInstallCatalog return already an HRESULT, use it.
  824. // otherwise convert to na HRESULT.
  825. if (dwRet & 0x80000000)
  826. hReturnCode = dwRet;
  827. else
  828. hReturnCode = HRESULT_FROM_WIN32(dwRet);
  829. goto done;
  830. }
  831. if (dwRet == ERROR_FILE_NOT_FOUND)
  832. *szCatalogName = '\0';
  833. }
  834. AdvWriteToLog("GenInstall: Sec=%1\r\n", szInstallSection);
  835. hReturnCode = GenInstall( (PSTR) c_pszInfFilename, szInstallSection, (PSTR) c_pszSourceDir );
  836. AdvWriteToLog("GenInstall return: Sec=%1 hr=0x%2!x!\r\n", szInstallSection, hReturnCode);
  837. if ( FAILED( hReturnCode ) )
  838. goto done;
  839. fRealNeedReboot = InternalNeedReboot( dwRebootCheck, ctx.wOSVer );
  840. fNeedReboot = fRealNeedReboot;
  841. // Process SmartReboot key
  842. if ( dwFlags & COREINSTALL_SMARTREBOOT )
  843. {
  844. if ( pcszSmartRebootOverride != NULL && *pcszSmartRebootOverride != '\0' )
  845. {
  846. lstrcpy( szSmartRebootValue, pcszSmartRebootOverride );
  847. }
  848. else
  849. {
  850. if ( FAILED( GetTranslatedString( c_pszInfFilename, szInstallSection, c_szSmartReboot,
  851. szSmartRebootValue, sizeof(szSmartRebootValue), NULL) ) )
  852. {
  853. lstrcpy( szSmartRebootValue, c_szSmartRebootDefault );
  854. }
  855. }
  856. switch ( szSmartRebootValue[0] )
  857. {
  858. case 'a':
  859. case 'A':
  860. fNeedReboot = TRUE;
  861. break;
  862. case 'N':
  863. case 'n':
  864. fNeedReboot = FALSE;
  865. break;
  866. case '\0':
  867. lstrcpy( szSmartRebootValue, c_szSmartRebootDefault );
  868. break;
  869. }
  870. }
  871. if ( ctx.wOSVer != _OSVER_WINNT3X )
  872. {
  873. if ( ! RegisterOCXs( (PSTR) c_pszInfFilename, szInstallSection, (fNeedReboot || fRealNeedReboot), TRUE, dwFlags ) )
  874. {
  875. hReturnCode = HRESULT_FROM_WIN32(GetLastError());
  876. goto done;
  877. }
  878. }
  879. // The reason we pass in the reboot flag is to be consistent with register OCX
  880. hReturnCode = RunCommandsSections( c_pszInfFilename, szInstallSection, c_szRunPostSetupCommands, c_pszSourceDir, dwFlags, (fNeedReboot || fRealNeedReboot) );
  881. if ( FAILED( hReturnCode ) )
  882. goto done;
  883. // process PerUserInstall section
  884. hReturnCode = ProcessPerUserSec( c_pszInfFilename, szInstallSection );
  885. if ( FAILED( hReturnCode ) )
  886. goto done;
  887. // if /R:P is passed in, check absolute reboot condition rather than delta
  888. if ( (dwFlags & COREINSTALL_DELAYPOSTCMD) || (hReturnCode == ERROR_SUCCESS_REBOOT_REQUIRED) )
  889. dwRebootCheck = 0;
  890. // Do we need a reboot now? Lets find out...
  891. fRealNeedReboot = InternalNeedReboot( dwRebootCheck, ctx.wOSVer );
  892. if (GetTranslatedInt(c_pszInfFilename, szInstallSection, "Reboot", 0))
  893. {
  894. fRealNeedReboot = TRUE;
  895. }
  896. if ( fRealNeedReboot )
  897. {
  898. hReturnCode = ERROR_SUCCESS_REBOOT_REQUIRED;
  899. }
  900. // Process SmartReboot key
  901. if ( szSmartRebootValue[0] == 'i' || szSmartRebootValue[0] == 'I' )
  902. {
  903. fNeedReboot = fRealNeedReboot;
  904. }
  905. if ( ctx.wOSVer != _OSVER_WINNT3X )
  906. {
  907. if ( NeedToRunGrpconv() )
  908. {
  909. if ( (dwFlags & COREINSTALL_GRPCONV) && !fNeedReboot && !fRealNeedReboot )
  910. {
  911. char szDir[MAX_PATH];
  912. GetWindowsDirectory( szDir, sizeof(szDir) );
  913. // only wait this unmoral member 30 secs
  914. LaunchAndWait( GRPCONV, szDir, NULL, 30000, (ctx.wQuietMode & QUIETMODE_ALL)? RUNCMDS_QUIET : 0 );
  915. }
  916. else
  917. {
  918. if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUNONCE, 0, NULL,
  919. REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, NULL) == ERROR_SUCCESS )
  920. {
  921. RegSetValueEx( hkey, "GrpConv", 0, REG_SZ, (LPBYTE) GRPCONV, lstrlen(GRPCONV) + 1 );
  922. RegCloseKey(hkey);
  923. }
  924. }
  925. }
  926. }
  927. // process DelDirs INF line
  928. DelDirs( c_pszInfFilename, szInstallSection );
  929. if ( dwFlags & COREINSTALL_PROMPT ) {
  930. EndPrompt( c_pszInfFilename, szInstallSection );
  931. }
  932. // process Cleanup INF line
  933. DoCleanup( c_pszInfFilename, szInstallSection );
  934. if ( fNeedReboot && (dwFlags & COREINSTALL_SMARTREBOOT) )
  935. {
  936. if ( szSmartRebootValue[1] == 's' || szSmartRebootValue[1] == 'S' )
  937. {
  938. id = IDYES;
  939. }
  940. else
  941. {
  942. id = MsgBox( ctx.hWnd, IDS_RESTARTYESNO, MB_ICONINFORMATION, MB_YESNO );
  943. }
  944. if ( id == IDYES )
  945. {
  946. if ( ctx.wOSVer == _OSVER_WIN95 )
  947. {
  948. // By default (all platforms), we assume powerdown is possible
  949. id = ExitWindowsEx( EWX_REBOOT, 0 );
  950. }
  951. else
  952. {
  953. MyNTReboot();
  954. }
  955. }
  956. }
  957. done:
  958. if ( dwFlags & COREINSTALL_PROMPT ) {
  959. ctx.lpszTitle = pszOldTitle;
  960. }
  961. if (*szCatalogName)
  962. UnloadSfcDLL();
  963. CommonInstallCleanup();
  964. AdvWriteToLog("CoreInstall: End InfFile=%1 hr=0x%2!x!\r\n", c_pszInfFilename, hReturnCode);
  965. return hReturnCode;
  966. }
  967. //***************************************************************************
  968. //* *
  969. //* NAME: RunCommandsSections *
  970. //* *
  971. //* SYNOPSIS: *
  972. //* *
  973. //* REQUIRES: *
  974. //* *
  975. //* RETURNS: *
  976. //* *
  977. //***************************************************************************
  978. HRESULT RunCommandsSections( PCSTR pcszInf, PCSTR pcszSection, PCSTR c_pszKey,
  979. PCSTR c_pszSourceDir, DWORD dwFlags, BOOL bNeedReboot )
  980. {
  981. HRESULT hRet = S_OK;
  982. char szBuf[MAX_INFLINE];
  983. LPSTR pszOneSec, pszStr, pszFlag;
  984. DWORD dwCmdsFlags;
  985. szBuf[0] = 0;
  986. pszStr = szBuf;
  987. if ( FAILED(GetTranslatedString( pcszInf, pcszSection, c_pszKey, szBuf, sizeof(szBuf), NULL)))
  988. szBuf[0] = 0;
  989. // Parse the arguments, SETUP engine is not called to process this line. So we check on \".
  990. pszOneSec = GetStringField( &pszStr, ",", '\"', TRUE );
  991. while ( (hRet == S_OK) && pszOneSec && *pszOneSec )
  992. {
  993. dwCmdsFlags = 0;
  994. pszFlag = ANSIStrChr( pszOneSec, ':' );
  995. if ( pszFlag && (*pszFlag == ':') )
  996. {
  997. pszFlag = CharNext(pszFlag);
  998. *CharPrev(pszOneSec, pszFlag) = '\0';
  999. dwCmdsFlags = AtoL(pszFlag);
  1000. }
  1001. if ( (dwFlags & COREINSTALL_DELAYPOSTCMD) &&
  1002. (!lstrcmpi(c_pszKey, c_szRunPostSetupCommands)) )
  1003. {
  1004. dwCmdsFlags |= RUNCMDS_DELAYPOSTCMD;
  1005. }
  1006. hRet = RunCommands( pcszInf, pszOneSec, c_pszSourceDir, dwCmdsFlags, bNeedReboot );
  1007. pszOneSec = GetStringField( &pszStr, ",", '\"', TRUE );
  1008. }
  1009. return hRet;
  1010. }
  1011. //***************************************************************************
  1012. //* *
  1013. //* NAME: RunCommands *
  1014. //* *
  1015. //* SYNOPSIS: *
  1016. //* *
  1017. //* REQUIRES: *
  1018. //* *
  1019. //* RETURNS: *
  1020. //* *
  1021. //***************************************************************************
  1022. HRESULT RunCommands( PCSTR pcszInfFilename, PCSTR pcszSection, PCSTR c_pszSourceDir,
  1023. DWORD dwCmdsFlags, BOOL bNeedReboot )
  1024. {
  1025. HRESULT hReturnCode = S_OK;
  1026. DWORD i = 0;
  1027. PSTR pszCommand = NULL, pszNewCommand;
  1028. CHAR szMessage[BIG_STRING];
  1029. AdvWriteToLog("RunCommands: Sec=%1\r\n", pcszSection);
  1030. pszNewCommand = (LPSTR) LocalAlloc( LPTR, BUF_1K );
  1031. if ( !pszNewCommand )
  1032. {
  1033. hReturnCode = HRESULT_FROM_WIN32(GetLastError());
  1034. goto done;
  1035. }
  1036. for ( i = 0; ; i += 1 )
  1037. {
  1038. if ( FAILED( GetTranslatedLine( pcszInfFilename, pcszSection,
  1039. i, &pszCommand, NULL ) ) || !pszCommand )
  1040. {
  1041. break;
  1042. }
  1043. // check if this command need to be delayed
  1044. // if there is reboot condition regardless who cause it, delay.
  1045. if ( (dwCmdsFlags & RUNCMDS_DELAYPOSTCMD) &&
  1046. (InternalNeedReboot( 0, ctx.wOSVer ) || bNeedReboot ) )
  1047. {
  1048. static int iSubKeyNum = 989;
  1049. static int iLine = 0;
  1050. static BOOL bRunOnceEx = FALSE;
  1051. HKEY hKey, hSubKey;
  1052. LPSTR lpRegTmp;
  1053. if ( iSubKeyNum == 989 )
  1054. {
  1055. if ( UseRunOnceEx() )
  1056. {
  1057. bRunOnceEx = TRUE;
  1058. }
  1059. }
  1060. // decide to add the entry to RunOnce or RunOnceEx
  1061. if ( !bRunOnceEx )
  1062. {
  1063. // no ierunonce.dll, use RunOnce key rather than RunOnceEx key
  1064. lpRegTmp = REGSTR_PATH_RUNONCE;
  1065. }
  1066. else
  1067. {
  1068. lpRegTmp = REGSTR_PATH_RUNONCEEX;
  1069. }
  1070. // open RunOnce or RunOnceEx key here
  1071. if ( RegCreateKeyEx( HKEY_LOCAL_MACHINE, lpRegTmp, (ULONG)0, NULL,
  1072. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL,
  1073. &hKey, NULL ) == ERROR_SUCCESS )
  1074. {
  1075. // SubKey "990" is the one used in one GenInstall section to
  1076. // store all the delayed post cmds.
  1077. if ( bRunOnceEx )
  1078. {
  1079. if ( iSubKeyNum == 989 )
  1080. GetNextRunOnceExSubKey( hKey, szMessage, &iSubKeyNum );
  1081. else
  1082. wsprintf( szMessage, "%d", iSubKeyNum );
  1083. // Generate the Value Name and ValueData.
  1084. //
  1085. if ( RegCreateKeyEx( hKey, szMessage, (ULONG)0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
  1086. NULL, &hSubKey, NULL ) == ERROR_SUCCESS )
  1087. {
  1088. GetNextRunOnceValName( hSubKey, "%03d", szMessage, iLine++ );
  1089. RegSetValueEx( hSubKey, szMessage, 0, REG_SZ, (LPBYTE)pszCommand, lstrlen(pszCommand)+1 );
  1090. AdvWriteToLog("RunOnceEx Entry: %1\r\n", pszCommand);
  1091. RegCloseKey( hSubKey );
  1092. }
  1093. }
  1094. else
  1095. {
  1096. GetNextRunOnceValName( hKey, achIEXREG, szMessage, iLine++ );
  1097. RegSetValueEx( hKey, szMessage, 0, REG_SZ, (LPBYTE)pszCommand, lstrlen(pszCommand)+1 );
  1098. AdvWriteToLog("RunOnce Entry: %1\r\n", pszCommand);
  1099. }
  1100. RegCloseKey( hKey );
  1101. // if we delay the commands, should trig the reboot.
  1102. hReturnCode = ERROR_SUCCESS_REBOOT_REQUIRED;
  1103. }
  1104. }
  1105. else
  1106. {
  1107. if ( ! IsFullPath( pszCommand ) )
  1108. {
  1109. lstrcpy( pszNewCommand, c_pszSourceDir );
  1110. AddPath( pszNewCommand, pszCommand );
  1111. }
  1112. if ( ( *pszNewCommand == 0 ) ||
  1113. ( LaunchAndWait( pszNewCommand, NULL, NULL, INFINITE, dwCmdsFlags ) == E_FAIL ) )
  1114. {
  1115. if ( LaunchAndWait( pszCommand, NULL, NULL, INFINITE, dwCmdsFlags ) == E_FAIL )
  1116. {
  1117. hReturnCode = HRESULT_FROM_WIN32(GetLastError());
  1118. FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
  1119. szMessage, sizeof(szMessage), NULL );
  1120. ErrorMsg2Param( ctx.hWnd, IDS_ERR_CREATE_PROCESS, pszCommand, szMessage );
  1121. break;
  1122. }
  1123. }
  1124. }
  1125. // release the buffer allocated by GetTranslatedLine
  1126. LocalFree( pszCommand );
  1127. pszCommand = NULL;
  1128. *pszNewCommand = 0;
  1129. }
  1130. // release the local buffer
  1131. if ( pszNewCommand )
  1132. LocalFree( pszNewCommand );
  1133. // release the buffer allocated by GetTranslatedLine
  1134. if ( pszCommand )
  1135. LocalFree( pszCommand );
  1136. done:
  1137. AdvWriteToLog("RunCommands: Sec=%1 End hr=0x%2!x!\r\n", pcszSection, hReturnCode);
  1138. return hReturnCode;
  1139. }
  1140. //***************************************************************************
  1141. //* *
  1142. //* NAME: GetTranslatedInt *
  1143. //* *
  1144. //* SYNOPSIS: Translates a string in an INF file. *
  1145. //* *
  1146. //* REQUIRES: *
  1147. //* *
  1148. //* RETURNS: *
  1149. //* *
  1150. //***************************************************************************
  1151. DWORD GetTranslatedInt( PCSTR pszInfFilename, PCSTR pszTranslateSection,
  1152. PCSTR pszTranslateKey, DWORD dwDefault )
  1153. {
  1154. CHAR szBuf[100];
  1155. //BOOL bLocalInitSetupapi = FALSE;
  1156. BOOL bLocalAssignSetupEng = FALSE;
  1157. DWORD dwResult, dwRequiredSize;
  1158. DWORD dwSaveSetupEngine;
  1159. dwResult = dwDefault;
  1160. // since we are no using GetPrivateProfileString anymore if setupapi present
  1161. // there are times this function called and setupapi.dll is not loaded yet.
  1162. // so we need to check on in and initalize it if it is necessary
  1163. if (ctx.hSetupLibrary==NULL)
  1164. {
  1165. if (CheckOSVersion() && (ctx.wOSVer != _OSVER_WIN95))
  1166. {
  1167. //dwSaveSetupEngine = ctx.dwSetupEngine;
  1168. ctx.dwSetupEngine = ENGINE_SETUPAPI;
  1169. //bLocalAssignSetupEng = TRUE;
  1170. if (InitializeSetupAPI())
  1171. {
  1172. // To avoid multiple times load and unload the NT setupapi DLLs
  1173. // On NT, we are not unload the setuplib unless the INF engine need to be
  1174. // updated.
  1175. //
  1176. if (FAILED(MySetupOpenInfFile(pszInfFilename)))
  1177. {
  1178. // UnloadSetupLib();
  1179. goto done;
  1180. }
  1181. //bLocalInitSetupapi = TRUE;
  1182. }
  1183. else
  1184. {
  1185. goto done;
  1186. }
  1187. }
  1188. else
  1189. {
  1190. // if setupx lib is not initialized yet, just use GetPrivateProfileString
  1191. dwSaveSetupEngine = ctx.dwSetupEngine;
  1192. ctx.dwSetupEngine = ENGINE_SETUPX;
  1193. bLocalAssignSetupEng = TRUE;
  1194. }
  1195. }
  1196. if ( ctx.dwSetupEngine == ENGINE_SETUPX )
  1197. {
  1198. dwResult = (DWORD)GetPrivateProfileInt(pszTranslateSection, pszTranslateKey, dwDefault, pszInfFilename);
  1199. }
  1200. else
  1201. {
  1202. szBuf[0] = '\0';
  1203. if ( FAILED(MySetupGetLineText( pszTranslateSection, pszTranslateKey, szBuf,
  1204. sizeof(szBuf), &dwRequiredSize )))
  1205. {
  1206. goto done;
  1207. }
  1208. // convert the string to DWORD
  1209. if (szBuf[0] != '\0')
  1210. dwResult = (DWORD)AtoL(szBuf);
  1211. else
  1212. dwResult = dwDefault;
  1213. }
  1214. done:
  1215. //if (bLocalInitSetupapi)
  1216. //{
  1217. // uninitialize setupapi
  1218. //CommonInstallCleanup();
  1219. //}
  1220. if (bLocalAssignSetupEng)
  1221. ctx.dwSetupEngine = dwSaveSetupEngine;
  1222. return dwResult;
  1223. }
  1224. //***************************************************************************
  1225. //* *
  1226. //* NAME: GetTranslatedString *
  1227. //* *
  1228. //* SYNOPSIS: Translates a string in an INF file. *
  1229. //* *
  1230. //* REQUIRES: *
  1231. //* *
  1232. //* RETURNS: *
  1233. //* *
  1234. //***************************************************************************
  1235. HRESULT GetTranslatedString( PCSTR pszInfFilename, PCSTR pszTranslateSection,
  1236. PCSTR pszTranslateKey, PSTR pszBuffer, DWORD dwBufferSize, PDWORD pdwRequiredSize )
  1237. {
  1238. HRESULT hReturnCode = S_OK;
  1239. PSTR pszPreTranslated = NULL;
  1240. PSTR pszPostTranslated = NULL;
  1241. DWORD dwSizePreTranslated = 2048;
  1242. DWORD dwSizePostTranslated = 4096;
  1243. DWORD dwRequiredSize = 0;
  1244. //BOOL bLocalInitSetupapi = FALSE;
  1245. BOOL bLocalAssignSetupEng = FALSE;
  1246. DWORD dwSaveSetupEngine;
  1247. // since we are no using GetPrivateProfileString anymore if setupapi present
  1248. // there are times this function called and setupapi.dll is not loaded yet.
  1249. // so we need to check on in and initalize it if it is necessary
  1250. if (ctx.hSetupLibrary==NULL)
  1251. {
  1252. if (CheckOSVersion() && (ctx.wOSVer != _OSVER_WIN95))
  1253. {
  1254. // To avoid multiple times load and unload the NT setupapi DLLs
  1255. // On NT, we are not unload the setuplib unless the INF engine need to be
  1256. // updated.
  1257. //
  1258. //dwSaveSetupEngine = ctx.dwSetupEngine;
  1259. ctx.dwSetupEngine = ENGINE_SETUPAPI;
  1260. //bLocalAssignSetupEng = TRUE;
  1261. if (InitializeSetupAPI())
  1262. {
  1263. hReturnCode = MySetupOpenInfFile(pszInfFilename);
  1264. if (FAILED(hReturnCode))
  1265. {
  1266. //UnloadSetupLib();
  1267. goto done;
  1268. }
  1269. //bLocalInitSetupapi = TRUE;
  1270. }
  1271. else
  1272. {
  1273. hReturnCode = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1274. goto done;
  1275. }
  1276. }
  1277. else
  1278. {
  1279. // if setupx lib is not initialized yet, just use GetPrivateProfileString
  1280. dwSaveSetupEngine = ctx.dwSetupEngine;
  1281. ctx.dwSetupEngine = ENGINE_SETUPX;
  1282. bLocalAssignSetupEng = TRUE;
  1283. }
  1284. }
  1285. // NOTE: There should never be a value in an INF greater than 2k
  1286. // and translated strings shouldn't exceed 4k.
  1287. pszPreTranslated = (PSTR) LocalAlloc( LPTR, dwSizePreTranslated );
  1288. pszPostTranslated = (PSTR) LocalAlloc( LPTR, dwSizePostTranslated );
  1289. if ( ! pszPreTranslated || ! pszPostTranslated ) {
  1290. hReturnCode = HRESULT_FROM_WIN32(GetLastError());
  1291. goto done;
  1292. }
  1293. if ( ctx.dwSetupEngine == ENGINE_SETUPX ) {
  1294. if ( ! MyGetPrivateProfileString( pszInfFilename, pszTranslateSection, pszTranslateKey,
  1295. pszPreTranslated, dwSizePreTranslated ) )
  1296. {
  1297. hReturnCode = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1298. goto done;
  1299. }
  1300. if ( ctx.hSetupLibrary )
  1301. {
  1302. if (!pfGenFormStrWithoutPlaceHolders32( pszPostTranslated, pszPreTranslated,
  1303. (LPSTR) pszInfFilename ) )
  1304. {
  1305. hReturnCode = E_UNEXPECTED;
  1306. goto done;
  1307. }
  1308. }
  1309. else
  1310. FormStrWithoutPlaceHolders( pszPreTranslated, pszPostTranslated, dwSizePostTranslated, pszInfFilename );
  1311. dwRequiredSize = lstrlen( pszPostTranslated ) + 1;
  1312. }
  1313. else
  1314. {
  1315. hReturnCode = MySetupGetLineText( pszTranslateSection, pszTranslateKey, pszPostTranslated,
  1316. dwSizePostTranslated, &dwRequiredSize );
  1317. if (FAILED(hReturnCode) && HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hReturnCode)
  1318. {
  1319. // resize buffer and retry.
  1320. LocalFree(pszPostTranslated);
  1321. pszPostTranslated = LocalAlloc(LPTR, dwRequiredSize);
  1322. dwSizePostTranslated = dwRequiredSize;
  1323. if ( !pszPostTranslated ) {
  1324. hReturnCode = HRESULT_FROM_WIN32(GetLastError());
  1325. goto done;
  1326. }
  1327. hReturnCode = MySetupGetLineText( pszTranslateSection, pszTranslateKey,
  1328. pszPostTranslated, dwSizePostTranslated,
  1329. &dwRequiredSize );
  1330. }
  1331. if ( FAILED(hReturnCode) )
  1332. {
  1333. goto done;
  1334. }
  1335. }
  1336. if ( pszBuffer == NULL ) {
  1337. hReturnCode = S_OK;
  1338. goto done;
  1339. }
  1340. if ( dwRequiredSize > dwBufferSize ) {
  1341. hReturnCode = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  1342. goto done;
  1343. }
  1344. lstrcpy( pszBuffer, pszPostTranslated );
  1345. done:
  1346. //if (bLocalInitSetupapi)
  1347. //{
  1348. // uninitialize setupapi
  1349. //CommonInstallCleanup();
  1350. //}
  1351. if (bLocalAssignSetupEng)
  1352. ctx.dwSetupEngine = dwSaveSetupEngine;
  1353. if ( pdwRequiredSize ) {
  1354. *pdwRequiredSize = dwRequiredSize;
  1355. }
  1356. if ( pszPreTranslated != NULL ) {
  1357. LocalFree( pszPreTranslated );
  1358. }
  1359. if ( pszPostTranslated != NULL ) {
  1360. LocalFree( pszPostTranslated );
  1361. }
  1362. return hReturnCode;
  1363. }
  1364. //***************************************************************************
  1365. //* *
  1366. //* NAME: GetTranslatedLine *
  1367. //* *
  1368. //* SYNOPSIS: *
  1369. //* *
  1370. //* REQUIRES: *
  1371. //* *
  1372. //* RETURNS: *
  1373. //* *
  1374. //***************************************************************************
  1375. HRESULT GetTranslatedLine( PCSTR c_pszInfFilename, PCSTR c_pszTranslateSection,
  1376. DWORD dwIndex, PSTR *ppszBuffer, PDWORD pdwRequiredSize )
  1377. {
  1378. HRESULT hReturnCode = S_OK;
  1379. PSTR pszPreTranslated = NULL;
  1380. PSTR pszPostTranslated = NULL;
  1381. DWORD dwPreTranslatedSize = 8192;
  1382. DWORD dwPostTranslatedSize = 4096;
  1383. DWORD dwRequiredSize = 0;
  1384. DWORD i = 0;
  1385. PSTR pszPoint = NULL;
  1386. //BOOL bLocalInitSetupapi = FALSE;
  1387. BOOL bLocalAssignSetupEng = FALSE;
  1388. DWORD dwSaveSetupEngine;
  1389. // since we are no using GetPrivateProfileString anymore if setupapi present
  1390. // there are times this function called and setupapi.dll is not loaded yet.
  1391. // so we need to check on in and initalize it if it is necessary
  1392. if (ctx.hSetupLibrary==NULL)
  1393. {
  1394. if (CheckOSVersion() && (ctx.wOSVer != _OSVER_WIN95))
  1395. {
  1396. // To avoid multiple times load and unload the NT setupapi DLLs
  1397. // On NT, we are not unload the setuplib unless the INF engine need to be
  1398. // updated.
  1399. //
  1400. //dwSaveSetupEngine = ctx.dwSetupEngine;
  1401. ctx.dwSetupEngine = ENGINE_SETUPAPI;
  1402. //bLocalAssignSetupEng = TRUE;
  1403. if (InitializeSetupAPI())
  1404. {
  1405. hReturnCode = MySetupOpenInfFile(c_pszInfFilename);
  1406. if (FAILED(hReturnCode))
  1407. {
  1408. //UnloadSetupLib();
  1409. goto done;
  1410. }
  1411. //bLocalInitSetupapi = TRUE;
  1412. }
  1413. else
  1414. {
  1415. hReturnCode = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1416. goto done;
  1417. }
  1418. }
  1419. else
  1420. {
  1421. // if setupx lib is not initialized yet, just use GetPrivateProfileString
  1422. dwSaveSetupEngine = ctx.dwSetupEngine;
  1423. ctx.dwSetupEngine = ENGINE_SETUPX;
  1424. bLocalAssignSetupEng = TRUE;
  1425. }
  1426. }
  1427. // initial to NULL in the case of error, otherwise
  1428. if ( ppszBuffer )
  1429. *ppszBuffer = NULL;
  1430. pszPreTranslated = (PSTR) LocalAlloc( LPTR, dwPreTranslatedSize );
  1431. pszPostTranslated = (PSTR) LocalAlloc( LPTR, dwPostTranslatedSize );
  1432. if ( !pszPreTranslated || !pszPostTranslated ) {
  1433. hReturnCode = HRESULT_FROM_WIN32(GetLastError());
  1434. goto done;
  1435. }
  1436. if ( ctx.dwSetupEngine == ENGINE_SETUPX )
  1437. {
  1438. // BUGBUG: Should automagically change buffer size until we get a big
  1439. // enough buffer to hold the full section.
  1440. // BUGBUG: For setupx engine, we don't support the multiple-inf line reading for the new
  1441. // advance INF options. In most case, there is no need for that. If really need, set
  1442. // RequireEngine=SETUPAPI,"string"
  1443. dwRequiredSize = RO_GetPrivateProfileSection( c_pszTranslateSection, pszPreTranslated,
  1444. dwPreTranslatedSize, c_pszInfFilename );
  1445. if ( dwRequiredSize == dwPreTranslatedSize - 2 ) {
  1446. ErrorMsg1Param( ctx.hWnd, IDS_ERR_INF_SYNTAX, c_pszTranslateSection );
  1447. hReturnCode = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1448. goto done;
  1449. }
  1450. pszPoint = pszPreTranslated;
  1451. while ( *pszPoint == ';' ) {
  1452. pszPoint += lstrlen(pszPoint) + 1;
  1453. }
  1454. for ( i = 0; i < dwIndex; i += 1 ) {
  1455. pszPoint += lstrlen(pszPoint) + 1;
  1456. if ( *pszPoint == '\0' ) {
  1457. hReturnCode = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  1458. goto done;
  1459. }
  1460. while ( *pszPoint == ';' ) {
  1461. pszPoint += lstrlen(pszPoint) + 1;
  1462. }
  1463. }
  1464. if ( *pszPoint == '\0' ) {
  1465. hReturnCode = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  1466. goto done;
  1467. }
  1468. if ( ctx.hSetupLibrary )
  1469. {
  1470. if ( ! pfGenFormStrWithoutPlaceHolders32( pszPostTranslated, pszPoint,
  1471. (PSTR) c_pszInfFilename ) )
  1472. {
  1473. hReturnCode = E_UNEXPECTED;
  1474. goto done;
  1475. }
  1476. }
  1477. else
  1478. FormStrWithoutPlaceHolders( pszPoint, pszPostTranslated, dwPostTranslatedSize, (PSTR) c_pszInfFilename );
  1479. // strip out the double quotes
  1480. pszPoint = pszPostTranslated;
  1481. pszPostTranslated = GetStringField( &pszPoint, "\0", '\"', TRUE );
  1482. dwRequiredSize = lstrlen( pszPostTranslated ) + 1;
  1483. }
  1484. else
  1485. {
  1486. hReturnCode = MySetupGetLineByIndex( c_pszTranslateSection, dwIndex,
  1487. pszPostTranslated, dwPostTranslatedSize,
  1488. &dwRequiredSize );
  1489. if (FAILED(hReturnCode) && HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hReturnCode)
  1490. {
  1491. // resize buffer and retry.
  1492. LocalFree(pszPostTranslated);
  1493. pszPostTranslated = LocalAlloc(LPTR, dwRequiredSize);
  1494. dwPostTranslatedSize = dwRequiredSize;
  1495. if ( !pszPostTranslated ) {
  1496. hReturnCode = HRESULT_FROM_WIN32(GetLastError());
  1497. goto done;
  1498. }
  1499. hReturnCode = MySetupGetLineByIndex( c_pszTranslateSection, dwIndex,
  1500. pszPostTranslated, dwPostTranslatedSize,
  1501. &dwRequiredSize );
  1502. }
  1503. if ( FAILED(hReturnCode) ) {
  1504. goto done;
  1505. }
  1506. }
  1507. // if NULL, return only size
  1508. //
  1509. if ( !ppszBuffer )
  1510. {
  1511. LocalFree( pszPostTranslated );
  1512. }
  1513. else
  1514. {
  1515. // this buffer has to be released by the caller!!
  1516. //
  1517. *ppszBuffer = (LPSTR)LocalReAlloc( pszPostTranslated, (lstrlen(pszPostTranslated)+1), LMEM_MOVEABLE );
  1518. if ( !*ppszBuffer )
  1519. *ppszBuffer = pszPostTranslated;
  1520. }
  1521. done:
  1522. //if (bLocalInitSetupapi)
  1523. //{
  1524. // uninitialize setupapi
  1525. //CommonInstallCleanup();
  1526. //}
  1527. if (bLocalAssignSetupEng)
  1528. ctx.dwSetupEngine = dwSaveSetupEngine;
  1529. if ( pdwRequiredSize ) {
  1530. *pdwRequiredSize = dwRequiredSize;
  1531. }
  1532. if ( pszPreTranslated != NULL ) {
  1533. LocalFree( pszPreTranslated );
  1534. }
  1535. if ( FAILED(hReturnCode) && (pszPostTranslated != NULL) )
  1536. {
  1537. if (ppszBuffer)
  1538. *ppszBuffer = NULL;
  1539. LocalFree( pszPostTranslated );
  1540. }
  1541. return hReturnCode;
  1542. }
  1543. //***************************************************************************
  1544. //* *
  1545. //* NAME: GetTranslatedSection *
  1546. //* *
  1547. //* SYNOPSIS: *
  1548. //* *
  1549. //* REQUIRES: *
  1550. //* *
  1551. //* RETURNS: *
  1552. //* *
  1553. //***************************************************************************
  1554. DWORD GetTranslatedSection(PCSTR c_pszInfFilename, PCSTR c_pszTranslateSection,
  1555. PSTR pszBuffer, DWORD dwBufSize )
  1556. {
  1557. CHAR szPreTranslated[MAX_INFLINE];
  1558. DWORD dwSize = 0;
  1559. //BOOL bLocalInitSetupapi = FALSE,
  1560. BOOL bLocalAssignSetupEng = FALSE;
  1561. DWORD dwSaveSetupEngine;
  1562. // since we are no using GetPrivateProfileString anymore if setupapi present
  1563. // there are times this function called and setupapi.dll is not loaded yet.
  1564. // so we need to check on in and initalize it if it is necessary
  1565. if (ctx.hSetupLibrary==NULL)
  1566. {
  1567. if (CheckOSVersion() && (ctx.wOSVer != _OSVER_WIN95))
  1568. {
  1569. // To avoid multiple times load and unload the NT setupapi DLLs
  1570. // On NT, we are not unload the setuplib unless the INF engine need to be
  1571. // updated.
  1572. //
  1573. //dwSaveSetupEngine = ctx.dwSetupEngine;
  1574. ctx.dwSetupEngine = ENGINE_SETUPAPI;
  1575. //bLocalAssignSetupEng = TRUE;
  1576. if (InitializeSetupAPI())
  1577. {
  1578. if (FAILED(MySetupOpenInfFile(c_pszInfFilename)))
  1579. {
  1580. //UnloadSetupLib();
  1581. goto done;
  1582. }
  1583. //bLocalInitSetupapi = TRUE;
  1584. }
  1585. else
  1586. {
  1587. goto done;
  1588. }
  1589. }
  1590. else
  1591. {
  1592. // if setupx lib is not initialized yet, just use GetPrivateProfileString
  1593. dwSaveSetupEngine = ctx.dwSetupEngine;
  1594. ctx.dwSetupEngine = ENGINE_SETUPX;
  1595. bLocalAssignSetupEng = TRUE;
  1596. }
  1597. }
  1598. if ( ctx.dwSetupEngine == ENGINE_SETUPX )
  1599. {
  1600. dwSize = RO_GetPrivateProfileSection( c_pszTranslateSection, pszBuffer,
  1601. dwBufSize, c_pszInfFilename );
  1602. if ( dwSize == dwBufSize - 2 )
  1603. {
  1604. ErrorMsg1Param( ctx.hWnd, IDS_ERR_INF_SYNTAX, c_pszTranslateSection );
  1605. goto done;
  1606. }
  1607. }
  1608. else
  1609. {
  1610. int i, len;
  1611. LPSTR pszTmp, pszStart;
  1612. DWORD dwReqSize;
  1613. char szBuf[MAX_INFLINE];
  1614. pszStart = pszBuffer;
  1615. *pszStart = '\0';
  1616. for (i=0; ; i++)
  1617. {
  1618. // if key does not contain ',', setupapi's SetupGetLineText only return the value part
  1619. // we need to get the corespondent key part to makeup the whole line text
  1620. dwReqSize = 0;
  1621. if (SUCCEEDED(MySetupGetStringField(c_pszTranslateSection, i, 0, szBuf,
  1622. sizeof(szBuf), &dwReqSize)) && dwReqSize)
  1623. {
  1624. dwReqSize = 0;
  1625. if ( SUCCEEDED(MySetupGetLineText( c_pszTranslateSection, szBuf, szPreTranslated,
  1626. sizeof(szPreTranslated), &dwReqSize )) && dwReqSize)
  1627. {
  1628. // got the key, so the line must be in the form A=B or Just A forms, no comma.
  1629. lstrcat(szBuf, "=");
  1630. lstrcat(szBuf, szPreTranslated);
  1631. }
  1632. }
  1633. else
  1634. {
  1635. // expect the line in the forms of A,B,C=B or just A,B,C
  1636. if ( FAILED(MySetupGetLineByIndex(c_pszTranslateSection, i,
  1637. szPreTranslated, sizeof(szPreTranslated),
  1638. &dwReqSize )))
  1639. {
  1640. // should not be here since you are here, the line must have commas or no '='
  1641. break;
  1642. }
  1643. lstrcpy(szBuf, szPreTranslated);
  1644. }
  1645. len = lstrlen(szBuf)+1;
  1646. if ((dwSize + len) < dwBufSize)
  1647. {
  1648. lstrcpy(pszStart, szBuf);
  1649. pszStart += len;
  1650. dwSize += len;
  1651. }
  1652. else
  1653. {
  1654. dwSize = dwBufSize - 2;
  1655. break;
  1656. }
  1657. }
  1658. if (pszStart > pszBuffer)
  1659. *pszStart = '\0';
  1660. else if (pszStart == pszBuffer)
  1661. *(pszStart+1) = '\0';
  1662. }
  1663. done:
  1664. //if (bLocalInitSetupapi)
  1665. //{
  1666. // uninitialize setupapi
  1667. //CommonInstallCleanup();
  1668. //}
  1669. if (bLocalAssignSetupEng)
  1670. ctx.dwSetupEngine = dwSaveSetupEngine;
  1671. return dwSize;
  1672. }
  1673. //***************************************************************************
  1674. //* *
  1675. //* NAME: MyNTReboot *
  1676. //* *
  1677. //* SYNOPSIS: *
  1678. //* *
  1679. //* REQUIRES: *
  1680. //* *
  1681. //* RETURNS: *
  1682. //* *
  1683. //***************************************************************************
  1684. BOOL MyNTReboot( VOID )
  1685. {
  1686. HANDLE hToken;
  1687. TOKEN_PRIVILEGES tkp;
  1688. // get a token from this process
  1689. if ( !OpenProcessToken( GetCurrentProcess(),
  1690. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
  1691. {
  1692. ErrorMsg( NULL, IDS_ERR_OPENPROCTK );
  1693. return FALSE;
  1694. }
  1695. // get the LUID for the shutdown privilege
  1696. LookupPrivilegeValue( NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid );
  1697. tkp.PrivilegeCount = 1;
  1698. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  1699. //get the shutdown privilege for this proces
  1700. if ( !AdjustTokenPrivileges( hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0 ) )
  1701. {
  1702. ErrorMsg( NULL, IDS_ERR_ADJTKPRIV );
  1703. return FALSE;
  1704. }
  1705. // shutdown the system and force all applications to close
  1706. if (!ExitWindowsEx( EWX_REBOOT, 0 ) )
  1707. {
  1708. ErrorMsg( NULL, IDS_ERR_EXITWINEX );
  1709. return FALSE;
  1710. }
  1711. return TRUE;
  1712. }
  1713. //***************************************************************************
  1714. //* *
  1715. //* NAME: GetStringField *
  1716. //* *
  1717. //* SYNOPSIS: Gets a field (separated with certain characters). *
  1718. //* *
  1719. //* REQUIRES: *
  1720. //* *
  1721. //* RETURNS: *
  1722. //* *
  1723. //***************************************************************************
  1724. PSTR GetStringField( PSTR *ppszString, PCSTR c_pszSeparators, CHAR chQuoteToCheck, BOOL bStripWhiteSpace)
  1725. {
  1726. PSTR pszInternalString;
  1727. PSTR pszPoint = NULL;
  1728. BOOL fWithinQuotes = FALSE;
  1729. CHAR ch1, chQuote = 0;
  1730. PSTR pszTmp;
  1731. pszInternalString = *ppszString;
  1732. if ( pszInternalString == NULL )
  1733. {
  1734. return NULL;
  1735. }
  1736. pszPoint = pszInternalString;
  1737. while ( 1 )
  1738. {
  1739. ch1 = *pszInternalString;
  1740. if ( ch1 == chQuoteToCheck )
  1741. {
  1742. pszTmp = CharNext( pszInternalString );
  1743. if ( chQuote == 0 )
  1744. {
  1745. // the first one
  1746. chQuote = ch1;
  1747. fWithinQuotes = !(fWithinQuotes);
  1748. // strip out this quote
  1749. MoveMemory( pszInternalString, pszTmp, lstrlen(pszTmp)+1 );
  1750. if ( *pszInternalString == chQuote )
  1751. continue;
  1752. }
  1753. else if ( chQuote == ch1 )
  1754. {
  1755. if ( *pszTmp == ch1 )
  1756. {
  1757. PSTR ptmp = CharNext( pszTmp );
  1758. // dest, src, count include terminate null char.
  1759. MoveMemory( pszTmp, ptmp, lstrlen(ptmp)+1 );
  1760. }
  1761. else
  1762. {
  1763. fWithinQuotes = !(fWithinQuotes);
  1764. chQuote = 0;
  1765. MoveMemory( pszInternalString, pszTmp, lstrlen(pszTmp)+1 );
  1766. }
  1767. }
  1768. }
  1769. if ( *pszInternalString == '\0' )
  1770. {
  1771. break;
  1772. }
  1773. if ( !fWithinQuotes && IsSeparator( *pszInternalString, (PSTR) c_pszSeparators ) )
  1774. {
  1775. break;
  1776. }
  1777. pszInternalString = CharNext(pszInternalString);
  1778. }
  1779. if ( *pszInternalString == '\0' )
  1780. {
  1781. pszInternalString = NULL;
  1782. }
  1783. else
  1784. {
  1785. *pszInternalString = '\0';
  1786. pszInternalString += 1;
  1787. }
  1788. if ( bStripWhiteSpace )
  1789. pszPoint = StripWhitespace( pszPoint );
  1790. *ppszString = pszInternalString;
  1791. return pszPoint;
  1792. }
  1793. //***************************************************************************
  1794. //* *
  1795. //* NAME: GetStringFieldNoQuote *
  1796. //* *
  1797. //* SYNOPSIS: Gets a field (separated with certain characters). *
  1798. //* *
  1799. //* REQUIRES: *
  1800. //* *
  1801. //* RETURNS: *
  1802. //* *
  1803. //***************************************************************************
  1804. LPSTR GetStringFieldNoQuote( PSTR *ppszString, PCSTR c_pszSeparators, BOOL bStripWhiteSpace)
  1805. {
  1806. LPSTR pszInternalString;
  1807. LPSTR pszPoint = NULL;
  1808. pszInternalString = *ppszString;
  1809. if ( pszInternalString == NULL )
  1810. {
  1811. return NULL;
  1812. }
  1813. pszPoint = pszInternalString;
  1814. while ( *pszInternalString )
  1815. {
  1816. if ( IsSeparator( *pszInternalString, c_pszSeparators ) )
  1817. {
  1818. break;
  1819. }
  1820. pszInternalString = CharNext(pszInternalString);
  1821. }
  1822. if ( *pszInternalString == '\0' )
  1823. {
  1824. pszInternalString = NULL;
  1825. }
  1826. else
  1827. {
  1828. *pszInternalString = '\0';
  1829. pszInternalString += 1;
  1830. }
  1831. if ( bStripWhiteSpace )
  1832. pszPoint = StripWhitespace( pszPoint );
  1833. *ppszString = pszInternalString;
  1834. return pszPoint;
  1835. }
  1836. //***************************************************************************
  1837. //* *
  1838. //* NAME: IsSeparator *
  1839. //* *
  1840. //* SYNOPSIS: Returns TRUE if the character is in the string. Else FALSE. *
  1841. //* *
  1842. //* REQUIRES: *
  1843. //* *
  1844. //* RETURNS: *
  1845. //* *
  1846. //***************************************************************************
  1847. BOOL IsSeparator( CHAR chChar, PCSTR pszSeparators )
  1848. {
  1849. if ( chChar == '\0' || pszSeparators == NULL ) {
  1850. return FALSE;
  1851. }
  1852. while ( *pszSeparators != chChar ) {
  1853. if ( *pszSeparators == '\0' ) {
  1854. return FALSE;
  1855. }
  1856. pszSeparators += 1;
  1857. }
  1858. return TRUE;
  1859. }
  1860. //***************************************************************************
  1861. //* *
  1862. //* NAME: StripWhitespace *
  1863. //* *
  1864. //* SYNOPSIS: Strips spaces and tabs from both sides of given string. *
  1865. //* *
  1866. //* REQUIRES: *
  1867. //* *
  1868. //* RETURNS: *
  1869. //* *
  1870. //***************************************************************************
  1871. PSTR StripWhitespace( PSTR pszString )
  1872. {
  1873. PSTR pszTemp = NULL;
  1874. if ( pszString == NULL ) {
  1875. return NULL;
  1876. }
  1877. while ( *pszString == ' ' || *pszString == '\t' ) {
  1878. pszString += 1;
  1879. }
  1880. // Catch case where string consists entirely of whitespace or empty string.
  1881. if ( *pszString == '\0' ) {
  1882. return pszString;
  1883. }
  1884. pszTemp = pszString;
  1885. pszString += lstrlen(pszString) - 1;
  1886. while ( *pszString == ' ' || *pszString == '\t' ) {
  1887. *pszString = '\0';
  1888. pszString -= 1;
  1889. }
  1890. return pszTemp;
  1891. }
  1892. //***************************************************************************
  1893. //* *
  1894. //* NAME: StripQuotes *
  1895. //* *
  1896. //* SYNOPSIS: Strips quotes from both sides of given string. *
  1897. //* *
  1898. //* REQUIRES: *
  1899. //* *
  1900. //* RETURNS: *
  1901. //* *
  1902. //***************************************************************************
  1903. #if 0
  1904. PSTR StripQuotes( PSTR pszString )
  1905. {
  1906. PSTR pszTemp = NULL;
  1907. CHAR chQuote;
  1908. if ( pszString == NULL )
  1909. {
  1910. return NULL;
  1911. }
  1912. ch = *pszString;
  1913. if ( ch == '"' || ch == '\'' )
  1914. {
  1915. pszTemp = pszString + 1;
  1916. }
  1917. else
  1918. {
  1919. return pszString;
  1920. }
  1921. pszString += lstrlen(pszString) - 1;
  1922. if ( *pszString == ch )
  1923. {
  1924. *pszString = '\0';
  1925. }
  1926. else
  1927. {
  1928. pszTemp--;
  1929. }
  1930. return pszTemp;
  1931. }
  1932. #endif
  1933. //***************************************************************************
  1934. //* *
  1935. //* NAME: IsGoodAdvancedInfVersion *
  1936. //* *
  1937. //* SYNOPSIS: *
  1938. //* *
  1939. //* REQUIRES: *
  1940. //* *
  1941. //* RETURNS: *
  1942. //* *
  1943. //***************************************************************************
  1944. BOOL IsGoodAdvancedInfVersion( PCSTR c_pszInfFilename )
  1945. {
  1946. static const CHAR c_szSection[] = "Version";
  1947. static const CHAR c_szKey[] = "AdvancedINF";
  1948. PSTR pszVersionData = NULL;
  1949. PSTR pszMajorVersion = NULL;
  1950. PSTR pszMinorVersion = NULL;
  1951. DWORD dwRequiredSize;
  1952. DWORD dwSize;
  1953. PSTR pszVersion = NULL;
  1954. PSTR pszErrorMsg = NULL;
  1955. DWORD dwVersion = 0;
  1956. BOOL fSuccess = TRUE;
  1957. PSTR pszTmp;
  1958. if ( FAILED( GetTranslatedString( c_pszInfFilename, c_szSection, c_szKey, pszVersionData,
  1959. 0, &dwRequiredSize ) ) )
  1960. {
  1961. // We return TRUE because even though they didn't specify a version, I still
  1962. // want to process the INF file.
  1963. fSuccess = TRUE;
  1964. goto done;
  1965. }
  1966. pszVersionData = (PSTR) LocalAlloc( LPTR, dwRequiredSize );
  1967. if ( !pszVersionData ) {
  1968. ErrorMsg( ctx.hWnd, IDS_ERR_NO_MEMORY );
  1969. fSuccess = FALSE;
  1970. goto done;
  1971. }
  1972. if ( FAILED( GetTranslatedString( c_pszInfFilename, c_szSection, c_szKey,
  1973. pszVersionData, dwRequiredSize, &dwSize ) ) )
  1974. {
  1975. // This guy should never fail because the call above didn't fail.
  1976. fSuccess = FALSE;
  1977. goto done;
  1978. }
  1979. pszTmp = pszVersionData;
  1980. // Parse the arguments, SETUP engine has processed \" so we only need to check on \'
  1981. pszVersion = GetStringField( &pszTmp, ",", '\'', TRUE );
  1982. pszErrorMsg = GetStringField( &pszTmp, ",", '\'', TRUE );
  1983. if ( pszVersion == NULL || *pszVersion == '\0' ) {
  1984. // If they don't specify a version, process the INF file anyway
  1985. fSuccess = TRUE;
  1986. goto done;
  1987. }
  1988. // Parse the arguments, SETUP engine has processed \" so we only need to check on \'
  1989. pszTmp = pszVersion;
  1990. pszMajorVersion = GetStringField( &pszTmp, ".", '\'', TRUE );
  1991. pszMinorVersion = GetStringField( &pszTmp, ".", '\'', TRUE );
  1992. if ( pszMajorVersion == NULL || pszMajorVersion == '\0' ) {
  1993. fSuccess = TRUE;
  1994. goto done;
  1995. }
  1996. dwVersion = ((DWORD) My_atol(pszMajorVersion)) * 100;
  1997. if ( pszMinorVersion != NULL ) {
  1998. dwVersion += (DWORD) My_atol(pszMinorVersion);
  1999. }
  2000. if ( dwVersion > ADVPACK_VERSION ) {
  2001. fSuccess = FALSE;
  2002. if ( pszErrorMsg != NULL && *pszErrorMsg != '\0' ) {
  2003. ErrorMsg1Param( ctx.hWnd, IDS_PROMPT, pszErrorMsg );
  2004. AdvWriteToLog("Advpack.dll Version check failed! InfFile=%1\r\n", c_pszInfFilename);
  2005. }
  2006. goto done;
  2007. }
  2008. done:
  2009. if ( pszVersionData ) {
  2010. LocalFree( pszVersionData );
  2011. }
  2012. return fSuccess;
  2013. }
  2014. //***************************************************************************
  2015. //* *
  2016. //* NAME: SelectSetupEngine *
  2017. //* *
  2018. //* SYNOPSIS: *
  2019. //* *
  2020. //* REQUIRES: *
  2021. //* *
  2022. //* RETURNS: *
  2023. //* *
  2024. //***************************************************************************
  2025. BOOL SelectSetupEngine( PCSTR c_pszInfFilename, PCSTR c_pszSection, DWORD dwFlags )
  2026. {
  2027. static const CHAR c_szKey[] = "RequiredEngine";
  2028. static const CHAR c_szSetupX[] = "SETUPX";
  2029. static const CHAR c_szSetupAPI[] = "SETUPAPI";
  2030. PSTR pszEngine = NULL;
  2031. PSTR pszErrorMsg = NULL;
  2032. BOOL fSuccess = TRUE;
  2033. PSTR pszDll = NULL;
  2034. PSTR pszFilePart = NULL;
  2035. CHAR szBuffer[MAX_PATH];
  2036. CHAR szEngineData[2048];
  2037. PSTR pszStr;
  2038. BOOL bMustSetupapi = FALSE;
  2039. if ( (dwFlags & COREINSTALL_BKINSTALL) || (dwFlags & COREINSTALL_ROLLBACK) ||
  2040. (dwFlags & COREINSTALL_REBOOTCHECKONINSTALL) || (dwFlags & COREINSTALL_SETUPAPI)||(ctx.wOSVer != _OSVER_WIN95))
  2041. {
  2042. ctx.dwSetupEngine = ENGINE_SETUPAPI;
  2043. bMustSetupapi = TRUE;
  2044. if (ctx.wOSVer != _OSVER_WIN95)
  2045. goto done;
  2046. }
  2047. else
  2048. {
  2049. ctx.dwSetupEngine = ENGINE_SETUPX;
  2050. }
  2051. if (FAILED(GetTranslatedString(c_pszInfFilename, c_pszSection, c_szKey,
  2052. szEngineData, sizeof(szEngineData), NULL)))
  2053. {
  2054. fSuccess = TRUE;
  2055. goto done;
  2056. }
  2057. // Parse the arguments, SETUP engine is NOT called. So we need to check on \"
  2058. pszStr = szEngineData;
  2059. pszEngine = GetStringField( &pszStr, ",", '\"', TRUE );
  2060. pszErrorMsg = GetStringField( &pszStr, ",", '\"', TRUE );
  2061. if ( pszEngine == NULL || *pszEngine == '\0' ) {
  2062. // If they don't specify an engine, process the INF file anyway
  2063. fSuccess = TRUE;
  2064. goto done;
  2065. }
  2066. if ( !bMustSetupapi && (lstrcmpi( pszEngine, c_szSetupX ) == 0) ) {
  2067. pszDll = W95INF32DLL;
  2068. ctx.dwSetupEngine = ENGINE_SETUPX;
  2069. } else {
  2070. pszDll = SETUPAPIDLL;
  2071. ctx.dwSetupEngine = ENGINE_SETUPAPI;
  2072. }
  2073. // only if you don't have the INF engine file and you don't have the UpdateINFEngine On, error out
  2074. if (!SearchPath( NULL, pszDll, NULL, sizeof(szBuffer), szBuffer, &pszFilePart ) &&
  2075. (GetTranslatedInt(c_pszInfFilename, c_pszSection, ADVINF_UPDINFENG, 0)==0))
  2076. {
  2077. fSuccess = FALSE;
  2078. if ( pszErrorMsg != NULL && *pszErrorMsg != '\0' )
  2079. {
  2080. ErrorMsg1Param( ctx.hWnd, IDS_PROMPT, pszErrorMsg );
  2081. }
  2082. else
  2083. ErrorMsg1Param( NULL, IDS_ERR_LOAD_DLL, SETUPAPIDLL );
  2084. }
  2085. done:
  2086. return fSuccess;
  2087. }
  2088. //***************************************************************************
  2089. //* *
  2090. //* NAME: BeginPrompt *
  2091. //* *
  2092. //* SYNOPSIS: Displays beginning (confirmation) prompt. *
  2093. //* *
  2094. //* REQUIRES: *
  2095. //* *
  2096. //* RETURNS: *
  2097. //* *
  2098. //***************************************************************************
  2099. INT BeginPrompt( PCSTR c_pszInfFilename, PCSTR c_pszSection, PSTR pszTitle, DWORD dwTitleSize )
  2100. {
  2101. static const CHAR c_szBeginPromptKey[] = "BeginPrompt";
  2102. static const CHAR c_szPromptKey[] = "Prompt";
  2103. static const CHAR c_szButtonTypeKey[] = "ButtonType";
  2104. static const CHAR c_szTitleKey[] = "Title";
  2105. static const CHAR c_szButtonYesNo[] = "YESNO";
  2106. CHAR szBeginPromptSection[256];
  2107. PSTR pszPrompt = NULL;
  2108. DWORD dwPromptSize = 2048;
  2109. INT nReturnCode = 0;
  2110. CHAR szButtonType[128];
  2111. UINT nButtons = 0;
  2112. DWORD dwSize;
  2113. if ( FAILED( GetTranslatedString( c_pszInfFilename, c_pszSection, c_szBeginPromptKey,
  2114. szBeginPromptSection, sizeof(szBeginPromptSection), &dwSize ) ) )
  2115. {
  2116. nReturnCode = IDOK;
  2117. goto done;
  2118. }
  2119. if ( ! FAILED( GetTranslatedString( c_pszInfFilename, szBeginPromptSection, c_szTitleKey,
  2120. pszTitle, dwTitleSize, &dwSize ) ) )
  2121. {
  2122. ctx.lpszTitle = pszTitle;
  2123. }
  2124. pszPrompt = (PSTR) LocalAlloc( LPTR, dwPromptSize );
  2125. if ( ! pszPrompt ) {
  2126. ErrorMsg( ctx.hWnd, IDS_ERR_NO_MEMORY );
  2127. nReturnCode = IDCANCEL;
  2128. goto done;
  2129. }
  2130. if ( FAILED( GetTranslatedString( c_pszInfFilename, szBeginPromptSection, c_szPromptKey,
  2131. pszPrompt, dwPromptSize, &dwSize ) ) )
  2132. {
  2133. nReturnCode = IDOK;
  2134. goto done;
  2135. }
  2136. GetTranslatedString( c_pszInfFilename, szBeginPromptSection, c_szButtonTypeKey,
  2137. szButtonType, sizeof(szButtonType), &dwSize );
  2138. if ( lstrcmpi( szButtonType, c_szButtonYesNo ) == 0 ) {
  2139. nButtons = MB_YESNO;
  2140. } else {
  2141. nButtons = MB_OKCANCEL;
  2142. }
  2143. nReturnCode = MsgBox1Param( ctx.hWnd, IDS_PROMPT, pszPrompt, MB_ICONQUESTION, nButtons | MB_DEFBUTTON2 );
  2144. if ( nReturnCode == 0 ) {
  2145. ErrorMsg( ctx.hWnd, IDS_ERR_NO_MEMORY );
  2146. nReturnCode = IDCANCEL;
  2147. goto done;
  2148. }
  2149. done:
  2150. if ( pszPrompt ) {
  2151. LocalFree( pszPrompt );
  2152. }
  2153. // Map all cancel buttons to IDCANCEL
  2154. if ( nReturnCode == IDNO ) {
  2155. nReturnCode = IDCANCEL;
  2156. }
  2157. return nReturnCode;
  2158. }
  2159. //***************************************************************************
  2160. //* *
  2161. //* NAME: EndPrompt *
  2162. //* *
  2163. //* SYNOPSIS: Displays end prompt. *
  2164. //* *
  2165. //* REQUIRES: *
  2166. //* *
  2167. //* RETURNS: *
  2168. //* *
  2169. //***************************************************************************
  2170. VOID EndPrompt( PCSTR c_pszInfFilename, PCSTR c_pszSection )
  2171. {
  2172. static const CHAR c_szEndPromptKey[] = "EndPrompt";
  2173. static const CHAR c_szPromptKey[] = "Prompt";
  2174. CHAR szEndPromptSection[256];
  2175. PSTR pszPrompt = NULL;
  2176. DWORD dwPromptSize = 2048;
  2177. DWORD dwSize = 0;
  2178. if ( FAILED( GetTranslatedString( c_pszInfFilename, c_pszSection, c_szEndPromptKey,
  2179. szEndPromptSection, sizeof(szEndPromptSection), &dwSize ) ) )
  2180. {
  2181. goto done;
  2182. }
  2183. pszPrompt = (PSTR) LocalAlloc( LPTR, dwPromptSize );
  2184. if ( ! pszPrompt ) {
  2185. goto done;
  2186. }
  2187. if ( FAILED( GetTranslatedString( c_pszInfFilename, szEndPromptSection, c_szPromptKey,
  2188. pszPrompt, dwPromptSize, &dwSize ) ) )
  2189. {
  2190. goto done;
  2191. }
  2192. MsgBox1Param( ctx.hWnd, IDS_PROMPT, pszPrompt, MB_ICONINFORMATION, MB_OK );
  2193. done:
  2194. if ( pszPrompt ) {
  2195. LocalFree( pszPrompt );
  2196. }
  2197. return;
  2198. }
  2199. //***************************************************************************
  2200. //* *
  2201. //* NAME: MyGetPrivateProfileString *
  2202. //* *
  2203. //* SYNOPSIS: Gets string from INF file. TRUE if success, else FALSE. *
  2204. //* *
  2205. //* REQUIRES: *
  2206. //* *
  2207. //* RETURNS: *
  2208. //* *
  2209. //***************************************************************************
  2210. BOOL MyGetPrivateProfileString( PCSTR c_pszInfFilename, PCSTR c_pszSection,
  2211. PCSTR c_pszKey, PSTR pszBuffer, DWORD dwBufferSize )
  2212. {
  2213. DWORD dwSize = 0;
  2214. static const CHAR c_szDefault[] = "ZzZzZzZz";
  2215. dwSize = GetPrivateProfileString( c_pszSection, c_pszKey, c_szDefault,
  2216. pszBuffer, dwBufferSize,
  2217. c_pszInfFilename );
  2218. if ( dwSize == (dwBufferSize - 1)
  2219. || lstrcmp( pszBuffer, c_szDefault ) == 0 )
  2220. {
  2221. return FALSE;
  2222. }
  2223. return TRUE;
  2224. }
  2225. //***************************************************************************
  2226. //* *
  2227. //* NAME: InitializeSetupAPI *
  2228. //* *
  2229. //* SYNOPSIS: Load the proper setup library and functions (for Win95) *
  2230. //* *
  2231. //* REQUIRES: *
  2232. //* *
  2233. //* RETURNS: *
  2234. //* *
  2235. //***************************************************************************
  2236. BOOL InitializeSetupAPI()
  2237. {
  2238. if ( ctx.hSetupLibrary == NULL )
  2239. {
  2240. ctx.hSetupLibrary = MyLoadLibrary( SETUPAPIDLL );
  2241. if ( ctx.hSetupLibrary == NULL )
  2242. {
  2243. ErrorMsg1Param( NULL, IDS_ERR_LOAD_DLL, SETUPAPIDLL );
  2244. return FALSE;
  2245. }
  2246. if ( ! LoadSetupAPIFuncs() )
  2247. {
  2248. ErrorMsg( NULL, IDS_ERR_GET_PROC_ADDR );
  2249. FreeLibrary( ctx.hSetupLibrary );
  2250. ctx.hSetupLibrary = NULL;
  2251. return FALSE;
  2252. }
  2253. }
  2254. return TRUE;
  2255. }
  2256. //***************************************************************************
  2257. //* *
  2258. //* NAME: LoadSetupLib *
  2259. //* *
  2260. //* SYNOPSIS: Load the proper setup library and functions (for Win95) *
  2261. //* *
  2262. //* REQUIRES: CheckOSV *
  2263. //* *
  2264. //* RETURNS: *
  2265. //* *
  2266. //***************************************************************************
  2267. BOOL LoadSetupLib( PCSTR c_pszInfFilename, PCSTR c_pszSection, BOOL fUpdDlls, DWORD dwFlags )
  2268. {
  2269. MSG tmpmsg;
  2270. if ( ! SelectSetupEngine( c_pszInfFilename, c_pszSection, dwFlags) ) {
  2271. return FALSE;
  2272. }
  2273. // update the advpack.dll etc if needed
  2274. if ( fUpdDlls && (ctx.wOSVer < _OSVER_WINNT50) && !RunningOnMillennium())
  2275. {
  2276. if (!UpdateHelpDlls( c_szAdvDlls, ((ctx.wOSVer ==_OSVER_WIN95)?3:1), NULL, "Advpack",
  2277. (ctx.bUpdHlpDlls?UPDHLPDLLS_FORCED:0) ) )
  2278. {
  2279. return FALSE;
  2280. }
  2281. }
  2282. // update INF Engine dlls if needed
  2283. if ( GetTranslatedInt(c_pszInfFilename, c_pszSection, ADVINF_UPDINFENG, 0) )
  2284. {
  2285. char szSrcPath[MAX_PATH];
  2286. lstrcpy(szSrcPath, c_pszInfFilename);
  2287. GetParentDir(szSrcPath);
  2288. if (ctx.dwSetupEngine == ENGINE_SETUPAPI)
  2289. {
  2290. // setupapi.dll may be loaded. So free it up before update
  2291. //
  2292. CommonInstallCleanup();
  2293. if (!UpdateHelpDlls(c_szSetupAPIDlls, 2, szSrcPath, "SetupAPI",
  2294. UPDHLPDLLS_FORCED|UPDHLPDLLS_ALERTREBOOT) )
  2295. {
  2296. return FALSE;
  2297. }
  2298. }
  2299. else
  2300. {
  2301. if (!UpdateHelpDlls(c_szSetupXDlls, 1, szSrcPath, "SetupX",
  2302. UPDHLPDLLS_FORCED|UPDHLPDLLS_ALERTREBOOT) )
  2303. {
  2304. return FALSE;
  2305. }
  2306. }
  2307. }
  2308. // Under Win95 load W95INF32.DLL to thunk down to 16-bit land.
  2309. // Under WinNT load SETUPAPI.DLL and call in directly.
  2310. if ( ctx.dwSetupEngine == ENGINE_SETUPX )
  2311. {
  2312. ctx.hSetupLibrary = MyLoadLibrary( W95INF32DLL );
  2313. if ( ctx.hSetupLibrary == NULL ) {
  2314. ErrorMsg1Param( NULL, IDS_ERR_LOAD_DLL, W95INF32DLL );
  2315. return FALSE;
  2316. }
  2317. pfCtlSetLddPath32 = (CTLSETLDDPATH32) GetProcAddress( ctx.hSetupLibrary, achCTLSETLDDPATH32 );
  2318. pfGenInstall32 = (GENINSTALL32) GetProcAddress( ctx.hSetupLibrary, achGENINSTALL32 );
  2319. pfGetSETUPXErrorText32 = (GETSETUPXERRORTEXT32) GetProcAddress( ctx.hSetupLibrary, achGETSETUPXERRORTEXT32 );
  2320. pfGenFormStrWithoutPlaceHolders32 = (GENFORMSTRWITHOUTPLACEHOLDERS32) GetProcAddress( ctx.hSetupLibrary, achGENFORMSTRWITHOUTPLACEHOLDERS32 );
  2321. if ( pfCtlSetLddPath32 == NULL
  2322. || pfGenInstall32 == NULL
  2323. || pfGetSETUPXErrorText32 == NULL
  2324. || pfGenFormStrWithoutPlaceHolders32 == NULL )
  2325. {
  2326. ErrorMsg( NULL, IDS_ERR_GET_PROC_ADDR );
  2327. FreeLibrary( ctx.hSetupLibrary );
  2328. ctx.hSetupLibrary = NULL;
  2329. return FALSE;
  2330. }
  2331. }
  2332. else
  2333. {
  2334. if (!InitializeSetupAPI())
  2335. return FALSE;
  2336. // BUGBUG: HACK: On NT if we are kicking off setupapi in silent mode,
  2337. // it hangs in a GetMessage() call. This is probably because the corr.
  2338. // PostThreadMessage() that ted posts fails because no Message Queue has
  2339. // been created. The following call should create a queue. Till Ted
  2340. // fixes SETUPAPI.DLL, I have added thsi hack!!!
  2341. //
  2342. PeekMessage(&tmpmsg, NULL, 0, 0, PM_NOREMOVE) ;
  2343. }
  2344. return TRUE;
  2345. }
  2346. //***************************************************************************
  2347. //* *
  2348. //* NAME: UnloadSetupLib *
  2349. //* *
  2350. //* SYNOPSIS: Load the proper setup library and functions (for Win95) *
  2351. //* *
  2352. //* REQUIRES: CheckOSV *
  2353. //* *
  2354. //* RETURNS: *
  2355. //* *
  2356. //***************************************************************************
  2357. VOID UnloadSetupLib( VOID )
  2358. {
  2359. if ( ctx.hSetupLibrary != NULL )
  2360. {
  2361. FreeLibrary( ctx.hSetupLibrary );
  2362. ctx.hSetupLibrary = NULL;
  2363. }
  2364. }
  2365. //***************************************************************************
  2366. //* *
  2367. //* NAME: CheckOSVersion *
  2368. //* *
  2369. //* SYNOPSIS: Checks the OS version and sets some global variables. *
  2370. //* *
  2371. //* REQUIRES: Nothing *
  2372. //* *
  2373. //* RETURNS: BOOL: TRUE if successful, FALSE otherwise. *
  2374. //* *
  2375. //***************************************************************************
  2376. BOOL CheckOSVersion( VOID )
  2377. {
  2378. OSVERSIONINFO verinfo; // Version Check
  2379. verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  2380. if ( GetVersionEx( &verinfo ) == FALSE )
  2381. {
  2382. ErrorMsg( ctx.hWnd, IDS_ERR_OS_VERSION );
  2383. return FALSE;
  2384. }
  2385. switch( verinfo.dwPlatformId )
  2386. {
  2387. case VER_PLATFORM_WIN32_WINDOWS: // Win95
  2388. ctx.wOSVer = _OSVER_WIN95;
  2389. ctx.fOSSupportsINFInstalls = TRUE;
  2390. return TRUE;
  2391. case VER_PLATFORM_WIN32_NT: // Win NT
  2392. ctx.fOSSupportsINFInstalls = TRUE;
  2393. ctx.wOSVer = _OSVER_WINNT40;
  2394. if ( verinfo.dwMajorVersion <= 3 )
  2395. {
  2396. ctx.wOSVer = _OSVER_WINNT3X;
  2397. if ( (verinfo.dwMajorVersion < 3) ||
  2398. ((verinfo.dwMajorVersion == 3) && (verinfo.dwMinorVersion < 51 )) )
  2399. {
  2400. // Reject for INF installs and Reject for animations
  2401. ctx.fOSSupportsINFInstalls = FALSE;
  2402. }
  2403. }
  2404. else if ( verinfo.dwMajorVersion == 5 &&
  2405. verinfo.dwMinorVersion == 0)
  2406. {
  2407. ctx.wOSVer = _OSVER_WINNT50;
  2408. }
  2409. else if ( (verinfo.dwMajorVersion == 5 &&
  2410. verinfo.dwMinorVersion > 0) ||
  2411. verinfo.dwMajorVersion > 5)
  2412. ctx.wOSVer = _OSVER_WINNT51;
  2413. return TRUE;
  2414. default:
  2415. ErrorMsg( ctx.hWnd, IDS_ERR_OS_UNSUPPORTED );
  2416. return FALSE;
  2417. }
  2418. }
  2419. //***************************************************************************
  2420. //* *
  2421. //* NAME: MsgBox2Param *
  2422. //* *
  2423. //* SYNOPSIS: Displays a message box with the specified string ID using *
  2424. //* 2 string parameters. *
  2425. //* *
  2426. //* REQUIRES: hWnd: Parent window *
  2427. //* nMsgID: String resource ID *
  2428. //* szParam1: Parameter 1 (or NULL) *
  2429. //* szParam2: Parameter 2 (or NULL) *
  2430. //* uIcon: Icon to display (or 0) *
  2431. //* uButtons: Buttons to display *
  2432. //* *
  2433. //* RETURNS: INT: ID of button pressed *
  2434. //* *
  2435. //* NOTES: Macros are provided for displaying 1 parameter or 0 *
  2436. //* parameter message boxes. Also see ErrorMsg() macros. *
  2437. //* *
  2438. //***************************************************************************
  2439. INT MsgBox2Param( HWND hWnd, UINT nMsgID, LPCSTR szParam1, LPCSTR szParam2,
  2440. UINT uIcon, UINT uButtons )
  2441. {
  2442. CHAR achMsgBuf[BIG_STRING];
  2443. CHAR szTitle[MAX_PATH];
  2444. LPSTR szMessage = NULL;
  2445. LPSTR pszTitle;
  2446. INT nReturn;
  2447. CHAR achError[] = "Unexpected Error. Could not load resource.";
  2448. LPSTR aszParams[2];
  2449. // BUGBUG: quiet mode return code should be caller's param passed in.
  2450. // we may need to check on FormatMessage's return code and handle it in more completed fashion.
  2451. //
  2452. if ( (ctx.wQuietMode & QUIETMODE_SHOWMSG) || !(ctx.wQuietMode & QUIETMODE_ALL) )
  2453. {
  2454. aszParams[0] = (LPSTR) szParam1;
  2455. aszParams[1] = (LPSTR) szParam2;
  2456. LoadSz( nMsgID, achMsgBuf, sizeof(achMsgBuf) );
  2457. if ( (*achMsgBuf) == '\0' ) {
  2458. lstrcpy( achMsgBuf, achError );
  2459. }
  2460. if ( FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY
  2461. | FORMAT_MESSAGE_ALLOCATE_BUFFER, achMsgBuf, 0, 0, (LPSTR) (&szMessage),
  2462. 0, (va_list *)aszParams ) )
  2463. {
  2464. MessageBeep( uIcon );
  2465. if ( ctx.lpszTitle == NULL )
  2466. {
  2467. LoadSz( IDS_ADVDEFTITLE, szTitle, sizeof(szTitle) );
  2468. if ( szTitle[0] == '\0' )
  2469. {
  2470. lstrcpy( szTitle, achError );
  2471. }
  2472. pszTitle = szTitle;
  2473. }
  2474. else
  2475. pszTitle = ctx.lpszTitle;
  2476. nReturn = MessageBox( hWnd, szMessage, pszTitle, uIcon |
  2477. uButtons | MB_APPLMODAL | MB_SETFOREGROUND |
  2478. ((RunningOnWin95BiDiLoc() && IsBiDiLocalizedBinary(g_hInst,RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO))) ? (MB_RIGHT | MB_RTLREADING) : 0) );
  2479. LocalFree( szMessage );
  2480. }
  2481. return nReturn;
  2482. }
  2483. else
  2484. return IDOK;
  2485. }
  2486. //***************************************************************************
  2487. //* *
  2488. //* NAME: LoadSz *
  2489. //* *
  2490. //* SYNOPSIS: Loads specified string resource into buffer. *
  2491. //* *
  2492. //* REQUIRES: idString: *
  2493. //* lpszBuf: *
  2494. //* cbBuf: *
  2495. //* *
  2496. //* RETURNS: LPSTR: Pointer to the passed-in buffer. *
  2497. //* *
  2498. //* NOTES: If this function fails (most likely due to low memory), the *
  2499. //* returned buffer will have a leading NULL so it is generally *
  2500. //* safe to use this without checking for failure. *
  2501. //* *
  2502. //***************************************************************************
  2503. LPSTR LoadSz( UINT idString, LPSTR lpszBuf, UINT cbBuf )
  2504. {
  2505. ASSERT( lpszBuf );
  2506. // Clear the buffer and load the string
  2507. if ( lpszBuf ) {
  2508. *lpszBuf = '\0';
  2509. LoadString( g_hInst, idString, lpszBuf, cbBuf );
  2510. }
  2511. return lpszBuf;
  2512. }
  2513. //***************************************************************************
  2514. //* *
  2515. //* NAME: UserDirPrompt *
  2516. //* *
  2517. //* SYNOPSIS: Pops up a dialog to ask the user for a directory. *
  2518. //* *
  2519. //* REQUIRES: lpszPromptText: Prompt to display or if null, use next parm *
  2520. //* uiPromptResID: ID of string to display as prompt *
  2521. //* lpszDefault: Default directory to put in edit box. *
  2522. //* lpszDestDir: Buffer to store user selected directory *
  2523. //* cbDestDirSize: Size of this buffer *
  2524. //* *
  2525. //* RETURNS: BOOL: TRUE if everything went well, FALSE *
  2526. //* if the user cancelled, or error. *
  2527. //* *
  2528. //***************************************************************************
  2529. BOOL UserDirPrompt( LPSTR lpszPromptText,
  2530. LPSTR lpszDefault, LPSTR lpszDestDir,
  2531. ULONG cbDestDirSize, DWORD dwInstNeedSize )
  2532. {
  2533. BOOL fDlgRC;
  2534. DIRDLGPARMS DirDlgParms;
  2535. DirDlgParms.lpszPromptText = lpszPromptText;
  2536. DirDlgParms.lpszDefault = lpszDefault;
  2537. DirDlgParms.lpszDestDir = lpszDestDir;
  2538. DirDlgParms.cbDestDirSize = cbDestDirSize;
  2539. DirDlgParms.dwInstNeedSize = dwInstNeedSize;
  2540. SetControlFont();
  2541. fDlgRC = (BOOL) DialogBoxParam( g_hInst, MAKEINTRESOURCE(IDD_DIRDLG),
  2542. NULL, DirDlgProc,
  2543. (LPARAM) &DirDlgParms );
  2544. if (g_hFont)
  2545. {
  2546. DeleteObject(g_hFont);
  2547. g_hFont = NULL;
  2548. }
  2549. return fDlgRC;
  2550. }
  2551. //***************************************************************************
  2552. //* *
  2553. //* NAME: DirDlgProc *
  2554. //* *
  2555. //* SYNOPSIS: Dialog Procedure for our dir dialog window. *
  2556. //* *
  2557. //* REQUIRES: hwndDlg: *
  2558. //* uMsg: *
  2559. //* wParam: *
  2560. //* lParam: *
  2561. //* *
  2562. //* RETURNS: BOOL: *
  2563. //* *
  2564. //***************************************************************************
  2565. INT_PTR CALLBACK DirDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam,
  2566. LPARAM lParam )
  2567. {
  2568. static CHAR achDir[MAX_PATH];
  2569. static CHAR achMsg[BIG_STRING];
  2570. static LPSTR lpszDestDir;
  2571. static LPSTR lpszDefaultDir;
  2572. static ULONG cbDestDirSize;
  2573. static DWORD dwInstNeedSize;
  2574. switch (uMsg) {
  2575. //*********************************************************************
  2576. case WM_INITDIALOG:
  2577. //*********************************************************************
  2578. {
  2579. DIRDLGPARMS *DirDlgParms = (DIRDLGPARMS *) lParam;
  2580. lpszDestDir = DirDlgParms->lpszDestDir;
  2581. lpszDefaultDir = DirDlgParms->lpszDefault;
  2582. cbDestDirSize = DirDlgParms->cbDestDirSize;
  2583. dwInstNeedSize = DirDlgParms->dwInstNeedSize;
  2584. CenterWindow( hwndDlg, GetDesktopWindow() );
  2585. SetWindowText( hwndDlg, ctx.lpszTitle );
  2586. if ( ! SetDlgItemText( hwndDlg, IDC_TEMPTEXT, DirDlgParms->lpszPromptText ) )
  2587. {
  2588. ErrorMsg( hwndDlg, IDS_ERR_UPDATE_DIR );
  2589. EndDialog( hwndDlg, FALSE );
  2590. return TRUE;
  2591. }
  2592. SetFontForControl(hwndDlg, IDC_EDIT_DIR);
  2593. if ( ! SetDlgItemText( hwndDlg, IDC_EDIT_DIR, DirDlgParms->lpszDefault ) )
  2594. {
  2595. ErrorMsg( hwndDlg, IDS_ERR_UPDATE_DIR );
  2596. EndDialog( hwndDlg, FALSE );
  2597. return TRUE;
  2598. }
  2599. // limit edit control length
  2600. SendDlgItemMessage( hwndDlg, IDC_EDIT_DIR, EM_SETLIMITTEXT, (MAX_PATH - 1), 0 );
  2601. if ( ctx.wOSVer == _OSVER_WINNT3X ) {
  2602. EnableWindow( GetDlgItem( hwndDlg, IDC_BUT_BROWSE ), FALSE );
  2603. }
  2604. return TRUE;
  2605. }
  2606. //*********************************************************************
  2607. case WM_CLOSE:
  2608. //*********************************************************************
  2609. EndDialog( hwndDlg, FALSE );
  2610. return TRUE;
  2611. //*********************************************************************
  2612. case WM_COMMAND:
  2613. //*********************************************************************
  2614. switch ( wParam )
  2615. {
  2616. //*************************************************************
  2617. case IDOK:
  2618. //*************************************************************
  2619. {
  2620. DWORD dwAttribs = 0, dwTemp;
  2621. // Read the user's entry. If it is different from the default
  2622. // and does not exist, prompt user. If user accepts
  2623. // create it
  2624. if ( ! GetDlgItemText( hwndDlg, IDC_EDIT_DIR,
  2625. lpszDestDir, cbDestDirSize - 1 ) || !IsFullPath(lpszDestDir) )
  2626. {
  2627. ErrorMsg( hwndDlg, IDS_ERR_EMPTY_DIR_FIELD );
  2628. return TRUE;
  2629. }
  2630. // check on the DestDir size if this is not UNC and this drive has not been checked
  2631. if ( (*lpszDestDir != '\\' ) && !IsDrvChecked( *lpszDestDir ) )
  2632. {
  2633. if ( !IsEnoughInstSpace( lpszDestDir, dwInstNeedSize, &dwTemp ) )
  2634. {
  2635. CHAR szSize[10];
  2636. if ( dwTemp )
  2637. {
  2638. wsprintf( szSize, "%lu", dwTemp );
  2639. if ( MsgBox1Param( hwndDlg, IDS_ERR_NO_SPACE_INST, szSize,
  2640. MB_ICONQUESTION, MB_YESNO|MB_DEFBUTTON2 ) == IDNO )
  2641. return TRUE;
  2642. }
  2643. else // given drive cannot be checked, error has been posted. no further needed
  2644. return TRUE;
  2645. }
  2646. }
  2647. dwAttribs = GetFileAttributes( lpszDestDir );
  2648. if ( dwAttribs == 0xFFFFFFFF )
  2649. {
  2650. // If this new entry is different from the original, then prompt the user.
  2651. if ((lstrcmpi(lpszDestDir, lpszDefaultDir) == 0) ||
  2652. MsgBox1Param( hwndDlg, IDS_CREATE_DIR, lpszDestDir, MB_ICONQUESTION, MB_YESNO )
  2653. == IDYES )
  2654. {
  2655. if ( FAILED(CreateFullPath( lpszDestDir, FALSE )) )
  2656. {
  2657. ErrorMsg1Param( hwndDlg, IDS_ERR_CREATE_DIR, lpszDestDir );
  2658. return TRUE;
  2659. }
  2660. }
  2661. else
  2662. {
  2663. return TRUE;
  2664. }
  2665. }
  2666. if ( ! IsGoodDir( lpszDestDir ) ) {
  2667. ErrorMsg( hwndDlg, IDS_ERR_INVALID_DIR );
  2668. return TRUE;
  2669. }
  2670. EndDialog( hwndDlg, TRUE );
  2671. return TRUE;
  2672. }
  2673. //*************************************************************
  2674. case IDCANCEL:
  2675. //*************************************************************
  2676. EndDialog( hwndDlg, FALSE );
  2677. return TRUE;
  2678. //*************************************************************
  2679. case IDC_BUT_BROWSE:
  2680. //*************************************************************
  2681. if ( LoadString( g_hInst, IDS_SELECTDIR, achMsg,
  2682. sizeof(achMsg) ) == 0 )
  2683. {
  2684. ErrorMsg( hwndDlg, IDS_ERR_NO_RESOURCE );
  2685. EndDialog( hwndDlg, FALSE );
  2686. return TRUE;
  2687. }
  2688. if ( ! BrowseForDir( hwndDlg, achMsg, achDir ) ) {
  2689. return TRUE;
  2690. }
  2691. if ( ! SetDlgItemText( hwndDlg, IDC_EDIT_DIR, achDir ) )
  2692. {
  2693. ErrorMsg( hwndDlg, IDS_ERR_UPDATE_DIR );
  2694. EndDialog( hwndDlg, FALSE );
  2695. return TRUE;
  2696. }
  2697. return TRUE;
  2698. }
  2699. return TRUE;
  2700. }
  2701. return FALSE;
  2702. }
  2703. int CALLBACK BrowseCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  2704. {
  2705. switch(uMsg) {
  2706. case BFFM_INITIALIZED:
  2707. // lpData is the path string
  2708. SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
  2709. break;
  2710. }
  2711. return 0;
  2712. }
  2713. //***************************************************************************
  2714. //* *
  2715. //* NAME: BrowseForDir *
  2716. //* *
  2717. //* SYNOPSIS: Let user browse for a directory on their system or network. *
  2718. //* *
  2719. //* REQUIRES: hwndParent: *
  2720. //* szTitle: *
  2721. //* szResult: *
  2722. //* *
  2723. //* RETURNS: BOOL: *
  2724. //* *
  2725. //* NOTES: It would be really cool to set the status line of the *
  2726. //* browse window to display "Yes, there's enough space", or *
  2727. //* "no there is not". *
  2728. //* *
  2729. //***************************************************************************
  2730. BOOL BrowseForDir( HWND hwndParent, LPCSTR szTitle, LPSTR szResult )
  2731. {
  2732. BROWSEINFO bi;
  2733. LPITEMIDLIST pidl;
  2734. HINSTANCE hShell32Lib;
  2735. SHFREE pfSHFree;
  2736. SHGETPATHFROMIDLIST pfSHGetPathFromIDList;
  2737. SHBROWSEFORFOLDER pfSHBrowseForFolder;
  2738. static const CHAR achShell32Lib[] = "SHELL32.DLL";
  2739. static const CHAR achSHBrowseForFolder[] = "SHBrowseForFolder";
  2740. static const CHAR achSHGetPathFromIDList[] = "SHGetPathFromIDList";
  2741. ASSERT( szResult );
  2742. // Load the Shell 32 Library to get the SHBrowseForFolder() features
  2743. if ( ( hShell32Lib = LoadLibrary( achShell32Lib ) ) != NULL ) {
  2744. if ( ( ! ( pfSHBrowseForFolder = (SHBROWSEFORFOLDER)
  2745. GetProcAddress( hShell32Lib, achSHBrowseForFolder ) ) )
  2746. || ( ! ( pfSHFree = (SHFREE) GetProcAddress( hShell32Lib,
  2747. MAKEINTRESOURCE(SHFREE_ORDINAL) ) ) )
  2748. || ( ! ( pfSHGetPathFromIDList = (SHGETPATHFROMIDLIST)
  2749. GetProcAddress( hShell32Lib, achSHGetPathFromIDList ) ) ) )
  2750. {
  2751. FreeLibrary( hShell32Lib );
  2752. ErrorMsg( hwndParent, IDS_ERR_LOADFUNCS );
  2753. return FALSE;
  2754. }
  2755. } else {
  2756. ErrorMsg( hwndParent, IDS_ERR_LOADDLL );
  2757. return FALSE;
  2758. }
  2759. if ( ! ctx.szBrowsePath[0] )
  2760. {
  2761. GetProgramFilesDir( ctx.szBrowsePath, sizeof(ctx.szBrowsePath) );
  2762. }
  2763. szResult[0] = 0;
  2764. bi.hwndOwner = hwndParent;
  2765. bi.pidlRoot = NULL;
  2766. bi.pszDisplayName = NULL;
  2767. bi.lpszTitle = szTitle;
  2768. bi.ulFlags = BIF_RETURNONLYFSDIRS;
  2769. bi.lpfn = BrowseCallback;
  2770. bi.lParam = (LPARAM)ctx.szBrowsePath;
  2771. pidl = pfSHBrowseForFolder( &bi );
  2772. if ( pidl ) {
  2773. pfSHGetPathFromIDList( pidl, ctx.szBrowsePath );
  2774. if ( ctx.szBrowsePath[0] ) {
  2775. lstrcpy( szResult, ctx.szBrowsePath );
  2776. }
  2777. pfSHFree( pidl );
  2778. }
  2779. FreeLibrary( hShell32Lib );
  2780. if ( szResult[0] != 0 ) {
  2781. return TRUE;
  2782. }
  2783. else {
  2784. return FALSE;
  2785. }
  2786. }
  2787. //***************************************************************************
  2788. //* *
  2789. //* NAME: CenterWindow *
  2790. //* *
  2791. //* SYNOPSIS: Center one window within another. *
  2792. //* *
  2793. //* REQUIRES: hwndChild: *
  2794. //* hWndParent: *
  2795. //* *
  2796. //* RETURNS: BOOL: TRUE if successful, FALSE otherwise *
  2797. //* *
  2798. //***************************************************************************
  2799. BOOL CenterWindow( HWND hwndChild, HWND hwndParent )
  2800. {
  2801. RECT rChild;
  2802. RECT rParent;
  2803. int wChild;
  2804. int hChild;
  2805. int wParent;
  2806. int hParent;
  2807. int wScreen;
  2808. int hScreen;
  2809. int xNew;
  2810. int yNew;
  2811. HDC hdc;
  2812. // Get the Height and Width of the child window
  2813. GetWindowRect (hwndChild, &rChild);
  2814. wChild = rChild.right - rChild.left;
  2815. hChild = rChild.bottom - rChild.top;
  2816. // Get the Height and Width of the parent window
  2817. GetWindowRect (hwndParent, &rParent);
  2818. wParent = rParent.right - rParent.left;
  2819. hParent = rParent.bottom - rParent.top;
  2820. // Get the display limits
  2821. hdc = GetDC (hwndChild);
  2822. wScreen = GetDeviceCaps (hdc, HORZRES);
  2823. hScreen = GetDeviceCaps (hdc, VERTRES);
  2824. ReleaseDC (hwndChild, hdc);
  2825. // Calculate new X position, then adjust for screen
  2826. xNew = rParent.left + ((wParent - wChild) /2);
  2827. if (xNew < 0) {
  2828. xNew = 0;
  2829. } else if ((xNew+wChild) > wScreen) {
  2830. xNew = wScreen - wChild;
  2831. }
  2832. // Calculate new Y position, then adjust for screen
  2833. yNew = rParent.top + ((hParent - hChild) /2);
  2834. if (yNew < 0) {
  2835. yNew = 0;
  2836. } else if ((yNew+hChild) > hScreen) {
  2837. yNew = hScreen - hChild;
  2838. }
  2839. // Set it, and return
  2840. return( SetWindowPos(hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER));
  2841. }
  2842. //***************************************************************************
  2843. //* *
  2844. //* NAME: IsGoodDir *
  2845. //* *
  2846. //* SYNOPSIS: Find out if it's a good temporary directory or not. *
  2847. //* *
  2848. //* REQUIRES: szPath: *
  2849. //* *
  2850. //* RETURNS: BOOL: TRUE if good, FALSE if nogood *
  2851. //* *
  2852. //***************************************************************************
  2853. BOOL IsGoodDir( LPCSTR szPath )
  2854. {
  2855. DWORD dwAttribs;
  2856. HANDLE hFile;
  2857. char szTestFile[MAX_PATH];
  2858. lstrcpy( szTestFile, szPath );
  2859. AddPath( szTestFile, "TMP4352$.TMP" );
  2860. DeleteFile( szTestFile );
  2861. hFile = CreateFile( szTestFile, GENERIC_WRITE, 0, NULL, CREATE_NEW,
  2862. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
  2863. NULL );
  2864. if ( hFile == INVALID_HANDLE_VALUE ) {
  2865. return( FALSE );
  2866. }
  2867. CloseHandle( hFile );
  2868. dwAttribs = GetFileAttributes( szPath );
  2869. if ( ( dwAttribs != 0xFFFFFFFF )
  2870. && ( dwAttribs & FILE_ATTRIBUTE_DIRECTORY ) )
  2871. {
  2872. return( TRUE );
  2873. }
  2874. return( FALSE );
  2875. }
  2876. //***************************************************************************
  2877. //* *
  2878. //* NAME: CtlSetLDDPath *
  2879. //* *
  2880. //* SYNOPSIS: *
  2881. //* *
  2882. //* REQUIRES: *
  2883. //* *
  2884. //* RETURNS: *
  2885. //* *
  2886. //***************************************************************************
  2887. HRESULT CtlSetLddPath( UINT uiLDID, LPSTR lpszPath, DWORD dwSwitches )
  2888. {
  2889. PSTR pszNewPath = NULL;
  2890. BOOL fSuccess = TRUE;
  2891. DWORD dwNewPathSize = 0;
  2892. HRESULT hResult = S_OK;
  2893. PSTR lpTmp;
  2894. BOOL bDBC = FALSE;
  2895. dwNewPathSize = max( MAX_PATH, lstrlen(lpszPath) + 1 );
  2896. pszNewPath = (PSTR) LocalAlloc( LPTR, dwNewPathSize );
  2897. if ( !pszNewPath ) {
  2898. hResult = HRESULT_FROM_WIN32(GetLastError());
  2899. ErrorMsg( ctx.hWnd, IDS_ERR_NO_MEMORY );
  2900. goto done;
  2901. }
  2902. if ( ((ctx.dwSetupEngine == ENGINE_SETUPX) && (dwSwitches & LDID_SFN)) ||
  2903. ((dwSwitches & LDID_SFN_NT_ALSO)&& (ctx.wOSVer == _OSVER_WIN95)) )
  2904. {
  2905. if ( GetShortPathName( lpszPath, pszNewPath, dwNewPathSize ) == 0 )
  2906. {
  2907. hResult = HRESULT_FROM_WIN32(GetLastError());
  2908. ErrorMsg( ctx.hWnd, IDS_ERR_SHORT_NAME );
  2909. goto done;
  2910. }
  2911. }
  2912. else
  2913. lstrcpy( pszNewPath, lpszPath );
  2914. if ( ctx.dwSetupEngine == ENGINE_SETUPX ){
  2915. if ( dwSwitches & LDID_OEM_CHARS ) {
  2916. CharToOem( pszNewPath, pszNewPath );
  2917. }
  2918. lpTmp = pszNewPath + lstrlen(pszNewPath) - 1;
  2919. if (*lpTmp == '\\') // Is the last byte a backslash
  2920. {
  2921. // Check if it is the trail byte of a DBC
  2922. lpTmp = pszNewPath;
  2923. do
  2924. {
  2925. bDBC = IsDBCSLeadByte(*lpTmp);
  2926. lpTmp = CharNext(lpTmp);
  2927. } while (*lpTmp);
  2928. if (bDBC)
  2929. {
  2930. // The backslash is a trail byte. Add another backslash
  2931. AddPath(pszNewPath, "");
  2932. }
  2933. }
  2934. if ( pfCtlSetLddPath32( uiLDID, pszNewPath ) ) {
  2935. ErrorMsg1Param( ctx.hWnd, IDS_ERR_SET_LDID, pszNewPath );
  2936. hResult = E_FAIL;
  2937. goto done;
  2938. }
  2939. }
  2940. else
  2941. {
  2942. hResult = MySetupSetDirectoryId( uiLDID, pszNewPath );
  2943. if ( FAILED( hResult ) ) {
  2944. ErrorMsg1Param( ctx.hWnd, IDS_ERR_SET_LDID, pszNewPath );
  2945. goto done;
  2946. }
  2947. }
  2948. done:
  2949. if ( pszNewPath ) {
  2950. LocalFree( pszNewPath );
  2951. }
  2952. return hResult;
  2953. }
  2954. //***************************************************************************
  2955. //* *
  2956. //* NAME: GenInstall *
  2957. //* *
  2958. //* SYNOPSIS: *
  2959. //* *
  2960. //* REQUIRES: lpszInfFileName: Filename of INF file. *
  2961. //* lpszSection: Section of the INF to install *
  2962. //* lpszDirectory: Directory of CABs (Temp Dir). *
  2963. //* *
  2964. //* RETURNS: BOOL: Error result, FALSE == ERROR *
  2965. //* *
  2966. //***************************************************************************
  2967. HRESULT GenInstall( LPSTR lpszInfFilename, LPSTR lpszInstallSection, LPSTR lpszSourceDir )
  2968. {
  2969. CHAR szErrorText[BIG_STRING];
  2970. DWORD dwError = 0;
  2971. HRESULT hResult = S_OK;
  2972. CHAR szSourceDir[MAX_PATH];
  2973. DWORD dwLen = 0;
  2974. // Remove trailing backslash from the source directory
  2975. lstrcpy( szSourceDir, lpszSourceDir );
  2976. dwLen = lstrlen( szSourceDir );
  2977. if ( szSourceDir[dwLen-2] != ':' && szSourceDir[dwLen-1] == '\\' ) {
  2978. szSourceDir[dwLen-1] = '\0';
  2979. }
  2980. if ( ctx.dwSetupEngine == ENGINE_SETUPX )
  2981. {
  2982. CHAR szSFNInf[MAX_PATH] = { 0 };
  2983. GetShortPathName( lpszInfFilename, szSFNInf, sizeof(szSFNInf) );
  2984. GetShortPathName( szSourceDir, szSourceDir, sizeof(szSourceDir) );
  2985. dwError = pfGenInstall32( szSFNInf, lpszInstallSection,
  2986. szSourceDir, (DWORD) ctx.wQuietMode,
  2987. HandleToUlong(ctx.hWnd)
  2988. );
  2989. if ( dwError ) {
  2990. szErrorText[0] = '\0';
  2991. pfGetSETUPXErrorText32( dwError, szErrorText, sizeof(szErrorText) );
  2992. ErrorMsg1Param( ctx.hWnd, IDS_ERR_INF_FAIL, szErrorText );
  2993. hResult = E_FAIL;
  2994. }
  2995. } else {
  2996. hResult = InstallOnNT( lpszInstallSection, szSourceDir );
  2997. if ( FAILED( hResult ) )
  2998. {
  2999. if ( !FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
  3000. szErrorText, sizeof(szErrorText), NULL) )
  3001. {
  3002. LoadSz( IDS_ERR_FMTMSG, szErrorText, sizeof(szErrorText) );
  3003. if ( *szErrorText == 0 )
  3004. lstrcpy( szErrorText, "Could not get the system message. You may run out of the resource." );
  3005. }
  3006. ErrorMsg1Param( ctx.hWnd, IDS_ERR_INF_FAILURE, szErrorText );
  3007. }
  3008. }
  3009. return hResult;
  3010. }
  3011. //***************************************************************************
  3012. //* *
  3013. //* NAME: GetValueFromRegistry *
  3014. //* *
  3015. //* SYNOPSIS: Get an app-path out of the registry as specified. *
  3016. //* *
  3017. //* REQUIRES: *
  3018. //* *
  3019. //* RETURNS: BOOL: Error result, FALSE == ERROR *
  3020. //* *
  3021. //***************************************************************************
  3022. BOOL GetValueFromRegistry( LPSTR szPath, UINT cbPath, LPSTR szKey,
  3023. LPSTR szSubKey, LPSTR szVName )
  3024. {
  3025. HKEY hkPath = NULL;
  3026. DWORD dwType = 0;
  3027. DWORD dwSize = 0;
  3028. HKEY hkRoot = NULL;
  3029. PSTR pszTemp = NULL;
  3030. // Figure out what root key they want to check
  3031. if ( lstrcmpi( szKey, "HKCR" ) == 0 ) {
  3032. hkRoot = HKEY_CLASSES_ROOT;
  3033. } else if ( lstrcmpi( szKey, "HKCU" ) == 0 ) {
  3034. hkRoot = HKEY_CURRENT_USER;
  3035. } else if ( lstrcmpi( szKey, "HKLM" ) == 0 ) {
  3036. hkRoot = HKEY_LOCAL_MACHINE;
  3037. } else if ( lstrcmpi( szKey, "HKU" ) == 0 ) {
  3038. hkRoot = HKEY_USERS;
  3039. } else if ( *szKey == '\0' ) {
  3040. // If they don't specify a root key, then assume they don't want to check
  3041. // the registry. So just return as if the registry key doesn't exist.
  3042. return FALSE;
  3043. } else {
  3044. ErrorMsg( ctx.hWnd, IDS_ERR_INVALID_REGROOT );
  3045. return FALSE;
  3046. }
  3047. // Get Path to program from the registry
  3048. if ( RegOpenKeyEx( hkRoot, szSubKey, (ULONG) 0, KEY_READ, &hkPath ) != ERROR_SUCCESS ) {
  3049. return( FALSE );
  3050. }
  3051. dwSize = cbPath;
  3052. if ( RegQueryValueEx( hkPath, szVName, NULL, &dwType, (LPBYTE) szPath, &dwSize)
  3053. != ERROR_SUCCESS )
  3054. {
  3055. RegCloseKey( hkPath );
  3056. return( FALSE );
  3057. }
  3058. RegCloseKey( hkPath );
  3059. // If we got nothing or it wasn't a string then we bail out
  3060. if ( (dwSize == 0) || (dwType != REG_SZ && dwType != REG_EXPAND_SZ) ) {
  3061. return( FALSE );
  3062. }
  3063. if ( dwType == REG_EXPAND_SZ ) {
  3064. pszTemp = (PSTR) LocalAlloc( LPTR, cbPath );
  3065. if ( pszTemp == NULL ) {
  3066. return( FALSE );
  3067. }
  3068. lstrcpy( pszTemp, szPath );
  3069. dwSize = ExpandEnvironmentStrings( pszTemp, szPath, cbPath );
  3070. LocalFree( pszTemp );
  3071. if ( dwSize == 0 || dwSize > cbPath ) {
  3072. return( FALSE );
  3073. }
  3074. }
  3075. return( TRUE );
  3076. }
  3077. //***************************************************************************
  3078. //* *
  3079. //* NAME: SetLDIDs *
  3080. //* *
  3081. //* SYNOPSIS: Sets the LDIDs as specified in the INF file. *
  3082. //* *
  3083. //* REQUIRES: *
  3084. //* *
  3085. //* RETURNS: *
  3086. //* *
  3087. //* NOTE: If c_pszSourceDir != NULL then we want to set the source *
  3088. //* directory and nothing else. *
  3089. //* *
  3090. //***************************************************************************
  3091. HRESULT SetLDIDs( PCSTR c_pszInfFilename, PCSTR c_pszInstallSection,
  3092. DWORD dwInstNeedSize, PCSTR c_pszSourceDir )
  3093. {
  3094. CHAR szDestSection[256];
  3095. CHAR szDestLDIDs[512];
  3096. PSTR pszDestLDID = NULL;
  3097. PSTR pszNextDestLDID = NULL;
  3098. CHAR szDestData[256];
  3099. DWORD dwStringLength = 0;
  3100. LPSTR pszCustomSection;
  3101. DWORD dwLDID[4] = { 0 };
  3102. DWORD dwSwitches = 0;
  3103. DWORD i = 0;
  3104. DWORD dwFlag = 1;
  3105. HRESULT hResult = S_OK;
  3106. CHAR szBuffer[MAX_PATH+2];
  3107. static const CHAR c_szCustDest[] = "CustomDestination";
  3108. static const CHAR c_szSourceDirKey[] = "SourceDir";
  3109. PSTR pszTmp;
  3110. // Get section name that specifies the custom LDID information.
  3111. if ( FAILED(GetTranslatedString( c_pszInfFilename, c_pszInstallSection, c_szCustDest,
  3112. szDestSection, sizeof(szDestSection), NULL)))
  3113. {
  3114. // There is no Custom Destination specification -- this probably
  3115. // means they didn't want to have a custom destination section,
  3116. // so we just return with a warm, tingly feeling
  3117. hResult = S_OK;
  3118. goto done;
  3119. }
  3120. // author defined CustomDestination, so add some system directories to the reg before continuing
  3121. SetSysPathsInReg();
  3122. dwStringLength = GetTranslatedSection( c_pszInfFilename, szDestSection,
  3123. szDestLDIDs, sizeof(szDestLDIDs));
  3124. if ( dwStringLength == 0 ) {
  3125. ErrorMsg1Param( ctx.hWnd, IDS_ERR_INF_SYNTAX, szDestSection );
  3126. hResult = E_FAIL;
  3127. goto done;
  3128. }
  3129. pszDestLDID = szDestLDIDs;
  3130. while ( *pszDestLDID != '\0' ) {
  3131. pszNextDestLDID = pszDestLDID + lstrlen(pszDestLDID) + 1;
  3132. if (*pszDestLDID == ';')
  3133. {
  3134. pszDestLDID = pszNextDestLDID;
  3135. continue;
  3136. }
  3137. #if 0
  3138. hResult = GetTranslatedString( c_pszInfFilename, szDestSection, pszDestLDID,
  3139. szDestData, sizeof(szDestData), NULL);
  3140. if (FAILED(hResult))
  3141. {
  3142. ErrorMsg1Param( ctx.hWnd, IDS_ERR_INF_SYNTAX, szDestSection );
  3143. goto done;
  3144. }
  3145. #endif
  3146. if ( pszTmp = ANSIStrChr(pszDestLDID, '=') )
  3147. {
  3148. lstrcpy(szDestData, CharNext(pszTmp));
  3149. *pszTmp = '\0';
  3150. }
  3151. else
  3152. {
  3153. // invalid define LDID line skip
  3154. pszDestLDID = pszNextDestLDID;
  3155. continue;
  3156. }
  3157. // Parse out the information in this line.
  3158. dwFlag = ParseDestinationLine( pszDestLDID, szDestData, &pszCustomSection,
  3159. &dwLDID[0], &dwLDID[1], &dwLDID[2], &dwLDID[3] );
  3160. if ( dwFlag == -1 ) {
  3161. ErrorMsg1Param( ctx.hWnd, IDS_ERR_INF_SYNTAX, szDestSection );
  3162. hResult = E_FAIL;
  3163. goto done;
  3164. }
  3165. if ( lstrcmpi( pszCustomSection, c_szSourceDirKey ) == 0 )
  3166. {
  3167. if ( c_pszSourceDir == NULL )
  3168. {
  3169. // The line specifies "SourceDir" but we don't want to set the source dir
  3170. pszDestLDID = pszNextDestLDID;
  3171. continue;
  3172. }
  3173. }
  3174. else
  3175. {
  3176. if ( c_pszSourceDir != NULL )
  3177. {
  3178. // The line doesn't specify "SourceDir" but we want to set the source dir
  3179. pszDestLDID = pszNextDestLDID;
  3180. continue;
  3181. }
  3182. }
  3183. if ( c_pszSourceDir != NULL )
  3184. {
  3185. // szBuffer is MAX_PATH big and c_pszSourceDir is a path, so we
  3186. // shouldn't have a problem.
  3187. lstrcpy( szBuffer, c_pszSourceDir );
  3188. }
  3189. else
  3190. {
  3191. hResult = GetDestinationDir( c_pszInfFilename, pszCustomSection, dwFlag,
  3192. dwInstNeedSize, szBuffer, sizeof(szBuffer) );
  3193. if ( FAILED(hResult) ) {
  3194. // Error message displayed in GetDestinationDir
  3195. goto done;
  3196. }
  3197. }
  3198. for ( i = 0; i < 4; i += 1 )
  3199. {
  3200. // Default is ANSI LFN
  3201. dwSwitches = 0;
  3202. if ( dwLDID[i] == 0 ) {
  3203. continue;
  3204. }
  3205. if ( i == 0 || i == 3 ) {
  3206. dwSwitches |= LDID_OEM_CHARS;
  3207. }
  3208. if ( (i == 0 || i == 2)
  3209. && (dwFlag & FLAG_VALUE && !(dwFlag & FLAG_NODIRCHECK) ) )
  3210. {
  3211. dwSwitches |= LDID_SFN;
  3212. if ((i==0) && (dwLDID[3] != 0) )
  3213. {
  3214. dwSwitches |= LDID_SFN_NT_ALSO;
  3215. }
  3216. if ((i==2) && (dwLDID[1] != 0))
  3217. {
  3218. dwSwitches |= LDID_SFN_NT_ALSO;
  3219. }
  3220. }
  3221. hResult = CtlSetLddPath( dwLDID[i], szBuffer, dwSwitches );
  3222. if ( FAILED( hResult ) )
  3223. {
  3224. // Error message is displayed in ClSetLddPath function.
  3225. goto done;
  3226. }
  3227. }
  3228. pszDestLDID = pszNextDestLDID;
  3229. }
  3230. done:
  3231. return hResult;
  3232. }
  3233. //***************************************************************************
  3234. //* *
  3235. //* NAME: GetDestinationDir *
  3236. //* *
  3237. //* SYNOPSIS: *
  3238. //* *
  3239. //* REQUIRES: *
  3240. //* *
  3241. //* RETURNS: *
  3242. //* *
  3243. //***************************************************************************
  3244. HRESULT GetDestinationDir( PCSTR c_pszInfFilename, PCSTR c_pszCustomSection,
  3245. DWORD dwFlag, DWORD dwInstNeedSize,
  3246. PSTR pszBuffer, DWORD dwBufferSize )
  3247. {
  3248. BOOL fFoundRegKey = FALSE;
  3249. BOOL fFoundLine = FALSE;
  3250. DWORD j = 0;
  3251. PSTR pszCustomData = NULL;
  3252. PSTR pszCurCustomData = NULL;
  3253. LPSTR pszRootKey = NULL;
  3254. LPSTR pszBranch = NULL;
  3255. LPSTR pszValueName = NULL;
  3256. LPSTR pszPrompt = NULL;
  3257. LPSTR pszDefault = NULL;
  3258. HRESULT hResult = S_OK;
  3259. CHAR szValue[MAX_PATH+2];
  3260. ASSERT( pszBuffer != NULL );
  3261. // Reset reg key found flag. For each custom destination, we want to set
  3262. // this flag to TRUE if any one of the registry keys are found.
  3263. fFoundRegKey = FALSE;
  3264. fFoundLine = FALSE;
  3265. for ( j = 0; ; j += 1 )
  3266. {
  3267. if ( FAILED( GetTranslatedLine( c_pszInfFilename, c_pszCustomSection,
  3268. j, &pszCurCustomData, NULL ) ) || !pszCurCustomData )
  3269. {
  3270. break;
  3271. }
  3272. fFoundLine = TRUE;
  3273. // save the last valid customData line before the break off
  3274. if ( pszCustomData )
  3275. {
  3276. LocalFree( pszCustomData );
  3277. }
  3278. pszCustomData = pszCurCustomData;
  3279. // Parse out the fields in the custom destination line.
  3280. if ( ! ParseCustomLine( pszCustomData, &pszRootKey, &pszBranch,
  3281. &pszValueName, &pszPrompt, &pszDefault, TRUE, TRUE ) )
  3282. {
  3283. ErrorMsg1Param( ctx.hWnd, IDS_ERR_INF_SYNTAX, c_pszCustomSection );
  3284. hResult = E_FAIL;
  3285. goto done;
  3286. }
  3287. // Check the specified registry branch and grab the contents.
  3288. if ( GetValueFromRegistry( szValue, sizeof(szValue), pszRootKey, pszBranch, pszValueName )
  3289. == TRUE )
  3290. {
  3291. LPSTR pszTmp;
  3292. // If the INF says to strip trailing semi-colon,
  3293. // and there is a trailing semi-colon,
  3294. // then strip it.
  3295. if ( !( dwFlag & FLAG_NOSTRIP ) )
  3296. {
  3297. if ( dwFlag & FLAG_STRIPAFTER_FIRST )
  3298. {
  3299. pszTmp = ANSIStrChr( szValue, ';' );
  3300. if ( pszTmp )
  3301. *pszTmp = '\0';
  3302. }
  3303. else
  3304. {
  3305. if ( szValue[lstrlen(szValue)-1] == ';' )
  3306. {
  3307. szValue[lstrlen(szValue)-1] = '\0';
  3308. }
  3309. }
  3310. }
  3311. // strip off the trailing blanks
  3312. pszTmp = szValue;
  3313. pszTmp += lstrlen(szValue) - 1;
  3314. while ( *pszTmp == ' ' )
  3315. {
  3316. *pszTmp = '\0';
  3317. pszTmp -= 1;
  3318. }
  3319. // If the INF says to check if directory exists,
  3320. // and the directory doesn't exist,
  3321. // then treat as if the reg key wasn't found
  3322. if ( ! ( dwFlag & FLAG_NODIRCHECK )
  3323. && ! DirExists( szValue ) )
  3324. {
  3325. // Directory doesn't exist. Don't break out of loop.
  3326. }
  3327. else
  3328. {
  3329. // Directory exists
  3330. // If the INF says to save the branch in the LDID,
  3331. // then save the branch.
  3332. // Otherwise save the value.
  3333. if ( dwFlag & FLAG_VALUE )
  3334. {
  3335. pszDefault = szValue;
  3336. }
  3337. else
  3338. {
  3339. pszDefault = pszBranch;
  3340. }
  3341. fFoundRegKey = TRUE;
  3342. break;
  3343. }
  3344. }
  3345. // Note; If the registry key is not found, then the defaults as specified in
  3346. // the INF file are used.
  3347. }
  3348. if ( ! fFoundLine ) {
  3349. ErrorMsg1Param( ctx.hWnd, IDS_ERR_INF_SYNTAX, c_pszCustomSection );
  3350. hResult = E_FAIL;
  3351. goto done;
  3352. }
  3353. // 2 specified + 32 not specified + not found reg
  3354. // 2 specified + 32 specified + found reg
  3355. if ( ((dwFlag & FLAG_FAIL) && (!(dwFlag & FLAG_FAIL_NOT)) && (fFoundRegKey == FALSE))
  3356. || ((dwFlag & FLAG_FAIL) && (dwFlag & FLAG_FAIL_NOT) && (fFoundRegKey == TRUE)) )
  3357. {
  3358. // NOTE: This uses the prompt specified in the INF file.
  3359. ErrorMsg1Param( ctx.hWnd, IDS_PROMPT, pszPrompt );
  3360. hResult = E_FAIL;
  3361. goto done;
  3362. }
  3363. // Prompt the user for the destination directory.
  3364. if ( (dwFlag & FLAG_VALUE) && (! (dwFlag & FLAG_NODIRCHECK)) )
  3365. {
  3366. if ( ctx.wQuietMode || (dwFlag & FLAG_QUIET) )
  3367. {
  3368. lstrcpy( szValue, pszDefault );
  3369. // check if the directory has enough disk space to install the program
  3370. if ( !IsFullPath(szValue) ) {
  3371. hResult = E_FAIL;
  3372. goto done;
  3373. }
  3374. if ( !IsEnoughInstSpace( szValue, dwInstNeedSize, NULL ) ) {
  3375. ErrorMsg( ctx.hWnd, IDS_ERR_USER_CANCEL_INST );
  3376. hResult = HRESULT_FROM_WIN32(ERROR_DISK_FULL);
  3377. goto done;
  3378. }
  3379. if ( ! DirExists( szValue ) ) {
  3380. hResult = CreateFullPath( szValue, FALSE );
  3381. if ( FAILED(hResult) ) {
  3382. goto done;
  3383. }
  3384. }
  3385. if ( ! IsGoodDir( szValue ) ) {
  3386. hResult = E_FAIL;
  3387. goto done;
  3388. }
  3389. pszDefault = szValue;
  3390. }
  3391. else
  3392. {
  3393. CHAR szLFNValue[MAX_PATH*2];
  3394. MakeLFNPath(pszDefault, szLFNValue, TRUE);
  3395. if ( UserDirPrompt( pszPrompt, szLFNValue, szValue, sizeof(szValue), dwInstNeedSize ) )
  3396. {
  3397. pszDefault = szValue;
  3398. }
  3399. else
  3400. {
  3401. ErrorMsg( ctx.hWnd, IDS_ERR_USER_CANCEL_INST );
  3402. hResult = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  3403. goto done;
  3404. }
  3405. }
  3406. }
  3407. if ( (DWORD)lstrlen(pszDefault) >= dwBufferSize ) {
  3408. ErrorMsg( ctx.hWnd, IDS_ERR_TOO_BIG );
  3409. hResult = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  3410. goto done;
  3411. }
  3412. lstrcpy( pszBuffer, pszDefault );
  3413. done:
  3414. // free the buf allocated by GetTranslatedLine
  3415. if ( pszCustomData )
  3416. {
  3417. if ( pszCustomData == pszCurCustomData )
  3418. pszCurCustomData = NULL;
  3419. LocalFree( pszCustomData );
  3420. }
  3421. if ( pszCurCustomData )
  3422. {
  3423. LocalFree( pszCurCustomData );
  3424. }
  3425. return hResult;
  3426. }
  3427. //***************************************************************************
  3428. //* *
  3429. //* NAME: DirExists *
  3430. //* *
  3431. //* SYNOPSIS: *
  3432. //* *
  3433. //* REQUIRES: *
  3434. //* *
  3435. //* RETURNS: *
  3436. //* *
  3437. //***************************************************************************
  3438. BOOL DirExists( LPSTR szDir )
  3439. {
  3440. DWORD dwAttribs = 0;
  3441. if ( szDir == NULL ) {
  3442. return FALSE;
  3443. }
  3444. dwAttribs = GetFileAttributes( szDir );
  3445. if ( ( dwAttribs != 0xFFFFFFFF )
  3446. && ( dwAttribs & FILE_ATTRIBUTE_DIRECTORY ) )
  3447. {
  3448. return TRUE;
  3449. }
  3450. return FALSE;
  3451. }
  3452. //***************************************************************************
  3453. //* *
  3454. //* NAME: ParseDestinationLine *
  3455. //* *
  3456. //* SYNOPSIS: *
  3457. //* *
  3458. //* REQUIRES: *
  3459. //* *
  3460. //* RETURNS: *
  3461. //* *
  3462. //* Bitwise flags: *
  3463. //* *
  3464. //* bit Off On Value *
  3465. //* --- -------------------- ---------------------------- ----- *
  3466. //* 0 Get value Get branch 1 *
  3467. //* 1 Use default if none exist Fail if none exist 2 *
  3468. //* 2 Non-quiet mode Quiet mode 4 *
  3469. //* 3 Strip trailing ";" Don't strip trailing ";" 8 *
  3470. //* 4 Treat value as directory Treat value as plain string 16 *
  3471. //* *
  3472. //***************************************************************************
  3473. DWORD ParseDestinationLine( PSTR pszLDIDs, PSTR pszValue, PSTR *ppszSectionName,
  3474. PDWORD pdwLDID1, PDWORD pdwLDID2,
  3475. PDWORD pdwLDID3, PDWORD pdwLDID4 )
  3476. {
  3477. PSTR pszPoint = NULL;
  3478. DWORD dwFlag = DEFAULT_FLAGS;
  3479. DWORD dwLDID[4] = { 0 };
  3480. DWORD i = 0;
  3481. PSTR pszStr;
  3482. pszPoint = pszLDIDs;
  3483. for ( i = 0; i < 4; i += 1 )
  3484. {
  3485. // Parse the arguments, SETUP engine is not called. So we only need to check on \'
  3486. pszStr = GetStringField( &pszPoint, ",", '\"', TRUE );
  3487. if ( pszStr == NULL )
  3488. {
  3489. dwLDID[i] = 0;
  3490. }
  3491. else
  3492. {
  3493. dwLDID[i] = (DWORD) My_atol(pszStr);
  3494. }
  3495. }
  3496. *pdwLDID1 = dwLDID[0];
  3497. *pdwLDID2 = dwLDID[1];
  3498. *pdwLDID3 = dwLDID[2];
  3499. *pdwLDID4 = dwLDID[3];
  3500. pszStr = pszValue;
  3501. *ppszSectionName = GetStringField( &pszStr, ",", '\"', TRUE );
  3502. if ( *ppszSectionName == NULL || **ppszSectionName == '\0' ) {
  3503. return (DWORD)-1;
  3504. }
  3505. pszPoint = GetStringField( &pszStr, ",", '\"', TRUE );
  3506. if ( pszPoint != NULL && *pszPoint != '\0' ) {
  3507. dwFlag = (DWORD) My_atol(pszPoint);
  3508. }
  3509. // Special case this. We definitely don't want to prompt the user
  3510. // for a registry branch to use!
  3511. if ( !( dwFlag & FLAG_VALUE ) ) {
  3512. dwFlag |= FLAG_QUIET;
  3513. }
  3514. return dwFlag;
  3515. }
  3516. //***************************************************************************
  3517. //* *
  3518. //* NAME: ParseCustomLine *
  3519. //* *
  3520. //* SYNOPSIS: *
  3521. //* *
  3522. //* REQUIRES: *
  3523. //* *
  3524. //* RETURNS: *
  3525. //* *
  3526. //***************************************************************************
  3527. BOOL ParseCustomLine( PSTR pszCheckKey, PSTR *ppszRootKey, PSTR *ppszBranch,
  3528. PSTR *ppszValueName, PSTR *ppszPrompt, PSTR *ppszDefault,
  3529. BOOL bStripWhiteSpace, BOOL bProcQuote )
  3530. {
  3531. DWORD i = 0;
  3532. PSTR pszField[5] = { NULL };
  3533. BOOL bRet = TRUE;
  3534. for ( i = 0; i < 5; i++ )
  3535. {
  3536. // Parse the arguments, SETUP engine has processed \" so we only need to check on \'
  3537. if (bProcQuote)
  3538. pszField[i] = GetStringField( &pszCheckKey, ",", '\'', bStripWhiteSpace );
  3539. else
  3540. pszField[i] = GetStringFieldNoQuote( &pszCheckKey, ",", bStripWhiteSpace );
  3541. if ( pszField[i] == NULL )
  3542. {
  3543. bRet = FALSE;
  3544. break;
  3545. }
  3546. }
  3547. *ppszRootKey = pszField[0];
  3548. *ppszBranch = pszField[1];
  3549. *ppszValueName = pszField[2];
  3550. *ppszPrompt = pszField[3];
  3551. *ppszDefault = pszField[4];
  3552. return bRet;
  3553. }
  3554. //***************************************************************************
  3555. //* *
  3556. //* NAME: RegisterOCXs *
  3557. //* *
  3558. //* SYNOPSIS: *
  3559. //* *
  3560. //* REQUIRES: *
  3561. //* *
  3562. //* RETURNS: *
  3563. //* *
  3564. //***************************************************************************
  3565. BOOL RegisterOCXs( LPSTR szInfFilename, LPSTR szInstallSection,
  3566. BOOL fNeedReboot, BOOL fRegister, DWORD dwFlags )
  3567. {
  3568. HRESULT hReturnCode = S_OK;
  3569. BOOL fOleInitialized = TRUE;
  3570. PSTR pszOCXLine = NULL;
  3571. BOOL fSuccess = TRUE;
  3572. PSTR pszSection = NULL;
  3573. DWORD i = 0;
  3574. REGOCXDATA RegOCX = { 0 };
  3575. CHAR szRegisterSection[256];
  3576. PSTR pszNotUsed;
  3577. static const CHAR c_szREGISTEROCXSECTION[] = "RegisterOCXs";
  3578. static const CHAR c_szUNREGISTEROCXSECTION[] = "UnRegisterOCXs";
  3579. // If we want to register, then use the register section.
  3580. // If we want to unregister, then use the unregister section.
  3581. if ( fRegister )
  3582. {
  3583. if ( dwFlags & COREINSTALL_ROLLBACK )
  3584. {
  3585. pszSection = (PSTR) c_szUNREGISTEROCXSECTION;
  3586. if ( FAILED(GetTranslatedString( szInfFilename, szInstallSection, pszSection,
  3587. szRegisterSection, sizeof(szRegisterSection), NULL)))
  3588. {
  3589. pszSection = (PSTR) c_szREGISTEROCXSECTION;
  3590. }
  3591. }
  3592. else
  3593. pszSection = (PSTR) c_szREGISTEROCXSECTION;
  3594. }
  3595. else
  3596. {
  3597. // if it is call with ROLLBACKL flag on,
  3598. // we have backed up all the files and reg data. Now we need to unregist (the new)OCXs from Register list
  3599. // before register the old one.
  3600. //
  3601. if ( dwFlags & COREINSTALL_ROLLBACK )
  3602. pszSection = (PSTR) c_szREGISTEROCXSECTION;
  3603. else
  3604. pszSection = (PSTR) c_szUNREGISTEROCXSECTION;
  3605. }
  3606. // Grab the section name of the Register OCX section
  3607. if ( FAILED(GetTranslatedString( szInfFilename, szInstallSection, pszSection,
  3608. szRegisterSection, sizeof(szRegisterSection), NULL)))
  3609. {
  3610. // There is no Register OCX section. Assume the user wanted it that
  3611. // way and return with a big smile.
  3612. return TRUE;
  3613. }
  3614. if ( FAILED( OleInitialize( NULL ) ) )
  3615. {
  3616. fOleInitialized = FALSE;
  3617. }
  3618. #pragma prefast(disable:56,"False warning at OemToChar line. Using workaround to disable it - PREfast bug 643")
  3619. for ( i = 0; ; i += 1 )
  3620. {
  3621. if ( pszOCXLine )
  3622. {
  3623. LocalFree( pszOCXLine );
  3624. pszOCXLine = NULL;
  3625. }
  3626. if ( FAILED( GetTranslatedLine( szInfFilename, szRegisterSection, i, &pszOCXLine, NULL ) ) )
  3627. {
  3628. break;
  3629. }
  3630. // process OCX line: Name [,<switch>,<str>] where switch - i== call both entries; in == only call
  3631. // DllRegister; n == call none; Empty means just call old DllRegister.
  3632. ParseCustomLine( pszOCXLine, &(RegOCX.pszOCX), &(RegOCX.pszSwitch), &(RegOCX.pszParam), &pszNotUsed, &pszNotUsed, TRUE, FALSE );
  3633. if ( ctx.dwSetupEngine == ENGINE_SETUPX ) {
  3634. OemToChar( RegOCX.pszOCX, RegOCX.pszOCX );
  3635. }
  3636. // before re-regiester OCX at ROLLBACK case, we need to check if the file exists.
  3637. // IF not, we don't want to try to register it.
  3638. if ( dwFlags & COREINSTALL_ROLLBACK )
  3639. {
  3640. DWORD dwAttr;
  3641. dwAttr = GetFileAttributes( RegOCX.pszOCX );
  3642. if ( (dwAttr == -1 ) || (dwAttr & FILE_ATTRIBUTE_DIRECTORY) )
  3643. {
  3644. //skip this one
  3645. continue;
  3646. }
  3647. }
  3648. // If we need to reboot, then just add registrations to the run once entry.
  3649. // Otherwise try to register right away.
  3650. // If we are unregistering OCXs, then fNeedReboot should always be FALSE,
  3651. // since unregistration happens before a GenInstall.
  3652. if ( !fNeedReboot && ( !fRegister || !(dwFlags & COREINSTALL_DELAYREGISTEROCX) ) )
  3653. {
  3654. // no reboot case, the last one params are ignored.
  3655. if ( !InstallOCX( &RegOCX, TRUE, fRegister, i ) && !(dwFlags & COREINSTALL_ROLLBACK) )
  3656. {
  3657. fSuccess = FALSE;
  3658. if ( fRegister )
  3659. {
  3660. ErrorMsg1Param( ctx.hWnd, IDS_ERR_REG_OCX, RegOCX.pszOCX );
  3661. goto done;
  3662. }
  3663. else
  3664. {
  3665. ErrorMsg1Param( ctx.hWnd, IDS_ERR_UNREG_OCX, RegOCX.pszOCX );
  3666. }
  3667. }
  3668. }
  3669. else
  3670. {
  3671. // Add a runonce entry so that the OCX is registered on next boot.
  3672. //
  3673. if ( !InstallOCX( &RegOCX, FALSE, fRegister, i ) )
  3674. {
  3675. ErrorMsg1Param( ctx.hWnd, IDS_ERR_RUNONCE_REG_OCX, RegOCX.pszOCX );
  3676. fSuccess = FALSE;
  3677. goto done;
  3678. }
  3679. }
  3680. }
  3681. #pragma prefast(enable:56,"")
  3682. done:
  3683. if ( fOleInitialized ) {
  3684. OleUninitialize();
  3685. }
  3686. if ( pszOCXLine )
  3687. {
  3688. LocalFree( pszOCXLine );
  3689. }
  3690. return fSuccess;
  3691. }
  3692. //***************************************************************************
  3693. //* *
  3694. //* NAME: DelDirs *
  3695. //* *
  3696. //* SYNOPSIS: *
  3697. //* *
  3698. //* REQUIRES: *
  3699. //* *
  3700. //* RETURNS: *
  3701. //* *
  3702. //***************************************************************************
  3703. void DelDirs( LPCSTR szInfFilename, LPCSTR szInstallSection )
  3704. {
  3705. PSTR pszFolder = NULL;
  3706. CHAR szDelDirsSection[MAX_PATH];
  3707. DWORD i = 0;
  3708. if ( FAILED(GetTranslatedString( szInfFilename, szInstallSection, ADVINF_DELDIRS,
  3709. szDelDirsSection, sizeof(szDelDirsSection), NULL)))
  3710. {
  3711. // no demands on remove folders
  3712. return;
  3713. }
  3714. for ( i = 0; ; i++ )
  3715. {
  3716. if ( FAILED( GetTranslatedLine( szInfFilename, szDelDirsSection,
  3717. i, &pszFolder, NULL ) ) || !pszFolder )
  3718. {
  3719. break;
  3720. }
  3721. MyRemoveDirectory( pszFolder );
  3722. LocalFree( pszFolder );
  3723. pszFolder = NULL;
  3724. }
  3725. return;
  3726. }
  3727. //***************************************************************************
  3728. //* *
  3729. //* NAME: DoCleanup *
  3730. //* *
  3731. //* SYNOPSIS: *
  3732. //* *
  3733. //* REQUIRES: *
  3734. //* *
  3735. //* RETURNS: *
  3736. //* *
  3737. //***************************************************************************
  3738. void DoCleanup( LPCSTR szInfFilename, LPCSTR szInstallSection )
  3739. {
  3740. int iFlags;
  3741. iFlags = GetTranslatedInt(szInfFilename, szInstallSection, ADVINF_CLEANUP, 0);
  3742. if ( iFlags & CLEN_REMVINF )
  3743. {
  3744. DeleteFile( szInfFilename );
  3745. }
  3746. return;
  3747. }
  3748. // greater than 4.71.0219
  3749. //
  3750. #define ROEX_VERSION_MS 0x00040047 // 4.71
  3751. #define ROEX_VERSION_LS 0x00DB0000 // 0219.0
  3752. BOOL UseRunOnceEx()
  3753. {
  3754. DWORD dwMV, dwLV;
  3755. BOOL bRet = FALSE;
  3756. char szPath[MAX_PATH] = "";
  3757. char szBuf[MAX_PATH] = "";
  3758. DWORD dwTmp;
  3759. GetSystemDirectory( szPath,sizeof( szPath ) );
  3760. AddPath( szPath, "iernonce.dll" );
  3761. GetVersionFromFile( szPath, &dwMV, &dwLV, TRUE );
  3762. // greater than 4.71.0230
  3763. //
  3764. if ( ( dwMV > ROEX_VERSION_MS ) || (( dwMV == ROEX_VERSION_MS ) && ( dwLV >= ROEX_VERSION_LS )) )
  3765. {
  3766. GetWindowsDirectory( szBuf, MAX_PATH );
  3767. AddPath( szBuf, "explorer.exe" );
  3768. GetVersionFromFile( szBuf, &dwMV, &dwLV, TRUE );
  3769. if (( dwMV < ROEX_VERSION_MS) || (( dwMV == ROEX_VERSION_MS) && ( dwLV < ROEX_VERSION_LS )) )
  3770. {
  3771. HKEY hkey;
  3772. if ( RegCreateKeyEx( HKEY_LOCAL_MACHINE, REGSTR_PATH_RUNONCE, (ULONG)0, NULL,
  3773. REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dwTmp ) == ERROR_SUCCESS )
  3774. {
  3775. wsprintf( szBuf, RUNONCE_IERNONCE, szPath );
  3776. if ( RegSetValueEx( hkey, RUNONCEEX, 0, REG_SZ, (CONST UCHAR *)szBuf, lstrlen(szBuf)+1 )
  3777. != ERROR_SUCCESS )
  3778. {
  3779. bRet = FALSE;
  3780. RegCloseKey( hkey );
  3781. goto done;
  3782. }
  3783. RegCloseKey( hkey );
  3784. }
  3785. else
  3786. bRet = FALSE;
  3787. }
  3788. bRet = TRUE;
  3789. }
  3790. done:
  3791. return bRet;
  3792. }
  3793. void GetNextRunOnceExSubKey( HKEY hKey, PSTR pszSubKey, int *piSubKeyNum )
  3794. {
  3795. HKEY hSubKey;
  3796. for (;;)
  3797. {
  3798. wsprintf( pszSubKey, "%d", ++*piSubKeyNum );
  3799. if ( RegOpenKeyEx( hKey, pszSubKey,(ULONG) 0, KEY_READ, &hSubKey ) != ERROR_SUCCESS )
  3800. {
  3801. break;
  3802. }
  3803. else
  3804. {
  3805. RegCloseKey( hSubKey );
  3806. }
  3807. }
  3808. }
  3809. void GetNextRunOnceValName( HKEY hKey, PCSTR pszFormat, PSTR pszValName, int line )
  3810. {
  3811. do
  3812. {
  3813. wsprintf( pszValName, pszFormat, line++ );
  3814. } while ( RegQueryValueEx( hKey, pszValName, 0, NULL, NULL, NULL ) == ERROR_SUCCESS );
  3815. }
  3816. BOOL DoDllReg( HANDLE hOCX, BOOL fRegister )
  3817. {
  3818. FARPROC lpfnDllRegisterServer = NULL;
  3819. PSTR pszRegSvr = NULL;
  3820. BOOL fSuccess = FALSE;
  3821. if ( fRegister )
  3822. {
  3823. pszRegSvr = (PSTR) achREGSVRDLL;
  3824. }
  3825. else
  3826. {
  3827. pszRegSvr = (PSTR) achUNREGSVRDLL;
  3828. }
  3829. lpfnDllRegisterServer = GetProcAddress( hOCX, pszRegSvr );
  3830. if ( lpfnDllRegisterServer )
  3831. {
  3832. if ( SUCCEEDED( lpfnDllRegisterServer() ) )
  3833. {
  3834. fSuccess = TRUE;
  3835. }
  3836. }
  3837. return fSuccess;
  3838. }
  3839. BOOL DoDllInst( HANDLE hOCX, BOOL fRegister, PCSTR pszParam )
  3840. {
  3841. WCHAR pwstrDllInstArg[MAX_PATH];
  3842. DLLINSTALL pfnDllInstall = NULL;
  3843. BOOL fSuccess = FALSE;
  3844. if ( pszParam == NULL )
  3845. pszParam = "";
  3846. pfnDllInstall = (DLLINSTALL)GetProcAddress( hOCX, "DllInstall" );
  3847. if ( pfnDllInstall )
  3848. {
  3849. MultiByteToWideChar(CP_ACP, 0, pszParam, -1, pwstrDllInstArg, ARRAYSIZE(pwstrDllInstArg));
  3850. if ( SUCCEEDED( pfnDllInstall( fRegister, pwstrDllInstArg ) ) )
  3851. fSuccess = TRUE;
  3852. }
  3853. return fSuccess;
  3854. }
  3855. //***************************************************************************
  3856. //* *
  3857. //* NAME: InstallOCX *
  3858. //* *
  3859. //* SYNOPSIS: Self-registers the OCX. *
  3860. //* *
  3861. //* REQUIRES: *
  3862. //* *
  3863. //* RETURNS: *
  3864. //* *
  3865. //***************************************************************************
  3866. BOOL InstallOCX( PREGOCXDATA pRegOCX, BOOL fDoItNow, BOOL fRegister, int line )
  3867. {
  3868. PSTR lpszCmdLine = NULL;
  3869. PSTR lpszCmdLine2 = NULL;
  3870. BOOL fSuccess = TRUE;
  3871. HKEY hKey = NULL, hSubKey = NULL;
  3872. HANDLE hOCX = NULL;
  3873. BOOL bDoDllReg = TRUE, bDoDllInst = FALSE;
  3874. PSTR pszCmds[2] = { 0 };
  3875. int i;
  3876. AdvWriteToLog("InstallOCX: %1 %2\r\n", pRegOCX->pszOCX, fRegister?"Register":"UnRegister" );
  3877. // parse what kind OCX entry points to call
  3878. if ( pRegOCX->pszSwitch && *pRegOCX->pszSwitch )
  3879. {
  3880. if ( ANSIStrChr( CharUpper(pRegOCX->pszSwitch), 'I' ) )
  3881. {
  3882. bDoDllInst = TRUE;
  3883. if ( ANSIStrChr( CharUpper(pRegOCX->pszSwitch), 'N' ) )
  3884. bDoDllReg = FALSE;
  3885. }
  3886. else
  3887. {
  3888. fSuccess = FALSE;
  3889. goto done;
  3890. }
  3891. }
  3892. lpszCmdLine = (LPSTR) LocalAlloc( LPTR, BUF_1K );
  3893. lpszCmdLine2 = (LPSTR) LocalAlloc( LPTR, BUF_1K );
  3894. if ( !lpszCmdLine || !lpszCmdLine2) {
  3895. ErrorMsg( ctx.hWnd, IDS_ERR_NO_MEMORY );
  3896. fSuccess = FALSE;
  3897. goto done;
  3898. }
  3899. // fDoItNow says whether we should add to runonce or register the OCX right away
  3900. if ( fDoItNow )
  3901. {
  3902. LPCSTR szExtension = NULL;
  3903. // ignore the display name line in this case
  3904. if ( *(pRegOCX->pszOCX) == '@' )
  3905. {
  3906. goto done;
  3907. }
  3908. // Figure out what type of OCX we are trying to register: two choices
  3909. // 1. EXE
  3910. // 2. DLL/OCX/etc
  3911. //
  3912. szExtension = &pRegOCX->pszOCX[lstrlen(pRegOCX->pszOCX)-3];
  3913. if ( lstrcmpi( szExtension, "EXE" ) == 0 )
  3914. {
  3915. PSTR pszRegSvr;
  3916. if ( fRegister )
  3917. pszRegSvr = (PSTR) achREGSVREXE;
  3918. else
  3919. pszRegSvr = (PSTR) achUNREGSVREXE;
  3920. lstrcpy( lpszCmdLine, pRegOCX->pszOCX );
  3921. lstrcat( lpszCmdLine, pszRegSvr );
  3922. if ( LaunchAndWait( lpszCmdLine, NULL, NULL, INFINITE, 0 ) == E_FAIL )
  3923. {
  3924. AdvWriteToLog("InstallOCX: %1 Failed\r\n", lpszCmdLine);
  3925. fSuccess = FALSE;
  3926. goto done;
  3927. }
  3928. AdvWriteToLog("%1 : Succeeded.\r\n", lpszCmdLine);
  3929. }
  3930. else
  3931. {
  3932. AdvWriteToLog("LoadLibrary %1\r\n", pRegOCX->pszOCX);
  3933. hOCX = LoadLibraryEx( pRegOCX->pszOCX, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
  3934. if ( hOCX == NULL )
  3935. {
  3936. fSuccess = FALSE;
  3937. goto done;
  3938. }
  3939. // Install time order: DllRegisterServer, DllInstall
  3940. // Uninstall order: DllInstall, DllRegisterServer
  3941. if ( fRegister )
  3942. {
  3943. if ( bDoDllReg )
  3944. {
  3945. fSuccess = DoDllReg( hOCX, fRegister );
  3946. AdvWriteToLog("Register: DoDllReg: %1\r\n", fSuccess?"Succeeded":"Failed" );
  3947. }
  3948. if ( fSuccess && bDoDllInst )
  3949. {
  3950. fSuccess = DoDllInst( hOCX, fRegister, pRegOCX->pszParam );
  3951. AdvWriteToLog("Register: DoDllInstall: %1\r\n", fSuccess?"Succeeded":"Failed" );
  3952. }
  3953. }
  3954. else
  3955. {
  3956. if ( bDoDllInst )
  3957. {
  3958. fSuccess = DoDllInst( hOCX, fRegister, pRegOCX->pszParam );
  3959. AdvWriteToLog("UnRegister: DoDllReg: %1\r\n", fSuccess?"Succeeded":"Failed" );
  3960. }
  3961. if ( fSuccess && bDoDllReg )
  3962. {
  3963. fSuccess = DoDllReg( hOCX, fRegister );
  3964. AdvWriteToLog("UnRegister: DoDllInstall: %1\r\n", fSuccess?"Succeeded":"Failed" );
  3965. }
  3966. }
  3967. }
  3968. }
  3969. else
  3970. {
  3971. // Add to runonce or runonceex
  3972. // from current logic, Unregister OCX will never be here!
  3973. //
  3974. char szPath[MAX_PATH];
  3975. LPCSTR lpRegTmp;
  3976. DWORD dwTmp;
  3977. HKEY hRealKey;
  3978. static BOOL bRunOnceEx = FALSE;
  3979. static int iSubKeyNum = 0;
  3980. if ( iSubKeyNum == 0 )
  3981. {
  3982. if ( UseRunOnceEx() )
  3983. {
  3984. iSubKeyNum = 799;
  3985. bRunOnceEx = TRUE;
  3986. }
  3987. }
  3988. // decide to add the entry to RunOnce or RunOnceEx
  3989. if ( !bRunOnceEx )
  3990. {
  3991. // ignore the display name line in this case
  3992. if ( *(pRegOCX->pszOCX) == '@' )
  3993. {
  3994. goto done;
  3995. }
  3996. // no ierunonce.dll, use RunOnce key rather than RunOnceEx key
  3997. lpRegTmp = REGSTR_PATH_RUNONCE;
  3998. }
  3999. else
  4000. {
  4001. lpRegTmp = REGSTR_PATH_RUNONCEEX;
  4002. }
  4003. // open RunOnce or RunOnceEx key here
  4004. if ( RegCreateKeyEx( HKEY_LOCAL_MACHINE, lpRegTmp, (ULONG)0, NULL,
  4005. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwTmp ) != ERROR_SUCCESS )
  4006. {
  4007. fSuccess = FALSE;
  4008. goto done;
  4009. }
  4010. // Generate the next unused SubKey name
  4011. //
  4012. if ( bRunOnceEx )
  4013. {
  4014. if ( line == 0 )
  4015. GetNextRunOnceExSubKey( hKey, szPath, &iSubKeyNum );
  4016. else
  4017. wsprintf( szPath, "%d", iSubKeyNum );
  4018. }
  4019. // Generate the Value Name and ValueData.
  4020. //
  4021. if ( bRunOnceEx )
  4022. {
  4023. if ( RegCreateKeyEx( hKey, szPath, (ULONG)0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
  4024. NULL, &hSubKey, &dwTmp ) != ERROR_SUCCESS )
  4025. {
  4026. fSuccess = FALSE;
  4027. goto done;
  4028. }
  4029. // if use RunOnceEx, process @ leaded display name.
  4030. if ( *pRegOCX->pszOCX == '@' )
  4031. {
  4032. if ( RegSetValue( hKey, szPath, REG_SZ, (LPCSTR)CharNext(pRegOCX->pszOCX),
  4033. lstrlen(CharNext(pRegOCX->pszOCX))+1 ) != ERROR_SUCCESS )
  4034. {
  4035. fSuccess = FALSE;
  4036. }
  4037. goto done;
  4038. }
  4039. GetNextRunOnceValName( hSubKey, "%03d", szPath, line );
  4040. if ( bDoDllReg )
  4041. {
  4042. wsprintf( lpszCmdLine, RUNONCEEXDATA, pRegOCX->pszOCX, fRegister? achREGSVRDLL : achUNREGSVRDLL );
  4043. }
  4044. if ( bDoDllInst )
  4045. {
  4046. wsprintf( lpszCmdLine2, "%s|%s|%c,%s",pRegOCX->pszOCX, "DllInstall",
  4047. fRegister? 'i':'u', pRegOCX->pszParam ? pRegOCX->pszParam : "" );
  4048. }
  4049. hRealKey = hSubKey;
  4050. if ( fRegister )
  4051. {
  4052. pszCmds[0] = lpszCmdLine;
  4053. pszCmds[1] = lpszCmdLine2;
  4054. }
  4055. else
  4056. {
  4057. pszCmds[1] = lpszCmdLine;
  4058. pszCmds[0] = lpszCmdLine2;
  4059. }
  4060. }
  4061. else
  4062. {
  4063. GetNextRunOnceValName( hKey, achIEXREG, szPath, line );
  4064. wsprintf( lpszCmdLine, achRUNDLL, pRegOCX->pszOCX,
  4065. pRegOCX->pszSwitch ?pRegOCX->pszSwitch:"",
  4066. pRegOCX->pszParam ? pRegOCX->pszParam : "" );
  4067. hRealKey = hKey;
  4068. pszCmds[0] = lpszCmdLine;
  4069. pszCmds[1] = "";
  4070. }
  4071. for ( i=0; i<2; i++ )
  4072. {
  4073. if (*pszCmds[i])
  4074. {
  4075. AdvWriteToLog("Delay Register: Value=%1 Data=%2\r\n", szPath, pszCmds[i]);
  4076. if ( RegSetValueEx( hRealKey, szPath, 0, REG_SZ, (CONST UCHAR *) pszCmds[i], lstrlen(pszCmds[i])+1 )
  4077. != ERROR_SUCCESS )
  4078. {
  4079. fSuccess = FALSE;
  4080. goto done;
  4081. }
  4082. if ( bRunOnceEx )
  4083. GetNextRunOnceValName( hRealKey, "%03d", szPath, line );
  4084. }
  4085. }
  4086. }
  4087. done:
  4088. if ( hOCX != NULL ) {
  4089. FreeLibrary( hOCX );
  4090. }
  4091. if ( hSubKey != NULL ) {
  4092. RegCloseKey( hSubKey );
  4093. }
  4094. if ( hKey != NULL ) {
  4095. RegCloseKey( hKey );
  4096. }
  4097. if ( lpszCmdLine != NULL ) {
  4098. LocalFree( lpszCmdLine );
  4099. }
  4100. if ( lpszCmdLine2 != NULL )
  4101. LocalFree( lpszCmdLine2 );
  4102. AdvWriteToLog("InstallOCX: End %1\r\n", pRegOCX->pszOCX);
  4103. return fSuccess;
  4104. }
  4105. //***************************************************************************
  4106. //
  4107. // FormStrWithoutPlaceHolders( LPSTR szDst, LPCSTR szSrc, LPCSTR lpFile );
  4108. //
  4109. // This function can be easily described by giving examples of what it
  4110. // does:
  4111. // Input: GenFormStrWithoutPlaceHolders(dest,"desc=%MS_XYZ%", hinf) ;
  4112. // INF file has MS_VGA="Microsoft XYZ" in its [Strings] section!
  4113. //
  4114. // Output: "desc=Microsoft XYZ" in buffer dest when done.
  4115. //
  4116. //
  4117. // ENTRY:
  4118. // szDst - the destination where the string after the substitutions
  4119. // for the place holders (the ones enclosed in "%' chars!)
  4120. // is placed. This buffer should be big enough (LINE_LEN)
  4121. // szSrc - the string with the place holders.
  4122. //
  4123. // EXIT:
  4124. //
  4125. //***************************************************************************
  4126. DWORD FormStrWithoutPlaceHolders( LPCSTR szSrc, LPSTR szDst, DWORD dwDstSize, LPCSTR szInfFilename )
  4127. {
  4128. INT uCnt ;
  4129. CHAR *pszTmp;
  4130. LPSTR pszSaveDst;
  4131. pszSaveDst = szDst;
  4132. // Do until we reach the end of source (null char)
  4133. while( ( *szDst++ = *szSrc ) )
  4134. {
  4135. // Increment source as we have only incremented destination above
  4136. if( *szSrc++ == '%' ) {
  4137. if ( *szSrc == '%' ) {
  4138. // One can use %% to get a single percentage char in message
  4139. szSrc++;
  4140. continue;
  4141. }
  4142. // see if it is well formed -- there should be a '%' delimiter
  4143. pszTmp = (LPSTR) szSrc;
  4144. while ( (*pszTmp != '\0') && (*pszTmp != '%') )
  4145. {
  4146. pszTmp += 1;
  4147. }
  4148. if ( *pszTmp == '%' ) {
  4149. szDst--; // get back to the '%' char to replace
  4150. // yes, there is a STR_KEY to be looked for in [Strings] sect.
  4151. *pszTmp = '\0' ; // replace '%' with a NULL char
  4152. // szSrc points to the replaceable key now as we put the NULL char above.
  4153. if ( ! MyGetPrivateProfileString( szInfFilename, "Strings", szSrc,
  4154. szDst, dwDstSize - (DWORD)(szDst - pszSaveDst) ) )
  4155. {
  4156. // key is missing in [Strings] section!
  4157. return (DWORD) -1;
  4158. }
  4159. else
  4160. {
  4161. // all was well, Dst filled right, but unfortunately count not passed
  4162. // back, like it used too... :-( quick fix is a lstrlen()...
  4163. uCnt = lstrlen( szDst ) ;
  4164. }
  4165. *pszTmp = '%'; // put back original character
  4166. szSrc = pszTmp + 1 ; // set Src after the second '%'
  4167. szDst += uCnt ; // set Dst also right.
  4168. }
  4169. // else it is ill-formed -- we use the '%' as such!
  4170. else
  4171. {
  4172. return (DWORD)-1;
  4173. }
  4174. }
  4175. } /* while */
  4176. return (DWORD)lstrlen(pszSaveDst);
  4177. }
  4178. // BUGBUG:BUGBUG:BUGBUG:BUGBUG
  4179. // The code below is duplicated in wextract.exe. If you do changed/fixes to this code
  4180. // make sure to also change the code in wextract.exe
  4181. //***************************************************************************
  4182. //* *
  4183. //* NAME: GetWininitSize *
  4184. //* *
  4185. //* SYNOPSIS: *
  4186. //* *
  4187. //* REQUIRES: *
  4188. //* *
  4189. //* RETURNS: *
  4190. //* *
  4191. //***************************************************************************
  4192. // Returns the size of wininit.ini in the windows directory.
  4193. // 0 if not found
  4194. DWORD GetWininitSize()
  4195. {
  4196. CHAR szPath[MAX_PATH];
  4197. HFILE hFile;
  4198. DWORD dwSize = (DWORD)0;
  4199. if ( GetWindowsDirectory( szPath, MAX_PATH ) )
  4200. {
  4201. AddPath( szPath, "wininit.ini" );
  4202. if ((hFile = _lopen(szPath, OF_READ|OF_SHARE_DENY_NONE)) != HFILE_ERROR)
  4203. {
  4204. dwSize = _llseek(hFile, 0L, FILE_END);
  4205. _lclose(hFile);
  4206. }
  4207. }
  4208. return dwSize;
  4209. }
  4210. //***************************************************************************
  4211. //* *
  4212. //* NAME: GetRegValueSize *
  4213. //* *
  4214. //* SYNOPSIS: *
  4215. //* *
  4216. //* REQUIRES: *
  4217. //* *
  4218. //* RETURNS: *
  4219. //* *
  4220. //***************************************************************************
  4221. // Returns the size of the value lpcszValue under lpcszRegKey
  4222. // 0 if the registry key or the value were not found
  4223. DWORD GetRegValueSize(LPCSTR lpcszRegKey, LPCSTR lpcszValue)
  4224. {
  4225. HKEY hKey;
  4226. DWORD dwValueSize = (DWORD)0;
  4227. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpcszRegKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  4228. {
  4229. if (RegQueryValueEx(hKey, lpcszValue, NULL, NULL, NULL,&dwValueSize) != ERROR_SUCCESS)
  4230. dwValueSize = (DWORD)0;
  4231. RegCloseKey(hKey);
  4232. }
  4233. return dwValueSize;
  4234. }
  4235. //***************************************************************************
  4236. //* *
  4237. //* NAME: GetNumberOfValues *
  4238. //* *
  4239. //* SYNOPSIS: *
  4240. //* *
  4241. //* REQUIRES: *
  4242. //* *
  4243. //* RETURNS: *
  4244. //* *
  4245. //***************************************************************************
  4246. // Returns the number of Values in the key
  4247. // 0 if the registry key was not found or RegQueryInfoKey failed
  4248. DWORD GetNumberOfValues(LPCSTR lpcszRegKey)
  4249. {
  4250. HKEY hKey;
  4251. DWORD dwValueSize = (DWORD)0;
  4252. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpcszRegKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  4253. {
  4254. if (RegQueryInfoKey(hKey,
  4255. NULL, NULL, NULL, NULL, NULL, NULL,
  4256. &dwValueSize,
  4257. NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
  4258. dwValueSize = (DWORD)0;
  4259. RegCloseKey(hKey);
  4260. }
  4261. return dwValueSize;
  4262. }
  4263. //***************************************************************************
  4264. //* *
  4265. //* NAME: InternalNeedRebootInit *
  4266. //* *
  4267. //* SYNOPSIS: *
  4268. //* *
  4269. //* REQUIRES: *
  4270. //* *
  4271. //* RETURNS: *
  4272. //* *
  4273. //***************************************************************************
  4274. // Returns the rebootcheck value depending on the OS we get passed in.
  4275. DWORD InternalNeedRebootInit(WORD wOSVer)
  4276. {
  4277. DWORD dwReturn = (DWORD)0;
  4278. switch (wOSVer)
  4279. {
  4280. case _OSVER_WIN95:
  4281. dwReturn = GetWininitSize();
  4282. break;
  4283. case _OSVER_WINNT40:
  4284. case _OSVER_WINNT50:
  4285. case _OSVER_WINNT51:
  4286. dwReturn = GetRegValueSize(szNT4XDelayUntilReboot, szNT4XPendingValue);
  4287. break;
  4288. case _OSVER_WINNT3X:
  4289. dwReturn = GetNumberOfValues(szNT3XDelayUntilReboot);
  4290. break;
  4291. }
  4292. return dwReturn;
  4293. }
  4294. //***************************************************************************
  4295. //* *
  4296. //* NAME: InternalNeedReboot *
  4297. //* *
  4298. //* SYNOPSIS: *
  4299. //* *
  4300. //* REQUIRES: *
  4301. //* *
  4302. //* RETURNS: *
  4303. //* *
  4304. //***************************************************************************
  4305. // Checks the passed in reboot check value against the current value.
  4306. // If they are different, we need to reboot.
  4307. // The reboot check value is dependend on the OS
  4308. BOOL InternalNeedReboot(DWORD dwRebootCheck, WORD wOSVer)
  4309. {
  4310. return (dwRebootCheck != InternalNeedRebootInit(wOSVer));
  4311. }
  4312. //***************************************************************************
  4313. //* *
  4314. //* NAME: IsEnoughInstSpace *
  4315. //* *
  4316. //* SYNOPSIS: *
  4317. //* *
  4318. //* REQUIRES: *
  4319. //* *
  4320. //* RETURNS: *
  4321. //* *
  4322. //***************************************************************************
  4323. // Checks the install destination dir free disk space
  4324. //
  4325. BOOL IsEnoughInstSpace( LPSTR szPath, DWORD dwInstNeedSize, LPDWORD pdwPadSize )
  4326. {
  4327. DWORD dwFreeBytes = 0;
  4328. CHAR achDrive[MAX_PATH];
  4329. DWORD dwVolFlags;
  4330. DWORD dwMaxCompLen;
  4331. ASSERT( szPath );
  4332. // set to zero to indicate to called that the given drive can not be checked.
  4333. if ( pdwPadSize )
  4334. *pdwPadSize = 0;
  4335. // If you are here, we expect that the caller have validated the path which
  4336. // has the Fullpath directory name
  4337. //
  4338. if ( dwInstNeedSize == 0 )
  4339. return TRUE;
  4340. if ( szPath[1] == ':' )
  4341. {
  4342. lstrcpyn( achDrive, szPath, 4 );
  4343. }
  4344. else if ( (szPath[0] == '\\') && (szPath[1] == '\\') )
  4345. {
  4346. return TRUE; //no way to get it
  4347. }
  4348. else
  4349. return FALSE; // you should not get here, if so, we don't know how to check it.
  4350. if ((dwFreeBytes=GetSpace(achDrive))==0)
  4351. {
  4352. ErrorMsg1Param( NULL, IDS_ERR_GET_DISKSPACE, achDrive );
  4353. //SetCurrentDirectory( achOldPath );
  4354. return( FALSE );
  4355. }
  4356. // find out if the drive is compressed
  4357. if ( !GetVolumeInformation( achDrive, NULL, 0, NULL,
  4358. &dwMaxCompLen, &dwVolFlags, NULL, 0 ) )
  4359. {
  4360. ErrorMsg1Param( NULL, IDS_ERR_GETVOLINFOR, achDrive );
  4361. //SetCurrentDirectory( achOldPath );
  4362. return( FALSE );
  4363. }
  4364. if ( pdwPadSize )
  4365. *pdwPadSize = dwInstNeedSize;
  4366. if ( (dwVolFlags & FS_VOL_IS_COMPRESSED) && ctx.bCompressed )
  4367. {
  4368. dwInstNeedSize = dwInstNeedSize + dwInstNeedSize/4;
  4369. if ( pdwPadSize )
  4370. *pdwPadSize = dwInstNeedSize;
  4371. }
  4372. if ( dwInstNeedSize > dwFreeBytes )
  4373. return FALSE;
  4374. else
  4375. return TRUE;
  4376. }
  4377. //***************************************************************************
  4378. //* *
  4379. //* NAME: My_atol *
  4380. //* *
  4381. //* SYNOPSIS: *
  4382. //* *
  4383. //* REQUIRES: *
  4384. //* *
  4385. //* RETURNS: *
  4386. //* *
  4387. //***************************************************************************
  4388. LONG My_atol( LPSTR nptr )
  4389. {
  4390. INT c;
  4391. LONG total;
  4392. INT sign;
  4393. while ( *nptr == ' ' || *nptr == '\t' ) {
  4394. ++nptr;
  4395. }
  4396. c = (INT)(UCHAR) *nptr++;
  4397. sign = c;
  4398. if ( c == '-' || c == '+' ) {
  4399. c = (INT)(UCHAR) *nptr++;
  4400. }
  4401. total = 0;
  4402. while ( c >= '0' && c <= '9' ) {
  4403. total = 10 * total + (c - '0');
  4404. c = (INT)(UCHAR) *nptr++;
  4405. }
  4406. if ( sign == '-' ) {
  4407. return -total;
  4408. } else {
  4409. return total;
  4410. }
  4411. }
  4412. //***************************************************************************
  4413. //* *
  4414. //* NAME: My_atoi *
  4415. //* *
  4416. //* SYNOPSIS: *
  4417. //* *
  4418. //* REQUIRES: *
  4419. //* *
  4420. //* RETURNS: *
  4421. //* *
  4422. //***************************************************************************
  4423. INT My_atoi( LPSTR nptr )
  4424. {
  4425. return (INT) My_atol(nptr);
  4426. }
  4427. //***************************************************************************
  4428. //* *
  4429. //* NAME: IsFullPath *
  4430. //* *
  4431. //* SYNOPSIS: *
  4432. //* *
  4433. //* REQUIRES: *
  4434. //* *
  4435. //* RETURNS: *
  4436. //* *
  4437. //***************************************************************************
  4438. // return TRUE if given path is FULL pathname
  4439. //
  4440. BOOL IsFullPath( PCSTR pszPath )
  4441. {
  4442. if ( (pszPath == NULL) || (lstrlen(pszPath) < 3) )
  4443. {
  4444. return FALSE;
  4445. }
  4446. if ( (pszPath[1] == ':') || ((pszPath[0] == '\\') && (pszPath[1]=='\\') ) )
  4447. return TRUE;
  4448. else
  4449. return FALSE;
  4450. }
  4451. //***************************************************************************
  4452. //* *
  4453. //* NAME: GetUNCroot *
  4454. //* *
  4455. //* SYNOPSIS: *
  4456. //* *
  4457. //* REQUIRES: *
  4458. //* *
  4459. //* RETURNS: *
  4460. //* *
  4461. //***************************************************************************
  4462. /*
  4463. BOOL GetUNCroot( LPSTR pszinPath, LPSTR pszoutPath )
  4464. {
  4465. ASSERT(pszinPath);
  4466. ASSERT(pszoutPath);
  4467. // if you are called, called is sure that you are UNC path
  4468. // get \\ first
  4469. *pszoutPath++ = *pszinPath++;
  4470. *pszoutPath++ = *pszinPath++;
  4471. if ( *pszinPath == '\\' )
  4472. {
  4473. return FALSE; // catch '\\\' case
  4474. }
  4475. while ( *pszinPath != '\0' )
  4476. {
  4477. if ( *pszinPath == '\\' )
  4478. {
  4479. break;
  4480. }
  4481. *pszoutPath++ = *pszinPath++;
  4482. }
  4483. if ( *(pszinPath-1) == '\\' )
  4484. {
  4485. return FALSE;
  4486. }
  4487. *pszoutPath = '\0';
  4488. return TRUE;
  4489. }
  4490. */
  4491. //***************************************************************************
  4492. //* *
  4493. //* NAME: MyFileSize *
  4494. //* *
  4495. //* SYNOPSIS: *
  4496. //* *
  4497. //* REQUIRES: *
  4498. //* *
  4499. //* RETURNS: *
  4500. //* *
  4501. //***************************************************************************
  4502. DWORD MyFileSize( PCSTR pszFile )
  4503. {
  4504. HANDLE hFile;
  4505. DWORD dwSize = 0;
  4506. if ( *pszFile == 0 )
  4507. return 0;
  4508. hFile = CreateFile( pszFile,
  4509. GENERIC_READ,
  4510. FILE_SHARE_READ,
  4511. NULL,
  4512. OPEN_EXISTING,
  4513. 0,
  4514. NULL
  4515. );
  4516. if (hFile != INVALID_HANDLE_VALUE)
  4517. {
  4518. dwSize = GetFileSize( hFile, NULL );
  4519. CloseHandle( hFile );
  4520. }
  4521. return dwSize;
  4522. }
  4523. //***************************************************************************
  4524. //* *
  4525. //* NAME: CreateFullPath *
  4526. //* *
  4527. //* SYNOPSIS: *
  4528. //* *
  4529. //* REQUIRES: *
  4530. //* *
  4531. //* RETURNS: *
  4532. //* *
  4533. //***************************************************************************
  4534. HRESULT CreateFullPath( PCSTR c_pszPath, BOOL bHiden )
  4535. {
  4536. CHAR szPath[MAX_PATH];
  4537. PSTR pszPoint = NULL;
  4538. BOOL fLastDir = FALSE;
  4539. HRESULT hReturnCode = S_OK;
  4540. LPSTR szTmp;
  4541. int i;
  4542. if ( ! IsFullPath( (PSTR)c_pszPath ) ) {
  4543. hReturnCode = HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME);
  4544. goto done;
  4545. }
  4546. lstrcpy( szPath, c_pszPath );
  4547. if ( lstrlen(szPath) > 3 ) {
  4548. szTmp = CharPrev(szPath, szPath + lstrlen(szPath)) ;
  4549. if ( szTmp > szPath && *szTmp == '\\' )
  4550. *szTmp = '\0';
  4551. }
  4552. // If it's a UNC path, seek up to the first share name.
  4553. if ( szPath[0] == '\\' && szPath[1] == '\\' ) {
  4554. pszPoint = &szPath[2];
  4555. for (i=0; i < 2; i++) {
  4556. while ( *pszPoint != '\\' ) {
  4557. if ( *pszPoint == '\0' ) {
  4558. // Share name missing? Else, nothing after sare name!
  4559. if (i == 0)
  4560. hReturnCode = HRESULT_FROM_WIN32(ERROR_BAD_PATHNAME);
  4561. goto done;
  4562. }
  4563. pszPoint = CharNext( pszPoint );
  4564. }
  4565. }
  4566. pszPoint = CharNext( pszPoint );
  4567. } else {
  4568. // Otherwise, just point to the beginning of the first directory
  4569. pszPoint = &szPath[3];
  4570. }
  4571. while ( *pszPoint != '\0' )
  4572. {
  4573. while ( *pszPoint != '\\' && *pszPoint != '\0' )
  4574. {
  4575. pszPoint = CharNext( pszPoint );
  4576. }
  4577. if ( *pszPoint == '\0' )
  4578. {
  4579. fLastDir = TRUE;
  4580. }
  4581. *pszPoint = '\0';
  4582. if ( GetFileAttributes( szPath ) == 0xFFFFFFFF )
  4583. {
  4584. if ( ! CreateDirectory( szPath, NULL ) )
  4585. {
  4586. hReturnCode = HRESULT_FROM_WIN32(GetLastError());
  4587. break;
  4588. }
  4589. else
  4590. {
  4591. if ( fLastDir && bHiden )
  4592. SetFileAttributes( szPath, FILE_ATTRIBUTE_HIDDEN );
  4593. }
  4594. }
  4595. if ( fLastDir )
  4596. {
  4597. break;
  4598. }
  4599. *pszPoint = '\\';
  4600. pszPoint = CharNext( pszPoint );
  4601. }
  4602. done:
  4603. return hReturnCode;
  4604. }
  4605. //***************************************************************************
  4606. //* *
  4607. //* NAME: LaunchAndWait *
  4608. //* *
  4609. //* SYNOPSIS: *
  4610. //* *
  4611. //* REQUIRES: *
  4612. //* *
  4613. //* RETURNS: *
  4614. //* *
  4615. //***************************************************************************
  4616. HRESULT LaunchAndWait(LPSTR pszCmd, LPSTR pszDir, HANDLE *phProc, DWORD dwWaitTime, DWORD dwCmdsFlags)
  4617. {
  4618. STARTUPINFO startInfo = { 0 };
  4619. PROCESS_INFORMATION processInfo;
  4620. HRESULT hr = S_OK;
  4621. BOOL fRet;
  4622. if(phProc)
  4623. *phProc = NULL;
  4624. AdvWriteToLog("LaunchAndWait: Cmd=%1\r\n", pszCmd);
  4625. // Create process on pszCmd
  4626. startInfo.cb = sizeof(startInfo);
  4627. startInfo.dwFlags |= STARTF_USESHOWWINDOW;
  4628. if ( dwCmdsFlags & RUNCMDS_QUIET )
  4629. startInfo.wShowWindow = SW_HIDE;
  4630. else
  4631. startInfo.wShowWindow = SW_SHOWNORMAL ;
  4632. fRet = CreateProcess(NULL, pszCmd, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
  4633. NULL, pszDir, &startInfo, &processInfo);
  4634. if(!fRet)
  4635. {
  4636. // Create Process failed
  4637. hr = E_FAIL;
  4638. goto done;
  4639. }
  4640. else
  4641. {
  4642. HANDLE pHandle;
  4643. BOOL fQuit = FALSE;
  4644. DWORD dwRet;
  4645. CloseHandle( processInfo.hThread );
  4646. pHandle = processInfo.hProcess;
  4647. if( phProc )
  4648. {
  4649. *phProc = processInfo.hProcess;
  4650. goto done;
  4651. }
  4652. else if ( dwCmdsFlags & RUNCMDS_NOWAIT )
  4653. {
  4654. goto done;
  4655. }
  4656. while(!fQuit)
  4657. {
  4658. dwRet = MsgWaitForMultipleObjects(1, &pHandle, FALSE, dwWaitTime, QS_ALLINPUT);
  4659. // Give abort the highest priority
  4660. if( (dwRet == WAIT_OBJECT_0) || ( dwRet == WAIT_TIMEOUT) )
  4661. {
  4662. if (dwRet == WAIT_TIMEOUT)
  4663. AdvWriteToLog("LaunchAndWait: %1: TimedOut.\r\n", pszCmd);
  4664. fQuit = TRUE;
  4665. }
  4666. else
  4667. {
  4668. MSG msg;
  4669. // read all of the messages in this next loop
  4670. // removing each message as we read it
  4671. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  4672. {
  4673. // if it's a quit message we're out of here
  4674. if (msg.message == WM_QUIT)
  4675. fQuit = TRUE;
  4676. else
  4677. {
  4678. // otherwise dispatch it
  4679. DispatchMessage(&msg);
  4680. } // end of PeekMessage while loop
  4681. }
  4682. }
  4683. }
  4684. CloseHandle( pHandle );
  4685. }
  4686. done:
  4687. AdvWriteToLog("LaunchAndWait: End hr=0x%1!x!, %2\r\n", hr, pszCmd);
  4688. return hr;
  4689. }
  4690. // RO_GetPrivateProfileSection
  4691. // ensure the file attribute is not read-only because the kernel api bug
  4692. //
  4693. DWORD RO_GetPrivateProfileSection( LPCSTR lpSec, LPSTR lpBuf, DWORD dwSize, LPCSTR lpFile)
  4694. {
  4695. DWORD dwRealSize;
  4696. DWORD dwAttr;
  4697. BOOL bHaveRead = FALSE;
  4698. dwAttr = GetFileAttributes( lpFile );
  4699. if ( (dwAttr != -1) && (dwAttr & FILE_ATTRIBUTE_READONLY) )
  4700. {
  4701. if ( !SetFileAttributes( lpFile, FILE_ATTRIBUTE_NORMAL ) )
  4702. {
  4703. char szInfFilePath[MAX_PATH];
  4704. char szInfFileName[MAX_PATH];
  4705. // ErrorMsg1Param( NULL, IDS_ERR_CANT_SETA_FILE, lpFile );
  4706. if ( GetTempPath(sizeof(szInfFilePath), szInfFilePath) )
  4707. {
  4708. if ( !IsGoodDir( szInfFilePath ) )
  4709. {
  4710. GetWindowsDirectory( szInfFilePath, sizeof(szInfFilePath) );
  4711. }
  4712. if ( GetTempFileName(szInfFilePath, TEXT("INF"), 0, szInfFileName) )
  4713. {
  4714. SetFileAttributes( szInfFileName, FILE_ATTRIBUTE_NORMAL );
  4715. DeleteFile( szInfFileName );
  4716. CopyFile( lpFile, szInfFileName, FALSE );
  4717. SetFileAttributes( szInfFileName, FILE_ATTRIBUTE_NORMAL );
  4718. dwRealSize = GetPrivateProfileSection( lpSec, lpBuf, dwSize, szInfFileName );
  4719. bHaveRead = TRUE;
  4720. DeleteFile( szInfFileName );
  4721. }
  4722. }
  4723. //if ( !bHaveRead )
  4724. //ErrorMsg1Param( NULL, IDS_ERR_CANT_SETA_FILE, lpFile );
  4725. }
  4726. }
  4727. if ( !bHaveRead )
  4728. dwRealSize = GetPrivateProfileSection( lpSec, lpBuf, dwSize, lpFile );
  4729. if ( (dwAttr != -1) && (dwAttr & FILE_ATTRIBUTE_READONLY) )
  4730. {
  4731. SetFileAttributes( lpFile, dwAttr );
  4732. }
  4733. return dwRealSize;
  4734. }
  4735. BOOL GetThisModulePath( LPSTR lpPath, int size )
  4736. {
  4737. LPSTR lpTmp;
  4738. ASSERT(lpPath);
  4739. if ( GetModuleFileName( g_hInst, lpPath, size ) )
  4740. {
  4741. lpTmp = CharPrev( lpPath, lpPath+lstrlen(lpPath));
  4742. // chop filename off
  4743. //
  4744. while ( (lpTmp > lpPath) && *lpTmp && (*lpTmp != '\\') )
  4745. lpTmp = CharPrev( lpPath, lpTmp );
  4746. if ( *CharPrev( lpPath, lpTmp ) != ':' )
  4747. *lpTmp = '\0';
  4748. else
  4749. *CharNext( lpTmp ) = '\0';
  4750. return TRUE;
  4751. }
  4752. return FALSE;
  4753. }
  4754. HINSTANCE MyLoadLibrary( LPSTR lpFile )
  4755. {
  4756. CHAR szPath[MAX_PATH];
  4757. HINSTANCE hInst = NULL;
  4758. DWORD dwAttr;
  4759. ASSERT( lpFile );
  4760. if ( GetThisModulePath( szPath, sizeof(szPath) ) )
  4761. {
  4762. AddPath( szPath, lpFile );
  4763. if ( ((dwAttr = GetFileAttributes(szPath)) != -1) &&
  4764. !( dwAttr & FILE_ATTRIBUTE_DIRECTORY ) )
  4765. {
  4766. hInst = LoadLibraryEx( szPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
  4767. }
  4768. }
  4769. // If we did not load the DLL yet, try plain LoadLibrary
  4770. if (hInst == NULL)
  4771. hInst = LoadLibrary( lpFile );
  4772. return hInst;
  4773. }
  4774. // typedef into advpack.h file
  4775. //typedef struct tagVERHEAD {
  4776. // WORD wTotLen;
  4777. // WORD wValLen;
  4778. // WORD wType; /* always 0 */
  4779. // WCHAR szKey[(sizeof("VS_VERSION_INFO")+3)&~03];
  4780. // VS_FIXEDFILEINFO vsf;
  4781. //} VERHEAD ;
  4782. /*
  4783. * MyGetFileVersionInfo: Maps a file directly without using LoadLibrary. This ensures
  4784. * that the right version of the file is examined without regard to where the loaded image
  4785. * is. Since this is local, it allocates the memory which is freed by the caller.
  4786. */
  4787. BOOL
  4788. NTGetFileVersionInfo(LPTSTR lpszFilename, LPVOID *lpVersionInfo)
  4789. {
  4790. VS_FIXEDFILEINFO *pvsFFI = NULL;
  4791. UINT uiBytes = 0;
  4792. HINSTANCE hinst;
  4793. HRSRC hVerRes;
  4794. HANDLE FileHandle = NULL;
  4795. HANDLE MappingHandle = NULL;
  4796. LPVOID DllBase = NULL;
  4797. VERHEAD *pVerHead;
  4798. BOOL bResult = FALSE;
  4799. DWORD dwHandle;
  4800. DWORD dwLength;
  4801. if (!lpVersionInfo)
  4802. return FALSE;
  4803. *lpVersionInfo = NULL;
  4804. FileHandle = CreateFile( lpszFilename,
  4805. GENERIC_READ,
  4806. FILE_SHARE_READ,
  4807. NULL,
  4808. OPEN_EXISTING,
  4809. 0,
  4810. NULL
  4811. );
  4812. if (FileHandle == INVALID_HANDLE_VALUE)
  4813. goto Cleanup;
  4814. MappingHandle = CreateFileMapping( FileHandle,
  4815. NULL,
  4816. PAGE_READONLY,
  4817. 0,
  4818. 0,
  4819. NULL
  4820. );
  4821. if (MappingHandle == NULL)
  4822. goto Cleanup;
  4823. DllBase = MapViewOfFileEx( MappingHandle,
  4824. FILE_MAP_READ,
  4825. 0,
  4826. 0,
  4827. 0,
  4828. NULL
  4829. );
  4830. if (DllBase == NULL)
  4831. goto Cleanup;
  4832. hinst = (HMODULE)((ULONG_PTR)DllBase | 0x00000001);
  4833. hVerRes = FindResource(hinst, MAKEINTRESOURCE(VS_VERSION_INFO), VS_FILE_INFO);
  4834. if (hVerRes == NULL)
  4835. {
  4836. // Probably a 16-bit file. Fall back to system APIs.
  4837. if(!(dwLength = GetFileVersionInfoSize(lpszFilename, &dwHandle)))
  4838. {
  4839. if(!GetLastError())
  4840. SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
  4841. goto Cleanup;
  4842. }
  4843. if(!(*lpVersionInfo = LocalAlloc(LPTR, dwLength)))
  4844. goto Cleanup;
  4845. if(!GetFileVersionInfo(lpszFilename, 0, dwLength, *lpVersionInfo))
  4846. goto Cleanup;
  4847. bResult = TRUE;
  4848. goto Cleanup;
  4849. }
  4850. pVerHead = (VERHEAD*)LoadResource(hinst, hVerRes);
  4851. if (pVerHead == NULL)
  4852. goto Cleanup;
  4853. *lpVersionInfo = LocalAlloc(LPTR, pVerHead->wTotLen + pVerHead->wTotLen/2);
  4854. if (*lpVersionInfo == NULL)
  4855. goto Cleanup;
  4856. memcpy(*lpVersionInfo, (PVOID)pVerHead, pVerHead->wTotLen);
  4857. bResult = TRUE;
  4858. Cleanup:
  4859. if (FileHandle)
  4860. CloseHandle(FileHandle);
  4861. if (MappingHandle)
  4862. CloseHandle(MappingHandle);
  4863. if (DllBase)
  4864. UnmapViewOfFile(DllBase);
  4865. if (*lpVersionInfo && bResult == FALSE)
  4866. LocalFree(*lpVersionInfo);
  4867. return bResult;
  4868. }
  4869. // this API will always get the version of the disk file
  4870. HRESULT WINAPI GetVersionFromFileEx(LPSTR lpszFilename, LPDWORD pdwMSVer, LPDWORD pdwLSVer, BOOL bVersion)
  4871. {
  4872. unsigned uiSize;
  4873. DWORD dwVerInfoSize;
  4874. DWORD dwHandle;
  4875. VS_FIXEDFILEINFO * lpVSFixedFileInfo;
  4876. void FAR *lpBuffer = NULL;
  4877. LPVOID lpVerBuffer;
  4878. CHAR szNewName[MAX_PATH];
  4879. BOOL bToCleanup = FALSE;
  4880. BOOL bContinue = FALSE;
  4881. *pdwMSVer = *pdwLSVer = 0L;
  4882. bContinue = NTGetFileVersionInfo(lpszFilename, &lpBuffer);
  4883. if ( bContinue )
  4884. {
  4885. if (bVersion)
  4886. {
  4887. // Get the value for Translation
  4888. if (VerQueryValue(lpBuffer, "\\", (LPVOID*)&lpVSFixedFileInfo, &uiSize) &&
  4889. (uiSize))
  4890. {
  4891. *pdwMSVer = lpVSFixedFileInfo->dwFileVersionMS;
  4892. *pdwLSVer = lpVSFixedFileInfo->dwFileVersionLS;
  4893. }
  4894. }
  4895. else
  4896. {
  4897. if (VerQueryValue(lpBuffer, "\\VarFileInfo\\Translation", &lpVerBuffer, &uiSize) &&
  4898. (uiSize))
  4899. {
  4900. *pdwMSVer = LOWORD(*((DWORD *) lpVerBuffer)); // Language ID
  4901. *pdwLSVer = HIWORD(*((DWORD *) lpVerBuffer)); // Codepage ID
  4902. }
  4903. }
  4904. }
  4905. if ( bToCleanup )
  4906. DeleteFile( szNewName );
  4907. if ( lpBuffer )
  4908. LocalFree( lpBuffer );
  4909. return S_OK;
  4910. }
  4911. //this api will get the version of the file being loaded
  4912. HRESULT WINAPI GetVersionFromFile(LPSTR lpszFilename, LPDWORD pdwMSVer, LPDWORD pdwLSVer, BOOL bVersion)
  4913. {
  4914. unsigned uiSize;
  4915. DWORD dwVerInfoSize;
  4916. DWORD dwHandle;
  4917. VS_FIXEDFILEINFO * lpVSFixedFileInfo;
  4918. void FAR *lpBuffer;
  4919. LPVOID lpVerBuffer;
  4920. CHAR szNewName[MAX_PATH];
  4921. BOOL bToCleanup = FALSE;
  4922. *pdwMSVer = *pdwLSVer = 0L;
  4923. dwVerInfoSize = GetFileVersionInfoSize(lpszFilename, &dwHandle);
  4924. lstrcpy( szNewName, lpszFilename );
  4925. if ( (dwVerInfoSize == 0) && FileExists( szNewName ) )
  4926. {
  4927. CHAR szPath[MAX_PATH];
  4928. // due to version.dll bug, file in extended character path will failed version.dll apis.
  4929. // So we copy it to a normal path and get its version info from there then clean it up.
  4930. GetWindowsDirectory( szPath, sizeof(szPath) );
  4931. GetTempFileName( szPath, "_&_", 0, szNewName );
  4932. CopyFile( lpszFilename, szNewName, FALSE );
  4933. bToCleanup = TRUE;
  4934. dwVerInfoSize = GetFileVersionInfoSize( szNewName, &dwHandle );
  4935. }
  4936. if (dwVerInfoSize)
  4937. {
  4938. // Alloc the memory for the version stamping
  4939. lpBuffer = LocalAlloc(LPTR, dwVerInfoSize);
  4940. if (lpBuffer)
  4941. {
  4942. // Read version stamping info
  4943. if (GetFileVersionInfo(szNewName, dwHandle, dwVerInfoSize, lpBuffer))
  4944. {
  4945. if (bVersion)
  4946. {
  4947. // Get the value for Translation
  4948. if (VerQueryValue(lpBuffer, "\\", (LPVOID*)&lpVSFixedFileInfo, &uiSize) &&
  4949. (uiSize))
  4950. {
  4951. *pdwMSVer = lpVSFixedFileInfo->dwFileVersionMS;
  4952. *pdwLSVer = lpVSFixedFileInfo->dwFileVersionLS;
  4953. }
  4954. }
  4955. else
  4956. {
  4957. if (VerQueryValue(lpBuffer, "\\VarFileInfo\\Translation", &lpVerBuffer, &uiSize) &&
  4958. (uiSize))
  4959. {
  4960. *pdwMSVer = LOWORD(*((DWORD *) lpVerBuffer)); // Language ID
  4961. *pdwLSVer = HIWORD(*((DWORD *) lpVerBuffer)); // Codepage ID
  4962. }
  4963. }
  4964. }
  4965. LocalFree(lpBuffer);
  4966. }
  4967. }
  4968. if ( bToCleanup )
  4969. DeleteFile( szNewName );
  4970. return S_OK;
  4971. }
  4972. #define WININIT_INI "wininit.ini"
  4973. // when the files is busy, adding them to wininit.ini
  4974. //
  4975. BOOL AddWinInit( LPSTR from, LPSTR to)
  4976. {
  4977. LPSTR lpWininit;
  4978. BOOL bRet = FALSE;
  4979. if ( ctx.wOSVer == _OSVER_WIN95 )
  4980. {
  4981. lpWininit = (LPSTR) LocalAlloc( LPTR, MAX_PATH );
  4982. if ( !lpWininit )
  4983. {
  4984. ErrorMsg( NULL, IDS_ERR_NO_MEMORY );
  4985. return FALSE;
  4986. }
  4987. GetWindowsDirectory( lpWininit, MAX_PATH);
  4988. AddPath( lpWininit, WININIT_INI);
  4989. WritePrivateProfileString( NULL, NULL, NULL, lpWininit );
  4990. if ( WritePrivateProfileString( "Rename", to, from, lpWininit ) )
  4991. bRet = TRUE;
  4992. WritePrivateProfileString( NULL, NULL, NULL, lpWininit );
  4993. LocalFree( lpWininit );
  4994. }
  4995. else
  4996. {
  4997. bRet = MoveFileEx(from, to, MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING);
  4998. }
  4999. return bRet;
  5000. }
  5001. void GetBackupName( LPSTR lpName, BOOL fOld )
  5002. {
  5003. LPSTR pTmp;
  5004. LPSTR pExt;
  5005. #define BACK_OLD ".~ol"
  5006. #define BACK_NEW ".~nw"
  5007. if ( fOld )
  5008. pExt = BACK_OLD;
  5009. else
  5010. pExt = BACK_NEW;
  5011. pTmp = CharPrev( lpName, lpName + lstrlen(lpName) );
  5012. while ( (pTmp>lpName) && *pTmp && (*pTmp != '\\') && (*pTmp != '.') )
  5013. {
  5014. pTmp = CharPrev( lpName, pTmp );
  5015. }
  5016. if ( (pTmp==lpName) || (*pTmp == '\\') )
  5017. {
  5018. lstrcat( lpName, pExt );
  5019. }
  5020. else
  5021. {
  5022. lstrcpy( pTmp, pExt );
  5023. }
  5024. }
  5025. BOOL UpdateHelpDlls( LPCSTR *ppszDlls, INT numDlls, LPSTR pszPath, LPSTR pszMsg, DWORD dwFlag)
  5026. {
  5027. DWORD dwSysMsV, dwSysLsV, dwTmpMsV, dwTmpLsV;
  5028. int i = 0;
  5029. LPSTR pSysEnd;
  5030. LPSTR pTmpEnd;
  5031. CHAR szTmpPath[MAX_PATH] = { 0 };
  5032. CHAR szSystemPath[MAX_PATH] = { 0 };
  5033. CHAR szBuf[MAX_PATH];
  5034. BOOL fCopySucc = TRUE;
  5035. BOOL bRet = TRUE;
  5036. BOOL fBackup[3] = {0};
  5037. BOOL bAlertReboot = FALSE;
  5038. // This function is used to update all the help Dlls: advpack, setupapi or setupx
  5039. // based on passed in ppDlls
  5040. // if not path passed in, get the module path (tmp path)
  5041. if (pszPath==NULL)
  5042. {
  5043. if (!GetThisModulePath( szTmpPath, sizeof(szTmpPath) ) )
  5044. {
  5045. DEBUGMSG("Can not get ModuleFileName directory");
  5046. return FALSE;
  5047. }
  5048. }
  5049. else
  5050. lstrcpy( szTmpPath, pszPath);
  5051. pTmpEnd = szTmpPath + lstrlen(szTmpPath);
  5052. // check if the newer or equal version files exist
  5053. if ( !GetSystemDirectory( szSystemPath, sizeof(szSystemPath) ) )
  5054. {
  5055. DEBUGMSG("Can not get system directory");
  5056. return FALSE;
  5057. }
  5058. pSysEnd = szSystemPath + lstrlen(szSystemPath);
  5059. // check if the.dll need to be updated
  5060. //
  5061. for ( i = 0; i < numDlls; i += 1 )
  5062. {
  5063. // restore the systemPath and ModulePath
  5064. *pTmpEnd = '\0';
  5065. *pSysEnd = '\0';
  5066. AddPath( szTmpPath, ppszDlls[i] );
  5067. if ( GetFileAttributes( szTmpPath ) == -1 )
  5068. {
  5069. continue;
  5070. }
  5071. GetVersionFromFile( szTmpPath, &dwTmpMsV, &dwTmpLsV, TRUE );
  5072. AddPath( szSystemPath, ppszDlls[i] );
  5073. if ( GetFileAttributes( szSystemPath ) != -1 )
  5074. {
  5075. GetVersionFromFile( szSystemPath, &dwSysMsV, &dwSysLsV, TRUE );
  5076. // compare if we need to copy those files
  5077. //
  5078. if ( (dwSysMsV > dwTmpMsV) ||
  5079. ((dwSysMsV == dwTmpMsV) && (dwSysLsV >= dwTmpLsV)) )
  5080. {
  5081. continue;
  5082. }
  5083. SetFileAttributes( szSystemPath, FILE_ATTRIBUTE_NORMAL );
  5084. //backup the original files first
  5085. lstrcpy( szBuf, szSystemPath );
  5086. GetBackupName( szBuf, TRUE );
  5087. SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
  5088. DeleteFile( szBuf );
  5089. if ( MoveFile( szSystemPath, szBuf ) )
  5090. {
  5091. fBackup[i] = TRUE;
  5092. }
  5093. }
  5094. if ( !CopyFile( szTmpPath, szSystemPath, FALSE ) )
  5095. {
  5096. //if forced to update
  5097. if ( dwFlag & UPDHLPDLLS_FORCED )
  5098. {
  5099. // copy to a basename.000 format
  5100. lstrcpy( szBuf, szSystemPath );
  5101. // get the temp name in destination dir to copy to
  5102. GetBackupName( szBuf, FALSE );
  5103. SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
  5104. if ( CopyFile( szTmpPath, szBuf, FALSE ) )
  5105. {
  5106. if ( AddWinInit( szBuf, szSystemPath ) )
  5107. {
  5108. if (dwFlag & UPDHLPDLLS_ALERTREBOOT)
  5109. bAlertReboot = TRUE;
  5110. continue;
  5111. }
  5112. else
  5113. bRet = FALSE;
  5114. }
  5115. else
  5116. {
  5117. wsprintf( szBuf, "Cannot create TMP file for %s Dll.", pszMsg );
  5118. DEBUGMSG(szBuf);
  5119. bRet = FALSE;
  5120. }
  5121. }
  5122. // you are here, means the current CopyFile/delay-CopyFile failed.
  5123. // restore the original state, clean-up backup file if there.
  5124. //
  5125. while ( i >= 0 )
  5126. {
  5127. if ( fBackup[i] )
  5128. {
  5129. *pSysEnd = '\0';
  5130. AddPath( szSystemPath, ppszDlls[i] );
  5131. lstrcpy( szBuf, szSystemPath );
  5132. GetBackupName( szBuf, TRUE );
  5133. SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
  5134. DeleteFile( szSystemPath );
  5135. if( !MoveFile( szBuf, szSystemPath ) )
  5136. {
  5137. wsprintf(szBuf, "Cannot restore %s dlls.", pszMsg);
  5138. DEBUGMSG(szBuf);
  5139. }
  5140. }
  5141. i--;
  5142. }
  5143. fCopySucc = FALSE;
  5144. break;
  5145. }
  5146. }
  5147. // clean up .~ol files
  5148. if ( fCopySucc )
  5149. {
  5150. for ( i=0; i<numDlls; i++)
  5151. {
  5152. if ( fBackup[i] )
  5153. {
  5154. *pSysEnd = '\0';
  5155. AddPath( szSystemPath, ppszDlls[i]);
  5156. lstrcpy( szBuf, szSystemPath );
  5157. GetBackupName( szBuf, TRUE );
  5158. SetFileAttributes( szBuf, FILE_ATTRIBUTE_NORMAL );
  5159. DeleteFile( szBuf );
  5160. }
  5161. }
  5162. // if caller want ot alert reboot, means that they want to get false return if the dlls is not
  5163. // in place now.
  5164. if (bAlertReboot)
  5165. bRet = FALSE;
  5166. }
  5167. return bRet;
  5168. }
  5169. void MyRemoveDirectory( LPSTR szFolder )
  5170. {
  5171. while ( RemoveDirectory( szFolder ) )
  5172. {
  5173. GetParentDir( szFolder );
  5174. }
  5175. }
  5176. BOOL IsDrvChecked( char chDrv )
  5177. {
  5178. static char szDrvChecked[MAX_NUM_DRIVES] = { 0 };
  5179. int idx;
  5180. idx = (CHAR)CharUpper( (PSTR)chDrv ) - 'A';
  5181. if ( szDrvChecked[idx] )
  5182. return TRUE;
  5183. else
  5184. szDrvChecked[idx] = chDrv;
  5185. return FALSE;
  5186. }
  5187. /////////////////////////////////////////////////////////////////////////////
  5188. // ENTRY POINT: DelNode
  5189. //
  5190. // SYNOPSIS: Deletes a file or directory
  5191. //
  5192. // RETURNS:
  5193. // S_OK success
  5194. // E_FAIL failure
  5195. /////////////////////////////////////////////////////////////////////////////
  5196. #define ADN_NO_SAFETY_CHECKS 0x40000000 // undocumented flag
  5197. HRESULT WINAPI DelNode(LPCSTR pszFileOrDirName, DWORD dwFlags)
  5198. {
  5199. HRESULT hResult = S_OK;
  5200. // we won't handle relative paths and UNC's(unless flag specified)
  5201. // BUGBUG: <oliverl> we're not checking for UNC server here
  5202. if (!IsFullPath(pszFileOrDirName) ||
  5203. (pszFileOrDirName[0] == '\\' && pszFileOrDirName[1] == '\\' &&
  5204. !(dwFlags & ADN_DEL_UNC_PATHS)))
  5205. return E_FAIL;
  5206. if (!(GetFileAttributes(pszFileOrDirName) & FILE_ATTRIBUTE_DIRECTORY)) // file
  5207. {
  5208. SetFileAttributes(pszFileOrDirName, FILE_ATTRIBUTE_NORMAL);
  5209. if (!DeleteFile(pszFileOrDirName))
  5210. hResult = E_FAIL;
  5211. }
  5212. else if (dwFlags & ADN_DEL_IF_EMPTY) // delete the dir only if it's empty
  5213. {
  5214. SetFileAttributes(pszFileOrDirName, FILE_ATTRIBUTE_NORMAL);
  5215. if (!RemoveDirectory(pszFileOrDirName))
  5216. hResult = E_FAIL;
  5217. }
  5218. else // delete the node
  5219. {
  5220. char szFile[MAX_PATH], *pszPtr;
  5221. WIN32_FIND_DATA fileData;
  5222. HANDLE hFindFile;
  5223. if (!(dwFlags & ADN_NO_SAFETY_CHECKS))
  5224. {
  5225. // if pszFileOrDirName is the root dir or windows dir or system dir or
  5226. // Program Files dir, return E_FAIL; this is just a safety precaution
  5227. hResult = DirSafe(pszFileOrDirName);
  5228. }
  5229. if (SUCCEEDED(hResult))
  5230. {
  5231. lstrcpy(szFile, pszFileOrDirName);
  5232. AddPath(szFile, "");
  5233. pszPtr = szFile + lstrlen(szFile); // save this position
  5234. lstrcpy(pszPtr, "*");
  5235. if ((hFindFile = FindFirstFile(szFile, &fileData)) != INVALID_HANDLE_VALUE)
  5236. {
  5237. do
  5238. {
  5239. // skip "." and ".."; if ADN_DONT_DEL_SUBDIRS is specified, skip all sub-dirs
  5240. if ((fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  5241. (lstrcmp(fileData.cFileName, ".") == 0 ||
  5242. lstrcmp(fileData.cFileName, "..") == 0 ||
  5243. (dwFlags & ADN_DONT_DEL_SUBDIRS)))
  5244. continue;
  5245. lstrcpy(pszPtr, fileData.cFileName);
  5246. // we need to pass along the ADN_DEL_UNC_PATHS flag, but all other flags
  5247. // are only for the top level node
  5248. if (dwFlags & ADN_DEL_UNC_PATHS)
  5249. hResult = DelNode(szFile, ADN_DEL_UNC_PATHS);
  5250. else
  5251. hResult = DelNode(szFile, 0); // delete the file or sub-dir
  5252. } while (SUCCEEDED(hResult) && FindNextFile(hFindFile, &fileData));
  5253. FindClose(hFindFile);
  5254. if (SUCCEEDED(hResult) && !(dwFlags & ADN_DONT_DEL_DIR))
  5255. {
  5256. // delete the dir; if DelNode fails, it's an error condition if ADN_DONT_DEL_SUBDIRS is not specified
  5257. if (dwFlags & ADN_DEL_UNC_PATHS)
  5258. {
  5259. if (FAILED(DelNode(pszFileOrDirName, ADN_DEL_IF_EMPTY | ADN_DEL_UNC_PATHS)) &&
  5260. !(dwFlags & ADN_DONT_DEL_SUBDIRS))
  5261. hResult = E_FAIL;
  5262. }
  5263. else
  5264. {
  5265. if (FAILED(DelNode(pszFileOrDirName, ADN_DEL_IF_EMPTY)) && !(dwFlags & ADN_DONT_DEL_SUBDIRS))
  5266. hResult = E_FAIL;
  5267. }
  5268. }
  5269. }
  5270. else
  5271. hResult = E_FAIL;
  5272. }
  5273. }
  5274. return hResult;
  5275. }
  5276. /////////////////////////////////////////////////////////////////////////////
  5277. // ENTRY POINT: DelNodeRunDLL32
  5278. //
  5279. // SYNOPSIS: Deletes a file or directory; the parameters to this API are of
  5280. // WinMain type
  5281. //
  5282. // RETURNS:
  5283. // S_OK success
  5284. // E_FAIL failure
  5285. /////////////////////////////////////////////////////////////////////////////
  5286. HRESULT WINAPI DelNodeRunDLL32(HWND hwnd, HINSTANCE hInstance, PSTR pszParms, INT nShow)
  5287. {
  5288. PSTR pszFileOrDirName = GetStringField(&pszParms, ",", '\"', TRUE);
  5289. PSTR pszFlags = GetStringField(&pszParms, ",", '\"', TRUE);
  5290. return DelNode(pszFileOrDirName, (pszFlags != NULL) ? My_atol(pszFlags) : 0);
  5291. }
  5292. HRESULT DirSafe(LPCSTR pszDir)
  5293. // If pszDir is the root drive of windows dir or windows dir or system dir or
  5294. // Program Files dir, return E_FAIL; otherwise, return S_OK
  5295. {
  5296. char szUnsafeDir[MAX_PATH], szDir[MAX_PATH];
  5297. lstrcpy(szDir, pszDir);
  5298. AddPath(szDir, "");
  5299. *szUnsafeDir = '\0';
  5300. GetWindowsDirectory(szUnsafeDir, sizeof(szUnsafeDir));
  5301. AddPath(szUnsafeDir, "");
  5302. if (lstrcmpi(szDir, szUnsafeDir) == 0) // windows dir
  5303. return E_FAIL;
  5304. else
  5305. {
  5306. szUnsafeDir[3] = '\0';
  5307. if (lstrcmpi(szDir, szUnsafeDir) == 0) // root drive of windows dir
  5308. return E_FAIL;
  5309. else
  5310. {
  5311. *szUnsafeDir = '\0';
  5312. GetSystemDirectory(szUnsafeDir, sizeof(szUnsafeDir));
  5313. AddPath(szUnsafeDir, "");
  5314. if (lstrcmpi(szDir, szUnsafeDir) == 0) // system dir
  5315. return E_FAIL;
  5316. else
  5317. {
  5318. *szUnsafeDir = '\0';
  5319. GetProgramFilesDir(szUnsafeDir, sizeof(szUnsafeDir));
  5320. AddPath(szUnsafeDir, "");
  5321. if (lstrcmpi(szDir, szUnsafeDir) == 0) // program files dir
  5322. return E_FAIL;
  5323. else
  5324. {
  5325. // check for the short pathname of the program files dir
  5326. GetShortPathName(szUnsafeDir, szUnsafeDir, sizeof(szUnsafeDir));
  5327. AddPath(szUnsafeDir, "");
  5328. if (lstrcmpi(szDir, szUnsafeDir) == 0) // short pathname of program files dir
  5329. return E_FAIL;
  5330. }
  5331. }
  5332. }
  5333. }
  5334. return S_OK;
  5335. }
  5336. void SetControlFont()
  5337. {
  5338. LOGFONT lFont;
  5339. if (GetSystemMetrics(SM_DBCSENABLED) &&
  5340. (GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof (lFont), &lFont) > 0))
  5341. {
  5342. g_hFont = CreateFontIndirect((LPLOGFONT)&lFont);
  5343. }
  5344. }
  5345. void SetFontForControl(HWND hwnd, UINT uiID)
  5346. {
  5347. if (g_hFont)
  5348. {
  5349. SendDlgItemMessage(hwnd, uiID, WM_SETFONT, (WPARAM)g_hFont ,0L);
  5350. }
  5351. }
  5352. void MyGetPlatformSection(LPCSTR lpSec, LPCSTR lpInfFile, LPSTR szNewSection)
  5353. {
  5354. OSVERSIONINFO VerInfo;
  5355. SYSTEM_INFO SystemInfo;
  5356. char szSection[MAX_PATH];
  5357. DWORD dwReqSize = 0;
  5358. lstrcpy(szSection, lpSec);
  5359. lstrcpy(szNewSection, lpSec);
  5360. VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  5361. GetVersionEx(&VerInfo);
  5362. if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  5363. {
  5364. GetSystemInfo( &SystemInfo );
  5365. switch (SystemInfo.wProcessorArchitecture)
  5366. {
  5367. case PROCESSOR_ARCHITECTURE_INTEL:
  5368. lstrcat( szSection, ".NTx86" );
  5369. break;
  5370. case PROCESSOR_ARCHITECTURE_AMD64:
  5371. lstrcat( szSection, ".NTAmd64" );
  5372. break;
  5373. case PROCESSOR_ARCHITECTURE_IA64:
  5374. lstrcat( szSection, ".NTIa64" );
  5375. break;
  5376. default:
  5377. DEBUGMSG("MyGetPlatformSection - need to deal w/ new PROCESS_ARCHITECTURE type!!");
  5378. ASSERT(FALSE);
  5379. break;
  5380. }
  5381. if (SUCCEEDED(GetTranslatedLine(lpInfFile, szSection, 0,
  5382. NULL, &dwReqSize )) && (dwReqSize!=0))
  5383. {
  5384. lstrcpy(szNewSection, szSection);
  5385. }
  5386. else
  5387. {
  5388. lstrcpy(szSection, lpSec);
  5389. lstrcat(szSection, ".NT");
  5390. if (SUCCEEDED(GetTranslatedLine(lpInfFile, szSection, 0,
  5391. NULL, &dwReqSize )) && (dwReqSize!=0))
  5392. lstrcpy(szNewSection, szSection);
  5393. }
  5394. }
  5395. else
  5396. {
  5397. lstrcat(szSection, ".WIN");
  5398. if (SUCCEEDED(GetTranslatedLine(lpInfFile, szSection, 0,
  5399. NULL, &dwReqSize )) && (dwReqSize!=0))
  5400. lstrcpy(szNewSection, szSection);
  5401. }
  5402. }
  5403. typedef HRESULT (WINAPI *PFProcessDownloadSection)(HINF, HWND, BOOL, LPCSTR, LPCSTR, LPVOID);
  5404. HRESULT RunPatchingCommands(PCSTR c_pszInfFilename, PCSTR szInstallSection, PCSTR c_pszSourceDir)
  5405. {
  5406. CHAR szBuf[512];
  5407. CHAR szDllName[MAX_PATH];
  5408. HRESULT hResult = S_OK;
  5409. INFCONTEXT InfContext;
  5410. static const CHAR c_szPatching[] = "Patching";
  5411. static const CHAR c_szAdvpackExt[] = "LoadAdvpackExtension";
  5412. //Check if patching is enabled for this section
  5413. if(!GetTranslatedInt(c_pszInfFilename, szInstallSection, c_szPatching, 0))
  5414. {
  5415. goto done;
  5416. }
  5417. //Read the dllname and entry point from LoadAdvpackExtension= line
  5418. if(FAILED(GetTranslatedString(c_pszInfFilename, szInstallSection, c_szAdvpackExt, szBuf, sizeof(szBuf), NULL)))
  5419. {
  5420. goto done;
  5421. }
  5422. //Got the extension dll
  5423. if(GetFieldString(szBuf, 0, szDllName, sizeof(szDllName)))
  5424. {
  5425. CHAR szEntryPoint[MAX_PATH];
  5426. HINSTANCE hInst = LoadLibrary(szDllName);
  5427. if(!hInst)
  5428. {
  5429. hResult = HRESULT_FROM_WIN32(GetLastError());
  5430. goto done;
  5431. }
  5432. if(GetFieldString(szBuf, 1, szEntryPoint, sizeof(szEntryPoint)))
  5433. {
  5434. PFProcessDownloadSection pfn = (PFProcessDownloadSection)GetProcAddress(hInst, szEntryPoint);
  5435. if(!pfn)
  5436. {
  5437. hResult = HRESULT_FROM_WIN32(GetLastError());
  5438. goto done;
  5439. }
  5440. hResult = pfn(ctx.hInf, ctx.hWnd, ctx.wQuietMode, szInstallSection, c_pszSourceDir, NULL);
  5441. }
  5442. FreeLibrary(hInst);
  5443. }
  5444. done:
  5445. return hResult;
  5446. }