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.

824 lines
18 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 XP fax driver user interface
  9. Revision History:
  10. 02/05/96 -davidx-
  11. Created it.
  12. 10/20/99 -danl-
  13. Get server name properly in GetServerCoverPageDirs.
  14. mm/dd/yy -author-
  15. description
  16. --*/
  17. #include "faxui.h"
  18. #include <faxreg.h>
  19. #include <shlobj.h>
  20. #include <shellapi.h>
  21. #include <commdlg.h>
  22. #include "faxutil.h"
  23. #define STRSAFE_NO_DEPRECATE
  24. #include <strsafe.h>
  25. //
  26. // Suffix string appended to all user cover page filenames
  27. //
  28. static TCHAR PersonalSuffixStr[64];
  29. VOID
  30. InsertOneCoverPageFilenameToList(
  31. HWND hwndList,
  32. LPTSTR pFilename,
  33. INT flags
  34. )
  35. /*++
  36. Routine Description:
  37. Insert one cover page filename into the list of cover pages
  38. Arguments:
  39. hwndList - Handle to list window
  40. pFilename - Name of the cover page file
  41. flags - Flags to be associated with the list item
  42. Return Value:
  43. NONE
  44. --*/
  45. {
  46. INT listIndex;
  47. LPTSTR pBuffer = NULL;
  48. //
  49. // Add " (Personal)" suffix to all user cover pages
  50. //
  51. if ((flags & CPFLAG_SERVERCP) == 0) {
  52. if (IsEmptyString(PersonalSuffixStr))
  53. {
  54. if(!LoadString(g_hResource, IDS_USERCP_SUFFIX, PersonalSuffixStr, 64))
  55. {
  56. Assert(FALSE);
  57. }
  58. }
  59. if (pBuffer = MemAlloc(SizeOfString(pFilename) + SizeOfString(PersonalSuffixStr)))
  60. {
  61. _tcscpy(pBuffer, pFilename);
  62. _tcscat(pBuffer, PersonalSuffixStr);
  63. flags |= CPFLAG_SUFFIX;
  64. pFilename = pBuffer;
  65. }
  66. }
  67. //
  68. // Insert the cover page filename into the list
  69. //
  70. listIndex = (INT)SendMessage(hwndList, CB_ADDSTRING, 0, (LPARAM) pFilename);
  71. if (listIndex != CB_ERR)
  72. SendMessage(hwndList, CB_SETITEMDATA, listIndex, flags);
  73. MemFree(pBuffer);
  74. }
  75. VOID
  76. AddCoverPagesToList(
  77. PCPDATA pCPInfo,
  78. HWND hwndList,
  79. LPTSTR pSelected,
  80. INT nDirs
  81. )
  82. /*++
  83. Routine Description:
  84. Add the cover page files in the specified directory to a list
  85. Arguments:
  86. pCPInfo - Points to cover page information
  87. hwndList - Handle to a list window
  88. pSelected - Currently selected cover page
  89. nDirs - Cover page directory index
  90. Return Value:
  91. NONE
  92. --*/
  93. {
  94. WIN32_FIND_DATA findData;
  95. TCHAR filename[MAX_PATH];
  96. HANDLE hFindFile;
  97. LPTSTR pDirPath, pExtension;
  98. INT dirLen, fileLen, flags;
  99. TCHAR tszPathName[MAX_PATH] = {0};
  100. TCHAR* pPathEnd;
  101. //
  102. // Are we working on server or user cover pages?
  103. //
  104. flags = nDirs | ((nDirs < pCPInfo->nServerDirs) ? CPFLAG_SERVERCP : 0);
  105. pDirPath = pCPInfo->pDirPath[nDirs];
  106. if (IsEmptyString(pDirPath))
  107. return;
  108. _tcsncpy(tszPathName, pDirPath, ARR_SIZE(tszPathName)-1);
  109. tszPathName[ARR_SIZE(tszPathName) - 1] = TEXT('\0');
  110. pPathEnd = _tcschr(tszPathName, '\0');
  111. //
  112. // Look at the directory prefix of the currently selected cover page file
  113. //
  114. if ((dirLen = _tcslen(pDirPath)) >= MAX_PATH - MAX_FILENAME_EXT - 1)
  115. {
  116. Error(("Directory name too long: %ws\n", pDirPath));
  117. return;
  118. }
  119. _tcscpy(filename, pDirPath);
  120. if (!pSelected || _tcsnicmp(pDirPath, pSelected, dirLen) != EQUAL_STRING)
  121. {
  122. pSelected = NULL;
  123. }
  124. else
  125. {
  126. pSelected += dirLen;
  127. }
  128. //
  129. // Generate a specification for the files we're interested in
  130. //
  131. _tcscat(filename, FAX_COVER_PAGE_MASK);
  132. //
  133. // Call FindFirstFile/FindNextFile to enumerate the files
  134. // matching our specification
  135. //
  136. hFindFile = FindFirstFile(filename, &findData);
  137. if (hFindFile == INVALID_HANDLE_VALUE)
  138. {
  139. return;
  140. }
  141. do
  142. {
  143. //
  144. // Exclude directories and hidden files
  145. //
  146. if (findData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY))
  147. continue;
  148. //
  149. // Make sure we have enough room to store the full pathname
  150. //
  151. if ((fileLen = _tcslen(findData.cFileName)) <= MAX_FILENAME_EXT)
  152. continue;
  153. if (fileLen + dirLen >= MAX_PATH)
  154. {
  155. Error(("Filename too long: %ws%ws\n", pDirPath, findData.cFileName));
  156. continue;
  157. }
  158. //
  159. // Compare with the currently selected cover page filename
  160. //
  161. if (pSelected && _tcsicmp(pSelected, findData.cFileName) == EQUAL_STRING)
  162. {
  163. pSelected = NULL;
  164. flags |= CPFLAG_SELECTED;
  165. }
  166. else
  167. {
  168. flags &= ~CPFLAG_SELECTED;
  169. }
  170. _tcsncpy(pPathEnd, findData.cFileName, MAX_PATH - dirLen);
  171. if(!IsValidCoverPage(tszPathName))
  172. {
  173. continue;
  174. }
  175. //
  176. // Don't display the filename extension
  177. //
  178. if (pExtension = _tcsrchr(findData.cFileName, TEXT(FILENAME_EXT))) {
  179. *pExtension = NUL;
  180. }
  181. //
  182. // Add the cover page name to the list window
  183. //
  184. InsertOneCoverPageFilenameToList(hwndList, findData.cFileName, flags);
  185. } while (FindNextFile(hFindFile, &findData));
  186. FindClose(hFindFile);
  187. }
  188. VOID
  189. InitCoverPageList(
  190. PCPDATA pCPInfo,
  191. HWND hwndList,
  192. LPTSTR pSelectedCoverPage
  193. )
  194. /*++
  195. Routine Description:
  196. Generate a list of available cover pages (both server and user)
  197. Arguments:
  198. pCPInfo - Points to cover page information
  199. hwndList - Handle to the list window
  200. pSelectedCoverPage - Name of currently selected cover page file
  201. Return Value:
  202. NONE
  203. --*/
  204. {
  205. INT itemFlags, index;
  206. //
  207. // Validate input parameters
  208. //
  209. if (pCPInfo == NULL || hwndList == NULL)
  210. return;
  211. //
  212. // Disable redraw on the list and reset its content
  213. //
  214. SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
  215. SendMessage(hwndList, CB_RESETCONTENT, FALSE, 0);
  216. //
  217. // Add server and user cover pages to the list
  218. //
  219. for (index=0; index < pCPInfo->nDirs; index++)
  220. AddCoverPagesToList(pCPInfo, hwndList, pSelectedCoverPage, index);
  221. //
  222. // Highlight the currently selected cover page
  223. //
  224. index = (INT)SendMessage(hwndList, CB_GETCOUNT, 0, 0);
  225. if (index > 0) {
  226. //
  227. // Go through each list item and check if it should be selected
  228. //
  229. while (--index >= 0) {
  230. itemFlags = (INT)SendMessage(hwndList, CB_GETITEMDATA, index, 0);
  231. if (itemFlags != CB_ERR && (itemFlags & CPFLAG_SELECTED)) {
  232. SendMessage(hwndList, CB_SETCURSEL, index, 0);
  233. break;
  234. }
  235. }
  236. //
  237. // If nothing is selected, select the first item by default
  238. //
  239. if (index < 0)
  240. SendMessage(hwndList, CB_SETCURSEL, 0, 0);
  241. }
  242. //
  243. // Enable redraw on the list window
  244. //
  245. SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
  246. }
  247. INT
  248. GetSelectedCoverPage(
  249. PCPDATA pCPInfo,
  250. IN HWND hwndList,
  251. OUT LPTSTR lptstrFullPath,
  252. IN UINT cchstrFullPath,
  253. OUT LPTSTR lptstrFileName,
  254. IN UINT cchstrFileName,
  255. OUT BOOL * pbIsServerPage
  256. )
  257. /*++
  258. Routine Description:
  259. Retrieves the currently selected cover page name and returns its flags.
  260. Provides both its full path and short name and indicates if it is a server cover page or not.
  261. If the cover page is a personal cover page the returned cover page name is a full path to it.
  262. If the cover page is a server cover page the returned cover page is just the file name.
  263. Arguments:
  264. pCPInfo - Points to cover page information
  265. hwndList - Handle to the list window
  266. lptstrFullPath - Points to a buffer for storing the selected cover page full path.
  267. if lptstrFullPath is NULL the full path is not returned.
  268. cchstrFullPath - The size of lptstrFullPath in TCHARs.
  269. lptstrFileName - Points to a buffer for storing the selected cover page file name.
  270. This parameter can be NULL in which case the file name will not be provided.
  271. cchstrFileName - The size of lptstrFileName in TCHARs.
  272. pbIsServerPage - Points to a BOOL variable that is set to TRUE if the selected cover page is a server cover page.
  273. Return Value:
  274. Flags associated with the currently selected item
  275. Negative (CB_ERR) if there is an error or the CB is empty (no *.COV files)
  276. --*/
  277. {
  278. LPTSTR pDirPath, pFilename;
  279. INT selIndex, itemFlags, nameLen;
  280. HRESULT hRc = E_FAIL;
  281. //
  282. // Default to empty string in case of an error
  283. //
  284. if (lptstrFullPath) {
  285. lptstrFullPath[0] = NUL;
  286. }
  287. if (lptstrFileName) {
  288. lptstrFileName[0]=NUL;
  289. }
  290. if (pCPInfo == NULL || hwndList == NULL) {
  291. return CB_ERR;
  292. }
  293. //
  294. // Get currently selected item index
  295. //
  296. // It's possible if there is no item in the combo-box (in case there are no *.COV files)
  297. if ((selIndex = (INT)SendMessage(hwndList, CB_GETCURSEL, 0, 0)) == CB_ERR) {
  298. return selIndex;
  299. }
  300. //
  301. // Get the flags associated with the currently selected item
  302. //
  303. itemFlags = (INT)SendMessage(hwndList, CB_GETITEMDATA, selIndex, 0);
  304. //
  305. // Let the caller know if this is a server cover page
  306. //
  307. *pbIsServerPage=itemFlags & CPFLAG_SERVERCP;
  308. if ((itemFlags != CB_ERR) && (lptstrFullPath || lptstrFileName)) {
  309. Assert((itemFlags & CPFLAG_DIRINDEX) < pCPInfo->nDirs);
  310. pDirPath = pCPInfo->pDirPath[itemFlags & CPFLAG_DIRINDEX];
  311. //
  312. // assemble the full pathname for the cover page file
  313. // directory prefix
  314. // display name
  315. // filename extension
  316. //
  317. pFilename = NULL;
  318. if ((nameLen = (INT)SendMessage(hwndList, CB_GETLBTEXTLEN, selIndex, 0)) != CB_ERR &&
  319. (pFilename = MemAlloc(sizeof(TCHAR) * (nameLen + 1))) &&
  320. SendMessage(hwndList, CB_GETLBTEXT, selIndex, (LPARAM) pFilename) != CB_ERR)
  321. {
  322. //
  323. // If the cover page filename has a suffix, we need to remove it first
  324. //
  325. if (itemFlags & CPFLAG_SUFFIX) {
  326. INT suffixLen = _tcslen(PersonalSuffixStr);
  327. if (nameLen >= suffixLen &&
  328. _tcscmp(pFilename + (nameLen - suffixLen), PersonalSuffixStr) == EQUAL_STRING)
  329. {
  330. *(pFilename + (nameLen - suffixLen)) = NUL;
  331. } else
  332. Error(("Corrupted cover page filename: %ws\n", pFilename));
  333. }
  334. if (lptstrFullPath)
  335. {
  336. hRc = StringCchPrintf(lptstrFullPath, cchstrFullPath, TEXT("%s%s%s"),
  337. pDirPath,
  338. pFilename,
  339. FAX_COVER_PAGE_FILENAME_EXT);
  340. if(FAILED(hRc))
  341. {
  342. itemFlags = CB_ERR;
  343. Assert(0);
  344. }
  345. }
  346. if (lptstrFileName)
  347. {
  348. hRc = StringCchPrintf(lptstrFileName, cchstrFileName, TEXT("%s%s"),
  349. pFilename,
  350. FAX_COVER_PAGE_FILENAME_EXT);
  351. if(FAILED(hRc))
  352. {
  353. itemFlags = CB_ERR;
  354. Assert(0);
  355. }
  356. }
  357. } else {
  358. itemFlags = CB_ERR;
  359. }
  360. MemFree(pFilename);
  361. }
  362. return itemFlags;
  363. }
  364. BOOL
  365. GetServerCoverPageDirs(
  366. LPTSTR lptstrServerName,
  367. LPTSTR lptstrPrinterName,
  368. PCPDATA pCPInfo
  369. )
  370. /*++
  371. Routine Description:
  372. Find the directories in which the server cover pages are stored
  373. Arguments:
  374. lptstrServerName - server name
  375. Return Value:
  376. TRUE if successful, FALSE otherwise
  377. --*/
  378. {
  379. BOOL status = FALSE;
  380. LPTSTR pServerDir = NULL;
  381. LPTSTR pServerSubDir, p;
  382. Assert(pCPInfo);
  383. Assert(lptstrPrinterName);
  384. pServerDir = MemAlloc(sizeof(TCHAR) * MAX_PATH);
  385. if (!pServerDir) {
  386. Error(("Memory allocation failed\n"));
  387. goto exit;
  388. }
  389. if ( !GetServerCpDir(lptstrServerName,
  390. pServerDir,
  391. MAX_PATH)
  392. )
  393. {
  394. Error(("GetServerCpDir failed\n"));
  395. goto exit;
  396. }
  397. pCPInfo->pDirPath[pCPInfo->nDirs] = pServerDir;
  398. pCPInfo->nDirs += 1;
  399. pCPInfo->nServerDirs += 1;
  400. status = TRUE;
  401. //
  402. // Find a subdirectory for the specified printer
  403. //
  404. if (p = _tcsrchr(lptstrPrinterName, FAX_PATH_SEPARATOR_CHR))
  405. p++;
  406. else
  407. p = lptstrPrinterName;
  408. if ((_tcslen(pServerDir) + _tcslen(p) + 1 < MAX_PATH ) &&
  409. (pServerSubDir = MemAlloc(sizeof(TCHAR) * MAX_PATH)))
  410. {
  411. _sntprintf( pServerSubDir,
  412. MAX_PATH -1,
  413. TEXT("%s\\%s"),
  414. pServerDir,
  415. p);
  416. pServerSubDir[MAX_PATH -1] = _T('\0');
  417. pCPInfo->pDirPath[pCPInfo->nDirs] = pServerSubDir;
  418. pCPInfo->nDirs += 1;
  419. pCPInfo->nServerDirs += 1;
  420. }
  421. //
  422. // Clean up before returning to caller
  423. //
  424. exit:
  425. if (!status) {
  426. MemFree(pServerDir);
  427. }
  428. return status;
  429. }
  430. VOID
  431. AppendPathSeparator(
  432. LPTSTR pDirPath
  433. )
  434. /*++
  435. Routine Description:
  436. Append a path separator (if necessary) at the end of a directory name
  437. Arguments:
  438. pDirPath - Points to a directory name
  439. Return Value:
  440. NONE
  441. --*/
  442. {
  443. INT length;
  444. TCHAR* pLast = NULL;
  445. //
  446. // Calculate the length of directory string
  447. //
  448. length = _tcslen(pDirPath);
  449. if (length >= MAX_PATH-1 || length < 1)
  450. return;
  451. //
  452. // If the last character is not a path separator,
  453. // append a path separator at the end
  454. //
  455. pLast = _tcsrchr(pDirPath,TEXT('\\'));
  456. if( !( pLast && (*_tcsinc(pLast)) == '\0' ) )
  457. {
  458. // the last character is not a separator, add one...
  459. _tcscat(pDirPath, TEXT("\\"));
  460. }
  461. }
  462. BOOL
  463. UseServerCp(
  464. LPTSTR lptstrServerName
  465. )
  466. {
  467. HANDLE FaxHandle = NULL;
  468. BOOL Rval = FALSE;
  469. if (!FaxConnectFaxServer( lptstrServerName, &FaxHandle ))
  470. {
  471. Verbose(("Can't connect to the fax server %s",lptstrServerName));
  472. goto exit;
  473. }
  474. if (!FaxGetPersonalCoverPagesOption( FaxHandle, &Rval))
  475. {
  476. Error(("FaxGetPersonalCoverPagesOption failed: %d\n", GetLastError()));
  477. goto exit;
  478. }
  479. else
  480. {
  481. //
  482. // the return value means server cover pages only
  483. //
  484. Rval = !Rval;
  485. }
  486. exit:
  487. if (FaxHandle)
  488. {
  489. if (!FaxClose( FaxHandle ))
  490. {
  491. Verbose(("Can't close the fax handle %x",FaxHandle));
  492. }
  493. }
  494. return Rval;
  495. }
  496. PCPDATA
  497. AllocCoverPageInfo(
  498. LPTSTR lptstrServerName,
  499. LPTSTR lptstrPrinterName,
  500. BOOL ServerCpOnly
  501. )
  502. /*++
  503. Routine Description:
  504. Allocate memory to hold cover page information
  505. Arguments:
  506. lptstrServerName - server name
  507. ServerCpOnly - flag says if he function should use server CP only
  508. Return Value:
  509. Pointer to a CPDATA structure, NULL if there is an error
  510. --*/
  511. {
  512. PCPDATA pCPInfo;
  513. INT nDirs;
  514. LPTSTR pDirPath, pUserCPDir, pSavedPtr;
  515. if (pCPInfo = MemAllocZ(sizeof(CPDATA))) {
  516. //
  517. // Find the directory in which the server cover pages are stored
  518. //
  519. if (! GetServerCoverPageDirs(lptstrServerName, lptstrPrinterName, pCPInfo))
  520. Error(("Couldn't get server cover page directories\n"));
  521. //
  522. // Find the directory in which the user cover pages are stored
  523. //
  524. if (ServerCpOnly == FALSE &&
  525. (pUserCPDir = pSavedPtr = GetUserCoverPageDir()))
  526. {
  527. while (pUserCPDir && pCPInfo->nDirs < MAX_COVERPAGE_DIRS) {
  528. LPTSTR pNextDir = pUserCPDir;
  529. //
  530. // Find the next semicolon character
  531. //
  532. pNextDir = _tcschr(pNextDir,TEXT(';'));
  533. if (pNextDir != NUL )
  534. {
  535. _tcsnset(pNextDir,TEXT('\0'),1);
  536. _tcsinc(pNextDir);
  537. }
  538. //
  539. // Make sure the directory name is not too long
  540. //
  541. if (_tcslen(pUserCPDir) < MAX_PATH) {
  542. if (! (pDirPath = MemAlloc(sizeof(TCHAR) * MAX_PATH)))
  543. break;
  544. pCPInfo->pDirPath[pCPInfo->nDirs++] = pDirPath;
  545. _tcscpy(pDirPath, pUserCPDir);
  546. }
  547. pUserCPDir = pNextDir;
  548. }
  549. MemFree(pSavedPtr);
  550. }
  551. //
  552. // Append path separators at the end if necessary
  553. //
  554. for (nDirs=0; nDirs < pCPInfo->nDirs; nDirs++) {
  555. AppendPathSeparator(pCPInfo->pDirPath[nDirs]);
  556. Verbose(("Cover page directory: %ws\n", pCPInfo->pDirPath[nDirs]));
  557. }
  558. }
  559. return pCPInfo;
  560. }
  561. VOID
  562. FreeCoverPageInfo(
  563. PCPDATA pCPInfo
  564. )
  565. /*++
  566. Routine Description:
  567. Free up memory used for cover page information
  568. Arguments:
  569. pCPInfo - Points to cover page information to be freed
  570. Return Value:
  571. NONE
  572. --*/
  573. {
  574. if (pCPInfo) {
  575. INT index;
  576. for (index=0; index < pCPInfo->nDirs; index++)
  577. MemFree(pCPInfo->pDirPath[index]);
  578. MemFree(pCPInfo);
  579. }
  580. }