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.

1275 lines
27 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. clientcp.c
  5. Abstract:
  6. Functions for handling events in the "Client Cover Page" tab of
  7. the fax client configuration property sheet
  8. Environment:
  9. Fax configuration applet
  10. Revision History:
  11. 03/13/96 -davidx-
  12. Created it.
  13. mm/dd/yy -author-
  14. description
  15. --*/
  16. #include <windows.h>
  17. #include <windowsx.h>
  18. #include <winfax.h>
  19. #include <shlobj.h>
  20. #include <shellapi.h>
  21. #include <tchar.h>
  22. #include <commdlg.h>
  23. #include "faxutil.h"
  24. #include "faxreg.h"
  25. #include "faxcfgrs.h"
  26. #include "faxhelp.h"
  27. #include "faxcfg.h"
  28. PCPDATA pCPInfo;
  29. BOOL
  30. ClientCoverPageProc(
  31. HWND hDlg,
  32. UINT message,
  33. WPARAM wParam,
  34. LPARAM lParam
  35. )
  36. /*++
  37. Routine Description:
  38. Procedure for handling the "Client Cover Page" tab
  39. Arguments:
  40. hDlg - Identifies the property sheet page
  41. message - Specifies the message
  42. wParam - Specifies additional message-specific information
  43. lParam - Specifies additional message-specific information
  44. Return Value:
  45. Depends on the value of message parameter
  46. --*/
  47. {
  48. INT cmdId;
  49. switch (message) {
  50. case WM_INITDIALOG:
  51. pCPInfo = AllocCoverPageInfo();
  52. InitCoverPageList(pCPInfo, hDlg);
  53. return TRUE;
  54. case WM_COMMAND:
  55. switch (cmdId = GET_WM_COMMAND_ID(wParam, lParam)) {
  56. case IDC_COVERPG_ADD:
  57. case IDC_COVERPG_NEW:
  58. case IDC_COVERPG_OPEN:
  59. case IDC_COVERPG_REMOVE:
  60. //
  61. // User clicked one of the buttons for managing cover page files
  62. //
  63. cmdId = (cmdId == IDC_COVERPG_REMOVE) ? CPACTION_REMOVE :
  64. (cmdId == IDC_COVERPG_OPEN) ? CPACTION_OPEN :
  65. (cmdId == IDC_COVERPG_NEW) ? CPACTION_NEW : CPACTION_BROWSE;
  66. ManageCoverPageList(hDlg,
  67. pCPInfo,
  68. GetDlgItem(hDlg, IDC_COVERPG_LIST),
  69. cmdId);
  70. break;
  71. case IDC_COVERPG_LIST:
  72. switch (GET_WM_COMMAND_CMD(wParam, lParam)) {
  73. case LBN_SELCHANGE:
  74. UpdateCoverPageControls(hDlg);
  75. break;
  76. case LBN_DBLCLK:
  77. //
  78. // Double-clicking in the cover page list is equivalent
  79. // to pressing the "Open" button
  80. //
  81. ManageCoverPageList(hDlg,
  82. pCPInfo,
  83. GetDlgItem(hDlg, cmdId),
  84. CPACTION_OPEN);
  85. break;
  86. }
  87. break;
  88. default:
  89. return FALSE;
  90. }
  91. return TRUE;
  92. case WM_NOTIFY:
  93. switch (((NMHDR *) lParam)->code) {
  94. case PSN_SETACTIVE:
  95. break;
  96. case PSN_APPLY:
  97. return PSNRET_NOERROR;
  98. }
  99. break;
  100. case WM_HELP:
  101. case WM_CONTEXTMENU:
  102. return HandleHelpPopup(hDlg, message, wParam, lParam, CLIENT_COVERPG_PAGE);
  103. }
  104. return FALSE;
  105. }
  106. //
  107. // Find the filename portion given a filename:
  108. // return a pointer to the '.' character if successful
  109. // NULL if there is no extension
  110. //
  111. #define FindFilenameExtension(pFilename) _tcsrchr(pFilename, TEXT(FILENAME_EXT))
  112. VOID
  113. HandleOpenCoverPage(
  114. HWND hDlg,
  115. PCPDATA pCPInfo,
  116. HWND hwndList,
  117. LPTSTR pSelected,
  118. INT action
  119. )
  120. /*++
  121. Routine Description:
  122. Edit the currently selected cover page file or
  123. create a new cover page file
  124. Arguments:
  125. hDlg - Handle to the dialog window on which the list of cover pages is displayed
  126. pCPInfo - Points to cover page information
  127. hwndList - Handle to cover page listbox window
  128. pSelected - Currently selected cover page filename
  129. action - Open an existing cover page file or create a new one
  130. Return Value:
  131. NONE
  132. --*/
  133. {
  134. MSG msg; // used for peeking messages
  135. DWORD WaitObj;
  136. TCHAR filename[MAX_PATH];
  137. LPTSTR pExecutableName, pDirPath, pFilename;
  138. SHELLEXECUTEINFO shellExeInfo = {
  139. sizeof(SHELLEXECUTEINFO),
  140. SEE_MASK_NOCLOSEPROCESS,
  141. hDlg,
  142. NULL,
  143. NULL,
  144. NULL,
  145. NULL,
  146. SW_SHOWNORMAL,
  147. };
  148. //
  149. // Determine the default directory to run the cover page editor in:
  150. //
  151. if (action == CPACTION_NEW) {
  152. //
  153. // When creating a new cover page, the default directory is either
  154. // the server cover page directory or the user cover page directory
  155. // depending on whether the user is doing server adminstration.
  156. //
  157. pDirPath = pCPInfo->pDirPath[0];
  158. pFilename = NULL;
  159. SetEnvironmentVariable(TEXT("ClientCoverpage"),TEXT("1"));
  160. } else {
  161. INT flags;
  162. //
  163. // If the currently selected file is a link, resolve it first
  164. //
  165. lstrcpy(filename, pSelected);
  166. if (!IsEmptyString(pSelected) &&
  167. (flags = GetSelectedCoverPage(pCPInfo, hwndList, NULL)) > 0 &&
  168. (flags & CPFLAG_LINK) &&
  169. !ResolveShortcut(pSelected, filename))
  170. {
  171. DisplayMessageDialog(hDlg, 0, 0, IDS_RESOLVE_LINK_FAILED, pSelected);
  172. return;
  173. }
  174. //
  175. // Separate the filename into directory and filename components
  176. //
  177. if (pFilename = _tcsrchr(filename, TEXT(PATH_SEPARATOR))) {
  178. *pFilename++ = NUL;
  179. pDirPath = filename;
  180. } else {
  181. pFilename = filename;
  182. pDirPath = NULL;
  183. }
  184. }
  185. //
  186. // Find the "Cover Page Editor" executable
  187. //
  188. if ((pExecutableName = GetCoverPageEditor()) == NULL) {
  189. DisplayMessageDialog(hDlg, 0, 0, IDS_CANNOT_FIND_CPEDITOR);
  190. return;
  191. }
  192. //
  193. // Start cover page editor and wait for it to exit before proceeding
  194. //
  195. shellExeInfo.lpFile = pExecutableName;
  196. shellExeInfo.lpDirectory = pDirPath;
  197. shellExeInfo.lpParameters = MakeQuotedParameterString(pFilename);
  198. DebugPrint((TEXT("Cover page editor: %ws\n"), pExecutableName));
  199. DebugPrint((TEXT("Initial working directory: %ws\n"), pDirPath));
  200. DebugPrint((TEXT("Cover page filename: %ws\n"), shellExeInfo.lpParameters));
  201. // Disable the parent window.
  202. EnableWindow( GetParent(hDlg), FALSE );
  203. if (! ShellExecuteEx(&shellExeInfo)) {
  204. DisplayMessageDialog(hDlg, 0, 0, IDS_CANNOT_OPEN_CPEDITOR, pExecutableName);
  205. MemFree((PVOID)shellExeInfo.lpParameters);
  206. MemFree((PVOID)pExecutableName);
  207. return;
  208. }
  209. //
  210. // Refresh the list of cover page files when we're done
  211. //
  212. MemFree((PVOID)shellExeInfo.lpParameters);
  213. MemFree((PVOID)pExecutableName);
  214. while (TRUE) {
  215. // Wait for multiple objects in case of other messages coming.
  216. WaitObj = MsgWaitForMultipleObjects( 1, &shellExeInfo.hProcess, FALSE, INFINITE, QS_ALLINPUT );
  217. if (WaitObj == WAIT_OBJECT_0)
  218. break;
  219. // PeekMessage instead of GetMessage so we drain the message queue
  220. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE )) {
  221. TranslateMessage( &msg );
  222. DispatchMessage( &msg );
  223. }
  224. }
  225. EnableWindow( GetParent(hDlg), TRUE );
  226. InitCoverPageList(pCPInfo, hDlg);
  227. SetEnvironmentVariable(TEXT("ClientCoverpage"),NULL);
  228. }
  229. VOID
  230. HandleBrowseCoverPage(
  231. HWND hDlg,
  232. PCPDATA pCPInfo,
  233. HWND hwndList,
  234. LPTSTR pSelected
  235. )
  236. /*++
  237. Routine Description:
  238. Remove the currently selected cover page file
  239. Arguments:
  240. hDlg - Handle to the dialog window on which the list of cover pages is displayed
  241. pCPInfo - Points to cover page information
  242. hwndList - Handle to cover page listbox window
  243. pSelected - Currently selected cover page filename
  244. Return Value:
  245. NONE
  246. --*/
  247. {
  248. TCHAR filename[MAX_PATH];
  249. TCHAR title[MAX_TITLE_LEN];
  250. TCHAR filter[MAX_TITLE_LEN];
  251. LPTSTR pExtension, pFilename;
  252. LPTSTR pCPDir;
  253. INT n;
  254. OPENFILENAME ofn = {
  255. sizeof(OPENFILENAME),
  256. hDlg,
  257. ghInstance,
  258. filter,
  259. NULL,
  260. 0,
  261. 1,
  262. filename,
  263. MAX_PATH,
  264. NULL,
  265. 0,
  266. NULL,
  267. title,
  268. OFN_FILEMUSTEXIST | OFN_NODEREFERENCELINKS | OFN_HIDEREADONLY,
  269. 0,
  270. 0,
  271. NULL,
  272. 0,
  273. NULL,
  274. NULL,
  275. };
  276. //
  277. // Figure out what the initial directory should be
  278. //
  279. if (! IsEmptyString(pSelected)) {
  280. INT flags;
  281. //
  282. // Find out if the currently selected cover page file is a
  283. // user cover page and whether it's a link
  284. //
  285. if ((flags = GetSelectedCoverPage(pCPInfo, hwndList, NULL)) > 0 &&
  286. (flags & CPFLAG_LINK) &&
  287. ResolveShortcut(pSelected, filename))
  288. {
  289. //
  290. // Set the initial directory to the link destination
  291. //
  292. _tcscpy(pSelected, filename);
  293. if (pFilename = _tcsrchr(pSelected, TEXT(PATH_SEPARATOR))) {
  294. *pFilename = NUL;
  295. ofn.lpstrInitialDir = pSelected;
  296. }
  297. }
  298. }
  299. //
  300. // Compose the file-type filter string
  301. //
  302. LoadString(ghInstance, IDS_CP_FILETYPE, title, MAX_TITLE_LEN);
  303. wsprintf(filter, TEXT("%s%c*%s%c"), title, NUL, CP_FILENAME_EXT, NUL);
  304. LoadString(ghInstance, IDS_BROWSE_COVERPAGE, title, MAX_TITLE_LEN);
  305. filename[0] = NUL;
  306. //
  307. // Present the "Open File" dialog
  308. //
  309. if (! GetOpenFileName(&ofn))
  310. return;
  311. //
  312. // Make sure the selected filename has the correct extension
  313. //
  314. if ((pExtension = FindFilenameExtension(filename)) == NULL ||
  315. _tcsicmp(pExtension, CP_FILENAME_EXT) != EQUAL_STRING)
  316. {
  317. DisplayMessageDialog(hDlg, 0, 0, IDS_BAD_CP_EXTENSION, CP_FILENAME_EXT);
  318. return;
  319. }
  320. //
  321. // Check if the selected file is already inside one of the
  322. // cover page directories
  323. //
  324. for (n=0; n < pCPInfo->nDirs; n++) {
  325. TCHAR Path[MAX_PATH];
  326. if (_tcslen(pCPInfo->pDirPath[n]) + _tcslen(&filename[ofn.nFileOffset]) >= MAX_PATH) {
  327. DisplayMessageDialog(hDlg, 0, 0, IDS_FILENAME_TOOLONG);
  328. return;
  329. }
  330. _tcscpy(Path, pCPInfo->pDirPath[n]);
  331. _tcscat(Path, &filename[ofn.nFileOffset]);
  332. if (GetFileAttributes(Path) != 0xffffffff) {
  333. DisplayMessageDialog(hDlg, 0, 0, IDS_CP_DUPLICATE, filename);
  334. return;
  335. }
  336. }
  337. //
  338. // Add the selected cover page file to the first cover page directory
  339. // Create the cover page directory if necessary
  340. //
  341. pCPDir = pCPInfo->pDirPath[0];
  342. if (!pCPDir || IsEmptyString(pCPDir)) {
  343. DisplayMessageDialog(hDlg, 0, 0, IDS_NO_COVERPG_DIR);
  344. return;
  345. }
  346. CreateDirectory(pCPDir, NULL);
  347. pFilename = &filename[ofn.nFileOffset];
  348. _tcscpy(pSelected, pCPDir);
  349. n = _tcslen(pSelected);
  350. if (n + _tcslen(pFilename) >= MAX_PATH - MAX_FILENAME_EXT || pFilename >= pExtension) {
  351. DisplayMessageDialog(hDlg, 0, 0, IDS_FILENAME_TOOLONG);
  352. return;
  353. }
  354. _tcsncpy(pSelected + n, pFilename, (INT)(pExtension - pFilename));
  355. n += (INT)(pExtension - pFilename);
  356. if (pCPInfo->serverCP) {
  357. //
  358. // Copy the physical file for server cover pages
  359. //
  360. _tcscpy(pSelected + n, CP_FILENAME_EXT);
  361. if (! CopyFile(filename, pSelected, TRUE)) {
  362. DisplayMessageDialog(hDlg, 0, 0, IDS_COPY_FILE_FAILED, filename, pSelected);
  363. return;
  364. }
  365. } else {
  366. //
  367. // Create the shortcut file for user cover page
  368. //
  369. _tcscpy(pSelected + n, LNK_FILENAME_EXT);
  370. if (GetFileAttributes(pSelected) != 0xffffffff) {
  371. DisplayMessageDialog(hDlg, 0, 0, IDS_CP_DUPLICATE, filename);
  372. return;
  373. }
  374. if (! CreateShortcut(pSelected, filename)) {
  375. DisplayMessageDialog(hDlg, 0, 0, IDS_CREATE_LINK_FAILED, pSelected, filename);
  376. return;
  377. }
  378. }
  379. //
  380. // Refresh the cover page list - we're being lazy here in that
  381. // we reset the entire list content
  382. //
  383. InitCoverPageList(pCPInfo, hDlg);
  384. }
  385. VOID
  386. HandleRemoveCoverPage(
  387. HWND hDlg,
  388. PCPDATA pCPInfo,
  389. HWND hwndList,
  390. LPTSTR pFilename
  391. )
  392. /*++
  393. Routine Description:
  394. Remove the currently selected cover page file
  395. Arguments:
  396. hDlg - Handle to the dialog window on which the list of cover pages is displayed
  397. pCPInfo - Points to cover page information
  398. hwndList - Handle to cover page listbox window
  399. pFilename - Currently selected cover page filename
  400. Return Value:
  401. NONE
  402. --*/
  403. {
  404. //
  405. // Display the confirmation dialog before proceeding
  406. //
  407. if (DisplayMessageDialog(hDlg,
  408. MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2,
  409. IDS_CONFIRM_DELETE,
  410. IDS_DELETE_PROMPT,
  411. pFilename) == IDYES)
  412. {
  413. if (DeleteFile(pFilename)) {
  414. //
  415. // Update the list box if the file is successfully removed
  416. //
  417. INT selIndex, count;
  418. if ((selIndex = (INT)SendMessage(hwndList, LB_GETCURSEL, 0, 0)) != LB_ERR) {
  419. SendMessage(hwndList, LB_DELETESTRING, selIndex, 0);
  420. if ((count = (INT)SendMessage(hwndList, LB_GETCOUNT, 0, 0)) > 0) {
  421. count --;
  422. SendMessage(hwndList, LB_SETCURSEL, min(selIndex, count), 0);
  423. }
  424. }
  425. UpdateCoverPageControls(hDlg);
  426. } else
  427. DisplayMessageDialog(hDlg, 0, 0, IDS_DELETE_FAILED, pFilename);
  428. }
  429. }
  430. VOID
  431. ManageCoverPageList(
  432. HWND hDlg,
  433. PCPDATA pCPInfo,
  434. HWND hwndList,
  435. INT action
  436. )
  437. /*++
  438. Routine Description:
  439. Perform various action to manage the list of cover pages
  440. Arguments:
  441. hDlg - Handle to the dialog window on which the list of cover pages is displayed
  442. pCPInfo - Points to cover page information
  443. hwndList - Handle to cover page listbox window
  444. action - What action to perform on the cover page list
  445. Return Value:
  446. NONE
  447. --*/
  448. {
  449. TCHAR filename[MAX_PATH];
  450. //
  451. // Get the name of currently selected cover page file
  452. //
  453. if (pCPInfo == NULL || hwndList == NULL)
  454. return;
  455. GetSelectedCoverPage(pCPInfo, hwndList, filename);
  456. //
  457. // Call appropriate function depends on the action parameter
  458. //
  459. switch (action) {
  460. case CPACTION_OPEN:
  461. if (IsEmptyString(filename))
  462. break;
  463. case CPACTION_NEW:
  464. HandleOpenCoverPage(hDlg, pCPInfo, hwndList, filename, action);
  465. break;
  466. case CPACTION_BROWSE:
  467. HandleBrowseCoverPage(hDlg, pCPInfo, hwndList, filename);
  468. break;
  469. case CPACTION_REMOVE:
  470. if (! IsEmptyString(filename))
  471. HandleRemoveCoverPage(hDlg, pCPInfo, hwndList, filename);
  472. break;
  473. }
  474. }
  475. VOID
  476. UpdateCoverPageControls(
  477. HWND hDlg
  478. )
  479. /*++
  480. Routine Description:
  481. Enable/disable buttons for manage cover page files
  482. Arguments:
  483. hDlg - Handle to the property page containing the cover page controls
  484. Return Value:
  485. NONE
  486. --*/
  487. {
  488. HWND hwndOpen, hwndRemove;
  489. //
  490. // If all buttons are disabled, leave them alone here
  491. //
  492. if (! IsWindowEnabled(GetDlgItem(hDlg, IDC_COVERPG_NEW)))
  493. return;
  494. hwndOpen = GetDlgItem(hDlg, IDC_COVERPG_OPEN);
  495. hwndRemove = GetDlgItem(hDlg, IDC_COVERPG_REMOVE);
  496. if (SendDlgItemMessage(hDlg, IDC_COVERPG_LIST, LB_GETCURSEL, 0, 0) != LB_ERR) {
  497. EnableWindow(hwndOpen, TRUE);
  498. EnableWindow(hwndRemove, TRUE);
  499. } else {
  500. if (GetFocus() == hwndOpen || GetFocus() == hwndRemove)
  501. SetFocus(GetDlgItem(hDlg, IDC_COVERPG_NEW));
  502. EnableWindow(hwndOpen, FALSE);
  503. EnableWindow(hwndRemove, FALSE);
  504. }
  505. }
  506. VOID
  507. AddCoverPagesToList(
  508. PCPDATA pCPInfo,
  509. HWND hwndList,
  510. INT dirIndex
  511. )
  512. /*++
  513. Routine Description:
  514. Add the cover page files in the specified directory to a list
  515. Arguments:
  516. pCPInfo - Points to cover page information
  517. hwndList - Handle to a list window
  518. dirIndex - Cover page directory index
  519. Return Value:
  520. NONE
  521. --*/
  522. {
  523. WIN32_FIND_DATA findData;
  524. TCHAR filename[MAX_PATH];
  525. HANDLE hFindFile;
  526. LPTSTR pDirPath, pFilename, pExtension;
  527. INT listIndex, dirLen, fileLen, flags;
  528. //
  529. // Copy the directory path to a local buffer
  530. //
  531. flags = dirIndex;
  532. pDirPath = pCPInfo->pDirPath[dirIndex];
  533. if (IsEmptyString(pDirPath))
  534. return;
  535. if ((dirLen = _tcslen(pDirPath)) >= MAX_PATH - MAX_FILENAME_EXT - 1) {
  536. DebugPrint(( TEXT("Directory name too long: %ws\n"), pDirPath));
  537. return;
  538. }
  539. _tcscpy(filename, pDirPath);
  540. //
  541. // Go through the following loop twice:
  542. // Once to add the files with .ncp extension
  543. // Again to add the files with .lnk extension
  544. //
  545. // Don't chase links for server based cover pages
  546. //
  547. do {
  548. //
  549. // Generate a specification for the files we're interested in
  550. //
  551. pFilename = &filename[dirLen];
  552. *pFilename = TEXT('*');
  553. _tcscpy(pFilename+1, (flags & CPFLAG_LINK) ? LNK_FILENAME_EXT : CP_FILENAME_EXT);
  554. //
  555. // Call FindFirstFile/FindNextFile to enumerate the files
  556. // matching our specification
  557. //
  558. hFindFile = FindFirstFile(filename, &findData);
  559. if (hFindFile != INVALID_HANDLE_VALUE) {
  560. do {
  561. //
  562. // Exclude directories and hidden files
  563. //
  564. if (findData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_DIRECTORY))
  565. continue;
  566. //
  567. // Make sure we have enough room to store the full pathname
  568. //
  569. if ((fileLen = _tcslen(findData.cFileName)) <= MAX_FILENAME_EXT)
  570. continue;
  571. if (fileLen + dirLen >= MAX_PATH) {
  572. DebugPrint(( TEXT("Filename too long: %ws%ws\n"), pDirPath, findData.cFileName));
  573. continue;
  574. }
  575. //
  576. // If we're chasing links, make sure the link refers to
  577. // a cover page file.
  578. //
  579. if (flags & CPFLAG_LINK) {
  580. _tcscpy(pFilename, findData.cFileName);
  581. if (! IsCoverPageShortcut(filename))
  582. continue;
  583. }
  584. //
  585. // Don't display the filename extension
  586. //
  587. if (pExtension = FindFilenameExtension(findData.cFileName))
  588. *pExtension = NUL;
  589. //
  590. // Add the cover page name to the list window
  591. //
  592. listIndex = (INT)SendMessage(hwndList,
  593. LB_ADDSTRING,
  594. 0,
  595. (LPARAM) findData.cFileName);
  596. if (listIndex != LB_ERR)
  597. SendMessage(hwndList, LB_SETITEMDATA, listIndex, flags);
  598. } while (FindNextFile(hFindFile, &findData));
  599. FindClose(hFindFile);
  600. }
  601. flags ^= CPFLAG_LINK;
  602. } while ((flags & CPFLAG_LINK) && ! pCPInfo->serverCP);
  603. }
  604. VOID
  605. InitCoverPageList(
  606. PCPDATA pCPInfo,
  607. HWND hDlg
  608. )
  609. /*++
  610. Routine Description:
  611. Generate a list of available cover pages
  612. Arguments:
  613. pCPInfo - Points to cover page information
  614. hDlg - Handle to the dialog window containing cover page list
  615. Return Value:
  616. NONE
  617. --*/
  618. {
  619. HWND hwndList;
  620. INT index, lastSel;
  621. if ((hwndList = GetDlgItem(hDlg, IDC_COVERPG_LIST)) && pCPInfo) {
  622. //
  623. // Disable redraw on the list and reset its content
  624. //
  625. if ((lastSel = (INT)SendMessage(hwndList, LB_GETCURSEL, 0, 0)) == LB_ERR)
  626. lastSel = 0;
  627. SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
  628. SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
  629. //
  630. // Add cover pages to the list
  631. //
  632. for (index=0; index < pCPInfo->nDirs; index++)
  633. AddCoverPagesToList(pCPInfo, hwndList, index);
  634. //
  635. // Highlight the first cover page in the list
  636. //
  637. if ((index = (INT)SendMessage(hwndList, LB_GETCOUNT, 0, 0)) > 0 && lastSel >= index)
  638. lastSel = index - 1;
  639. SendMessage(hwndList, LB_SETCURSEL, lastSel, 0);
  640. //
  641. // Enable redraw on the list window
  642. //
  643. SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
  644. } else if (hwndList) {
  645. SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
  646. }
  647. UpdateCoverPageControls(hDlg);
  648. }
  649. INT
  650. GetSelectedCoverPage(
  651. PCPDATA pCPInfo,
  652. HWND hwndList,
  653. LPTSTR pBuffer
  654. )
  655. /*++
  656. Routine Description:
  657. Retrieve the currently selected cover page filename
  658. Arguments:
  659. pCPInfo - Points to cover page information
  660. hwndList - Handle to the list window
  661. pBuffer - Points to a buffer for storing the selected cover page filename
  662. The size of the buffer is assumed to be MAX_PATH characters.
  663. if pBuffer is NULL, we assume the called is interested in the item flags
  664. Return Value:
  665. Flags associated with the currently selected item
  666. Negative if there is an error
  667. --*/
  668. {
  669. LPTSTR pDirPath;
  670. INT selIndex, itemFlags;
  671. //
  672. // Default to empty string in case of an error
  673. //
  674. if (pBuffer)
  675. pBuffer[0] = NUL;
  676. if (pCPInfo == NULL || hwndList == NULL)
  677. return LB_ERR;
  678. //
  679. // Get currently selected item index
  680. //
  681. if ((selIndex = (INT)SendMessage(hwndList, LB_GETCURSEL, 0, 0)) == LB_ERR)
  682. return selIndex;
  683. //
  684. // Get the flags associated with the currently selected item
  685. //
  686. itemFlags = (INT)SendMessage(hwndList, LB_GETITEMDATA, selIndex, 0);
  687. if (itemFlags == LB_ERR || !pBuffer)
  688. return itemFlags;
  689. Assert((itemFlags & CPFLAG_DIRINDEX) < pCPInfo->nDirs);
  690. pDirPath = pCPInfo->pDirPath[itemFlags & CPFLAG_DIRINDEX];
  691. //
  692. // Assemble the full pathname for the cover page file
  693. // directory prefix
  694. // display name
  695. // filename extension
  696. //
  697. while (*pBuffer++ = *pDirPath++)
  698. NULL;
  699. pBuffer--;
  700. SendMessage(hwndList, LB_GETTEXT, selIndex, (LPARAM) pBuffer);
  701. _tcscat(pBuffer, (itemFlags & CPFLAG_LINK) ? LNK_FILENAME_EXT : CP_FILENAME_EXT);
  702. return itemFlags;
  703. }
  704. VOID
  705. AppendPathSeparator(
  706. LPTSTR pDirPath
  707. )
  708. /*++
  709. Routine Description:
  710. Append a path separator (if necessary) at the end of a directory name
  711. Arguments:
  712. pDirPath - Points to a directory name
  713. Return Value:
  714. NONE
  715. --*/
  716. {
  717. INT length;
  718. //
  719. // Calculate the length of directory string
  720. //
  721. length = _tcslen(pDirPath);
  722. if (length >= MAX_PATH-1 || length < 1)
  723. return;
  724. //
  725. // If the last character is not a path separator,
  726. // append a path separator at the end
  727. //
  728. if (pDirPath[length-1] != TEXT(PATH_SEPARATOR)) {
  729. pDirPath[length] = TEXT(PATH_SEPARATOR);
  730. pDirPath[length+1] = NUL;
  731. }
  732. }
  733. PCPDATA
  734. AllocCoverPageInfo(
  735. )
  736. /*++
  737. Routine Description:
  738. Allocate memory to hold cover page information
  739. Arguments:
  740. hPrinter - Handle to a printer object if serverCP is TRUE
  741. Return Value:
  742. Pointer to a CPDATA structure, NULL if there is an error
  743. NOTE:
  744. Put this inside a critical section is the caller is concerned about
  745. being thread safe.
  746. --*/
  747. {
  748. PCPDATA pCPInfo;
  749. INT nDirs;
  750. LPTSTR pDirPath, pUserCPDir, pSavedPtr;
  751. if (pCPInfo = MemAlloc(sizeof(CPDATA))) {
  752. ZeroMemory(pCPInfo,sizeof(CPDATA));
  753. if ( (pUserCPDir = MemAlloc(MAX_PATH)) && (pSavedPtr = pUserCPDir) && (GetClientCpDir(pUserCPDir,MAX_PATH)) ) {
  754. //
  755. // Find the directory in which the user cover pages are stored
  756. //
  757. while (*pUserCPDir && pCPInfo->nDirs < MAX_COVERPAGE_DIRS) {
  758. LPTSTR pNextDir = pUserCPDir;
  759. //
  760. // Find the next semicolon character
  761. //
  762. while (*pNextDir && *pNextDir != TEXT(';'))
  763. pNextDir++;
  764. if (*pNextDir != NUL)
  765. *pNextDir++ = NUL;
  766. //
  767. // Make sure the directory name is not too long
  768. //
  769. if (_tcslen(pUserCPDir) < MAX_PATH) {
  770. if (! (pDirPath = AllocStringZ(MAX_PATH)))
  771. break;
  772. pCPInfo->pDirPath[pCPInfo->nDirs++] = pDirPath;
  773. _tcscpy(pDirPath, pUserCPDir);
  774. }
  775. pUserCPDir = pNextDir;
  776. }
  777. MemFree(pSavedPtr);
  778. }
  779. //
  780. // Append path separators at the end if necessary
  781. //
  782. for (nDirs=0; nDirs < pCPInfo->nDirs; nDirs++) {
  783. AppendPathSeparator(pCPInfo->pDirPath[nDirs]);
  784. DebugPrint(( TEXT("Cover page directory: %ws\n"), pCPInfo->pDirPath[nDirs]));
  785. }
  786. }
  787. return pCPInfo;
  788. }
  789. VOID
  790. FreeCoverPageInfo(
  791. PCPDATA pCPInfo
  792. )
  793. /*++
  794. Routine Description:
  795. Free up memory used for cover page information
  796. Arguments:
  797. pCPInfo - Points to cover page information to be freed
  798. Return Value:
  799. NONE
  800. --*/
  801. {
  802. if (pCPInfo) {
  803. INT index;
  804. for (index=0; index < pCPInfo->nDirs; index++)
  805. MemFree(pCPInfo->pDirPath[index]);
  806. MemFree(pCPInfo);
  807. }
  808. }
  809. LPTSTR
  810. MakeQuotedParameterString(
  811. LPTSTR pInputStr
  812. )
  813. /*++
  814. Routine Description:
  815. Make a copy of the input string and make sure it's in the same form
  816. as expected by SHELLEXECUTEINFO.lpParameters.
  817. Arguments:
  818. pInputStr - Specifies the input string
  819. Return Value:
  820. Pointer to the processed parameter string
  821. --*/
  822. #define QUOTE TEXT('"')
  823. {
  824. LPTSTR pStr, pDestStr;
  825. INT length;
  826. //
  827. // Special case: if the input string is NULL, simply return NULL
  828. //
  829. if (pInputStr == NULL)
  830. return NULL;
  831. //
  832. // Figure out how long the resulting string is.
  833. // Initial value is 3 = two extra quotes plus NUL terminator.
  834. //
  835. for (pStr=pInputStr, length=3; *pStr; pStr++)
  836. length += (*pStr == QUOTE) ? 3 : 1;
  837. //
  838. // Copy the input string and replace quote characters
  839. //
  840. if (pStr = pDestStr = MemAlloc(length * sizeof(TCHAR))) {
  841. *pStr++ = QUOTE;
  842. while (*pInputStr) {
  843. if ((*pStr++ = *pInputStr++) == QUOTE) {
  844. *pStr++ = QUOTE;
  845. *pStr++ = QUOTE;
  846. }
  847. }
  848. *pStr++ = QUOTE;
  849. *pStr = NUL;
  850. }
  851. return pDestStr;
  852. }
  853. LPTSTR GetCoverPageEditor()
  854. {
  855. LPTSTR Location;
  856. HKEY hKey = OpenRegistryKey(HKEY_CURRENT_USER,REGKEY_FAX_SETUP,TRUE,0);
  857. if (hKey == NULL) {
  858. return NULL;
  859. }
  860. Location = GetRegistryStringExpand(hKey,REGVAL_CP_EDITOR,DEFAULT_COVERPAGE_EDITOR);
  861. RegCloseKey(hKey);
  862. return Location;
  863. }