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.

400 lines
9.8 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. All Rights Reserved
  4. Module Name:
  5. DynaMon.cpp
  6. Abstract:
  7. Multiple Transport core port monitor routines
  8. Author: M. Fenelon
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "ntddpar.h"
  13. // Global Values for Monitor
  14. TCHAR cszUSB[] = TEXT("USB");
  15. TCHAR cszDOT4[] = TEXT("DOT4");
  16. TCHAR cszTS[] = TEXT("TS");
  17. TCHAR csz1394[] = TEXT("1394");
  18. TCHAR cszBaseName[] = TEXT("Base Name");
  19. TCHAR cszPortNumber[] = TEXT("Port Number");
  20. TCHAR cszRecyclable[] = TEXT("recyclable");
  21. TCHAR cszPortDescription[] = TEXT("Port Description");
  22. TCHAR cszMaxBufferSize[] = TEXT("MaxBufferSize");
  23. TCHAR cszUSBPortDesc[] = TEXT("Virtual printer port for USB");
  24. TCHAR cszDot4PortDesc[] = TEXT("Virtual printer port for Dot4");
  25. TCHAR csz1394PortDesc[] = TEXT("Virtual printer port for 1394");
  26. TCHAR cszTSPortDesc[] = TEXT("Virtual printer port for TS");
  27. DYNAMON_MONITOR_INFO gDynaMonInfo;
  28. MODULE_DEBUG_INIT( DBG_ERROR, DBG_ERROR );
  29. BOOL
  30. APIENTRY
  31. DllMain(
  32. HANDLE hModule,
  33. DWORD dwReason,
  34. LPVOID lpRes
  35. )
  36. {
  37. if ( dwReason == DLL_PROCESS_ATTACH )
  38. DisableThreadLibraryCalls(hModule);
  39. return TRUE;
  40. }
  41. // Construct MonitorEx structure to provide to Spooler
  42. MONITOREX MonitorEx = {
  43. sizeof(MONITOR),
  44. {
  45. DynaMon_EnumPorts,
  46. DynaMon_OpenPort,
  47. NULL, // OpenPortEx not supported
  48. DynaMon_StartDocPort,
  49. DynaMon_WritePort,
  50. DynaMon_ReadPort,
  51. DynaMon_EndDocPort,
  52. DynaMon_ClosePort,
  53. NULL, // AddPort not supported
  54. NULL, // AddPortEx not supported
  55. NULL, // ConfigurePort not supported
  56. NULL, // DeletePort not supported
  57. DynaMon_GetPrinterDataFromPort,
  58. DynaMon_SetPortTimeOuts,
  59. NULL, // XcvOpenPort not supported
  60. NULL, // XcvDataPort not supported
  61. NULL // XcvClosePort not supported
  62. }
  63. };
  64. LPMONITOREX
  65. WINAPI
  66. InitializePrintMonitor(
  67. LPTSTR pszRegistryRoot
  68. )
  69. {
  70. BOOL bEnumPortsCS = FALSE;
  71. BOOL bUpdateListCS = FALSE;
  72. LPMONITOREX pMonitorEx = NULL;
  73. DWORD dwStatus = ERROR_SUCCESS;
  74. // Clear the Global info
  75. ZeroMemory( &gDynaMonInfo, sizeof(gDynaMonInfo) );
  76. if (dwStatus == ERROR_SUCCESS)
  77. {
  78. __try
  79. {
  80. InitializeCriticalSection (&gDynaMonInfo.EnumPortsCS);
  81. bEnumPortsCS = TRUE;
  82. }
  83. __except (EXCEPTION_EXECUTE_HANDLER)
  84. {
  85. dwStatus = GetExceptionCode ();
  86. }
  87. }
  88. if (dwStatus == ERROR_SUCCESS)
  89. {
  90. __try
  91. {
  92. InitializeCriticalSection (&gDynaMonInfo.UpdateListCS);
  93. bUpdateListCS = TRUE;
  94. }
  95. __except (EXCEPTION_EXECUTE_HANDLER)
  96. {
  97. dwStatus = GetExceptionCode ();
  98. }
  99. }
  100. if (dwStatus == ERROR_SUCCESS)
  101. {
  102. gDynaMonInfo.hUpdateEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  103. if (gDynaMonInfo.hUpdateEvent == NULL)
  104. {
  105. dwStatus = GetLastError ();
  106. }
  107. }
  108. if (dwStatus == ERROR_SUCCESS)
  109. {
  110. //
  111. // Get the Background Thread going
  112. //
  113. dwStatus = SpinUpdateThread ();
  114. }
  115. //
  116. //
  117. if (dwStatus == ERROR_SUCCESS)
  118. {
  119. pMonitorEx = &MonitorEx;
  120. }
  121. else
  122. {
  123. if (bEnumPortsCS)
  124. {
  125. DeleteCriticalSection (&gDynaMonInfo.EnumPortsCS);
  126. }
  127. if (bUpdateListCS)
  128. {
  129. DeleteCriticalSection (&gDynaMonInfo.UpdateListCS);
  130. }
  131. if (gDynaMonInfo.hUpdateEvent)
  132. {
  133. CloseHandle (&gDynaMonInfo.hUpdateEvent);
  134. }
  135. ZeroMemory( &gDynaMonInfo, sizeof(gDynaMonInfo) );
  136. SetLastError (dwStatus);
  137. }
  138. return pMonitorEx;
  139. }
  140. BOOL
  141. WINAPI
  142. DynaMon_EnumPorts(
  143. LPTSTR pszName,
  144. DWORD dwLevel,
  145. LPBYTE pPorts,
  146. DWORD cbBuf,
  147. LPDWORD pcbNeeded,
  148. LPDWORD pcReturned
  149. )
  150. {
  151. DWORD dwLastError = ERROR_SUCCESS, dwRequestIndex;
  152. LPBYTE pEnd;
  153. PDYNAMON_PORT pPortList;
  154. PPORT_UPDATE pPortUpdateList = NULL;
  155. *pcbNeeded = *pcReturned = 0;
  156. if ( dwLevel != 1 && dwLevel != 2 )
  157. {
  158. SetLastError(ERROR_INVALID_LEVEL);
  159. return FALSE;
  160. }
  161. dwRequestIndex = gDynaMonInfo.dwLastEnumIndex;
  162. ECS( gDynaMonInfo.EnumPortsCS );
  163. if ( dwRequestIndex >= gDynaMonInfo.dwLastEnumIndex )
  164. {
  165. //
  166. // No complete enumeration has occurred since this request was made.
  167. // Since the request may be an indication that something has changed,
  168. // the full reenumeration must be done.
  169. //
  170. // Updated the index of enumeration before actually doing the
  171. // work so it will show up as the most conservative
  172. //
  173. // Consequence of rollover on gdwLastEnumIndex:
  174. // Any threads that recorded 0xFFFFFFFF as the dwRequestIndex
  175. // will show as greater than the new value 0 and therefore reenum
  176. // gratuitously. Not very much extra work.
  177. //
  178. ++gDynaMonInfo.dwLastEnumIndex;
  179. if ( dwLastError = BuildPortList( &gDynaMonInfo, &pPortUpdateList) )
  180. goto Done;
  181. }
  182. for ( pPortList = gDynaMonInfo.pPortList ;
  183. pPortList ;
  184. pPortList = pPortList->pNext )
  185. {
  186. *pcbNeeded += pPortList->pBasePort->getEnumInfoSize( dwLevel );
  187. }
  188. if ( cbBuf < *pcbNeeded )
  189. {
  190. dwLastError = ERROR_INSUFFICIENT_BUFFER;
  191. goto Done;
  192. }
  193. pEnd = pPorts + cbBuf;
  194. for ( pPortList = gDynaMonInfo.pPortList ;
  195. pPortList ;
  196. pPortList = pPortList->pNext )
  197. {
  198. pEnd = pPortList->pBasePort->copyEnumInfo( dwLevel, pPorts, pEnd );
  199. if ( dwLevel == 1 )
  200. pPorts += sizeof(PORT_INFO_1);
  201. else
  202. pPorts += sizeof(PORT_INFO_2);
  203. ++(*pcReturned);
  204. }
  205. SPLASSERT(pEnd >= pPorts);
  206. Done:
  207. // If we have anything to update do it now
  208. if ( pPortUpdateList )
  209. PassPortUpdateListToUpdateThread( pPortUpdateList );
  210. LCS( gDynaMonInfo.EnumPortsCS );
  211. if ( dwLastError )
  212. {
  213. SetLastError(dwLastError);
  214. return FALSE;
  215. }
  216. else
  217. return TRUE;
  218. }
  219. BOOL
  220. WINAPI
  221. DynaMon_OpenPort(
  222. LPTSTR pszPortName,
  223. LPHANDLE pHandle
  224. )
  225. {
  226. PDYNAMON_PORT pPort, pPrev;
  227. pPort = FindPort( &gDynaMonInfo, pszPortName, &pPrev);
  228. if ( pPort )
  229. {
  230. *pHandle = (LPHANDLE)pPort;
  231. pPort->pBasePort->InitCS();
  232. return TRUE;
  233. }
  234. else
  235. {
  236. SetLastError(ERROR_PATH_NOT_FOUND);
  237. return FALSE;
  238. }
  239. }
  240. BOOL
  241. WINAPI
  242. DynaMon_ClosePort(
  243. HANDLE hPort
  244. )
  245. {
  246. PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
  247. IF_INVALID_PORT_FAIL( pPort )
  248. pPort->pBasePort->ClearCS();
  249. return TRUE;
  250. }
  251. BOOL
  252. WINAPI
  253. DynaMon_StartDocPort(
  254. HANDLE hPort,
  255. LPTSTR pPrinterName,
  256. DWORD dwJobId,
  257. DWORD dwLevel,
  258. LPBYTE pDocInfo
  259. )
  260. {
  261. PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
  262. IF_INVALID_PORT_FAIL( pPort )
  263. return pPort->pBasePort->startDoc( pPrinterName, dwJobId, dwLevel, pDocInfo );
  264. }
  265. BOOL
  266. WINAPI
  267. DynaMon_EndDocPort(
  268. HANDLE hPort
  269. )
  270. {
  271. PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
  272. IF_INVALID_PORT_FAIL( pPort )
  273. return pPort->pBasePort->endDoc();
  274. }
  275. BOOL
  276. WINAPI
  277. DynaMon_GetPrinterDataFromPort(
  278. HANDLE hPort,
  279. DWORD dwControlID,
  280. LPWSTR pValueName,
  281. LPWSTR lpInBuffer,
  282. DWORD cbInBuffer,
  283. LPWSTR lpOutBuffer,
  284. DWORD cbOutBuffer,
  285. LPDWORD lpcbReturned
  286. )
  287. {
  288. PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
  289. IF_INVALID_PORT_FAIL( pPort )
  290. return pPort->pBasePort->getPrinterDataFromPort( dwControlID, pValueName, lpInBuffer, cbInBuffer,
  291. lpOutBuffer, cbOutBuffer, lpcbReturned );
  292. }
  293. BOOL
  294. WINAPI
  295. DynaMon_ReadPort(
  296. HANDLE hPort,
  297. LPBYTE pBuffer,
  298. DWORD cbBuffer,
  299. LPDWORD pcbRead
  300. )
  301. {
  302. PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
  303. IF_INVALID_PORT_FAIL( pPort )
  304. return pPort->pBasePort->read( pBuffer, cbBuffer, pcbRead );
  305. }
  306. BOOL
  307. WINAPI
  308. DynaMon_WritePort(
  309. HANDLE hPort,
  310. LPBYTE pBuffer,
  311. DWORD cbBuffer,
  312. LPDWORD pcbWritten
  313. )
  314. {
  315. PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
  316. IF_INVALID_PORT_FAIL( pPort )
  317. return pPort->pBasePort->write( pBuffer, cbBuffer, pcbWritten );
  318. }
  319. BOOL
  320. WINAPI
  321. DynaMon_SetPortTimeOuts(
  322. HANDLE hPort,
  323. LPCOMMTIMEOUTS lpCTO,
  324. DWORD reserved
  325. )
  326. {
  327. PDYNAMON_PORT pPort = (PDYNAMON_PORT) hPort;
  328. IF_INVALID_PORT_FAIL( pPort )
  329. return pPort->pBasePort->setPortTimeOuts( lpCTO );
  330. }