Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

745 lines
20 KiB

  1. /*****************************************************************************\
  2. * MODULE: ppinit.c
  3. *
  4. * This module contains the initialization routines for the Print-Provider.
  5. * The spooler calls InitializePrintProvider() to retreive the list of
  6. * calls that the Print-Processor supports.
  7. *
  8. *
  9. * Copyright (C) 1996-1997 Microsoft Corporation
  10. * Copyright (C) 1996-1997 Hewlett Packard
  11. *
  12. * History:
  13. * 07-Oct-1996 HWP-Guys Initiated port from win95 to winNT
  14. *
  15. \*****************************************************************************/
  16. #include "precomp.h"
  17. #include "priv.h"
  18. #ifdef WINNT32
  19. extern "C" {
  20. BOOL
  21. BuildOtherNamesFromMachineName(
  22. LPWSTR **ppszMyOtherNames,
  23. DWORD *cOtherNames
  24. );
  25. }
  26. #endif
  27. /*****************************************************************************\
  28. * _init_provider_worker (Local Routine)
  29. *
  30. *
  31. \*****************************************************************************/
  32. void _init_provider_worker ()
  33. {
  34. // Get the default spool directory
  35. HANDLE hServer = NULL;
  36. DWORD dwType = REG_SZ;
  37. DWORD cbSize = MAX_PATH * sizeof (TCHAR);
  38. g_szDefSplDir[0] = 0;
  39. semEnterCrit ();
  40. #ifdef WINNT32
  41. if (OpenPrinter (NULL, &hServer, NULL)) {
  42. if (ERROR_SUCCESS != GetPrinterData (hServer,
  43. SPLREG_DEFAULT_SPOOL_DIRECTORY,
  44. &dwType,
  45. (LPBYTE) g_szDefSplDir,
  46. cbSize,
  47. &cbSize)) {
  48. }
  49. ClosePrinter (hServer);
  50. }
  51. #endif
  52. SplClean ();
  53. semLeaveCrit ();
  54. }
  55. /*****************************************************************************\
  56. * _init_write_displayname (Local Routine)
  57. *
  58. *
  59. \*****************************************************************************/
  60. BOOL _init_write_displayname(VOID)
  61. {
  62. LONG lRet;
  63. HKEY hkPath;
  64. DWORD dwType;
  65. DWORD cbSize;
  66. if (!LoadString (g_hInst,
  67. IDS_DISPLAY_NAME,
  68. g_szDisplayStr,
  69. MAX_PATH)) {
  70. g_szDisplayStr[0] = 0;
  71. }
  72. // Open the key to the Print-Providor.
  73. //
  74. lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  75. g_szRegProvider,
  76. 0,
  77. KEY_READ | KEY_WRITE,
  78. &hkPath);
  79. if (lRet == ERROR_SUCCESS) {
  80. // Look for the "displayname". If it doesn't exist, then write it.
  81. //
  82. dwType = REG_SZ;
  83. cbSize = 0;
  84. lRet = RegQueryValueEx(hkPath,
  85. g_szDisplayName,
  86. NULL,
  87. &dwType,
  88. (LPBYTE)NULL,
  89. &cbSize);
  90. // Write the string.
  91. //
  92. if ((lRet != ERROR_SUCCESS) || (cbSize == 0)) {
  93. dwType = REG_SZ;
  94. cbSize = (lstrlen(g_szDisplayStr) + 1) * sizeof(TCHAR);
  95. lRet = RegSetValueEx(hkPath,
  96. g_szDisplayName,
  97. 0,
  98. dwType,
  99. (LPBYTE)g_szDisplayStr,
  100. cbSize);
  101. }
  102. RegCloseKey(hkPath);
  103. }
  104. if (lRet != ERROR_SUCCESS) {
  105. SetLastError (lRet);
  106. return FALSE;
  107. }
  108. else
  109. return TRUE;
  110. }
  111. /*****************************************************************************\
  112. * _init_find_filename (Local Routine)
  113. *
  114. *
  115. \*****************************************************************************/
  116. LPTSTR _init_find_filename(
  117. LPCTSTR lpszPathName)
  118. {
  119. LPTSTR lpszFileName;
  120. if (lpszPathName == NULL)
  121. return NULL;
  122. // Look for the filename in the path, by starting at the end
  123. // and looking for the ('\') char.
  124. //
  125. if (!(lpszFileName = utlStrChrR(lpszPathName, TEXT('\\'))))
  126. lpszFileName = (LPTSTR)lpszPathName;
  127. else
  128. lpszFileName++;
  129. return lpszFileName;
  130. }
  131. /*****************************************************************************\
  132. * _init_load_netapi (Local Routine)
  133. *
  134. * Initialize INET API pointers.
  135. *
  136. \*****************************************************************************/
  137. BOOL _init_load_netapi(VOID)
  138. {
  139. g_pfnHttpQueryInfo = (PFNHTTPQUERYINFO) HttpQueryInfoA;
  140. g_pfnInternetOpenUrl = (PFNINTERNETOPENURL) InternetOpenUrlA;
  141. g_pfnInternetErrorDlg = (PFNINTERNETERRORDLG) InternetErrorDlg;
  142. g_pfnHttpSendRequest = (PFNHTTPSENDREQUEST) HttpSendRequestA;
  143. g_pfnHttpSendRequestEx = (PFNHTTPSENDREQUESTEX) HttpSendRequestExA;
  144. g_pfnInternetReadFile = (PFNINTERNETREADFILE) InternetReadFile;
  145. g_pfnInternetWriteFile = (PFNINTERNETWRITEFILE) InternetWriteFile;
  146. g_pfnInternetCloseHandle = (PFNINTERNETCLOSEHANDLE) InternetCloseHandle;
  147. g_pfnInternetOpen = (PFNINTERNETOPEN) InternetOpenA;
  148. g_pfnInternetConnect = (PFNINTERNETCONNECT) InternetConnectA;
  149. g_pfnHttpOpenRequest = (PFNHTTPOPENREQUEST) HttpOpenRequestA;
  150. g_pfnHttpAddRequestHeaders = (PFNHTTPADDREQUESTHEADERS)HttpAddRequestHeadersA;
  151. g_pfnHttpEndRequest = (PFNHTTPENDREQUEST) HttpEndRequestA;
  152. g_pfnInternetSetOption = (PFNINTERNETSETOPTION) InternetSetOptionA;
  153. return TRUE;
  154. #if 0
  155. HINSTANCE hWinInet;
  156. // Initialize the WinInet API function-ptrs.
  157. //
  158. if (hWinInet = LoadLibrary(g_szWinInetDll)) {
  159. g_pfnHttpQueryInfo = (PFNHTTPQUERYINFO) GetProcAddress(hWinInet, g_szHttpQueryInfo);
  160. g_pfnInternetOpenUrl = (PFNINTERNETOPENURL) GetProcAddress(hWinInet, g_szInternetOpenUrl);
  161. g_pfnInternetErrorDlg = (PFNINTERNETERRORDLG) GetProcAddress(hWinInet, g_szInternetErrorDlg);
  162. g_pfnHttpSendRequest = (PFNHTTPSENDREQUEST) GetProcAddress(hWinInet, g_szHttpSendRequest);
  163. g_pfnHttpSendRequestEx = (PFNHTTPSENDREQUESTEX) GetProcAddress(hWinInet, g_szHttpSendRequestEx);
  164. g_pfnInternetReadFile = (PFNINTERNETREADFILE) GetProcAddress(hWinInet, g_szInternetReadFile);
  165. g_pfnInternetWriteFile = (PFNINTERNETWRITEFILE) GetProcAddress(hWinInet, g_szInternetWriteFile);
  166. g_pfnInternetCloseHandle = (PFNINTERNETCLOSEHANDLE) GetProcAddress(hWinInet, g_szInternetCloseHandle);
  167. g_pfnInternetOpen = (PFNINTERNETOPEN) GetProcAddress(hWinInet, g_szInternetOpen);
  168. g_pfnInternetConnect = (PFNINTERNETCONNECT) GetProcAddress(hWinInet, g_szInternetConnect);
  169. g_pfnHttpOpenRequest = (PFNHTTPOPENREQUEST) GetProcAddress(hWinInet, g_szHttpOpenRequest);
  170. g_pfnHttpAddRequestHeaders = (PFNHTTPADDREQUESTHEADERS)GetProcAddress(hWinInet, g_szHttpAddRequestHeaders);
  171. g_pfnHttpEndRequest = (PFNHTTPENDREQUEST) GetProcAddress(hWinInet, g_szHttpEndRequest);
  172. g_pfnInternetSetOption = (PFNINTERNETSETOPTION) GetProcAddress(hWinInet, g_szInternetSetOption);
  173. // Check for any failures.
  174. //
  175. if (g_pfnHttpQueryInfo &&
  176. g_pfnInternetOpenUrl &&
  177. g_pfnInternetErrorDlg &&
  178. g_pfnHttpSendRequest &&
  179. g_pfnHttpSendRequestEx &&
  180. g_pfnInternetReadFile &&
  181. g_pfnInternetWriteFile &&
  182. g_pfnInternetCloseHandle &&
  183. g_pfnInternetOpen &&
  184. g_pfnInternetConnect &&
  185. g_pfnHttpOpenRequest &&
  186. g_pfnHttpAddRequestHeaders &&
  187. g_pfnHttpEndRequest &&
  188. g_pfnInternetSetOption) {
  189. return TRUE;
  190. }
  191. FreeLibrary(hWinInet);
  192. }
  193. return FALSE;
  194. #endif
  195. }
  196. /*****************************************************************************\
  197. * _init_load_provider (Local Routine)
  198. *
  199. * This performs the startup initialization for the print-provider.
  200. *
  201. \*****************************************************************************/
  202. BOOL _init_load_provider()
  203. {
  204. LPTSTR lpszFileName;
  205. TCHAR szBuf[MAX_PATH];
  206. DWORD i = MAX_COMPUTERNAME_LENGTH + 1;
  207. // Get the module name for this process.
  208. //
  209. if (!GetModuleFileName(NULL, szBuf, MAX_PATH))
  210. goto exit_load;
  211. // Get the filename from the full module-name. and check that
  212. // it's the spooler.
  213. //
  214. if (lpszFileName = _init_find_filename(szBuf)) {
  215. if (lstrcmpi(lpszFileName, g_szProcessName) == 0) {
  216. // Initialize the computer name.
  217. //
  218. if (!GetComputerName(g_szMachine, &i))
  219. goto exit_load;
  220. // Initialize the internet API pointers.
  221. //
  222. if (_init_load_netapi() == FALSE)
  223. goto exit_load;
  224. // !!!
  225. // Load spoolss here if we need to call spooler functions
  226. // from the print provider.
  227. //
  228. // Initialize the crit-sect for synchronizing port access.
  229. //
  230. semInitCrit();
  231. return TRUE;
  232. }
  233. }
  234. exit_load:
  235. return FALSE;
  236. }
  237. /*****************************************************************************\
  238. * _init_unload_provider (Local Routine)
  239. *
  240. * This performs the unloading/freeing of resources allocated by the
  241. * provider.
  242. *
  243. \*****************************************************************************/
  244. #if 0
  245. // This piece of code is not needed since the dll is never get reloaded by spooler twice.
  246. // -weihaic
  247. BOOL _init_unload_provider(VOID)
  248. {
  249. // Free the critical-section.
  250. //
  251. semFreeCrit();
  252. // Free the Registry
  253. //
  254. memFree (g_szRegProvider, sizeof (TCHAR) * (lstrlen (g_szRegProvider) + 1));
  255. #ifdef WINNT32
  256. memFree (g_szRegPrintProviders, sizeof (TCHAR) * (lstrlen (g_szRegPrintProviders) + 1));
  257. #endif
  258. // Free the monitor-port-list
  259. //
  260. memFree(g_pPortList, sizeof(INIMONPORTLIST));
  261. // !!!
  262. // Unload spoolss here if it's been loaded.
  263. //
  264. return TRUE;
  265. }
  266. #endif
  267. /*****************************************************************************\
  268. * _init_load_ports (Local Routine)
  269. *
  270. * This performs the port initialization for the print-provider.
  271. *
  272. \*****************************************************************************/
  273. BOOL _init_load_ports(
  274. LPTSTR lpszRegPath)
  275. {
  276. LONG lStat;
  277. HKEY hkPath;
  278. HKEY hkPortNames;
  279. TCHAR szPortName[MAX_PATH];
  280. BOOL bRet = FALSE;
  281. LPTSTR pEnd = NULL;
  282. // Make sure there is a registry-path pointing to the
  283. // INET provider entry.
  284. //
  285. if (lpszRegPath == NULL)
  286. return FALSE;
  287. // Copy the string to global-memory. We will need this if we require
  288. // the need to write to the registry when creating new ports.
  289. //
  290. if (! (g_szRegProvider = (LPTSTR) memAlloc ((1 + lstrlen (lpszRegPath)) * sizeof (TCHAR)))) {
  291. return FALSE;
  292. }
  293. lstrcpy(g_szRegProvider, lpszRegPath);
  294. #ifdef WINNT32
  295. // Copy the registry key of all the printer providers
  296. if (! (g_szRegPrintProviders = (LPTSTR) memAlloc ((1 + lstrlen (lpszRegPath)) * sizeof (TCHAR)))) {
  297. return FALSE;
  298. }
  299. lstrcpy(g_szRegPrintProviders, lpszRegPath);
  300. pEnd = wcsrchr (g_szRegPrintProviders, L'\\');
  301. if ( pEnd )
  302. {
  303. *pEnd = 0;
  304. }
  305. #endif
  306. // Open registry key for Provider-Name.
  307. //
  308. lStat = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszRegPath, 0, KEY_READ, &hkPath);
  309. if (lStat == ERROR_SUCCESS) {
  310. bRet = TRUE;
  311. // Open the "ports" key for enumeration of the ports. We need to
  312. // build up this list at the provider initialization time so that
  313. // we can return the list of ports if called to EnumPorts().
  314. //
  315. lStat = RegOpenKeyEx(hkPath, g_szRegPorts, 0, KEY_READ, &hkPortNames);
  316. if (lStat == ERROR_SUCCESS) {
  317. DWORD dwSize;
  318. DWORD i = 0;
  319. while (lStat == ERROR_SUCCESS) {
  320. dwSize = sizeof(szPortName) / sizeof (TCHAR);
  321. lStat = RegEnumKey (hkPortNames,
  322. i,
  323. szPortName,
  324. dwSize);
  325. if (lStat == ERROR_SUCCESS) {
  326. // Do not short-cut this call to InetmonAddPort(),
  327. // as this will leave the crit-sect unprotected.
  328. //
  329. PPAddPort(szPortName, NULL, NULL);
  330. }
  331. i++;
  332. }
  333. RegCloseKey(hkPortNames);
  334. } else {
  335. DBG_MSG(DBG_LEV_INFO, (TEXT("RegOpenKeyEx(%s) failed: Error = %lu"), g_szRegPorts, lStat));
  336. SetLastError(lStat);
  337. }
  338. RegCloseKey(hkPath);
  339. } else {
  340. DBG_MSG(DBG_LEV_WARN, (TEXT("RegOpenKeyEx(%s) failed: Error = %lu"), lpszRegPath, lStat));
  341. SetLastError(lStat);
  342. }
  343. return bRet;
  344. }
  345. /*****************************************************************************\
  346. * _init_create_sync (Local Routine)
  347. *
  348. * This creates the events and Critical Section needed for handling the synchronisation
  349. * in the monitor.
  350. *
  351. \*****************************************************************************/
  352. _inline BOOL _init_create_sync(VOID) {
  353. #ifdef WINNT32
  354. BOOL bRet = TRUE;
  355. g_dwConCount = 0;
  356. __try {
  357. InitializeCriticalSection(&g_csCreateSection);
  358. }
  359. __except (1) {
  360. bRet = FALSE;
  361. SetLastError (ERROR_INVALID_HANDLE);
  362. }
  363. if (bRet) {
  364. g_eResetConnections = CreateEvent( NULL, TRUE, TRUE, NULL );
  365. if (g_eResetConnections == NULL)
  366. bRet = FALSE;
  367. }
  368. return bRet;
  369. #else
  370. return TRUE;
  371. #endif
  372. }
  373. /*****************************************************************************\
  374. * InitializePrintProvider (API)
  375. *
  376. * The spooler calls this routine to initialize the Print-Provider. The list
  377. * of functions in the table are passed back to the spooler for it to use
  378. * when interfacing with the provider.
  379. *
  380. * NOTE: The (pszFullRegistryPath) is really a LPTSTR as far as Win9X is
  381. * concerned.
  382. *
  383. \*****************************************************************************/
  384. #ifdef WINNT32
  385. static PRINTPROVIDOR pfnPPList[] = {
  386. #else
  387. static LPCVOID pfnPPList[] = {
  388. #endif
  389. PPOpenPrinter,
  390. PPSetJob,
  391. PPGetJob,
  392. PPEnumJobs,
  393. stubAddPrinter,
  394. stubDeletePrinter,
  395. PPSetPrinter,
  396. PPGetPrinter,
  397. PPEnumPrinters,
  398. stubAddPrinterDriver,
  399. stubEnumPrinterDrivers,
  400. stubGetPrinterDriver,
  401. stubGetPrinterDriverDirectory,
  402. stubDeletePrinterDriver,
  403. stubAddPrintProcessor,
  404. stubEnumPrintProcessors,
  405. stubGetPrintProcessorDirectory,
  406. stubDeletePrintProcessor,
  407. stubEnumPrintProcessorDatatypes,
  408. PPStartDocPrinter,
  409. PPStartPagePrinter,
  410. PPWritePrinter,
  411. PPEndPagePrinter,
  412. PPAbortPrinter,
  413. stubReadPrinter,
  414. PPEndDocPrinter,
  415. PPAddJob,
  416. PPScheduleJob,
  417. stubGetPrinterData,
  418. stubSetPrinterData,
  419. stubWaitForPrinterChange,
  420. PPClosePrinter,
  421. stubAddForm,
  422. stubDeleteForm,
  423. stubGetForm,
  424. stubSetForm,
  425. stubEnumForms,
  426. stubEnumMonitors,
  427. PPEnumPorts,
  428. stubAddPort,
  429. #ifdef WINNT32
  430. NULL,
  431. NULL,
  432. #else
  433. stubConfigurePort,
  434. PPDeletePort,
  435. #endif
  436. stubCreatePrinterIC,
  437. stubPlayGdiScriptOnPrinterIC,
  438. stubDeletePrinterIC,
  439. stubAddPrinterConnection,
  440. stubDeletePrinterConnection,
  441. stubPrinterMessageBox,
  442. stubAddMonitor,
  443. stubDeleteMonitor
  444. #ifndef WIN9X
  445. ,
  446. NULL, // stubResetPrinter,
  447. NULL, // stubGetPrinterDriverEx should not be called as specified in spoolss\dll\nullpp.c
  448. PPFindFirstPrinterChangeNotification,
  449. PPFindClosePrinterChangeNotification,
  450. NULL, // stubAddPortEx,
  451. NULL, // stubShutDown,
  452. NULL, // stubRefreshPrinterChangeNotification,
  453. NULL, // stubOpenPrinterEx,
  454. NULL, // stubAddPrinterEx,
  455. NULL, // stubSetPort,
  456. NULL, // stubEnumPrinterData,
  457. NULL, // stubDeletePrinterData,
  458. NULL, // fpClusterSplOpen
  459. NULL, // fpClusterSplClose
  460. NULL, // fpClusterSplIsAlive
  461. NULL, // fpSetPrinterDataEx
  462. NULL, // fpGetPrinterDataEx
  463. NULL, // fpEnumPrinterDataEx
  464. NULL, // fpEnumPrinterKey
  465. NULL, // fpDeletePrinterDataEx
  466. NULL, // fpDeletePrinterKey
  467. NULL, // fpSeekPrinter
  468. NULL, // fpDeletePrinterDriverEx
  469. NULL, // fpAddPerMachineConnection
  470. NULL, // fpDeletePerMachineConnection
  471. NULL, // fpEnumPerMachineConnections
  472. PPXcvData, // fpXcvData
  473. NULL, // fpAddPrinterDriverEx
  474. NULL, // fpSplReadPrinter
  475. NULL, // fpDriverUnloadComplete
  476. NULL, // fpGetSpoolFileInfo
  477. NULL, // fpCommitSpoolData
  478. NULL, // fpCloseSpoolFileHandle
  479. NULL, // fpFlushPrinter
  480. NULL, // fpSendRecvBidiData
  481. NULL, // fpAddDriverCatalog
  482. #endif
  483. };
  484. BOOL WINAPI InitializePrintProvidor(
  485. LPPRINTPROVIDOR pPP,
  486. DWORD cEntries,
  487. LPWSTR pszFullRegistryPath)
  488. {
  489. HANDLE hThread;
  490. DWORD dwThreadId;
  491. g_pcsEndBrowserSessionLock = new CCriticalSection ();
  492. if (!g_pcsEndBrowserSessionLock || g_pcsEndBrowserSessionLock->bValid () == FALSE) {
  493. SetLastError(ERROR_INVALID_PARAMETER);
  494. return FALSE;
  495. }
  496. if (_init_load_provider() == FALSE) {
  497. DBG_ASSERT(FALSE, (TEXT("Assert: Failed module initialization")));
  498. return FALSE;
  499. }
  500. if (!pszFullRegistryPath || !*pszFullRegistryPath) {
  501. SetLastError(ERROR_INVALID_PARAMETER);
  502. return FALSE;
  503. }
  504. gpInetMon = new CInetMon;
  505. if (!gpInetMon || gpInetMon->bValid() == FALSE) {
  506. if (gpInetMon) {
  507. delete gpInetMon;
  508. }
  509. return FALSE;
  510. }
  511. if (gpInetMon && !gpInetMon->bValid ()) {
  512. delete gpInetMon;
  513. SetLastError(ERROR_INVALID_PARAMETER);
  514. return FALSE;
  515. }
  516. DBG_MSG(DBG_LEV_CALLTREE, (TEXT("Call: InitializePrintProvidor")));
  517. memcpy(pPP, pfnPPList, min(sizeof(pfnPPList), (int)cEntries));
  518. #ifdef WINNT32
  519. // Initialise synchronisation objects
  520. if (!_init_create_sync())
  521. return FALSE;
  522. // Initialize other names
  523. if (!BuildOtherNamesFromMachineName(&g_ppszOtherNames, &g_cOtherNames))
  524. return FALSE;
  525. g_bUpgrade = SplIsUpgrade();
  526. #endif
  527. if (_init_load_ports((LPTSTR)pszFullRegistryPath) == FALSE) {
  528. DBG_ASSERT(FALSE, (TEXT("Assert: Failed port initialization")));
  529. return FALSE;
  530. }
  531. if (!_init_write_displayname())
  532. return FALSE;
  533. if (hThread = CreateThread (NULL,
  534. 0,
  535. (LPTHREAD_START_ROUTINE) _init_provider_worker,
  536. NULL,
  537. 0,
  538. &dwThreadId)) {
  539. CloseHandle (hThread);
  540. return TRUE;
  541. }
  542. else
  543. return FALSE;
  544. }
  545. /*****************************************************************************\
  546. * DllEntryPoint
  547. *
  548. * This is the main entry-point for the library.
  549. *
  550. \*****************************************************************************/
  551. extern "C" {
  552. BOOL WINAPI DllEntryPoint(
  553. HINSTANCE hInstDll,
  554. DWORD dwAttach,
  555. LPVOID lpcReserved)
  556. {
  557. static BOOL s_bIsSpoolerProcess = FALSE;
  558. BOOL bRet = TRUE;
  559. switch (dwAttach) {
  560. case DLL_PROCESS_ATTACH:
  561. // Set the global-instance variable.
  562. //
  563. g_hInst = hInstDll;
  564. s_bIsSpoolerProcess = TRUE;
  565. break;
  566. case DLL_PROCESS_DETACH:
  567. #if 0
  568. // This code is not needed since the dll is never get loaded twice by spooler
  569. // -weihaic
  570. //
  571. if (s_bIsSpoolerProcess)
  572. _init_unload_provider();
  573. #endif
  574. #ifdef WINNT32
  575. DeleteCriticalSection( &g_csCreateSection );
  576. CloseHandle( g_eResetConnections );
  577. #endif
  578. if (g_pcsEndBrowserSessionLock)
  579. {
  580. delete g_pcsEndBrowserSessionLock;
  581. }
  582. break;
  583. case DLL_THREAD_ATTACH:
  584. case DLL_THREAD_DETACH:
  585. break;
  586. }
  587. return bRet;
  588. }
  589. }