/*++ Copyright (c) 1999 Microsoft Corporation Module Name: print.c Abstract: This file implements basic printer functionality Author: Asaf Shaar (asafs) 28-Nov-1999 Environment: User Mode --*/ #include #include #include #include #include #include #include #include /*++ Routine Description: Wrapper function for EnumPrinters API Arguments: pServerName - Server name (NULL for current server) dwLevel - Specifies PRINTER_INFO level to be returned pcPrinters - Returns the number of printers found dwFlags - Specifies the type of printer objects to be enumerated level - pCount - Return Value: Pointer to an array of PRINTER_INFO_x structures NULL if there is an error --*/ PVOID MyEnumPrinters( LPTSTR pServerName, DWORD dwLevel, PDWORD pcPrinters, DWORD dwFlags ) { PBYTE pPrinterInfo = NULL; DWORD cb = 0; DWORD Error = ERROR_SUCCESS; if (!dwFlags) { dwFlags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS; } if (!EnumPrinters(dwFlags, pServerName, dwLevel, NULL, 0, &cb, pcPrinters)) { Error = GetLastError(); if ( Error == ERROR_INSUFFICIENT_BUFFER && (pPrinterInfo = (PBYTE) MemAlloc(cb)) != NULL) { if (EnumPrinters(dwFlags, pServerName, dwLevel, pPrinterInfo, cb, &cb, pcPrinters)) { return pPrinterInfo; } Error = GetLastError(); } } MemFree(pPrinterInfo); SetLastError(Error); return NULL; } /*++ Routine Description: Returns the name of the first Fax printer on the local machine: for LOCAL fax printer use GetFirstLocalFaxPrinterName. for REMOTE fax printer use GetFirstRemoteFaxPrinterName. Arguments: OUT lptstrPrinterName - A buffer to hold the returned printer name. IN dwPrintNameInChars - The size of the buffer in characters (including the space for terminating null) Return Value: TRUE if the function succeeded and found a fax printer. FALSE if the function failed or did not find a fax printer. If a printer was not found then GetLastError() will report ERROR_PRINTER_NOT_FOUND. --*/ BOOL GetFirstFaxPrinterName( OUT LPTSTR lptstrPrinterName, IN DWORD dwMaxLenInChars, IN DWORD dwFlag) { PPRINTER_INFO_2 pPrinterInfo = NULL; DWORD dwNumPrinters; DWORD dwPrinter; DWORD ec = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("GetFirstFaxPrinterName")); SetLastError (ERROR_SUCCESS); pPrinterInfo = (PPRINTER_INFO_2) MyEnumPrinters(NULL, 2, &dwNumPrinters, dwFlag ); if (!pPrinterInfo) { // // Either error on no printers // ec = GetLastError(); if (ERROR_SUCCESS == ec) { // // Not an error - no printers // SetLastError (ERROR_PRINTER_NOT_FOUND); return FALSE; } DebugPrintEx( DEBUG_ERR, TEXT("MyEnumPrinters() failed (ec: %ld)"), ec); goto Error; } for (dwPrinter=0; dwPrinter < dwNumPrinters; dwPrinter++) { if (!_tcscmp(pPrinterInfo[dwPrinter].pDriverName,FAX_DRIVER_NAME)) { memset(lptstrPrinterName,0,dwMaxLenInChars*sizeof(TCHAR)); _tcsncpy(lptstrPrinterName,pPrinterInfo[dwPrinter].pPrinterName,dwMaxLenInChars-1); goto Exit; } } ec = ERROR_PRINTER_NOT_FOUND; goto Error; Error: Assert (ERROR_SUCCESS != ec); Exit: MemFree(pPrinterInfo); pPrinterInfo = NULL; if (ERROR_SUCCESS != ec) { SetLastError(ec); return FALSE; } return (ERROR_SUCCESS == ec); } BOOL GetFirstLocalFaxPrinterName( OUT LPTSTR lptstrPrinterName, IN DWORD dwMaxLenInChars) { return GetFirstFaxPrinterName(lptstrPrinterName,dwMaxLenInChars,PRINTER_ENUM_LOCAL); } BOOL GetFirstRemoteFaxPrinterName( OUT LPTSTR lptstrPrinterName, IN DWORD dwMaxLenInChars) { return GetFirstFaxPrinterName(lptstrPrinterName,dwMaxLenInChars,PRINTER_ENUM_CONNECTIONS); } // // // Function: GetPrinterInfo // Description: Returns a pointer to PRINTER_INFO_2 of the specified printer name. // If the printer was not found or there was an error than the function // return NULL. To get extended error information, call GetLastError(). // // Remarks: The caller must release the allocated memory with MemFree() // // Args: LPTSTR lptstrPrinterName : The name of the printer. // // Author: AsafS PPRINTER_INFO_2 GetFaxPrinterInfo( LPCTSTR lptstrPrinterName ) { DEBUG_FUNCTION_NAME(TEXT("GetPrinterInfo")) DWORD ec = ERROR_SUCCESS; PPRINTER_INFO_2 pPrinterInfo = NULL; DWORD dwNeededSize = 0; BOOL result = FALSE; HANDLE hPrinter = NULL; if (!OpenPrinter( (LPTSTR) lptstrPrinterName, &hPrinter, NULL)) { ec = GetLastError(); DebugPrintEx( DEBUG_ERR, TEXT("A printer with %s name was not found (ec: %ld)."), lptstrPrinterName, GetLastError() ); goto Exit; } result = GetPrinter( hPrinter, 2, NULL, 0, &dwNeededSize ); if (!result) { if ( (ec = GetLastError()) != ERROR_INSUFFICIENT_BUFFER ) { DebugPrintEx( DEBUG_ERR, TEXT("GetPrinter return an unexpected result or error (ec: %ld)."), ec ); goto Exit; } } pPrinterInfo = (PPRINTER_INFO_2) MemAlloc(dwNeededSize); if (!pPrinterInfo) { ec = ERROR_NOT_ENOUGH_MEMORY; goto Exit; } result = GetPrinter( hPrinter, 2, (LPBYTE) pPrinterInfo, dwNeededSize, &dwNeededSize ); if (!result) { ec = GetLastError(); DebugPrintEx( DEBUG_ERR, TEXT("GetPrinter failed in second call (ec: %ld)."), ec ); MemFree(pPrinterInfo); pPrinterInfo = NULL; goto Exit; } Exit: SetLastError(ec); if (hPrinter) { if (!ClosePrinter(hPrinter)) { DebugPrintEx( DEBUG_ERR, TEXT("ClosePrinter failed with %ld"), GetLastError () ); } } return pPrinterInfo; } // GetFaxPrinterInfo /////////////////////////////////////////////////////////////////////////////////////// // Function: // IsPrinterFaxPrinter // // Purpose: determines whether the input printer name is a valid // fax printer by checking the driver name // // Params: // LPTSTR PrinterName - printer name to evaluate // // Return Value: // TRUE - printer is a valid fax printer // FALSE - otherwise // // Author: // Mooly Beery (MoolyB) 21-Aug-2001 /////////////////////////////////////////////////////////////////////////////////////// BOOL IsPrinterFaxPrinter(LPTSTR PrinterName) { DWORD Rval = FALSE; LPPRINTER_INFO_2 lpPrinterInfo = NULL; DEBUG_FUNCTION_NAME(TEXT("IsPrinterFaxPrinter")) lpPrinterInfo = GetFaxPrinterInfo(PrinterName); if (lpPrinterInfo==NULL) { DebugPrintEx(DEBUG_ERR,_T("GetFaxPrinterInfo failed with %ld."),GetLastError()); return FALSE; } if (_tcscmp( lpPrinterInfo->pDriverName, FAX_DRIVER_NAME ) == 0) { Rval = TRUE; } else { Rval = FALSE; } MemFree( lpPrinterInfo ); return Rval; } DWORD IsLocalFaxPrinterInstalled( LPBOOL lpbLocalFaxPrinterInstalled ) /*++ Routine name : IsLocalFaxPrinterInstalled Routine description: Checks if a local fax printer is installed and not marked for deletion. Author: Eran Yariv (EranY), Jul, 2000 Arguments: lpbLocalFaxPrinterInstalled [out] - Result flag Return Value: Standard Win32 error code --*/ { TCHAR tszPrinterName[MAX_PATH * 3] = TEXT("\0"); DWORD dwErr; PPRINTER_INFO_2 pi2 = NULL; DEBUG_FUNCTION_NAME(TEXT("IsLocalFaxPrinterInstalled")) if (!GetFirstLocalFaxPrinterName (tszPrinterName, sizeof (tszPrinterName) / sizeof (tszPrinterName[0]))) { dwErr = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("GetFirstLocalFaxPrinterName failed with %ld."), dwErr); if (ERROR_PRINTER_NOT_FOUND == dwErr) { // // Local fax printer is not installed // *lpbLocalFaxPrinterInstalled = FALSE; return ERROR_SUCCESS; } Assert (ERROR_SUCCESS != dwErr); return dwErr; } // // Local fax printer is installed // Let's see if it is PRINTER_STATUS_PENDING_DELETION. // If so, let's return FALSE because the printer will be gone soon. // If someone will call AddPrinter because we return FALSE, it's OK. See AddPrinter() remarks. // Assert (lstrlen (tszPrinterName)); pi2 = GetFaxPrinterInfo (tszPrinterName); if (!pi2) { dwErr = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("GetFaxPrinterInfo failed with %ld."), dwErr); // // Printer is installed but somehow I can't get it's info - weird // Assert (ERROR_SUCCESS != dwErr); return dwErr; } if ((pi2->Status) & PRINTER_STATUS_PENDING_DELETION) { // // Printer is there but is marked for deletion // DebugPrintEx( DEBUG_MSG, TEXT("Printer %s is installed but marked for deletion. Reported as non-existant"), tszPrinterName); *lpbLocalFaxPrinterInstalled = FALSE; } else { *lpbLocalFaxPrinterInstalled = TRUE; } MemFree (pi2); return ERROR_SUCCESS; } // IsLocalFaxPrinterInstalled DWORD IsLocalFaxPrinterShared ( LPBOOL lpbShared ) /*++ Routine name : IsLocalFaxPrinterShared Routine description: Detects if the local fax printer is shared Author: Eran Yariv (EranY), Jul, 2000 Arguments: lpbShared [out] - Sharing flag Return Value: Standard Win32 error code --*/ { TCHAR tszPrinterName[MAX_PATH * 3]; DWORD dwErr; PPRINTER_INFO_2 pInfo2; DEBUG_FUNCTION_NAME(TEXT("IsLocalFaxPrinterShared")) if (!GetFirstLocalFaxPrinterName (tszPrinterName, sizeof (tszPrinterName) / sizeof (tszPrinterName[0]))) { dwErr = GetLastError (); if (ERROR_PRINTER_NOT_FOUND == dwErr) { // // Local fax printer is not installed // *lpbShared = FALSE; return ERROR_SUCCESS; } DebugPrintEx( DEBUG_ERR, TEXT("GetFirstLocalFaxPrinterName failed with %ld."), dwErr); return dwErr; } pInfo2 = GetFaxPrinterInfo (tszPrinterName); if (!pInfo2) { dwErr = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("GetFaxPrinterInfo failed with %ld."), dwErr); return dwErr; } *lpbShared = ((pInfo2->Attributes) & PRINTER_ATTRIBUTE_SHARED) ? TRUE : FALSE; MemFree (pInfo2); return ERROR_SUCCESS; } // IsLocalFaxPrinterShared DWORD AddLocalFaxPrinter ( LPCTSTR lpctstrPrinterName, LPCTSTR lpctstrPrinterDescription ) /*++ Routine name : AddLocalFaxPrinter Routine description: Adds a local fax printer Author: Eran Yariv (EranY), Jul, 2000 Arguments: lpctstrPrinterName [in] - Printer name lpctstrPrinterDescription [in] - Printer comments (description) Return Value: Standard Win32 error code Remarks: This function should not be called if a local fax printer is installed. --*/ { DWORD ec = ERROR_SUCCESS; HANDLE hPrinter = NULL; PRINTER_INFO_2 PrinterInfo2 = {0}; BOOL bLocalPrinterInstalled; BOOL bIsFaxPrinterShared = FALSE; DWORD dwAttributes = PRINTER_ATTRIBUTE_LOCAL | PRINTER_ATTRIBUTE_FAX; LPCTSTR lpctstrShareName = NULL; DEBUG_FUNCTION_NAME(TEXT("AddLocalFaxPrinter")) ec = IsLocalFaxPrinterInstalled (&bLocalPrinterInstalled); if (ERROR_SUCCESS == ec && bLocalPrinterInstalled) { // // Local fax printer already installed // return ec; } // // Check if this is SKU supports fax sharing. // If it does not - do not share printer. // if (IsFaxShared()) { // We can share the printer on this SKU. Let's check if Fax is // installed in Sharing enabled mode. HKEY hFaxKey = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_FAX_SETUP,FALSE,KEY_READ); if (hFaxKey) { if (GetRegistryDword(hFaxKey,REGVAL_IS_SHARED_FAX_PRINTER)) { DebugPrintEx(DEBUG_MSG, TEXT("Fax is installed in a mode that enables sharing")); bIsFaxPrinterShared = TRUE; } else { DebugPrintEx(DEBUG_MSG, TEXT("Fax is installed in a mode that does not enable sharing")); } RegCloseKey(hFaxKey); } else { DebugPrintEx(DEBUG_WRN, TEXT("Failed to open REGKEY_FAX_SETUP, printer won't be shared (ec=%d)"),GetLastError()); } } if (bIsFaxPrinterShared) { dwAttributes |= PRINTER_ATTRIBUTE_SHARED; lpctstrShareName = lpctstrPrinterName; } PrinterInfo2.pServerName = NULL; PrinterInfo2.pPrinterName = (LPTSTR) lpctstrPrinterName; PrinterInfo2.pPortName = FAX_MONITOR_PORT_NAME; PrinterInfo2.pDriverName = FAX_DRIVER_NAME; PrinterInfo2.pPrintProcessor = TEXT("WinPrint"); PrinterInfo2.pDatatype = TEXT("RAW"); PrinterInfo2.Attributes = dwAttributes; PrinterInfo2.pShareName = (LPTSTR) lpctstrShareName; PrinterInfo2.pComment = (LPTSTR) lpctstrPrinterDescription; hPrinter = AddPrinter(NULL, 2, (LPBYTE)&PrinterInfo2); if (hPrinter == NULL) { ec = GetLastError(); DebugPrintEx( DEBUG_ERR, TEXT("AddPrinter failed with %ld."), ec); } else { if (IsFaxShared() && bIsFaxPrinterShared) { // // Publish the printer in the DS // PRINTER_INFO_7 pi7; pi7.pszObjectGUID = NULL; pi7.dwAction = DSPRINT_PUBLISH; if (!SetPrinter(hPrinter, // handle to printer object 7, // information level (LPBYTE)&pi7, // printer data buffer 0 // printer-state command )) { DebugPrintEx(DEBUG_ERR,TEXT("SetPrinter failed with %ld."),GetLastError()); // // In any case we do not want to fail the whole setup just because we were // unable to publish the printer on the DS. // common error codes are: // // ERROR_IO_PENDING means SetPrinter is trying to publish the printer in the // background, we do not wait for it to succeed/fail. // // ERROR_DS_UNAVAILABLE means the DS is not accesible. // } } if (!ClosePrinter(hPrinter)) { DebugPrintEx( DEBUG_ERR, TEXT("ClosePrinter failed with %ld."), GetLastError ()); } hPrinter = NULL; RefreshPrintersAndFaxesFolder(); } return ec; } // AddLocalFaxPrinter //********************************************************************************* //* Name: ParamTagsToString() //* Author: Ronen Barenboim //* Date: March 23, 1999 //********************************************************************************* //* DESCRIPTION: //* Writes a collection of tag parameters and values in the format of a parameter //* string into a caller provided buffer. // Reports the size of the tagged string. //* PARAMETERS: //* lpTagMap //* A pointer to an array of FAX_TAG_MAP_ENTRY structures that contain the //* tag names and values. //* dwTagCount //* The number of entries in the tag map array. //* lpTargetBuf //* A pointer to a buffer where the tag value string will be placed. //* The size of this buffer must be big enough to hold the resulting string // including a terminating NULL char. //* If this parameter is NULL the function will not generate the tag value //* string and only report its size in *lpdwSize; //* lpdwSize //* A pointer to a DWORD that will accept the size of the resulting //* tagged string in BYTES. The size DOES NOT INCLUDE the terminating NULL char. //* RETURN VALUE: //* NONE //* REMARKS: //* The format of the resulting string is: //* Tag1Value1Tag2Value2....TagNValueN'\0' //********************************************************************************* void ParamTagsToString( FAX_TAG_MAP_ENTRY * lpTagMap, DWORD dwTagCount, LPTSTR lpTargetBuf, LPDWORD lpdwSize) { DWORD index; LPTSTR p; DWORD dwSize = 0; // // Calculate string size WITHOUT termianting NULL // for (index=0; index Free(pidlPF); } // // Release the shell allocator // pShellMalloc->Release(); } return hr; } // RefreshPrintersAndFaxesFolder #ifdef UNICODE PPRINTER_NAMES CollectPrinterNames ( LPDWORD lpdwNumPrinters, BOOL bFilterOutFaxPrinters ) /*++ Routine name : CollectPrinterNames Routine description: Creates a list of printer names for all visible local and remote printers Author: Eran Yariv (EranY), Apr, 2001 Arguments: lpdwNumPrinters [out] - Number of elements in the list bFilterOutFaxPrinters [in] - If TRUE, fax printers are not returned in the list Return Value: Allocated list of printers names. If NULL, an error has occurred - check LastError. Use ReleasePrinterNames() to release allocated value. --*/ { DWORD dwPrinter; DWORD dwNumPrinters; DWORD dwIndex = 0; BOOL bSuccess = FALSE; PPRINTER_INFO_2 pPrinterInfo = NULL; PPRINTER_NAMES pRes = NULL; DEBUG_FUNCTION_NAME(TEXT("ReleasePrinterNames")); SetLastError (ERROR_SUCCESS); pPrinterInfo = (PPRINTER_INFO_2) MyEnumPrinters(NULL, // Local machine 2, // Level 2 &dwNumPrinters, // [out] Number of printers found 0 // Both local and remote ); if (!pPrinterInfo) { // // Either error on no printers // DWORD ec = GetLastError(); if (ERROR_SUCCESS == ec) { // // Not an error - no printers // SetLastError (ERROR_PRINTER_NOT_FOUND); return NULL; } DebugPrintEx( DEBUG_ERR, TEXT("MyEnumPrinters() failed (ec: %ld)"), ec); return NULL; } Assert (dwNumPrinters > 0); if (bFilterOutFaxPrinters) { // // Counter number of printers w/out the fax printer(s) // DWORD dwNewPrintersCount = 0; for (dwPrinter = 0; dwPrinter < dwNumPrinters; dwPrinter++) { if (_tcscmp(pPrinterInfo[dwPrinter].pDriverName,FAX_DRIVER_NAME)) { // // Not a fax printer // dwNewPrintersCount++; } } if (!dwNewPrintersCount) { // // Only fax printers - return NULL // SetLastError (ERROR_PRINTER_NOT_FOUND); goto exit; } *lpdwNumPrinters = dwNewPrintersCount; } else { *lpdwNumPrinters = dwNumPrinters; } pRes = (PPRINTER_NAMES)MemAlloc (sizeof (PRINTER_NAMES) * (*lpdwNumPrinters)); if (!pRes) { goto exit; } memset (pRes, 0, sizeof (PRINTER_NAMES) * (*lpdwNumPrinters)); for (dwPrinter = 0; dwPrinter < dwNumPrinters; dwPrinter++) { if (bFilterOutFaxPrinters && !_tcscmp(pPrinterInfo[dwPrinter].pDriverName,FAX_DRIVER_NAME)) { // // This is a fax printer and filtering is on - skip it // continue; } pRes[dwIndex].lpcwstrDisplayName = StringDup (pPrinterInfo[dwPrinter].pPrinterName); if (!pRes[dwIndex].lpcwstrDisplayName) { goto exit; } if (pPrinterInfo[dwPrinter].pServerName) { // // Remote printer // WCHAR wszShare[MAX_PATH] = {0}; // // Server name must begin with '\\' // Assert (lstrlen (pPrinterInfo[dwPrinter].pServerName) > 2) Assert ((TEXT('\\') == pPrinterInfo[dwPrinter].pServerName[0]) && (TEXT('\\') == pPrinterInfo[dwPrinter].pServerName[1])); // // Share name cannot be NULL or empty string // Assert (pPrinterInfo[dwPrinter].pShareName && lstrlen(pPrinterInfo[dwPrinter].pShareName)); // // Compose UNC path to print share // if (0 > _snwprintf (wszShare, ARR_SIZE(wszShare) -1, TEXT("%s\\%s"), pPrinterInfo[dwPrinter].pServerName, pPrinterInfo[dwPrinter].pShareName)) { // // Buffer too small // SetLastError (ERROR_GEN_FAILURE); goto exit; } pRes[dwIndex].lpcwstrPath = StringDup (wszShare); } else { // // Local printer // pRes[dwIndex].lpcwstrPath = StringDup (pPrinterInfo[dwPrinter].pPrinterName); } if (!pRes[dwIndex].lpcwstrPath) { goto exit; } dwIndex++; } Assert (dwIndex == *lpdwNumPrinters); bSuccess = TRUE; exit: MemFree (pPrinterInfo); if (!bSuccess) { // // Free data and return NULL // if (pRes) { ReleasePrinterNames (pRes, *lpdwNumPrinters); pRes = NULL; } } return pRes; } // CollectPrinterNames VOID ReleasePrinterNames ( PPRINTER_NAMES pNames, DWORD dwNumPrinters ) /*++ Routine name : ReleasePrinterNames Routine description: Releases the list of printer names returned by CollectPrinterNames(). Author: Eran Yariv (EranY), Apr, 2001 Arguments: pNames [in] - List of printer names dwNumPrinters [in] - Number of elements in the list Return Value: None. --*/ { DWORD dw; DEBUG_FUNCTION_NAME(TEXT("ReleasePrinterNames")); if (!dwNumPrinters) { return; } Assert (pNames); for (dw = 0; dw < dwNumPrinters; dw++) { MemFree ((PVOID)(pNames[dw].lpcwstrDisplayName)); pNames[dw].lpcwstrDisplayName = NULL; MemFree ((PVOID)(pNames[dw].lpcwstrPath)); pNames[dw].lpcwstrPath = NULL; } MemFree ((PVOID)pNames); } // ReleasePrinterNames LPCWSTR FindPrinterNameFromPath ( PPRINTER_NAMES pNames, DWORD dwNumPrinters, LPCWSTR lpcwstrPath ) { DWORD dw; DEBUG_FUNCTION_NAME(TEXT("FindPrinterNameFromPath")); if (!pNames || !dwNumPrinters) { return NULL; } if (!lpcwstrPath) { return NULL; } for (dw = 0; dw < dwNumPrinters; dw++) { if (!lstrcmpi (pNames[dw].lpcwstrPath, lpcwstrPath)) { return pNames[dw].lpcwstrDisplayName; } } return NULL; } // FindPrinterNameFromPath LPCWSTR FindPrinterPathFromName ( PPRINTER_NAMES pNames, DWORD dwNumPrinters, LPCWSTR lpcwstrName ) { DWORD dw; DEBUG_FUNCTION_NAME(TEXT("FindPrinterPathFromName")); if (!pNames || !dwNumPrinters) { return NULL; } if (!lpcwstrName) { return NULL; } for (dw = 0; dw < dwNumPrinters; dw++) { if (!lstrcmpi (pNames[dw].lpcwstrDisplayName, lpcwstrName)) { return pNames[dw].lpcwstrPath; } } return NULL; } // FindPrinterPathFromName #endif // UNICODE BOOL VerifyPrinterIsOnline ( LPCTSTR lpctstrPrinterName ) /*++ Routine name : VerifyPrinterIsOnline Routine description: Verifies a printer is online and shared Author: Eran Yariv (EranY), Apr, 2001 Arguments: lpctstrPrinterName [in] - Printer name Return Value: TRUE if printer is online and shared, FALSE otherwise. --*/ { HANDLE hPrinter = NULL; PRINTER_DEFAULTS pd = {0}; DEBUG_FUNCTION_NAME(TEXT("VerifyPrinterIsOnline")); Assert (lpctstrPrinterName); // // According to Mark Lawrence (NT PRINT), only by opening the printer in admistrator mode, we actually hit the wire. // pd.DesiredAccess = PRINTER_ACCESS_ADMINISTER; if (!OpenPrinter ((LPTSTR)lpctstrPrinterName, &hPrinter, &pd)) { DWORD dwRes = GetLastError (); if (ERROR_ACCESS_DENIED == dwRes) { // // Printer is there - we just can't admin it. // DebugPrintEx( DEBUG_MSG, TEXT("OpenPrinter(%s) failed with ERROR_ACCESS_DENIED - Printer is there - we just can't admin it"), lpctstrPrinterName); return TRUE; } if (ERROR_INVALID_PRINTER_NAME == dwRes) { // // Printer is deleted // DebugPrintEx( DEBUG_ERR, TEXT("OpenPrinter(%s) failed with ERROR_INVALID_PRINTER_NAME - Printer is deleted"), lpctstrPrinterName); return FALSE; } if (RPC_S_SERVER_UNAVAILABLE == dwRes) { // // Printer is not shared / server is unreachable // DebugPrintEx( DEBUG_ERR, TEXT("OpenPrinter(%s) failed with RPC_SERVER_UNAVAILABLE - Printer is not shared / server is unreachable"), lpctstrPrinterName); return FALSE; } else { // // Any other error - assume printer is not valid // DebugPrintEx( DEBUG_ERR, TEXT("OpenPrinter(%s) failed with %ld - assuming printer is not valid"), lpctstrPrinterName, dwRes); return FALSE; } } // // Printer succesfully opened - it's online // DebugPrintEx( DEBUG_MSG, TEXT("OpenPrinter(%s) succeeded - Printer is there"), lpctstrPrinterName); ClosePrinter (hPrinter); return TRUE; } // VerifyPrinterIsOnline VOID FaxPrinterProperty(DWORD dwPage) /*++ Routine name : FaxPrinterProperty Routine description: Opens fax printer properties sheet Arguments: dwPage [in] - Initial page number Return Value: none --*/ { HWND hWndFaxMon = NULL; DEBUG_FUNCTION_NAME(TEXT("FaxPrinterProperty")); hWndFaxMon = FindWindow(FAXSTAT_WINCLASS, NULL); if (hWndFaxMon) { SetForegroundWindow(hWndFaxMon); SendMessage(hWndFaxMon, WM_FAXSTAT_PRINTER_PROPERTY, dwPage, 0); } else { DebugPrintEx(DEBUG_ERR, TEXT("FindWindow(FAXSTAT_WINCLASS) failed with %d"), GetLastError()); } } // FaxPrinterProperty DWORD SetLocalFaxPrinterSharing ( BOOL bShared ) /*++ Routine name : SetLocalFaxPrinterSharing Routine description: Shares or un-shares the local fax printer Author: Eran Yariv (EranY), Jul, 2001 Arguments: bShared [in] - Share the printer? Return Value: Standard Win32 error code --*/ { TCHAR tszFaxPrinterName[MAX_PATH *3]; HANDLE hPrinter = NULL; BYTE aBuf[4096]; PRINTER_INFO_2 *pInfo = (PRINTER_INFO_2 *)aBuf; PRINTER_DEFAULTS pd = {0}; DWORD dwRequiredSize; DWORD dwRes = ERROR_SUCCESS; DEBUG_FUNCTION_NAME(TEXT("SetLocalFaxPrinterSharing")); if (!GetFirstLocalFaxPrinterName (tszFaxPrinterName, ARR_SIZE(tszFaxPrinterName))) { dwRes = GetLastError (); DebugPrintEx(DEBUG_ERR, TEXT("GetFirstLocalFaxPrinterName failed with %d"), dwRes); return dwRes; } pd.DesiredAccess = PRINTER_ALL_ACCESS; if (!OpenPrinter (tszFaxPrinterName, &hPrinter, &pd)) { dwRes = GetLastError (); DebugPrintEx(DEBUG_ERR, TEXT("OpenPrinter failed with %d"), dwRes); return dwRes; } if (!GetPrinter (hPrinter, 2, (LPBYTE)pInfo, sizeof (aBuf), &dwRequiredSize)) { dwRes = GetLastError (); if (ERROR_INSUFFICIENT_BUFFER != dwRes) { // // Real error // DebugPrintEx(DEBUG_ERR, TEXT("GetPrinter failed with %d"), dwRes); goto exit; } pInfo = (PRINTER_INFO_2 *)MemAlloc (dwRequiredSize); if (!pInfo) { dwRes = GetLastError (); DebugPrintEx(DEBUG_ERR, TEXT("Failed to allocate %d bytes"), dwRequiredSize); goto exit; } if (!GetPrinter (hPrinter, 2, (LPBYTE)pInfo, dwRequiredSize, &dwRequiredSize)) { dwRes = GetLastError (); DebugPrintEx(DEBUG_ERR, TEXT("GetPrinter failed with %d"), dwRes); goto exit; } } dwRes = ERROR_SUCCESS; if (bShared) { if (pInfo->Attributes & PRINTER_ATTRIBUTE_SHARED) { // // Printer already shared // goto exit; } // // Set the sharing bit // pInfo->Attributes |= PRINTER_ATTRIBUTE_SHARED; } else { if (!(pInfo->Attributes & PRINTER_ATTRIBUTE_SHARED)) { // // Printer already un-shared // goto exit; } // // Clear the sharing bit // pInfo->Attributes &= ~PRINTER_ATTRIBUTE_SHARED; } if (!SetPrinter (hPrinter, 2, (LPBYTE)pInfo, 0)) { dwRes = GetLastError (); DebugPrintEx(DEBUG_ERR, TEXT("SetPrinter failed with %d"), dwRes); goto exit; } Assert (ERROR_SUCCESS == dwRes); exit: if (hPrinter) { ClosePrinter (hPrinter); } if ((LPBYTE)pInfo != aBuf) { MemFree (pInfo); } return dwRes; } // SetLocalFaxPrinterSharing DWORD AddOrVerifyLocalFaxPrinter () /*++ Routine name : AddOrVerifyLocalFaxPrinter Routine description: This function verifies a local fax printer is installed. If not installed, this function installs one. Author: Eran Yariv (EranY), June, 2002 Arguments: None. Return Value: Standard Win32 error code --*/ { DWORD dwRes; BOOL bLocalFaxPrinterInstalled; BOOL bFaxInstalled; DEBUG_FUNCTION_NAME(TEXT("AddOrVerifyLocalFaxPrinter")); dwRes = IsFaxInstalled (&bFaxInstalled); if (ERROR_SUCCESS != dwRes) { return dwRes; } if (!bFaxInstalled) { // // The fax product (optional component) is not installed on the system. // Bail out here // return ERROR_SUCCESS; } dwRes = IsLocalFaxPrinterInstalled(&bLocalFaxPrinterInstalled); if (ERROR_SUCCESS != dwRes) { // // Can't really tell if local fax printer is installed. // Better install anyway, just to be on the safe side. // DebugPrintEx( DEBUG_ERR, TEXT("IsLocalFaxPrinterInstalled failed with %ld"), dwRes); bLocalFaxPrinterInstalled = FALSE; } if (bLocalFaxPrinterInstalled) { // // Nothing more to do here // return ERROR_SUCCESS; } dwRes = AddLocalFaxPrinter (FAX_PRINTER_NAME, NULL); if (ERROR_SUCCESS != dwRes) { DebugPrintEx( DEBUG_ERR, TEXT("AddLocalFaxPrinter failed with %ld"), dwRes); } return dwRes; } // AddOrVerifyLocalFaxPrinter