/*++ Copyright (c) 1998 Microsoft Corporation Module Name: util.cpp Abstract: This module implements utility functions for the fax queue viewer Environment: WIN32 User Mode Author: Andrew Ritz (andrewr) 14-jan-1998 Steven Kehrli (steveke) 30-oct-1998 - major rewrite --*/ #include "faxqueue.h" VOID GetFaxQueueRegistryData( PWINPOSINFO pWinPosInfo ) /*++ Routine Description: Get the persistent data for the fax queue viewer Arguments: pWinPosInfo - pointer to the structure that contains the persistent data Return Value: None --*/ { HKEY hKey; DWORD dwDisposition; DWORD dwType; #ifdef DEBUG // bDebug indicates if debugging is enabled BOOL bDebug; DWORD dwDebugSize; #endif // DEBUG #ifdef TOOLBAR_ENABLED // bToolbarVisible is the status of the toolbar BOOL bToolbarVisible; DWORD dwToolbarSize; #endif // bStatusBarVisible is the state of the status bar BOOL bStatusBarVisible; DWORD dwStatusBarSize; // nColumnIndex is used to enumerate each column of the list view INT nColumnIndex; // szColumnKey is the string representation of a column's registry value TCHAR szColumnKey[RESOURCE_STRING_LEN]; // dwColumnWidth is the column width DWORD dwColumnWidth; DWORD dwColumnSize; // WindowPlacement is the window placement WINDOWPLACEMENT WindowPlacement; DWORD dwWindowPlacementSize; #ifdef DEBUG if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGKEY_FAXSERVER, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) { // Get the state of the job id dwDebugSize = sizeof(bDebug); if (RegQueryValueEx(hKey, REGVAL_DBGLEVEL, NULL, &dwType, (LPBYTE) &bDebug, &dwDebugSize) == ERROR_SUCCESS) { pWinPosInfo->bDebug = bDebug; } RegCloseKey(hKey); } #endif // DEBUG if (RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_FAXQUEUE, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) { #ifdef TOOLBAR_ENABLED // Get the state of the toolbar dwToolbarSize = sizeof(bToolbarVisible); if (RegQueryValueEx(hKey, REGVAL_TOOLBARS, NULL, &dwType, (LPBYTE) &bToolbarVisible, &dwToolbarSize) == ERROR_SUCCESS) { pWinPosInfo->bToolbarVisible = bToolbarVisible; } #endif // TOOLBAR_ENABLED // Get the state of the status bar dwStatusBarSize = sizeof(bStatusBarVisible); if (RegQueryValueEx(hKey, REGVAL_STATUSBAR, NULL, &dwType, (LPBYTE) &bStatusBarVisible, &dwStatusBarSize) == ERROR_SUCCESS) { pWinPosInfo->bStatusBarVisible = bStatusBarVisible; } // Get the column widths for (nColumnIndex = 0; nColumnIndex < (INT) eIllegalColumnIndex; nColumnIndex++) { // Set the column's registry value wsprintf(szColumnKey, REGVAL_COLUMNWIDTH, nColumnIndex); dwColumnSize = sizeof(dwColumnWidth); if (RegQueryValueEx(hKey, szColumnKey, NULL, &dwType, (LPBYTE) &dwColumnWidth, &dwColumnSize) == ERROR_SUCCESS) { pWinPosInfo->ColumnWidth[nColumnIndex] = dwColumnWidth; } } // Get the window placement dwWindowPlacementSize = sizeof(WindowPlacement); if (RegQueryValueEx(hKey, REGVAL_WINDOW_PLACEMENT, NULL, &dwType, (LPBYTE) &WindowPlacement, &dwWindowPlacementSize) == ERROR_SUCCESS) { if (dwWindowPlacementSize == sizeof(WindowPlacement)) { CopyMemory((LPBYTE) &pWinPosInfo->WindowPlacement, (LPBYTE) &WindowPlacement, sizeof(WindowPlacement)); } } RegCloseKey(hKey); } } VOID SetFaxQueueRegistryData( #ifdef TOOLBAR_ENABLED BOOL bToolbarVisible, #endif // TOOLBAR_ENABLED BOOL bStatusBarVisible, HWND hWndList, HWND hWnd ) /*++ Routine Description: Set the persistent data for the fax queue viewer Arguments: bToolbarVisible - status of the toolbar bStatusBarVisible - status of the status bar hWndList - handle to the list view hWnd - handle to the fax queue viewer window Return Value: None --*/ { HKEY hKey; DWORD dwDisposition; // nColumnIndex is used to enumerate each column of the list view INT nColumnIndex; // szColumnKey is the string representation of a column's registry value TCHAR szColumnKey[RESOURCE_STRING_LEN]; // dwColumnWidth is the column width DWORD dwColumnWidth; // WindowPlacement is the window placement WINDOWPLACEMENT WindowPlacement; if (RegCreateKeyEx(HKEY_CURRENT_USER, REGKEY_FAXQUEUE, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) { #ifdef TOOLBAR_ENABLED // Set the state of the toolbar RegSetValueEx(hKey, REGVAL_TOOLBARS, 0, REG_DWORD, (LPBYTE) &bToolbarVisible, sizeof(bToolbarVisible)); #endif // TOOLBAR_ENABLED // Set the state of the status bar RegSetValueEx(hKey, REGVAL_STATUSBAR, 0, REG_DWORD, (LPBYTE) &bStatusBarVisible, sizeof(bStatusBarVisible)); // Set the column widths for (nColumnIndex = 0; nColumnIndex < (INT) eIllegalColumnIndex; nColumnIndex++) { // Set the column's registry value wsprintf(szColumnKey, REGVAL_COLUMNWIDTH, nColumnIndex); dwColumnWidth = ListView_GetColumnWidth(hWndList, nColumnIndex); RegSetValueEx(hKey, szColumnKey, 0, REG_DWORD, (LPBYTE) &dwColumnWidth, sizeof(dwColumnWidth)); } // Set the window placement GetWindowPlacement(hWnd, &WindowPlacement); WindowPlacement.showCmd = SW_SHOWNORMAL; RegSetValueEx(hKey, REGVAL_WINDOW_PLACEMENT, 0, REG_BINARY, (LPBYTE) &WindowPlacement, sizeof(WindowPlacement)); RegCloseKey(hKey); } } VOID GetColumnHeaderText( eListViewColumnIndex eColumnIndex, LPTSTR szColumnHeader ) /*++ Routine Description: Builds a string containing the text of a column header to be added to the list view Arguments: eColumnIndex - indicates the column number szColumnHeader - column header text Return Value: None --*/ { UINT uResource = 0; TCHAR szString[RESOURCE_STRING_LEN]; switch (eColumnIndex) { case eDocumentName: uResource = IDS_DOCUMENT_NAME_COLUMN; break; case eJobType: uResource = IDS_JOB_TYPE_COLUMN; break; case eStatus: uResource = IDS_STATUS_COLUMN; break; case eOwner: uResource = IDS_OWNER_COLUMN; break; case ePages: uResource = IDS_PAGES_COLUMN; break; case eSize: uResource = IDS_SIZE_COLUMN; break; case eScheduledTime: uResource = IDS_SCHEDULED_TIME_COLUMN; break; case ePort: uResource = IDS_PORT_COLUMN; break; } if (uResource) { LoadString(g_hInstance, uResource, szString, RESOURCE_STRING_LEN); lstrcpy(szColumnHeader, szString); } else { lstrcpy(szColumnHeader, TEXT("")); } } LPVOID LocalEnumPrinters( DWORD dwFlags, DWORD dwLevel, LPDWORD pdwNumPrinters ) /*++ Routine Description: Enumerate all the printers Arguments: dwFlags - type of print objects to enumerate dwLevel - type of printer info structure pdwNumPrinters - pointer to the number of printers Return Value: Pointer to the printers configuration --*/ { // pPrintersConfig is a pointer to the printers configuration LPVOID pPrintersConfig; DWORD cb; *pdwNumPrinters = 0; // Enumerate all the printers if ((!EnumPrinters(dwFlags, NULL, dwLevel, NULL, 0, &cb, pdwNumPrinters)) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { // EnumPrinters failed because the buffer is too small // cb is the size of the buffer needed, so allocate a buffer of that size pPrintersConfig = MemAlloc(cb); // Call EnumPrinters again with the correct size buffer if (!EnumPrinters(dwFlags, NULL, dwLevel, (LPBYTE) pPrintersConfig, cb, &cb, pdwNumPrinters)) { // EnumPrinters failed MemFree(pPrintersConfig); // Return NULL pointer return NULL; } // Return pointer to the buffer return pPrintersConfig; } // Return NULL pointer return NULL; } int __cdecl ComparePrinterNames( const void *arg1, const void *arg2 ) { return (CompareString(LOCALE_USER_DEFAULT, 0, ((LPPRINTER_INFO_2) arg1)->pPrinterName, -1, ((LPPRINTER_INFO_2) arg2)->pPrinterName, -1) - 2); } LPVOID GetFaxPrinters( LPDWORD pdwNumFaxPrinters ) /*++ Routine Description: Get the fax printers Arguments: pdwNumFaxPrinters - pointer to the number of fax printers Return Value: Pointer to the fax printers configuration --*/ { // pFaxPrintersConfig is a pointer to the printers configuration LPPRINTER_INFO_2 pFaxPrintersConfig; // dwNumPrinters is the number of printers DWORD dwNumPrinters; // dwNumFaxPrinters is the number of fax printers DWORD dwNumFaxPrinters; // dwIndex is a counter to enumerate each printer DWORD dwIndex; // dwFlags is the type of print objects to enumerate DWORD dwFlags; #ifdef WIN95 dwFlags = PRINTER_ENUM_LOCAL; #else dwFlags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS; #endif // WIN95 // Enumerate all the printers pFaxPrintersConfig = (LPPRINTER_INFO_2) LocalEnumPrinters(dwFlags, 2, &dwNumPrinters); if (!pFaxPrintersConfig) { *pdwNumFaxPrinters = 0; return NULL; } // Determine the number of fax printers for (dwIndex = 0, dwNumFaxPrinters = 0; dwIndex < dwNumPrinters; dwIndex++) { // A fax printer is determined by comparing the name of the current printer driver against the name of the fax printer driver if (!lstrcmpi((pFaxPrintersConfig)[dwIndex].pDriverName, FAX_DRIVER_NAME)) { // Name of the current printer driver and the name of the fax printer driver match // Increment the number of fax printers dwNumFaxPrinters += 1; } } if (dwNumFaxPrinters > 0) { for (dwIndex = 0, dwNumFaxPrinters = 0; dwIndex < dwNumPrinters; dwIndex++) { // A fax printer is determined by comparing the name of the current printer driver against the name of the fax printer driver if (!lstrcmpi((pFaxPrintersConfig)[dwIndex].pDriverName, FAX_DRIVER_NAME)) { // Name of the current printer driver and the name of the fax printer driver match // Move fax printer up to the next available slot pFaxPrintersConfig[dwNumFaxPrinters] = pFaxPrintersConfig[dwIndex]; // Increment the number of fax printers dwNumFaxPrinters++; } } // Quick sort the fax printers qsort(pFaxPrintersConfig, dwNumFaxPrinters, sizeof(PRINTER_INFO_2), ComparePrinterNames); } else { MemFree(pFaxPrintersConfig); pFaxPrintersConfig = NULL; } *pdwNumFaxPrinters = dwNumFaxPrinters; return pFaxPrintersConfig; } LPTSTR GetDefaultPrinterName( ) /*++ Routine Description: Get the default printer Return Value: Name of the default printer --*/ { // szPrinterName is the printer name LPTSTR szPrinterName; #ifdef WIN95 // pPrintersConfig is a pointer to the printers configuration LPPRINTER_INFO_5 pPrintersConfig; // dwNumPrinters is the number of printers DWORD dwNumPrinters; // Enumerate all the printers pPrintersConfig = (LPPRINTER_INFO_5) LocalEnumPrinters(PRINTER_ENUM_DEFAULT, 5, &dwNumPrinters); if (!pPrintersConfig) { return NULL; } // Allocate the memory for the printer name szPrinterName = (LPTSTR) MemAlloc((lstrlen(pPrintersConfig->pPrinterName) + 1) * sizeof(TCHAR)); // Copy the printer name lstrcpy(szPrinterName, pPrintersConfig->pPrinterName); MemFree(pPrintersConfig); return szPrinterName; #else DWORD cb; // Get the default printer cb = 0; if ((!GetDefaultPrinter(NULL, &cb)) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { // GetDefaultPrinter failed because the buffer is too small // cb is the size of the buffer needed, so allocate a buffer of that size szPrinterName = (LPTSTR) MemAlloc(cb * sizeof(TCHAR)); // Call GetDefaultPrinter again with the correct size buffer if (!GetDefaultPrinter(szPrinterName, &cb)) { // GetDefaultPrinter failed MemFree(szPrinterName); // Return NULL pointer return NULL; } // Return pointer to the buffer return szPrinterName; } // Return NULL pointer return NULL; #endif // WIN95 } VOID SetDefaultPrinterName( LPTSTR szPrinterName ) /*++ Routine Description: Set the default printer Arguments: szPrinterName - name of the printer to set as the default Return Value: None --*/ { #ifdef WIN95 // hPrinter is the handle to the printer HANDLE hPrinter; // pPrintersConfig is a pointer to the printers configuration LPPRINTER_INFO_2 pPrintersConfig; DWORD cb; // Open the printer if (OpenPrinter(szPrinterName, &hPrinter, NULL)) { // Get the printer cb = 0; if ((!GetPrinter(hPrinter, 2, NULL, 0, &cb)) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { // GetPrinter failed because the buffer is too small // cb is the size of the buffer needed, so allocate a buffer of that size pPrintersConfig = (LPPRINTER_INFO_2) MemAlloc(cb); // Call GetPrinter again with the correct size buffer if (!GetPrinter(hPrinter, 2, (LPBYTE) pPrintersConfig, cb, &cb)) { // GetPrinter failed MemFree(pPrintersConfig); // Close the printer ClosePrinter(hPrinter); // Return return; } // Set the default attribute pPrintersConfig->Attributes |= PRINTER_ATTRIBUTE_DEFAULT; // Set the printer SetPrinter(hPrinter, 2, (LPBYTE) pPrintersConfig, 0); MemFree(pPrintersConfig); } // Close the printer ClosePrinter(hPrinter); } #else // Set the default printer SetDefaultPrinter(szPrinterName); #endif // WIN95 } VOID Disconnect( ) { // Wait for access to these fax service routines WaitForSingleObject(g_hFaxSvcMutex, INFINITE); // Decrement the number of connections to the fax service g_nNumConnections--; // Disconnect from the fax service if no outstanding connections if (!g_nNumConnections) { FaxClose(g_hFaxSvcHandle); g_hFaxSvcHandle = NULL; } ReleaseMutex(g_hFaxSvcMutex); } BOOL Connect( ) { BOOL bVal = FALSE; // Wait for access to these fax service routines WaitForSingleObject(g_hFaxSvcMutex, INFINITE); // Connect to the fax service if not already connected if ((g_nNumConnections) || (FaxConnectFaxServer(g_szMachineName, &g_hFaxSvcHandle))) { // Increment the number of connections to the fax service g_nNumConnections++; bVal = TRUE; } ReleaseMutex(g_hFaxSvcMutex); return bVal; } LPTSTR GetColumnItemText( eListViewColumnIndex eColumnIndex, PFAX_JOB_ENTRY pFaxJobEntry, LPTSTR szDeviceName ) /*++ Routine Description: Build a string containing the text of a column item to be added to the list view Arguments: eColumnIndex - indicates the column number pFaxJobEntry - pointer to the fax job szDeviceName - device name the fax job is active on Return Value: LPTSTR - text of the column item --*/ { // szColumnItem is the text of the column item LPTSTR szColumnItem; // szResourceString is a resource string TCHAR szResourceString[RESOURCE_STRING_LEN]; // uResource is the id of the resource string UINT uResource; DWORD cb; switch (eColumnIndex) { case eDocumentName: // szNullString is the null resource string TCHAR szNullString[RESOURCE_STRING_LEN]; // Determine the queue status resource string if (pFaxJobEntry->QueueStatus & JS_DELETING) { uResource = IDS_QUEUE_STATUS_DELETING; } else if (pFaxJobEntry->QueueStatus & JS_PAUSED) { uResource = IDS_QUEUE_STATUS_PAUSED; } else if (pFaxJobEntry->QueueStatus & JS_RETRYING) { uResource = IDS_QUEUE_STATUS_RETRYING; } else { uResource = 0; } // Load the queue status resource string, if necessary, and determine its memory requirement cb = 0; if (uResource) { LoadString(g_hInstance, uResource, szResourceString, RESOURCE_STRING_LEN); cb = lstrlen(szResourceString) * sizeof(TCHAR); } if (pFaxJobEntry->DocumentName) { cb += (lstrlen(pFaxJobEntry->DocumentName) + 1) * sizeof(TCHAR); } else { // Load the null resource string LoadString(g_hInstance, IDS_NO_DOCUMENT_NAME, szNullString, RESOURCE_STRING_LEN); cb += (lstrlen(szNullString) + 1) * sizeof(TCHAR); } #ifdef DEBUG if (WinPosInfo.bDebug) { cb += lstrlen(TEXT("0x00000000 ")) * sizeof(TCHAR); } #endif // DEBUG // Allocate the memory for the document name and set the document name szColumnItem = (LPTSTR) MemAlloc(cb); if (szColumnItem) { #ifdef DEBUG if (WinPosInfo.bDebug) { wsprintf(szColumnItem, TEXT("0x%08x "), pFaxJobEntry->JobId); } if (pFaxJobEntry->DocumentName) { lstrcat(szColumnItem, pFaxJobEntry->DocumentName); } else { lstrcat(szColumnItem, szNullString); } #else if (pFaxJobEntry->DocumentName) { lstrcpy(szColumnItem, pFaxJobEntry->DocumentName); } else { lstrcpy(szColumnItem, szNullString); } #endif // DEBUG if (uResource) { lstrcat(szColumnItem, szResourceString); } return szColumnItem; } return NULL; case eJobType: // Determine the job type resource string switch (pFaxJobEntry->JobType) { case JT_SEND: uResource = IDS_JOB_TYPE_SEND; break; case JT_RECEIVE: uResource = IDS_JOB_TYPE_RECEIVE; break; case JT_ROUTING: uResource = IDS_JOB_TYPE_ROUTING; break; case JT_FAIL_RECEIVE: uResource = IDS_JOB_TYPE_FAIL_RECEIVE; break; default: uResource = 0; break; } // Load the job type resource string, if necessary if (uResource) { LoadString(g_hInstance, uResource, szResourceString, RESOURCE_STRING_LEN); // Allocate the memory for the job type and set the job type szColumnItem = (LPTSTR) MemAlloc((lstrlen(szResourceString) + 1) * sizeof(TCHAR)); if (szColumnItem) { lstrcpy(szColumnItem, szResourceString); return szColumnItem; } } return NULL; case eStatus: // Determine the job status resource string switch (pFaxJobEntry->Status) { case FPS_DIALING: uResource = IDS_JOB_STATUS_DIALING; break; case FPS_SENDING: uResource = IDS_JOB_STATUS_SENDING; break; case FPS_RECEIVING: uResource = IDS_JOB_STATUS_RECEIVING; break; case FPS_COMPLETED: uResource = IDS_JOB_STATUS_COMPLETED; break; case FPS_HANDLED: uResource = IDS_JOB_STATUS_HANDLED; break; case FPS_UNAVAILABLE: uResource = IDS_JOB_STATUS_UNAVAILABLE; break; case FPS_BUSY: uResource = IDS_JOB_STATUS_BUSY; break; case FPS_NO_ANSWER: uResource = IDS_JOB_STATUS_NO_ANSWER; break; case FPS_BAD_ADDRESS: uResource = IDS_JOB_STATUS_BAD_ADDRESS; break; case FPS_NO_DIAL_TONE: uResource = IDS_JOB_STATUS_NO_DIAL_TONE; break; case FPS_DISCONNECTED: uResource = IDS_JOB_STATUS_DISCONNECTED; break; case FPS_FATAL_ERROR: if (pFaxJobEntry->JobType == JT_RECEIVE) { uResource = IDS_JOB_STATUS_FATAL_ERROR_RCV; } else { uResource = IDS_JOB_STATUS_FATAL_ERROR_SND; } break; case FPS_NOT_FAX_CALL: uResource = IDS_JOB_STATUS_NOT_FAX_CALL; break; case FPS_CALL_DELAYED: uResource = IDS_JOB_STATUS_CALL_DELAYED; break; case FPS_CALL_BLACKLISTED: uResource = IDS_JOB_STATUS_CALL_BLACKLISTED; break; case FPS_INITIALIZING: uResource = IDS_JOB_STATUS_INITIALIZING; break; case FPS_OFFLINE: uResource = IDS_JOB_STATUS_OFFLINE; break; case FPS_RINGING: uResource = IDS_JOB_STATUS_RINGING; break; case FPS_AVAILABLE: uResource = IDS_JOB_STATUS_AVAILABLE; break; case FPS_ABORTING: uResource = IDS_JOB_STATUS_ABORTING; break; case FPS_ROUTING: uResource = IDS_JOB_STATUS_ROUTING; break; case FPS_ANSWERED: uResource = IDS_JOB_STATUS_ANSWERED; break; default: uResource = 0; break; } // Determine if retries have been exceeded if (((pFaxJobEntry->JobType == JT_SEND) || (pFaxJobEntry->JobType == JT_ROUTING)) && (pFaxJobEntry->QueueStatus & JS_RETRIES_EXCEEDED)) { uResource = IDS_QUEUE_STATUS_RETRIES_EXCEEDED; } // Load the job status resource string, if necessary if (uResource) { LoadString(g_hInstance, uResource, szResourceString, RESOURCE_STRING_LEN); // Allocate the memory for the job status and set the job type if (uResource == IDS_JOB_STATUS_DIALING) { szColumnItem = (LPTSTR) MemAlloc((lstrlen(szResourceString) + lstrlen(pFaxJobEntry->RecipientNumber) + 1) * sizeof(TCHAR)); } else { szColumnItem = (LPTSTR) MemAlloc((lstrlen(szResourceString) + 1) * sizeof(TCHAR)); } if (szColumnItem) { if (uResource == IDS_JOB_STATUS_DIALING) { wsprintf(szColumnItem, szResourceString, pFaxJobEntry->RecipientNumber); } else { lstrcpy(szColumnItem, szResourceString); } return szColumnItem; } } return NULL; case eOwner: // Allocate the memory for the job owner and set the job owner, if necessary if (pFaxJobEntry->UserName) { szColumnItem = (LPTSTR) MemAlloc((lstrlen(pFaxJobEntry->UserName) + 1) * sizeof(TCHAR)); if (szColumnItem) { lstrcpy(szColumnItem, pFaxJobEntry->UserName); return szColumnItem; } } return NULL; case ePages: // Set the job pages resource string, if necessary if (pFaxJobEntry->PageCount) { wsprintf(szResourceString, TEXT("%d"), pFaxJobEntry->PageCount); // Allocate the memory for the job pages and set the job pages szColumnItem = (LPTSTR) MemAlloc((lstrlen(szResourceString) + 1) * sizeof(TCHAR)); if (szColumnItem) { lstrcpy(szColumnItem, szResourceString); return szColumnItem; } } return NULL; case eSize: // Determine the job size resource string if (pFaxJobEntry->Size) { // szNumberString is the number string LPTSTR szNumberString; if (pFaxJobEntry->Size < 1024) { uResource = IDS_JOB_SIZE_BYTES; // Set the job size number string wsprintf(szResourceString, TEXT("%u"), pFaxJobEntry->Size); } else if (pFaxJobEntry->Size < 1024 * 1024) { uResource = IDS_JOB_SIZE_KBYTES; // Set the job size number string wsprintf(szResourceString, TEXT("%u.%2u"), pFaxJobEntry->Size / 1024, pFaxJobEntry->Size % 1024); } else if (pFaxJobEntry->Size < 1024 * 1024 * 1024) { uResource = IDS_JOB_SIZE_MBYTES; // Set the job size number string wsprintf(szResourceString, TEXT("%u.%2u"), pFaxJobEntry->Size / (1024 * 1024), pFaxJobEntry->Size % (1024 * 1024)); } else { uResource = IDS_JOB_SIZE_GBYTES; // Set the job size number string wsprintf(szResourceString, TEXT("%u.%2u"), pFaxJobEntry->Size / (1024 * 1024 * 1024), pFaxJobEntry->Size % (1024 * 1024 * 1024)); } // Format the number string cb = GetNumberFormat(LOCALE_USER_DEFAULT, 0, szResourceString, NULL, NULL, 0); szNumberString = (LPTSTR) MemAlloc((cb + 1) * sizeof(TCHAR)); if (szNumberString) { GetNumberFormat(LOCALE_USER_DEFAULT, 0, szResourceString, NULL, szNumberString, cb); LoadString(g_hInstance, uResource, szResourceString, RESOURCE_STRING_LEN); // Allocate the memory for the job size and set the job size szColumnItem = (LPTSTR) MemAlloc((lstrlen(szNumberString) + lstrlen(szResourceString) + 1) * sizeof(TCHAR)); if (szColumnItem) { wsprintf(szColumnItem, szResourceString, szNumberString); MemFree(szNumberString); return szColumnItem; } MemFree(szNumberString); } } return NULL; case eScheduledTime: // Set the job scheduled time resource string if (pFaxJobEntry->ScheduleAction == JSA_NOW) { LoadString(g_hInstance, IDS_JOB_SCHEDULED_TIME_NOW, szResourceString, RESOURCE_STRING_LEN); } else { // Convert the schedule time to the local time zone SystemTimeToTzSpecificLocalTime(NULL, &pFaxJobEntry->ScheduleTime, &pFaxJobEntry->ScheduleTime); GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &pFaxJobEntry->ScheduleTime, NULL, szResourceString, RESOURCE_STRING_LEN); lstrcat(szResourceString, TEXT(" ")); cb = lstrlen(szResourceString); GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &pFaxJobEntry->ScheduleTime, NULL, &szResourceString[cb], RESOURCE_STRING_LEN - cb); } // Allocate the memory for the job schedule time and set the job schedule time szColumnItem = (LPTSTR) MemAlloc((lstrlen(szResourceString) + 1) * sizeof(TCHAR)); if (szColumnItem) { lstrcpy(szColumnItem, szResourceString); return szColumnItem; } return NULL; case ePort: // Allocate the memory for the job port and set the job port, if necessary if (szDeviceName) { szColumnItem = (LPTSTR) MemAlloc((lstrlen(szDeviceName) + 1) * sizeof(TCHAR)); if (szColumnItem) { lstrcpy(szColumnItem, szDeviceName); return szColumnItem; } } return NULL; case eIllegalColumnIndex: break; } return NULL; } VOID SetColumnItem( HWND hWndListView, BOOL bInsert, INT iItem, INT iSubItem, LPTSTR szColumnItem, UINT uState, PFAX_JOB_ENTRY pFaxJobEntry ) /*++ Routine Description: Set or insert a column item in the list view Arguments: hWndListView - handle to the list view window bInsert - indicates item is to be inserted into the list view iItem - index of the item iSubItem - index of the subitem szColumnItem - column item text uState - state of the item pFaxJobEntry - pointer to the fax job Return Value: None --*/ { // lvi specifies the attributes of a particular item in the list view LV_ITEM lvi; // Initialize lvi lvi.mask = LVIF_TEXT; // Set the item number lvi.iItem = iItem; // Set the subitem number lvi.iSubItem = iSubItem; // Set the item text lvi.pszText = szColumnItem; if (iSubItem == (INT) eDocumentName) { // Include the fax job id in the lParam lvi.mask = lvi.mask | LVIF_PARAM | LVIF_STATE; // Set the lParam lvi.lParam = pFaxJobEntry->JobId; // Set the item state lvi.state = uState; if (pFaxJobEntry->JobType == JT_SEND) { lvi.state |= ITEM_SEND_MASK; } if (!(pFaxJobEntry->QueueStatus & JS_INPROGRESS)) { lvi.state |= ITEM_IDLE_MASK; } if (pFaxJobEntry->QueueStatus & JS_PAUSED) { lvi.state |= ITEM_PAUSED_MASK; } if ((g_szCurrentUserName) && (!lstrcmpi(g_szCurrentUserName, pFaxJobEntry->UserName))) { lvi.state |= ITEM_USEROWNSJOB_MASK; } // Set the item state mask lvi.stateMask = uState | LVIS_OVERLAYMASK; } if ((bInsert) && (iSubItem == (INT) eDocumentName)) { ListView_InsertItem(hWndListView, &lvi); } else { ListView_SetItem(hWndListView, &lvi); } }