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.

1046 lines
31 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. util.cpp
  5. Abstract:
  6. This module implements utility functions for the fax queue viewer
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Andrew Ritz (andrewr) 14-jan-1998
  11. Steven Kehrli (steveke) 30-oct-1998 - major rewrite
  12. --*/
  13. #include "faxqueue.h"
  14. VOID
  15. GetFaxQueueRegistryData(
  16. PWINPOSINFO pWinPosInfo
  17. )
  18. /*++
  19. Routine Description:
  20. Get the persistent data for the fax queue viewer
  21. Arguments:
  22. pWinPosInfo - pointer to the structure that contains the persistent data
  23. Return Value:
  24. None
  25. --*/
  26. {
  27. HKEY hKey;
  28. DWORD dwDisposition;
  29. DWORD dwType;
  30. #ifdef DEBUG
  31. // bDebug indicates if debugging is enabled
  32. BOOL bDebug;
  33. DWORD dwDebugSize;
  34. #endif // DEBUG
  35. #ifdef TOOLBAR_ENABLED
  36. // bToolbarVisible is the status of the toolbar
  37. BOOL bToolbarVisible;
  38. DWORD dwToolbarSize;
  39. #endif
  40. // bStatusBarVisible is the state of the status bar
  41. BOOL bStatusBarVisible;
  42. DWORD dwStatusBarSize;
  43. // nColumnIndex is used to enumerate each column of the list view
  44. INT nColumnIndex;
  45. // szColumnKey is the string representation of a column's registry value
  46. TCHAR szColumnKey[RESOURCE_STRING_LEN];
  47. // dwColumnWidth is the column width
  48. DWORD dwColumnWidth;
  49. DWORD dwColumnSize;
  50. // WindowPlacement is the window placement
  51. WINDOWPLACEMENT WindowPlacement;
  52. DWORD dwWindowPlacementSize;
  53. #ifdef DEBUG
  54. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGKEY_FAXSERVER, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) {
  55. // Get the state of the job id
  56. dwDebugSize = sizeof(bDebug);
  57. if (RegQueryValueEx(hKey, REGVAL_DBGLEVEL, NULL, &dwType, (LPBYTE) &bDebug, &dwDebugSize) == ERROR_SUCCESS) {
  58. pWinPosInfo->bDebug = bDebug;
  59. }
  60. RegCloseKey(hKey);
  61. }
  62. #endif // DEBUG
  63. if (RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_FAXQUEUE, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) {
  64. #ifdef TOOLBAR_ENABLED
  65. // Get the state of the toolbar
  66. dwToolbarSize = sizeof(bToolbarVisible);
  67. if (RegQueryValueEx(hKey, REGVAL_TOOLBARS, NULL, &dwType, (LPBYTE) &bToolbarVisible, &dwToolbarSize) == ERROR_SUCCESS) {
  68. pWinPosInfo->bToolbarVisible = bToolbarVisible;
  69. }
  70. #endif // TOOLBAR_ENABLED
  71. // Get the state of the status bar
  72. dwStatusBarSize = sizeof(bStatusBarVisible);
  73. if (RegQueryValueEx(hKey, REGVAL_STATUSBAR, NULL, &dwType, (LPBYTE) &bStatusBarVisible, &dwStatusBarSize) == ERROR_SUCCESS) {
  74. pWinPosInfo->bStatusBarVisible = bStatusBarVisible;
  75. }
  76. // Get the column widths
  77. for (nColumnIndex = 0; nColumnIndex < (INT) eIllegalColumnIndex; nColumnIndex++) {
  78. // Set the column's registry value
  79. wsprintf(szColumnKey, REGVAL_COLUMNWIDTH, nColumnIndex);
  80. dwColumnSize = sizeof(dwColumnWidth);
  81. if (RegQueryValueEx(hKey, szColumnKey, NULL, &dwType, (LPBYTE) &dwColumnWidth, &dwColumnSize) == ERROR_SUCCESS) {
  82. pWinPosInfo->ColumnWidth[nColumnIndex] = dwColumnWidth;
  83. }
  84. }
  85. // Get the window placement
  86. dwWindowPlacementSize = sizeof(WindowPlacement);
  87. if (RegQueryValueEx(hKey, REGVAL_WINDOW_PLACEMENT, NULL, &dwType, (LPBYTE) &WindowPlacement, &dwWindowPlacementSize) == ERROR_SUCCESS) {
  88. if (dwWindowPlacementSize == sizeof(WindowPlacement)) {
  89. CopyMemory((LPBYTE) &pWinPosInfo->WindowPlacement, (LPBYTE) &WindowPlacement, sizeof(WindowPlacement));
  90. }
  91. }
  92. RegCloseKey(hKey);
  93. }
  94. }
  95. VOID
  96. SetFaxQueueRegistryData(
  97. #ifdef TOOLBAR_ENABLED
  98. BOOL bToolbarVisible,
  99. #endif // TOOLBAR_ENABLED
  100. BOOL bStatusBarVisible,
  101. HWND hWndList,
  102. HWND hWnd
  103. )
  104. /*++
  105. Routine Description:
  106. Set the persistent data for the fax queue viewer
  107. Arguments:
  108. bToolbarVisible - status of the toolbar
  109. bStatusBarVisible - status of the status bar
  110. hWndList - handle to the list view
  111. hWnd - handle to the fax queue viewer window
  112. Return Value:
  113. None
  114. --*/
  115. {
  116. HKEY hKey;
  117. DWORD dwDisposition;
  118. // nColumnIndex is used to enumerate each column of the list view
  119. INT nColumnIndex;
  120. // szColumnKey is the string representation of a column's registry value
  121. TCHAR szColumnKey[RESOURCE_STRING_LEN];
  122. // dwColumnWidth is the column width
  123. DWORD dwColumnWidth;
  124. // WindowPlacement is the window placement
  125. WINDOWPLACEMENT WindowPlacement;
  126. if (RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_FAXQUEUE, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) {
  127. #ifdef TOOLBAR_ENABLED
  128. // Set the state of the toolbar
  129. RegSetValueEx(hKey, REGVAL_TOOLBARS, 0, REG_DWORD, (LPBYTE) &bToolbarVisible, sizeof(bToolbarVisible));
  130. #endif // TOOLBAR_ENABLED
  131. // Set the state of the status bar
  132. RegSetValueEx(hKey, REGVAL_STATUSBAR, 0, REG_DWORD, (LPBYTE) &bStatusBarVisible, sizeof(bStatusBarVisible));
  133. // Set the column widths
  134. for (nColumnIndex = 0; nColumnIndex < (INT) eIllegalColumnIndex; nColumnIndex++) {
  135. // Set the column's registry value
  136. wsprintf(szColumnKey, REGVAL_COLUMNWIDTH, nColumnIndex);
  137. dwColumnWidth = ListView_GetColumnWidth(hWndList, nColumnIndex);
  138. RegSetValueEx(hKey, szColumnKey, 0, REG_DWORD, (LPBYTE) &dwColumnWidth, sizeof(dwColumnWidth));
  139. }
  140. // Set the window placement
  141. GetWindowPlacement(hWnd, &WindowPlacement);
  142. WindowPlacement.showCmd = SW_SHOWNORMAL;
  143. RegSetValueEx(hKey, REGVAL_WINDOW_PLACEMENT, 0, REG_BINARY, (LPBYTE) &WindowPlacement, sizeof(WindowPlacement));
  144. RegCloseKey(hKey);
  145. }
  146. }
  147. VOID
  148. GetColumnHeaderText(
  149. eListViewColumnIndex eColumnIndex,
  150. LPTSTR szColumnHeader
  151. )
  152. /*++
  153. Routine Description:
  154. Builds a string containing the text of a column header to be added to the list view
  155. Arguments:
  156. eColumnIndex - indicates the column number
  157. szColumnHeader - column header text
  158. Return Value:
  159. None
  160. --*/
  161. {
  162. UINT uResource = 0;
  163. TCHAR szString[RESOURCE_STRING_LEN];
  164. switch (eColumnIndex) {
  165. case eDocumentName:
  166. uResource = IDS_DOCUMENT_NAME_COLUMN;
  167. break;
  168. case eJobType:
  169. uResource = IDS_JOB_TYPE_COLUMN;
  170. break;
  171. case eStatus:
  172. uResource = IDS_STATUS_COLUMN;
  173. break;
  174. case eOwner:
  175. uResource = IDS_OWNER_COLUMN;
  176. break;
  177. case ePages:
  178. uResource = IDS_PAGES_COLUMN;
  179. break;
  180. case eSize:
  181. uResource = IDS_SIZE_COLUMN;
  182. break;
  183. case eScheduledTime:
  184. uResource = IDS_SCHEDULED_TIME_COLUMN;
  185. break;
  186. case ePort:
  187. uResource = IDS_PORT_COLUMN;
  188. break;
  189. }
  190. if (uResource) {
  191. LoadString(g_hInstance, uResource, szString, RESOURCE_STRING_LEN);
  192. lstrcpy(szColumnHeader, szString);
  193. }
  194. else {
  195. lstrcpy(szColumnHeader, TEXT(""));
  196. }
  197. }
  198. LPVOID
  199. LocalEnumPrinters(
  200. DWORD dwFlags,
  201. DWORD dwLevel,
  202. LPDWORD pdwNumPrinters
  203. )
  204. /*++
  205. Routine Description:
  206. Enumerate all the printers
  207. Arguments:
  208. dwFlags - type of print objects to enumerate
  209. dwLevel - type of printer info structure
  210. pdwNumPrinters - pointer to the number of printers
  211. Return Value:
  212. Pointer to the printers configuration
  213. --*/
  214. {
  215. // pPrintersConfig is a pointer to the printers configuration
  216. LPVOID pPrintersConfig;
  217. DWORD cb;
  218. *pdwNumPrinters = 0;
  219. // Enumerate all the printers
  220. if ((!EnumPrinters(dwFlags, NULL, dwLevel, NULL, 0, &cb, pdwNumPrinters)) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
  221. // EnumPrinters failed because the buffer is too small
  222. // cb is the size of the buffer needed, so allocate a buffer of that size
  223. pPrintersConfig = MemAlloc(cb);
  224. // Call EnumPrinters again with the correct size buffer
  225. if (!EnumPrinters(dwFlags, NULL, dwLevel, (LPBYTE) pPrintersConfig, cb, &cb, pdwNumPrinters)) {
  226. // EnumPrinters failed
  227. MemFree(pPrintersConfig);
  228. // Return NULL pointer
  229. return NULL;
  230. }
  231. // Return pointer to the buffer
  232. return pPrintersConfig;
  233. }
  234. // Return NULL pointer
  235. return NULL;
  236. }
  237. int __cdecl
  238. ComparePrinterNames(
  239. const void *arg1,
  240. const void *arg2
  241. )
  242. {
  243. return (CompareString(LOCALE_USER_DEFAULT, 0, ((LPPRINTER_INFO_2) arg1)->pPrinterName, -1, ((LPPRINTER_INFO_2) arg2)->pPrinterName, -1) - 2);
  244. }
  245. LPVOID
  246. GetFaxPrinters(
  247. LPDWORD pdwNumFaxPrinters
  248. )
  249. /*++
  250. Routine Description:
  251. Get the fax printers
  252. Arguments:
  253. pdwNumFaxPrinters - pointer to the number of fax printers
  254. Return Value:
  255. Pointer to the fax printers configuration
  256. --*/
  257. {
  258. // pFaxPrintersConfig is a pointer to the printers configuration
  259. LPPRINTER_INFO_2 pFaxPrintersConfig;
  260. // dwNumPrinters is the number of printers
  261. DWORD dwNumPrinters;
  262. // dwNumFaxPrinters is the number of fax printers
  263. DWORD dwNumFaxPrinters;
  264. // dwIndex is a counter to enumerate each printer
  265. DWORD dwIndex;
  266. // dwFlags is the type of print objects to enumerate
  267. DWORD dwFlags;
  268. #ifdef WIN95
  269. dwFlags = PRINTER_ENUM_LOCAL;
  270. #else
  271. dwFlags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS;
  272. #endif // WIN95
  273. // Enumerate all the printers
  274. pFaxPrintersConfig = (LPPRINTER_INFO_2) LocalEnumPrinters(dwFlags, 2, &dwNumPrinters);
  275. if (!pFaxPrintersConfig) {
  276. *pdwNumFaxPrinters = 0;
  277. return NULL;
  278. }
  279. // Determine the number of fax printers
  280. for (dwIndex = 0, dwNumFaxPrinters = 0; dwIndex < dwNumPrinters; dwIndex++) {
  281. // A fax printer is determined by comparing the name of the current printer driver against the name of the fax printer driver
  282. if (!lstrcmpi((pFaxPrintersConfig)[dwIndex].pDriverName, FAX_DRIVER_NAME)) {
  283. // Name of the current printer driver and the name of the fax printer driver match
  284. // Increment the number of fax printers
  285. dwNumFaxPrinters += 1;
  286. }
  287. }
  288. if (dwNumFaxPrinters > 0) {
  289. for (dwIndex = 0, dwNumFaxPrinters = 0; dwIndex < dwNumPrinters; dwIndex++) {
  290. // A fax printer is determined by comparing the name of the current printer driver against the name of the fax printer driver
  291. if (!lstrcmpi((pFaxPrintersConfig)[dwIndex].pDriverName, FAX_DRIVER_NAME)) {
  292. // Name of the current printer driver and the name of the fax printer driver match
  293. // Move fax printer up to the next available slot
  294. pFaxPrintersConfig[dwNumFaxPrinters] = pFaxPrintersConfig[dwIndex];
  295. // Increment the number of fax printers
  296. dwNumFaxPrinters++;
  297. }
  298. }
  299. // Quick sort the fax printers
  300. qsort(pFaxPrintersConfig, dwNumFaxPrinters, sizeof(PRINTER_INFO_2), ComparePrinterNames);
  301. }
  302. else {
  303. MemFree(pFaxPrintersConfig);
  304. pFaxPrintersConfig = NULL;
  305. }
  306. *pdwNumFaxPrinters = dwNumFaxPrinters;
  307. return pFaxPrintersConfig;
  308. }
  309. LPTSTR
  310. GetDefaultPrinterName(
  311. )
  312. /*++
  313. Routine Description:
  314. Get the default printer
  315. Return Value:
  316. Name of the default printer
  317. --*/
  318. {
  319. // szPrinterName is the printer name
  320. LPTSTR szPrinterName;
  321. #ifdef WIN95
  322. // pPrintersConfig is a pointer to the printers configuration
  323. LPPRINTER_INFO_5 pPrintersConfig;
  324. // dwNumPrinters is the number of printers
  325. DWORD dwNumPrinters;
  326. // Enumerate all the printers
  327. pPrintersConfig = (LPPRINTER_INFO_5) LocalEnumPrinters(PRINTER_ENUM_DEFAULT, 5, &dwNumPrinters);
  328. if (!pPrintersConfig) {
  329. return NULL;
  330. }
  331. // Allocate the memory for the printer name
  332. szPrinterName = (LPTSTR) MemAlloc((lstrlen(pPrintersConfig->pPrinterName) + 1) * sizeof(TCHAR));
  333. // Copy the printer name
  334. lstrcpy(szPrinterName, pPrintersConfig->pPrinterName);
  335. MemFree(pPrintersConfig);
  336. return szPrinterName;
  337. #else
  338. DWORD cb;
  339. // Get the default printer
  340. cb = 0;
  341. if ((!GetDefaultPrinter(NULL, &cb)) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
  342. // GetDefaultPrinter failed because the buffer is too small
  343. // cb is the size of the buffer needed, so allocate a buffer of that size
  344. szPrinterName = (LPTSTR) MemAlloc(cb * sizeof(TCHAR));
  345. // Call GetDefaultPrinter again with the correct size buffer
  346. if (!GetDefaultPrinter(szPrinterName, &cb)) {
  347. // GetDefaultPrinter failed
  348. MemFree(szPrinterName);
  349. // Return NULL pointer
  350. return NULL;
  351. }
  352. // Return pointer to the buffer
  353. return szPrinterName;
  354. }
  355. // Return NULL pointer
  356. return NULL;
  357. #endif // WIN95
  358. }
  359. VOID
  360. SetDefaultPrinterName(
  361. LPTSTR szPrinterName
  362. )
  363. /*++
  364. Routine Description:
  365. Set the default printer
  366. Arguments:
  367. szPrinterName - name of the printer to set as the default
  368. Return Value:
  369. None
  370. --*/
  371. {
  372. #ifdef WIN95
  373. // hPrinter is the handle to the printer
  374. HANDLE hPrinter;
  375. // pPrintersConfig is a pointer to the printers configuration
  376. LPPRINTER_INFO_2 pPrintersConfig;
  377. DWORD cb;
  378. // Open the printer
  379. if (OpenPrinter(szPrinterName, &hPrinter, NULL)) {
  380. // Get the printer
  381. cb = 0;
  382. if ((!GetPrinter(hPrinter, 2, NULL, 0, &cb)) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
  383. // GetPrinter failed because the buffer is too small
  384. // cb is the size of the buffer needed, so allocate a buffer of that size
  385. pPrintersConfig = (LPPRINTER_INFO_2) MemAlloc(cb);
  386. // Call GetPrinter again with the correct size buffer
  387. if (!GetPrinter(hPrinter, 2, (LPBYTE) pPrintersConfig, cb, &cb)) {
  388. // GetPrinter failed
  389. MemFree(pPrintersConfig);
  390. // Close the printer
  391. ClosePrinter(hPrinter);
  392. // Return
  393. return;
  394. }
  395. // Set the default attribute
  396. pPrintersConfig->Attributes |= PRINTER_ATTRIBUTE_DEFAULT;
  397. // Set the printer
  398. SetPrinter(hPrinter, 2, (LPBYTE) pPrintersConfig, 0);
  399. MemFree(pPrintersConfig);
  400. }
  401. // Close the printer
  402. ClosePrinter(hPrinter);
  403. }
  404. #else
  405. // Set the default printer
  406. SetDefaultPrinter(szPrinterName);
  407. #endif // WIN95
  408. }
  409. VOID
  410. Disconnect(
  411. )
  412. {
  413. // Wait for access to these fax service routines
  414. WaitForSingleObject(g_hFaxSvcMutex, INFINITE);
  415. // Decrement the number of connections to the fax service
  416. g_nNumConnections--;
  417. // Disconnect from the fax service if no outstanding connections
  418. if (!g_nNumConnections) {
  419. FaxClose(g_hFaxSvcHandle);
  420. g_hFaxSvcHandle = NULL;
  421. }
  422. ReleaseMutex(g_hFaxSvcMutex);
  423. }
  424. BOOL
  425. Connect(
  426. )
  427. {
  428. BOOL bVal = FALSE;
  429. // Wait for access to these fax service routines
  430. WaitForSingleObject(g_hFaxSvcMutex, INFINITE);
  431. // Connect to the fax service if not already connected
  432. if ((g_nNumConnections) || (FaxConnectFaxServer(g_szMachineName, &g_hFaxSvcHandle))) {
  433. // Increment the number of connections to the fax service
  434. g_nNumConnections++;
  435. bVal = TRUE;
  436. }
  437. ReleaseMutex(g_hFaxSvcMutex);
  438. return bVal;
  439. }
  440. LPTSTR
  441. GetColumnItemText(
  442. eListViewColumnIndex eColumnIndex,
  443. PFAX_JOB_ENTRY pFaxJobEntry,
  444. LPTSTR szDeviceName
  445. )
  446. /*++
  447. Routine Description:
  448. Build a string containing the text of a column item to be added to the list view
  449. Arguments:
  450. eColumnIndex - indicates the column number
  451. pFaxJobEntry - pointer to the fax job
  452. szDeviceName - device name the fax job is active on
  453. Return Value:
  454. LPTSTR - text of the column item
  455. --*/
  456. {
  457. // szColumnItem is the text of the column item
  458. LPTSTR szColumnItem;
  459. // szResourceString is a resource string
  460. TCHAR szResourceString[RESOURCE_STRING_LEN];
  461. // uResource is the id of the resource string
  462. UINT uResource;
  463. DWORD cb;
  464. switch (eColumnIndex) {
  465. case eDocumentName:
  466. // szNullString is the null resource string
  467. TCHAR szNullString[RESOURCE_STRING_LEN];
  468. // Determine the queue status resource string
  469. if (pFaxJobEntry->QueueStatus & JS_DELETING) {
  470. uResource = IDS_QUEUE_STATUS_DELETING;
  471. }
  472. else if (pFaxJobEntry->QueueStatus & JS_PAUSED) {
  473. uResource = IDS_QUEUE_STATUS_PAUSED;
  474. }
  475. else if (pFaxJobEntry->QueueStatus & JS_RETRYING) {
  476. uResource = IDS_QUEUE_STATUS_RETRYING;
  477. }
  478. else {
  479. uResource = 0;
  480. }
  481. // Load the queue status resource string, if necessary, and determine its memory requirement
  482. cb = 0;
  483. if (uResource) {
  484. LoadString(g_hInstance, uResource, szResourceString, RESOURCE_STRING_LEN);
  485. cb = lstrlen(szResourceString) * sizeof(TCHAR);
  486. }
  487. if (pFaxJobEntry->DocumentName) {
  488. cb += (lstrlen(pFaxJobEntry->DocumentName) + 1) * sizeof(TCHAR);
  489. }
  490. else {
  491. // Load the null resource string
  492. LoadString(g_hInstance, IDS_NO_DOCUMENT_NAME, szNullString, RESOURCE_STRING_LEN);
  493. cb += (lstrlen(szNullString) + 1) * sizeof(TCHAR);
  494. }
  495. #ifdef DEBUG
  496. if (WinPosInfo.bDebug) {
  497. cb += lstrlen(TEXT("0x00000000 ")) * sizeof(TCHAR);
  498. }
  499. #endif // DEBUG
  500. // Allocate the memory for the document name and set the document name
  501. szColumnItem = (LPTSTR) MemAlloc(cb);
  502. if (szColumnItem) {
  503. #ifdef DEBUG
  504. if (WinPosInfo.bDebug) {
  505. wsprintf(szColumnItem, TEXT("0x%08x "), pFaxJobEntry->JobId);
  506. }
  507. if (pFaxJobEntry->DocumentName) {
  508. lstrcat(szColumnItem, pFaxJobEntry->DocumentName);
  509. }
  510. else {
  511. lstrcat(szColumnItem, szNullString);
  512. }
  513. #else
  514. if (pFaxJobEntry->DocumentName) {
  515. lstrcpy(szColumnItem, pFaxJobEntry->DocumentName);
  516. }
  517. else {
  518. lstrcpy(szColumnItem, szNullString);
  519. }
  520. #endif // DEBUG
  521. if (uResource) {
  522. lstrcat(szColumnItem, szResourceString);
  523. }
  524. return szColumnItem;
  525. }
  526. return NULL;
  527. case eJobType:
  528. // Determine the job type resource string
  529. switch (pFaxJobEntry->JobType) {
  530. case JT_SEND:
  531. uResource = IDS_JOB_TYPE_SEND;
  532. break;
  533. case JT_RECEIVE:
  534. uResource = IDS_JOB_TYPE_RECEIVE;
  535. break;
  536. case JT_ROUTING:
  537. uResource = IDS_JOB_TYPE_ROUTING;
  538. break;
  539. case JT_FAIL_RECEIVE:
  540. uResource = IDS_JOB_TYPE_FAIL_RECEIVE;
  541. break;
  542. default:
  543. uResource = 0;
  544. break;
  545. }
  546. // Load the job type resource string, if necessary
  547. if (uResource) {
  548. LoadString(g_hInstance, uResource, szResourceString, RESOURCE_STRING_LEN);
  549. // Allocate the memory for the job type and set the job type
  550. szColumnItem = (LPTSTR) MemAlloc((lstrlen(szResourceString) + 1) * sizeof(TCHAR));
  551. if (szColumnItem) {
  552. lstrcpy(szColumnItem, szResourceString);
  553. return szColumnItem;
  554. }
  555. }
  556. return NULL;
  557. case eStatus:
  558. // Determine the job status resource string
  559. switch (pFaxJobEntry->Status) {
  560. case FPS_DIALING:
  561. uResource = IDS_JOB_STATUS_DIALING;
  562. break;
  563. case FPS_SENDING:
  564. uResource = IDS_JOB_STATUS_SENDING;
  565. break;
  566. case FPS_RECEIVING:
  567. uResource = IDS_JOB_STATUS_RECEIVING;
  568. break;
  569. case FPS_COMPLETED:
  570. uResource = IDS_JOB_STATUS_COMPLETED;
  571. break;
  572. case FPS_HANDLED:
  573. uResource = IDS_JOB_STATUS_HANDLED;
  574. break;
  575. case FPS_UNAVAILABLE:
  576. uResource = IDS_JOB_STATUS_UNAVAILABLE;
  577. break;
  578. case FPS_BUSY:
  579. uResource = IDS_JOB_STATUS_BUSY;
  580. break;
  581. case FPS_NO_ANSWER:
  582. uResource = IDS_JOB_STATUS_NO_ANSWER;
  583. break;
  584. case FPS_BAD_ADDRESS:
  585. uResource = IDS_JOB_STATUS_BAD_ADDRESS;
  586. break;
  587. case FPS_NO_DIAL_TONE:
  588. uResource = IDS_JOB_STATUS_NO_DIAL_TONE;
  589. break;
  590. case FPS_DISCONNECTED:
  591. uResource = IDS_JOB_STATUS_DISCONNECTED;
  592. break;
  593. case FPS_FATAL_ERROR:
  594. if (pFaxJobEntry->JobType == JT_RECEIVE) {
  595. uResource = IDS_JOB_STATUS_FATAL_ERROR_RCV;
  596. }
  597. else {
  598. uResource = IDS_JOB_STATUS_FATAL_ERROR_SND;
  599. }
  600. break;
  601. case FPS_NOT_FAX_CALL:
  602. uResource = IDS_JOB_STATUS_NOT_FAX_CALL;
  603. break;
  604. case FPS_CALL_DELAYED:
  605. uResource = IDS_JOB_STATUS_CALL_DELAYED;
  606. break;
  607. case FPS_CALL_BLACKLISTED:
  608. uResource = IDS_JOB_STATUS_CALL_BLACKLISTED;
  609. break;
  610. case FPS_INITIALIZING:
  611. uResource = IDS_JOB_STATUS_INITIALIZING;
  612. break;
  613. case FPS_OFFLINE:
  614. uResource = IDS_JOB_STATUS_OFFLINE;
  615. break;
  616. case FPS_RINGING:
  617. uResource = IDS_JOB_STATUS_RINGING;
  618. break;
  619. case FPS_AVAILABLE:
  620. uResource = IDS_JOB_STATUS_AVAILABLE;
  621. break;
  622. case FPS_ABORTING:
  623. uResource = IDS_JOB_STATUS_ABORTING;
  624. break;
  625. case FPS_ROUTING:
  626. uResource = IDS_JOB_STATUS_ROUTING;
  627. break;
  628. case FPS_ANSWERED:
  629. uResource = IDS_JOB_STATUS_ANSWERED;
  630. break;
  631. default:
  632. uResource = 0;
  633. break;
  634. }
  635. // Determine if retries have been exceeded
  636. if (((pFaxJobEntry->JobType == JT_SEND) || (pFaxJobEntry->JobType == JT_ROUTING)) && (pFaxJobEntry->QueueStatus & JS_RETRIES_EXCEEDED)) {
  637. uResource = IDS_QUEUE_STATUS_RETRIES_EXCEEDED;
  638. }
  639. // Load the job status resource string, if necessary
  640. if (uResource) {
  641. LoadString(g_hInstance, uResource, szResourceString, RESOURCE_STRING_LEN);
  642. // Allocate the memory for the job status and set the job type
  643. if (uResource == IDS_JOB_STATUS_DIALING) {
  644. szColumnItem = (LPTSTR) MemAlloc((lstrlen(szResourceString) + lstrlen(pFaxJobEntry->RecipientNumber) + 1) * sizeof(TCHAR));
  645. }
  646. else {
  647. szColumnItem = (LPTSTR) MemAlloc((lstrlen(szResourceString) + 1) * sizeof(TCHAR));
  648. }
  649. if (szColumnItem) {
  650. if (uResource == IDS_JOB_STATUS_DIALING) {
  651. wsprintf(szColumnItem, szResourceString, pFaxJobEntry->RecipientNumber);
  652. }
  653. else {
  654. lstrcpy(szColumnItem, szResourceString);
  655. }
  656. return szColumnItem;
  657. }
  658. }
  659. return NULL;
  660. case eOwner:
  661. // Allocate the memory for the job owner and set the job owner, if necessary
  662. if (pFaxJobEntry->UserName) {
  663. szColumnItem = (LPTSTR) MemAlloc((lstrlen(pFaxJobEntry->UserName) + 1) * sizeof(TCHAR));
  664. if (szColumnItem) {
  665. lstrcpy(szColumnItem, pFaxJobEntry->UserName);
  666. return szColumnItem;
  667. }
  668. }
  669. return NULL;
  670. case ePages:
  671. // Set the job pages resource string, if necessary
  672. if (pFaxJobEntry->PageCount) {
  673. wsprintf(szResourceString, TEXT("%d"), pFaxJobEntry->PageCount);
  674. // Allocate the memory for the job pages and set the job pages
  675. szColumnItem = (LPTSTR) MemAlloc((lstrlen(szResourceString) + 1) * sizeof(TCHAR));
  676. if (szColumnItem) {
  677. lstrcpy(szColumnItem, szResourceString);
  678. return szColumnItem;
  679. }
  680. }
  681. return NULL;
  682. case eSize:
  683. // Determine the job size resource string
  684. if (pFaxJobEntry->Size) {
  685. // szNumberString is the number string
  686. LPTSTR szNumberString;
  687. if (pFaxJobEntry->Size < 1024) {
  688. uResource = IDS_JOB_SIZE_BYTES;
  689. // Set the job size number string
  690. wsprintf(szResourceString, TEXT("%u"), pFaxJobEntry->Size);
  691. }
  692. else if (pFaxJobEntry->Size < 1024 * 1024) {
  693. uResource = IDS_JOB_SIZE_KBYTES;
  694. // Set the job size number string
  695. wsprintf(szResourceString, TEXT("%u.%2u"), pFaxJobEntry->Size / 1024, pFaxJobEntry->Size % 1024);
  696. }
  697. else if (pFaxJobEntry->Size < 1024 * 1024 * 1024) {
  698. uResource = IDS_JOB_SIZE_MBYTES;
  699. // Set the job size number string
  700. wsprintf(szResourceString, TEXT("%u.%2u"), pFaxJobEntry->Size / (1024 * 1024), pFaxJobEntry->Size % (1024 * 1024));
  701. }
  702. else {
  703. uResource = IDS_JOB_SIZE_GBYTES;
  704. // Set the job size number string
  705. wsprintf(szResourceString, TEXT("%u.%2u"), pFaxJobEntry->Size / (1024 * 1024 * 1024), pFaxJobEntry->Size % (1024 * 1024 * 1024));
  706. }
  707. // Format the number string
  708. cb = GetNumberFormat(LOCALE_USER_DEFAULT, 0, szResourceString, NULL, NULL, 0);
  709. szNumberString = (LPTSTR) MemAlloc((cb + 1) * sizeof(TCHAR));
  710. if (szNumberString) {
  711. GetNumberFormat(LOCALE_USER_DEFAULT, 0, szResourceString, NULL, szNumberString, cb);
  712. LoadString(g_hInstance, uResource, szResourceString, RESOURCE_STRING_LEN);
  713. // Allocate the memory for the job size and set the job size
  714. szColumnItem = (LPTSTR) MemAlloc((lstrlen(szNumberString) + lstrlen(szResourceString) + 1) * sizeof(TCHAR));
  715. if (szColumnItem) {
  716. wsprintf(szColumnItem, szResourceString, szNumberString);
  717. MemFree(szNumberString);
  718. return szColumnItem;
  719. }
  720. MemFree(szNumberString);
  721. }
  722. }
  723. return NULL;
  724. case eScheduledTime:
  725. // Set the job scheduled time resource string
  726. if (pFaxJobEntry->ScheduleAction == JSA_NOW) {
  727. LoadString(g_hInstance, IDS_JOB_SCHEDULED_TIME_NOW, szResourceString, RESOURCE_STRING_LEN);
  728. }
  729. else {
  730. // Convert the schedule time to the local time zone
  731. SystemTimeToTzSpecificLocalTime(NULL, &pFaxJobEntry->ScheduleTime, &pFaxJobEntry->ScheduleTime);
  732. GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &pFaxJobEntry->ScheduleTime, NULL, szResourceString, RESOURCE_STRING_LEN);
  733. lstrcat(szResourceString, TEXT(" "));
  734. cb = lstrlen(szResourceString);
  735. GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &pFaxJobEntry->ScheduleTime, NULL, &szResourceString[cb], RESOURCE_STRING_LEN - cb);
  736. }
  737. // Allocate the memory for the job schedule time and set the job schedule time
  738. szColumnItem = (LPTSTR) MemAlloc((lstrlen(szResourceString) + 1) * sizeof(TCHAR));
  739. if (szColumnItem) {
  740. lstrcpy(szColumnItem, szResourceString);
  741. return szColumnItem;
  742. }
  743. return NULL;
  744. case ePort:
  745. // Allocate the memory for the job port and set the job port, if necessary
  746. if (szDeviceName) {
  747. szColumnItem = (LPTSTR) MemAlloc((lstrlen(szDeviceName) + 1) * sizeof(TCHAR));
  748. if (szColumnItem) {
  749. lstrcpy(szColumnItem, szDeviceName);
  750. return szColumnItem;
  751. }
  752. }
  753. return NULL;
  754. case eIllegalColumnIndex:
  755. break;
  756. }
  757. return NULL;
  758. }
  759. VOID
  760. SetColumnItem(
  761. HWND hWndListView,
  762. BOOL bInsert,
  763. INT iItem,
  764. INT iSubItem,
  765. LPTSTR szColumnItem,
  766. UINT uState,
  767. PFAX_JOB_ENTRY pFaxJobEntry
  768. )
  769. /*++
  770. Routine Description:
  771. Set or insert a column item in the list view
  772. Arguments:
  773. hWndListView - handle to the list view window
  774. bInsert - indicates item is to be inserted into the list view
  775. iItem - index of the item
  776. iSubItem - index of the subitem
  777. szColumnItem - column item text
  778. uState - state of the item
  779. pFaxJobEntry - pointer to the fax job
  780. Return Value:
  781. None
  782. --*/
  783. {
  784. // lvi specifies the attributes of a particular item in the list view
  785. LV_ITEM lvi;
  786. // Initialize lvi
  787. lvi.mask = LVIF_TEXT;
  788. // Set the item number
  789. lvi.iItem = iItem;
  790. // Set the subitem number
  791. lvi.iSubItem = iSubItem;
  792. // Set the item text
  793. lvi.pszText = szColumnItem;
  794. if (iSubItem == (INT) eDocumentName) {
  795. // Include the fax job id in the lParam
  796. lvi.mask = lvi.mask | LVIF_PARAM | LVIF_STATE;
  797. // Set the lParam
  798. lvi.lParam = pFaxJobEntry->JobId;
  799. // Set the item state
  800. lvi.state = uState;
  801. if (pFaxJobEntry->JobType == JT_SEND) {
  802. lvi.state |= ITEM_SEND_MASK;
  803. }
  804. if (!(pFaxJobEntry->QueueStatus & JS_INPROGRESS)) {
  805. lvi.state |= ITEM_IDLE_MASK;
  806. }
  807. if (pFaxJobEntry->QueueStatus & JS_PAUSED) {
  808. lvi.state |= ITEM_PAUSED_MASK;
  809. }
  810. if ((g_szCurrentUserName) && (!lstrcmpi(g_szCurrentUserName, pFaxJobEntry->UserName))) {
  811. lvi.state |= ITEM_USEROWNSJOB_MASK;
  812. }
  813. // Set the item state mask
  814. lvi.stateMask = uState | LVIS_OVERLAYMASK;
  815. }
  816. if ((bInsert) && (iSubItem == (INT) eDocumentName)) {
  817. ListView_InsertItem(hWndListView, &lvi);
  818. }
  819. else {
  820. ListView_SetItem(hWndListView, &lvi);
  821. }
  822. }