/*****************************************************************************\ * 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" #ifdef WINNT32 extern "C" { BOOL BuildOtherNamesFromMachineName( LPWSTR **ppszMyOtherNames, DWORD *cOtherNames ); } #endif /*****************************************************************************\ * _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 (); #ifdef WINNT32 if (OpenPrinter (NULL, &hServer, NULL)) { if (ERROR_SUCCESS != GetPrinterData (hServer, SPLREG_DEFAULT_SPOOL_DIRECTORY, &dwType, (LPBYTE) g_szDefSplDir, cbSize, &cbSize)) { } ClosePrinter (hServer); } #endif 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; #if 0 HINSTANCE hWinInet; // Initialize the WinInet API function-ptrs. // if (hWinInet = LoadLibrary(g_szWinInetDll)) { g_pfnHttpQueryInfo = (PFNHTTPQUERYINFO) GetProcAddress(hWinInet, g_szHttpQueryInfo); g_pfnInternetOpenUrl = (PFNINTERNETOPENURL) GetProcAddress(hWinInet, g_szInternetOpenUrl); g_pfnInternetErrorDlg = (PFNINTERNETERRORDLG) GetProcAddress(hWinInet, g_szInternetErrorDlg); g_pfnHttpSendRequest = (PFNHTTPSENDREQUEST) GetProcAddress(hWinInet, g_szHttpSendRequest); g_pfnHttpSendRequestEx = (PFNHTTPSENDREQUESTEX) GetProcAddress(hWinInet, g_szHttpSendRequestEx); g_pfnInternetReadFile = (PFNINTERNETREADFILE) GetProcAddress(hWinInet, g_szInternetReadFile); g_pfnInternetWriteFile = (PFNINTERNETWRITEFILE) GetProcAddress(hWinInet, g_szInternetWriteFile); g_pfnInternetCloseHandle = (PFNINTERNETCLOSEHANDLE) GetProcAddress(hWinInet, g_szInternetCloseHandle); g_pfnInternetOpen = (PFNINTERNETOPEN) GetProcAddress(hWinInet, g_szInternetOpen); g_pfnInternetConnect = (PFNINTERNETCONNECT) GetProcAddress(hWinInet, g_szInternetConnect); g_pfnHttpOpenRequest = (PFNHTTPOPENREQUEST) GetProcAddress(hWinInet, g_szHttpOpenRequest); g_pfnHttpAddRequestHeaders = (PFNHTTPADDREQUESTHEADERS)GetProcAddress(hWinInet, g_szHttpAddRequestHeaders); g_pfnHttpEndRequest = (PFNHTTPENDREQUEST) GetProcAddress(hWinInet, g_szHttpEndRequest); g_pfnInternetSetOption = (PFNINTERNETSETOPTION) GetProcAddress(hWinInet, g_szInternetSetOption); // Check for any failures. // if (g_pfnHttpQueryInfo && g_pfnInternetOpenUrl && g_pfnInternetErrorDlg && g_pfnHttpSendRequest && g_pfnHttpSendRequestEx && g_pfnInternetReadFile && g_pfnInternetWriteFile && g_pfnInternetCloseHandle && g_pfnInternetOpen && g_pfnInternetConnect && g_pfnHttpOpenRequest && g_pfnHttpAddRequestHeaders && g_pfnHttpEndRequest && g_pfnInternetSetOption) { return TRUE; } FreeLibrary(hWinInet); } return FALSE; #endif } /*****************************************************************************\ * _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; // 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; // !!! // Load spoolss here if we need to call spooler functions // from the print provider. // // Initialize the crit-sect for synchronizing port access. // semInitCrit(); return TRUE; } } exit_load: return FALSE; } /*****************************************************************************\ * _init_unload_provider (Local Routine) * * This performs the unloading/freeing of resources allocated by the * provider. * \*****************************************************************************/ #if 0 // This piece of code is not needed since the dll is never get reloaded by spooler twice. // -weihaic BOOL _init_unload_provider(VOID) { // Free the critical-section. // semFreeCrit(); // Free the Registry // memFree (g_szRegProvider, sizeof (TCHAR) * (lstrlen (g_szRegProvider) + 1)); #ifdef WINNT32 memFree (g_szRegPrintProviders, sizeof (TCHAR) * (lstrlen (g_szRegPrintProviders) + 1)); #endif // Free the monitor-port-list // memFree(g_pPortList, sizeof(INIMONPORTLIST)); // !!! // Unload spoolss here if it's been loaded. // return TRUE; } #endif /*****************************************************************************\ * _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; // 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. // if (! (g_szRegProvider = (LPTSTR) memAlloc ((1 + lstrlen (lpszRegPath)) * sizeof (TCHAR)))) { return FALSE; } lstrcpy(g_szRegProvider, lpszRegPath); #ifdef WINNT32 // Copy the registry key of all the printer providers if (! (g_szRegPrintProviders = (LPTSTR) memAlloc ((1 + lstrlen (lpszRegPath)) * sizeof (TCHAR)))) { return FALSE; } lstrcpy(g_szRegPrintProviders, lpszRegPath); pEnd = wcsrchr (g_szRegPrintProviders, L'\\'); if ( pEnd ) { *pEnd = 0; } #endif // 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) { #ifdef WINNT32 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; #else return TRUE; #endif } /*****************************************************************************\ * 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. * * NOTE: The (pszFullRegistryPath) is really a LPTSTR as far as Win9X is * concerned. * \*****************************************************************************/ #ifdef WINNT32 static PRINTPROVIDOR pfnPPList[] = { #else static LPCVOID pfnPPList[] = { #endif 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, #ifdef WINNT32 NULL, NULL, #else stubConfigurePort, PPDeletePort, #endif stubCreatePrinterIC, stubPlayGdiScriptOnPrinterIC, stubDeletePrinterIC, stubAddPrinterConnection, stubDeletePrinterConnection, stubPrinterMessageBox, stubAddMonitor, stubDeleteMonitor #ifndef WIN9X , 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 #endif }; 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)); #ifdef WINNT32 // Initialise synchronisation objects if (!_init_create_sync()) return FALSE; // Initialize other names if (!BuildOtherNamesFromMachineName(&g_ppszOtherNames, &g_cOtherNames)) return FALSE; g_bUpgrade = SplIsUpgrade(); #endif 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; } /*****************************************************************************\ * DllEntryPoint * * This is the main entry-point for the library. * \*****************************************************************************/ extern "C" { BOOL WINAPI DllEntryPoint( HINSTANCE hInstDll, DWORD dwAttach, LPVOID lpcReserved) { static BOOL s_bIsSpoolerProcess = FALSE; BOOL bRet = TRUE; switch (dwAttach) { case DLL_PROCESS_ATTACH: // Set the global-instance variable. // g_hInst = hInstDll; s_bIsSpoolerProcess = TRUE; break; case DLL_PROCESS_DETACH: #if 0 // This code is not needed since the dll is never get loaded twice by spooler // -weihaic // if (s_bIsSpoolerProcess) _init_unload_provider(); #endif #ifdef WINNT32 DeleteCriticalSection( &g_csCreateSection ); CloseHandle( g_eResetConnections ); #endif if (g_pcsEndBrowserSessionLock) { delete g_pcsEndBrowserSessionLock; } break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; } return bRet; } }