/*****************************************************************************\ * MODULE: ppinit.c * * This module contains the initialization routines for the Print-Provider. * The spooler calls InitializePrintProvider() to retreive the list of * calls that the Print-Processor supports. * * * Copyright (C) 1996-1997 Microsoft Corporation * Copyright (C) 1996-1997 Hewlett Packard * * History: * 07-Oct-1996 HWP-Guys Initiated port from win95 to winNT * \*****************************************************************************/ #include "precomp.h" #include "priv.h" /*****************************************************************************\ * _init_provider_worker (Local Routine) * * \*****************************************************************************/ void _init_provider_worker () { // Get the default spool directory HANDLE hServer = NULL; DWORD dwType = REG_SZ; DWORD cbSize = MAX_PATH * sizeof (TCHAR); g_szDefSplDir[0] = 0; semEnterCrit (); if (OpenPrinter (NULL, &hServer, NULL)) { if (ERROR_SUCCESS != GetPrinterData (hServer, SPLREG_DEFAULT_SPOOL_DIRECTORY, &dwType, (LPBYTE) g_szDefSplDir, cbSize, &cbSize)) { } ClosePrinter (hServer); } SplClean (); semLeaveCrit (); } /*****************************************************************************\ * _init_write_displayname (Local Routine) * * \*****************************************************************************/ BOOL _init_write_displayname(VOID) { LONG lRet; HKEY hkPath; DWORD dwType; DWORD cbSize; if (!LoadString (g_hInst, IDS_DISPLAY_NAME, g_szDisplayStr, MAX_PATH)) { g_szDisplayStr[0] = 0; } // Open the key to the Print-Providor. // lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_szRegProvider, 0, KEY_READ | KEY_WRITE, &hkPath); if (lRet == ERROR_SUCCESS) { // Look for the "displayname". If it doesn't exist, then write it. // dwType = REG_SZ; cbSize = 0; lRet = RegQueryValueEx(hkPath, g_szDisplayName, NULL, &dwType, (LPBYTE)NULL, &cbSize); // Write the string. // if ((lRet != ERROR_SUCCESS) || (cbSize == 0)) { dwType = REG_SZ; cbSize = (lstrlen(g_szDisplayStr) + 1) * sizeof(TCHAR); lRet = RegSetValueEx(hkPath, g_szDisplayName, 0, dwType, (LPBYTE)g_szDisplayStr, cbSize); } RegCloseKey(hkPath); } if (lRet != ERROR_SUCCESS) { SetLastError (lRet); return FALSE; } else return TRUE; } /*****************************************************************************\ * _init_find_filename (Local Routine) * * \*****************************************************************************/ LPTSTR _init_find_filename( LPCTSTR lpszPathName) { LPTSTR lpszFileName; if (lpszPathName == NULL) return NULL; // Look for the filename in the path, by starting at the end // and looking for the ('\') char. // if (!(lpszFileName = utlStrChrR(lpszPathName, TEXT('\\')))) lpszFileName = (LPTSTR)lpszPathName; else lpszFileName++; return lpszFileName; } /*****************************************************************************\ * _init_load_netapi (Local Routine) * * Initialize INET API pointers. * \*****************************************************************************/ BOOL _init_load_netapi(VOID) { g_pfnHttpQueryInfo = (PFNHTTPQUERYINFO) HttpQueryInfoA; g_pfnInternetOpenUrl = (PFNINTERNETOPENURL) InternetOpenUrlA; g_pfnInternetErrorDlg = (PFNINTERNETERRORDLG) InternetErrorDlg; g_pfnHttpSendRequest = (PFNHTTPSENDREQUEST) HttpSendRequestA; g_pfnHttpSendRequestEx = (PFNHTTPSENDREQUESTEX) HttpSendRequestExA; g_pfnInternetReadFile = (PFNINTERNETREADFILE) InternetReadFile; g_pfnInternetWriteFile = (PFNINTERNETWRITEFILE) InternetWriteFile; g_pfnInternetCloseHandle = (PFNINTERNETCLOSEHANDLE) InternetCloseHandle; g_pfnInternetOpen = (PFNINTERNETOPEN) InternetOpenA; g_pfnInternetConnect = (PFNINTERNETCONNECT) InternetConnectA; g_pfnHttpOpenRequest = (PFNHTTPOPENREQUEST) HttpOpenRequestA; g_pfnHttpAddRequestHeaders = (PFNHTTPADDREQUESTHEADERS)HttpAddRequestHeadersA; g_pfnHttpEndRequest = (PFNHTTPENDREQUEST) HttpEndRequestA; g_pfnInternetSetOption = (PFNINTERNETSETOPTION) InternetSetOptionA; return TRUE; } /*****************************************************************************\ * _init_load_provider (Local Routine) * * This performs the startup initialization for the print-provider. * \*****************************************************************************/ BOOL _init_load_provider() { LPTSTR lpszFileName; TCHAR szBuf[MAX_PATH]; DWORD i = MAX_COMPUTERNAME_LENGTH + 1; BOOL bRet = FALSE; // Get the module name for this process. // if (!GetModuleFileName(NULL, szBuf, MAX_PATH)) goto exit_load; // Get the filename from the full module-name. and check that // it's the spooler. // if (lpszFileName = _init_find_filename(szBuf)) { if (lstrcmpi(lpszFileName, g_szProcessName) == 0) { // Initialize the computer name. // if (!GetComputerName(g_szMachine, &i)) goto exit_load; // Initialize the internet API pointers. // if (_init_load_netapi() == FALSE) goto exit_load; // // Assume success. // bRet = TRUE; // // Try and initialize the crit-sect for synchronizing port access. // __try { InitializeCriticalSection(&g_csMonitorSection); } __except (1) { bRet = FALSE; SetLastError (ERROR_INVALID_HANDLE); } return bRet; } } exit_load: return bRet; } /*****************************************************************************\ * _init_load_ports (Local Routine) * * This performs the port initialization for the print-provider. * \*****************************************************************************/ BOOL _init_load_ports( LPTSTR lpszRegPath) { LONG lStat; HKEY hkPath; HKEY hkPortNames; TCHAR szPortName[MAX_PATH]; BOOL bRet = FALSE; LPTSTR pEnd = NULL; size_t uSize = 0; // // Make sure there is a registry-path pointing to the // INET provider entry. // if (lpszRegPath == NULL) return FALSE; // // Copy the string to global-memory. We will need this if we require // the need to write to the registry when creating new ports. // uSize = 1 + lstrlen (lpszRegPath); if (! (g_szRegProvider = (LPTSTR) memAlloc (uSize * sizeof (TCHAR)))) { return FALSE; } StringCchCopy(g_szRegProvider, uSize, lpszRegPath); // // Copy the registry key of all the printer providers // if (! (g_szRegPrintProviders = (LPTSTR) memAlloc (uSize * sizeof (TCHAR)))) { return FALSE; } StringCchCopy(g_szRegPrintProviders, uSize, lpszRegPath); pEnd = wcsrchr (g_szRegPrintProviders, L'\\'); if ( pEnd ) { *pEnd = 0; } // Open registry key for Provider-Name. // lStat = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszRegPath, 0, KEY_READ, &hkPath); if (lStat == ERROR_SUCCESS) { bRet = TRUE; // Open the "ports" key for enumeration of the ports. We need to // build up this list at the provider initialization time so that // we can return the list of ports if called to EnumPorts(). // lStat = RegOpenKeyEx(hkPath, g_szRegPorts, 0, KEY_READ, &hkPortNames); if (lStat == ERROR_SUCCESS) { DWORD dwSize; DWORD i = 0; while (lStat == ERROR_SUCCESS) { dwSize = sizeof(szPortName) / sizeof (TCHAR); lStat = RegEnumKey (hkPortNames, i, szPortName, dwSize); if (lStat == ERROR_SUCCESS) { // Do not short-cut this call to InetmonAddPort(), // as this will leave the crit-sect unprotected. // PPAddPort(szPortName, NULL, NULL); } i++; } RegCloseKey(hkPortNames); } else { DBG_MSG(DBG_LEV_INFO, (TEXT("RegOpenKeyEx(%s) failed: Error = %lu"), g_szRegPorts, lStat)); SetLastError(lStat); } RegCloseKey(hkPath); } else { DBG_MSG(DBG_LEV_WARN, (TEXT("RegOpenKeyEx(%s) failed: Error = %lu"), lpszRegPath, lStat)); SetLastError(lStat); } return bRet; } /*****************************************************************************\ * _init_create_sync (Local Routine) * * This creates the events and Critical Section needed for handling the synchronisation * in the monitor. * \*****************************************************************************/ _inline BOOL _init_create_sync(VOID) { BOOL bRet = TRUE; g_dwConCount = 0; __try { InitializeCriticalSection(&g_csCreateSection); } __except (1) { bRet = FALSE; SetLastError (ERROR_INVALID_HANDLE); } if (bRet) { g_eResetConnections = CreateEvent( NULL, TRUE, TRUE, NULL ); if (g_eResetConnections == NULL) bRet = FALSE; } return bRet; } /*****************************************************************************\ * InitializePrintProvider (API) * * The spooler calls this routine to initialize the Print-Provider. The list * of functions in the table are passed back to the spooler for it to use * when interfacing with the provider. * \*****************************************************************************/ static PRINTPROVIDOR pfnPPList[] = { PPOpenPrinter, PPSetJob, PPGetJob, PPEnumJobs, stubAddPrinter, stubDeletePrinter, PPSetPrinter, PPGetPrinter, PPEnumPrinters, stubAddPrinterDriver, stubEnumPrinterDrivers, stubGetPrinterDriver, stubGetPrinterDriverDirectory, stubDeletePrinterDriver, stubAddPrintProcessor, stubEnumPrintProcessors, stubGetPrintProcessorDirectory, stubDeletePrintProcessor, stubEnumPrintProcessorDatatypes, PPStartDocPrinter, PPStartPagePrinter, PPWritePrinter, PPEndPagePrinter, PPAbortPrinter, stubReadPrinter, PPEndDocPrinter, PPAddJob, PPScheduleJob, stubGetPrinterData, stubSetPrinterData, stubWaitForPrinterChange, PPClosePrinter, stubAddForm, stubDeleteForm, stubGetForm, stubSetForm, stubEnumForms, stubEnumMonitors, PPEnumPorts, stubAddPort, NULL, NULL, stubCreatePrinterIC, stubPlayGdiScriptOnPrinterIC, stubDeletePrinterIC, stubAddPrinterConnection, stubDeletePrinterConnection, stubPrinterMessageBox, stubAddMonitor, stubDeleteMonitor, NULL, // stubResetPrinter, NULL, // stubGetPrinterDriverEx should not be called as specified in spoolss\dll\nullpp.c PPFindFirstPrinterChangeNotification, PPFindClosePrinterChangeNotification, NULL, // stubAddPortEx, NULL, // stubShutDown, NULL, // stubRefreshPrinterChangeNotification, NULL, // stubOpenPrinterEx, NULL, // stubAddPrinterEx, NULL, // stubSetPort, NULL, // stubEnumPrinterData, NULL, // stubDeletePrinterData, NULL, // fpClusterSplOpen NULL, // fpClusterSplClose NULL, // fpClusterSplIsAlive NULL, // fpSetPrinterDataEx NULL, // fpGetPrinterDataEx NULL, // fpEnumPrinterDataEx NULL, // fpEnumPrinterKey NULL, // fpDeletePrinterDataEx NULL, // fpDeletePrinterKey NULL, // fpSeekPrinter NULL, // fpDeletePrinterDriverEx NULL, // fpAddPerMachineConnection NULL, // fpDeletePerMachineConnection NULL, // fpEnumPerMachineConnections PPXcvData, // fpXcvData NULL, // fpAddPrinterDriverEx NULL, // fpSplReadPrinter NULL, // fpDriverUnloadComplete NULL, // fpGetSpoolFileInfo NULL, // fpCommitSpoolData NULL, // fpCloseSpoolFileHandle NULL, // fpFlushPrinter NULL, // fpSendRecvBidiData NULL, // fpAddDriverCatalog }; BOOL WINAPI InitializePrintProvidor( LPPRINTPROVIDOR pPP, DWORD cEntries, LPWSTR pszFullRegistryPath) { HANDLE hThread; DWORD dwThreadId; g_pcsEndBrowserSessionLock = new CCriticalSection (); if (!g_pcsEndBrowserSessionLock || g_pcsEndBrowserSessionLock->bValid () == FALSE) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (_init_load_provider() == FALSE) { DBG_ASSERT(FALSE, (TEXT("Assert: Failed module initialization"))); return FALSE; } if (!pszFullRegistryPath || !*pszFullRegistryPath) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } gpInetMon = new CInetMon; if (!gpInetMon || gpInetMon->bValid() == FALSE) { if (gpInetMon) { delete gpInetMon; } return FALSE; } if (gpInetMon && !gpInetMon->bValid ()) { delete gpInetMon; SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } DBG_MSG(DBG_LEV_CALLTREE, (TEXT("Call: InitializePrintProvidor"))); memcpy(pPP, pfnPPList, min(sizeof(pfnPPList), (int)cEntries)); // Initialise synchronisation objects if (!_init_create_sync()) return FALSE; g_bUpgrade = SplIsUpgrade(); if (_init_load_ports((LPTSTR)pszFullRegistryPath) == FALSE) { DBG_ASSERT(FALSE, (TEXT("Assert: Failed port initialization"))); return FALSE; } if (!_init_write_displayname()) return FALSE; if (hThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) _init_provider_worker, NULL, 0, &dwThreadId)) { CloseHandle (hThread); return TRUE; } else return FALSE; } /*****************************************************************************\ * DllMain * * This is the main entry-point for the library. * \*****************************************************************************/ extern "C" BOOL WINAPI DllMain( HINSTANCE hInstDll, DWORD dwAttach, LPVOID lpcReserved) { switch (dwAttach) { case DLL_PROCESS_ATTACH: g_hInst = hInstDll; DisableThreadLibraryCalls(hInstDll); break; case DLL_PROCESS_DETACH: DeleteCriticalSection(&g_csCreateSection); DeleteCriticalSection(&g_csMonitorSection); CloseHandle(g_eResetConnections); delete g_pcsEndBrowserSessionLock; break; } return TRUE; }