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.

1127 lines
36 KiB

  1. /*++
  2. Copyright (c) 1989-2001 Microsoft Corporation
  3. Module Name:
  4. CAppHelpWizard.cpp
  5. Abstract:
  6. Code for the AppHelp Wizard
  7. Author:
  8. kinshu created July 2, 2001
  9. Notes:
  10. The name of the AppHelp message in the library section is made same as the
  11. HTMLHelp id for that apphelp message as in the entry
  12. Apphelp messages are not shared and each apphelped entry has an exclusive apphelp
  13. message in the library
  14. E.g of XML for soft blocked AppHelped entry:
  15. <?xml version="1.0" encoding="UTF-16"?>
  16. <DATABASE NAME="New Database(1)" ID="{780BE9F6-B750-404B-9BF1-ECA7B407B592}">
  17. <LIBRARY>
  18. <MESSAGE NAME="1">
  19. <SUMMARY>
  20. Hello World!!!!
  21. </SUMMARY>
  22. </MESSAGE>
  23. </LIBRARY>
  24. <APP NAME="New Application" VENDOR="Vendor Name">
  25. <EXE NAME="w.exe" ID="{31490b6d-6202-4bbf-9b92-2edf209b3ccc}" BIN_FILE_VERSION="5.1.2467.0" BIN_PRODUCT_VERSION="5.1.2467.0" PRODUCT_VERSION="5.1.2467.0" FILE_VERSION="5.1.2467.0 (lab06_N.010419-2241)">
  26. <APPHELP MESSAGE="1" BLOCK="NO" HTMLHELPID="1" DETAILS_URL="www.microsoft.com"/>
  27. </EXE>
  28. </APP>
  29. </DATABASE>
  30. Part of the .sdb created for the above XML:
  31. 0x00000134 | 0x7007 | EXE | LIST | Size 0x0000006C
  32. 0x0000013A | 0x6001 | NAME | STRINGREF | w.exe
  33. 0x00000140 | 0x6006 | APP_NAME | STRINGREF | New Application
  34. 0x00000146 | 0x6005 | VENDOR | STRINGREF | Vendor Name
  35. 0x0000014C | 0x9004 | EXE_ID(GUID) | BINARY | Size 0x00000010 | {31490b6d-6202-4bbf-9b92-2edf209b3ccc}
  36. 0x00000162 | 0x700D | APPHELP | LIST | Size 0x00000012
  37. 0x00000168 | 0x4017 | FLAGS | DWORD | 0x00000001
  38. 0x0000016E | 0x4010 | PROBLEM_SEVERITY | DWORD | 0x00000001
  39. 0x00000174 | 0x4015 | HTMLHELPID | DWORD | 0x00000001
  40. -end- APPHELP
  41. 0x0000017A | 0x7008 | MATCHING_FILE | LIST | Size 0x00000026
  42. 0x00000180 | 0x6001 | NAME | STRINGREF | *
  43. 0x00000186 | 0x6011 | PRODUCT_VERSION | STRINGREF | 5.1.2467.0
  44. 0x0000018C | 0x5002 | BIN_FILE_VERSION | QWORD | 0x0005000109A30000
  45. 0x00000196 | 0x5003 | BIN_PRODUCT_VERSION | QWORD | 0x0005000109A30000
  46. 0x000001A0 | 0x6013 | FILE_VERSION | STRINGREF | 5.1.2467.0 (lab06_N.010419-2241)
  47. -end- MATCHING_FILE
  48. -end- EXE
  49. 0x000001A6 | 0x700D | APPHELP | LIST | Size 0x0000001E
  50. 0x000001AC | 0x4015 | HTMLHELPID | DWORD | 0x00000001
  51. 0x000001B2 | 0x700E | LINK | LIST | Size 0x00000006
  52. 0x000001B8 | 0x6019 | LINK_URL | STRINGREF | www.microsoft.com
  53. -end- LINK
  54. 0x000001BE | 0x601B | APPHELP_TITLE | STRINGREF | New Application
  55. 0x000001C4 | 0x6018 | PROBLEM_DETAILS | STRINGREF | Hello World!!!!
  56. -end- APPHELP
  57. Revision History:
  58. --*/
  59. #include "precomp.h"
  60. /////////////////////// Defines ///////////////////////////////////////////////
  61. // The first page of the wizard. Gets the app info, app name, vendor name, exe path
  62. #define PAGE_GETAPP_INFO 0
  63. // The second page of the wizard
  64. #define PAGE_GET_MATCH_FILES 1
  65. // The third page of the wizard. Gets the type of apphelp-soft or hard bloc
  66. #define PAGE_GETMSG_TYPE 2
  67. // The last page of the wizard. Gets the message and the URL
  68. #define PAGE_GETMSG_INFORMATION 3
  69. // Total number of pages in the wizard
  70. #define NUM_PAGES 4
  71. // The maximum length of a apphelp URL in chars
  72. #define MAX_URL_LENGTH 1023
  73. // The maximum length of a apphelp message in chars
  74. #define MAX_MESSAGE_LENGTH 1023
  75. ///////////////////////////////////////////////////////////////////////////////
  76. //////////////////////// Externs //////////////////////////////////////////////
  77. extern CShimWizard* g_pCurrentWizard;
  78. extern HINSTANCE g_hInstance;
  79. extern DATABASE GlobalDataBase;
  80. ///////////////////////////////////////////////////////////////////////////////
  81. //////////////////////// Function declarations ////////////////////////////////
  82. BOOL
  83. DeleteAppHelp(
  84. DWORD nHelpID
  85. );
  86. ///////////////////////////////////////////////////////////////////////////////
  87. BOOL
  88. CAppHelpWizard::BeginWizard(
  89. IN HWND hParent,
  90. IN PDBENTRY pEntry,
  91. IN PDATABASE pDatabase
  92. )
  93. /*++
  94. CAppHelpWizard::BeginWizard
  95. Desc: Starts up the wizard. Initializes the various prop-sheet parameters
  96. and calls the wizard
  97. Params:
  98. IN HWND hParent : Parent for the wizard window
  99. IN PDBENTRY pEntry : Entry for which AppHelp has to be created or modified
  100. IN PDATABASE pDatabase : Database in which pEntry resides
  101. Return:
  102. TRUE: The user pressed Finish
  103. FALSE: The user pressed Cancel
  104. --*/
  105. {
  106. m_pDatabase = pDatabase;
  107. PROPSHEETPAGE Pages[NUM_PAGES];
  108. if (pEntry == NULL) {
  109. //
  110. // Create a new fix.
  111. //
  112. ZeroMemory(&m_Entry, sizeof(m_Entry));
  113. GUID Guid;
  114. CoCreateGuid(&Guid);
  115. StringCchPrintf(m_Entry.szGUID,
  116. ARRAYSIZE(m_Entry.szGUID),
  117. TEXT("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  118. Guid.Data1,
  119. Guid.Data2,
  120. Guid.Data3,
  121. Guid.Data4[0],
  122. Guid.Data4[1],
  123. Guid.Data4[2],
  124. Guid.Data4[3],
  125. Guid.Data4[4],
  126. Guid.Data4[5],
  127. Guid.Data4[6],
  128. Guid.Data4[7]);
  129. m_bEditing = FALSE;
  130. } else {
  131. //
  132. // Edit the passed fix.
  133. //
  134. m_bEditing = TRUE;
  135. //
  136. // If we are editing then set m_Entry as *pEntry. The operator is overloaded
  137. // All throughout the wizard we only work on m_pEntry
  138. //
  139. m_Entry = *pEntry;
  140. }
  141. //
  142. // Setup wizard variables
  143. //
  144. g_pCurrentWizard = this;
  145. g_pCurrentWizard->m_uType = TYPE_APPHELPWIZARD;
  146. //
  147. // begin the wizard
  148. //
  149. PROPSHEETHEADER Header;
  150. Header.dwSize = sizeof(PROPSHEETHEADER);
  151. Header.dwFlags = PSH_WIZARD97 | PSH_HEADER | PSH_WATERMARK | PSH_PROPSHEETPAGE;
  152. Header.hwndParent = hParent;
  153. Header.hInstance = g_hInstance;
  154. Header.pszCaption = MAKEINTRESOURCE(IDS_CUSTOMAPPHELP);
  155. Header.nStartPage = 0;
  156. Header.ppsp = Pages;
  157. Header.nPages = NUM_PAGES;
  158. Header.pszbmHeader = MAKEINTRESOURCE(IDB_WIZBMP);
  159. if (m_bEditing) {
  160. //
  161. // If we are editing then, put Finish button on all pages
  162. //
  163. Header.dwFlags |= PSH_WIZARDHASFINISH;
  164. }
  165. Pages[PAGE_GETAPP_INFO].dwSize = sizeof(PROPSHEETPAGE);
  166. Pages[PAGE_GETAPP_INFO].dwFlags = PSP_DEFAULT| PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  167. Pages[PAGE_GETAPP_INFO].hInstance = g_hInstance;
  168. Pages[PAGE_GETAPP_INFO].pszTemplate = MAKEINTRESOURCE(IDD_HELPWIZ_APPINFO);
  169. Pages[PAGE_GETAPP_INFO].pfnDlgProc = GetAppInfo;
  170. Pages[PAGE_GETAPP_INFO].pszHeaderTitle = MAKEINTRESOURCE(IDS_GIVEAPPINFO);
  171. Pages[PAGE_GETAPP_INFO].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_GIVEAPPINFOSUBHEADING);
  172. Pages[PAGE_GET_MATCH_FILES].dwSize = sizeof(PROPSHEETPAGE);
  173. Pages[PAGE_GET_MATCH_FILES].dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  174. Pages[PAGE_GET_MATCH_FILES].hInstance = g_hInstance;
  175. Pages[PAGE_GET_MATCH_FILES].pszTemplate = MAKEINTRESOURCE(IDD_FIXWIZ_MATCHINGINFO);
  176. Pages[PAGE_GET_MATCH_FILES].pfnDlgProc = SelectFiles;
  177. Pages[PAGE_GET_MATCH_FILES].pszHeaderTitle = MAKEINTRESOURCE(IDS_MATCHINFO);
  178. Pages[PAGE_GET_MATCH_FILES].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_MATCHINFO_SUBHEADING);
  179. Pages[PAGE_GETMSG_TYPE].dwSize = sizeof(PROPSHEETPAGE);
  180. Pages[PAGE_GETMSG_TYPE].dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  181. Pages[PAGE_GETMSG_TYPE].hInstance = g_hInstance;
  182. Pages[PAGE_GETMSG_TYPE].pszTemplate = MAKEINTRESOURCE(IDD_HELPWIZ_TYPE);
  183. Pages[PAGE_GETMSG_TYPE].pfnDlgProc = GetMessageType;
  184. Pages[PAGE_GETMSG_TYPE].pszHeaderTitle = MAKEINTRESOURCE(IDS_MESSAGETYPE);
  185. Pages[PAGE_GETMSG_TYPE].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_MESSAGETYPE_SUBHEADING);
  186. Pages[PAGE_GETMSG_INFORMATION].dwSize = sizeof(PROPSHEETPAGE);
  187. Pages[PAGE_GETMSG_INFORMATION].dwFlags = PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
  188. Pages[PAGE_GETMSG_INFORMATION].hInstance = g_hInstance;
  189. Pages[PAGE_GETMSG_INFORMATION].pszTemplate = MAKEINTRESOURCE(IDD_HELPWIZ_MESSAGE);
  190. Pages[PAGE_GETMSG_INFORMATION].pfnDlgProc = GetMessageInformation;
  191. Pages[PAGE_GETMSG_INFORMATION].pszHeaderTitle = MAKEINTRESOURCE(IDS_MESSAGEINFO);
  192. Pages[PAGE_GETMSG_INFORMATION].pszHeaderSubTitle = MAKEINTRESOURCE(IDS_MESSAGEINFO_SUBHEADING);
  193. BOOL bReturn = FALSE;
  194. if (0 < PropertySheet(&Header)) {
  195. //
  196. // Finish Pressed
  197. //
  198. bReturn = TRUE;
  199. } else {
  200. //
  201. // Cancel pressed, we might have to delete the new apphelp in the Database.
  202. //
  203. bReturn = FALSE;
  204. if (nPresentHelpId != -1) {
  205. //
  206. // There is some apphelp that has been entered in the database
  207. //
  208. if(!g_pCurrentWizard->m_pDatabase) {
  209. assert(FALSE);
  210. goto End;
  211. }
  212. g_pCurrentWizard->m_Entry.appHelp.bPresent = FALSE;
  213. g_pCurrentWizard->m_Entry.appHelp.bBlock = FALSE;
  214. DeleteAppHelp(g_pCurrentWizard->m_pDatabase,
  215. g_pCurrentWizard->m_pDatabase->m_nMAXHELPID);
  216. nPresentHelpId = -1;
  217. //
  218. // Decrement the maximum help id, so that the next apphelp for this database
  219. // can use that id
  220. //
  221. --(g_pCurrentWizard->m_pDatabase->m_nMAXHELPID);
  222. }
  223. }
  224. End:
  225. ENABLEWINDOW(g_hDlg, TRUE);
  226. return bReturn;
  227. }
  228. /*++---------------------------------------------------------------------------
  229. All the wizard page routines
  230. ---------------------------------------------------------------------------
  231. --*/
  232. INT_PTR
  233. CALLBACK
  234. GetAppInfo(
  235. IN HWND hDlg,
  236. IN UINT uMsg,
  237. IN WPARAM wParam,
  238. IN LPARAM lParam
  239. )
  240. /*++
  241. GetAppInfo
  242. Desc: Handler for the first page of the wizard.
  243. Params: Standard dialog handler parameters
  244. IN HWND hDlg
  245. IN UINT uMsg
  246. IN WPARAM wParam
  247. IN LPARAM lParam
  248. Return: Standard dialog handler return
  249. --*/
  250. {
  251. switch (uMsg) {
  252. case WM_INITDIALOG:
  253. {
  254. HWND hParent = GetParent(hDlg);
  255. CenterWindow(GetParent(hParent), hParent);
  256. if (g_pCurrentWizard->m_bEditing
  257. && g_pCurrentWizard->m_Entry.appHelp.bPresent) {
  258. //
  259. // We are editing an existing apphelp
  260. //
  261. SetWindowText(hParent, CSTRING(IDS_CUSTOMAPPHELP_EDIT));
  262. } else if (g_pCurrentWizard->m_bEditing
  263. && !g_pCurrentWizard->m_Entry.appHelp.bPresent) {
  264. //
  265. // We are adding a new apphelp to an existing entry, which contains some fix
  266. //
  267. SetWindowText(hParent, CSTRING(IDS_CUSTOMAPPHELP_ADD));
  268. } else {
  269. //
  270. // Creating a new apphelp entry
  271. //
  272. SetWindowText(hParent, CSTRING(IDS_CUSTOMAPPHELP));
  273. }
  274. //
  275. // Limit the length of the text boxes
  276. //
  277. SendMessage(GetDlgItem(hDlg, IDC_APPNAME),
  278. EM_LIMITTEXT,
  279. (WPARAM)LIMIT_APP_NAME,
  280. (LPARAM)0);
  281. SendMessage(GetDlgItem(hDlg, IDC_VENDOR),
  282. EM_LIMITTEXT,
  283. (WPARAM)MAX_VENDOR_LENGTH,
  284. (LPARAM)0);
  285. SendMessage(GetDlgItem(hDlg, IDC_EXEPATH),
  286. EM_LIMITTEXT,
  287. (WPARAM)MAX_PATH - 1,
  288. (LPARAM)0);
  289. if (g_pCurrentWizard->m_bEditing) {
  290. //
  291. // If we are editing a fix, make the App. and exe path text fields read only
  292. //
  293. SendMessage(GetDlgItem(hDlg, IDC_APPNAME), EM_SETREADONLY, TRUE, 0);
  294. SendMessage(GetDlgItem(hDlg, IDC_EXEPATH), EM_SETREADONLY, TRUE, 0);
  295. ENABLEWINDOW(GetDlgItem(hDlg, IDC_BROWSE), FALSE);
  296. }
  297. //
  298. // Set the text for the app name field
  299. //
  300. if (g_pCurrentWizard->m_Entry.strAppName.Length() > 0) {
  301. SetDlgItemText(hDlg, IDC_APPNAME, g_pCurrentWizard->m_Entry.strAppName);
  302. } else {
  303. SetDlgItemText(hDlg, IDC_APPNAME, GetString(IDS_DEFAULT_APP_NAME));
  304. SendMessage(GetDlgItem(hDlg, IDC_APPNAME), EM_SETSEL, 0,-1);
  305. }
  306. //
  307. // Set the text for the vendor name field
  308. //
  309. if (g_pCurrentWizard->m_Entry.strVendor.Length() > 0) {
  310. SetDlgItemText(hDlg,
  311. IDC_VENDOR,
  312. g_pCurrentWizard->m_Entry.strVendor);
  313. } else {
  314. SetDlgItemText(hDlg, IDC_VENDOR, GetString(IDS_DEFAULT_VENDOR_NAME));
  315. }
  316. //
  317. // Set the text for the entry name field
  318. //
  319. if (g_pCurrentWizard->m_Entry.strExeName.Length() > 0) {
  320. SetDlgItemText(hDlg,
  321. IDC_EXEPATH,
  322. g_pCurrentWizard->m_Entry.strExeName);
  323. }
  324. SHAutoComplete(GetDlgItem(hDlg, IDC_EXEPATH), AUTOCOMPLETE);
  325. //
  326. // Force proper Next button state.
  327. //
  328. SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_APPNAME, EN_CHANGE), 0);
  329. break;
  330. }
  331. case WM_NOTIFY:
  332. {
  333. NMHDR* pHdr = (NMHDR*)lParam;
  334. if (pHdr == NULL) {
  335. break;
  336. }
  337. switch (pHdr->code) {
  338. case PSN_SETACTIVE:
  339. SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_EXEPATH, EN_CHANGE), 0);
  340. break;
  341. case PSN_WIZFINISH:
  342. case PSN_WIZNEXT:
  343. {
  344. TCHAR szTemp[MAX_PATH];
  345. TCHAR szEXEPath[MAX_PATH];
  346. TCHAR szPathTemp[MAX_PATH];
  347. *szTemp = *szEXEPath = *szPathTemp = 0;
  348. GetDlgItemText(hDlg, IDC_APPNAME, szTemp, ARRAYSIZE(szTemp));
  349. CSTRING::Trim(szTemp);
  350. if (!IsValidAppName(szTemp)) {
  351. //
  352. // The app name contains invalid chars
  353. //
  354. DisplayInvalidAppNameMessage(hDlg);
  355. SetFocus(GetDlgItem(hDlg, IDC_APPNAME));
  356. SetWindowLongPtr(hDlg, DWLP_MSGRESULT,-1);
  357. return -1;
  358. }
  359. g_pCurrentWizard->m_Entry.strAppName = szTemp;
  360. GetDlgItemText(hDlg, IDC_EXEPATH, szEXEPath, ARRAYSIZE(szEXEPath));
  361. CSTRING::Trim(szEXEPath);
  362. *szPathTemp = 0;
  363. //
  364. // Check if the file exists. We check for this only when we are creating
  365. // a new fix and not when we are editing an existing fix
  366. //
  367. if (!g_pCurrentWizard->m_bEditing) {
  368. HANDLE hFile = CreateFile(szEXEPath,
  369. 0,
  370. 0,
  371. NULL,
  372. OPEN_EXISTING,
  373. FILE_ATTRIBUTE_NORMAL,
  374. NULL);
  375. if (INVALID_HANDLE_VALUE == hFile) {
  376. //
  377. // File does not exist
  378. //
  379. MessageBox(hDlg,
  380. CSTRING(IDS_INVALIDEXE),
  381. g_szAppName,
  382. MB_OK | MB_ICONWARNING);
  383. SetWindowLongPtr(hDlg, DWLP_MSGRESULT,-1);
  384. return -1;
  385. }
  386. CloseHandle(hFile);
  387. //
  388. // Set the full path
  389. //
  390. g_pCurrentWizard->m_Entry.strFullpath = szEXEPath;
  391. g_pCurrentWizard->m_Entry.strFullpath.ConvertToLongFileName();
  392. //
  393. // Set the default mask for the matching attributes to be used
  394. //
  395. g_pCurrentWizard->dwMaskOfMainEntry = DEFAULT_MASK;
  396. //
  397. // Set the entry name that will be written in the xml
  398. //
  399. SafeCpyN(szPathTemp, (PCTSTR)g_pCurrentWizard->m_Entry.strFullpath, ARRAYSIZE(szPathTemp));
  400. PathStripPath(szPathTemp);
  401. g_pCurrentWizard->m_Entry.strExeName = szPathTemp;
  402. } else if (g_pCurrentWizard->m_Entry.strFullpath.Length() == 0) {
  403. //
  404. // Since we do not have the complete path,
  405. // this SDB was loaded from the disk
  406. //
  407. g_pCurrentWizard->m_Entry.strFullpath = szEXEPath;
  408. }
  409. GetDlgItemText(hDlg, IDC_VENDOR, szTemp, ARRAYSIZE(szTemp));
  410. //
  411. // Set the vendor information
  412. //
  413. if (CSTRING::Trim(szTemp)) {
  414. g_pCurrentWizard->m_Entry.strVendor = szTemp;
  415. } else {
  416. g_pCurrentWizard->m_Entry.strVendor = GetString(IDS_DEFAULT_VENDOR_NAME);
  417. }
  418. break;
  419. }
  420. }
  421. break;
  422. }
  423. case WM_COMMAND:
  424. switch (LOWORD(wParam)) {
  425. case IDC_EXEPATH:
  426. case IDC_APPNAME:
  427. //
  428. // Check if all the fields are filled up properly.
  429. // We enable disable the Next/Finish button here.
  430. //
  431. // The vendor name field is not mandatory
  432. //
  433. //
  434. if (EN_CHANGE == HIWORD(wParam)) {
  435. TCHAR szTemp[MAX_PATH];
  436. DWORD dwFlags = 0;
  437. BOOL bEnable = FALSE;
  438. *szTemp = 0;
  439. GetDlgItemText(hDlg, IDC_APPNAME, szTemp, ARRAYSIZE(szTemp));
  440. bEnable = ValidInput(szTemp);
  441. GetDlgItemText(hDlg, IDC_EXEPATH, szTemp, ARRAYSIZE(szTemp));
  442. bEnable &= ValidInput(szTemp);
  443. if (bEnable) {
  444. dwFlags |= PSWIZB_NEXT;
  445. if (g_pCurrentWizard->m_bEditing) {
  446. dwFlags |= PSWIZB_FINISH;
  447. }
  448. } else {
  449. if (g_pCurrentWizard->m_bEditing) {
  450. dwFlags |= PSWIZB_DISABLEDFINISH;
  451. }
  452. }
  453. SendMessage(GetParent(hDlg), PSM_SETWIZBUTTONS, 0, dwFlags);
  454. }
  455. break;
  456. case IDC_BROWSE:
  457. {
  458. CSTRING szFilename;
  459. TCHAR szBuffer[64] = TEXT("");
  460. HWND hwndFocus = GetFocus();
  461. GetString(IDS_EXEFILTER, szBuffer, ARRAYSIZE(szBuffer));
  462. if (GetFileName(hDlg,
  463. CSTRING(IDS_FINDEXECUTABLE),
  464. szBuffer,
  465. TEXT(""),
  466. CSTRING(IDS_EXE_EXT),
  467. OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST,
  468. TRUE,
  469. szFilename)) {
  470. SetDlgItemText(hDlg, IDC_EXEPATH, szFilename);
  471. //
  472. // Force proper Next button state.
  473. //
  474. SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_EXEPATH, EN_CHANGE), 0);
  475. }
  476. SetFocus(hwndFocus);
  477. break;
  478. }
  479. }
  480. }
  481. return FALSE;
  482. }
  483. INT_PTR
  484. CALLBACK
  485. GetMessageType(
  486. IN HWND hDlg,
  487. IN UINT uMsg,
  488. IN WPARAM wParam,
  489. IN LPARAM lParam
  490. )
  491. /*++
  492. GetMessageType
  493. Desc: Handler for the third wizard page. This routine collects the type
  494. of the apphelp message. One of soft block or hard block.
  495. These are set in @pEntry.apphelp
  496. Params: Standard dialog handler parameters
  497. IN HWND hDlg
  498. IN UINT uMsg
  499. IN WPARAM wParam
  500. IN LPARAM lParam
  501. Return: Standard dialog handler return
  502. --*/
  503. {
  504. switch (uMsg) {
  505. case WM_INITDIALOG:
  506. //
  507. // Set the type of the app help radio button
  508. //
  509. if (g_pCurrentWizard->m_Entry.appHelp.bBlock == FALSE || g_pCurrentWizard->m_Entry.appHelp.bPresent == FALSE) {
  510. SendMessage(GetDlgItem(hDlg, IDC_NOBLOCK), BM_SETCHECK, 1, 0);
  511. } else {
  512. SendMessage(GetDlgItem(hDlg, IDC_BLOCK), BM_SETCHECK, 1, 0);
  513. }
  514. return TRUE;
  515. case WM_NOTIFY:
  516. {
  517. NMHDR* pHdr = (NMHDR*)lParam;
  518. if (pHdr == NULL) {
  519. break;
  520. }
  521. switch (pHdr->code) {
  522. case PSN_WIZFINISH:
  523. case PSN_WIZNEXT:
  524. {
  525. int iReturn = SendMessage(GetDlgItem(hDlg, IDC_NOBLOCK),
  526. BM_GETCHECK,
  527. 1,
  528. 0);
  529. if (iReturn == BST_CHECKED) {
  530. //
  531. // Soft block
  532. //
  533. g_pCurrentWizard->m_Entry.appHelp.bBlock = FALSE;
  534. } else {
  535. //
  536. // Hard block
  537. //
  538. g_pCurrentWizard->m_Entry.appHelp.bBlock = TRUE;
  539. }
  540. //
  541. // Set the severity depending upon type of block
  542. //
  543. if (g_pCurrentWizard->m_Entry.appHelp.bBlock) {
  544. g_pCurrentWizard->m_Entry.appHelp.severity = APPTYPE_INC_HARDBLOCK;
  545. } else {
  546. g_pCurrentWizard->m_Entry.appHelp.severity = APPTYPE_INC_NOBLOCK;
  547. }
  548. break;
  549. }
  550. case PSN_SETACTIVE:
  551. {
  552. DWORD dwFlags = PSWIZB_NEXT | PSWIZB_BACK;
  553. //
  554. // Set finish buttton status appropriately if we are editing
  555. //
  556. if (g_pCurrentWizard->m_bEditing) {
  557. if (g_pCurrentWizard->m_Entry.appHelp.bPresent) {
  558. dwFlags |= PSWIZB_FINISH;
  559. } else {
  560. dwFlags |= PSWIZB_DISABLEDFINISH;
  561. }
  562. }
  563. //
  564. // Set the buttons
  565. //
  566. SendMessage(GetParent(hDlg), PSM_SETWIZBUTTONS, 0, dwFlags);
  567. return TRUE;
  568. }
  569. }
  570. break;
  571. }
  572. }
  573. return FALSE;
  574. }
  575. INT_PTR
  576. CALLBACK
  577. GetMessageInformation(
  578. IN HWND hDlg,
  579. IN UINT uMsg,
  580. IN WPARAM wParam,
  581. IN LPARAM lParam
  582. )
  583. /*++
  584. GetMessageInformation
  585. Desc: Handler for the last wizard page. This routine collects the apphelp message
  586. and the url for the apphelp. Creates a new apphelp message and puts the
  587. apphelp message inside the database.
  588. When we are editing a apphelp, the previous apphelp needs to be removed
  589. Params: Standard dialog handler parameters
  590. IN HWND hDlg
  591. IN UINT uMsg
  592. IN WPARAM wParam
  593. IN LPARAM lParam
  594. Return: Standard dialog handler return
  595. --*/
  596. {
  597. switch (uMsg) {
  598. case WM_INITDIALOG:
  599. {
  600. //
  601. // Set the maximum length of the text boxes
  602. //
  603. SendMessage(GetDlgItem(hDlg, IDC_URL),
  604. EM_LIMITTEXT,
  605. (WPARAM)MAX_URL_LENGTH,
  606. (LPARAM)0);
  607. SendMessage(GetDlgItem(hDlg, IDC_MSG_SUMMARY),
  608. EM_LIMITTEXT,
  609. (WPARAM)MAX_MESSAGE_LENGTH,
  610. (LPARAM)0);
  611. if (g_pCurrentWizard->m_bEditing && g_pCurrentWizard->m_Entry.appHelp.bPresent) {
  612. PAPPHELP pAppHelp= g_pCurrentWizard->m_Entry.appHelp.pAppHelpinLib;
  613. if (pAppHelp == NULL) {
  614. //
  615. // This is an error. We should have had a proper value..
  616. //
  617. assert(FALSE);
  618. Dbg(dlError, "[GetMessageInformation] WM_INITDIALOG: pApphelp is NULL");
  619. break;
  620. }
  621. if (pAppHelp->strURL.Length()) {
  622. SetDlgItemText(hDlg, IDC_URL, pAppHelp->strURL);
  623. }
  624. SetDlgItemText(hDlg, IDC_MSG_SUMMARY, pAppHelp->strMessage);
  625. }
  626. //
  627. // Force proper Next/Finish button state.
  628. //
  629. SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_MSG_SUMMARY, EN_CHANGE), 0);
  630. break;
  631. }
  632. case WM_NOTIFY:
  633. {
  634. NMHDR * pHdr = (NMHDR*)lParam;
  635. switch (pHdr->code) {
  636. case PSN_SETACTIVE:
  637. //
  638. // Force proper Next/Finish button state
  639. //
  640. SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_MSG_SUMMARY, EN_CHANGE), 0);
  641. break;
  642. case PSN_WIZFINISH:
  643. if (!OnAppHelpFinish(hDlg)) {
  644. //
  645. // We failed most probably because the message input was not valid
  646. //
  647. MessageBox(hDlg, GetString(IDS_INVALID_APPHELP_MESSAGE), g_szAppName, MB_ICONWARNING);
  648. SetWindowLongPtr(hDlg, DWLP_MSGRESULT,-1);
  649. return -1;
  650. }
  651. return TRUE;
  652. }
  653. }
  654. break;
  655. case WM_COMMAND:
  656. switch (LOWORD(wParam)) {
  657. case IDC_MSG_SUMMARY:
  658. if (EN_CHANGE == HIWORD(wParam)) {
  659. BOOL bEnable = (GetWindowTextLength(GetDlgItem(hDlg,
  660. IDC_MSG_SUMMARY)) > 0) ? TRUE:FALSE;
  661. DWORD dwFlags = PSWIZB_BACK;
  662. if (bEnable) {
  663. dwFlags |= PSWIZB_FINISH;
  664. } else {
  665. if (g_pCurrentWizard->m_bEditing) {
  666. dwFlags |= PSWIZB_DISABLEDFINISH;
  667. }
  668. }
  669. ENABLEWINDOW(GetDlgItem(hDlg, IDC_TESTRUN), bEnable);
  670. SendMessage(GetParent(hDlg), PSM_SETWIZBUTTONS, 0, dwFlags);
  671. }
  672. break;
  673. case IDC_TESTRUN:
  674. {
  675. if (g_bAdmin == FALSE) {
  676. //
  677. // Test run will need to call sdbinst.exe which will not run if we are
  678. // not an admin
  679. //
  680. MessageBox(hDlg,
  681. GetString(IDS_ERRORNOTADMIN),
  682. g_szAppName,
  683. MB_ICONINFORMATION);
  684. break;
  685. }
  686. //
  687. // Save the apphelp of the entry so that we can revert back after test run.
  688. // After test run, the database and the entry should be in the same state as
  689. // it was before test run. Any apphelp message added to the database should be
  690. // removed and any apphelp properties that were changed for the entry should be
  691. // reverted
  692. //
  693. APPHELP AppHelpPrev = g_pCurrentWizard->m_Entry.appHelp;
  694. //
  695. // Add apphelp info to the library and set the fields of the entry
  696. //
  697. if (!OnAppHelpTestRun(hDlg)) {
  698. //
  699. // We failed most probably because the message input was not valid
  700. //
  701. MessageBox(hDlg, GetString(IDS_INVALID_APPHELP_MESSAGE), g_szAppName, MB_ICONWARNING);
  702. break;
  703. }
  704. TestRun(&g_pCurrentWizard->m_Entry,
  705. &g_pCurrentWizard->m_Entry.strFullpath,
  706. NULL,
  707. hDlg);
  708. //
  709. // <HACK>This is a hack!!!. TestRun launches a process using CreateProcess
  710. // and then the modal wizard starts behaving like a modeless wizard
  711. //
  712. ENABLEWINDOW(g_hDlg, FALSE);
  713. //
  714. // We have to delete the apphelp message that has been added to the library.
  715. //
  716. if (((CAppHelpWizard*)g_pCurrentWizard)->nPresentHelpId != -1) {
  717. if (g_pCurrentWizard->m_pDatabase == NULL) {
  718. assert(FALSE);
  719. break;
  720. }
  721. DeleteAppHelp(g_pCurrentWizard->m_pDatabase,
  722. g_pCurrentWizard->m_pDatabase->m_nMAXHELPID);
  723. g_pCurrentWizard->m_Entry.appHelp.bPresent = FALSE;
  724. g_pCurrentWizard->m_Entry.appHelp.bBlock = FALSE;
  725. --(g_pCurrentWizard->m_pDatabase->m_nMAXHELPID);
  726. ((CAppHelpWizard*)g_pCurrentWizard)->nPresentHelpId = -1;
  727. }
  728. //
  729. // Revert the apphelp properties. This is necessary for edit mode as
  730. // OnAppHelpTestRun will make changes to g_pCurrentWizard->m_Entry.appHelp.
  731. //
  732. g_pCurrentWizard->m_Entry.appHelp = AppHelpPrev;
  733. SetActiveWindow(hDlg);
  734. SetFocus(hDlg);
  735. }
  736. break;
  737. }
  738. }
  739. return FALSE;
  740. }
  741. BOOL
  742. DeleteAppHelp(
  743. IN PDATABASE pDatabase,
  744. IN DWORD nHelpID
  745. )
  746. /*++
  747. DeleteAppHelp
  748. Desc: Deletes the AppHelp message with ID of nHelpID from database pDatabase
  749. Params:
  750. IN PDATABASE pDatabase : The database in which the apphelp message lives
  751. IN DWORD nHelpID : ID of the apphelp message that has to be deleted
  752. Return:
  753. TRUE: The apphelp message was deleted
  754. FALSE: Otherwise
  755. --*/
  756. {
  757. if (pDatabase == NULL) {
  758. assert(FALSE);
  759. return FALSE;
  760. }
  761. PAPPHELP pAppHelp = pDatabase->pAppHelp;
  762. PAPPHELP pPrev = NULL;
  763. while (pAppHelp) {
  764. if (pAppHelp->HTMLHELPID == nHelpID) {
  765. if (pPrev == NULL) {
  766. pDatabase->pAppHelp = pDatabase->pAppHelp->pNext;
  767. } else {
  768. pPrev->pNext = pAppHelp->pNext;
  769. }
  770. delete pAppHelp;
  771. return TRUE;
  772. } else {
  773. pPrev = pAppHelp;
  774. pAppHelp = pAppHelp->pNext;
  775. }
  776. }
  777. return FALSE;
  778. }
  779. BOOL
  780. OnAppHelpTestRun(
  781. IN HWND hDlg
  782. )
  783. /*++
  784. OnAppHelpTestRun
  785. Desc: Handles the test run case. Lets OnAppHelpFinish handle it.
  786. This routine is invoked when the user presses Test Run
  787. Params:
  788. IN HWND hDlg: The wizard page containing the Test-Run button
  789. --*/
  790. {
  791. return OnAppHelpFinish(hDlg, TRUE);
  792. }
  793. BOOL
  794. OnAppHelpFinish(
  795. IN HWND hDlg,
  796. IN BOOL bTestRun // (FALSE)
  797. )
  798. /*++
  799. OnAppHelpFinish
  800. Desc: Handles the user's pressing Finish button in the wizard
  801. Also is called by the routine that handles the pressing of Test Run button
  802. Params:
  803. IN HWND hDlg : The wizard page
  804. IN BOOL bTestRun (FALSE) : Whether this routine is invoked because of
  805. pressing Test-Run or Finish
  806. Return: void
  807. --*/
  808. {
  809. K_SIZE k_szTemp = MAX_MESSAGE_LENGTH + 1;
  810. PTSTR pszTemp = new TCHAR[k_szTemp];
  811. BOOL bOk = TRUE;
  812. if (pszTemp == NULL) {
  813. bOk = FALSE;
  814. goto End;
  815. }
  816. *pszTemp = 0;
  817. GetDlgItemText(hDlg, IDC_MSG_SUMMARY, pszTemp, k_szTemp);
  818. if (ValidInput(pszTemp) == FALSE) {
  819. bOk = FALSE;
  820. goto End;
  821. }
  822. //
  823. // If we are in editing mode we have to remove the previous AppHelp
  824. // from the Lib. But NOT if this function is being called because of test run !!
  825. //
  826. if (g_pCurrentWizard->m_bEditing && !bTestRun) {
  827. if (g_pCurrentWizard->m_Entry.appHelp.bPresent) {
  828. DeleteAppHelp(g_pCurrentWizard->m_pDatabase,
  829. g_pCurrentWizard->m_Entry.appHelp.HTMLHELPID);
  830. }
  831. }
  832. //
  833. // Create a new apphelp message that we will put in the lib of the database.
  834. // The entry being apphelped will point to this though its Apphelp.pAppHelpinLib
  835. //
  836. PAPPHELP pAppHelp = NULL;
  837. pAppHelp = new APPHELP;
  838. if (pAppHelp == NULL) {
  839. MEM_ERR;
  840. bOk = FALSE;
  841. goto End;
  842. }
  843. assert(g_pCurrentWizard->m_pDatabase);
  844. //
  845. // Give it the next apphelp message id
  846. //
  847. pAppHelp->HTMLHELPID = ++(g_pCurrentWizard->m_pDatabase->m_nMAXHELPID);
  848. pAppHelp->strMessage = pszTemp;
  849. pAppHelp->strMessage.Trim();
  850. *pszTemp = 0;
  851. GetDlgItemText(hDlg, IDC_URL, pszTemp, k_szTemp);
  852. pAppHelp->strURL = pszTemp;
  853. pAppHelp->strURL.Trim();
  854. //
  855. // Add the APPHELP message in the Library.
  856. //
  857. pAppHelp->pNext = g_pCurrentWizard->m_pDatabase->pAppHelp;
  858. g_pCurrentWizard->m_pDatabase->pAppHelp = pAppHelp;
  859. //
  860. // Indicate that we have added a new apphelp message in the database. If during an
  861. // Apphelp wizard invocation, no apphelp message was added in the database
  862. // then (CAppHelpWizard*)g_pCurrentWizard)->nPresentHelpId should be equal
  863. // to -1
  864. //
  865. ((CAppHelpWizard*)g_pCurrentWizard)->nPresentHelpId = pAppHelp->HTMLHELPID;
  866. //
  867. // Add the AppHelp fields for the entry
  868. //
  869. g_pCurrentWizard->m_Entry.appHelp.bPresent = TRUE;
  870. g_pCurrentWizard->m_Entry.appHelp.pAppHelpinLib = pAppHelp;
  871. g_pCurrentWizard->m_Entry.appHelp.HTMLHELPID = ((CAppHelpWizard*)g_pCurrentWizard)->nPresentHelpId;
  872. End:
  873. if (pszTemp) {
  874. delete[] pszTemp;
  875. pszTemp = NULL;
  876. }
  877. return bOk;
  878. }