Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

711 lines
15 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. books.c
  5. Abstract:
  6. Main module for on-line reference books installation/invocation.
  7. Author:
  8. Ted Miller (tedm) 5-Jan-1995
  9. Revision History:
  10. --*/
  11. #include "books.h"
  12. #include <setupapi.h>
  13. #include <stdlib.h>
  14. WCHAR TagFile[MAX_PATH];
  15. WCHAR CdRomName[250];
  16. //
  17. // Module handle
  18. //
  19. HANDLE hInst;
  20. //
  21. // Handle of main icon.
  22. //
  23. HICON MainIcon;
  24. //
  25. // Command line parameters
  26. //
  27. ForceProduct CmdLineForce = ForceNone;
  28. BOOL CmdLineForcePrompt = FALSE;
  29. typedef struct _PROMPTDIALOGPARAMS {
  30. PWSTR MainMessage;
  31. PWSTR InitialLocation;
  32. PWSTR FinalLocation;
  33. } PROMPTDIALOGPARAMS, *PPROMPTDIALOGPARAMS;
  34. INT_PTR
  35. CALLBACK
  36. DlgProcPrompt(
  37. IN HWND hdlg,
  38. IN UINT msg,
  39. IN WPARAM wParam,
  40. IN LPARAM lParam
  41. );
  42. VOID
  43. FixupNames(
  44. VOID
  45. );
  46. VOID
  47. DoBooks(
  48. IN WCHAR CdRomDrive,
  49. IN PWSTR PreviousLocation
  50. );
  51. BOOL
  52. ParseArgs(
  53. IN int argc,
  54. IN char *argv[]
  55. );
  56. VOID
  57. Usage(
  58. VOID
  59. );
  60. int
  61. __cdecl
  62. main(
  63. IN int argc,
  64. IN char *argv[]
  65. )
  66. {
  67. PWSTR BooksLocation;
  68. WCHAR CdRomDrive;
  69. WCHAR Path[MAX_PATH];
  70. hInst = GetModuleHandle(NULL);
  71. MainIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_MAIN));
  72. if(!ParseArgs(argc,argv)) {
  73. Usage();
  74. }
  75. FixupNames();
  76. //
  77. // Get BooksLocation profile value.
  78. //
  79. BooksLocation = MyGetProfileValue(BooksProfileLocation,L"");
  80. if (!BooksLocation[0] && !CmdLineForcePrompt) {
  81. //
  82. // Look for the Help file in its normal location and make
  83. // sure it's present. If it is, set BooksLocation.
  84. //
  85. WCHAR pwcsHelpPath[_MAX_PATH];
  86. if (GetWindowsDirectory(pwcsHelpPath, _MAX_PATH)) {
  87. lstrcat(pwcsHelpPath, L"\\Help");
  88. if (DoesFileExist(pwcsHelpPath))
  89. BooksLocation = DupString(pwcsHelpPath);
  90. }
  91. }
  92. if(BooksLocation[0] && !CmdLineForcePrompt) {
  93. //
  94. // BooksLocation has been set previously. This is no guarantee that
  95. // the location is currently accessible. Check to see if the help file
  96. // is available. If not we will prompt the user.
  97. //
  98. if(CheckHelpfilePresent(BooksLocation)) {
  99. //
  100. // The help file is accessible. Fire up winhelp.
  101. //
  102. FireUpWinhelp(0,BooksLocation);
  103. } else {
  104. //
  105. // The help file is not currently accessible.
  106. //
  107. DoBooks(LocateCdRomDrive(),BooksLocation);
  108. }
  109. } else {
  110. //
  111. // Books location was not specified already.
  112. // In this case look for a cd-rom drive.
  113. //
  114. if(CdRomDrive = LocateCdRomDrive()) {
  115. //
  116. // Form the path of the helpfile on the CD
  117. //
  118. Path[0] = CdRomDrive;
  119. Path[1] = L':';
  120. Path[2] = 0;
  121. lstrcat(Path,PathOfBooksFilesOnCd);
  122. //
  123. // Found a cd-rom drive. Look for the relevent nt cd in there
  124. // and make sure the help file is there too just for good measure.
  125. //
  126. if(!CmdLineForcePrompt
  127. && IsCdRomInDrive(CdRomDrive,TagFile)
  128. && CheckHelpfilePresent(Path))
  129. {
  130. //
  131. // The nt cd-rom is in there. Fire up winhelp.
  132. //
  133. FireUpWinhelp(CdRomDrive,PathOfBooksFilesOnCd);
  134. } else {
  135. //
  136. // Prompt for the nt cd-rom, or an alternate location.
  137. //
  138. DoBooks(CdRomDrive,NULL);
  139. }
  140. } else {
  141. //
  142. // No cd-rom drive; prompt for an alternate location.
  143. //
  144. DoBooks(0,NULL);
  145. }
  146. }
  147. return 0;
  148. }
  149. VOID
  150. Usage(
  151. VOID
  152. )
  153. {
  154. MyError(NULL,IDS_USAGE,TRUE);
  155. }
  156. BOOL
  157. ParseArgs(
  158. IN int argc,
  159. IN char *argv[]
  160. )
  161. {
  162. int i;
  163. for(argc--,i=1; argc; argc--,i++) {
  164. if((argv[i][0] == '-') || (argv[i][0] == '/')) {
  165. switch(argv[i][1]) {
  166. case 's':
  167. case 'S':
  168. //
  169. // accept /s or /server
  170. //
  171. if(!argv[i][2]) {
  172. CmdLineForce = ForceServer;
  173. } else {
  174. if(lstrcmpiA(argv[i]+1,"server")) {
  175. return(FALSE);
  176. }
  177. CmdLineForce = ForceServer;
  178. }
  179. break;
  180. case 'w':
  181. case 'W':
  182. //
  183. // accept /w or /workstation
  184. //
  185. if(!argv[i][2]) {
  186. CmdLineForce = ForceWorkstation;
  187. } else {
  188. if(lstrcmpiA(argv[i]+1,"workstation")) {
  189. return(FALSE);
  190. }
  191. CmdLineForce = ForceWorkstation;
  192. }
  193. break;
  194. case 'n':
  195. case 'N':
  196. //
  197. // Ignore remembered location (ie, *N*ew location)
  198. //
  199. if(argv[i][2]) {
  200. return(FALSE);
  201. } else {
  202. CmdLineForcePrompt = TRUE;
  203. }
  204. break;
  205. default:
  206. return(FALSE);
  207. }
  208. } else {
  209. //
  210. // All args are switches
  211. //
  212. return(FALSE);
  213. }
  214. }
  215. return(TRUE);
  216. }
  217. VOID
  218. DoBooks(
  219. IN WCHAR CdRomDrive,
  220. IN PWSTR PreviousLocation
  221. )
  222. {
  223. DWORD Id;
  224. INT_PTR DialogReturn;
  225. WCHAR CurrentDirectory[MAX_PATH];
  226. // UINT DriveType;
  227. PROMPTDIALOGPARAMS Params;
  228. //
  229. // The dialog looks slightly different depending on
  230. // whether there is a CD-ROM drive in the system.
  231. //
  232. // If there is we say something like "insert the cdrom in
  233. // the drive or give an alternate location." If there is not
  234. // we say something like "tell us where the files are."
  235. //
  236. //retry:
  237. if(PreviousLocation) {
  238. Id = CdRomDrive ? MSG_PROMPT_CD : MSG_PROMPT_NO_CD;
  239. Params.InitialLocation = PreviousLocation;
  240. } else {
  241. Id = CdRomDrive ? MSG_PROMPT_CD_FIRST : MSG_PROMPT_NO_CD_FIRST;
  242. if(CdRomDrive) {
  243. wsprintf(CurrentDirectory,L"%c:%s",CdRomDrive,PathOfBooksFilesOnCd);
  244. } else {
  245. GetCurrentDirectory(
  246. sizeof(CurrentDirectory)/sizeof(CurrentDirectory[0]),
  247. CurrentDirectory
  248. );
  249. }
  250. Params.InitialLocation = CurrentDirectory;
  251. }
  252. Params.MainMessage = RetreiveMessage(Id,PreviousLocation,CdRomName);
  253. DialogReturn = DialogBoxParam(
  254. hInst,
  255. MAKEINTRESOURCE(DLG_PROMPT),
  256. NULL,
  257. DlgProcPrompt,
  258. (LPARAM)&Params
  259. );
  260. MyFree(Params.MainMessage);
  261. if(DialogReturn) {
  262. //
  263. // Removed the copy stuff for now, as it's not done yet
  264. // and not likely to be completed any time soon.
  265. //
  266. #if 0
  267. //
  268. // If the path is a UNC path this should be 0 (drive type unknown)
  269. // so the test below will work just fine
  270. //
  271. DriveType = MyGetDriveType(Params.FinalLocation[0]);
  272. //
  273. // If there is no previous location and the files are
  274. // not on a local hard drive offer to install them on
  275. // the hard drive.
  276. //
  277. // Treat removable drives like hard drives, because it's unlikely
  278. // the files are on a floppy and removable hard drives come back as
  279. // DRIVE_REMOVABLE, not DRIVE_FIXED.
  280. //
  281. if(!PreviousLocation && (DriveType != DRIVE_FIXED) && (DriveType != DRIVE_REMOVABLE)) {
  282. if(!DoInstall(&Params.FinalLocation)) {
  283. MyFree(Params.FinalLocation);
  284. PreviousLocation = NULL;
  285. goto retry;
  286. }
  287. }
  288. #endif
  289. FireUpWinhelp(0,Params.FinalLocation);
  290. }
  291. }
  292. VOID
  293. FixupNames(
  294. VOID
  295. )
  296. {
  297. HKEY hKey;
  298. LONG l;
  299. DWORD DataType;
  300. WCHAR Data[128];
  301. DWORD DataSize;
  302. BOOL IsServer;
  303. BOOL b;
  304. UINT SourceId;
  305. HINF Inf;
  306. //
  307. // Figure out if this is a server or workstation and fix up
  308. // the global cd-rom name and tagfile variables accordingly.
  309. //
  310. // Open HKLM\System\CCS\Control\ProductOptions and check ProductType value.
  311. // If it's 'winnt' then this is a workststion. Otherwise assume server.
  312. //
  313. switch(CmdLineForce) {
  314. case ForceServer:
  315. IsServer = TRUE;
  316. break;
  317. case ForceWorkstation:
  318. IsServer = FALSE;
  319. break;
  320. case ForceNone:
  321. default:
  322. IsServer= FALSE;
  323. l = RegOpenKeyEx(
  324. HKEY_LOCAL_MACHINE,
  325. L"System\\CurrentControlSet\\Control\\ProductOptions",
  326. 0,
  327. KEY_READ,
  328. &hKey
  329. );
  330. if(l == NO_ERROR) {
  331. DataSize = sizeof(Data)/sizeof(Data[0]);
  332. l = RegQueryValueEx(
  333. hKey,
  334. L"ProductType",
  335. 0,
  336. &DataType,
  337. (LPBYTE)Data,
  338. &DataSize
  339. );
  340. RegCloseKey(hKey);
  341. if((l == NO_ERROR) && (DataType == REG_SZ) && lstrcmpi(Data,L"winnt")) {
  342. IsServer = TRUE;
  343. }
  344. }
  345. break;
  346. }
  347. if(IsServer) {
  348. HelpFileName = L"WINDOWS.CHM";
  349. BooksProfileLocation = L"ServerBooksLocation";
  350. } else {
  351. HelpFileName = L"WINDOWS.CHM";
  352. BooksProfileLocation = L"WorkstationBooksLocation";
  353. }
  354. //
  355. // Get information about the NT CD-ROM. We assume that the books files
  356. // are on the same CD as the basic system, which also must have
  357. // ntoskrnl.exe on it.
  358. //
  359. b = FALSE;
  360. Inf = SetupOpenMasterInf();
  361. if(Inf != INVALID_HANDLE_VALUE) {
  362. if(SetupGetSourceFileLocation(Inf,NULL,L"NTOSKRNL.EXE",&SourceId,NULL,0,NULL)) {
  363. b = SetupGetSourceInfo(
  364. Inf,
  365. SourceId,
  366. SRCINFO_TAGFILE,
  367. TagFile,
  368. sizeof(TagFile)/sizeof(WCHAR),
  369. NULL
  370. );
  371. if(b) {
  372. b = SetupGetSourceInfo(
  373. Inf,
  374. SourceId,
  375. SRCINFO_DESCRIPTION,
  376. CdRomName,
  377. sizeof(CdRomName)/sizeof(WCHAR),
  378. NULL
  379. );
  380. }
  381. }
  382. SetupCloseInfFile(Inf);
  383. }
  384. if(!b) {
  385. MyError(NULL,IDS_LAYOUT_INF_DAMAGED,TRUE);
  386. }
  387. }
  388. ////////////////////////////////////////////////////////
  389. PWSTR PropertyName = L"__mydlgparams";
  390. BOOL
  391. PromptDialogOk(
  392. IN HWND hdlg
  393. )
  394. {
  395. WCHAR Location[MAX_PATH];
  396. UINT Length;
  397. PPROMPTDIALOGPARAMS DlgParams;
  398. DlgParams = (PPROMPTDIALOGPARAMS)GetProp(hdlg,PropertyName);
  399. //
  400. // Get the text the user has typed into the edit control
  401. // as the location of the files.
  402. //
  403. Length = GetDlgItemText(hdlg,IDC_LOCATION,Location,MAX_PATH);
  404. //
  405. // Remove trailing backslash if any.
  406. //
  407. if(Length && (Location[Length-1] == L'\\')) {
  408. Location[Length-1] = 0;
  409. }
  410. //
  411. // See whether the online books help file is at that location.
  412. //
  413. if(CheckHelpfilePresent(Location)) {
  414. DlgParams->FinalLocation = DupString(Location);
  415. return(TRUE);
  416. }
  417. //
  418. // See whether the online books help file is in the subdirectory
  419. // where it would be on the CD.
  420. //
  421. lstrcat(Location,PathOfBooksFilesOnCd);
  422. if(CheckHelpfilePresent(Location)) {
  423. DlgParams->FinalLocation = DupString(Location);
  424. return(TRUE);
  425. }
  426. return(FALSE);
  427. }
  428. BOOL
  429. PromptDialogBrowse(
  430. IN HWND hdlg
  431. )
  432. {
  433. BOOL b;
  434. OPENFILENAME on;
  435. WCHAR Filter[256];
  436. WCHAR Location[MAX_PATH];
  437. PWSTR Title;
  438. WCHAR InitialDir[MAX_PATH];
  439. PWSTR p;
  440. DWORD len;
  441. p = MyLoadString(IDS_FILETYPE_NAME);
  442. lstrcpy(Filter,p);
  443. MyFree(p);
  444. len = lstrlen(Filter)+1;
  445. lstrcpy(Filter+len,HelpFileName);
  446. len += lstrlen(HelpFileName) + 1;
  447. Filter[len] = 0;
  448. lstrcpy(Location,HelpFileName);
  449. Title = MyLoadString(IDS_BROWSE_TITLE);
  450. GetDlgItemText(hdlg,IDC_LOCATION,InitialDir,MAX_PATH);
  451. on.lStructSize = sizeof(on);
  452. on.hwndOwner = hdlg;
  453. on.hInstance = hInst;
  454. on.lpstrFilter = Filter;
  455. on.lpstrCustomFilter = NULL;
  456. on.nMaxCustFilter = 0;
  457. on.nFilterIndex = 1;
  458. on.lpstrFile = Location;
  459. on.nMaxFile = MAX_PATH;
  460. on.lpstrFileTitle = NULL;
  461. on.nMaxFileTitle = 0;
  462. on.lpstrInitialDir = InitialDir;
  463. on.lpstrTitle = Title;
  464. on.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  465. on.nFileOffset = 0;
  466. on.nFileExtension = 0;
  467. on.lpstrDefExt = L"HLP";
  468. on.lCustData = 0;
  469. on.lpfnHook = NULL;
  470. on.lpTemplateName = NULL;
  471. b = GetOpenFileName(&on);
  472. MyFree(Title);
  473. if(b) {
  474. //
  475. // User said ok. The full path of the help file is in
  476. // Location. Ignore the actual filename; the path is
  477. // what we want.
  478. //
  479. Location[on.nFileOffset ? on.nFileOffset-1 : 0] = 0;
  480. //
  481. // Set the text in the edit cntrol so the dialog
  482. // can fetch it later.
  483. //
  484. SetDlgItemText(hdlg,IDC_LOCATION,Location);
  485. }
  486. return b;
  487. }
  488. INT_PTR
  489. CALLBACK
  490. DlgProcPrompt(
  491. IN HWND hdlg,
  492. IN UINT msg,
  493. IN WPARAM wParam,
  494. IN LPARAM lParam
  495. )
  496. {
  497. PPROMPTDIALOGPARAMS DlgParams;
  498. switch(msg) {
  499. case WM_INITDIALOG:
  500. CenterDialogOnScreen(hdlg);
  501. DlgParams = (PPROMPTDIALOGPARAMS)lParam;
  502. //
  503. // Set the main text message.
  504. //
  505. SetDlgItemText(hdlg,IDT_MAIN_CAPTION,DlgParams->MainMessage);
  506. //
  507. // Set the text in the edit control and select all of it.
  508. // Also set focus to that control.
  509. //
  510. SetDlgItemText(hdlg,IDC_LOCATION,DlgParams->InitialLocation);
  511. SendDlgItemMessage(hdlg,IDC_LOCATION,EM_SETSEL,0,(LPARAM)(-1));
  512. SendDlgItemMessage(hdlg,IDC_LOCATION,EM_LIMITTEXT,MAX_PATH-1,0);
  513. SetFocus(GetDlgItem(hdlg,IDC_LOCATION));
  514. //
  515. // Remember the init params
  516. //
  517. if(!SetProp(hdlg,PropertyName,(HANDLE)lParam)) {
  518. OutOfMemory();
  519. }
  520. //
  521. // Tell windows we set the focus.
  522. //
  523. return(FALSE);
  524. case WM_COMMAND:
  525. switch(HIWORD(wParam)) {
  526. case BN_CLICKED:
  527. switch(LOWORD(wParam)) {
  528. case IDB_BROWSE:
  529. if(!PromptDialogBrowse(hdlg)) {
  530. break;
  531. }
  532. // FALL THROUGH IF BROWSE WAS SUCCESSFUL
  533. case IDOK:
  534. if(PromptDialogOk(hdlg)) {
  535. EndDialog(hdlg,TRUE);
  536. } else {
  537. MyError(hdlg,IDS_BAD_LOCATION,FALSE);
  538. }
  539. return(FALSE);
  540. case IDCANCEL:
  541. EndDialog(hdlg,FALSE);
  542. return(FALSE);
  543. }
  544. break;
  545. }
  546. break;
  547. case WM_QUERYDRAGICON:
  548. return(MainIcon != NULL);
  549. default:
  550. return(FALSE);
  551. }
  552. return(TRUE);
  553. }