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.

675 lines
14 KiB

  1. /*++
  2. Copyright (c) 1990-2000 Microsoft Corporation
  3. Module Name:
  4. Lpt
  5. Abstract:
  6. Takes care of request involving an LPT device
  7. Author:
  8. Ramon Juan San Andres (ramonsa) 26-Jun-1991
  9. Revision History:
  10. --*/
  11. #define _NTAPI_ULIB_
  12. #include "mode.hxx"
  13. #include "lpt.hxx"
  14. #include "file.hxx"
  15. #include "path.hxx"
  16. #include "stream.hxx"
  17. #include "redir.hxx"
  18. #include "registry.hxx"
  19. #include "regvalue.hxx"
  20. #include "array.hxx"
  21. #include "arrayit.hxx"
  22. //
  23. // When an LPT port is set, mode only sends it an EPSON/IBM sequence.
  24. // The following macros define the EPSON sequences used.
  25. //
  26. #define CODE_ESCAPE 0x27
  27. #define CODE_COLS_80 0x18
  28. #define CODE_COLS_132 0x15
  29. #define CODE_LINES_6 '2'
  30. #define CODE_LINES_8 '0'
  31. #undef LAST_COM
  32. #define LAST_COM 4
  33. //
  34. // Local prototypes
  35. //
  36. BOOLEAN
  37. LptStatus(
  38. IN PCPATH DevicePath,
  39. IN PREQUEST_HEADER Request
  40. );
  41. BOOLEAN
  42. LptCodePage(
  43. IN PCPATH DevicePath,
  44. IN PREQUEST_HEADER Request
  45. );
  46. BOOLEAN
  47. LptSetup(
  48. IN PCPATH DevicePath,
  49. IN PREQUEST_HEADER Request
  50. );
  51. BOOLEAN
  52. LptRedirect(
  53. IN PCPATH DevicePath,
  54. IN PREQUEST_HEADER Request
  55. );
  56. BOOLEAN
  57. LptEndRedir(
  58. IN PCPATH DevicePath,
  59. IN PREQUEST_HEADER Request
  60. );
  61. PPATH
  62. GetRedirection(
  63. IN PCPATH DevicePath,
  64. OUT PREDIR_STATUS RedirStatus
  65. );
  66. BOOLEAN
  67. IsAValidLptDevice (
  68. IN DEVICE_TTYPE DeviceType,
  69. IN ULONG DeviceNumber,
  70. OUT PPATH *DevicePathPointer
  71. )
  72. /*++
  73. Routine Description:
  74. Determines if a certain comm device exists and optionally
  75. creates a path for it.
  76. Arguments:
  77. DeviceType - Supplies the type of device
  78. DeviceNumber - Supplies the device number
  79. DeviceName - Supplies a pointer to a pointer to the path for
  80. the device.
  81. Return Value:
  82. BOOLEAN - TRUE if the device exists,
  83. FALSE otherwise.
  84. Notes:
  85. --*/
  86. {
  87. DSTRING DeviceName;
  88. DSTRING AlternateName;
  89. DSTRING Number;
  90. BOOLEAN Valid = FALSE;
  91. REGISTRY Registry;
  92. DSTRING ParentName;
  93. DSTRING KeyName;
  94. ARRAY ValueArray;
  95. PARRAY_ITERATOR Iterator;
  96. ULONG ErrorCode;
  97. PCBYTE Data;
  98. DSTRING PortName;
  99. PREGISTRY_VALUE_ENTRY Value;
  100. UNREFERENCED_PARAMETER( DeviceType );
  101. if ( DeviceName.Initialize( (LPWSTR)L"LPT" )&&
  102. Number.Initialize( DeviceNumber ) &&
  103. DeviceName.Strcat( &Number ) &&
  104. AlternateName.Initialize( (LPWSTR)L"\\DosDevices\\" ) &&
  105. AlternateName.Strcat( &DeviceName ) &&
  106. ParentName.Initialize( "" ) &&
  107. KeyName.Initialize( LPT_KEY_NAME ) &&
  108. ValueArray.Initialize() &&
  109. Registry.Initialize()
  110. ) {
  111. //
  112. // Get the names of all the serial ports
  113. //
  114. if ( Registry.QueryValues(
  115. PREDEFINED_KEY_LOCAL_MACHINE,
  116. &ParentName,
  117. &KeyName,
  118. &ValueArray,
  119. &ErrorCode
  120. ) ) {
  121. //
  122. // See if the given name matches any of the serial ports
  123. //
  124. if ( Iterator = (PARRAY_ITERATOR)ValueArray.QueryIterator() ) {
  125. while ( Value = (PREGISTRY_VALUE_ENTRY)(Iterator->GetNext() ) ) {
  126. if ( Value->GetData( &Data ) ) {
  127. if ( PortName.Initialize( (PWSTR)Data ) ) {
  128. if ( !DeviceName.Stricmp( &PortName ) ||
  129. !AlternateName.Stricmp( &PortName ) ) {
  130. Valid = TRUE;
  131. break;
  132. }
  133. }
  134. }
  135. }
  136. DELETE( Iterator );
  137. }
  138. }
  139. if ( DevicePathPointer ) {
  140. if (!(*DevicePathPointer = NEW PATH)) {
  141. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  142. NULL,
  143. (ULONG)EXIT_ERROR );
  144. return FALSE; // help lint
  145. }
  146. (*DevicePathPointer)->Initialize( &DeviceName );
  147. }
  148. }
  149. return Valid;
  150. }
  151. BOOLEAN
  152. LptHandler(
  153. IN PREQUEST_HEADER Request
  154. )
  155. /*++
  156. Routine Description:
  157. Handles LPT requests
  158. Arguments:
  159. Request - Supplies pointer to request
  160. Return Value:
  161. None.
  162. Notes:
  163. --*/
  164. {
  165. PPATH DevicePath; // Name of Device
  166. BOOLEAN Served = TRUE; // TRUE if request served OK.
  167. REDIR_STATUS Status;
  168. DebugPtrAssert( Request );
  169. DebugAssert( Request->DeviceType == DEVICE_TYPE_LPT );
  170. //
  171. // Make sure that the device exists, and at the same time get its
  172. // name ( For calling APIs ).
  173. //
  174. if ( Request->DeviceName ) {
  175. if (!(DevicePath = NEW PATH)) {
  176. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  177. NULL,
  178. (ULONG)EXIT_ERROR );
  179. return FALSE; // help lint
  180. }
  181. DevicePath->Initialize( Request->DeviceName );
  182. } else if ( (!IsAValidLptDevice( Request->DeviceType, Request->DeviceNumber, &DevicePath ) &&
  183. Request->RequestType != REQUEST_TYPE_LPT_REDIRECT &&
  184. !REDIR::IsRedirected( &Status, DevicePath )) ||
  185. Request->DeviceNumber > LAST_LPT ) {
  186. DisplayMessageAndExit( MODE_ERROR_INVALID_DEVICE_NAME,
  187. DevicePath->GetPathString(),
  188. (ULONG)EXIT_ERROR );
  189. }
  190. //
  191. // So the device is valid. Now serve the request
  192. //
  193. switch( Request->RequestType ) {
  194. case REQUEST_TYPE_STATUS:
  195. //
  196. // Display State of device
  197. //
  198. Served = LptStatus( DevicePath, Request );
  199. break;
  200. case REQUEST_TYPE_CODEPAGE_PREPARE:
  201. case REQUEST_TYPE_CODEPAGE_SELECT:
  202. case REQUEST_TYPE_CODEPAGE_REFRESH:
  203. case REQUEST_TYPE_CODEPAGE_STATUS:
  204. //
  205. // Codepage request
  206. //
  207. Served = LptCodePage( DevicePath, Request );
  208. break;
  209. case REQUEST_TYPE_LPT_SETUP:
  210. //
  211. // Printer setup
  212. //
  213. Served = LptSetup( DevicePath, Request );
  214. break;
  215. case REQUEST_TYPE_LPT_REDIRECT:
  216. //
  217. // Redirect LPT to COM
  218. //
  219. Served = LptRedirect( DevicePath, Request );
  220. break;
  221. case REQUEST_TYPE_LPT_ENDREDIR:
  222. //
  223. // End redirection of LPT
  224. //
  225. Served = LptEndRedir( DevicePath, Request );
  226. break;
  227. default:
  228. DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER,
  229. NULL,
  230. (ULONG)EXIT_ERROR );
  231. }
  232. DELETE( DevicePath );
  233. return Served;
  234. }
  235. BOOLEAN
  236. LptStatus(
  237. IN PCPATH DevicePath,
  238. IN PREQUEST_HEADER Request
  239. )
  240. /*++
  241. Routine Description:
  242. Displays status if an LPT device
  243. Arguments:
  244. DevicePath - Supplies pointer to path of device
  245. Request - Supplies pointer to request
  246. Return Value:
  247. BOOLEAN - TRUE if status displayed successfully,
  248. FALSE otherwise
  249. Notes:
  250. --*/
  251. {
  252. UNREFERENCED_PARAMETER( DevicePath );
  253. UNREFERENCED_PARAMETER( Request );
  254. PPATH RedirPath = NULL;
  255. REDIR_STATUS RedirStatus;
  256. RedirPath = GetRedirection( DevicePath, &RedirStatus );
  257. if ( !RedirPath && (RedirStatus != REDIR_STATUS_NONEXISTENT) ) {
  258. //
  259. // We cannot find out the status of the redirection.
  260. // This is almost certainly due to lack of privileges.
  261. // We won't display the LPT status
  262. //
  263. return TRUE;
  264. }
  265. //
  266. // Write the Header
  267. //
  268. WriteStatusHeader( DevicePath );
  269. if ( !RedirPath ) {
  270. DisplayMessage( MODE_MESSAGE_STATUS_NOT_REROUTED, NULL );
  271. } else {
  272. DisplayMessage( MODE_MESSAGE_STATUS_REROUTED, RedirPath->GetPathString() );
  273. DELETE( RedirPath );
  274. }
  275. Get_Standard_Output_Stream()->WriteChar( '\r' );
  276. Get_Standard_Output_Stream()->WriteChar( '\n' );
  277. return TRUE;
  278. }
  279. BOOLEAN
  280. LptCodePage(
  281. IN PCPATH DevicePath,
  282. IN PREQUEST_HEADER Request
  283. )
  284. /*++
  285. Routine Description:
  286. Handles Codepage requests for LPT device
  287. Arguments:
  288. DevicePath - Supplies pointer to path of device
  289. Request - Supplies pointer to request
  290. Return Value:
  291. BOOLEAN - TRUE if request handled successfully,
  292. FALSE otherwise
  293. Notes:
  294. --*/
  295. {
  296. UNREFERENCED_PARAMETER( DevicePath );
  297. UNREFERENCED_PARAMETER( Request );
  298. DisplayMessage( MODE_ERROR_CODEPAGE_OPERATION_NOT_SUPPORTED, NULL );
  299. return TRUE;
  300. }
  301. BOOLEAN
  302. LptSetup(
  303. IN PCPATH DevicePath,
  304. IN PREQUEST_HEADER Request
  305. )
  306. /*++
  307. Routine Description:
  308. Sets LPT state
  309. Arguments:
  310. DevicePath - Supplies pointer to path of device
  311. Request - Supplies pointer to request
  312. Return Value:
  313. BOOLEAN - TRUE if state set successfully,
  314. FALSE otherwise
  315. Notes:
  316. --*/
  317. {
  318. PREQUEST_DATA_LPT_SETUP Data;
  319. PFSN_FILE Lpt;
  320. PFILE_STREAM LptStream;
  321. Data = (PREQUEST_DATA_LPT_SETUP)&(((PLPT_REQUEST)Request)->Data.Setup);
  322. if ( ( Data->SetCol && (Data->Col != 132) && ( Data->Col != 80 ) ) ||
  323. ( Data->SetLines && (Data->Lines != 6) && (Data->Lines != 8) ) ) {
  324. //
  325. // Invalid number of lines or columns
  326. //
  327. DisplayMessageAndExit( MODE_ERROR_LPT_CANNOT_SET, NULL, (ULONG)EXIT_ERROR );
  328. }
  329. Lpt = SYSTEM::QueryFile( DevicePath );
  330. DebugPtrAssert( Lpt );
  331. if ( Lpt ) {
  332. LptStream = Lpt->QueryStream( WRITE_ACCESS );
  333. DebugPtrAssert( LptStream );
  334. }
  335. if ( !Lpt || !LptStream ) {
  336. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, (ULONG)EXIT_ERROR );
  337. }
  338. if ( Data->SetCol ) {
  339. //
  340. // Set number of columns. The sequence consists of one byte.
  341. //
  342. LptStream->WriteByte( (Data->Col == 80) ? CODE_COLS_80 : CODE_COLS_132 );
  343. }
  344. if ( Data->SetLines ) {
  345. //
  346. // Set line spacing. The sequence consists of one escape byte
  347. // followed by one CODE_LINES_6 or CODE_LINES 8 byte.
  348. //
  349. LptStream->WriteByte( CODE_ESCAPE );
  350. LptStream->WriteByte( (Data->Lines == 6) ? CODE_LINES_6 : CODE_LINES_8 );
  351. }
  352. DELETE( LptStream );
  353. DELETE( Lpt );
  354. return TRUE;
  355. }
  356. BOOLEAN
  357. LptRedirect(
  358. IN PCPATH DevicePath,
  359. IN PREQUEST_HEADER Request
  360. )
  361. /*++
  362. Routine Description:
  363. Redirects LPT to a COMM port.
  364. Arguments:
  365. DevicePath - Supplies pointer to path of device
  366. Request - Supplies pointer to request
  367. Return Value:
  368. BOOLEAN - TRUE if LPT redirected,
  369. FALSE otherwise
  370. Notes:
  371. --*/
  372. {
  373. PREQUEST_DATA_LPT_REDIRECT Data;
  374. PPATH RedirPath;
  375. Data = (PREQUEST_DATA_LPT_REDIRECT)&(((PLPT_REQUEST)Request)->Data.Redirect);
  376. //
  377. // Verify that the serial device specified is valid
  378. //
  379. if ( !IsAValidDevice( Data->DeviceType, Data->DeviceNumber, &RedirPath )) {
  380. DisplayMessageAndExit( MODE_ERROR_INVALID_DEVICE_NAME,
  381. RedirPath->GetPathString(),
  382. (ULONG)EXIT_ERROR );
  383. }
  384. if ( !REDIR::Redirect( DevicePath, RedirPath ) ) {
  385. DisplayMessageAndExit( MODE_ERROR_LPT_CANNOT_REROUTE, RedirPath->GetPathString(), (ULONG)EXIT_ERROR );
  386. }
  387. //
  388. // Display the status as confirmation
  389. //
  390. LptStatus( DevicePath, Request );
  391. DELETE( RedirPath );
  392. return TRUE;
  393. }
  394. BOOLEAN
  395. LptEndRedir (
  396. IN PCPATH DevicePath,
  397. IN PREQUEST_HEADER Request
  398. )
  399. /*++
  400. Routine Description:
  401. Ends the redirection of an LPT port
  402. Arguments:
  403. DevicePath - Supplies pointer to path of device
  404. Request - Supplies pointer to request
  405. Return Value:
  406. BOOLEAN - TRUE
  407. Notes:
  408. --*/
  409. {
  410. REDIR_STATUS Status;
  411. //
  412. // If the LPT is being redirected, end the redirection
  413. //
  414. if ( REDIR::IsRedirected( &Status, DevicePath ) ) {
  415. if ( !REDIR::EndRedirection( DevicePath )) {
  416. DisplayMessageAndExit( MODE_ERROR_LPT_CANNOT_ENDREROUTE, NULL, (ULONG)EXIT_ERROR );
  417. }
  418. }
  419. //
  420. // Display status
  421. //
  422. LptStatus( DevicePath, Request );
  423. return TRUE;
  424. }
  425. PPATH
  426. GetRedirection(
  427. IN PCPATH DevicePath,
  428. OUT PREDIR_STATUS RedirStatus
  429. )
  430. /*++
  431. Routine Description:
  432. Determines to what device is the LPT redirected to
  433. Arguments:
  434. DevicePath - Supplies pointer to path of device
  435. RedirStatus - Supplies pointer to redirection status
  436. Return Value:
  437. PPATH - Pointer to the redirected device
  438. --*/
  439. {
  440. ULONG DeviceNumber = 1;
  441. PPATH DestPath = NULL;
  442. BOOLEAN ValidDevice = TRUE;
  443. if ( REDIR::IsRedirected( RedirStatus, DevicePath ) ) {
  444. for ( DeviceNumber = 1; DeviceNumber <= LAST_COM; DeviceNumber++ ) {
  445. IsAValidDevice( DEVICE_TYPE_COM, DeviceNumber, &DestPath );
  446. if ( REDIR::IsRedirected( RedirStatus, DevicePath, DestPath )) {
  447. break;
  448. }
  449. DELETE( DestPath );
  450. DestPath = NULL;
  451. }
  452. }
  453. return DestPath;
  454. }