Leaked source code of windows server 2003
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.

753 lines
19 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. StringCchCopy(pszNameNew, cchBufferSize, pszName );
  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. IN OUT PWSTR pszNameNew,
  195. IN SIZE_T cchNameNew
  196. )
  197. /*++
  198. Routine Description:
  199. Create a downlevel name that can be parsed by GetDlPointers.
  200. Arguments:
  201. pszName - Name of port. The newly created name must be < MAX_PATH,
  202. and since we need to append one hex values (4 characters) plus
  203. one comma, we need to verify that the string length has at least
  204. 5 characters left.
  205. pIniMonitor - Monitor structure of the uplevel port monitor.
  206. Return Value:
  207. TRUE - Success
  208. FALSE - Failure, due to too long port name length.
  209. --*/
  210. {
  211. return BoolFromHResult(StringCchPrintf(pszNameNew, cchNameNew, TEXT( "%s,%p" ), pszName, pIniMonitor));
  212. }
  213. FARPROC gafpMonitor2Stub[] = {
  214. (FARPROC) &DpEnumPorts,
  215. (FARPROC) &DpOpenPort,
  216. NULL, // OpenPortEx
  217. NULL, // StartDocPort
  218. NULL, // WritePort
  219. NULL, // ReadPort
  220. NULL, // EndDocPort
  221. NULL, // ClosePort
  222. (FARPROC) &DpAddPort,
  223. (FARPROC) &DpAddPortEx,
  224. (FARPROC) &DpConfigurePort,
  225. (FARPROC) &DpDeletePort,
  226. NULL,
  227. NULL,
  228. (FARPROC) &DpXcvOpenPort,
  229. NULL, // XcvDataPortW
  230. NULL, // XcvClosePortW
  231. NULL // Shutdown
  232. };
  233. BOOL
  234. DlEnumPorts(
  235. LPWSTR pName,
  236. DWORD Level,
  237. LPBYTE pPorts,
  238. DWORD cbBuf,
  239. LPDWORD pcbNeeded,
  240. LPDWORD pcReturned
  241. )
  242. {
  243. WCHAR szName[MAX_PATH];
  244. PINIMONITOR pIniMonitor;
  245. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  246. return pIniMonitor->Monitor2.pfnEnumPorts( pIniMonitor->hMonitor,
  247. szName,
  248. Level,
  249. pPorts,
  250. cbBuf,
  251. pcbNeeded,
  252. pcReturned );
  253. }
  254. return FALSE;
  255. }
  256. BOOL
  257. DlOpenPort(
  258. LPWSTR pName,
  259. PHANDLE pHandle
  260. )
  261. {
  262. WCHAR szName[MAX_PATH];
  263. PINIMONITOR pIniMonitor;
  264. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  265. return pIniMonitor->Monitor2.pfnOpenPort( pIniMonitor->hMonitor,
  266. szName,
  267. pHandle );
  268. }
  269. return FALSE;
  270. }
  271. BOOL
  272. DlOpenPortEx(
  273. LPWSTR pPortName,
  274. LPWSTR pPrinterName,
  275. PHANDLE pHandle,
  276. struct _MONITOR FAR *pMonitor
  277. )
  278. {
  279. SetLastError( ERROR_NOT_SUPPORTED );
  280. return FALSE;
  281. }
  282. BOOL
  283. DlAddPort(
  284. LPWSTR pName,
  285. HWND hWnd,
  286. LPWSTR pMonitorName
  287. )
  288. {
  289. WCHAR szName[MAX_PATH];
  290. PINIMONITOR pIniMonitor;
  291. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  292. return pIniMonitor->Monitor2.pfnAddPort( pIniMonitor->hMonitor,
  293. szName,
  294. hWnd,
  295. pMonitorName );
  296. }
  297. return FALSE;
  298. }
  299. BOOL
  300. DlAddPortEx(
  301. LPWSTR pName,
  302. DWORD Level,
  303. LPBYTE pBuffer,
  304. LPWSTR pMonitorName
  305. )
  306. {
  307. WCHAR szName[MAX_PATH];
  308. PINIMONITOR pIniMonitor;
  309. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  310. return pIniMonitor->Monitor2.pfnAddPortEx( pIniMonitor->hMonitor,
  311. pName,
  312. Level,
  313. pBuffer,
  314. pMonitorName );
  315. }
  316. return FALSE;
  317. }
  318. BOOL
  319. DlConfigurePort(
  320. LPWSTR pName,
  321. HWND hWnd,
  322. LPWSTR pPortName
  323. )
  324. {
  325. WCHAR szName[MAX_PATH];
  326. PINIMONITOR pIniMonitor;
  327. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  328. return pIniMonitor->Monitor2.pfnConfigurePort( pIniMonitor->hMonitor,
  329. szName,
  330. hWnd,
  331. pPortName );
  332. }
  333. return FALSE;
  334. }
  335. BOOL
  336. DlDeletePort(
  337. LPWSTR pName,
  338. HWND hWnd,
  339. LPWSTR pPortName
  340. )
  341. {
  342. WCHAR szName[MAX_PATH];
  343. PINIMONITOR pIniMonitor;
  344. if( GetDlPointers( pName, szName, &pIniMonitor, COUNTOF(szName) )){
  345. return pIniMonitor->Monitor2.pfnDeletePort( pIniMonitor->hMonitor,
  346. szName,
  347. hWnd,
  348. pPortName );
  349. }
  350. return FALSE;
  351. }
  352. FARPROC gafpDlStub[] = {
  353. (FARPROC) &DlEnumPorts,
  354. (FARPROC) &DlOpenPort,
  355. (FARPROC) &DlOpenPortEx,
  356. NULL, // StartDocPort
  357. NULL, // WritePort
  358. NULL, // ReadPort
  359. NULL, // EndDocPort
  360. NULL, // ClosePort
  361. (FARPROC) &DlAddPort,
  362. (FARPROC) &DlAddPortEx,
  363. (FARPROC) &DlConfigurePort,
  364. (FARPROC) &DlDeletePort,
  365. NULL,
  366. NULL,
  367. };
  368. VOID
  369. InitializeUMonitor(
  370. PINIMONITOR pIniMonitor
  371. )
  372. /*++
  373. Routine Description:
  374. Initialize an uplevel port monitor for downlevel support. When a
  375. downlevel language monitor is used with an uplevel port monitor,
  376. we need to setup stubs since the language monitor calls the port
  377. monitor interfaces directly.
  378. We create a downlevel function vector with patched entries and pass
  379. it to the language monitor. The LM is passed in a formatted name
  380. that has both the port name and also the pIniMonitor encoded in the
  381. string.
  382. Arguments:
  383. pIniMonitor - Monitor to initialize.
  384. Return Value:
  385. --*/
  386. {
  387. FARPROC *pfpSrc;
  388. FARPROC *pfpDest;
  389. FARPROC *pfpStub;
  390. INT i;
  391. //
  392. // Create the downlevel port monitor interface. This is
  393. // used when we have a downlevel language monitor with an
  394. // uplevel port monitor.
  395. //
  396. CopyMemory((LPBYTE)&pIniMonitor->Monitor, (LPBYTE)&pIniMonitor->Monitor2.pfnEnumPorts, sizeof( pIniMonitor->Monitor ));
  397. for( i=0,
  398. pfpSrc = (FARPROC*)&pIniMonitor->Monitor2.pfnEnumPorts,
  399. pfpDest = (FARPROC*)&pIniMonitor->Monitor,
  400. pfpStub = gafpDlStub;
  401. i < sizeof( pIniMonitor->Monitor )/sizeof( *pfpDest );
  402. ++i, ++pfpDest, ++pfpStub, ++pfpSrc ){
  403. *pfpDest = *pfpStub ?
  404. *pfpStub :
  405. *pfpSrc;
  406. }
  407. }
  408. /********************************************************************
  409. Initialize a Downlevel language or port monitor.
  410. ********************************************************************/
  411. //
  412. // List of monitor functions for downlevel (3.51) monitors. Instead
  413. // of receiving a function vector, the spooler has to call GetProcAddress
  414. // on each of these functions. The order of these ports must be in the
  415. // same format as the pMonitor2 structure.
  416. //
  417. LPCSTR aszMonitorFunction[] = {
  418. "EnumPortsW",
  419. "OpenPort",
  420. NULL,
  421. "StartDocPort",
  422. "WritePort",
  423. "ReadPort",
  424. "EndDocPort",
  425. "ClosePort",
  426. "AddPortW",
  427. "AddPortExW",
  428. "ConfigurePortW",
  429. "DeletePortW",
  430. NULL,
  431. NULL,
  432. "XcvOpenPortW",
  433. "XcvDataPortW",
  434. "XcvClosePortW"
  435. };
  436. PINIMONITOR
  437. InitializeDMonitor(
  438. PINIMONITOR pIniMonitor,
  439. LPWSTR pszRegistryRoot
  440. )
  441. /*++
  442. Routine Description:
  443. Initialize downlevel monitor.
  444. Arguments:
  445. pIniMonitor - Partially created pIniMonitor that needs to be initialized
  446. with functions.
  447. Return Value:
  448. NULL - Initialization failed, but possibly because monitor could not
  449. initialize. Still add monitor to spooler datastructures.
  450. (PINIMONITOR)-1 - Failed.
  451. --*/
  452. {
  453. BOOL (*pfnInitialize)(LPWSTR) = NULL;
  454. BOOL (*pfnInitializeMonitorEx)(LPWSTR, LPMONITOR) = NULL;
  455. LPMONITOREX (*pfnInitializePrintMonitor)(LPWSTR) = NULL;
  456. LPMONITOREX pMonEx;
  457. DWORD cbDpMonitor;
  458. PINIMONITOR pReturnValue = (PINIMONITOR)-1;
  459. //
  460. // Try calling the entry points in the following order:
  461. // InitializePrintMonitor,
  462. // InitializeMonitorEx,
  463. // InitializeMonitor
  464. //
  465. (FARPROC)pfnInitializePrintMonitor = GetProcAddress(
  466. pIniMonitor->hModule,
  467. "InitializePrintMonitor" );
  468. if( !pfnInitializePrintMonitor ){
  469. (FARPROC)pfnInitializeMonitorEx = GetProcAddress(
  470. pIniMonitor->hModule,
  471. "InitializeMonitorEx" );
  472. if( !pfnInitializeMonitorEx ){
  473. (FARPROC)pfnInitialize = GetProcAddress(
  474. pIniMonitor->hModule,
  475. "InitializeMonitor" );
  476. }
  477. }
  478. if ( !pfnInitializePrintMonitor &&
  479. !pfnInitializeMonitorEx &&
  480. !pfnInitialize ) {
  481. DBGMSG( DBG_WARNING,
  482. ( "InitializeDLPrintMonitor %ws GetProcAddress failed %d\n",
  483. pszRegistryRoot,
  484. GetLastError()));
  485. } else {
  486. BOOL bSuccess = FALSE;
  487. LeaveSplSem();
  488. if( pfnInitializePrintMonitor ) {
  489. pMonEx = (*pfnInitializePrintMonitor)(pszRegistryRoot);
  490. if( pMonEx ){
  491. bSuccess = TRUE;
  492. cbDpMonitor = pMonEx->dwMonitorSize;
  493. CopyMemory((LPBYTE)&pIniMonitor->Monitor,
  494. (LPBYTE)&pMonEx->Monitor,
  495. min(pMonEx->dwMonitorSize, sizeof(MONITOR)));
  496. }
  497. } else if ( pfnInitializeMonitorEx ) {
  498. bSuccess = (*pfnInitializeMonitorEx)( pszRegistryRoot,
  499. &pIniMonitor->Monitor );
  500. cbDpMonitor = sizeof(MONITOR);
  501. } else {
  502. INT i;
  503. FARPROC* pfp;
  504. bSuccess = (BOOL)((*pfnInitialize)(pszRegistryRoot));
  505. cbDpMonitor = sizeof(MONITOR);
  506. for( i=0, pfp=(FARPROC*)&pIniMonitor->Monitor;
  507. i< COUNTOF( aszMonitorFunction );
  508. ++i, ++pfp ){
  509. if( aszMonitorFunction[i] ){
  510. *pfp = GetProcAddress( pIniMonitor->hModule,
  511. aszMonitorFunction[i] );
  512. }
  513. }
  514. }
  515. EnterSplSem();
  516. if( bSuccess ){
  517. INT i;
  518. INT iMax;
  519. FARPROC* pfpSrc;
  520. FARPROC* pfpDest;
  521. FARPROC* pfpStub;
  522. //
  523. // Store away the pIniMonitor as the handle returned from the monitor.
  524. // When we call the stub, it will cast it back to a pIniMonitor then
  525. // use it to get to pIniMonitor->Monitor.fn.
  526. //
  527. pIniMonitor->hMonitor = (HANDLE)pIniMonitor;
  528. //
  529. // New size of the stub Monitor2 structure is the size of the
  530. // downlevel monitor, plus the extra DWORD for Monitor2.cbSize.
  531. //
  532. pIniMonitor->Monitor2.cbSize = min( cbDpMonitor + sizeof( DWORD ),
  533. sizeof( MONITOR2 ));
  534. //
  535. // The number of stub pointers we want to copy is the size of
  536. // the struct, minus the extra DWORD that we added above.
  537. //
  538. iMax = (pIniMonitor->Monitor2.cbSize - sizeof( DWORD )) / sizeof( pfpSrc );
  539. //
  540. // We have copied the monitor entrypoints into the downlevel Monitor
  541. // structure. Now we must run through the uplevel vector and fill
  542. // it in with the stubs.
  543. //
  544. for( i=0,
  545. pfpSrc = (FARPROC*)&pIniMonitor->Monitor,
  546. pfpDest = (FARPROC*)&pIniMonitor->Monitor2.pfnEnumPorts,
  547. pfpStub = (FARPROC*)gafpMonitor2Stub;
  548. i< iMax;
  549. ++i, ++pfpSrc, ++pfpDest, ++pfpStub ){
  550. if( *pfpSrc ){
  551. //
  552. // Stubs aren't needed for all routines. Only use them
  553. // when they are needed; in other cases, just use the
  554. // regular one.
  555. //
  556. *pfpDest = *pfpStub ?
  557. *pfpStub :
  558. *pfpSrc;
  559. }
  560. }
  561. //
  562. // Success, return the original pIniMonitor.
  563. //
  564. pReturnValue = pIniMonitor;
  565. } else {
  566. DBGMSG( DBG_WARNING,
  567. ( "InitializeDLPrintMonitor %ws Init failed %d\n",
  568. pszRegistryRoot,
  569. GetLastError()));
  570. //
  571. // Some old (before NT 4.0) monitors may not initialize until
  572. // reboot.
  573. //
  574. if( pfnInitialize ){
  575. pReturnValue = NULL;
  576. }
  577. }
  578. }
  579. return pReturnValue;
  580. }