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.

765 lines
18 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. All rights reserved
  4. Module Name:
  5. Downlevel cluster port support.
  6. Abstract:
  7. Supports mixing and matching downlevel and uplevel language
  8. and monitor ports.
  9. Author:
  10. Environment:
  11. User Mode -Win32
  12. Revision History:
  13. --*/
  14. #include <precomp.h>
  15. #pragma hdrstop
  16. /********************************************************************
  17. Downlevel Port Monitor (Dp)
  18. Dp support is used when we have an uplevel language monitor
  19. and downlevel port monitor. We pass a stub function vector
  20. to the LM and set the hMonitor to the downlevel pIniMonitor.
  21. When we get called, we can dereference the hMonitor to call the
  22. real downlevel monitor.
  23. ********************************************************************/
  24. BOOL
  25. DpEnumPorts(
  26. HANDLE hMonitor,
  27. LPWSTR pName,
  28. DWORD Level,
  29. LPBYTE pPorts,
  30. DWORD cbBuf,
  31. LPDWORD pcbNeeded,
  32. LPDWORD pcReturned
  33. )
  34. {
  35. PINIMONITOR pIniMonitor = (PINIMONITOR)hMonitor;
  36. return pIniMonitor->Monitor.pfnEnumPorts( pName,
  37. Level,
  38. pPorts,
  39. cbBuf,
  40. pcbNeeded,
  41. pcReturned );
  42. }
  43. BOOL
  44. DpOpenPort(
  45. HANDLE hMonitor,
  46. LPWSTR pName,
  47. PHANDLE pHandle
  48. )
  49. {
  50. PINIMONITOR pIniMonitor = (PINIMONITOR)hMonitor;
  51. return pIniMonitor->Monitor.pfnOpenPort( pName, pHandle );
  52. }
  53. BOOL
  54. DpOpenPortEx(
  55. HANDLE hMonitor,
  56. LPWSTR pPortName,
  57. LPWSTR pPrinterName,
  58. PHANDLE pHandle,
  59. struct _MONITOR FAR *pMonitor
  60. )
  61. {
  62. PINIMONITOR pIniMonitor = (PINIMONITOR)hMonitor;
  63. return pIniMonitor->Monitor.pfnOpenPortEx( pPortName,
  64. pPrinterName,
  65. pHandle,
  66. pMonitor );
  67. }
  68. BOOL
  69. DpAddPort(
  70. HANDLE hMonitor,
  71. LPWSTR pName,
  72. HWND hWnd,
  73. LPWSTR pMonitorName
  74. )
  75. {
  76. PINIMONITOR pIniMonitor = (PINIMONITOR)hMonitor;
  77. return pIniMonitor->Monitor.pfnAddPort( pName,
  78. hWnd,
  79. pMonitorName );
  80. }
  81. BOOL
  82. DpAddPortEx(
  83. HANDLE hMonitor,
  84. LPWSTR pName,
  85. DWORD Level,
  86. LPBYTE pBuffer,
  87. LPWSTR pMonitorName
  88. )
  89. {
  90. PINIMONITOR pIniMonitor = (PINIMONITOR)hMonitor;
  91. return pIniMonitor->Monitor.pfnAddPortEx( pName,
  92. Level,
  93. pBuffer,
  94. pMonitorName );
  95. }
  96. BOOL
  97. DpConfigurePort(
  98. HANDLE hMonitor,
  99. LPWSTR pName,
  100. HWND hWnd,
  101. LPWSTR pPortName
  102. )
  103. {
  104. PINIMONITOR pIniMonitor = (PINIMONITOR)hMonitor;
  105. return pIniMonitor->Monitor.pfnConfigurePort( pName,
  106. hWnd,
  107. pPortName );
  108. }
  109. BOOL
  110. DpDeletePort(
  111. HANDLE hMonitor,
  112. LPWSTR pName,
  113. HWND hWnd,
  114. LPWSTR pPortName
  115. )
  116. {
  117. PINIMONITOR pIniMonitor = (PINIMONITOR)hMonitor;
  118. return pIniMonitor->Monitor.pfnDeletePort( pName,
  119. hWnd,
  120. pPortName );
  121. }
  122. BOOL
  123. DpXcvOpenPort(
  124. HANDLE hMonitor,
  125. LPCWSTR pszObject,
  126. ACCESS_MASK GrantedAccess,
  127. PHANDLE phXcv
  128. )
  129. {
  130. PINIMONITOR pIniMonitor = (PINIMONITOR)hMonitor;
  131. return pIniMonitor->Monitor.pfnXcvOpenPort( pszObject,
  132. GrantedAccess,
  133. phXcv );
  134. }
  135. /********************************************************************
  136. Downlevel Language Monitor (Dl)
  137. Dl support is used when we have a downlevel language monitor
  138. and uplevel port monitor.
  139. This is very messy, since the language monitor is given the
  140. ports function vector directly, and we don't have any extra
  141. handles to pass around state information.
  142. Instead, we overload the name string yet again. The port name
  143. is converted to:
  144. {NormalPortName},{pIniMonitorHex}
  145. LPT1:,a53588
  146. We then strip off the two trailing hex numbers and pass LPT1:
  147. back.
  148. ********************************************************************/
  149. BOOL
  150. GetDlPointers(
  151. IN LPCWSTR pszName,
  152. OUT LPWSTR pszNameNew,
  153. OUT PINIMONITOR *ppIniMonitor,
  154. IN DWORD cchBufferSize
  155. )
  156. /*++
  157. Routine Description:
  158. Hack function to take a pszName and convert it to a new name
  159. string with two additional parameters: hMonitor and pMonitor2
  160. Arguments:
  161. pszName - Hacked up name overloaded with pIniMonitor.
  162. pszNameNew - Receives "real" shorter name of the port.
  163. ppIniMonitor - Receives cracked pIniMonitor.
  164. Return Value:
  165. --*/
  166. {
  167. BOOL bReturn = FALSE;
  168. LPCWSTR p;
  169. LPCWSTR p1 = NULL;
  170. for( p = pszName; p = wcschr( p, TEXT( ',' )); ){
  171. p1 = p;
  172. ++p;
  173. }
  174. if( p1 ){
  175. lstrcpyn( pszNameNew, pszName, cchBufferSize );
  176. pszNameNew[p1-pszName] = 0;
  177. ++p1;
  178. *ppIniMonitor = (PINIMONITOR)atox( p1 );
  179. __try {
  180. bReturn = ( (*ppIniMonitor)->signature == IMO_SIGNATURE );
  181. } except( EXCEPTION_EXECUTE_HANDLER ){
  182. }
  183. if( bReturn ){
  184. return TRUE;
  185. }
  186. }
  187. SetLastError( ERROR_NOT_SUPPORTED );
  188. return FALSE;
  189. }
  190. BOOL
  191. CreateDlName(
  192. IN LPCWSTR pszName,
  193. IN PINIMONITOR pIniMonitor,
  194. OUT LPWSTR pszNameNew
  195. )
  196. /*++
  197. Routine Description:
  198. Create a downlevel name that can be parsed by GetDlPointers.
  199. Arguments:
  200. pszName - Name of port. The newly created name must be < MAX_PATH,
  201. and since we need to append one hex values (4 characters) plus
  202. one comma, we need to verify that the string length has at least
  203. 5 characters left.
  204. pIniMonitor - Monitor structure of the uplevel port monitor.
  205. Return Value:
  206. TRUE - Success
  207. FALSE - Failure, due to too long port name length.
  208. --*/
  209. {
  210. if( lstrlen( pszName ) >= MAX_PATH - sizeof(ULONG_PTR) -1 ){
  211. SetLastError( ERROR_INVALID_PARAMETER );
  212. return FALSE;
  213. }
  214. wsprintf( pszNameNew,
  215. TEXT( "%s,%p" ),
  216. pszName,
  217. pIniMonitor );
  218. return TRUE;
  219. }
  220. FARPROC gafpMonitor2Stub[] = {
  221. (FARPROC) &DpEnumPorts,
  222. (FARPROC) &DpOpenPort,
  223. NULL, // OpenPortEx
  224. NULL, // StartDocPort
  225. NULL, // WritePort
  226. NULL, // ReadPort
  227. NULL, // EndDocPort
  228. NULL, // ClosePort
  229. (FARPROC) &DpAddPort,
  230. (FARPROC) &DpAddPortEx,
  231. (FARPROC) &DpConfigurePort,
  232. (FARPROC) &DpDeletePort,
  233. NULL,
  234. NULL,
  235. (FARPROC) &DpXcvOpenPort,
  236. NULL, // XcvDataPortW
  237. NULL, // XcvClosePortW
  238. NULL // Shutdown
  239. };
  240. BOOL
  241. DlEnumPorts(
  242. LPWSTR pName,
  243. DWORD Level,
  244. LPBYTE pPorts,
  245. DWORD cbBuf,
  246. LPDWORD pcbNeeded,
  247. LPDWORD pcReturned
  248. )
  249. {
  250. WCHAR szName[MAX_PATH];
  251. PINIMONITOR pIniMonitor;
  252. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  253. return pIniMonitor->Monitor2.pfnEnumPorts( pIniMonitor->hMonitor,
  254. szName,
  255. Level,
  256. pPorts,
  257. cbBuf,
  258. pcbNeeded,
  259. pcReturned );
  260. }
  261. return FALSE;
  262. }
  263. BOOL
  264. DlOpenPort(
  265. LPWSTR pName,
  266. PHANDLE pHandle
  267. )
  268. {
  269. WCHAR szName[MAX_PATH];
  270. PINIMONITOR pIniMonitor;
  271. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  272. return pIniMonitor->Monitor2.pfnOpenPort( pIniMonitor->hMonitor,
  273. szName,
  274. pHandle );
  275. }
  276. return FALSE;
  277. }
  278. BOOL
  279. DlOpenPortEx(
  280. LPWSTR pPortName,
  281. LPWSTR pPrinterName,
  282. PHANDLE pHandle,
  283. struct _MONITOR FAR *pMonitor
  284. )
  285. {
  286. SetLastError( ERROR_NOT_SUPPORTED );
  287. return FALSE;
  288. }
  289. BOOL
  290. DlAddPort(
  291. LPWSTR pName,
  292. HWND hWnd,
  293. LPWSTR pMonitorName
  294. )
  295. {
  296. WCHAR szName[MAX_PATH];
  297. PINIMONITOR pIniMonitor;
  298. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  299. return pIniMonitor->Monitor2.pfnAddPort( pIniMonitor->hMonitor,
  300. szName,
  301. hWnd,
  302. pMonitorName );
  303. }
  304. return FALSE;
  305. }
  306. BOOL
  307. DlAddPortEx(
  308. LPWSTR pName,
  309. DWORD Level,
  310. LPBYTE pBuffer,
  311. LPWSTR pMonitorName
  312. )
  313. {
  314. WCHAR szName[MAX_PATH];
  315. PINIMONITOR pIniMonitor;
  316. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  317. return pIniMonitor->Monitor2.pfnAddPortEx( pIniMonitor->hMonitor,
  318. pName,
  319. Level,
  320. pBuffer,
  321. pMonitorName );
  322. }
  323. return FALSE;
  324. }
  325. BOOL
  326. DlConfigurePort(
  327. LPWSTR pName,
  328. HWND hWnd,
  329. LPWSTR pPortName
  330. )
  331. {
  332. WCHAR szName[MAX_PATH];
  333. PINIMONITOR pIniMonitor;
  334. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  335. return pIniMonitor->Monitor2.pfnConfigurePort( pIniMonitor->hMonitor,
  336. szName,
  337. hWnd,
  338. pPortName );
  339. }
  340. return FALSE;
  341. }
  342. BOOL
  343. DlDeletePort(
  344. LPWSTR pName,
  345. HWND hWnd,
  346. LPWSTR pPortName
  347. )
  348. {
  349. WCHAR szName[MAX_PATH];
  350. PINIMONITOR pIniMonitor;
  351. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  352. return pIniMonitor->Monitor2.pfnDeletePort( pIniMonitor->hMonitor,
  353. szName,
  354. hWnd,
  355. pPortName );
  356. }
  357. return FALSE;
  358. }
  359. FARPROC gafpDlStub[] = {
  360. (FARPROC) &DlEnumPorts,
  361. (FARPROC) &DlOpenPort,
  362. (FARPROC) &DlOpenPortEx,
  363. NULL, // StartDocPort
  364. NULL, // WritePort
  365. NULL, // ReadPort
  366. NULL, // EndDocPort
  367. NULL, // ClosePort
  368. (FARPROC) &DlAddPort,
  369. (FARPROC) &DlAddPortEx,
  370. (FARPROC) &DlConfigurePort,
  371. (FARPROC) &DlDeletePort,
  372. NULL,
  373. NULL,
  374. };
  375. VOID
  376. InitializeUMonitor(
  377. PINIMONITOR pIniMonitor
  378. )
  379. /*++
  380. Routine Description:
  381. Initialize an uplevel port monitor for downlevel support. When a
  382. downlevel language monitor is used with an uplevel port monitor,
  383. we need to setup stubs since the language monitor calls the port
  384. monitor interfaces directly.
  385. We create a downlevel function vector with patched entries and pass
  386. it to the language monitor. The LM is passed in a formatted name
  387. that has both the port name and also the pIniMonitor encoded in the
  388. string.
  389. Arguments:
  390. pIniMonitor - Monitor to initialize.
  391. Return Value:
  392. --*/
  393. {
  394. FARPROC *pfpSrc;
  395. FARPROC *pfpDest;
  396. FARPROC *pfpStub;
  397. INT i;
  398. //
  399. // Create the downlevel port monitor interface. This is
  400. // used when we have a downlevel language monitor with an
  401. // uplevel port monitor.
  402. //
  403. CopyMemory( (LPBYTE)&pIniMonitor->Monitor,
  404. (LPBYTE)&pIniMonitor->Monitor2.pfnEnumPorts,
  405. sizeof( pIniMonitor->Monitor ));
  406. for( i=0,
  407. pfpSrc = (FARPROC*)&pIniMonitor->Monitor2.pfnEnumPorts,
  408. pfpDest = (FARPROC*)&pIniMonitor->Monitor,
  409. pfpStub = gafpDlStub;
  410. i < sizeof( pIniMonitor->Monitor )/sizeof( *pfpDest );
  411. ++i, ++pfpDest, ++pfpStub, ++pfpSrc ){
  412. *pfpDest = *pfpStub ?
  413. *pfpStub :
  414. *pfpSrc;
  415. }
  416. }
  417. /********************************************************************
  418. Initialize a Downlevel language or port monitor.
  419. ********************************************************************/
  420. //
  421. // List of monitor functions for downlevel (3.51) monitors. Instead
  422. // of receiving a function vector, the spooler has to call GetProcAddress
  423. // on each of these functions. The order of these ports must be in the
  424. // same format as the pMonitor2 structure.
  425. //
  426. LPCSTR aszMonitorFunction[] = {
  427. "EnumPortsW",
  428. "OpenPort",
  429. NULL,
  430. "StartDocPort",
  431. "WritePort",
  432. "ReadPort",
  433. "EndDocPort",
  434. "ClosePort",
  435. "AddPortW",
  436. "AddPortExW",
  437. "ConfigurePortW",
  438. "DeletePortW",
  439. NULL,
  440. NULL,
  441. "XcvOpenPortW",
  442. "XcvDataPortW",
  443. "XcvClosePortW"
  444. };
  445. PINIMONITOR
  446. InitializeDMonitor(
  447. PINIMONITOR pIniMonitor,
  448. LPWSTR pszRegistryRoot
  449. )
  450. /*++
  451. Routine Description:
  452. Initialize downlevel monitor.
  453. Arguments:
  454. pIniMonitor - Partially created pIniMonitor that needs to be initialized
  455. with functions.
  456. Return Value:
  457. NULL - Initialization failed, but possibly because monitor could not
  458. initialize. Still add monitor to spooler datastructures.
  459. (PINIMONITOR)-1 - Failed.
  460. --*/
  461. {
  462. BOOL (*pfnInitialize)(LPWSTR) = NULL;
  463. BOOL (*pfnInitializeMonitorEx)(LPWSTR, LPMONITOR) = NULL;
  464. LPMONITOREX (*pfnInitializePrintMonitor)(LPWSTR) = NULL;
  465. LPMONITOREX pMonEx;
  466. DWORD cbDpMonitor;
  467. PINIMONITOR pReturnValue = (PINIMONITOR)-1;
  468. //
  469. // Try calling the entry points in the following order:
  470. // InitializePrintMonitor,
  471. // InitializeMonitorEx,
  472. // InitializeMonitor
  473. //
  474. (FARPROC)pfnInitializePrintMonitor = GetProcAddress(
  475. pIniMonitor->hModule,
  476. "InitializePrintMonitor" );
  477. if( !pfnInitializePrintMonitor ){
  478. (FARPROC)pfnInitializeMonitorEx = GetProcAddress(
  479. pIniMonitor->hModule,
  480. "InitializeMonitorEx" );
  481. if( !pfnInitializeMonitorEx ){
  482. (FARPROC)pfnInitialize = GetProcAddress(
  483. pIniMonitor->hModule,
  484. "InitializeMonitor" );
  485. }
  486. }
  487. if ( !pfnInitializePrintMonitor &&
  488. !pfnInitializeMonitorEx &&
  489. !pfnInitialize ) {
  490. DBGMSG( DBG_WARNING,
  491. ( "InitializeDLPrintMonitor %ws GetProcAddress failed %d\n",
  492. pszRegistryRoot,
  493. GetLastError()));
  494. } else {
  495. BOOL bSuccess = FALSE;
  496. LeaveSplSem();
  497. if( pfnInitializePrintMonitor ) {
  498. pMonEx = (*pfnInitializePrintMonitor)(pszRegistryRoot);
  499. if( pMonEx ){
  500. bSuccess = TRUE;
  501. cbDpMonitor = pMonEx->dwMonitorSize;
  502. CopyMemory((LPBYTE)&pIniMonitor->Monitor,
  503. (LPBYTE)&pMonEx->Monitor,
  504. min(pMonEx->dwMonitorSize, sizeof(MONITOR)));
  505. }
  506. } else if ( pfnInitializeMonitorEx ) {
  507. bSuccess = (*pfnInitializeMonitorEx)( pszRegistryRoot,
  508. &pIniMonitor->Monitor );
  509. cbDpMonitor = sizeof(MONITOR);
  510. } else {
  511. INT i;
  512. FARPROC* pfp;
  513. bSuccess = (BOOL)((*pfnInitialize)(pszRegistryRoot));
  514. cbDpMonitor = sizeof(MONITOR);
  515. for( i=0, pfp=(FARPROC*)&pIniMonitor->Monitor;
  516. i< COUNTOF( aszMonitorFunction );
  517. ++i, ++pfp ){
  518. if( aszMonitorFunction[i] ){
  519. *pfp = GetProcAddress( pIniMonitor->hModule,
  520. aszMonitorFunction[i] );
  521. }
  522. }
  523. }
  524. EnterSplSem();
  525. if( bSuccess ){
  526. INT i;
  527. INT iMax;
  528. FARPROC* pfpSrc;
  529. FARPROC* pfpDest;
  530. FARPROC* pfpStub;
  531. //
  532. // Store away the pIniMonitor as the handle returned from the monitor.
  533. // When we call the stub, it will cast it back to a pIniMonitor then
  534. // use it to get to pIniMonitor->Monitor.fn.
  535. //
  536. pIniMonitor->hMonitor = (HANDLE)pIniMonitor;
  537. //
  538. // New size of the stub Monitor2 structure is the size of the
  539. // downlevel monitor, plus the extra DWORD for Monitor2.cbSize.
  540. //
  541. pIniMonitor->Monitor2.cbSize = min( cbDpMonitor + sizeof( DWORD ),
  542. sizeof( MONITOR2 ));
  543. //
  544. // The number of stub pointers we want to copy is the size of
  545. // the struct, minus the extra DWORD that we added above.
  546. //
  547. iMax = (pIniMonitor->Monitor2.cbSize - sizeof( DWORD )) / sizeof( pfpSrc );
  548. //
  549. // We have copied the monitor entrypoints into the downlevel Monitor
  550. // structure. Now we must run through the uplevel vector and fill
  551. // it in with the stubs.
  552. //
  553. for( i=0,
  554. pfpSrc = (FARPROC*)&pIniMonitor->Monitor,
  555. pfpDest = (FARPROC*)&pIniMonitor->Monitor2.pfnEnumPorts,
  556. pfpStub = (FARPROC*)gafpMonitor2Stub;
  557. i< iMax;
  558. ++i, ++pfpSrc, ++pfpDest, ++pfpStub ){
  559. if( *pfpSrc ){
  560. //
  561. // Stubs aren't needed for all routines. Only use them
  562. // when they are needed; in other cases, just use the
  563. // regular one.
  564. //
  565. *pfpDest = *pfpStub ?
  566. *pfpStub :
  567. *pfpSrc;
  568. }
  569. }
  570. //
  571. // Success, return the original pIniMonitor.
  572. //
  573. pReturnValue = pIniMonitor;
  574. } else {
  575. DBGMSG( DBG_WARNING,
  576. ( "InitializeDLPrintMonitor %ws Init failed %d\n",
  577. pszRegistryRoot,
  578. GetLastError()));
  579. //
  580. // Some old (before NT 4.0) monitors may not initialize until
  581. // reboot.
  582. //
  583. if( pfnInitialize ){
  584. pReturnValue = NULL;
  585. }
  586. }
  587. }
  588. return pReturnValue;
  589. }