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.

1132 lines
33 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. runmyinf.c
  5. Abstract:
  6. This windows app is the setup program for installing symbols off of
  7. the Customer Support Diagnostics CD. It calls LaunchInfSection in
  8. advpack.dll to run "symbols.inf" that is sitting in the same directory.
  9. By default it launches DefaultInstall.
  10. The setup is designed to be used with a chained install for the Customer
  11. Support CD for Service Packs. If the Service Pack inf (symbols_sp.inf)
  12. is present in the same directory as symbols.inf, then the program launches
  13. DefaultInstall.Chained.1 in symbols.inf and DefaultInstall.Chained.2
  14. in symbols_sp.inf.
  15. Author:
  16. Barb Kess (barbkess) 19-July-1999
  17. Environment:
  18. User Mode
  19. --*/
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <assert.h>
  24. #include "dbghelp.h"
  25. #include "advpub.h"
  26. #include "setupapi.h"
  27. #include "spapip.h"
  28. #include "winbase.h"
  29. #include "tchar.h"
  30. #include "resource.h"
  31. #include "runmyinf.h"
  32. #include "strsafe.h"
  33. // header for CheckCommandLineOptions()
  34. #include "CommandLine.h"
  35. #define MAX_FILENAME (300)
  36. // Global variables
  37. LPTSTR szEulaFile = _T("eula.txt");
  38. TCHAR szEulaFullPath[_MAX_PATH*2];
  39. TCHAR szInfName1[_MAX_PATH*2];
  40. BOOL ChainedInstall=FALSE;
  41. // dwInstallOptions is global so all subs can test for FLAG_TOTALLY_QUIET and FLAG_UNATTENDED_INSTALL
  42. DWORD dwInstallOptions;
  43. //
  44. // Call back procedure for displaying the license agreement
  45. //
  46. INT_PTR
  47. CALLBACK
  48. DlgProcDisplayLicense(
  49. HWND hwndDlg,
  50. UINT uMsg,
  51. WPARAM wParam,
  52. LPARAM lParam
  53. );
  54. BOOL
  55. CopyFilesToTempDir(
  56. LPTSTR szSrcDir,
  57. LPTSTR szInfDir
  58. );
  59. BOOL
  60. CopySomeFiles(
  61. LPTSTR szSrcDir,
  62. LPTSTR szDestDir,
  63. LPTSTR szFileName
  64. );
  65. BOOL
  66. DeleteFilesAndTempDir(
  67. LPTSTR szTempDir
  68. );
  69. BOOL
  70. GetTempDirName(
  71. LPTSTR szTempDir
  72. );
  73. BOOL
  74. MyMakeSureDirectoryPathExists(
  75. LPCSTR DirPath
  76. );
  77. BOOL
  78. DeleteAllFilesInDirectory(
  79. LPTSTR szDir
  80. );
  81. BOOL
  82. DeleteSymbolInstallKey(
  83. );
  84. BOOL
  85. SymbolInstallKeyExists(
  86. );
  87. //
  88. // Procedure taken from wextract.c code that centers the window
  89. //
  90. BOOL
  91. CenterWindow(
  92. HWND hwndChild,
  93. HWND hwndParent
  94. );
  95. //
  96. // Procedure that reads the license agreement into a buffer
  97. //
  98. DWORD
  99. GetMyBuffer(
  100. LPTSTR* pszBuf,
  101. LPTSTR szFileName
  102. );
  103. //
  104. // This setupapi function is only available on Windows 2000.
  105. // Therefore it is getting loaded manually so NT4 installs won't
  106. // throw up a pop-up saying it can't find this function
  107. //
  108. #define pSetupSetGlobalFlags ppSetupSetGlobalFlags
  109. #define pSetupGetGlobalFlags ppSetupGetGlobalFlags
  110. typedef VOID ( * PPSETUPSETGLOBALFLAGS )( DWORD );
  111. typedef DWORD ( * PPSETUPGETGLOBALFLAGS )( VOID );
  112. PPSETUPSETGLOBALFLAGS ppSetupSetGlobalFlags;
  113. PPSETUPGETGLOBALFLAGS ppSetupGetGlobalFlags;
  114. int WINAPI WinMain(
  115. HINSTANCE hInstance,
  116. HINSTANCE hPrevInstance,
  117. LPTSTR lpszCmdLine,
  118. int nCmdShow
  119. )
  120. {
  121. HMODULE hdll = NULL;
  122. HRESULT hr = E_FAIL;
  123. TCHAR szCommand[_MAX_PATH*2]=_T(""); // Full path (including filename) of this exe
  124. int cchFileName; // Index into szCommand of the \ before the filename
  125. int cchNameOnly;
  126. TCHAR szInf2FullPath[_MAX_PATH*2]=_T(""); // Full path (including filename) of the
  127. // international inf, if one exists
  128. TCHAR szSrcDir[_MAX_PATH*2]=_T(""); // Directory where symbols.exe was launched
  129. TCHAR szInfDir[_MAX_PATH*2]=_T(""); // Directory to Launch the Inf from
  130. TCHAR szInstallCommand1[_MAX_PATH * 2]=_T(""); // Command sent to LaunchINFSection. If this
  131. // is a chained install, this is the
  132. // command sent to LaunchINFSection for the
  133. // first part of the chained install.
  134. TCHAR szInstallCommand2[_MAX_PATH * 2]=_T(""); // Command sent to LaunchINFSection for the
  135. // second part of the chained install
  136. TCHAR szDefaultInstall[_MAX_PATH*2] = _T("");
  137. TCHAR szDefaultInstallChained1[_MAX_PATH*2] = _T("");
  138. TCHAR szDefaultInstallChained2[_MAX_PATH*2] = _T("");
  139. DWORD rc;
  140. BOOL ThisIsNT4=FALSE; // Is this being installed on NT4?
  141. INT nAcceptLicense;
  142. WIN32_FIND_DATA FindFileData;
  143. OSVERSIONINFO VersionInfo;
  144. // Variables for handling command line flags
  145. // Get lpszCmndLine as an array instead of as a flat string. This means
  146. // we don't have to roll our own logic for handling long and/or quoted file
  147. // names- it gets done for us.
  148. // No such API as CommandLineToArgvA, so this work is always done in Unicode.
  149. INT iArgC;
  150. LPWSTR cmdLine = GetCommandLineW();
  151. LPWSTR * lpArgVW = CommandLineToArgvW(cmdLine, &iArgC);
  152. dwInstallOptions = CheckCommandLineOptions(iArgC, lpArgVW);
  153. if ( IS_FLAG_SET(dwInstallOptions, FLAG_USAGE) ) {
  154. // usage message is printed in CheckCommandLineOptions(), so just exit
  155. exit(0);
  156. }
  157. // don't allow FLAG_TOTALLY_QUIET unless doing an unattended install
  158. if ( IS_FLAG_SET(dwInstallOptions, FLAG_TOTALLY_QUIET) ) {
  159. if (! IS_FLAG_SET(dwInstallOptions, FLAG_UNATTENDED_INSTALL) ) {
  160. CLEAR_FLAG(dwInstallOptions, FLAG_TOTALLY_QUIET);
  161. MessageBox( NULL,
  162. "It is not possible to do a quiet install without doing an unattended\ninstall. Defaulting to a normal install.",
  163. "Microsoft Windows Symbols",
  164. 0 );
  165. }
  166. }
  167. // FLAG_FATAL_ERROR indicates that writing the registry key for FLAG_UNATTENDED_INSTALL failed
  168. if ( IS_FLAG_SET(dwInstallOptions,FLAG_UNATTENDED_INSTALL) &&
  169. IS_FLAG_SET(dwInstallOptions,FLAG_FATAL_ERROR) ) {
  170. // if FLAG_TOTALLY_QUIET, just exit
  171. if ( IS_FLAG_SET(dwInstallOptions, FLAG_TOTALLY_QUIET) ) {
  172. exit(1);
  173. } else {
  174. // otherwise, default to an anttended install
  175. CLEAR_FLAG(dwInstallOptions, FLAG_UNATTENDED_INSTALL);
  176. CLEAR_FLAG(dwInstallOptions, FLAG_FATAL_ERROR);
  177. MessageBox( NULL,
  178. "Microsoft Windows Symbols encountered an error doing the unattended\ninstall. Defaulting to a normal install.",
  179. "Microsoft Windows Symbols",
  180. 0 );
  181. }
  182. }
  183. VersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  184. GetVersionEx( &VersionInfo );
  185. //
  186. // Give a friendly pop-up message if this is Win9x or NT 3.51
  187. //
  188. if ( (VersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT ) ||
  189. (VersionInfo.dwMajorVersion < 4.0 ) ) {
  190. if (! IS_FLAG_SET(dwInstallOptions, FLAG_TOTALLY_QUIET) ) {
  191. MessageBox( NULL,
  192. "Microsoft Windows Symbols does not install on this Operating System.",
  193. "Microsoft Windows Symbols",
  194. 0 );
  195. }
  196. exit(0);
  197. }
  198. //
  199. // For NT 5 RC1 and greater, use pSetupSetGlobalFlags to keep old
  200. // symbol files from filling up people's hard drives with backed up symbols
  201. //
  202. // Not sure which build this was introduced in, but I know its broken if this
  203. // pSetupSetGlobalFlags procedure tries to load on NT4.
  204. //
  205. if (VersionInfo.dwBuildNumber >= 2072 ) {
  206. hdll = (HMODULE)LoadLibrary("setupapi.dll");
  207. if (hdll != NULL) {
  208. ppSetupSetGlobalFlags = ( PPSETUPSETGLOBALFLAGS )
  209. GetProcAddress(
  210. hdll,
  211. "pSetupSetGlobalFlags"
  212. );
  213. if (ppSetupSetGlobalFlags==NULL) {
  214. if (! IS_FLAG_SET(dwInstallOptions, FLAG_TOTALLY_QUIET) ) {
  215. MessageBox( NULL,
  216. "The install cannot finish because the function pSetupSetGlobalFlags is not in setupapi.dll",
  217. "Microsoft Windows 2000 Symbols",
  218. 0 );
  219. }
  220. exit(0);
  221. }
  222. ppSetupGetGlobalFlags = ( PPSETUPGETGLOBALFLAGS )
  223. GetProcAddress(
  224. hdll,
  225. "pSetupGetGlobalFlags"
  226. );
  227. if (ppSetupGetGlobalFlags==NULL) {
  228. if (! IS_FLAG_SET(dwInstallOptions, FLAG_TOTALLY_QUIET) ) {
  229. MessageBox( NULL,
  230. "The install cannot finish because the function pSetupGetGlobalFlags is not in setupapi.dll",
  231. "Microsoft Windows 2000 Symbols",
  232. 0 );
  233. }
  234. exit(0);
  235. }
  236. }
  237. //
  238. // Fix it so it doesn't try to keep old symbol files
  239. // and fill up people's hard drives with backed up symbols
  240. //
  241. pSetupSetGlobalFlags( pSetupGetGlobalFlags() | PSPGF_NO_BACKUP);
  242. }
  243. // Get this exe's full path name
  244. if (GetModuleFileName( NULL, szCommand, MAX_FILENAME ) == 0) {
  245. goto done;
  246. }
  247. // Get the index of the beginning of the filename by moving
  248. // backwards to the \ before the executable name.
  249. cchFileName = _tcslen( szCommand );
  250. while ( szCommand[cchFileName] != '\\' && cchFileName >= 0 ) {
  251. cchFileName--;
  252. }
  253. if ( cchFileName < 0 ) exit(1);
  254. // Create a string for the InfName
  255. StringCbCopy ( szInfName1, _MAX_PATH*2*sizeof(TCHAR), szCommand+cchFileName+1 );
  256. cchNameOnly = _tcslen( szInfName1 );
  257. while ( szInfName1[cchNameOnly] != '.' && cchNameOnly >= 0 ) {
  258. cchNameOnly--;
  259. }
  260. if ( cchNameOnly < 0 ) exit(1);
  261. szInfName1[cchNameOnly] = _T('\0');
  262. // Create a string containing the Default Install command
  263. StringCbCopy ( szDefaultInstall, _MAX_PATH*2*sizeof(TCHAR), szInfName1 );
  264. StringCbCat ( szDefaultInstall, _MAX_PATH*2*sizeof(TCHAR), _T(".inf, DefaultInstall") );
  265. if (IS_FLAG_SET(dwInstallOptions, FLAG_UNATTENDED_INSTALL)) {
  266. StringCbCat ( szDefaultInstall, _MAX_PATH*2*sizeof(TCHAR), _T(".Quiet") );
  267. }
  268. // Make this work for the way Windows 2000 SRP has the names
  269. // of the sections in their infs
  270. if ( (_tcscmp(szInfName1, _T("symbols_srp")) == 0) ||
  271. (_tcscmp(szInfName1, _T("symbols_sp")) == 0) ) {
  272. StringCbCat ( szDefaultInstall, _MAX_PATH*2*sizeof(TCHAR), _T(".x86") );
  273. }
  274. // Create a string for the DefaultInstall.Chained.1
  275. StringCbCopy ( szDefaultInstallChained1, _MAX_PATH*2*sizeof(TCHAR), szInfName1 );
  276. StringCbCat ( szDefaultInstallChained1, _MAX_PATH*2*sizeof(TCHAR), _T(".inf, DefaultInstall.Chained.1") );
  277. if (IS_FLAG_SET(dwInstallOptions, FLAG_UNATTENDED_INSTALL)) {
  278. StringCbCat ( szDefaultInstallChained1, _MAX_PATH*2*sizeof(TCHAR), _T(".Quiet") );
  279. }
  280. // Create a string for the DefaultInstall.Chained.2
  281. StringCbCopy ( szDefaultInstallChained2, _MAX_PATH*2*sizeof(TCHAR), szInfName2 );
  282. StringCbCat ( szDefaultInstallChained2, _MAX_PATH*2*sizeof(TCHAR), _T(".inf, DefaultInstall.Chained.2") );
  283. if (IS_FLAG_SET(dwInstallOptions, FLAG_UNATTENDED_INSTALL)) {
  284. StringCbCat ( szDefaultInstallChained2, _MAX_PATH*2*sizeof(TCHAR), _T(".Quiet") );
  285. }
  286. // Create a string containing the directory where the inf is
  287. StringCbCopy( szInfDir, _MAX_PATH*2*sizeof(TCHAR), szCommand);
  288. szInfDir[cchFileName+1] = _T('\0');
  289. // Create a string containing this install directory
  290. StringCbCopy ( szSrcDir, _MAX_PATH*2*sizeof(TCHAR), szCommand);
  291. szSrcDir[cchFileName+1] = _T('\0');
  292. StringCbCopy ( szEulaFullPath, _MAX_PATH*2*sizeof(TCHAR), szCommand);
  293. StringCbCopy ( &szEulaFullPath[cchFileName+1], _MAX_PATH*2*sizeof(TCHAR), szEulaFile);
  294. // Unattended install implies the EULA has already been agreed to
  295. if (! IS_FLAG_SET(dwInstallOptions, FLAG_UNATTENDED_INSTALL)) {
  296. DWORD dwSize = 0;
  297. LPTSTR szBuf;
  298. //
  299. // Make sure the EULA exists
  300. //
  301. dwSize = GetMyBuffer(&szBuf, szEulaFullPath);
  302. if (dwSize == 0) {
  303. if (! IS_FLAG_SET(dwInstallOptions, FLAG_TOTALLY_QUIET) ) {
  304. MessageBox( NULL,
  305. "The End User License Agreement could not be found.",
  306. "Windows Symbols",
  307. 0 );
  308. }
  309. exit(1);
  310. }
  311. free(&szBuf);
  312. // Display license agreement
  313. nAcceptLicense = (INT) DialogBox( hInstance,
  314. MAKEINTRESOURCE(IDD_LICENSE),
  315. NULL,
  316. DlgProcDisplayLicense
  317. );
  318. if ( nAcceptLicense != IDYES ) {
  319. MessageBox( NULL,
  320. "You need to accept the license agreement in order to install Windows Symbols.",
  321. "Windows Symbols",
  322. 0 );
  323. exit(1);
  324. }
  325. }
  326. //
  327. // Decide if this is a chained install or not.
  328. //
  329. StringCbCopy ( szInf2FullPath, _MAX_PATH*2*sizeof(TCHAR), szSrcDir);
  330. StringCbCat ( szInf2FullPath, _MAX_PATH*2*sizeof(TCHAR), szInfName2);
  331. StringCbCat ( szInf2FullPath, _MAX_PATH*2*sizeof(TCHAR), _T(".inf") );
  332. ChainedInstall=TRUE;
  333. if ( _tcscmp( szInfName1, szInfName2 ) == 0 ) {
  334. ChainedInstall=FALSE;
  335. } else if (FindFirstFile( szInf2FullPath, &FindFileData) == INVALID_HANDLE_VALUE) {
  336. ChainedInstall=FALSE;
  337. }
  338. //
  339. // If this is NT4, do a work around for a bug in setupapi
  340. // Setupapi can't get the name of the cab correctly unless it is in
  341. // the root of the CD.
  342. // Workaround is to copy the files to a temp directory.
  343. // If this is NT4 and the setup isn't being run from a CD-ROM, we don't have to
  344. // copy the files to a temp directory.
  345. if ( (GetDriveType(NULL) == DRIVE_CDROM) &&
  346. (VersionInfo.dwMajorVersion < 5.0 ) ) {
  347. ThisIsNT4 = TRUE;
  348. if (! IS_FLAG_SET(dwInstallOptions, FLAG_UNATTENDED_INSTALL)) {
  349. MessageBox( NULL,
  350. "The installer needs to copy some files to a temporary directory. This may take several minutes.",
  351. "Windows Symbols",
  352. 0 );
  353. }
  354. rc = CopyFilesToTempDir(szSrcDir,szInfDir);
  355. if (!rc) {
  356. if (! IS_FLAG_SET(dwInstallOptions, FLAG_TOTALLY_QUIET) ) {
  357. MessageBox( NULL,
  358. "Setup failed to copy all the files to a temporary directory",
  359. "Windows Symbols",
  360. 0 );
  361. }
  362. DeleteFilesAndTempDir(szInfDir);
  363. exit(1);
  364. }
  365. }
  366. //
  367. // See if the second inf exists in this directory. If it does then
  368. // call the chained installs. Otherwise call the section that only
  369. // installs the US file.
  370. //
  371. StringCbCopy ( szInf2FullPath, _MAX_PATH*2*sizeof(TCHAR), szInfDir);
  372. StringCbCat ( szInf2FullPath, _MAX_PATH*2*sizeof(TCHAR), szInfName2);
  373. StringCbCat ( szInf2FullPath, _MAX_PATH*2*sizeof(TCHAR), _T(".inf") );
  374. if (FindFirstFile( szInf2FullPath, &FindFileData) == INVALID_HANDLE_VALUE) {
  375. StringCbCopy( szInstallCommand1, _MAX_PATH*2*sizeof(TCHAR), szInfDir );
  376. StringCbCat( szInstallCommand1, _MAX_PATH*2*sizeof(TCHAR), szDefaultInstall );
  377. } else {
  378. StringCbCopy( szInstallCommand1, _MAX_PATH*2*sizeof(TCHAR), szInfDir );
  379. StringCbCat( szInstallCommand1, _MAX_PATH*2*sizeof(TCHAR), szDefaultInstallChained1 );
  380. StringCbCopy( szInstallCommand2, _MAX_PATH*2*sizeof(TCHAR), szInfDir );
  381. StringCbCat( szInstallCommand2, _MAX_PATH*2*sizeof(TCHAR), szDefaultInstallChained2 );
  382. }
  383. /* tell AdvPack to process this INF */
  384. DeleteSymbolInstallKey();
  385. hr = LaunchINFSection( NULL, hInstance, szInstallCommand1, 0 );
  386. if ( ChainedInstall && SymbolInstallKeyExists() ) {
  387. hr = LaunchINFSection( NULL, hInstance, szInstallCommand2, 0 );
  388. }
  389. if ( ThisIsNT4) {
  390. DeleteFilesAndTempDir( szInfDir );
  391. }
  392. done:
  393. return( (int) hr );
  394. }
  395. INT_PTR
  396. CALLBACK
  397. DlgProcDisplayLicense(
  398. HWND hwndDlg,
  399. UINT uMsg,
  400. WPARAM wParam,
  401. LPARAM lParam
  402. )
  403. {
  404. //
  405. // This is the callback procedure for displaying the
  406. // license agreement.
  407. //
  408. DWORD dwSize;
  409. LPTSTR szBuf;
  410. HWND hwndCtrl;
  411. // Get the license agreement text and store it in szBuf
  412. dwSize = GetMyBuffer(&szBuf, szEulaFullPath);
  413. if (dwSize == 0) {
  414. return FALSE;
  415. }
  416. switch (uMsg) {
  417. case WM_INITDIALOG:
  418. CenterWindow( hwndDlg, GetDesktopWindow() );
  419. SetDlgItemText( hwndDlg, IDC_EDIT_LICENSE, szBuf );
  420. hwndCtrl = GetDlgItem(hwndDlg, IDC_EDIT_LICENSE);
  421. PostMessage(hwndCtrl, EM_SETSEL, -1, -1);
  422. return TRUE;
  423. case WM_CLOSE:
  424. EndDialog( hwndDlg, IDNO );
  425. return TRUE;
  426. case WM_COMMAND:
  427. switch ( LOWORD (wParam) )
  428. {
  429. case IDYES: EndDialog( hwndDlg, IDYES );
  430. return (TRUE);
  431. case IDNO: EndDialog( hwndDlg, IDNO );
  432. return (TRUE);
  433. }
  434. break;
  435. }
  436. return FALSE;
  437. }
  438. BOOL CenterWindow( HWND hwndChild, HWND hwndParent )
  439. {
  440. RECT rChild;
  441. RECT rParent;
  442. int wChild;
  443. int hChild;
  444. int wParent;
  445. int hParent;
  446. int wScreen;
  447. int hScreen;
  448. int xNew;
  449. int yNew;
  450. HDC hdc;
  451. //
  452. // This is a procedure I got from the wextract.c code -- it centers the
  453. // window.
  454. //
  455. // Returns: BOOL
  456. // True if successful,
  457. // False otherwise
  458. //
  459. // Get the Height and Width of the child window
  460. GetWindowRect (hwndChild, &rChild);
  461. wChild = rChild.right - rChild.left;
  462. hChild = rChild.bottom - rChild.top;
  463. // Get the Height and Width of the parent window
  464. GetWindowRect (hwndParent, &rParent);
  465. wParent = rParent.right - rParent.left;
  466. hParent = rParent.bottom - rParent.top;
  467. // Get the display limits
  468. hdc = GetDC (hwndChild);
  469. if (hdc == NULL) {
  470. return FALSE;
  471. }
  472. wScreen = GetDeviceCaps (hdc, HORZRES);
  473. hScreen = GetDeviceCaps (hdc, VERTRES);
  474. ReleaseDC (hwndChild, hdc);
  475. // Calculate new X position, then adjust for screen
  476. xNew = rParent.left + ((wParent - wChild) /2);
  477. if (xNew < 0) {
  478. xNew = 0;
  479. } else if ((xNew+wChild) > wScreen) {
  480. xNew = wScreen - wChild;
  481. }
  482. // Calculate new Y position, then adjust for screen
  483. yNew = rParent.top + ((hParent - hChild) /2);
  484. if (yNew < 0) {
  485. yNew = 0;
  486. } else if ((yNew+hChild) > hScreen) {
  487. yNew = hScreen - hChild;
  488. }
  489. // Set it, and return
  490. return( SetWindowPos(hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER));
  491. }
  492. DWORD
  493. GetMyBuffer(
  494. LPTSTR* pszBuf,
  495. LPTSTR szFileName
  496. )
  497. {
  498. //
  499. // Reads contents of szFileName into a buffer.
  500. //
  501. // OUT pszBuf
  502. // IN szFileName
  503. //
  504. // Return Value: size of the buffer
  505. //
  506. HANDLE hFile;
  507. DWORD dwSize;
  508. DWORD NumBytesRead;
  509. hFile = CreateFile( (LPCTSTR) szFileName,
  510. GENERIC_READ,
  511. FILE_SHARE_READ,
  512. NULL,
  513. OPEN_EXISTING,
  514. FILE_ATTRIBUTE_NORMAL,
  515. NULL
  516. );
  517. // handle a missing EULA
  518. if (hFile == INVALID_HANDLE_VALUE ) {
  519. return(0);
  520. }
  521. dwSize = GetFileSize( hFile, NULL );
  522. *pszBuf = (LPTSTR)malloc( dwSize * sizeof(TCHAR) );
  523. if ( *pszBuf == NULL ) {
  524. return(0);
  525. }
  526. if (!ReadFile( hFile,
  527. (LPVOID)*pszBuf,
  528. dwSize,
  529. &NumBytesRead,
  530. NULL )
  531. ) {
  532. free(*pszBuf);
  533. return(0);
  534. }
  535. return (dwSize);
  536. }
  537. BOOL
  538. CopyFilesToTempDir(
  539. LPTSTR szSrcDir,
  540. LPTSTR szInfDir
  541. )
  542. {
  543. /* szSrcDir - IN - Directory that symbols.exe was launched from
  544. szInfDir - OUT - Directory that INF is copied to
  545. Purpose: Copy files to a temporary directory
  546. */
  547. BOOL rc;
  548. HINF hInf;
  549. PVOID Context;
  550. TCHAR szInfFile[_MAX_PATH * 2];
  551. TCHAR buf[_MAX_PATH * 2];
  552. GetTempDirName(szInfDir);
  553. // Create the Temporary Install Directory
  554. rc = MyMakeSureDirectoryPathExists( szInfDir );
  555. if (!rc) {
  556. StringCbPrintf( buf,
  557. _MAX_PATH*2*sizeof(TCHAR),
  558. "Installation failed because it can't create the temporary directory %s.", szInfDir );
  559. if (! IS_FLAG_SET(dwInstallOptions, FLAG_TOTALLY_QUIET) ) {
  560. MessageBox( NULL,
  561. buf,
  562. "Microsoft Windows 2000 Symbols",
  563. 0 );
  564. }
  565. return FALSE;
  566. }
  567. // Copy the 3 files associated with szInfName1
  568. StringCbCopy(buf, _MAX_PATH*2*sizeof(TCHAR), szInfName1 );
  569. StringCbCat(buf, _MAX_PATH*2*sizeof(TCHAR), _T(".cab") );
  570. rc = CopySomeFiles(szSrcDir, szInfDir, buf );
  571. if (!rc) return FALSE;
  572. StringCbCopy(buf, _MAX_PATH*2*sizeof(TCHAR), szInfName1 );
  573. StringCbCat(buf, _MAX_PATH*2*sizeof(TCHAR), _T(".cat") );
  574. rc = CopySomeFiles(szSrcDir, szInfDir, buf );
  575. if (!rc) return FALSE;
  576. StringCbCopy(buf, _MAX_PATH*2*sizeof(TCHAR), szInfName1 );
  577. StringCbCat(buf, _MAX_PATH*2*sizeof(TCHAR), _T(".inf") );
  578. rc = CopySomeFiles(szSrcDir, szInfDir, buf );
  579. if (!rc) return FALSE;
  580. // If this is a chained install, copy the 3 files associated
  581. // with szInfName2
  582. if (ChainedInstall) {
  583. StringCbCopy(buf, _MAX_PATH*2*sizeof(TCHAR), szInfName2 );
  584. StringCbCat(buf, _MAX_PATH*2*sizeof(TCHAR), _T(".cab") );
  585. rc = CopySomeFiles(szSrcDir, szInfDir, buf );
  586. if (!rc) return FALSE;
  587. StringCbCopy(buf, _MAX_PATH*2*sizeof(TCHAR), szInfName2 );
  588. StringCbCat(buf, _MAX_PATH*2*sizeof(TCHAR), _T(".cat") );
  589. rc = CopySomeFiles(szSrcDir, szInfDir, buf );
  590. if (!rc) return FALSE;
  591. StringCbCopy(buf, _MAX_PATH*2*sizeof(TCHAR), szInfName2 );
  592. StringCbCat(buf, _MAX_PATH*2*sizeof(TCHAR), _T(".inf") );
  593. rc = CopySomeFiles(szSrcDir, szInfDir, buf );
  594. if (!rc) return FALSE;
  595. }
  596. // Copy the other two files that are needed for the install
  597. // onto NT4
  598. rc = CopySomeFiles(szSrcDir, szInfDir, _T("eula.txt") );
  599. if (!rc) return FALSE;
  600. rc = CopySomeFiles(szSrcDir, szInfDir, _T("advpack.dll") );
  601. if (!rc) return FALSE;
  602. return (TRUE);
  603. }
  604. BOOL
  605. DeleteFilesAndTempDir(
  606. LPTSTR szTempDir
  607. )
  608. {
  609. /*
  610. szTempDir -IN - Directory to delete
  611. Purpose: Delete the files in the temporary directory.
  612. */
  613. BOOL rc;
  614. DeleteAllFilesInDirectory(szTempDir);
  615. rc = RemoveDirectory(szTempDir);
  616. RemoveDirectory(szTempDir);
  617. return (TRUE);
  618. }
  619. BOOL
  620. GetTempDirName(
  621. LPTSTR szTempDir
  622. )
  623. {
  624. DWORD dwPathLength;
  625. BOOL rc, Finished;
  626. UINT Num;
  627. TCHAR szNum[20];
  628. DWORD Length;
  629. HINF hInf;
  630. PVOID Context;
  631. LPSECURITY_ATTRIBUTES lpSecurityAttributes;
  632. TCHAR szInfDir[_MAX_PATH];
  633. TCHAR buf[_MAX_PATH * 2];
  634. HANDLE hFile;
  635. dwPathLength = GetTempPath( _MAX_PATH, szTempDir);
  636. if ( dwPathLength == 0 ) return FALSE;
  637. if ( dwPathLength > _MAX_PATH) return FALSE;
  638. // Append the symbol install temp dir
  639. StringCbCat(szTempDir, _MAX_PATH*2*sizeof(TCHAR), _T("sym") );
  640. Finished = FALSE;
  641. Length = _tcslen(szTempDir);
  642. Num = 0;
  643. while ( !Finished) {
  644. Num++;
  645. _itoa( Num, szNum, 10 );
  646. StringCbCopy( szTempDir+Length, (_MAX_PATH*2 - Length) * sizeof(TCHAR), szNum );
  647. StringCbCat( szTempDir, _MAX_PATH*2*sizeof(TCHAR), _T("\\") );
  648. hFile = CreateFile( szTempDir,
  649. GENERIC_READ,
  650. FILE_SHARE_READ,
  651. NULL,
  652. OPEN_EXISTING,
  653. FILE_FLAG_BACKUP_SEMANTICS,
  654. NULL );
  655. if ( hFile == INVALID_HANDLE_VALUE ) {
  656. Finished = TRUE;
  657. }
  658. }
  659. // Create the Temporary Install Directory
  660. rc = MyMakeSureDirectoryPathExists( szTempDir );
  661. if (!rc) {
  662. StringCbPrintf( buf,
  663. _MAX_PATH*2*sizeof(TCHAR),
  664. "Installation failed because it can't create the temporary directory %s.", szTempDir );
  665. if (! IS_FLAG_SET(dwInstallOptions, FLAG_TOTALLY_QUIET) ) {
  666. MessageBox( NULL,
  667. buf,
  668. "Microsoft Windows 2000 Symbols",
  669. 0 );
  670. }
  671. return FALSE;
  672. }
  673. return TRUE;
  674. }
  675. BOOL
  676. MyMakeSureDirectoryPathExists(
  677. LPCSTR DirPath
  678. )
  679. {
  680. LPTSTR p, DirCopy;
  681. DWORD dw;
  682. // Make a copy of the string for editing.
  683. __try {
  684. DirCopy = (LPTSTR) malloc(_tcslen(DirPath) + 1);
  685. if (!DirCopy) {
  686. return FALSE;
  687. }
  688. StringCbCopy( DirCopy,
  689. (_tcslen(DirPath) + 1) * sizeof(TCHAR),
  690. DirPath );
  691. p = DirCopy;
  692. // If the second character in the path is "\", then this is a UNC
  693. // path, and we should skip forward until we reach the 2nd \ in the path.
  694. if ((*p == '\\') && (*(p+1) == '\\')) {
  695. p++; // Skip over the first \ in the name.
  696. p++; // Skip over the second \ in the name.
  697. // Skip until we hit the first "\" (\\Server\).
  698. while (*p && *p != '\\') {
  699. p = CharNext(p);
  700. }
  701. // Advance over it.
  702. if (*p) {
  703. p++;
  704. }
  705. // Skip until we hit the second "\" (\\Server\Share\).
  706. while (*p && *p != '\\') {
  707. p = CharNext(p);
  708. }
  709. // Advance over it also.
  710. if (*p) {
  711. p++;
  712. }
  713. } else
  714. // Not a UNC. See if it's <drive>:
  715. if (*(p+1) == ':' ) {
  716. p++;
  717. p++;
  718. // If it exists, skip over the root specifier
  719. if (*p && (*p == '\\')) {
  720. p++;
  721. }
  722. }
  723. while( *p ) {
  724. if ( *p == '\\' ) {
  725. *p = '\0';
  726. dw = GetFileAttributes(DirCopy);
  727. // Nothing exists with this name. Try to make the directory name
  728. // and error if unable to.
  729. if ( dw == 0xffffffff ) {
  730. if ( !CreateDirectory(DirCopy,NULL) ) {
  731. if( GetLastError() != ERROR_ALREADY_EXISTS ) {
  732. free(DirCopy);
  733. return FALSE;
  734. }
  735. }
  736. } else {
  737. if ( (dw & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ) {
  738. // Something exists with this name,
  739. // but it's not a directory... Error
  740. free(DirCopy);
  741. return FALSE;
  742. }
  743. }
  744. *p = '\\';
  745. }
  746. p = CharNext(p);
  747. }
  748. } __except (EXCEPTION_EXECUTE_HANDLER) {
  749. // ImagepSetLastErrorFromStatus( GetExceptionCode() );
  750. free(DirCopy);
  751. return(FALSE);
  752. }
  753. free(DirCopy);
  754. return TRUE;
  755. }
  756. BOOL
  757. CopySomeFiles(
  758. LPTSTR szSrcDir,
  759. LPTSTR szDestDir,
  760. LPTSTR szFileName
  761. )
  762. {
  763. TCHAR szSearchFileName[_MAX_PATH * 2];
  764. TCHAR szDestFileName[_MAX_PATH * 2];
  765. TCHAR szFoundFileName[_MAX_PATH * 2];
  766. TCHAR szBuf[_MAX_PATH * 3];
  767. WIN32_FIND_DATA Win32FindData;
  768. HANDLE hFindFile;
  769. BOOL Found;
  770. BOOL rc;
  771. // Copy the catalog files
  772. StringCbCopy(szSearchFileName, _MAX_PATH*2*sizeof(TCHAR), szSrcDir);
  773. StringCbCat(szSearchFileName, _MAX_PATH*2*sizeof(TCHAR), szFileName );
  774. Found = TRUE;
  775. hFindFile = FindFirstFile((LPCTSTR)szSearchFileName, &Win32FindData);
  776. if ( hFindFile == INVALID_HANDLE_VALUE) {
  777. return(FALSE);
  778. }
  779. while ( Found ) {
  780. StringCbCopy(szFoundFileName, _MAX_PATH*2*sizeof(TCHAR), szSrcDir);
  781. StringCbCat(szFoundFileName, _MAX_PATH*2*sizeof(TCHAR), Win32FindData.cFileName);
  782. StringCbCopy(szDestFileName, _MAX_PATH*2*sizeof(TCHAR), szDestDir);
  783. StringCbCat(szDestFileName, _MAX_PATH*2*sizeof(TCHAR), Win32FindData.cFileName);
  784. rc = CopyFile(szFoundFileName, szDestFileName, FALSE);
  785. if (!rc) {
  786. if ( GetLastError() == ERROR_HANDLE_DISK_FULL ) {
  787. StringCbPrintf( szBuf,
  788. _MAX_PATH*2*sizeof(TCHAR),
  789. _T("There is not enough disk space in the temporary directory %s %s"),
  790. szDestDir,
  791. _T("to complete the install.") );
  792. if (! IS_FLAG_SET(dwInstallOptions, FLAG_TOTALLY_QUIET) ) {
  793. MessageBox( NULL,
  794. szBuf,
  795. "Microsoft Windows 2000 Symbols",
  796. 0 );
  797. }
  798. }
  799. RemoveDirectory(szDestDir);
  800. return (FALSE);
  801. }
  802. Found = FindNextFile( hFindFile, &Win32FindData );
  803. }
  804. return (TRUE);
  805. }
  806. BOOL
  807. DeleteAllFilesInDirectory(
  808. LPTSTR szDir
  809. )
  810. {
  811. HANDLE hFindFile;
  812. BOOL Found = FALSE;
  813. BOOL rc = TRUE;
  814. LPTSTR szBuf;
  815. LPTSTR szDir2;
  816. LPWIN32_FIND_DATA lpFindFileData;
  817. szDir2 = (LPTSTR)malloc( (_tcslen(szDir) + 4) * sizeof(TCHAR) );
  818. if (szDir2 == NULL) return (FALSE);
  819. StringCbCopy( szDir2, (_tcslen(szDir) + 4) * sizeof(TCHAR), szDir);
  820. StringCbCat( szDir2, (_tcslen(szDir) + 4) * sizeof(TCHAR), _T("*.*") );
  821. szBuf = (LPTSTR)malloc( ( _tcslen(szDir) + _MAX_FNAME + _MAX_EXT + 2 )
  822. * sizeof(TCHAR) );
  823. if (szBuf == NULL) return(FALSE);
  824. lpFindFileData = (LPWIN32_FIND_DATA) malloc (sizeof(WIN32_FIND_DATA) );
  825. if (!lpFindFileData) return(FALSE);
  826. Found = TRUE;
  827. hFindFile = FindFirstFile((LPCTSTR)szDir2, lpFindFileData);
  828. if ( hFindFile == INVALID_HANDLE_VALUE) {
  829. Found = FALSE;
  830. }
  831. while ( Found ) {
  832. if ( !(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  833. StringCbPrintf( szBuf, (_tcslen(szDir) + _MAX_FNAME + _MAX_EXT + 2) * sizeof(TCHAR),
  834. _T("%s%s"),
  835. szDir,
  836. lpFindFileData->cFileName);
  837. if (!DeleteFile(szBuf)) {
  838. rc = FALSE;
  839. }
  840. }
  841. Found = FindNextFile(hFindFile, lpFindFileData);
  842. }
  843. free(lpFindFileData);
  844. FindClose(hFindFile);
  845. free(szDir2);
  846. free(szBuf);
  847. return(rc);
  848. }
  849. BOOL DeleteSymbolInstallKey()
  850. {
  851. DWORD rc;
  852. LONG rc2;
  853. HKEY hKeySymbols;
  854. rc = RegOpenKeyEx( HKEY_CURRENT_USER,
  855. _T("software\\microsoft\\Symbols"),
  856. 0,
  857. KEY_QUERY_VALUE | KEY_SET_VALUE |
  858. KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
  859. &hKeySymbols
  860. );
  861. if (rc == ERROR_SUCCESS) {
  862. rc2 = RegDeleteKey( hKeySymbols,
  863. _T("SymbolInstall")
  864. );
  865. }
  866. if (rc) {
  867. RegCloseKey(hKeySymbols);
  868. }
  869. return (TRUE);
  870. }
  871. BOOL SymbolInstallKeyExists ()
  872. {
  873. DWORD rc;
  874. LONG rc2;
  875. HKEY hKeySymbols;
  876. rc = RegOpenKeyEx( HKEY_CURRENT_USER,
  877. _T("software\\microsoft\\Symbols\\SymbolInstall"),
  878. 0,
  879. KEY_QUERY_VALUE | KEY_SET_VALUE |
  880. KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
  881. &hKeySymbols
  882. );
  883. if (rc == ERROR_SUCCESS) {
  884. RegCloseKey(hKeySymbols);
  885. return(TRUE);
  886. } else {
  887. return (FALSE);
  888. }
  889. }