//======================================================================= // // Copyright (c) 1998-1999 Microsoft Corporation. All Rights Reserved. // // File: printers.cpp // // Owner: YanL // // Description: // // Printing support // // //======================================================================= #include "stdafx.h" #include #include #include #include #include #include #define LOGGING_LEVEL 1 #include #include "printers.h" #include // private header containing EPD_ALL_LOCAL_AND_CLUSTER define /*** CPrinterDriverInfoArray::CPrinterDriverInfoArray * Does all the work on constructing array of IDs for all available * printer/environment combinations */ CPrinterDriverInfoArray::CPrinterDriverInfoArray() : m_dwNumDrivers(0) { LOG_block("CPrinterDriverInfoArray::CPrinterDriverInfoArray"); // Only works on NT 5 and Millennium bool fNT; OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); if( VER_PLATFORM_WIN32_WINDOWS == osvi.dwPlatformId && 4 == osvi.dwMajorVersion && 90 == osvi.dwMinorVersion) { // Millennium fNT = false; } else if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId && 5 == osvi.dwMajorVersion) { // W2K fNT = true; } else { LOG_error("ERROR_INVALID_FUNCTION"); SetLastError(ERROR_INVALID_FUNCTION); return; } LPTSTR pszEnvironment = fNT ? EPD_ALL_LOCAL_AND_CLUSTER : NULL; // Get current processor architecture SYSTEM_INFO si; GetSystemInfo(&si); m_wCurArchitecture = si.wProcessorArchitecture; DWORD dwNumDrivers = 0; DWORD dwBytesNeeded = 0; EnumPrinterDrivers(NULL, pszEnvironment, 6, NULL, 0, &dwBytesNeeded, &dwNumDrivers); if (0 == dwBytesNeeded) { LOG_out("No printers"); return; // No printers } // reserve memory for the data m_bufInfo.resize(dwBytesNeeded); if (!m_bufInfo.valid()) return; // get driver info if (!EnumPrinterDrivers(NULL, pszEnvironment, 6, m_bufInfo, dwBytesNeeded, &dwBytesNeeded, &dwNumDrivers)) { LOG_error("Fail to get printer drivers"); return; } LOG_out("%d drivers found", dwNumDrivers); m_dwNumDrivers = dwNumDrivers; } LPDRIVER_INFO_6 CPrinterDriverInfoArray::GetDriverInfo(DWORD dwDriverIdx) { if (m_dwNumDrivers <= dwDriverIdx) return NULL; LPDRIVER_INFO_6 pinfo = (LPDRIVER_INFO_6)(LPBYTE)m_bufInfo; return &pinfo[dwDriverIdx]; } static const struct SEnv { LPCTSTR szEnv; LPCTSTR szEnvID; WORD wArchitecture; LPCTSTR szArchtecture; } asEnv[] = { _T("Windows NT x86"), PRINT_ENVIRONMENT_INTEL, PROCESSOR_ARCHITECTURE_INTEL, _T("Intel"), _T("Windows NT Alpha_AXP"), PRINT_ENVIRONMENT_ALPHA, PROCESSOR_ARCHITECTURE_ALPHA, _T("Alpha"), _T("Windows 4.0"), PRINT_ENVIRONMENT_INTEL, PROCESSOR_ARCHITECTURE_INTEL, _T("Intel"), }; typedef const SEnv * PCENV; static PCENV GetEnv(LPDRIVER_INFO_6 pinfo) { if (NULL == pinfo->pEnvironment || 0 == pinfo->pEnvironment[0]) return NULL; for (int iEnv = 0; iEnv < sizeOfArray(asEnv); iEnv ++) { if (0 == lstrcmpi(asEnv[iEnv].szEnv, pinfo->pEnvironment)) return &asEnv[iEnv]; } return NULL; } LPCTSTR CPrinterDriverInfoArray::GetArchitecture(LPDRIVER_INFO_6 pinfo) { PCENV penv = GetEnv(pinfo); if (NULL == penv) return NULL; return penv->szArchtecture; } bool CPrinterDriverInfoArray::GetHardwareID(LPDRIVER_INFO_6 pinfo, tchar_buffer& bufHardwareID) { LOG_block("CPrinterDriverInfoArray::GetHardwareID"); if (NULL == pinfo->pszHardwareID || 0 == pinfo->pszHardwareID[0]) { LOG_error("printer doesn't have Hardware ID"); return false; } if (NULL == pinfo->pName || 0 == pinfo->pName[0]) { LOG_error("printer %s doesn't have a name", pinfo->pszHardwareID); return false; } PCENV penv = GetEnv(pinfo); if (NULL == penv) { LOG_error("printer %s doesn't have a environment", pinfo->pszHardwareID); return false; } // We need this driver - make shure that id is correct if (penv->wArchitecture == m_wCurArchitecture) { // reserve memory for the data bufHardwareID.resize(lstrlen(pinfo->pszHardwareID) + 1); if (!bufHardwareID.valid()) return false; lstrcpy(bufHardwareID, pinfo->pszHardwareID); } else { // reserve memory for the data bufHardwareID.resize(lstrlen(penv->szEnvID) + lstrlen(pinfo->pszHardwareID) + 1); if (!bufHardwareID.valid()) return false; lstrcpy(bufHardwareID, penv->szEnvID); lstrcat(bufHardwareID, pinfo->pszHardwareID); } // #ifdef _WUV3TEST LPCTSTR szCorrectID = bufHardwareID; SYSTEMTIME st; FileTimeToSystemTime(&(pinfo->ftDriverDate), &st); LOG_out("%s \t %s \t %2d/%02d/%04d", pinfo->pName, szCorrectID, (int)st.wMonth, (int)st.wDay, (int)st.wYear); // #endif return true; } /*** InstallPrinterDriver - * */ DWORD InstallPrinterDriver( IN LPCTSTR szDriverName, // Printer driver model name IN LPCTSTR szInstallFolder, IN LPCTSTR szArchitecture ) { USES_CONVERSION; LOG_block("InstallPrinterDriver"); LOG_out("szDriverName = %s, szInstallFolder = %s, szArchitecture = %s", szDriverName, szInstallFolder, szArchitecture); TCHAR szFileName[MAX_PATH]; /*find .inf*/ lstrcpy(szFileName, szInstallFolder); PathAppend(szFileName, TEXT("*.inf")); WIN32_FIND_DATA ffd; auto_hfindfile hfind = FindFirstFile(szFileName, &ffd); return_error_if_false(hfind.valid()); //construct .inf lstrcpy(szFileName, szInstallFolder); PathAppend(szFileName, ffd.cFileName); DWORD dwError; /*** printui.h access (from NT sources) * We cannot include printui.h couse printui.dll compliled in UNICODE and we are in MBCS */ typedef DWORD (*PFN_PrintUIEntryW)( IN HWND hwnd, IN HINSTANCE hInstance, IN LPCWSTR pszCmdLine, IN UINT nCmdShow ); const TCHAR szCmdLineFormat[] = _T("/ia /U /m \"%s\" /h \"%s\" /v \"Windows 2000\" /f \"%s\" /q"); tchar_buffer bufCmd(lstrlen(szCmdLineFormat) + lstrlen(szDriverName) + lstrlen(szArchitecture) + lstrlen(szFileName) + 1); wsprintf(bufCmd, szCmdLineFormat, szDriverName, szArchitecture, szFileName); // Load printui.dll auto_hlib hlib = LoadLibrary(_T("printui.dll")); return_error_if_false(hlib.valid()); PFN_PrintUIEntryW pfnPrintUIEntryW = (PFN_PrintUIEntryW)GetProcAddress(hlib, "PrintUIEntryW"); return_error_if_false(NULL != pfnPrintUIEntryW); dwError = pfnPrintUIEntryW(GetActiveWindow(), 0, T2W((LPTSTR)bufCmd), SW_HIDE); LOG_out( "pfnPrintUIEntryW(%s) returns %d", (LPTSTR)bufCmd, dwError); return dwError; }