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.

544 lines
11 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. openmon.cxx
  5. Abstract:
  6. Methods to interact with the language/port monitor.
  7. The methods in this file are a replacement for the old OpenMonitorPort/CloseMonitorPort
  8. that used to close an opened handle on OpenMonitorPort while another thread was using it.
  9. OpenMonitorPort - Opens a handle to the language or port monitor.
  10. If the port has already an opened handle to the requested
  11. monitor, then bump the handle's refcount and use it.If the
  12. port has already an opened handle to another monitor then the
  13. one requested, then fail the call with ERROR_BUSY.
  14. CloseMonitorPort - Decrements the monitor handle's refcount and deletes the object
  15. if no longer in use.
  16. GetMonitorHandle - Returns the monitor handle curently opened
  17. on the port.
  18. GetOpenedMonitor - Returns a pointer to the INIMONITOR curently opened.
  19. on the port.
  20. ReleaseMonitorPort - Releases the port handle so that it can be closed.
  21. Author:
  22. Adina Trufinescu July 16th, 2002
  23. Revision History:
  24. --*/
  25. #include "precomp.h"
  26. #pragma hdrstop
  27. #include "monhndl.hxx"
  28. HRESULT
  29. InternalCloseMonitorPort(
  30. IN PINIPORT pIniPort
  31. );
  32. void
  33. AquirePortCriticalSection(
  34. PINIPORT pIniPort
  35. );
  36. void
  37. ReleasePortCriticalSection(
  38. PINIPORT pIniPort
  39. );
  40. /*++
  41. Routine Name:
  42. OpenMonitorPort
  43. Routine Description:
  44. Opens a handle to either the language monitor or
  45. the port monitor. If a handle is already opened, then
  46. use it.
  47. Arguments:
  48. pIniPort - pointer to INIPORT structure
  49. pIniLangMonitor - pointer to INIMONITOR structure
  50. represented the preffered language monitor.
  51. pszPrinterName - string representing the printer name
  52. Return Value:
  53. HANDLE
  54. Last Error:
  55. Not Set.
  56. --*/
  57. HRESULT
  58. OpenMonitorPort(
  59. PINIPORT pIniPort,
  60. PINIMONITOR pIniLangMonitor,
  61. LPWSTR pszPrinterName
  62. )
  63. {
  64. HRESULT hRes = S_OK;
  65. SplInSem();
  66. SPLASSERT (pIniPort != NULL && pIniPort->signature == IPO_SIGNATURE);
  67. if(pIniPort &&
  68. pIniPort->signature == IPO_SIGNATURE)
  69. {
  70. //
  71. // If no monitor associated, do not have to open
  72. //
  73. if (!(pIniPort->Status & PP_MONITOR))
  74. {
  75. hRes = S_OK;
  76. }
  77. else
  78. {
  79. TMonitorHandle* pMonitorHandle = NULL;
  80. //
  81. // If a LM is passed and it does not have an OpenPortEx can't use it
  82. //
  83. if (pIniLangMonitor &&
  84. !(pIniLangMonitor)->Monitor2.pfnOpenPortEx)
  85. {
  86. pIniLangMonitor = NULL;
  87. }
  88. AquirePortCriticalSection(pIniPort);
  89. //
  90. // If the port already has a handle opened to the wanted language monitor
  91. // or if we don't care about the language monitor, then just use it.
  92. //
  93. pMonitorHandle = reinterpret_cast<TMonitorHandle*>(pIniPort->hMonitorHandle);
  94. if (pMonitorHandle)
  95. {
  96. if (static_cast<PINIMONITOR>(*pMonitorHandle) ==
  97. (pIniLangMonitor ? pIniLangMonitor : pIniPort->pIniMonitor))
  98. {
  99. pMonitorHandle->AddRef();
  100. hRes = S_OK;
  101. }
  102. else
  103. {
  104. if (SUCCEEDED(hRes = InternalCloseMonitorPort(pIniPort)))
  105. {
  106. pMonitorHandle = NULL;
  107. }
  108. }
  109. }
  110. if (SUCCEEDED(hRes) && !pMonitorHandle)
  111. {
  112. //
  113. // Open a monitor handle. On constructor we exit Spooler CS.
  114. //
  115. pMonitorHandle = new TMonitorHandle(pIniPort,
  116. pIniLangMonitor,
  117. pszPrinterName);
  118. //
  119. // We could get an invalid handle because another thread could try open
  120. // monitor and succeed.OpenPort fails when called multiple times.
  121. //
  122. if (SUCCEEDED(hRes = pMonitorHandle ? S_OK : E_OUTOFMEMORY))
  123. {
  124. //
  125. // Delete the object.
  126. //
  127. if (FAILED(hRes = pMonitorHandle->IsValid()))
  128. {
  129. delete pMonitorHandle;
  130. pMonitorHandle = NULL;
  131. }
  132. if (pMonitorHandle)
  133. {
  134. pIniPort->hMonitorHandle = reinterpret_cast<HANDLE>(pMonitorHandle);
  135. pMonitorHandle->AddRef();
  136. hRes = S_OK;
  137. }
  138. }
  139. }
  140. ReleasePortCriticalSection(pIniPort);
  141. }
  142. }
  143. else
  144. {
  145. hRes = E_INVALIDARG;
  146. }
  147. return hRes;
  148. }
  149. /*++
  150. Routine Name:
  151. InternalCloseMonitorPort
  152. Routine Description:
  153. Closes the monitor handle if the refcount reaches 0.
  154. It assumes the port MonitorCS is aquired.
  155. Arguments:
  156. pIniPort - pointer to INIPORT structure
  157. Return Value:
  158. HANDLE
  159. Last Error:
  160. Not Set.
  161. --*/
  162. HRESULT
  163. InternalCloseMonitorPort(
  164. IN PINIPORT pIniPort
  165. )
  166. {
  167. HRESULT hRes = S_OK;
  168. TMonitorHandle* pMonitorHandle = NULL;
  169. SplInSem();
  170. if (pIniPort->hMonitorHandle)
  171. {
  172. pMonitorHandle = reinterpret_cast<TMonitorHandle*>(pIniPort->hMonitorHandle);
  173. //
  174. // If the handle refcount reached 0, then we close the handle. On the destructor,
  175. // we exit the Spooler CS.
  176. //
  177. if (pMonitorHandle->InUse() == 0)
  178. {
  179. pIniPort->hMonitorHandle = NULL;
  180. //
  181. // The destructor exits the Spooler CS.
  182. //
  183. delete pMonitorHandle;
  184. }
  185. else
  186. {
  187. hRes = HResultFromWin32(ERROR_BUSY);
  188. }
  189. }
  190. else
  191. {
  192. hRes = E_INVALIDARG;
  193. }
  194. return hRes;
  195. }
  196. /*++
  197. Routine Name:
  198. CloseMonitorPort
  199. Routine Description:
  200. Decrement the handle object refcount and
  201. closes the monitor handle if the refcount reaches 0.
  202. Arguments:
  203. pIniPort - pointer to INIPORT structure
  204. Return Value:
  205. HANDLE
  206. Last Error:
  207. Not Set.
  208. --*/
  209. HRESULT
  210. CloseMonitorPort(
  211. IN PINIPORT pIniPort
  212. )
  213. {
  214. HRESULT hr = E_INVALIDARG;
  215. SplInSem();
  216. hr = (pIniPort &&
  217. pIniPort->signature == IPO_SIGNATURE &&
  218. pIniPort->hMonitorHandle) ?
  219. S_OK :
  220. E_INVALIDARG;
  221. if (SUCCEEDED(hr))
  222. {
  223. AquirePortCriticalSection(pIniPort);
  224. hr = InternalCloseMonitorPort(pIniPort);
  225. ReleasePortCriticalSection(pIniPort);
  226. }
  227. return hr;
  228. }
  229. /*++
  230. Routine Name:
  231. GetMonitorHandle
  232. Routine Description:
  233. Returns the monitor handle curently opened
  234. on the port.
  235. Arguments:
  236. pIniPort - pointer to INIPORT structure
  237. Return Value:
  238. HANDLE
  239. Last Error:
  240. Not Set.
  241. --*/
  242. HANDLE
  243. GetMonitorHandle(
  244. IN PINIPORT pIniPort
  245. )
  246. {
  247. HANDLE hMonitor = NULL;
  248. if (pIniPort &&
  249. pIniPort->signature == IPO_SIGNATURE &&
  250. pIniPort->hMonitorHandle)
  251. {
  252. TMonitorHandle* pMonitorHandle = NULL;
  253. pMonitorHandle = reinterpret_cast<TMonitorHandle*>(pIniPort->hMonitorHandle);
  254. hMonitor = static_cast<HANDLE>(*pMonitorHandle);
  255. }
  256. return hMonitor;
  257. }
  258. /*++
  259. Routine Name:
  260. GetOpenedMonitor
  261. Routine Description:
  262. Returns a pointer to the INIMONITOR curently opened.
  263. on the port.
  264. Arguments:
  265. pIniPort - pointer to INIPORT structure
  266. Return Value:
  267. HANDLE
  268. Last Error:
  269. Not Set.
  270. --*/
  271. PINIMONITOR
  272. GetOpenedMonitor(
  273. IN PINIPORT pIniPort
  274. )
  275. {
  276. PINIMONITOR pIniMonitor = NULL;
  277. if (pIniPort && pIniPort->hMonitorHandle)
  278. {
  279. TMonitorHandle* pMonitorHandle = NULL;
  280. pMonitorHandle = reinterpret_cast<TMonitorHandle*>(pIniPort->hMonitorHandle);
  281. pIniMonitor = static_cast<PINIMONITOR>(*pMonitorHandle);
  282. }
  283. return pIniMonitor;
  284. }
  285. /*++
  286. Routine Name:
  287. ReleaseMonitorPort
  288. Routine Description:
  289. This will decrement the port handle ref count. When the ref count is 0,
  290. the port handle is "not in use" and another thread can close it.
  291. Arguments:
  292. pIniPort - pointer to INIPORT structure
  293. Return Value:
  294. HRESULT
  295. Last Error:
  296. Not Set.
  297. --*/
  298. HRESULT
  299. ReleaseMonitorPort(
  300. PINIPORT pIniPort
  301. )
  302. {
  303. HRESULT hr = E_INVALIDARG;
  304. SplInSem();
  305. hr = (pIniPort &&
  306. pIniPort->signature == IPO_SIGNATURE &&
  307. pIniPort->hMonitorHandle) ?
  308. S_OK :
  309. E_INVALIDARG;
  310. if (SUCCEEDED(hr))
  311. {
  312. TMonitorHandle* pMonitorHandle;
  313. AquirePortCriticalSection(pIniPort);
  314. pMonitorHandle = reinterpret_cast<TMonitorHandle*>(pIniPort->hMonitorHandle);
  315. if (pMonitorHandle)
  316. {
  317. pMonitorHandle->Release();
  318. }
  319. else
  320. {
  321. hr = E_POINTER;
  322. }
  323. ReleasePortCriticalSection(pIniPort);
  324. }
  325. return hr;
  326. }
  327. /*++
  328. Routine Name:
  329. AquirePortCriticalSection
  330. Routine Description:
  331. This method aquires the IniPort section. Because Spooler cannot
  332. open the monitor multiple times, it needs to do the open/close calls
  333. inside a critical section. Because the Spooler section cannot be used,
  334. the port was added a new CS. The method must be called inside Spooler section.
  335. The method aquires the port CS outside the Spooler section and then reenters.
  336. Arguments:
  337. pIniPort - pointer to INIPORT structure
  338. Return Value:
  339. void
  340. Last Error:
  341. Not Set.
  342. --*/
  343. void
  344. AquirePortCriticalSection(
  345. IN PINIPORT pIniPort
  346. )
  347. {
  348. if (pIniPort)
  349. {
  350. INCPORTREF(pIniPort);
  351. INCSPOOLERREF(pIniPort->pIniSpooler);
  352. INCMONITORREF(pIniPort->pIniMonitor);
  353. LeaveSplSem();
  354. SplOutSem();
  355. EnterCriticalSection(&pIniPort->MonitorCS);
  356. EnterSplSem();
  357. SplInSem();
  358. DECPORTREF(pIniPort);
  359. DECSPOOLERREF(pIniPort->pIniSpooler);
  360. DECMONITORREF(pIniPort->pIniMonitor);
  361. }
  362. }
  363. /*++
  364. Routine Name:
  365. ReleasePortCriticalSection
  366. Routine Description:
  367. This method releases the IniPort section.
  368. Arguments:
  369. pIniPort - pointer to INIPORT structure
  370. Return Value:
  371. void
  372. Last Error:
  373. Not Set.
  374. --*/
  375. void
  376. ReleasePortCriticalSection(
  377. PINIPORT pIniPort
  378. )
  379. {
  380. if (pIniPort)
  381. {
  382. LeaveCriticalSection(&pIniPort->MonitorCS);
  383. }
  384. }