Source code of Windows XP (NT5)
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.

464 lines
14 KiB

  1. /////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // requests.cpp
  7. //
  8. // Abstract:
  9. // This module contains code which handles the IRP_MJ_DEVICE_CONTROL
  10. // calls, which corresponds to DeviceIoControl calls make by the dll
  11. //
  12. //////////////////////////////////////////////////////////
  13. #include "sysvars.h"
  14. ///////////////////////////////////
  15. // private constants
  16. ///////////////////////////////////
  17. const PCHAR strFunc1 = "TSIssueRequest";
  18. const ULONG ulNoHandleUsed = ulINVALID_OBJECT;
  19. ULONG ulCommandHandleUsage[ulNUM_COMMANDS] =
  20. {
  21. ulNoHandleUsed, // ulNO_COMMAND
  22. ulNoHandleUsed, // ulVERSION_CHECK
  23. ulNoHandleUsed, // ulABORT_COMMAND
  24. ulNoHandleUsed, // ulDEBUGLEVEL
  25. ulNoHandleUsed, // ulGETNUMDEVICES
  26. ulNoHandleUsed, // ulGETDEVICE
  27. ulNoHandleUsed, // ulGETADDRESS
  28. ulNoHandleUsed, // ulOPENCONTROL
  29. ulNoHandleUsed, // ulOPENADDRESS
  30. ulNoHandleUsed, // ulOPENENDPOINT
  31. ulControlChannelObject, // ulCLOSECONTROL
  32. ulAddressObject, // ulCLOSEADDRESS
  33. ulAddressObject, // ulSENDDATAGRAM
  34. ulAddressObject, // ulRECEIVEDATAGRAM
  35. ulEndpointObject, // ulCLOSEENDPOINT
  36. ulEndpointObject, // ulCONNECT
  37. ulEndpointObject, // ulDISCONNECT
  38. ulEndpointObject, // ulISCONNECTED
  39. ulEndpointObject, // ulSEND
  40. ulEndpointObject, // ulRECEIVE
  41. ulEndpointObject, // ulLISTEN
  42. ulControlChannelObject |
  43. ulAddressObject |
  44. ulEndpointObject, // ulQUERYINFO
  45. ulAddressObject |
  46. ulEndpointObject, // ulSETEVENTHANDLER
  47. ulAddressObject |
  48. ulEndpointObject, // ulPOSTRECEIVEBUFFER
  49. ulAddressObject |
  50. ulEndpointObject // ulFETCHRECEIVEBUFFER
  51. };
  52. //------------------------------------------------------
  53. //
  54. // Function: TSIssueRequest
  55. //
  56. // Arguments: DeviceContext -- DeviceContext for ndistest.sys.
  57. // Irp -- ptr to current irp structure
  58. // IrpSp -- ptr to current irp stack
  59. //
  60. // Returns: final status of whatever operation performed-- STATUS_SUCCESS,
  61. // STATUS_PENDING, or error status (usually STATUS_UNSUCCESSFUL)
  62. //
  63. // Descript: This function calls the appropriate function(s) to deal with
  64. // an IRP_DEVICE_CONTROL request. Basically all commands from
  65. // the dll come thru here.
  66. //
  67. // --------------------------------------------------------
  68. NTSTATUS
  69. TSIssueRequest(PDEVICE_CONTEXT pDeviceContext,
  70. PIRP pIrp,
  71. PIO_STACK_LOCATION pIrpSp)
  72. {
  73. NTSTATUS lStatus;
  74. PGENERIC_HEADER pGenericHeader; // node used as main argument
  75. ULONG ulCmdCode // IOCTL command to execute
  76. = ulTdiIoctlToCommand(pIrpSp->Parameters.DeviceIoControl.IoControlCode);
  77. PSEND_BUFFER pSendBuffer // arguments for command (inputbuffer)
  78. = TSGetSendBuffer(pIrp);
  79. PRECEIVE_BUFFER pReceiveBuffer // data to return to dll (outputbuffer)
  80. = TSGetReceiveBuffer(pIrp);
  81. PIRP pLastCommandIrp
  82. = pDeviceContext->pLastCommandIrp;
  83. //
  84. // check for an illegal command number
  85. //
  86. if (ulCmdCode >= ulNUM_COMMANDS)
  87. {
  88. DebugPrint2("\n%s: Illegal command code: 0x%08x\n",
  89. strFunc1,
  90. ulCmdCode);
  91. ulCmdCode = ulNO_COMMAND;
  92. }
  93. //
  94. // check for commands that don't require a handle
  95. //
  96. if (ulCommandHandleUsage[ulCmdCode] == ulNoHandleUsed)
  97. {
  98. pGenericHeader = NULL;
  99. }
  100. //
  101. // for commands that require a handle, make sure that they
  102. // have the correct type!
  103. //
  104. else
  105. {
  106. pGenericHeader = TSGetObjectFromHandle(pSendBuffer->TdiHandle,
  107. ulCommandHandleUsage[ulCmdCode]);
  108. if (pGenericHeader)
  109. {
  110. TSAcquireSpinLock(&pObjectList->TdiSpinLock);
  111. if (pGenericHeader->fInCommand)
  112. {
  113. DebugPrint1("\n%s: ERROR -- command already in progress!\n",
  114. strFunc1);
  115. ulCmdCode = ulNO_COMMAND;
  116. pGenericHeader = NULL;
  117. }
  118. else
  119. {
  120. pGenericHeader->fInCommand = TRUE;
  121. }
  122. TSReleaseSpinLock(&pObjectList->TdiSpinLock);
  123. }
  124. else
  125. {
  126. DebugPrint1("\n%s: handle type invalid for command!\n", strFunc1);
  127. ulCmdCode = ulNO_COMMAND;
  128. }
  129. }
  130. //
  131. // if a real command, store as last command
  132. //
  133. if ((ulCmdCode != ulNO_COMMAND) && (ulCmdCode != ulABORT_COMMAND))
  134. {
  135. pDeviceContext->pLastCommandIrp = pIrp;
  136. pSendBuffer->pvLowerIrp = NULL;
  137. pSendBuffer->pvDeviceContext = pDeviceContext;
  138. }
  139. //
  140. // now deal with the specific command..
  141. //
  142. switch (ulCmdCode)
  143. {
  144. //-----------------------------------------------------------
  145. // commands that do not require any handle
  146. //-----------------------------------------------------------
  147. //
  148. // ulNO_COMMAND -- does this if missing required handle type
  149. // (don't want to hit real command OR default..)
  150. //
  151. case ulNO_COMMAND:
  152. lStatus = STATUS_INVALID_PARAMETER;
  153. break;
  154. //
  155. // ulVERSION_CHECK -- return current version id
  156. //
  157. case ulVERSION_CHECK:
  158. //
  159. // Get the Input and buffers for the Incoming command.
  160. // Make sure both lengths are ok..
  161. //
  162. if ((pIrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(SEND_BUFFER)) ||
  163. (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(RECEIVE_BUFFER)))
  164. {
  165. DebugPrint1("\n%s: IRP buffer size mismatch!\n"
  166. "DLL and driver are mismatched!\n",
  167. strFunc1);
  168. lStatus = STATUS_UNSUCCESSFUL;
  169. }
  170. else
  171. {
  172. pReceiveBuffer->RESULTS.ulReturnValue = TDI_SAMPLE_VERSION_ID;
  173. lStatus = STATUS_SUCCESS;
  174. }
  175. break;
  176. //
  177. // ulABORT_COMMAND -- abort the previous command, if possible
  178. //
  179. case ulABORT_COMMAND:
  180. lStatus = STATUS_SUCCESS;
  181. if (pLastCommandIrp)
  182. {
  183. PSEND_BUFFER pLastSendBuffer = TSGetSendBuffer(pLastCommandIrp);
  184. if (pLastSendBuffer)
  185. {
  186. if (pLastSendBuffer->pvLowerIrp)
  187. {
  188. DebugPrint0("\nCommand = ulABORT_COMMAND\n");
  189. IoCancelIrp((PIRP)pLastSendBuffer->pvLowerIrp);
  190. break;
  191. }
  192. }
  193. }
  194. DebugPrint0("\nCommand = ulABORT_COMMAND w/no command\n");
  195. break;
  196. //
  197. // ulDEBUGLEVEL -- set the current debuglevel
  198. //
  199. case ulDEBUGLEVEL:
  200. ulDebugLevel = pSendBuffer->COMMAND_ARGS.ulDebugLevel;
  201. DebugPrint1("\nSetting debug level to 0x%x\n", ulDebugLevel);
  202. lStatus = STATUS_SUCCESS;
  203. break;
  204. //
  205. // ulGETNUMDEVICES -- get number of openable devices
  206. //
  207. case ulGETNUMDEVICES:
  208. TSGetNumDevices(pSendBuffer,
  209. pReceiveBuffer);
  210. lStatus = STATUS_SUCCESS;
  211. break;
  212. //
  213. // ulGETDEVICE -- get the name to open for a specific device
  214. //
  215. case ulGETDEVICE:
  216. lStatus = TSGetDevice(pSendBuffer,
  217. pReceiveBuffer);
  218. break;
  219. //
  220. // ulGETADDRESS -- get the address to open for a specific device
  221. //
  222. case ulGETADDRESS:
  223. lStatus = TSGetAddress(pSendBuffer,
  224. pReceiveBuffer);
  225. break;
  226. //
  227. // ulOPENCONTROL -- open a control channel
  228. //
  229. case ulOPENCONTROL:
  230. lStatus = TSOpenControl(pSendBuffer,
  231. pReceiveBuffer);
  232. break;
  233. //
  234. // ulOPENADDRESS -- open an address object
  235. //
  236. case ulOPENADDRESS:
  237. lStatus = TSOpenAddress(pSendBuffer,
  238. pReceiveBuffer);
  239. break;
  240. //
  241. // ulOPENENDPOINT -- open an endpoint object
  242. //
  243. case ulOPENENDPOINT:
  244. lStatus = TSOpenEndpoint(pSendBuffer,
  245. pReceiveBuffer);
  246. break;
  247. //-----------------------------------------------------------
  248. // commands that require a control channel handle
  249. //-----------------------------------------------------------
  250. //
  251. // ulCLOSECONTROL -- close a control channel
  252. //
  253. case ulCLOSECONTROL:
  254. TSRemoveNode(pSendBuffer->TdiHandle);
  255. TSCloseControl((PCONTROL_CHANNEL)pGenericHeader);
  256. pGenericHeader = NULL;
  257. lStatus = STATUS_SUCCESS;
  258. break;
  259. //-----------------------------------------------------------
  260. // commands that require an address handle
  261. //-----------------------------------------------------------
  262. //
  263. // ulCLOSEADDRESS -- close an address object
  264. //
  265. case ulCLOSEADDRESS:
  266. TSRemoveNode(pSendBuffer->TdiHandle);
  267. TSCloseAddress((PADDRESS_OBJECT)pGenericHeader);
  268. pGenericHeader = NULL;
  269. lStatus = STATUS_SUCCESS;
  270. break;
  271. //
  272. // ulSENDDATAGRAM -- send a datagram
  273. //
  274. case ulSENDDATAGRAM:
  275. lStatus = TSSendDatagram((PADDRESS_OBJECT)pGenericHeader,
  276. pSendBuffer,
  277. pIrp);
  278. break;
  279. //
  280. // ulRECEIVEDATAGRAM -- receive a datagram
  281. //
  282. case ulRECEIVEDATAGRAM:
  283. lStatus = TSReceiveDatagram((PADDRESS_OBJECT)pGenericHeader,
  284. pSendBuffer,
  285. pReceiveBuffer);
  286. break;
  287. //-----------------------------------------------------------
  288. // commands that require an endpoint
  289. //-----------------------------------------------------------
  290. //
  291. // ulCLOSEENDPOINT -- close an endpoint object
  292. //
  293. case ulCLOSEENDPOINT:
  294. TSRemoveNode(pSendBuffer->TdiHandle);
  295. TSCloseEndpoint((PENDPOINT_OBJECT)pGenericHeader);
  296. pGenericHeader = NULL;
  297. lStatus = STATUS_SUCCESS;
  298. break;
  299. //
  300. // ulCONNECT -- establish connection between local endpoint and remote endpoint
  301. //
  302. case ulCONNECT:
  303. lStatus = TSConnect((PENDPOINT_OBJECT)pGenericHeader,
  304. pSendBuffer,
  305. pIrp);
  306. break;
  307. //
  308. // ulDISCONNECT -- removed connection between local and remote endpoints
  309. //
  310. case ulDISCONNECT:
  311. lStatus = TSDisconnect((PENDPOINT_OBJECT)pGenericHeader,
  312. pSendBuffer,
  313. pIrp);
  314. break;
  315. //
  316. // ulISCONNECTED -- check to see if endpoint is connected
  317. //
  318. case ulISCONNECTED:
  319. lStatus = TSIsConnected((PENDPOINT_OBJECT)pGenericHeader,
  320. pReceiveBuffer);
  321. break;
  322. //
  323. // ulSEND -- send data over the connection
  324. //
  325. case ulSEND:
  326. lStatus = TSSend((PENDPOINT_OBJECT)pGenericHeader,
  327. pSendBuffer,
  328. pIrp);
  329. break;
  330. //
  331. // ulRECEIVE -- receive a packet over the connection
  332. //
  333. case ulRECEIVE:
  334. lStatus = TSReceive((PENDPOINT_OBJECT)pGenericHeader,
  335. pSendBuffer,
  336. pReceiveBuffer);
  337. break;
  338. //
  339. // ulLISTEN -- wait for an incoming call
  340. //
  341. case ulLISTEN:
  342. lStatus = TSListen((PENDPOINT_OBJECT)pGenericHeader);
  343. break;
  344. //-----------------------------------------------------------
  345. // commands that require a handle, but type may vary
  346. //-----------------------------------------------------------
  347. //
  348. // ulQUERYINFO -- query object for information
  349. //
  350. case ulQUERYINFO:
  351. lStatus = TSQueryInfo(pGenericHeader,
  352. pSendBuffer,
  353. pIrp);
  354. break;
  355. //
  356. // ulSETEVENTHANDLER -- enable or disable an event handler
  357. //
  358. case ulSETEVENTHANDLER:
  359. lStatus = TSSetEventHandler(pGenericHeader,
  360. pSendBuffer,
  361. pIrp);
  362. break;
  363. //
  364. // ulPOSTRECEIVEBUFFER -- post buffer for receive/recvdgram
  365. //
  366. case ulPOSTRECEIVEBUFFER:
  367. lStatus = TSPostReceiveBuffer(pGenericHeader,
  368. pSendBuffer);
  369. break;
  370. //
  371. // ulFETCHRECEIVEBUFFER -- retrieve a previously posted receive buffer
  372. //
  373. case ulFETCHRECEIVEBUFFER:
  374. lStatus = TSFetchReceiveBuffer(pGenericHeader,
  375. pReceiveBuffer);
  376. break;
  377. // --------------------------------------------
  378. // not a recognized command...
  379. //---------------------------------------------
  380. default:
  381. DebugPrint1("\n%s: Invalid Command Received\n", strFunc1);
  382. lStatus = STATUS_INVALID_PARAMETER;
  383. break;
  384. }
  385. if (lStatus != STATUS_PENDING)
  386. {
  387. pReceiveBuffer->lStatus = lStatus;
  388. lStatus = STATUS_SUCCESS; // return SUCCESS or PENDING for DeviceIoControl
  389. }
  390. //
  391. // clear flag to allow another command in on this handle
  392. //
  393. if (pGenericHeader)
  394. {
  395. TSAcquireSpinLock(&pObjectList->TdiSpinLock);
  396. pGenericHeader->fInCommand = FALSE;
  397. TSReleaseSpinLock(&pObjectList->TdiSpinLock);
  398. }
  399. return lStatus;
  400. }
  401. ////////////////////////////////////////////////////////////////////////
  402. // end of file requests.cpp
  403. ////////////////////////////////////////////////////////////////////////