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.

780 lines
16 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. coverpg.c
  5. Abstract:
  6. Functions for working with cover pages
  7. Environment:
  8. Windows NT fax driver user interface
  9. Revision History:
  10. 02/05/96 -davidx-
  11. Created it.
  12. mm/dd/yy -author-
  13. description
  14. --*/
  15. #include "faxui.h"
  16. #include <shlobj.h>
  17. #include <shellapi.h>
  18. #include <commdlg.h>
  19. //
  20. // Suffix string appended to all user cover page filenames
  21. //
  22. static TCHAR PersonalSuffixStr[64];
  23. VOID
  24. InsertOneCoverPageFilenameToList(
  25. HWND hwndList,
  26. LPTSTR pFilename,
  27. INT flags
  28. )
  29. /*++
  30. Routine Description:
  31. Insert one cover page filename into the list of cover pages
  32. Arguments:
  33. hwndList - Handle to list window
  34. pFilename - Name of the cover page file
  35. flags - Flags to be associated with the list item
  36. Return Value:
  37. NONE
  38. --*/
  39. {
  40. INT listIndex;
  41. LPTSTR pBuffer = NULL;
  42. //
  43. // Add " (Personal)" suffix to all user cover pages
  44. //
  45. if ((flags & CPFLAG_SERVERCP) == 0) {
  46. if (IsEmptyString(PersonalSuffixStr))
  47. LoadString(ghInstance, IDS_USERCP_SUFFIX, PersonalSuffixStr, 64);
  48. if (pBuffer = MemAlloc(SizeOfString(pFilename) + SizeOfString(PersonalSuffixStr))) {
  49. _tcscpy(pBuffer, pFilename);
  50. _tcscat(pBuffer, PersonalSuffixStr);
  51. flags |= CPFLAG_SUFFIX;
  52. pFilename = pBuffer;
  53. }
  54. }
  55. //
  56. // Insert the cover page filename into the list
  57. //
  58. listIndex = (INT)SendMessage(hwndList, CB_ADDSTRING, 0, (LPARAM) pFilename);
  59. if (listIndex != CB_ERR)
  60. SendMessage(hwndList, CB_SETITEMDATA, listIndex, flags);
  61. MemFree(pBuffer);
  62. }
  63. VOID
  64. AddCoverPagesToList(
  65. PCPDATA pCPInfo,
  66. HWND hwndList,
  67. LPTSTR pSelected,
  68. INT nDirs
  69. )
  70. /*++
  71. Routine Description:
  72. Add the cover page files in the specified directory to a list
  73. Arguments:
  74. pCPInfo - Points to cover page information
  75. hwndList - Handle to a list window
  76. pSelected - Currently selected cover page
  77. nDirs - Cover page directory index
  78. Return Value:
  79. NONE
  80. --*/
  81. {
  82. WIN32_FIND_DATA findData;
  83. TCHAR filename[MAX_PATH];
  84. HANDLE hFindFile;
  85. LPTSTR pDirPath, pFilename, pExtension;
  86. INT dirLen, fileLen, flags;
  87. //
  88. // Are we working on server or user cover pages?
  89. //
  90. flags = nDirs | ((nDirs < pCPInfo->nServerDirs) ? CPFLAG_SERVERCP : 0);
  91. pDirPath = pCPInfo->pDirPath[nDirs];
  92. if (IsEmptyString(pDirPath))
  93. return;
  94. //
  95. // Look at the directory prefix of the currently selected cover page file
  96. //
  97. if ((dirLen = _tcslen(pDirPath)) >= MAX_PATH - MAX_FILENAME_EXT - 1) {
  98. Error(("Directory name too long: %ws\n", pDirPath));
  99. return;
  100. }
  101. _tcscpy(filename, pDirPath);
  102. if (_tcsnicmp(pDirPath, pSelected, dirLen) != EQUAL_STRING)
  103. pSelected = NULL;
  104. else
  105. pSelected += dirLen;
  106. //
  107. // Go through the following loop twice:
  108. // Once to add the files with .ncp extension
  109. // Again to add the files with .lnk extension
  110. //
  111. // Don't chase links for server based cover pages
  112. //
  113. do {
  114. //
  115. // Generate a specification for the files we're interested in
  116. //
  117. pFilename = &filename[dirLen];
  118. *pFilename = TEXT('*');
  119. _tcscpy(pFilename+1, (flags & CPFLAG_LINK) ? LNK_FILENAME_EXT : CP_FILENAME_EXT);
  120. //
  121. // Call FindFirstFile/FindNextFile to enumerate the files
  122. // matching our specification
  123. //
  124. hFindFile = FindFirstFile(filename, &findData);
  125. if (hFindFile != INVALID_HANDLE_VALUE) {
  126. do {
  127. //
  128. // Exclude directories and hidden files
  129. //
  130. if (findData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_DIRECTORY))
  131. continue;
  132. //
  133. // Make sure we have enough room to store the full pathname
  134. //
  135. if ((fileLen = _tcslen(findData.cFileName)) <= MAX_FILENAME_EXT)
  136. continue;
  137. if (fileLen + dirLen >= MAX_PATH) {
  138. Error(("Filename too long: %ws%ws\n", pDirPath, findData.cFileName));
  139. continue;
  140. }
  141. //
  142. // If we're chasing links, make sure the link refers to
  143. // a cover page file.
  144. //
  145. if (flags & CPFLAG_LINK) {
  146. _tcscpy(pFilename, findData.cFileName);
  147. if (! IsCoverPageShortcut(filename))
  148. continue;
  149. }
  150. //
  151. // Compare with the currently selected cover page filename
  152. //
  153. if (pSelected && _tcsicmp(pSelected, findData.cFileName) == EQUAL_STRING) {
  154. pSelected = NULL;
  155. flags |= CPFLAG_SELECTED;
  156. } else
  157. flags &= ~CPFLAG_SELECTED;
  158. //
  159. // Don't display the filename extension
  160. //
  161. if (pExtension = _tcsrchr(findData.cFileName, TEXT(FILENAME_EXT))) {
  162. *pExtension = NUL;
  163. }
  164. //
  165. // Add the cover page name to the list window
  166. //
  167. InsertOneCoverPageFilenameToList(hwndList, findData.cFileName, flags);
  168. } while (FindNextFile(hFindFile, &findData));
  169. FindClose(hFindFile);
  170. }
  171. flags ^= CPFLAG_LINK;
  172. } while ((flags & CPFLAG_LINK) && ! (flags & CPFLAG_SERVERCP));
  173. }
  174. VOID
  175. InitCoverPageList(
  176. PCPDATA pCPInfo,
  177. HWND hwndList,
  178. LPTSTR pSelectedCoverPage
  179. )
  180. /*++
  181. Routine Description:
  182. Generate a list of available cover pages (both server and user)
  183. Arguments:
  184. pCPInfo - Points to cover page information
  185. hwndList - Handle to the list window
  186. pSelectedCoverPage - Name of currently selected cover page file
  187. Return Value:
  188. NONE
  189. --*/
  190. {
  191. INT itemFlags, index;
  192. //
  193. // Validate input parameters
  194. //
  195. if (pCPInfo == NULL || hwndList == NULL)
  196. return;
  197. //
  198. // Disable redraw on the list and reset its content
  199. //
  200. SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
  201. SendMessage(hwndList, CB_RESETCONTENT, FALSE, 0);
  202. //
  203. // Add server and user cover pages to the list
  204. //
  205. for (index=0; index < pCPInfo->nDirs; index++)
  206. AddCoverPagesToList(pCPInfo, hwndList, pSelectedCoverPage, index);
  207. //
  208. // Highlight the currently selected cover page
  209. //
  210. index = (INT)SendMessage(hwndList, CB_GETCOUNT, 0, 0);
  211. if (index > 0) {
  212. //
  213. // Go through each list item and check if it should be selected
  214. //
  215. while (--index >= 0) {
  216. itemFlags = (INT)SendMessage(hwndList, CB_GETITEMDATA, index, 0);
  217. if (itemFlags != CB_ERR && (itemFlags & CPFLAG_SELECTED)) {
  218. SendMessage(hwndList, CB_SETCURSEL, index, 0);
  219. break;
  220. }
  221. }
  222. //
  223. // If nothing is selected, select the first item by default
  224. //
  225. if (index < 0)
  226. SendMessage(hwndList, CB_SETCURSEL, 0, 0);
  227. }
  228. //
  229. // Enable redraw on the list window
  230. //
  231. SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
  232. }
  233. INT
  234. GetSelectedCoverPage(
  235. PCPDATA pCPInfo,
  236. HWND hwndList,
  237. LPTSTR pBuffer
  238. )
  239. /*++
  240. Routine Description:
  241. Retrieve the currently selected cover page name
  242. Arguments:
  243. pCPInfo - Points to cover page information
  244. hwndList - Handle to the list window
  245. pBuffer - Points to a buffer for storing the selected cover page filename
  246. The size of the buffer is assumed to be MAX_PATH characters.
  247. if pBuffer is NULL, we assume the called is interested in the item flags
  248. Return Value:
  249. Flags associated with the currently selected item
  250. Negative if there is an error
  251. --*/
  252. {
  253. LPTSTR pDirPath, pFilename;
  254. INT selIndex, itemFlags, nameLen;
  255. //
  256. // Default to empty string in case of an error
  257. //
  258. if (pBuffer)
  259. pBuffer[0] = NUL;
  260. if (pCPInfo == NULL || hwndList == NULL)
  261. return CB_ERR;
  262. //
  263. // Get currently selected item index
  264. //
  265. if ((selIndex = (INT)SendMessage(hwndList, CB_GETCURSEL, 0, 0)) == CB_ERR)
  266. return selIndex;
  267. //
  268. // Get the flags associated with the currently selected item
  269. //
  270. itemFlags = (INT)SendMessage(hwndList, CB_GETITEMDATA, selIndex, 0);
  271. if (itemFlags != CB_ERR && pBuffer != NULL) {
  272. Assert((itemFlags & CPFLAG_DIRINDEX) < pCPInfo->nDirs);
  273. pDirPath = pCPInfo->pDirPath[itemFlags & CPFLAG_DIRINDEX];
  274. //
  275. // Assemble the full pathname for the cover page file
  276. // directory prefix
  277. // display name
  278. // filename extension
  279. //
  280. while (*pBuffer++ = *pDirPath++)
  281. NULL;
  282. pBuffer--;
  283. pFilename = NULL;
  284. if ((nameLen = (INT)SendMessage(hwndList, CB_GETLBTEXTLEN, selIndex, 0)) != CB_ERR &&
  285. (pFilename = MemAlloc(sizeof(TCHAR) * (nameLen + 1))) &&
  286. SendMessage(hwndList, CB_GETLBTEXT, selIndex, (LPARAM) pFilename) != CB_ERR)
  287. {
  288. //
  289. // If the cover page filename has a suffix, we need to remove it first
  290. //
  291. if (itemFlags & CPFLAG_SUFFIX) {
  292. INT suffixLen = _tcslen(PersonalSuffixStr);
  293. if (nameLen >= suffixLen &&
  294. _tcscmp(pFilename + (nameLen - suffixLen), PersonalSuffixStr) == EQUAL_STRING)
  295. {
  296. *(pFilename + (nameLen - suffixLen)) = NUL;
  297. } else
  298. Error(("Corrupted cover page filename: %ws\n", pFilename));
  299. }
  300. _tcscpy(pBuffer, pFilename);
  301. _tcscat(pBuffer, (itemFlags & CPFLAG_LINK) ? LNK_FILENAME_EXT : CP_FILENAME_EXT);
  302. } else
  303. itemFlags = CB_ERR;
  304. MemFree(pFilename);
  305. }
  306. return itemFlags;
  307. }
  308. BOOL
  309. GetServerCoverPageDirs(
  310. HANDLE hPrinter,
  311. PCPDATA pCPInfo
  312. )
  313. /*++
  314. Routine Description:
  315. Find the directories in which the server cover pages are stored
  316. Arguments:
  317. hPrinter - Handle to a printer object
  318. pCPInfo - Points to cover page information
  319. Return Value:
  320. TRUE if successful, FALSE otherwise
  321. --*/
  322. {
  323. PPRINTER_INFO_2 pPrinterInfo2;
  324. BOOL status = FALSE;
  325. LPTSTR pServerDir = NULL;
  326. LPTSTR pServerSubDir, p;
  327. //
  328. // Find the name of the print server - We really would like to use
  329. // level 4 instead of level 2 here. But GetPrinter returns error for
  330. // remote printers.
  331. //
  332. if (! (pPrinterInfo2 = MyGetPrinter(hPrinter, 2)))
  333. return FALSE;
  334. if ( !(pServerDir = MemAlloc(sizeof(TCHAR) * MAX_PATH)) ||
  335. !GetServerCpDir(pPrinterInfo2->pServerName,pServerDir,MAX_PATH*sizeof(TCHAR)) ) {
  336. goto exit;
  337. }
  338. pCPInfo->pDirPath[pCPInfo->nDirs] = pServerDir;
  339. pCPInfo->nDirs += 1;
  340. pCPInfo->nServerDirs += 1;
  341. status = TRUE;
  342. //
  343. // Find a subdirectory for the specified printer
  344. //
  345. if (p = _tcsrchr(pPrinterInfo2->pPrinterName, TEXT(PATH_SEPARATOR)))
  346. p++;
  347. else
  348. p = pPrinterInfo2->pPrinterName;
  349. if ((_tcslen(pServerDir) + _tcslen(p) < MAX_PATH) &&
  350. (pServerSubDir = MemAlloc(sizeof(TCHAR) * MAX_PATH)))
  351. {
  352. _tcscpy(pServerSubDir, pServerDir);
  353. ConcatenatePaths(pServerSubDir, p);
  354. pCPInfo->pDirPath[pCPInfo->nDirs] = pServerSubDir;
  355. pCPInfo->nDirs += 1;
  356. pCPInfo->nServerDirs += 1;
  357. }
  358. //
  359. // Clean up before returning to caller
  360. //
  361. exit:
  362. if (!status) {
  363. MemFree(pServerDir);
  364. }
  365. MemFree( pPrinterInfo2 );
  366. return status;
  367. }
  368. VOID
  369. AppendPathSeparator(
  370. LPTSTR pDirPath
  371. )
  372. /*++
  373. Routine Description:
  374. Append a path separator (if necessary) at the end of a directory name
  375. Arguments:
  376. pDirPath - Points to a directory name
  377. Return Value:
  378. NONE
  379. --*/
  380. {
  381. INT length;
  382. //
  383. // Calculate the length of directory string
  384. //
  385. length = _tcslen(pDirPath);
  386. if (length >= MAX_PATH-1 || length < 1)
  387. return;
  388. //
  389. // If the last character is not a path separator,
  390. // append a path separator at the end
  391. //
  392. if (pDirPath[length-1] != TEXT(PATH_SEPARATOR)) {
  393. pDirPath[length] = TEXT(PATH_SEPARATOR);
  394. pDirPath[length+1] = NUL;
  395. }
  396. }
  397. BOOL
  398. UseServerCp(
  399. HANDLE hPrinter
  400. )
  401. {
  402. PPRINTER_INFO_2 pPrinterInfo2 = NULL;
  403. HANDLE FaxHandle = NULL;
  404. PFAX_CONFIGURATION FaxConfig = NULL;
  405. BOOL Rval = FALSE;
  406. HMODULE hMod = NULL;
  407. PFAXCONNECTFAXSERVERW pFaxConnectFaxServer;
  408. PFAXCLOSE pFaxClose;
  409. PFAXFREEBUFFER pFaxFreeBuffer;
  410. PFAXGETCONFIGURATIONW pFaxGetConfiguration;
  411. hMod = LoadLibrary( L"winfax.dll" );
  412. if (hMod == NULL) {
  413. return FALSE;
  414. }
  415. pFaxConnectFaxServer = (PFAXCONNECTFAXSERVER) GetProcAddress( hMod, "FaxConnectFaxServerW" );
  416. pFaxClose = (PFAXCLOSE) GetProcAddress( hMod, "FaxClose" );
  417. pFaxFreeBuffer = (PFAXFREEBUFFER) GetProcAddress( hMod, "FaxFreeBuffer" );
  418. pFaxGetConfiguration = (PFAXGETCONFIGURATIONW) GetProcAddress( hMod, "FaxGetConfigurationW" );
  419. if (pFaxConnectFaxServer == NULL || pFaxClose == NULL || pFaxFreeBuffer == NULL || pFaxGetConfiguration == NULL) {
  420. FreeLibrary( hMod );
  421. return FALSE;
  422. }
  423. if (! (pPrinterInfo2 = MyGetPrinter(hPrinter, 2))) {
  424. goto exit;
  425. }
  426. if (!pFaxConnectFaxServer( pPrinterInfo2->pServerName, &FaxHandle )) {
  427. goto exit;
  428. }
  429. if (!pFaxGetConfiguration( FaxHandle, &FaxConfig )) {
  430. goto exit;
  431. }
  432. Rval = FaxConfig->ServerCp;
  433. exit:
  434. if (pPrinterInfo2) {
  435. MemFree( pPrinterInfo2 );
  436. }
  437. if (FaxConfig) {
  438. pFaxFreeBuffer( FaxConfig );
  439. }
  440. if (FaxHandle) {
  441. pFaxClose( FaxHandle );
  442. }
  443. return Rval;
  444. }
  445. PCPDATA
  446. AllocCoverPageInfo(
  447. HANDLE hPrinter,
  448. BOOL ServerCpOnly
  449. )
  450. /*++
  451. Routine Description:
  452. Allocate memory to hold cover page information
  453. Arguments:
  454. hPrinter - Handle to a printer object
  455. Return Value:
  456. Pointer to a CPDATA structure, NULL if there is an error
  457. --*/
  458. {
  459. PCPDATA pCPInfo;
  460. INT nDirs;
  461. LPTSTR pDirPath, pUserCPDir, pSavedPtr;
  462. if (pCPInfo = MemAllocZ(sizeof(CPDATA))) {
  463. //
  464. // Find the directory in which the server cover pages are stored
  465. //
  466. if (! GetServerCoverPageDirs(hPrinter, pCPInfo))
  467. Error(("Couldn't get server cover page directories\n"));
  468. //
  469. // Find the directory in which the user cover pages are stored
  470. //
  471. if (ServerCpOnly == FALSE &&
  472. (pUserCPDir = pSavedPtr = GetUserCoverPageDir()))
  473. {
  474. while (*pUserCPDir && pCPInfo->nDirs < MAX_COVERPAGE_DIRS) {
  475. LPTSTR pNextDir = pUserCPDir;
  476. //
  477. // Find the next semicolon character
  478. //
  479. while (*pNextDir && *pNextDir != TEXT(';'))
  480. pNextDir++;
  481. if (*pNextDir != NUL)
  482. *pNextDir++ = NUL;
  483. //
  484. // Make sure the directory name is not too long
  485. //
  486. if (_tcslen(pUserCPDir) < MAX_PATH) {
  487. if (! (pDirPath = MemAlloc(sizeof(TCHAR) * MAX_PATH)))
  488. break;
  489. pCPInfo->pDirPath[pCPInfo->nDirs++] = pDirPath;
  490. _tcscpy(pDirPath, pUserCPDir);
  491. }
  492. pUserCPDir = pNextDir;
  493. }
  494. MemFree(pSavedPtr);
  495. }
  496. //
  497. // Append path separators at the end if necessary
  498. //
  499. for (nDirs=0; nDirs < pCPInfo->nDirs; nDirs++) {
  500. AppendPathSeparator(pCPInfo->pDirPath[nDirs]);
  501. Verbose(("Cover page directory: %ws\n", pCPInfo->pDirPath[nDirs]));
  502. }
  503. }
  504. return pCPInfo;
  505. }
  506. VOID
  507. FreeCoverPageInfo(
  508. PCPDATA pCPInfo
  509. )
  510. /*++
  511. Routine Description:
  512. Free up memory used for cover page information
  513. Arguments:
  514. pCPInfo - Points to cover page information to be freed
  515. Return Value:
  516. NONE
  517. --*/
  518. {
  519. if (pCPInfo) {
  520. INT index;
  521. for (index=0; index < pCPInfo->nDirs; index++)
  522. MemFree(pCPInfo->pDirPath[index]);
  523. MemFree(pCPInfo);
  524. }
  525. }