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.

409 lines
10 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Copyright (c) 1991 Nokia Data Systems AB
  4. Module Name:
  5. dlctimr.c
  6. Abstract:
  7. This module implements timer services of NT DLC API.
  8. Contents:
  9. DirTimerSet
  10. DirTimerCancelGroup
  11. DirTimerCancel
  12. SearchTimerCommand
  13. AbortCommandsWithFlag
  14. Author:
  15. Antti Saarenheimo 02-Sep-1991
  16. Environment:
  17. Kernel mode
  18. Revision History:
  19. --*/
  20. #include <dlc.h>
  21. NTSTATUS
  22. DirTimerSet(
  23. IN PIRP pIrp,
  24. IN PDLC_FILE_CONTEXT pFileContext,
  25. IN PNT_DLC_PARMS pDlcParms,
  26. IN ULONG InputBufferLength,
  27. IN ULONG OutputBufferLength
  28. )
  29. /*++
  30. Routine Description:
  31. Procedure queues a timer set command to a special timer command
  32. queue. The timer commands are queue by the cumulative time in
  33. such way, that only the timer tick needs to decrement (and possibly
  34. to complete) only the first command in the queue.
  35. Arguments:
  36. pIrp - current io request packet
  37. pFileContext - DLC adapter context
  38. pDlcParms - the current parameter block
  39. InputBufferLength - the length of input parameters
  40. OutputBufferLength - the length of output parameters
  41. Return Value:
  42. NTSTATUS:
  43. STATUS_SUCCESS
  44. --*/
  45. {
  46. PDLC_COMMAND* ppNode;
  47. PDLC_COMMAND pDlcCommand;
  48. UINT TimerTicks;
  49. UNREFERENCED_PARAMETER(InputBufferLength);
  50. UNREFERENCED_PARAMETER(OutputBufferLength);
  51. //
  52. // Check the timer value (I don't know what 13107 half seconds
  53. // means, this is just as in IBM spec).
  54. //
  55. TimerTicks = pDlcParms->Async.Ccb.u.dir.usParameter0 + 1;
  56. if (TimerTicks > 13108) {
  57. return DLC_STATUS_TIMER_ERROR;
  58. }
  59. //
  60. // DIR.TIMER.CANCEL returns wrong error code !!!!
  61. // (0x0a insted of TIMER_ERROR)
  62. //
  63. pDlcCommand = (PDLC_COMMAND)ALLOCATE_PACKET_DLC_PKT(pFileContext->hPacketPool);
  64. if (pDlcCommand == NULL) {
  65. return DLC_STATUS_NO_MEMORY;
  66. }
  67. pDlcCommand->Event = 0;
  68. pDlcCommand->pIrp = pIrp;
  69. pDlcCommand->StationId = 0;
  70. pDlcCommand->StationIdMask = (USHORT)(-1);
  71. pDlcCommand->AbortHandle = pDlcParms->Async.Ccb.pCcbAddress;
  72. //
  73. // find the right place in the list to put this timer
  74. //
  75. for (ppNode = &pFileContext->pTimerQueue; ; ) {
  76. if (*ppNode == NULL) {
  77. pDlcCommand->LlcPacket.pNext = NULL;
  78. break;
  79. } else if ((*ppNode)->Overlay.TimerTicks >= TimerTicks) {
  80. (*ppNode)->Overlay.TimerTicks -= TimerTicks;
  81. pDlcCommand->LlcPacket.pNext = (PLLC_PACKET)*ppNode;
  82. break;
  83. } else {
  84. TimerTicks -= (*ppNode)->Overlay.TimerTicks;
  85. }
  86. ppNode = (PDLC_COMMAND *)&(*ppNode)->LlcPacket.pNext;
  87. }
  88. *ppNode = pDlcCommand;
  89. pDlcCommand->Overlay.TimerTicks = TimerTicks;
  90. return STATUS_PENDING;
  91. }
  92. NTSTATUS
  93. DirTimerCancelGroup(
  94. IN PIRP pIrp,
  95. IN PDLC_FILE_CONTEXT pFileContext,
  96. IN PNT_DLC_PARMS pDlcParms,
  97. IN ULONG InputBufferLength,
  98. IN ULONG OutputBufferLength
  99. )
  100. /*++
  101. Routine Description:
  102. Procedure cancels all DirTimerSet commands having the given
  103. command completion flag.
  104. Arguments:
  105. pIrp - current io request packet
  106. pFileContext - DLC adapter context
  107. pDlcParms - the current parameter block
  108. InputBufferLength - the length of input parameters
  109. Return Value:
  110. NTSTATUS:
  111. STATUS_SUCCESS
  112. --*/
  113. {
  114. UNREFERENCED_PARAMETER(pIrp);
  115. UNREFERENCED_PARAMETER(InputBufferLength);
  116. UNREFERENCED_PARAMETER(OutputBufferLength);
  117. //
  118. // All terminated DirTimerSet commands are chained to the
  119. // CCB pointer of this cancel group command.
  120. // Terminate the link list of the canceled CCBs.
  121. //
  122. pDlcParms->InputCcb.pCcbAddress = NULL;
  123. AbortCommandsWithFlag(pFileContext,
  124. pDlcParms->InputCcb.u.ulParameter, // CompletionFlag
  125. &pDlcParms->InputCcb.pCcbAddress,
  126. DLC_STATUS_CANCELLED_BY_USER
  127. );
  128. return STATUS_SUCCESS;
  129. }
  130. NTSTATUS
  131. DirTimerCancel(
  132. IN PIRP pIrp,
  133. IN PDLC_FILE_CONTEXT pFileContext,
  134. IN PNT_DLC_PARMS pDlcParms,
  135. IN ULONG InputBufferLength,
  136. IN ULONG OutputBufferLength
  137. )
  138. /*++
  139. Routine Description:
  140. This primitive cancels the given timer command in a
  141. special timer queue.
  142. Arguments:
  143. pIrp - current io request packet
  144. pFileContext - DLC process specific adapter context
  145. pDlcParms - the current parameter block
  146. InputBufferLength - the length of input parameters
  147. Return Value:
  148. NTSTATUS:
  149. STATUS_SUCCESS
  150. DLC_STATUS_TIMER_ERROR
  151. --*/
  152. {
  153. PDLC_COMMAND pDlcCommand;
  154. PDLC_COMMAND *ppDlcCommand;
  155. PVOID pCcbAddress = NULL;
  156. UNREFERENCED_PARAMETER(pIrp);
  157. UNREFERENCED_PARAMETER(InputBufferLength);
  158. UNREFERENCED_PARAMETER(OutputBufferLength);
  159. ppDlcCommand = SearchTimerCommand(&pFileContext->pTimerQueue,
  160. pDlcParms->DlcCancelCommand.CcbAddress,
  161. FALSE
  162. );
  163. //
  164. // if the timer queue is not empty, cancel the timed DLC request else
  165. // return an error
  166. //
  167. if (ppDlcCommand != NULL && *ppDlcCommand != NULL) {
  168. pDlcCommand = *ppDlcCommand;
  169. *ppDlcCommand = (PDLC_COMMAND)pDlcCommand->LlcPacket.pNext;
  170. // >>> SNA bug #10126
  171. //
  172. // If there's a next timer after the canceled one we need to update
  173. // it's tick count. Things will go really wrong if the next timer's tick
  174. // count is 0 (it expires at the same time as the canceled one) because
  175. // the timer tick routine (LlcEventIndication) first decrements the tick
  176. // value and then checks if the result is 0.
  177. //
  178. if( *ppDlcCommand )
  179. {
  180. (*ppDlcCommand)->Overlay.TimerTicks += pDlcCommand->Overlay.TimerTicks;
  181. if((*ppDlcCommand)->Overlay.TimerTicks == 0)
  182. {
  183. (*ppDlcCommand)->Overlay.TimerTicks++;
  184. }
  185. }
  186. // >>> SNA bug #10126
  187. #if LLC_DBG
  188. pDlcCommand->LlcPacket.pNext = NULL;
  189. #endif
  190. CancelDlcCommand(pFileContext,
  191. pDlcCommand,
  192. &pCcbAddress,
  193. DLC_STATUS_CANCELLED_BY_USER,
  194. TRUE
  195. );
  196. return STATUS_SUCCESS;
  197. } else {
  198. return DLC_STATUS_TIMER_ERROR;
  199. }
  200. }
  201. PDLC_COMMAND*
  202. SearchTimerCommand(
  203. IN PDLC_COMMAND *ppQueue,
  204. IN PVOID pSearchHandle,
  205. IN BOOLEAN SearchCompletionFlags
  206. )
  207. /*++
  208. Routine Description:
  209. This primitive cancels the given timer command in a
  210. special timer queue.
  211. Arguments:
  212. ppQueue - the base address of the command queue
  213. pSearchHandle - command completion flag or ccb address of
  214. the timer command.
  215. SearchCompletionFlags - ste TRUE, if we are searching a completion flag
  216. Return Value:
  217. PDLC_COMMAND * the address of the address of the found timer command
  218. --*/
  219. {
  220. PDLC_COMMAND pCmd;
  221. for (; *ppQueue != NULL; ppQueue = (PDLC_COMMAND *)&(*ppQueue)->LlcPacket.pNext) {
  222. pCmd = *ppQueue;
  223. //
  224. // A Timer command can be cancelled either by its CCB address
  225. // or by its command completion flag. The boolean flag
  226. // defines the used search condition.
  227. // We will rather space than speed optimize the rarely used
  228. // procedures like this one.
  229. //
  230. if (pSearchHandle
  231. == (SearchCompletionFlags
  232. ? (PVOID)
  233. UlongToPtr(((PNT_DLC_CCB)pCmd->pIrp->AssociatedIrp.SystemBuffer)->CommandCompletionFlag)
  234. : pCmd->AbortHandle)) {
  235. return ppQueue;
  236. }
  237. }
  238. return NULL;
  239. }
  240. VOID
  241. AbortCommandsWithFlag(
  242. IN PDLC_FILE_CONTEXT pFileContext,
  243. IN ULONG CommandCompletionFlag,
  244. IN OUT PVOID *ppCcbLink,
  245. IN UINT CancelStatus
  246. )
  247. /*++
  248. Routine Description:
  249. The command cancels all (timer) commands having the given command
  250. completion flag.
  251. Arguments:
  252. pFileContext - process specific adapetr context
  253. EventMask - the event mask defining the canceled command
  254. CommandCompletionFlag - the command completion flag of the canceled
  255. commands
  256. ppCcbLink - the canceled commands are linked by their next CCB pointer
  257. fields together. The caller must provide the next CCB address
  258. in this parameter (usually *ppCcbLink == NULL) and the function
  259. will return the address of the last canceled CCB field.
  260. Return Value:
  261. DLC_STATUS_TIMER_ERROR - no mathing command was found
  262. STATUS_SUCCESS - the command was canceled
  263. --*/
  264. {
  265. PDLC_COMMAND pDlcCommand;
  266. PDLC_COMMAND *ppQueue;
  267. PVOID pNextCcb = NULL;
  268. ppQueue = &pFileContext->pTimerQueue;
  269. for (;;) {
  270. ppQueue = SearchTimerCommand(ppQueue,
  271. (PVOID)UlongToPtr(CommandCompletionFlag),
  272. TRUE
  273. );
  274. if (ppQueue != NULL) {
  275. pDlcCommand = *ppQueue;
  276. *ppQueue = (PDLC_COMMAND)pDlcCommand->LlcPacket.pNext;
  277. #if LLC_DBG
  278. pDlcCommand->LlcPacket.pNext = NULL;
  279. #endif
  280. *ppCcbLink = ((PNT_DLC_PARMS)pDlcCommand->pIrp->AssociatedIrp.SystemBuffer)->Async.Ccb.pCcbAddress;
  281. //
  282. // We must suppress any kind of command
  283. // completion indications to the applications.
  284. // It is very intersting to see, if Io- system hangs up
  285. // because of this modification.
  286. //
  287. pDlcCommand->pIrp->UserEvent = NULL;
  288. pDlcCommand->pIrp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
  289. pDlcCommand->pIrp->Overlay.AsynchronousParameters.UserApcContext = NULL;
  290. CompleteAsyncCommand(pFileContext, CancelStatus, pDlcCommand->pIrp, pNextCcb, FALSE);
  291. pNextCcb = *ppCcbLink;
  292. DEALLOCATE_PACKET_DLC_PKT(pFileContext->hPacketPool, pDlcCommand);
  293. } else {
  294. //
  295. // This procedure do not care if we find any commands
  296. // or not. Everything is ok, when there are no commands
  297. // in the queue.
  298. //
  299. return;
  300. }
  301. }
  302. }