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.

844 lines
14 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. monitorhndl.cxx
  5. Abstract:
  6. This is the class that wrapps the port/language monitor
  7. handle.
  8. Author:
  9. Adina Trufinescu July 16th, 2002
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "monhndl.hxx"
  15. WCHAR TMonitorHandle::m_szFILE[] = L"FILE:";
  16. /*++
  17. Routine Name:
  18. Constructor
  19. Routine Description:
  20. Returns number of elements that could be enumerated.
  21. NOT thread safe.
  22. Arguments:
  23. pIniPort - pointer to INIPORT structure
  24. pIniLangMonitor - pointer to INIMONITOR structure
  25. represented the preffered language monitor.
  26. pszPrinterName - string representing the printer name
  27. Return Value:
  28. NONE
  29. Last Error:
  30. Not Set.
  31. --*/
  32. TMonitorHandle::
  33. TMonitorHandle(
  34. IN PINIPORT pIniPort,
  35. IN PINIMONITOR pIniLangMonitor,
  36. IN LPWSTR pszPrinterName
  37. ) : m_pIniPort(pIniPort),
  38. m_pIniLangMonitor(pIniLangMonitor),
  39. m_pszPrinterName(pszPrinterName),
  40. m_RefCnt(0),
  41. m_hPort(NULL),
  42. m_OpenedMonitorType(kNone),
  43. m_hValid(E_FAIL)
  44. {
  45. SplInSem();
  46. if (SUCCEEDED(m_hValid = (m_pIniPort) ? S_OK : E_INVALIDARG))
  47. {
  48. if (SUCCEEDED(m_hValid))
  49. {
  50. if (m_pIniPort->Status & PP_FILE)
  51. {
  52. m_hValid = OpenMonitorForFILEPort();
  53. }
  54. else
  55. {
  56. if (m_pIniLangMonitor && !m_pIniLangMonitor->Monitor2.pfnOpenPortEx)
  57. {
  58. m_pIniLangMonitor = NULL;
  59. }
  60. m_hValid = Open();
  61. }
  62. if (SUCCEEDED(m_hValid))
  63. {
  64. INCPORTREF(m_pIniPort);
  65. INCSPOOLERREF(m_pIniPort->pIniSpooler);
  66. INCMONITORREF(static_cast<PINIMONITOR>(*this));
  67. }
  68. }
  69. }
  70. }
  71. /*++
  72. Routine Name:
  73. Destructor
  74. Routine Description:
  75. Destructor
  76. Arguments:
  77. NONE
  78. Return Value:
  79. NONE
  80. Last Error:
  81. Not Set.
  82. --*/
  83. TMonitorHandle::
  84. ~TMonitorHandle(
  85. VOID
  86. )
  87. {
  88. SplInSem();
  89. if (SUCCEEDED(m_hValid))
  90. {
  91. Close();
  92. DECPORTREF(m_pIniPort);
  93. DECSPOOLERREF(m_pIniPort->pIniSpooler);
  94. }
  95. }
  96. /*++
  97. Routine Name:
  98. Open
  99. Routine Description:
  100. Opens the correct monitor.
  101. If the language monitor is NULL or it
  102. doesn't support OpenPortEx, it will open the port monitor.
  103. Arguments:
  104. NONE
  105. Return Value:
  106. HRESULT
  107. Last Error:
  108. Not Set.
  109. --*/
  110. HRESULT
  111. TMonitorHandle::
  112. Open(
  113. VOID
  114. )
  115. {
  116. HRESULT hr;
  117. hr = m_pIniLangMonitor ?
  118. (m_pIniLangMonitor->bUplevel ?
  119. OpenLangMonitorUplevel() :
  120. OpenLangMonitorDownlevel()):
  121. OpenPortMonitor();
  122. return hr;
  123. }
  124. /*++
  125. Routine Name:
  126. Close
  127. Routine Description:
  128. Closes the opened monitor.
  129. Arguments:
  130. NONE
  131. Return Value:
  132. HRESULT
  133. Last Error:
  134. Not Set.
  135. --*/
  136. HRESULT
  137. TMonitorHandle::
  138. Close(
  139. VOID
  140. )
  141. {
  142. HRESULT hr = m_hValid;
  143. HANDLE hPort = m_hPort;
  144. if (SUCCEEDED(hr))
  145. {
  146. PINIMONITOR pIniMonitor = static_cast<PINIMONITOR>(*this);
  147. if (pIniMonitor)
  148. {
  149. LeaveSpoolerSem();
  150. if (!(pIniMonitor->Monitor2.pfnClosePort)(hPort))
  151. {
  152. hPort = NULL;
  153. hr = HResultFromWin32(GetLastError());
  154. }
  155. ReEnterSpoolerSem();
  156. if (SUCCEEDED(hr))
  157. {
  158. if (pIniMonitor == m_pIniPort->pIniLangMonitor)
  159. {
  160. m_pIniPort->pIniLangMonitor = NULL;
  161. }
  162. m_hPort = NULL;
  163. DECMONITORREF(pIniMonitor);
  164. }
  165. }
  166. }
  167. return hr;
  168. }
  169. /*++
  170. Routine Name:
  171. OpenLangMonitorUplevel
  172. Routine Description:
  173. Opens the language monitor using Monitor2.OpenPortEx.
  174. Arguments:
  175. NONE
  176. Return Value:
  177. HRESULT
  178. Last Error:
  179. Not Set.
  180. --*/
  181. HRESULT
  182. TMonitorHandle::
  183. OpenLangMonitorUplevel(
  184. VOID
  185. )
  186. {
  187. HRESULT hr = S_OK;
  188. INCMONITORREF(m_pIniLangMonitor);
  189. LeaveSpoolerSem();
  190. SetLastError(ERROR_SUCCESS);
  191. if (!(*(m_pIniLangMonitor)->Monitor2.pfnOpenPortEx)(m_pIniLangMonitor->hMonitor,
  192. m_pIniPort->pIniMonitor->hMonitor,
  193. m_pIniPort->pName,
  194. m_pszPrinterName,
  195. &m_hPort,
  196. &m_pIniPort->pIniMonitor->Monitor2))
  197. {
  198. if (SUCCEEDED(hr = HResultFromWin32(GetLastError())))
  199. {
  200. hr = HResultFromWin32(ERROR_INVALID_HANDLE);
  201. }
  202. }
  203. else
  204. {
  205. hr = m_hPort ?
  206. S_OK :
  207. HResultFromWin32(ERROR_INVALID_HANDLE);
  208. }
  209. ReEnterSpoolerSem();
  210. DECMONITORREF(m_pIniLangMonitor);
  211. if (SUCCEEDED(hr))
  212. {
  213. m_OpenedMonitorType = kLanguage;
  214. m_pIniPort->pIniLangMonitor = m_pIniLangMonitor;
  215. }
  216. SetLastError(HRESULT_CODE(hr));
  217. return hr;
  218. }
  219. /*++
  220. Routine Name:
  221. OpenLangMonitorDownlevel
  222. Routine Description:
  223. Opens the language monitor using Monitor.OpenPortEx.
  224. If the port monitor is downlevel, create unique name string.
  225. Arguments:
  226. NONE
  227. Return Value:
  228. HRESULT
  229. Last Error:
  230. Not Set.
  231. --*/
  232. HRESULT
  233. TMonitorHandle::
  234. OpenLangMonitorDownlevel(
  235. VOID
  236. )
  237. {
  238. HRESULT hr = S_OK;
  239. LPWSTR pszPort = NULL;
  240. WCHAR szPortNew[MAX_PATH];
  241. if (m_pIniPort->pIniMonitor->bUplevel)
  242. {
  243. //
  244. // Downlevel port monitor; create hack string.
  245. //
  246. if (SUCCEEDED(StringCchPrintf(szPortNew,
  247. COUNTOF(szPortNew),
  248. TEXT("%s,%p"),
  249. m_pIniPort->pName,
  250. m_pIniPort->pIniMonitor)))
  251. {
  252. pszPort = szPortNew;
  253. }
  254. }
  255. else
  256. {
  257. pszPort = m_pIniPort->pName;
  258. }
  259. if (pszPort)
  260. {
  261. INCMONITORREF(m_pIniLangMonitor);
  262. LeaveSpoolerSem();
  263. SetLastError(ERROR_SUCCESS);
  264. if (!(*(m_pIniLangMonitor)->Monitor.pfnOpenPortEx)(pszPort,
  265. m_pszPrinterName,
  266. &m_hPort,
  267. &m_pIniPort->pIniMonitor->Monitor))
  268. {
  269. if (SUCCEEDED(hr = HResultFromWin32(GetLastError())))
  270. {
  271. hr = HResultFromWin32(ERROR_INVALID_HANDLE);
  272. }
  273. }
  274. else
  275. {
  276. hr = m_hPort ?
  277. S_OK :
  278. HResultFromWin32(ERROR_INVALID_HANDLE);
  279. }
  280. ReEnterSpoolerSem();
  281. DECMONITORREF(m_pIniLangMonitor);
  282. if (SUCCEEDED(hr))
  283. {
  284. m_OpenedMonitorType = kLanguage;
  285. m_pIniPort->pIniLangMonitor = m_pIniLangMonitor;
  286. }
  287. }
  288. else
  289. {
  290. m_pIniLangMonitor = NULL;
  291. hr = OpenPortMonitor();
  292. }
  293. SetLastError(HRESULT_CODE(hr));
  294. return hr;
  295. }
  296. /*++
  297. Routine Name:
  298. OpenPortMonitor
  299. Routine Description:
  300. Opens the port monitor using Monitor2.pfnOpenPort.
  301. Arguments:
  302. NONE
  303. Return Value:
  304. HRESULT
  305. Last Error:
  306. Not Set.
  307. --*/
  308. HRESULT
  309. TMonitorHandle::
  310. OpenPortMonitor(
  311. VOID
  312. )
  313. {
  314. HRESULT hr = E_INVALIDARG;
  315. if (m_pIniPort &&
  316. m_pIniPort->pIniMonitor &&
  317. m_pIniPort->pIniMonitor->Monitor2.pfnOpenPort)
  318. {
  319. INCMONITORREF(m_pIniPort->pIniMonitor);
  320. LeaveSpoolerSem();
  321. SetLastError(ERROR_SUCCESS);
  322. if ((m_pIniPort->pIniMonitor->Monitor2.pfnOpenPort)(m_pIniPort->pIniMonitor->hMonitor,
  323. m_pIniPort->pName,
  324. &m_hPort))
  325. {
  326. hr = m_hPort ?
  327. S_OK :
  328. HResultFromWin32(ERROR_INVALID_HANDLE);
  329. }
  330. else
  331. {
  332. if (SUCCEEDED(hr = HResultFromWin32(GetLastError())))
  333. {
  334. hr = HResultFromWin32(ERROR_INVALID_HANDLE);
  335. }
  336. }
  337. ReEnterSpoolerSem();
  338. DECMONITORREF(m_pIniPort->pIniMonitor);
  339. if (SUCCEEDED(hr))
  340. {
  341. m_OpenedMonitorType = kPort;
  342. }
  343. }
  344. SetLastError(HRESULT_CODE(hr));
  345. return hr;
  346. }
  347. /*++
  348. Routine Name:
  349. OpenMonitorForFILEPort
  350. Routine Description:
  351. Opens the port monitor for FILE: port.
  352. Arguments:
  353. NONE
  354. Return Value:
  355. HRESULT
  356. Last Error:
  357. Not Set.
  358. --*/
  359. HRESULT
  360. TMonitorHandle::
  361. OpenMonitorForFILEPort(
  362. VOID
  363. )
  364. {
  365. HRESULT hr = E_INVALIDARG;
  366. if (m_pIniPort &&
  367. m_pIniPort->pIniMonitor &&
  368. m_pIniPort->pIniMonitor->Monitor2.pfnOpenPort)
  369. {
  370. INCMONITORREF(m_pIniPort->pIniMonitor);
  371. LeaveSpoolerSem();
  372. SetLastError(ERROR_SUCCESS);
  373. if ((m_pIniPort->pIniMonitor->Monitor2.pfnOpenPort)(m_pIniPort->pIniMonitor->hMonitor,
  374. m_szFILE,
  375. &m_hPort))
  376. {
  377. hr = m_hPort ?
  378. S_OK :
  379. HResultFromWin32(ERROR_INVALID_HANDLE);
  380. }
  381. else
  382. {
  383. if (SUCCEEDED(hr = HResultFromWin32(GetLastError())))
  384. {
  385. hr = HResultFromWin32(ERROR_INVALID_HANDLE);
  386. }
  387. }
  388. ReEnterSpoolerSem();
  389. DECMONITORREF(m_pIniPort->pIniMonitor);
  390. if (SUCCEEDED(hr))
  391. {
  392. m_OpenedMonitorType = kFile;
  393. }
  394. }
  395. SetLastError(HRESULT_CODE(hr));
  396. return hr;
  397. }
  398. /*++
  399. Routine Name:
  400. AddRef
  401. Routine Description:
  402. Increments object refcount.
  403. Arguments:
  404. NONE
  405. Return Value:
  406. HRESULT
  407. Last Error:
  408. Not Set.
  409. --*/
  410. ULONG
  411. TMonitorHandle ::
  412. AddRef(
  413. VOID
  414. )
  415. {
  416. return InterlockedIncrement(&m_RefCnt);
  417. }
  418. /*++
  419. Routine Name:
  420. Release
  421. Routine Description:
  422. Decrements object refcount.
  423. Notice that it doesn't delete the object as
  424. the destructor would exit the Spooler CS while the
  425. pIniPort still has a reference to the object.
  426. Arguments:
  427. NONE
  428. Return Value:
  429. HRESULT
  430. Last Error:
  431. Not Set.
  432. --*/
  433. ULONG
  434. TMonitorHandle ::
  435. Release(
  436. VOID
  437. )
  438. {
  439. ULONG RefCnt = InterlockedDecrement(&m_RefCnt);
  440. InterlockedCompareExchange(&m_RefCnt, 0, ULONG(-1));
  441. return RefCnt;
  442. }
  443. /*++
  444. Routine Name:
  445. InUse
  446. Routine Description:
  447. Checks whether the ref count is zero.
  448. If it is, then the object can be deleted.
  449. Arguments:
  450. NONE
  451. Return Value:
  452. ULONG - the ref count value.
  453. Last Error:
  454. Not Set.
  455. --*/
  456. ULONG
  457. TMonitorHandle ::
  458. InUse(
  459. VOID
  460. )
  461. {
  462. return InterlockedCompareExchange(&m_RefCnt, 0 , 0);
  463. }
  464. /*++
  465. Routine Name:
  466. IsValid
  467. Routine Description:
  468. Checks object validity.
  469. Arguments:
  470. NONE
  471. Return Value:
  472. HRESULT
  473. Last Error:
  474. Not Set.
  475. --*/
  476. HRESULT
  477. TMonitorHandle::
  478. IsValid(
  479. VOID
  480. )
  481. {
  482. return m_hValid;
  483. }
  484. /*++
  485. Routine Name:
  486. LeaveSpoolerSem
  487. Routine Description:
  488. Leaves Spooler CS
  489. Arguments:
  490. NONE
  491. Return Value:
  492. HRESULT
  493. Last Error:
  494. Not Set.
  495. --*/
  496. VOID
  497. TMonitorHandle::
  498. LeaveSpoolerSem(
  499. VOID
  500. )
  501. {
  502. INCPORTREF(m_pIniPort);
  503. INCSPOOLERREF(m_pIniPort->pIniSpooler);
  504. LeaveSplSem();
  505. SplOutSem();
  506. }
  507. /*++
  508. Routine Name:
  509. ReEnterSpoolerSem
  510. Routine Description:
  511. Enters Spooler CS
  512. Arguments:
  513. NONE
  514. Return Value:
  515. HRESULT
  516. Last Error:
  517. Not Set.
  518. --*/
  519. VOID
  520. TMonitorHandle::
  521. ReEnterSpoolerSem(
  522. VOID
  523. )
  524. {
  525. EnterSplSem();
  526. DECPORTREF(m_pIniPort);
  527. DECSPOOLERREF(m_pIniPort->pIniSpooler);
  528. SplInSem();
  529. }
  530. /*++
  531. Routine Name:
  532. operator PINIMONITOR
  533. Routine Description:
  534. Returns a pointer to the opened monitor.
  535. Arguments:
  536. NONE
  537. Return Value:
  538. HRESULT
  539. Last Error:
  540. Not Set.
  541. --*/
  542. TMonitorHandle::
  543. operator PINIMONITOR(
  544. VOID
  545. )
  546. {
  547. PINIMONITOR pIniMonitor = NULL;
  548. switch (m_OpenedMonitorType)
  549. {
  550. case kLanguage:
  551. {
  552. pIniMonitor = m_pIniLangMonitor;
  553. break;
  554. }
  555. case kPort:
  556. case kFile:
  557. {
  558. pIniMonitor = m_pIniPort->pIniMonitor;
  559. break;
  560. }
  561. default:
  562. {
  563. break;
  564. }
  565. }
  566. return pIniMonitor;
  567. }
  568. /*++
  569. Routine Name:
  570. operator HANDLE
  571. Routine Description:
  572. Returns a monitor handle.
  573. Arguments:
  574. NONE
  575. Return Value:
  576. HRESULT
  577. Last Error:
  578. Not Set.
  579. --*/
  580. TMonitorHandle::
  581. operator HANDLE(
  582. VOID
  583. )
  584. {
  585. return m_hPort;
  586. }