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.

3356 lines
95 KiB

  1. /*-------------------------------------------------------------------
  2. | utils.c -
  3. This module contains code that perform queueing and completion
  4. manipulation on requests.
  5. 1-21-99 fix tick count [#] on peer traces. kpb.
  6. 11-24-98 Minor adjustment to purge to when WaitOnTx selected. kpb.
  7. 6-01-98 Add modem reset/row routines (generic for VS and Rkt)
  8. 3-18-98 Add time_stall function for modem settle time after reset clear - jl
  9. 3-04-98 Add synch. routine back in to synch up to isr service routine. kpb.
  10. 7-10-97 Adjust SerialPurgeTxBuffers to not purge tx-hardware buffer
  11. as per MS driver. Now we only purge it if it is flowed-off.
  12. Copyright 1993-98 Comtrol Corporation. All rights reserved.
  13. |--------------------------------------------------------------------*/
  14. #include "precomp.h"
  15. //-- local funcs
  16. BOOLEAN SerialPurgeRxBuffers(IN PVOID Context);
  17. BOOLEAN SerialPurgeTxBuffers(IN PVOID Context, int always);
  18. NTSTATUS SerialStartFlush(IN PSERIAL_DEVICE_EXTENSION Extension);
  19. static char *szParameters = {"\\Parameters"};
  20. /*----------------------------------------------------------------------------
  21. SyncUp - sync up to either the IRQ or Timer-DPC. If an Interrupt is
  22. used, then we must use KeSynchronizeExecution(), if a timer-dpc is used
  23. then we
  24. |----------------------------------------------------------------------------*/
  25. VOID SyncUp(IN PKINTERRUPT IntObj,
  26. IN PKSPIN_LOCK SpinLock,
  27. IN PKSYNCHRONIZE_ROUTINE SyncProc,
  28. IN PVOID Context)
  29. {
  30. KIRQL OldIrql;
  31. if (IntObj != NULL)
  32. {
  33. KeSynchronizeExecution(IntObj, SyncProc, Context);
  34. }
  35. else // assume spinlock, using timer
  36. {
  37. KeAcquireSpinLock(SpinLock, &OldIrql);
  38. SyncProc(Context);
  39. KeReleaseSpinLock(SpinLock, OldIrql );
  40. }
  41. }
  42. /*--------------------------------------------------------------------------
  43. SerialKillAllReadsOrWrites -
  44. This function is used to cancel all queued and the current irps
  45. for reads or for writes.
  46. Arguments:
  47. DeviceObject - A pointer to the serial device object.
  48. QueueToClean - A pointer to the queue which we're going to clean out.
  49. CurrentOpIrp - Pointer to a pointer to the current irp.
  50. Return Value:
  51. None.
  52. |--------------------------------------------------------------------------*/
  53. VOID
  54. SerialKillAllReadsOrWrites(
  55. IN PDEVICE_OBJECT DeviceObject,
  56. IN PLIST_ENTRY QueueToClean,
  57. IN PIRP *CurrentOpIrp
  58. )
  59. {
  60. KIRQL cancelIrql;
  61. PDRIVER_CANCEL cancelRoutine;
  62. // We acquire the cancel spin lock. This will prevent the
  63. // irps from moving around.
  64. IoAcquireCancelSpinLock(&cancelIrql);
  65. // Clean the list from back to front.
  66. while (!IsListEmpty(QueueToClean))
  67. {
  68. PIRP currentLastIrp = CONTAINING_RECORD(
  69. QueueToClean->Blink,
  70. IRP,
  71. Tail.Overlay.ListEntry
  72. );
  73. RemoveEntryList(QueueToClean->Blink);
  74. cancelRoutine = currentLastIrp->CancelRoutine;
  75. currentLastIrp->CancelIrql = cancelIrql;
  76. currentLastIrp->CancelRoutine = NULL;
  77. currentLastIrp->Cancel = TRUE;
  78. cancelRoutine( DeviceObject, currentLastIrp );
  79. IoAcquireCancelSpinLock(&cancelIrql);
  80. }
  81. // The queue is clean. Now go after the current if it's there.
  82. if (*CurrentOpIrp)
  83. {
  84. cancelRoutine = (*CurrentOpIrp)->CancelRoutine;
  85. (*CurrentOpIrp)->Cancel = TRUE;
  86. // If the current irp is not in a cancelable state
  87. // then it *will* try to enter one and the above
  88. // assignment will kill it. If it already is in
  89. // a cancelable state then the following will kill it.
  90. if (cancelRoutine)
  91. {
  92. (*CurrentOpIrp)->CancelRoutine = NULL;
  93. (*CurrentOpIrp)->CancelIrql = cancelIrql;
  94. // This irp is already in a cancelable state. We simply
  95. // mark it as canceled and call the cancel routine for it.
  96. cancelRoutine( DeviceObject, *CurrentOpIrp );
  97. }
  98. else
  99. {
  100. IoReleaseCancelSpinLock(cancelIrql);
  101. }
  102. }
  103. else
  104. {
  105. IoReleaseCancelSpinLock(cancelIrql);
  106. }
  107. }
  108. /*--------------------------------------------------------------------------
  109. SerialGetNextIrp -
  110. This function is used to make the head of the particular
  111. queue the current irp. It also completes the what
  112. was the old current irp if desired.
  113. Arguments:
  114. CurrentOpIrp - Pointer to a pointer to the currently active
  115. irp for the particular work list. Note that
  116. this item is not actually part of the list.
  117. QueueToProcess - The list to pull the new item off of.
  118. NextIrp - The next Irp to process. Note that CurrentOpIrp
  119. will be set to this value under protection of the
  120. cancel spin lock. However, if *NextIrp is NULL when
  121. this routine returns, it is not necessaryly true the
  122. what is pointed to by CurrentOpIrp will also be NULL.
  123. The reason for this is that if the queue is empty
  124. when we hold the cancel spin lock, a new irp may come
  125. in immediately after we release the lock.
  126. CompleteCurrent - If TRUE then this routine will complete the
  127. irp pointed to by the pointer argument
  128. CurrentOpIrp.
  129. Return Value: None.
  130. |--------------------------------------------------------------------------*/
  131. VOID
  132. SerialGetNextIrp(
  133. IN PIRP *CurrentOpIrp,
  134. IN PLIST_ENTRY QueueToProcess,
  135. OUT PIRP *NextIrp,
  136. IN BOOLEAN CompleteCurrent,
  137. IN PSERIAL_DEVICE_EXTENSION extension
  138. )
  139. {
  140. PIRP oldIrp;
  141. KIRQL oldIrql;
  142. IoAcquireCancelSpinLock(&oldIrql);
  143. oldIrp = *CurrentOpIrp;
  144. if (oldIrp) {
  145. if (CompleteCurrent)
  146. {
  147. MyAssert(!oldIrp->CancelRoutine);
  148. }
  149. }
  150. // Check to see if there is a new irp to start up.
  151. if (!IsListEmpty(QueueToProcess))
  152. {
  153. PLIST_ENTRY headOfList;
  154. headOfList = RemoveHeadList(QueueToProcess);
  155. *CurrentOpIrp = CONTAINING_RECORD(
  156. headOfList,
  157. IRP,
  158. Tail.Overlay.ListEntry
  159. );
  160. IoSetCancelRoutine( *CurrentOpIrp, NULL );
  161. }
  162. else
  163. {
  164. *CurrentOpIrp = NULL;
  165. }
  166. *NextIrp = *CurrentOpIrp;
  167. IoReleaseCancelSpinLock(oldIrql);
  168. if (CompleteCurrent)
  169. {
  170. if (oldIrp) {
  171. SerialCompleteRequest(extension, oldIrp, IO_SERIAL_INCREMENT);
  172. }
  173. }
  174. }
  175. /*--------------------------------------------------------------------------
  176. SerialTryToCompleteCurrent -
  177. This routine attempts to kill all of the reasons there are
  178. references on the current read/write. If everything can be killed
  179. it will complete this read/write and try to start another.
  180. NOTE: This routine assumes that it is called with the cancel
  181. spinlock held.
  182. Arguments:
  183. Extension - Simply a pointer to the device extension.
  184. SynchRoutine - A routine that will synchronize with the isr
  185. and attempt to remove the knowledge of the
  186. current irp from the isr. NOTE: This pointer
  187. can be null.
  188. IrqlForRelease - This routine is called with the cancel spinlock held.
  189. This is the irql that was current when the cancel
  190. spinlock was acquired.
  191. StatusToUse - The irp's status field will be set to this value, if
  192. this routine can complete the irp.
  193. Return Value:
  194. None.
  195. |--------------------------------------------------------------------------*/
  196. VOID
  197. SerialTryToCompleteCurrent(
  198. IN PSERIAL_DEVICE_EXTENSION Extension,
  199. IN PKSYNCHRONIZE_ROUTINE SynchRoutine OPTIONAL,
  200. IN KIRQL IrqlForRelease,
  201. IN NTSTATUS StatusToUse,
  202. IN PIRP *CurrentOpIrp,
  203. IN PLIST_ENTRY QueueToProcess OPTIONAL,
  204. IN PKTIMER IntervalTimer OPTIONAL,
  205. IN PKTIMER TotalTimer OPTIONAL,
  206. IN PSERIAL_START_ROUTINE Starter OPTIONAL,
  207. IN PSERIAL_GET_NEXT_ROUTINE GetNextIrp OPTIONAL,
  208. IN LONG RefType
  209. )
  210. {
  211. KIRQL OldIrql;
  212. // We can decrement the reference to "remove" the fact
  213. // that the caller no longer will be accessing this irp.
  214. SERIAL_CLEAR_REFERENCE(*CurrentOpIrp, RefType);
  215. if (SynchRoutine)
  216. {
  217. #ifdef USE_SYNC_LOCKS
  218. if (Driver.InterruptObject != NULL)
  219. {
  220. KeSynchronizeExecution(Driver.InterruptObject, SynchRoutine, Extension);
  221. }
  222. else // assume spinlock, using timer dpc
  223. {
  224. KeAcquireSpinLock(&Driver.TimerLock, &OldIrql);
  225. SynchRoutine(Extension);
  226. KeReleaseSpinLock(&Driver.TimerLock, OldIrql );
  227. }
  228. #else
  229. SynchRoutine(Extension);
  230. #endif
  231. }
  232. // Try to run down all other references to this irp.
  233. SerialRundownIrpRefs(
  234. CurrentOpIrp,
  235. IntervalTimer,
  236. TotalTimer
  237. );
  238. // See if the ref count is zero after trying to kill everybody else.
  239. if (!SERIAL_REFERENCE_COUNT(*CurrentOpIrp))
  240. {
  241. PIRP newIrp;
  242. // The ref count was zero so we should complete this request.
  243. // The following call will also cause the current irp to be completed.
  244. (*CurrentOpIrp)->IoStatus.Status = StatusToUse;
  245. if (StatusToUse == STATUS_CANCELLED)
  246. {
  247. (*CurrentOpIrp)->IoStatus.Information = 0;
  248. }
  249. if (GetNextIrp)
  250. {
  251. IoReleaseCancelSpinLock(IrqlForRelease);
  252. GetNextIrp(
  253. CurrentOpIrp,
  254. QueueToProcess,
  255. &newIrp,
  256. TRUE,
  257. Extension
  258. );
  259. if (newIrp) {
  260. Starter(Extension);
  261. }
  262. }
  263. else
  264. {
  265. PIRP oldIrp = *CurrentOpIrp;
  266. // There was no get next routine. We will simply complete
  267. // the irp. We should make sure that we null out the
  268. // pointer to the pointer to this irp.
  269. *CurrentOpIrp = NULL;
  270. IoReleaseCancelSpinLock(IrqlForRelease);
  271. SerialCompleteRequest(Extension, oldIrp, IO_SERIAL_INCREMENT);
  272. }
  273. }
  274. else
  275. {
  276. IoReleaseCancelSpinLock(IrqlForRelease);
  277. }
  278. }
  279. /*--------------------------------------------------------------------------
  280. SerialRundownIrpRefs -
  281. This routine runs through the various items that *could*
  282. have a reference to the current read/write. It try's to kill
  283. the reason. If it does succeed in killing the reason it
  284. will decrement the reference count on the irp.
  285. NOTE: This routine assumes that it is called with the cancel
  286. spin lock held.
  287. Arguments:
  288. CurrentOpIrp - Pointer to a pointer to current irp for the
  289. particular operation.
  290. IntervalTimer - Pointer to the interval timer for the operation.
  291. NOTE: This could be null.
  292. TotalTimer - Pointer to the total timer for the operation.
  293. NOTE: This could be null.
  294. Return Value:
  295. None.
  296. |--------------------------------------------------------------------------*/
  297. VOID
  298. SerialRundownIrpRefs(
  299. IN PIRP *CurrentOpIrp,
  300. IN PKTIMER IntervalTimer OPTIONAL,
  301. IN PKTIMER TotalTimer OPTIONAL
  302. )
  303. {
  304. // This routine is called with the cancel spin lock held
  305. // so we know only one thread of execution can be in here
  306. // at one time.
  307. // First we see if there is still a cancel routine. If
  308. // so then we can decrement the count by one.
  309. if ((*CurrentOpIrp)->CancelRoutine)
  310. {
  311. SERIAL_CLEAR_REFERENCE(*CurrentOpIrp, SERIAL_REF_CANCEL);
  312. IoSetCancelRoutine(
  313. *CurrentOpIrp,
  314. NULL
  315. );
  316. }
  317. if (IntervalTimer)
  318. {
  319. // Try to cancel the operations interval timer. If the operation
  320. // returns true then the timer did have a reference to the
  321. // irp. Since we've canceled this timer that reference is
  322. // no longer valid and we can decrement the reference count.
  323. // If the cancel returns false then this means either of two things:
  324. // a) The timer has already fired.
  325. // b) There never was an interval timer.
  326. // In the case of "b" there is no need to decrement the reference
  327. // count since the "timer" never had a reference to it.
  328. // In the case of "a", then the timer itself will be coming
  329. // along and decrement it's reference. Note that the caller
  330. // of this routine might actually be the this timer, but it
  331. // has already decremented the reference.
  332. if (KeCancelTimer(IntervalTimer))
  333. {
  334. SERIAL_CLEAR_REFERENCE(*CurrentOpIrp,SERIAL_REF_INT_TIMER);
  335. }
  336. }
  337. if (TotalTimer)
  338. {
  339. // Try to cancel the operations total timer. If the operation
  340. // returns true then the timer did have a reference to the
  341. // irp. Since we've canceled this timer that reference is
  342. // no longer valid and we can decrement the reference count.
  343. // If the cancel returns false then this means either of two things:
  344. // a) The timer has already fired.
  345. // b) There never was an total timer.
  346. // In the case of "b" there is no need to decrement the reference
  347. // count since the "timer" never had a reference to it.
  348. // In the case of "a", then the timer itself will be coming
  349. // along and decrement it's reference. Note that the caller
  350. // of this routine might actually be the this timer, but it
  351. // has already decremented the reference.
  352. if (KeCancelTimer(TotalTimer))
  353. {
  354. SERIAL_CLEAR_REFERENCE(*CurrentOpIrp,SERIAL_REF_TOTAL_TIMER);
  355. }
  356. }
  357. }
  358. /*--------------------------------------------------------------------------
  359. SerialStartOrQueue -
  360. This routine is used to either start or queue any requst
  361. that can be queued in the driver.
  362. Arguments:
  363. Extension - Points to the serial device extension.
  364. Irp - The irp to either queue or start. In either
  365. case the irp will be marked pending.
  366. QueueToExamine - The queue the irp will be place on if there
  367. is already an operation in progress.
  368. CurrentOpIrp - Pointer to a pointer to the irp the is current
  369. for the queue. The pointer pointed to will be
  370. set with to Irp if what CurrentOpIrp points to
  371. is NULL.
  372. Starter - The routine to call if the queue is empty.
  373. Return Value:
  374. This routine will return STATUS_PENDING if the queue is
  375. not empty. Otherwise, it will return the status returned
  376. from the starter routine (or cancel, if the cancel bit is
  377. on in the irp).
  378. |--------------------------------------------------------------------------*/
  379. NTSTATUS
  380. SerialStartOrQueue(
  381. IN PSERIAL_DEVICE_EXTENSION Extension,
  382. IN PIRP Irp,
  383. IN PLIST_ENTRY QueueToExamine,
  384. IN PIRP *CurrentOpIrp,
  385. IN PSERIAL_START_ROUTINE Starter
  386. )
  387. {
  388. KIRQL oldIrql;
  389. IoAcquireCancelSpinLock(&oldIrql);
  390. // If this is a write irp then take the amount of characters
  391. // to write and add it to the count of characters to write.
  392. if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_WRITE)
  393. {
  394. Extension->TotalCharsQueued +=
  395. IoGetCurrentIrpStackLocation(Irp)->Parameters.Write.Length;
  396. } else if ((IoGetCurrentIrpStackLocation(Irp)->MajorFunction
  397. == IRP_MJ_DEVICE_CONTROL) &&
  398. ((IoGetCurrentIrpStackLocation(Irp)
  399. ->Parameters.DeviceIoControl.IoControlCode ==
  400. IOCTL_SERIAL_IMMEDIATE_CHAR) ||
  401. (IoGetCurrentIrpStackLocation(Irp)
  402. ->Parameters.DeviceIoControl.IoControlCode ==
  403. IOCTL_SERIAL_XOFF_COUNTER)))
  404. {
  405. Extension->TotalCharsQueued++; // immediate char
  406. }
  407. if ((IsListEmpty(QueueToExamine)) && !(*CurrentOpIrp))
  408. {
  409. // There was no current operation. Mark this one as
  410. // current and start it up.
  411. *CurrentOpIrp = Irp;
  412. IoReleaseCancelSpinLock(oldIrql);
  413. return Starter(Extension);
  414. }
  415. else
  416. {
  417. // We don't know how long the irp will be in the
  418. // queue. So we need to handle cancel.
  419. if (Irp->Cancel)
  420. {
  421. IoReleaseCancelSpinLock(oldIrql);
  422. Irp->IoStatus.Status = STATUS_CANCELLED;
  423. SerialCompleteRequest(Extension, Irp, 0);
  424. return STATUS_CANCELLED;
  425. }
  426. else
  427. {
  428. Irp->IoStatus.Status = STATUS_PENDING;
  429. IoMarkIrpPending(Irp);
  430. InsertTailList(
  431. QueueToExamine,
  432. &Irp->Tail.Overlay.ListEntry
  433. );
  434. IoSetCancelRoutine( Irp, SerialCancelQueued );
  435. IoReleaseCancelSpinLock(oldIrql);
  436. return STATUS_PENDING;
  437. }
  438. }
  439. }
  440. /*--------------------------------------------------------------------------
  441. SerialCancelQueued -
  442. This routine is used to cancel Irps that currently reside on
  443. a queue.
  444. Arguments:
  445. DeviceObject - Pointer to the device object for this device
  446. Irp - Pointer to the IRP to be canceled.
  447. Return Value:
  448. None.
  449. |--------------------------------------------------------------------------*/
  450. VOID
  451. SerialCancelQueued(
  452. PDEVICE_OBJECT DeviceObject,
  453. PIRP Irp
  454. )
  455. {
  456. PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  457. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  458. Irp->IoStatus.Status = STATUS_CANCELLED;
  459. Irp->IoStatus.Information = 0;
  460. RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  461. // If this is a write irp then take the amount of characters
  462. // to write and subtract it from the count of characters to write.
  463. if (irpSp->MajorFunction == IRP_MJ_WRITE)
  464. {
  465. extension->TotalCharsQueued -= irpSp->Parameters.Write.Length;
  466. }
  467. else if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
  468. {
  469. // If it's an immediate then we need to decrement the
  470. // count of chars queued. If it's a resize then we
  471. // need to deallocate the pool that we're passing on
  472. // to the "resizing" routine.
  473. if ((irpSp->Parameters.DeviceIoControl.IoControlCode ==
  474. IOCTL_SERIAL_IMMEDIATE_CHAR) ||
  475. (irpSp->Parameters.DeviceIoControl.IoControlCode ==
  476. IOCTL_SERIAL_XOFF_COUNTER))
  477. {
  478. extension->TotalCharsQueued--;
  479. }
  480. #ifdef COMMENT_OUT
  481. //#ifdef DYNAMICQUEUE // Dynamic transmit queue size
  482. else if (irpSp->Parameters.DeviceIoControl.IoControlCode ==
  483. IOCTL_SERIAL_SET_QUEUE_SIZE)
  484. {
  485. // We shoved the pointer to the memory into the
  486. // the type 3 buffer pointer which we KNOW we
  487. // never use.
  488. MyAssert(irpSp->Parameters.DeviceIoControl.Type3InputBuffer);
  489. our_free(irpSp->Parameters.DeviceIoControl.Type3InputBuffer);
  490. irpSp->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
  491. }
  492. #endif //DYNAMICQUEUE
  493. }
  494. IoReleaseCancelSpinLock(Irp->CancelIrql);
  495. SerialCompleteRequest(extension, Irp, IO_SERIAL_INCREMENT);
  496. }
  497. /*--------------------------------------------------------------------------
  498. Routine Description:
  499. If the current irp is not an IOCTL_SERIAL_GET_COMMSTATUS request and
  500. there is an error and the application requested abort on errors,
  501. then cancel the irp.
  502. Arguments:
  503. DeviceObject - Pointer to the device object for this device
  504. Irp - Pointer to the IRP to test.
  505. Return Value:
  506. STATUS_SUCCESS or STATUS_CANCELLED.
  507. |--------------------------------------------------------------------------*/
  508. NTSTATUS
  509. SerialCompleteIfError(
  510. PDEVICE_OBJECT DeviceObject,
  511. PIRP Irp
  512. )
  513. {
  514. PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
  515. NTSTATUS status = STATUS_SUCCESS;
  516. if ((extension->HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) &&
  517. extension->ErrorWord)
  518. {
  519. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  520. // There is a current error in the driver. No requests should
  521. // come through except for the GET_COMMSTATUS.
  522. if ((irpSp->MajorFunction != IRP_MJ_DEVICE_CONTROL) ||
  523. (irpSp->Parameters.DeviceIoControl.IoControlCode !=
  524. IOCTL_SERIAL_GET_COMMSTATUS))
  525. {
  526. status = STATUS_CANCELLED;
  527. Irp->IoStatus.Status = STATUS_CANCELLED;
  528. Irp->IoStatus.Information = 0;
  529. SerialCompleteRequest(extension, Irp, 0);
  530. }
  531. }
  532. return status;
  533. }
  534. /*--------------------------------------------------------------------------
  535. Routine Description:
  536. This routine is invoked at dpc level to in response to
  537. a comm error. All comm errors kill all read and writes
  538. Arguments:
  539. Dpc - Not Used.
  540. DeferredContext - Really points to the device object.
  541. SystemContext1 - Not Used.
  542. SystemContext2 - Not Used.
  543. Return Value:
  544. None.
  545. |--------------------------------------------------------------------------*/
  546. VOID
  547. SerialCommError(
  548. IN PKDPC Dpc,
  549. IN PVOID DeferredContext,
  550. IN PVOID SystemContext1,
  551. IN PVOID SystemContext2
  552. )
  553. {
  554. PSERIAL_DEVICE_EXTENSION Extension = DeferredContext;
  555. UNREFERENCED_PARAMETER(Dpc);
  556. UNREFERENCED_PARAMETER(SystemContext1);
  557. UNREFERENCED_PARAMETER(SystemContext2);
  558. SerialKillAllReadsOrWrites(
  559. Extension->DeviceObject,
  560. &Extension->WriteQueue,
  561. &Extension->CurrentWriteIrp
  562. );
  563. SerialKillAllReadsOrWrites(
  564. Extension->DeviceObject,
  565. &Extension->ReadQueue,
  566. &Extension->CurrentReadIrp
  567. );
  568. }
  569. /*--------------------------------------------------------------------------
  570. Routine Description:
  571. This is the dispatch routine for flush. Flushing works by placing
  572. this request in the write queue. When this request reaches the
  573. front of the write queue we simply complete it since this implies
  574. that all previous writes have completed.
  575. Arguments:
  576. DeviceObject - Pointer to the device object for this device
  577. Irp - Pointer to the IRP for the current request
  578. Return Value:
  579. Could return status success, cancelled, or pending.
  580. |--------------------------------------------------------------------------*/
  581. NTSTATUS SerialFlush(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  582. {
  583. PSERIAL_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
  584. ExtTrace(Extension,D_Ioctl,("Flush"))
  585. Irp->IoStatus.Information = 0L;
  586. if (SerialIRPPrologue(Extension) == TRUE)
  587. {
  588. if (Extension->ErrorWord)
  589. {
  590. if (SerialCompleteIfError( DeviceObject, Irp ) != STATUS_SUCCESS)
  591. {
  592. return STATUS_CANCELLED;
  593. }
  594. }
  595. return SerialStartOrQueue(
  596. Extension,
  597. Irp,
  598. &Extension->WriteQueue,
  599. &Extension->CurrentWriteIrp,
  600. SerialStartFlush
  601. );
  602. }
  603. else
  604. {
  605. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  606. return STATUS_NO_SUCH_DEVICE;
  607. }
  608. }
  609. /*--------------------------------------------------------------------------
  610. Routine Description:
  611. This routine is called if there were no writes in the queue.
  612. The flush became the current write because there was nothing
  613. in the queue. Note however that does not mean there is
  614. nothing in the queue now! So, we will start off the write
  615. that might follow us.
  616. Arguments:
  617. Extension - Points to the serial device extension
  618. Return Value:
  619. This will always return STATUS_SUCCESS.
  620. |--------------------------------------------------------------------------*/
  621. NTSTATUS SerialStartFlush(IN PSERIAL_DEVICE_EXTENSION Extension)
  622. {
  623. PIRP NewIrp;
  624. Extension->CurrentWriteIrp->IoStatus.Status = STATUS_SUCCESS;
  625. // The following call will actually complete the flush.
  626. SerialGetNextWrite(
  627. &Extension->CurrentWriteIrp,
  628. &Extension->WriteQueue,
  629. &NewIrp,
  630. TRUE,
  631. Extension
  632. );
  633. if (NewIrp)
  634. {
  635. MyAssert(NewIrp == Extension->CurrentWriteIrp);
  636. SerialStartWrite(Extension);
  637. }
  638. return STATUS_SUCCESS;
  639. }
  640. /*--------------------------------------------------------------------------
  641. SerialStartPurge -
  642. Routine Description:
  643. Depending on the mask in the current irp, purge the interrupt
  644. buffer, the read queue, or the write queue, or all of the above.
  645. Arguments:
  646. Extension - Pointer to the device extension.
  647. Return Value:
  648. Will return STATUS_SUCCESS always. This is reasonable
  649. since the DPC completion code that calls this routine doesn't
  650. care and the purge request always goes through to completion
  651. once it's started.
  652. |--------------------------------------------------------------------------*/
  653. NTSTATUS SerialStartPurge(IN PSERIAL_DEVICE_EXTENSION Extension)
  654. {
  655. PIRP NewIrp;
  656. do
  657. {
  658. ULONG Mask;
  659. Mask = *((ULONG *)
  660. (Extension->CurrentPurgeIrp->AssociatedIrp.SystemBuffer));
  661. if (Mask & SERIAL_PURGE_RXABORT)
  662. {
  663. SerialKillAllReadsOrWrites(
  664. Extension->DeviceObject,
  665. &Extension->ReadQueue,
  666. &Extension->CurrentReadIrp
  667. );
  668. }
  669. if (Mask & SERIAL_PURGE_RXCLEAR)
  670. {
  671. KIRQL OldIrql;
  672. // Flush the Rocket Tx FIFO
  673. KeAcquireSpinLock(
  674. &Extension->ControlLock,
  675. &OldIrql
  676. );
  677. // KeSynchronizeExecution(
  678. // Driver.Interrupt,
  679. // SerialPurgeRxBuffers,
  680. // Extension
  681. // );
  682. SerialPurgeRxBuffers(Extension);
  683. KeReleaseSpinLock(
  684. &Extension->ControlLock,
  685. OldIrql
  686. );
  687. }
  688. if (Mask & SERIAL_PURGE_TXABORT)
  689. {
  690. SerialKillAllReadsOrWrites(
  691. Extension->DeviceObject,
  692. &Extension->WriteQueue,
  693. &Extension->CurrentWriteIrp
  694. );
  695. SerialKillAllReadsOrWrites(
  696. Extension->DeviceObject,
  697. &Extension->WriteQueue,
  698. &Extension->CurrentXoffIrp
  699. );
  700. if (Extension->port_config->WaitOnTx)
  701. {
  702. // if they have this option set, then
  703. // really do a purge of tx hardware buffer.
  704. SerialPurgeTxBuffers(Extension, 1);
  705. }
  706. }
  707. if (Mask & SERIAL_PURGE_TXCLEAR)
  708. {
  709. KIRQL OldIrql;
  710. // Flush the Rocket Rx FIFO and the system side buffer
  711. // Note that we do this under protection of the
  712. // the drivers control lock so that we don't hose
  713. // the pointers if there is currently a read that
  714. // is reading out of the buffer.
  715. KeAcquireSpinLock(&Extension->ControlLock, &OldIrql);
  716. // KeSynchronizeExecution(
  717. // Driver.Interrupt,
  718. // SerialPurgeTxBuffers,
  719. // Extension
  720. // );
  721. if (Extension->port_config->WaitOnTx)
  722. SerialPurgeTxBuffers(Extension, 1); // force
  723. else
  724. SerialPurgeTxBuffers(Extension, 0); // only if flowed off
  725. KeReleaseSpinLock(&Extension->ControlLock, OldIrql);
  726. }
  727. Extension->CurrentPurgeIrp->IoStatus.Status = STATUS_SUCCESS;
  728. Extension->CurrentPurgeIrp->IoStatus.Information = 0;
  729. SerialGetNextIrp(
  730. &Extension->CurrentPurgeIrp,
  731. &Extension->PurgeQueue,
  732. &NewIrp,
  733. TRUE,
  734. Extension
  735. );
  736. } while (NewIrp);
  737. return STATUS_SUCCESS;
  738. }
  739. /*--------------------------------------------------------------------------
  740. Routine Description:
  741. Flushes out the Rx data pipe: Rocket Rx FIFO, Host side Rx buffer
  742. NOTE: This routine is being called from KeSynchronizeExecution.
  743. Arguments:
  744. Context - Really a pointer to the device extension.
  745. |--------------------------------------------------------------------------*/
  746. BOOLEAN SerialPurgeRxBuffers(IN PVOID Context)
  747. {
  748. PSERIAL_DEVICE_EXTENSION Extension = Context;
  749. q_flush(&Extension->RxQ); // flush our rx buffer
  750. #ifdef S_VS
  751. PortFlushRx(Extension->Port); // flush rx hardware
  752. #else
  753. sFlushRxFIFO(Extension->ChP);
  754. //Extension->RxQ.QPut = Extension->RxQ.QGet = 0;
  755. #endif
  756. return FALSE;
  757. }
  758. /*--------------------------------------------------------------------------
  759. Routine Description:
  760. Flushes the Rocket Tx FIFO
  761. NOTE: This routine is being called from KeSynchronizeExecution(not).
  762. Arguments:
  763. Context - Really a pointer to the device extension.
  764. |--------------------------------------------------------------------------*/
  765. BOOLEAN SerialPurgeTxBuffers(IN PVOID Context, int always)
  766. {
  767. PSERIAL_DEVICE_EXTENSION Extension = Context;
  768. /* The stock com-port driver does not purge its hardware queue,
  769. but just ignores TXCLEAR. Since we do flow-control in hardware
  770. buffer and have a larger buffer, we will purge it only if it
  771. is "stuck" or flowed off.
  772. This hopefully provides a somewhat compatible and useful match.
  773. We shouldn't need to check for EV_TXEMPTY here, as the ISR will
  774. take care of this.
  775. */
  776. #ifdef S_VS
  777. // check for tx-flowed off condition
  778. if ((Extension->Port->msr_value & MSR_TX_FLOWED_OFF) || always)
  779. PortFlushTx(Extension->Port); // flush tx hardware
  780. #else
  781. {
  782. int TxCount;
  783. ULONG wstat;
  784. if (always)
  785. {
  786. sFlushTxFIFO(Extension->ChP);
  787. }
  788. else
  789. {
  790. wstat = sGetChanStatusLo(Extension->ChP);
  791. // check for tx-flowed off condition
  792. if ((wstat & (TXFIFOMT | TXSHRMT)) == TXSHRMT)
  793. {
  794. wstat = sGetChanStatusLo(Extension->ChP);
  795. if ((wstat & (TXFIFOMT | TXSHRMT)) == TXSHRMT)
  796. {
  797. TxCount = sGetTxCnt(Extension->ChP);
  798. ExtTrace1(Extension,D_Ioctl,"Purge %d bytes from Hardware.", TxCount);
  799. sFlushTxFIFO(Extension->ChP);
  800. }
  801. }
  802. }
  803. }
  804. #endif
  805. return FALSE;
  806. }
  807. /*--------------------------------------------------------------------------
  808. Routine Description:
  809. This routine is used to query the end of file information on
  810. the opened serial port. Any other file information request
  811. is retured with an invalid parameter.
  812. This routine always returns an end of file of 0.
  813. Arguments:
  814. DeviceObject - Pointer to the device object for this device
  815. Irp - Pointer to the IRP for the current request
  816. Return Value:
  817. The function value is the final status of the call
  818. |--------------------------------------------------------------------------*/
  819. NTSTATUS
  820. SerialQueryInformationFile(
  821. IN PDEVICE_OBJECT DeviceObject,
  822. IN PIRP Irp
  823. )
  824. {
  825. // The status that gets returned to the caller and
  826. // set in the Irp.
  827. NTSTATUS Status;
  828. BOOLEAN acceptingIRPs;
  829. // The current stack location. This contains all of the
  830. // information we need to process this particular request.
  831. PIO_STACK_LOCATION IrpSp;
  832. UNREFERENCED_PARAMETER(DeviceObject);
  833. acceptingIRPs = SerialIRPPrologue((PSERIAL_DEVICE_EXTENSION)DeviceObject->
  834. DeviceExtension);
  835. if (acceptingIRPs == FALSE)
  836. {
  837. Irp->IoStatus.Information = 0;
  838. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  839. SerialCompleteRequest((PSERIAL_DEVICE_EXTENSION)DeviceObject->
  840. DeviceExtension, Irp, IO_NO_INCREMENT);
  841. return STATUS_NO_SUCH_DEVICE;
  842. }
  843. if (SerialCompleteIfError(DeviceObject, Irp) != STATUS_SUCCESS)
  844. {
  845. return STATUS_CANCELLED;
  846. }
  847. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  848. Irp->IoStatus.Information = 0L;
  849. Status = STATUS_SUCCESS;
  850. if (IrpSp->Parameters.QueryFile.FileInformationClass ==
  851. FileStandardInformation)
  852. {
  853. PFILE_STANDARD_INFORMATION Buf = Irp->AssociatedIrp.SystemBuffer;
  854. Buf->AllocationSize = RtlConvertUlongToLargeInteger(0ul);
  855. Buf->EndOfFile = Buf->AllocationSize;
  856. Buf->NumberOfLinks = 0;
  857. Buf->DeletePending = FALSE;
  858. Buf->Directory = FALSE;
  859. Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
  860. }
  861. else if (IrpSp->Parameters.QueryFile.FileInformationClass ==
  862. FilePositionInformation)
  863. {
  864. ((PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->
  865. CurrentByteOffset = RtlConvertUlongToLargeInteger(0ul);
  866. Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
  867. }
  868. else
  869. {
  870. Status = STATUS_INVALID_PARAMETER;
  871. }
  872. Irp->IoStatus.Status = Status;
  873. SerialCompleteRequest((PSERIAL_DEVICE_EXTENSION)DeviceObject->
  874. DeviceExtension, Irp, 0);
  875. return Status;
  876. }
  877. /*--------------------------------------------------------------------------
  878. Routine Description:
  879. This routine is used to set the end of file information on
  880. the opened serial port. Any other file information request
  881. is retured with an invalid parameter.
  882. This routine always ignores the actual end of file since
  883. the query information code always returns an end of file of 0.
  884. Arguments:
  885. DeviceObject - Pointer to the device object for this device
  886. Irp - Pointer to the IRP for the current request
  887. Return Value:
  888. The function value is the final status of the call
  889. |--------------------------------------------------------------------------*/
  890. NTSTATUS
  891. SerialSetInformationFile(
  892. IN PDEVICE_OBJECT DeviceObject,
  893. IN PIRP Irp
  894. )
  895. {
  896. // The status that gets returned to the caller and
  897. // set in the Irp.
  898. NTSTATUS Status;
  899. BOOLEAN acceptingIRPs;
  900. UNREFERENCED_PARAMETER(DeviceObject);
  901. acceptingIRPs = SerialIRPPrologue((PSERIAL_DEVICE_EXTENSION)DeviceObject->
  902. DeviceExtension);
  903. if (acceptingIRPs == FALSE)
  904. {
  905. Irp->IoStatus.Information = 0;
  906. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  907. SerialCompleteRequest((PSERIAL_DEVICE_EXTENSION)DeviceObject->
  908. DeviceExtension, Irp, IO_NO_INCREMENT);
  909. return STATUS_NO_SUCH_DEVICE;
  910. }
  911. if (SerialCompleteIfError( DeviceObject, Irp ) != STATUS_SUCCESS)
  912. {
  913. return STATUS_CANCELLED;
  914. }
  915. Irp->IoStatus.Information = 0L;
  916. if ((IoGetCurrentIrpStackLocation(Irp)->
  917. Parameters.SetFile.FileInformationClass ==
  918. FileEndOfFileInformation) ||
  919. (IoGetCurrentIrpStackLocation(Irp)->
  920. Parameters.SetFile.FileInformationClass ==
  921. FileAllocationInformation))
  922. {
  923. Status = STATUS_SUCCESS;
  924. }
  925. else
  926. {
  927. Status = STATUS_INVALID_PARAMETER;
  928. }
  929. Irp->IoStatus.Status = Status;
  930. SerialCompleteRequest((PSERIAL_DEVICE_EXTENSION)DeviceObject->
  931. DeviceExtension, Irp, 0);
  932. return Status;
  933. }
  934. /*--------------------------------------------------------------------------
  935. UToC1 - Simple convert from NT-Unicode string to c-string.
  936. !!!!!!!Uses a statically(static prefix) allocated buffer!!!!!
  937. This means that it is NOT re-entrant. Which means only one thread can
  938. use this call at a time. Also, a thread could get in trouble if it
  939. tried to use it twice recursively(calling a function that uses this,
  940. which calls a function which uses this.) Since these translator functions
  941. are used mainly during driver initialization and teardown, we do not have
  942. to worry about multiple callers at that time. Any calls which may be
  943. time sliced(port-calls) should not use this routine due to possible
  944. time-slice conflict with another thread. It should allocate a variable
  945. on the stack and use UToCStr().
  946. |--------------------------------------------------------------------------*/
  947. OUT PCHAR UToC1(IN PUNICODE_STRING ustr)
  948. {
  949. // we make it a ULONG to avoid alignment problems(gives ULONG alignment).
  950. static char cstr[140];
  951. return UToCStr(cstr, ustr, sizeof(cstr));
  952. }
  953. /*--------------------------------------------------------------------------
  954. UToCStr -
  955. Purpose: Convert a Unicode string to c-string. Used to easily convert
  956. given a simple char buffer.
  957. Parameters:
  958. Buffer - Working buffer to set up the c-string AND ansi_string struct in.
  959. u_str - unicode string structure.
  960. BufferSize - number of bytes in Buffer which we can use.
  961. Return: pointer to our c-string on success, NULL on err.
  962. |--------------------------------------------------------------------------*/
  963. OUT PCHAR UToCStr(
  964. IN OUT PCHAR Buffer,
  965. IN PUNICODE_STRING ustr,
  966. IN int BufferSize)
  967. {
  968. // assume unicode structure over Buffer.
  969. ANSI_STRING astr;
  970. astr.Buffer = Buffer;
  971. astr.Length = 0;
  972. astr.MaximumLength = BufferSize - 1;
  973. if (RtlUnicodeStringToAnsiString(&astr,ustr,FALSE) == STATUS_SUCCESS)
  974. return Buffer; // ok
  975. MyKdPrint(D_Init,("Bad UToCStr!\n"))
  976. Buffer[0] = 0;
  977. return Buffer;
  978. }
  979. /*--------------------------------------------------------------------------
  980. CToU1 - Simple convert from c-string to NT-Unicode string.
  981. !!!!!!!Uses a statically(static prefix) allocated buffer!!!!!
  982. This means that it is NOT re-entrant. Which means only one thread can
  983. use this call at a time. Also, a thread could get in trouble if it
  984. tried to use it twice recursively(calling a function that uses this,
  985. which calls a function which uses this.) Since these translator functions
  986. are used mainly during driver initialization and teardown, we do not have
  987. to worry about multiple callers at that time. Any calls which may be
  988. time sliced(port-calls) should not use this routine due to possible
  989. time-slice conflict with another thread. It should allocate a variable
  990. on the stack and use CToUStr().
  991. |--------------------------------------------------------------------------*/
  992. OUT PUNICODE_STRING CToU1(IN const char *c_str)
  993. {
  994. // we make it a ULONG to avoid alignment problems(gives ULONG alignment).
  995. static USTR_160 ubuf; // equal to 160 normal chars length
  996. return CToUStr(
  997. (PUNICODE_STRING) &ubuf, // where unicode struct & string gets put
  998. c_str, // our c-string we wish to convert
  999. sizeof(ubuf));
  1000. }
  1001. /*--------------------------------------------------------------------------
  1002. CToU2 - Simple convert from c-string to NT-Unicode string.
  1003. !!!!!!!Uses a statically(static prefix) allocated buffer!!!!!
  1004. This means that it is NOT re-entrant. Which means only one thread can
  1005. use this call at a time. Also, a thread could get in trouble if it
  1006. tried to use it twice recursively(calling a function that uses this,
  1007. which calls a function which uses this.) Since these translator functions
  1008. are used mainly during driver initialization and teardown, we do not have
  1009. to worry about multiple callers at that time. Any calls which may be
  1010. time sliced(port-calls) should not use this routine due to possible
  1011. time-slice conflict with another thread. It should allocate a variable
  1012. on the stack and use CToUStr().
  1013. |--------------------------------------------------------------------------*/
  1014. OUT PUNICODE_STRING CToU2(IN const char *c_str)
  1015. {
  1016. // we make it a ULONG to avoid alignment problems(gives ULONG alignment).
  1017. static USTR_160 ubuf; // equal to 160 normal chars length
  1018. return CToUStr(
  1019. (PUNICODE_STRING) &ubuf, // where unicode struct & string gets put
  1020. c_str, // our c-string we wish to convert
  1021. sizeof(ubuf));
  1022. }
  1023. /*--------------------------------------------------------------------------
  1024. Function: CToUStr
  1025. Purpose: Convert a c-style null-terminated char[] string to a Unicode string
  1026. Parameters:
  1027. Buffer - Working buffer to set up the unicode structure AND
  1028. unicode_string in.
  1029. c_str - normal c-style string.
  1030. BufferSize - number of bytes in Buffer which we can use.
  1031. Return: pointer to our converted UNICODE_STRING on success, NULL on err.
  1032. |-------------------------------------------------------------------------*/
  1033. OUT PUNICODE_STRING CToUStr(
  1034. OUT PUNICODE_STRING Buffer,
  1035. IN const char * c_str,
  1036. IN int BufferSize)
  1037. {
  1038. // assume unicode structure followed by wchar Buffer.
  1039. USTR_40 *us = (USTR_40 *)Buffer;
  1040. ANSI_STRING astr; // ansi structure, temporary go between
  1041. RtlInitAnsiString(&astr, c_str); // c-str to ansi-string struct
  1042. // configure the unicode string to: point the buffer ptr to the wstr.
  1043. us->ustr.Buffer = us->wstr;
  1044. us->ustr.Length = 0;
  1045. us->ustr.MaximumLength = BufferSize - sizeof(UNICODE_STRING);
  1046. // now translate from ansi-c-struct-str to unicode-struct-str
  1047. if (RtlAnsiStringToUnicodeString(&us->ustr,&astr,FALSE) == STATUS_SUCCESS)
  1048. return (PUNICODE_STRING) us; // ok - return ptr
  1049. MyKdPrint(D_Init,("Bad CToUStr!\n"))
  1050. return NULL; // error
  1051. }
  1052. /*--------------------------------------------------------------------------
  1053. Function: WStrToCStr
  1054. Purpose: Convert a wide-string to byte-c-style string.
  1055. Assume wstr is null-terminated.
  1056. |-------------------------------------------------------------------------*/
  1057. VOID WStrToCStr(OUT PCHAR c_str, IN PWCHAR w_str, int max_size)
  1058. {
  1059. int i = 0;
  1060. // assume unicode structure followed by wchar Buffer.
  1061. while ((*w_str != 0) && (i < (max_size-1)))
  1062. {
  1063. *c_str = (CHAR) *w_str;
  1064. ++c_str;
  1065. ++w_str;
  1066. ++i;
  1067. }
  1068. *c_str = 0;
  1069. }
  1070. /*--------------------------------------------------------------------------
  1071. get_reg_value -
  1072. |-------------------------------------------------------------------------*/
  1073. int get_reg_value(
  1074. IN HANDLE keyHandle,
  1075. OUT PVOID outptr,
  1076. IN PCHAR val_name,
  1077. int max_size)
  1078. {
  1079. NTSTATUS status = STATUS_SUCCESS;
  1080. char tmparr[80];
  1081. PKEY_VALUE_PARTIAL_INFORMATION parInfo =
  1082. (PKEY_VALUE_PARTIAL_INFORMATION) &tmparr[0];
  1083. int stat = 0;
  1084. ULONG length = 0;
  1085. USTR_40 ubuf; // equal to 40 normal chars length
  1086. PUNICODE_STRING ustr;
  1087. ustr = CToUStr(
  1088. (PUNICODE_STRING) &ubuf, // where unicode struct & string gets put
  1089. val_name, // our c-string we wish to convert
  1090. sizeof(ubuf));
  1091. if (ustr == NULL)
  1092. return 3; // err
  1093. status = ZwQueryValueKey (keyHandle,
  1094. ustr, // input reg key name
  1095. KeyValuePartialInformation,
  1096. parInfo,
  1097. sizeof(tmparr) -2,
  1098. &length);
  1099. if (NT_SUCCESS(status))
  1100. {
  1101. if (parInfo->Type == REG_SZ)
  1102. {
  1103. tmparr[length] = 0; // null terminate it.
  1104. tmparr[length+1] = 0; // null terminate it.
  1105. WStrToCStr((PCHAR) outptr, (PWCHAR)&parInfo->Data[0], max_size);
  1106. }
  1107. else if (parInfo->Type == REG_DWORD)
  1108. {
  1109. *((ULONG *)outptr) = *((ULONG *) &parInfo->Data[0]);
  1110. }
  1111. else
  1112. {
  1113. stat = 1;
  1114. MyKdPrint(D_Error,("regStrErr56!\n"))
  1115. }
  1116. }
  1117. else
  1118. {
  1119. stat = 2;
  1120. MyKdPrint(D_Error,("regStrErr57!\n"))
  1121. }
  1122. return stat;
  1123. }
  1124. #if DBG
  1125. /*-----------------------------------------------------------------------
  1126. MyAssertMessage - Our Assertion error message. We do our own assert
  1127. because the normal DDK ASSERT() macro only works or reports under
  1128. checked build of NT OS.
  1129. |-----------------------------------------------------------------------*/
  1130. void MyAssertMessage(char *filename, int line)
  1131. {
  1132. MyKdPrint(D_Init,("ASSERT FAILED!!! File %s, line %d !!!!\n", filename, line))
  1133. #ifdef COMMENT_OUT
  1134. char str[40];
  1135. strcpy(str, "FAIL:");
  1136. strcat(str, filename);
  1137. strcat(str, " ln:%d ");
  1138. mess1(str, line);
  1139. #endif
  1140. }
  1141. #endif
  1142. /*-----------------------------------------------------------------------
  1143. EvLog - EvLog an event to NT's event log.
  1144. |-----------------------------------------------------------------------*/
  1145. void EvLog(char *mess)
  1146. {
  1147. static USTR_160 ubuf; // our own private buffer(static)
  1148. UNICODE_STRING *u;
  1149. NTSTATUS event_type;
  1150. if (mess == NULL)
  1151. {
  1152. MyKdPrint(D_Init,("EvLog Err1!\n"))
  1153. return;
  1154. }
  1155. if ((mess[0] == 'E') && (mess[1] == 'r')) // "Error..."
  1156. event_type = SERIAL_CUSTOM_ERROR_MESSAGE;
  1157. else if ((mess[0] == 'W') && (mess[1] == 'a')) // "Warning..."
  1158. event_type = SERIAL_CUSTOM_ERROR_MESSAGE;
  1159. else
  1160. event_type = SERIAL_CUSTOM_INFO_MESSAGE;
  1161. u = CToUStr(
  1162. (PUNICODE_STRING) &ubuf, // where unicode struct & string gets put
  1163. mess, // our c-string we wish to convert
  1164. sizeof(ubuf));
  1165. if (u==NULL)
  1166. {
  1167. MyKdPrint(D_Init,("EvLog Err2!\n"))
  1168. return;
  1169. }
  1170. // MyKdPrint(D_Init,("EvLog Size:%d, messsize:%d!\n",u->Length, strlen(mess) ))
  1171. EventLog(Driver.GlobalDriverObject,
  1172. STATUS_SUCCESS,
  1173. event_type, // red"stop" or blue"i"..
  1174. u->Length + sizeof(WCHAR),
  1175. u->Buffer);
  1176. }
  1177. /*-------------------------------------------------------------------
  1178. | our_ultoa -
  1179. |--------------------------------------------------------------------*/
  1180. char * our_ultoa(unsigned long u, char* s, int radix)
  1181. {
  1182. long pow, prevpow;
  1183. int digit;
  1184. char* p;
  1185. if ( (radix < 2) || (36 < radix) )
  1186. {
  1187. *s = 0;
  1188. return s;
  1189. }
  1190. if (u == 0)
  1191. {
  1192. s[0] = '0';
  1193. s[1] = 0;
  1194. return s;
  1195. }
  1196. p = s;
  1197. for (prevpow=0, pow=1; (u >= (unsigned long)pow) && (prevpow < pow); pow *= radix)
  1198. prevpow=pow;
  1199. pow = prevpow;
  1200. while (pow != 0)
  1201. {
  1202. digit = u/pow;
  1203. *p = (digit <= 9) ? ('0'+digit) : ( ('a'-10)+digit);
  1204. p++;
  1205. u -= digit*pow;
  1206. pow /= radix;
  1207. }
  1208. *p = 0;
  1209. return s;
  1210. }
  1211. /*-------------------------------------------------------------------
  1212. | our_ltoa -
  1213. |--------------------------------------------------------------------*/
  1214. char * our_ltoa(long value, char* s, int radix)
  1215. {
  1216. unsigned long u;
  1217. long pow, prevpow;
  1218. int digit;
  1219. char* p;
  1220. if ( (radix < 2) || (36 < radix) )
  1221. {
  1222. *s = 0;
  1223. return s;
  1224. }
  1225. if (value == 0)
  1226. {
  1227. s[0] = '0';
  1228. s[1] = 0;
  1229. return s;
  1230. }
  1231. p = s;
  1232. if ( (radix == 10) && (value < 0) )
  1233. {
  1234. *p++ = '-';
  1235. value = -value;
  1236. }
  1237. *(long*)&u = value;
  1238. for (prevpow=0, pow=1; (u >= (unsigned long)pow) && (prevpow < pow); pow *= radix)
  1239. prevpow=pow;
  1240. pow = prevpow;
  1241. while (pow != 0)
  1242. {
  1243. digit = u/pow;
  1244. *p = (digit <= 9) ? ('0'+digit) : ( ('a'-10)+digit);
  1245. p++;
  1246. u -= digit*pow;
  1247. pow /= radix;
  1248. }
  1249. *p = 0;
  1250. return s;
  1251. }
  1252. /*-------------------------------------------------------------------
  1253. | our_assert -
  1254. |--------------------------------------------------------------------*/
  1255. void our_assert(int id, int line)
  1256. {
  1257. Tprintf("Assert %d line:%d!", id, line);
  1258. }
  1259. /*-------------------------------------------------------------------
  1260. | TTprintf - Trace printf with prefix. Dump trace messages to debug port.
  1261. With TRACE_PORT turned on, this allows us to use a spare port for
  1262. tracing another.
  1263. |--------------------------------------------------------------------*/
  1264. void __cdecl TTprintf(char *leadstr, const char *format, ...)
  1265. {
  1266. #ifdef TRACE_PORT
  1267. #endif
  1268. char temp[120];
  1269. va_list Next;
  1270. int sCount, ls;
  1271. ls = strlen(leadstr);
  1272. memcpy(temp, leadstr, ls);
  1273. temp[ls++] = ' ';
  1274. va_start(Next, format);
  1275. our_vsnprintf(&temp[ls], 78, format, Next);
  1276. sCount = strlen(temp);
  1277. temp[sCount++] = '[';
  1278. our_ultoa( (long) Driver.PollCnt, &temp[sCount], 10);
  1279. sCount += strlen(&temp[sCount]);
  1280. temp[sCount++] = ']';
  1281. temp[sCount++] = 0xd;
  1282. temp[sCount++] = 0xa;
  1283. temp[sCount] = 0;
  1284. TracePut(temp, sCount);
  1285. // dump out to normal nt debug console
  1286. DbgPrint(temp);
  1287. }
  1288. /*-------------------------------------------------------------------
  1289. | Tprintf - Trace printf. Dump trace messages to debug port.
  1290. With TRACE_PORT turned on, this allows us to use a spare port for
  1291. tracing another.
  1292. |--------------------------------------------------------------------*/
  1293. void __cdecl Tprintf(const char *format, ...)
  1294. {
  1295. #ifdef TRACE_PORT
  1296. #endif
  1297. char temp[100];
  1298. va_list Next;
  1299. int sCount;
  1300. va_start(Next, format);
  1301. our_vsnprintf(temp, 78, format, Next);
  1302. sCount = strlen(temp);
  1303. temp[sCount++] = '[';
  1304. our_ultoa( (long) Driver.PollCnt, &temp[sCount], 10);
  1305. sCount += strlen(&temp[sCount]);
  1306. temp[sCount++] = ']';
  1307. temp[sCount++] = 0xd;
  1308. temp[sCount++] = 0xa;
  1309. temp[sCount] = 0;
  1310. TracePut(temp, sCount);
  1311. // dump out to normal nt debug console
  1312. DbgPrint(temp);
  1313. }
  1314. /*-------------------------------------------------------------------
  1315. | OurTrace - Trace, put data into debug ports buffer.
  1316. |--------------------------------------------------------------------*/
  1317. void OurTrace(char *leadstr, char *newdata)
  1318. {
  1319. char temp[86];
  1320. int ls, ds;
  1321. ls = strlen(leadstr);
  1322. if (ls > 20)
  1323. ls = 20;
  1324. ds = strlen(newdata);
  1325. if (ds > 60)
  1326. ds = 60;
  1327. memcpy(temp, leadstr, ls);
  1328. temp[ls++] = ' ';
  1329. memcpy(&temp[ls], newdata, ds);
  1330. ds += ls;
  1331. temp[ds++] = 0xd;
  1332. temp[ds++] = 0xa;
  1333. temp[ds] = 0;
  1334. TracePut(temp, ds);
  1335. // dump out to normal nt debug console
  1336. DbgPrint(temp);
  1337. }
  1338. /*-------------------------------------------------------------------
  1339. | TraceDump - Trace, put data into debug ports buffer.
  1340. |--------------------------------------------------------------------*/
  1341. void TraceDump(PSERIAL_DEVICE_EXTENSION ext, char *newdata, int sCount, int style)
  1342. {
  1343. int len,i,j;
  1344. char trace_buf[50];
  1345. len = sCount;
  1346. j = 0;
  1347. trace_buf[j++] = ' ';
  1348. trace_buf[j++] = 'D';
  1349. trace_buf[j++] = 'A';
  1350. trace_buf[j++] = 'T';
  1351. trace_buf[j++] = 'A';
  1352. trace_buf[j++] = ':';
  1353. // dump data into the trace buffer in a hex or ascii dump format
  1354. if (len > 32) len = 32;
  1355. for (i=0; i<len; i++)
  1356. {
  1357. trace_buf[j] = (CHAR) newdata[i];
  1358. if ((trace_buf[j] < 0x20) || (trace_buf[j] > 0x80))
  1359. trace_buf[j] = '.';
  1360. ++j;
  1361. }
  1362. trace_buf[j++] = 0xd;
  1363. trace_buf[j++] = 0xa;
  1364. trace_buf[j] = 0;
  1365. TracePut(trace_buf, j);
  1366. }
  1367. /*-------------------------------------------------------------------
  1368. | TracePut - Trace, put data into debug ports buffer.
  1369. |--------------------------------------------------------------------*/
  1370. void TracePut(char *newdata, int sCount)
  1371. {
  1372. #ifdef TRACE_PORT
  1373. // int RxFree,i;
  1374. KIRQL controlIrql;
  1375. // PSERIAL_DEVICE_EXTENSION extension;
  1376. // drop this into our debug queue...
  1377. //----- THIS COMES BACK AS DISPATCH_LEVEL OR PASSIVE LEVEL, is it
  1378. //----- SAFE FOR SPINLOCK TO HAVE BOTH ??????
  1379. //-- YES, SpinLocks meant for calling when <= DISPATCH_LEVEL
  1380. #if DBG
  1381. if ((KeGetCurrentIrql() != DISPATCH_LEVEL) &&
  1382. (KeGetCurrentIrql() != PASSIVE_LEVEL))
  1383. {
  1384. MyKdPrint(D_Error, ("BAD IRQL:%d ", KeGetCurrentIrql(), newdata))
  1385. return;
  1386. }
  1387. #endif
  1388. if (sCount == 0)
  1389. sCount = strlen(newdata);
  1390. KeAcquireSpinLock(&Driver.DebugLock, &controlIrql);
  1391. q_put(&Driver.DebugQ, (BYTE *) newdata, sCount);
  1392. KeReleaseSpinLock(&Driver.DebugLock, controlIrql);
  1393. #endif
  1394. }
  1395. /*-------------------------------------------------------------------
  1396. | Dprintf -
  1397. |--------------------------------------------------------------------*/
  1398. void __cdecl Dprintf(const char *format, ...)
  1399. {
  1400. char temp[100];
  1401. va_list Next;
  1402. va_start(Next, format);
  1403. our_vsnprintf(temp, 100, format, Next);
  1404. // EvLog(temp);
  1405. // dump out to normal nt debug console
  1406. DbgPrint(temp);
  1407. DbgPrint("\n");
  1408. }
  1409. /*-------------------------------------------------------------------
  1410. | Sprintf -
  1411. |--------------------------------------------------------------------*/
  1412. void __cdecl Sprintf(char *dest, const char *format, ...)
  1413. {
  1414. va_list Next;
  1415. va_start(Next, format);
  1416. our_vsnprintf(dest, 80, format, Next);
  1417. }
  1418. /*-------------------------------------------------------------------
  1419. | Eprintf -
  1420. |--------------------------------------------------------------------*/
  1421. void __cdecl Eprintf(const char *format, ...)
  1422. {
  1423. char temp[80];
  1424. va_list Next;
  1425. va_start(Next, format);
  1426. our_vsnprintf(temp, 79, format, Next);
  1427. if (KeGetCurrentIrql() == PASSIVE_LEVEL) {
  1428. EvLog(temp);
  1429. }
  1430. strcat(temp, "\n");
  1431. DbgPrint(temp);
  1432. }
  1433. /*-------------------------------------------------------------------
  1434. | our_vsnprintf -
  1435. |--------------------------------------------------------------------*/
  1436. int __cdecl our_vsnprintf(char *buffer, size_t Limit, const char *format, va_list Next)
  1437. {
  1438. #ifndef BOOL
  1439. #define BOOL int
  1440. #endif
  1441. int InitLimit = Limit; // Limit at entry point
  1442. BOOL bMore; // Loop control
  1443. int Width; // Optional width
  1444. int Precision; // Optional precision
  1445. char *str; // String
  1446. char strbuf[36]; // Constructed string
  1447. int len; // Length of string
  1448. int nLeadingZeros; // Number of leading zeros required
  1449. int nPad; // Number of pad characters required
  1450. char cPad; // Current pad character ('0' or ' ')
  1451. char *sPrefix; // Prefix string
  1452. unsigned long val; // Value of current number
  1453. BOOL bLeftJustify; // Justification
  1454. BOOL bPlusSign; // Show plus sign?
  1455. BOOL bBlankSign; // Blank for positives?
  1456. BOOL bZeroPrefix; // Want 0x for hex, 0 for octal?
  1457. BOOL bIsShort; // TRUE if short
  1458. BOOL bIsLong; // TRUE if long
  1459. #define PUTONE(c) if (Limit) { --Limit; *buffer++ = c; } else c;
  1460. #define fLeftJustify (1 << 0)
  1461. #define fPlusSign (1 << 1)
  1462. #define fZeroPad (1 << 2)
  1463. #define fBlankSign (1 << 3)
  1464. #define fPrefixOX (1 << 4)
  1465. #define fIsShort (1 << 5)
  1466. #define fIsLong (1 << 6)
  1467. if (Limit == 0)
  1468. return -1;
  1469. Limit--; // Leave room for terminating NULL
  1470. while (*format != '\0')
  1471. {
  1472. // Everything but '%' is copied to buffer
  1473. if (*format != '%')
  1474. // '%' gets special handling here
  1475. PUTONE(*format++)
  1476. else
  1477. {
  1478. // Set default flags, etc
  1479. Width = 0;
  1480. Precision = -1;
  1481. cPad = ' ';
  1482. bLeftJustify = FALSE;
  1483. bPlusSign = FALSE;
  1484. bBlankSign = FALSE;
  1485. bZeroPrefix = FALSE;
  1486. bIsShort = FALSE;
  1487. bIsLong = FALSE;
  1488. sPrefix = "";
  1489. format++;
  1490. bMore = TRUE;
  1491. while (bMore)
  1492. {
  1493. // optional flags
  1494. switch (*format)
  1495. {
  1496. case '-': bLeftJustify = TRUE; format++; break;
  1497. case '+': bPlusSign = TRUE; format++; break;
  1498. case '0': cPad = '0'; format++; break;
  1499. case ' ': bBlankSign = TRUE; format++; break;
  1500. case '#': bZeroPrefix = TRUE; format++; break;
  1501. default: bMore = FALSE;
  1502. }
  1503. }
  1504. // optional width
  1505. if (*format == '*')
  1506. {
  1507. Width = (int) va_arg(Next, int);
  1508. format++;
  1509. }
  1510. else if (our_isdigit(*format))
  1511. {
  1512. while (our_isdigit(*format))
  1513. {
  1514. Width *= 10;
  1515. Width += (*format++) - '0';
  1516. }
  1517. }
  1518. // optional precision
  1519. if (*format == '.')
  1520. {
  1521. format++;
  1522. Precision = 0;
  1523. if (*format == '*')
  1524. {
  1525. Precision = (int) va_arg(Next, int);
  1526. format++;
  1527. }
  1528. else while (our_isdigit(*format))
  1529. {
  1530. Precision *= 10;
  1531. Precision += (*format++) - '0';
  1532. }
  1533. }
  1534. // optional size
  1535. switch (*format)
  1536. {
  1537. case 'h': bIsShort = TRUE; format++; break;
  1538. case 'l': bIsLong = TRUE; format++; break;
  1539. }
  1540. // All controls are completed, dispatch on the conversion character
  1541. switch (*format++)
  1542. {
  1543. case 'd':
  1544. case 'i':
  1545. if (bIsLong) // Signed long int
  1546. our_ltoa( (long) va_arg(Next, long), strbuf, 10);
  1547. else // Signed int
  1548. our_ltoa( (long) va_arg(Next, int), strbuf, 10);
  1549. // _itoa( (int) va_arg(Next, int), strbuf, 10);
  1550. if (strbuf[0] == '-')
  1551. sPrefix = "-";
  1552. else
  1553. {
  1554. if (bPlusSign)
  1555. sPrefix = "+";
  1556. else if (bBlankSign)
  1557. sPrefix = " ";
  1558. }
  1559. goto EmitNumber;
  1560. case 'u':
  1561. if (bIsLong) // Unsigned long int
  1562. our_ultoa( (long) va_arg(Next, long), strbuf, 10);
  1563. else // Unsigned int
  1564. our_ultoa( (long) (int) va_arg(Next, int), strbuf, 10);
  1565. goto EmitNumber;
  1566. // set sPrefix for these...
  1567. case 'o':
  1568. if (bZeroPrefix)
  1569. sPrefix = "0";
  1570. if (bIsLong)
  1571. val = (long) va_arg(Next, long);
  1572. else
  1573. val = (int) va_arg(Next, int);
  1574. our_ultoa(val, strbuf, 8);
  1575. if (val == 0)
  1576. sPrefix = "";
  1577. goto EmitNumber;
  1578. case 'x':
  1579. case 'X':
  1580. if (bZeroPrefix)
  1581. sPrefix = "0x";
  1582. if (bIsLong)
  1583. val = (unsigned long) va_arg(Next, long);
  1584. else
  1585. val = (unsigned int) va_arg(Next, int);
  1586. our_ultoa(val, strbuf, 16);
  1587. if (val == 0)
  1588. sPrefix = "";
  1589. goto EmitNumber;
  1590. case 'c':
  1591. strbuf[0] = (char) va_arg(Next, char);
  1592. str = strbuf;
  1593. len = 1;
  1594. goto EmitString;
  1595. case 's':
  1596. str = (char *) va_arg(Next, char*);
  1597. len = strlen(str);
  1598. if (Precision != -1 &&
  1599. Precision < len)
  1600. len = Precision;
  1601. goto EmitString;
  1602. case 'n':
  1603. case 'p':
  1604. break;
  1605. case '%':
  1606. strbuf[0] = '%';
  1607. str = strbuf;
  1608. len = 1;
  1609. goto EmitString;
  1610. break;
  1611. case 'f':
  1612. case 'e':
  1613. case 'E':
  1614. case 'g':
  1615. case 'G':
  1616. str = "<float format not supported>";
  1617. len = strlen(str);
  1618. goto EmitString;
  1619. default:
  1620. str = "<bad format character>";
  1621. len = strlen(str);
  1622. goto EmitString;
  1623. }
  1624. EmitNumber:
  1625. if (Precision == -1)
  1626. Precision = 1;
  1627. str = strbuf;
  1628. if (*str == '-')
  1629. str++; // if negative, already have prefix
  1630. len = strlen(str);
  1631. nLeadingZeros = Precision - len;
  1632. if (nLeadingZeros < 0)
  1633. nLeadingZeros = 0;
  1634. nPad = Width - (len + nLeadingZeros + strlen(sPrefix));
  1635. if (nPad < 0)
  1636. nPad = 0;
  1637. if (nPad && !bLeftJustify)
  1638. {
  1639. // Left padding required
  1640. while (nPad--)
  1641. {
  1642. PUTONE(cPad);
  1643. }
  1644. nPad = 0; // Indicate padding completed
  1645. }
  1646. while (*sPrefix != '\0')
  1647. PUTONE(*sPrefix++);
  1648. while (nLeadingZeros-- > 0)
  1649. PUTONE('0');
  1650. while (len-- > 0)
  1651. {
  1652. PUTONE(*str++);
  1653. }
  1654. if (nPad)
  1655. {
  1656. // Right padding required
  1657. while (nPad--)
  1658. PUTONE(' ');
  1659. }
  1660. goto Done;
  1661. EmitString:
  1662. // Here we have the string ready to emit. Handle padding, etc.
  1663. if (Width > len)
  1664. nPad = Width - len;
  1665. else
  1666. nPad = 0;
  1667. if (nPad && !bLeftJustify)
  1668. {
  1669. // Left padding required
  1670. while (nPad--)
  1671. PUTONE(cPad);
  1672. }
  1673. while (len-- > 0)
  1674. PUTONE(*str++);
  1675. if (nPad)
  1676. {
  1677. // Right padding required
  1678. while (nPad--)
  1679. PUTONE(' ');
  1680. }
  1681. Done: ;
  1682. }
  1683. }
  1684. *buffer = '\0';
  1685. return InitLimit - Limit - 1; // Don't count terminating NULL
  1686. }
  1687. /*-------------------------------------------------------------------
  1688. | our_isdigit -
  1689. |--------------------------------------------------------------------*/
  1690. int our_isdigit(char c)
  1691. {
  1692. if ((c >= '0') && (c <= '9'))
  1693. return 1;
  1694. return 0;
  1695. }
  1696. /*-----------------------------------------------------------------
  1697. listfind - find matching string in list. List is null terminated.
  1698. |------------------------------------------------------------------*/
  1699. int listfind(char *str, char **list)
  1700. {
  1701. int i=0;
  1702. for (i=0; list[i] != NULL; i++)
  1703. {
  1704. if (my_lstricmp(str, list[i]) == 0) // match
  1705. return i;
  1706. }
  1707. return -1;
  1708. }
  1709. /*-----------------------------------------------------------------
  1710. getnum - get a number. Hex or Dec.
  1711. |------------------------------------------------------------------*/
  1712. int getnum(char *str, int *index)
  1713. {
  1714. int i,val;
  1715. int ch_i;
  1716. *index = 0;
  1717. ch_i = 0;
  1718. while (*str == ' ')
  1719. {
  1720. ++str;
  1721. ++ch_i;
  1722. }
  1723. if ((*str == '0') && (my_toupper(str[1]) == 'X'))
  1724. {
  1725. str += 2;
  1726. ch_i += 2;
  1727. val = (int) gethint(str,&i);
  1728. if (i==0)
  1729. return 0;
  1730. }
  1731. else
  1732. {
  1733. val = getint(str,&i);
  1734. if (i==0)
  1735. return 0;
  1736. }
  1737. ch_i += i;
  1738. *index = ch_i; // num bytes consumed
  1739. return val;
  1740. }
  1741. /*-----------------------------------------------------------------
  1742. getnumbers - get numbers from string, comma or space delimited.
  1743. return number of integers read.
  1744. |------------------------------------------------------------------*/
  1745. int getnumbers(char *str, long *nums, int max_nums, int hex_flag)
  1746. {
  1747. // int stat;
  1748. int i,j, num_cnt;
  1749. ULONG *wnums = (ULONG *)nums;
  1750. i = 0;
  1751. num_cnt = 0;
  1752. while (num_cnt < max_nums)
  1753. {
  1754. while ((str[i] == ' ') || (str[i] == ',') || (str[i] == ':'))
  1755. ++i;
  1756. if (hex_flag)
  1757. wnums[num_cnt] = gethint(&str[i], &j);
  1758. else
  1759. nums[num_cnt] = getint(&str[i], &j);
  1760. i += j;
  1761. if (j == 0) return num_cnt;
  1762. else ++num_cnt;
  1763. }
  1764. return num_cnt;
  1765. }
  1766. /*-----------------------------------------------------------------
  1767. my_lstricmp -
  1768. |------------------------------------------------------------------*/
  1769. int my_lstricmp(char *str1, char *str2)
  1770. {
  1771. if ((str1 == NULL) || (str2 == NULL))
  1772. return 1; // not a match
  1773. if ((*str1 == 0) || (*str2 == 0))
  1774. return 1; // not a match
  1775. while ( (my_toupper(*str1) == my_toupper(*str2)) &&
  1776. (*str1 != 0) && (*str2 != 0))
  1777. {
  1778. ++str1;
  1779. ++str2;
  1780. }
  1781. if ((*str1 == 0) && (*str2 == 0))
  1782. return 0; // ok match
  1783. return 1; // no match
  1784. }
  1785. /*-----------------------------------------------------------------
  1786. my_sub_lstricmp -
  1787. |------------------------------------------------------------------*/
  1788. int my_sub_lstricmp(const char *name, const char *codeline)
  1789. {
  1790. int c;
  1791. if ((name == NULL) || (codeline == NULL))
  1792. return 1; // not a match
  1793. if ((*name == 0) || (*codeline == 0))
  1794. return 1; // not a match
  1795. while ( (my_toupper(*name) == my_toupper(*codeline)) &&
  1796. (*name != 0) && (*codeline != 0))
  1797. {
  1798. ++name;
  1799. ++codeline;
  1800. }
  1801. // return if either is at end of string
  1802. if (*name == 0)
  1803. {
  1804. c = my_toupper(*codeline);
  1805. if ((c <= 'Z') && (c >= 'A'))
  1806. return 1; // not a match
  1807. if (c == '_')
  1808. return 1; // not a match
  1809. return 0; // ok match
  1810. }
  1811. return 1; // no match
  1812. }
  1813. /*------------------------------------------------------------------------
  1814. | getstr - grab a text string parameter off a command line.
  1815. |-----------------------------------------------------------------------*/
  1816. int getstr(char *deststr, char *textptr, int *countptr, int max_size)
  1817. {
  1818. // int number;
  1819. int tempcount, i;
  1820. *deststr = 0;
  1821. tempcount = 0;
  1822. while ((*textptr == ' ') || (*textptr == ','))
  1823. {
  1824. ++textptr;
  1825. ++tempcount;
  1826. }
  1827. i = 0;
  1828. while ((*textptr != 0) && (*textptr != ' ') && (*textptr != ',') &&
  1829. (i < max_size) )
  1830. {
  1831. *deststr++ = *textptr;
  1832. ++textptr;
  1833. ++tempcount;
  1834. ++i;
  1835. }
  1836. *deststr = 0;
  1837. *countptr = tempcount;
  1838. return 0;
  1839. }
  1840. /*------------------------------------------------------------------------
  1841. | getint -
  1842. |-----------------------------------------------------------------------*/
  1843. int getint(char *textptr, int *countptr)
  1844. {
  1845. int number;
  1846. int tempcount;
  1847. int negate = 0;
  1848. int digit_cnt = 0;
  1849. tempcount = 0;
  1850. number = 0;
  1851. while (*textptr == 0x20)
  1852. {
  1853. ++textptr;
  1854. ++tempcount;
  1855. }
  1856. if (*textptr == '-')
  1857. {
  1858. ++textptr;
  1859. ++tempcount;
  1860. negate = 1;
  1861. }
  1862. while ( ((*textptr >= 0x30) && (*textptr <= 0x39)) )
  1863. {
  1864. number = (number * 10) + ( *textptr & 0x0f);
  1865. ++textptr;
  1866. ++tempcount;
  1867. ++digit_cnt;
  1868. }
  1869. if (digit_cnt == 0)
  1870. {
  1871. tempcount = 0;
  1872. number = 0;
  1873. }
  1874. if (countptr)
  1875. *countptr = tempcount;
  1876. if (negate)
  1877. return (-number);
  1878. return number;
  1879. } /* getint */
  1880. /*------------------------------------------------------------------------
  1881. | gethint - for finding hex words.
  1882. |-----------------------------------------------------------------------*/
  1883. unsigned int gethint(char *bufptr, int *countptr)
  1884. {
  1885. unsigned int count;
  1886. unsigned char temphex;
  1887. unsigned int number;
  1888. int digit_cnt = 0;
  1889. number = 0;
  1890. count = 0;
  1891. while (*bufptr == 0x20)
  1892. {
  1893. ++bufptr;
  1894. ++count;
  1895. }
  1896. while ( ((*bufptr >= 0x30) && (*bufptr <= 0x39))
  1897. ||
  1898. ((my_toupper(*bufptr) >= 0x41) && (my_toupper(*bufptr) <= 0x46)) )
  1899. {
  1900. if (*bufptr > 0x39)
  1901. temphex = (my_toupper(*bufptr) & 0x0f) + 9;
  1902. else
  1903. temphex = *bufptr & 0x0f;
  1904. number = (number * 16) + temphex;
  1905. ++bufptr;
  1906. ++count;
  1907. ++digit_cnt;
  1908. }
  1909. if (digit_cnt == 0)
  1910. {
  1911. count = 0;
  1912. number = 0;
  1913. }
  1914. if (countptr)
  1915. *countptr = count;
  1916. return number;
  1917. } /* gethint */
  1918. /*-----------------------------------------------------------------
  1919. my_toupper - to upper case
  1920. |------------------------------------------------------------------*/
  1921. int my_toupper(int c)
  1922. {
  1923. if ((c >= 'a') && (c <= 'z'))
  1924. return ((c-'a') + 'A');
  1925. else return c;
  1926. }
  1927. /*----------------------------------------------------------------------------
  1928. | hextoa -
  1929. |----------------------------------------------------------------------------*/
  1930. void hextoa(char *str, unsigned int v, int places)
  1931. {
  1932. while (places > 0)
  1933. {
  1934. --places;
  1935. if ((v & 0xf) < 0xa)
  1936. str[places] = '0' + (v & 0xf);
  1937. else
  1938. str[places] = 'A' + (v & 0xf) - 0xa;
  1939. v >>= 4;
  1940. }
  1941. }
  1942. //#define DUMP_MEM
  1943. #if DBG
  1944. #define TRACK_MEM
  1945. #endif
  1946. /*----------------------------------------------------------------------------
  1947. | our_free -
  1948. |----------------------------------------------------------------------------*/
  1949. void our_free(PVOID ptr, char *str)
  1950. {
  1951. #ifdef TRACK_MEM
  1952. ULONG size;
  1953. BYTE *bptr;
  1954. if (ptr == NULL)
  1955. {
  1956. MyKdPrint(D_Error, ("MemFree Null Error\n"))
  1957. //Tprintf("ERR,MemNull Err!");
  1958. return;
  1959. }
  1960. bptr = ptr;
  1961. bptr -= 16;
  1962. if (*((DWORD *)bptr) != 0x1111) // frame it with something we can check
  1963. {
  1964. MyKdPrint(D_Error, ("MemFree Frame Error\n"))
  1965. //Tprintf("ERR, MemFree Frame!");
  1966. }
  1967. bptr += 4;
  1968. size = *((DWORD *)bptr); // frame it with something we can check
  1969. bptr -= 4;
  1970. Driver.mem_alloced -= size; // track how much memory we are using
  1971. #ifdef DUMP_MEM
  1972. MyKdPrint(D_Init, ("Free:%x(%d),%s, [T:%d]\n",bptr, size, str, Driver.mem_alloced))
  1973. //Tprintf("Free:%x(%d),%s, [T:%d]",bptr, size, str, Driver.mem_alloced);
  1974. #endif
  1975. ExFreePool(bptr);
  1976. #else
  1977. ExFreePool(ptr);
  1978. #endif
  1979. }
  1980. /*----------------------------------------------------------------------------
  1981. | our_locked_alloc -
  1982. |----------------------------------------------------------------------------*/
  1983. PVOID our_locked_alloc(ULONG size, char *str)
  1984. {
  1985. BYTE *bptr;
  1986. #ifdef TRACK_MEM
  1987. int i;
  1988. size += 16;
  1989. #endif
  1990. bptr = ExAllocatePool(NonPagedPool, size);
  1991. if (bptr == NULL)
  1992. {
  1993. MyKdPrint(D_Error, ("MemCreate Fail\n"))
  1994. //Tprintf("ERR, MemCreate Error!");
  1995. return NULL;
  1996. }
  1997. RtlZeroMemory(bptr, size);
  1998. #ifdef TRACK_MEM
  1999. #ifdef DUMP_MEM
  2000. MyKdPrint(D_Init, ("Alloc:%x(%d),%s\n",bptr, size, str))
  2001. //Tprintf("Alloc:%x(%d),%s",bptr, size, str);
  2002. #endif
  2003. *((DWORD *)bptr) = 0x1111; // frame it with something we can check
  2004. bptr += 4;
  2005. *((DWORD *)bptr) = size;
  2006. bptr += 4;
  2007. for (i=0; i<4; i++) // copy the name
  2008. {
  2009. bptr[i] = str[i];
  2010. if (str[i] == 0)
  2011. break;
  2012. }
  2013. bptr += 8;
  2014. #endif
  2015. Driver.mem_alloced += size; // track how much memory we are using
  2016. return bptr;
  2017. }
  2018. #ifdef S_VS
  2019. /*----------------------------------------------------------------------
  2020. mac_cmp - compare two 6-byte mac addresses, return -1 if mac1 < ma2,
  2021. 0 if mac1==mac2, 1 if mac1 > mac2.
  2022. |----------------------------------------------------------------------*/
  2023. int mac_cmp(UCHAR *mac1, UCHAR *mac2)
  2024. {
  2025. int i;
  2026. for (i=0; i<6; i++)
  2027. {
  2028. if (mac1[i] != mac2[i])
  2029. {
  2030. if (mac1[i] < mac2[i])
  2031. return -1;
  2032. else
  2033. return 1;
  2034. }
  2035. }
  2036. return 0; // same
  2037. }
  2038. #endif
  2039. /*----------------------------------------------------------------------
  2040. time_stall -
  2041. |----------------------------------------------------------------------*/
  2042. void time_stall(int tenth_secs)
  2043. {
  2044. int i;
  2045. LARGE_INTEGER WaitTime; // Actual time req'd for buffer to drain
  2046. // set wait-time to .1 second.(-1000 000 = relative(-), 100-ns units)
  2047. WaitTime.QuadPart = -1000000L * tenth_secs;
  2048. KeDelayExecutionThread(KernelMode,FALSE,&WaitTime);
  2049. #if 0
  2050. // this is wasteing resources, see new version above
  2051. // wait .4 seconds for response
  2052. for (i=0; i<tenth_secs; i++)
  2053. {
  2054. // set wait-time to .1 second.(-1000 000 = relative(-), 100-ns units)
  2055. //WaitTime = RtlConvertLongToLargeInteger(-1000000L);
  2056. // set wait-time to .1 second.(-1000 000 = relative(-), 100-ns units)
  2057. WaitTime.QuadPart = -1000000L;
  2058. KeDelayExecutionThread(KernelMode,FALSE,&WaitTime);
  2059. }
  2060. #endif
  2061. }
  2062. /*----------------------------------------------------------------------
  2063. ms_time_stall -
  2064. |----------------------------------------------------------------------*/
  2065. void ms_time_stall(int millisecs)
  2066. {
  2067. int i;
  2068. LARGE_INTEGER WaitTime; // Actual time req'd for buffer to drain
  2069. // set wait-time to .001 second.(-10000 = relative(-), 100-ns units)
  2070. WaitTime.QuadPart = -10000L * millisecs;
  2071. KeDelayExecutionThread(KernelMode,FALSE,&WaitTime);
  2072. }
  2073. /*----------------------------------------------------------------------
  2074. str_to_wstr_dup - allocate wchar string and convert from char to wchar.
  2075. |----------------------------------------------------------------------*/
  2076. WCHAR *str_to_wstr_dup(char *str, int alloc_space)
  2077. {
  2078. WCHAR *wstr;
  2079. WCHAR *wtmpstr;
  2080. int siz;
  2081. siz = (strlen(str) * 2) + 4;
  2082. wstr = ExAllocatePool (alloc_space, siz);
  2083. if ( wstr ) {
  2084. RtlZeroMemory(wstr, siz);
  2085. wtmpstr = wstr;
  2086. while (*str != 0)
  2087. {
  2088. *wtmpstr = (WCHAR) *str;
  2089. ++wtmpstr;
  2090. ++str;
  2091. }
  2092. }
  2093. return wstr;
  2094. }
  2095. /*----------------------------------------------------------------------
  2096. NumDevices - return number of devices in device linked list.
  2097. |----------------------------------------------------------------------*/
  2098. int NumDevices(void)
  2099. {
  2100. PSERIAL_DEVICE_EXTENSION board_ext = NULL;
  2101. int num_devices;
  2102. num_devices = 0;
  2103. while (board_ext != NULL)
  2104. {
  2105. board_ext = board_ext->board_ext;
  2106. ++num_devices;
  2107. }
  2108. return num_devices;
  2109. }
  2110. /*----------------------------------------------------------------------
  2111. NumPorts - return number of ports for a device based on the actual
  2112. number of Object extensions linked to our device.
  2113. board_ext - board/device to return number of ports, or NULL for
  2114. a count of all ports for all boards.
  2115. |----------------------------------------------------------------------*/
  2116. int NumPorts(PSERIAL_DEVICE_EXTENSION board_ext)
  2117. {
  2118. int num_devices;
  2119. PSERIAL_DEVICE_EXTENSION port_ext;
  2120. int all_devices = 0;
  2121. if (board_ext == NULL)
  2122. {
  2123. all_devices = 1;
  2124. board_ext = Driver.board_ext;
  2125. }
  2126. num_devices = 0;
  2127. while (board_ext != NULL)
  2128. {
  2129. port_ext = board_ext->port_ext;
  2130. while (port_ext != NULL)
  2131. {
  2132. port_ext = port_ext->port_ext;
  2133. ++num_devices;
  2134. }
  2135. if (all_devices)
  2136. board_ext = board_ext->board_ext; // next
  2137. else
  2138. board_ext = NULL; // only the one
  2139. }
  2140. return num_devices;
  2141. }
  2142. /*----------------------------------------------------------------------
  2143. BoardExtToNumber - generate a board number based on the position
  2144. in linked list with head Driver.board_ext. Used for NT4.0 driver
  2145. install to report a board number.
  2146. |----------------------------------------------------------------------*/
  2147. int BoardExtToNumber(PSERIAL_DEVICE_EXTENSION board_ext)
  2148. {
  2149. PSERIAL_DEVICE_EXTENSION ext;
  2150. int board_num;
  2151. if (board_ext == NULL)
  2152. return 0;
  2153. // walk list of boards to determine which "board number" we are
  2154. board_num = 0;
  2155. ext = Driver.board_ext;
  2156. while (ext != NULL)
  2157. {
  2158. if (board_ext == ext)
  2159. {
  2160. return board_num;
  2161. }
  2162. ext = ext->board_ext;
  2163. ++board_num;
  2164. }
  2165. return 0; // return first board index as default.
  2166. }
  2167. /*----------------------------------------------------------------------
  2168. PortExtToIndex - Given a port extension, return the index into
  2169. the devices or drivers ports.
  2170. driver_flag - if set, then return in relation to driver, otherwise
  2171. return port index in relation to parent device.
  2172. |----------------------------------------------------------------------*/
  2173. int PortExtToIndex(PSERIAL_DEVICE_EXTENSION port_ext,
  2174. int driver_flag)
  2175. {
  2176. PSERIAL_DEVICE_EXTENSION b_ext;
  2177. PSERIAL_DEVICE_EXTENSION p_ext;
  2178. int port_num;
  2179. if (port_ext == NULL)
  2180. return 0;
  2181. // walk list of boards & ports
  2182. port_num = 0;
  2183. b_ext = Driver.board_ext;
  2184. while (b_ext != NULL)
  2185. {
  2186. if (!driver_flag)
  2187. port_num = 0;
  2188. p_ext = b_ext->port_ext;
  2189. while (p_ext != NULL)
  2190. {
  2191. if (p_ext == port_ext)
  2192. return port_num;
  2193. p_ext = p_ext->port_ext;
  2194. ++port_num;
  2195. }
  2196. b_ext = b_ext->board_ext;
  2197. }
  2198. // walk list of boards & pdo ports
  2199. port_num = 0;
  2200. b_ext = Driver.board_ext;
  2201. while (b_ext != NULL)
  2202. {
  2203. if (!driver_flag)
  2204. port_num = 0;
  2205. p_ext = b_ext->port_pdo_ext;
  2206. while (p_ext != NULL)
  2207. {
  2208. if (p_ext == port_ext)
  2209. return port_num;
  2210. p_ext = p_ext->port_ext;
  2211. ++port_num;
  2212. }
  2213. b_ext = b_ext->board_ext;
  2214. }
  2215. MyKdPrint(D_Error,("PortExtErr5!\n"))
  2216. return 0; // return 0(same as first port) if not found
  2217. }
  2218. /*----------------------------------------------------------------------------
  2219. | find_ext_by_name - Given name("COM5"), find the extension structure
  2220. |----------------------------------------------------------------------------*/
  2221. PSERIAL_DEVICE_EXTENSION find_ext_by_name(char *name, int *dev_num)
  2222. {
  2223. int Dev;
  2224. PSERIAL_DEVICE_EXTENSION ext;
  2225. PSERIAL_DEVICE_EXTENSION board_ext;
  2226. board_ext = Driver.board_ext;
  2227. while (board_ext)
  2228. {
  2229. ext = board_ext->port_ext;
  2230. Dev = 0;
  2231. while (ext)
  2232. {
  2233. if (my_lstricmp(name, ext->SymbolicLinkName) == 0)
  2234. {
  2235. if (dev_num != NULL)
  2236. *dev_num = Dev;
  2237. return ext;
  2238. }
  2239. ++Dev;
  2240. ext = ext->port_ext; // next in chain
  2241. } // while port extension
  2242. board_ext = board_ext->board_ext; // next in chain
  2243. } // while board extension
  2244. return NULL;
  2245. }
  2246. /*----------------------------------------------------------------------------
  2247. | is_board_in_use - Given Board extension, determine if anyone is using it.
  2248. (If any ports associated with it are open.)
  2249. |----------------------------------------------------------------------------*/
  2250. int is_board_in_use(PSERIAL_DEVICE_EXTENSION board_ext)
  2251. {
  2252. PSERIAL_DEVICE_EXTENSION port_ext;
  2253. int in_use = 0;
  2254. #ifdef S_VS
  2255. int i;
  2256. Hdlc *hd;
  2257. #endif
  2258. if (board_ext == NULL)
  2259. return 0;
  2260. #ifdef S_VS
  2261. hd = board_ext->hd;
  2262. if ( hd ) {
  2263. for( i=0; i<2; i++ ) {
  2264. if ( (hd->TxCtlPackets[i]) &&
  2265. (hd->TxCtlPackets[i]->ProtocolReserved[1]) ) {
  2266. in_use = 1;
  2267. }
  2268. }
  2269. for( i=0; i<HDLC_TX_PKT_QUEUE_SIZE; i++ ) {
  2270. if ( (hd->TxPackets[i]) &&
  2271. (hd->TxPackets[i]->ProtocolReserved[1]) ) {
  2272. in_use = 1;
  2273. }
  2274. }
  2275. }
  2276. #endif
  2277. port_ext = board_ext->port_ext;
  2278. while((in_use == 0) && (port_ext != NULL)) {
  2279. if (port_ext->DeviceIsOpen) {
  2280. in_use = 1;
  2281. }
  2282. #ifdef S_VS
  2283. hd = port_ext->hd;
  2284. if ( hd ) {
  2285. for( i=0; i<2; i++ ) {
  2286. if ( (hd->TxCtlPackets[i]) &&
  2287. (hd->TxCtlPackets[i]->ProtocolReserved[1]) ) {
  2288. in_use = 1;
  2289. }
  2290. }
  2291. for( i=0; i<HDLC_TX_PKT_QUEUE_SIZE; i++ ) {
  2292. if ( (hd->TxPackets[i]) &&
  2293. (hd->TxPackets[i]->ProtocolReserved[1]) ) {
  2294. in_use = 1;
  2295. }
  2296. }
  2297. }
  2298. #endif
  2299. port_ext = port_ext->port_ext;
  2300. }
  2301. return in_use; // not in use.
  2302. }
  2303. /*----------------------------------------------------------------------------
  2304. | find_ext_by_index - Given device X and port Y, find the extension structure
  2305. If port_num is -1, then a board ext is assumed to be looked for.
  2306. |----------------------------------------------------------------------------*/
  2307. PSERIAL_DEVICE_EXTENSION find_ext_by_index(int dev_num, int port_num)
  2308. {
  2309. PSERIAL_DEVICE_EXTENSION ext;
  2310. PSERIAL_DEVICE_EXTENSION board_ext;
  2311. int bn;
  2312. int pn;
  2313. bn = -1;
  2314. pn = -1;
  2315. board_ext = Driver.board_ext;
  2316. while ( (board_ext) && (bn < dev_num) )
  2317. {
  2318. bn++;
  2319. if (bn == dev_num) {
  2320. ext = board_ext->port_ext;
  2321. if (port_num == -1)
  2322. return board_ext; // they wanted a board ext.
  2323. while (ext)
  2324. {
  2325. pn++;
  2326. if (pn == port_num)
  2327. return ext;
  2328. else
  2329. ext = ext->port_ext; // next in port chain
  2330. }
  2331. }
  2332. board_ext = board_ext->board_ext; // next in device chain
  2333. }
  2334. return NULL;
  2335. }
  2336. /*----------------------------------------------------------------------------
  2337. | ModemReset - wrappers around hardware routines to put SocketModems into or
  2338. | clear SocketModems from reset state.
  2339. |----------------------------------------------------------------------------*/
  2340. void ModemReset(PSERIAL_DEVICE_EXTENSION ext, int on)
  2341. {
  2342. #ifdef S_RK
  2343. sModemReset(ext->ChP, on);
  2344. #else
  2345. if (on == 1)
  2346. {
  2347. // put the modem into reset state (firmware will pull it out of reset
  2348. // automatically)
  2349. ext->Port->action_reg |= ACT_MODEM_RESET;
  2350. }
  2351. else
  2352. {
  2353. // don't need to do anything to clear a modem from reset on the vs
  2354. }
  2355. #endif
  2356. }
  2357. /*-----------------------------------------------------------------
  2358. our_enum_key - Enumerate a registry key, handle misc stuff.
  2359. |------------------------------------------------------------------*/
  2360. int our_enum_key(IN HANDLE handle,
  2361. IN int index,
  2362. IN CHAR *buffer,
  2363. IN ULONG max_buffer_size,
  2364. OUT PCHAR *retdataptr)
  2365. {
  2366. NTSTATUS status;
  2367. PKEY_BASIC_INFORMATION KeyInfo;
  2368. ULONG actuallyReturned;
  2369. KeyInfo = (PKEY_BASIC_INFORMATION) buffer;
  2370. max_buffer_size -= 8; // subtract off some space for nulling end, slop, etc.
  2371. // return a pointer to the start of data.
  2372. *retdataptr = ((PCHAR)(&KeyInfo->Name[0]));
  2373. // Pad the name returned with 2 wchar zeros.
  2374. RtlZeroMemory( ((PUCHAR)(&KeyInfo->Name[0])), sizeof(WCHAR)*2);
  2375. status = ZwEnumerateKey(handle,
  2376. index,
  2377. KeyBasicInformation,
  2378. KeyInfo,
  2379. max_buffer_size,
  2380. &actuallyReturned);
  2381. if (status == STATUS_NO_MORE_ENTRIES)
  2382. {
  2383. //MyKdPrint(D_Init, ("Done.\n"))
  2384. return 1; // err, done
  2385. }
  2386. if (status != STATUS_SUCCESS)
  2387. {
  2388. MyKdPrint(D_Error, ("Err3G\n"))
  2389. return 2; // err
  2390. }
  2391. if (KeyInfo->NameLength > max_buffer_size) // check limits
  2392. KeyInfo->NameLength = max_buffer_size;
  2393. // Pad the name returned with 2 wchar zeros.
  2394. RtlZeroMemory( ((PUCHAR)(&KeyInfo->Name[0]))+KeyInfo->NameLength,
  2395. sizeof(WCHAR)*2);
  2396. return 0; // ok, done
  2397. }
  2398. /*-----------------------------------------------------------------
  2399. our_enum_value - Enumerate a registry value, handle misc stuff.
  2400. |------------------------------------------------------------------*/
  2401. int our_enum_value(IN HANDLE handle,
  2402. IN int index,
  2403. IN CHAR *buffer,
  2404. IN ULONG max_buffer_size,
  2405. OUT PULONG type,
  2406. OUT PCHAR *retdataptr,
  2407. OUT PCHAR sz_retname)
  2408. {
  2409. NTSTATUS status;
  2410. PKEY_VALUE_FULL_INFORMATION KeyValueInfo;
  2411. //PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo;
  2412. ULONG actuallyReturned;
  2413. ULONG i;
  2414. KeyValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
  2415. max_buffer_size -= 8; // subtract off some space for nulling end, slop, etc.
  2416. // Pad the name returned with 2 wchar zeros.
  2417. RtlZeroMemory( ((PUCHAR)(&KeyValueInfo->Name[0])), sizeof(WCHAR)*2);
  2418. // return a pointer to the start of data.
  2419. *retdataptr = ((PCHAR)(&KeyValueInfo->Name[0]));
  2420. *sz_retname = 0;
  2421. status = ZwEnumerateValueKey(handle,
  2422. index,
  2423. KeyValueFullInformation,
  2424. KeyValueInfo,
  2425. max_buffer_size,
  2426. &actuallyReturned);
  2427. if (status == STATUS_NO_MORE_ENTRIES)
  2428. {
  2429. //MyKdPrint(D_Init, ("Done.\n"))
  2430. return 1; // err, done
  2431. }
  2432. if (status != STATUS_SUCCESS)
  2433. {
  2434. MyKdPrint(D_Init, ("Err3H\n"))
  2435. return 2; // err
  2436. }
  2437. if (KeyValueInfo->NameLength < 80) // limit to 40 char entries
  2438. {
  2439. for (i=0; i<(KeyValueInfo->NameLength/2); i++)
  2440. {
  2441. sz_retname[i] = (CHAR)KeyValueInfo->Name[i];
  2442. }
  2443. sz_retname[i] = 0;
  2444. }
  2445. *retdataptr = ((PCHAR) KeyValueInfo) + KeyValueInfo->DataOffset;
  2446. // Pad the data returned with 2 wchar zeros.
  2447. RtlZeroMemory( (PUCHAR)(*retdataptr + KeyValueInfo->DataLength),
  2448. sizeof(WCHAR)*2);
  2449. if (type != NULL)
  2450. *type = KeyValueInfo->Type;
  2451. return 0; // ok, done
  2452. }
  2453. /*-----------------------------------------------------------------
  2454. our_query_value - get data from an entry in the registry.
  2455. We give a generic buffer space(and size), and the routine passes
  2456. back a ptr (into this generic buffer space where the data
  2457. is read into.
  2458. |------------------------------------------------------------------*/
  2459. int our_query_value(IN HANDLE Handle,
  2460. IN char *key_name,
  2461. IN CHAR *buffer,
  2462. IN ULONG max_buffer_size,
  2463. OUT PULONG type,
  2464. OUT PCHAR *retdataptr)
  2465. {
  2466. NTSTATUS status;
  2467. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo;
  2468. ULONG length;
  2469. OUT USTR_40 ubuf; // about 90 bytes on stack
  2470. if (strlen(key_name) > 38)
  2471. {
  2472. MyKdPrint(D_Error, ("Err, KeyValue Len!\n"))
  2473. return 2;
  2474. }
  2475. // convert our name to unicode;
  2476. CToUStr(
  2477. (PUNICODE_STRING) &ubuf, // where unicode struct & string gets put
  2478. key_name, // our c-string we wish to convert
  2479. sizeof(ubuf));
  2480. KeyValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
  2481. max_buffer_size -= 8; // subtract off some space for nulling end, slop, etc.
  2482. // return a pointer to the start of data.
  2483. *retdataptr = ((PCHAR)(&KeyValueInfo->Data[0]));
  2484. // Pad the name returned with 2 wchar zeros.
  2485. RtlZeroMemory( ((PUCHAR)(&KeyValueInfo->Data[0])), sizeof(WCHAR)*2);
  2486. status = ZwQueryValueKey (Handle,
  2487. (PUNICODE_STRING) &ubuf, // input reg key name
  2488. KeyValuePartialInformation,
  2489. KeyValueInfo,
  2490. max_buffer_size,
  2491. &length);
  2492. if (status != STATUS_SUCCESS)
  2493. {
  2494. //MyKdPrint(D_Init, ("No Value\n"))
  2495. return 1; // err
  2496. }
  2497. if (KeyValueInfo->DataLength > max_buffer_size)
  2498. KeyValueInfo->DataLength = max_buffer_size;
  2499. // Pad the data returned with a null,null.
  2500. RtlZeroMemory( ((PUCHAR)(&KeyValueInfo->Data[0]))+KeyValueInfo->DataLength,
  2501. sizeof(WCHAR)*2);
  2502. if (type != NULL)
  2503. *type = KeyValueInfo->Type;
  2504. return 0; // ok
  2505. }
  2506. /*-----------------------------------------------------------------
  2507. our_set_value - get data from an entry in the registry.
  2508. |------------------------------------------------------------------*/
  2509. int our_set_value(IN HANDLE Handle,
  2510. IN char *key_name,
  2511. IN PVOID pValue,
  2512. IN ULONG value_size,
  2513. IN ULONG value_type)
  2514. {
  2515. NTSTATUS status;
  2516. PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo;
  2517. ULONG length;
  2518. OUT USTR_40 ubuf_name; // about 90 bytes on stack
  2519. OUT USTR_40 ubuf_val; // about 90 bytes on stack
  2520. if (strlen(key_name) > 38)
  2521. {
  2522. MyKdPrint(D_Error, ("Err, KeyValue Len!\n"))
  2523. return 2;
  2524. }
  2525. // convert our name to unicode;
  2526. CToUStr(
  2527. (PUNICODE_STRING) &ubuf_name, // where unicode struct & string gets put
  2528. key_name, // our c-string we wish to convert
  2529. sizeof(ubuf_name));
  2530. if (value_type == REG_SZ)
  2531. {
  2532. // convert our value to unicode;
  2533. CToUStr(
  2534. (PUNICODE_STRING) &ubuf_val, // where unicode struct & string gets put
  2535. (char *)pValue, // our c-string we wish to convert
  2536. sizeof(ubuf_val));
  2537. MyKdPrint(D_Init, ("set_value reg_sz %s=%s\n",
  2538. key_name, (char *)pValue))
  2539. pValue = (PVOID)ubuf_val.ustr.Buffer;
  2540. value_size = ubuf_val.ustr.Length;
  2541. }
  2542. status = ZwSetValueKey (Handle,
  2543. (PUNICODE_STRING) &ubuf_name,
  2544. 0, // type optional
  2545. value_type,
  2546. pValue,
  2547. value_size);
  2548. if (status != STATUS_SUCCESS)
  2549. {
  2550. MyKdPrint(D_Error, ("Error setting reg %\n",key_name))
  2551. return 1; // err
  2552. }
  2553. return 0; // ok
  2554. }
  2555. /*-----------------------------------------------------------------
  2556. our_open_key - Make sure *pHandle is initialized to NULL, because
  2557. this routine auto-closes the handle with ZwClose().
  2558. |------------------------------------------------------------------*/
  2559. int our_open_key(OUT PHANDLE phandle,
  2560. IN OPTIONAL HANDLE relative_key_handle,
  2561. IN char *regkeyname,
  2562. IN ULONG attribs)
  2563. {
  2564. OBJECT_ATTRIBUTES objAttribs;
  2565. NTSTATUS status;
  2566. OUT USTR_160 ubuf; // about 340 bytes on the stack
  2567. if (strlen(regkeyname) > 158)
  2568. {
  2569. MyKdPrint(D_Error, ("Err, Key Len!\n"))
  2570. return 2;
  2571. }
  2572. // convert our name to unicode;
  2573. CToUStr(
  2574. (PUNICODE_STRING) &ubuf, // where unicode struct & string gets put
  2575. regkeyname, // our c-string we wish to convert
  2576. sizeof(ubuf));
  2577. // if previously open, then close it up.
  2578. if (*phandle != NULL)
  2579. {
  2580. ZwClose(*phandle);
  2581. *phandle = NULL;
  2582. }
  2583. InitializeObjectAttributes(&objAttribs,
  2584. (PUNICODE_STRING) &ubuf,
  2585. OBJ_CASE_INSENSITIVE,
  2586. relative_key_handle, // root dir relative handle
  2587. NULL); // security desc
  2588. status = ZwOpenKey(phandle,
  2589. attribs,
  2590. &objAttribs);
  2591. if ((status != STATUS_SUCCESS) && (attribs == KEY_ALL_ACCESS))
  2592. {
  2593. MyKdPrint(D_Error, ("OpenKey,Try to Create %s, status 0x%x\n", regkeyname,status))
  2594. status = ZwCreateKey(phandle,
  2595. attribs, //KEY_ALL_ACCESS, etc
  2596. &objAttribs,
  2597. 0, // index, optional
  2598. NULL, // ptr to unicode string, class
  2599. REG_OPTION_NON_VOLATILE,
  2600. NULL); // disposition, tells if created
  2601. if (status == STATUS_SUCCESS)
  2602. {
  2603. // try to open the original key again.
  2604. status = ZwOpenKey(phandle,
  2605. attribs,
  2606. &objAttribs);
  2607. }
  2608. else
  2609. {
  2610. MyKdPrint(D_Error, ("OpenKey,Error Creating %s\n", regkeyname))
  2611. }
  2612. }
  2613. if (status != STATUS_SUCCESS)
  2614. {
  2615. MyKdPrint(D_Error, ("OpenKey,Error Opening %s, status 0x%x\n", regkeyname,status))
  2616. //MyKdPrint(D_Init, ("Failed ZwOpenKey\n"))
  2617. *phandle = NULL; // make sure null if not open
  2618. return 1;
  2619. }
  2620. return 0;
  2621. }
  2622. /*-----------------------------------------------------------------
  2623. our_open_device_reg -
  2624. |------------------------------------------------------------------*/
  2625. int our_open_device_reg(OUT HANDLE *pHandle,
  2626. IN PSERIAL_DEVICE_EXTENSION dev_ext,
  2627. IN ULONG RegOpenRights)
  2628. {
  2629. NTSTATUS status;
  2630. HANDLE DriverHandle = NULL;
  2631. HANDLE DevHandle = NULL;
  2632. #if TRY_NEW_NT50
  2633. // PLUGPLAY_REGKEY_DRIVER opens up the control\class\{guid}\node
  2634. // PLUGPLAY_REGKEY_DEVICE opens up the enum\enum-type\node\Device Parameters
  2635. status = IoOpenDeviceRegistryKey(dev_ext->Pdo,
  2636. PLUGPLAY_REGKEY_DRIVER,
  2637. RegOpenRights, pHandle);
  2638. if (status != STATUS_SUCCESS)
  2639. {
  2640. //MyKdPrint(D_Init, ("Failed ZwOpenKey\n"))
  2641. *phandle = NULL; // make sure null if not open
  2642. return 1;
  2643. }
  2644. #else
  2645. {
  2646. int j, stat;
  2647. char dev_str[60];
  2648. char tmpstr[200];
  2649. OBJECT_ATTRIBUTES objAttribs;
  2650. MyKdPrint(D_Init, ("our_open_device_reg\n"))
  2651. #if NT50
  2652. if (dev_ext->config->szNt50DevObjName[0] == 0)
  2653. {
  2654. MyKdPrint(D_Error, ("Error, device options Pnp key!\n"))
  2655. *pHandle = NULL;
  2656. return 1; // err
  2657. }
  2658. Sprintf(dev_str, "%s\\%s",
  2659. szParameters, dev_ext->config->szNt50DevObjName);
  2660. #else
  2661. j = BoardExtToNumber(dev_ext);
  2662. Sprintf(dev_str, "%s\\Device%d", szParameters, BoardExtToNumber(dev_ext));
  2663. #endif
  2664. // force a creation of "Parameters" if not exist
  2665. stat = our_open_driver_reg(&DriverHandle,
  2666. KEY_ALL_ACCESS);
  2667. if (stat)
  2668. {
  2669. MyKdPrint(D_Error, ("Err4b!\n"))
  2670. *pHandle = NULL;
  2671. return 1;
  2672. }
  2673. ZwClose(DriverHandle);
  2674. DriverHandle = NULL;
  2675. MyKdPrint(D_Init, ("Driver.OptionRegPath: %s\n", dev_str))
  2676. stat = MakeRegPath(dev_str); // this forms Driver.OptionRegPath
  2677. if (stat) {
  2678. *pHandle = NULL;
  2679. return 1;
  2680. }
  2681. UToCStr(tmpstr, &Driver.OptionRegPath, sizeof(tmpstr));
  2682. stat = our_open_key(pHandle,
  2683. NULL,
  2684. tmpstr,
  2685. RegOpenRights);
  2686. if (stat != 0)
  2687. {
  2688. MyKdPrint(D_Error, ("Err3e\n"))
  2689. *pHandle = NULL; // make sure null if not open
  2690. return 1;
  2691. }
  2692. }
  2693. #endif
  2694. return 0;
  2695. }
  2696. /*-----------------------------------------------------------------
  2697. our_open_driver_reg -
  2698. |------------------------------------------------------------------*/
  2699. int our_open_driver_reg(OUT HANDLE *pHandle,
  2700. IN ULONG RegOpenRights)
  2701. {
  2702. NTSTATUS status;
  2703. int j, stat;
  2704. OBJECT_ATTRIBUTES objAttribs;
  2705. char tmpstr[200];
  2706. stat = MakeRegPath(szParameters); // this forms Driver.OptionRegPath
  2707. if ( stat ) {
  2708. *pHandle = NULL; // make sure null if not open
  2709. return 1;
  2710. }
  2711. UToCStr(tmpstr, &Driver.OptionRegPath, sizeof(tmpstr));
  2712. stat = our_open_key(pHandle,
  2713. NULL,
  2714. tmpstr,
  2715. RegOpenRights);
  2716. if (stat != 0)
  2717. {
  2718. MyKdPrint(D_Error, ("Failed ZwOpenKey %s\n",tmpstr))
  2719. *pHandle = NULL; // make sure null if not open
  2720. return 1;
  2721. }
  2722. return 0;
  2723. }
  2724. /*----------------------------------------------------------------------------
  2725. | ModemSpeakerEnable - wrappers around hardware routines to enable the
  2726. | RocketModemII speaker...
  2727. |----------------------------------------------------------------------------*/
  2728. void ModemSpeakerEnable(PSERIAL_DEVICE_EXTENSION ext)
  2729. {
  2730. MyKdPrint(D_Init,("ModemSpeakerEnable: %x\n",(unsigned long)ext))
  2731. #ifdef S_RK
  2732. sModemSpeakerEnable(ext->ChP);
  2733. #endif
  2734. }
  2735. /*----------------------------------------------------------------------------
  2736. | ModemWriteROW - wrappers around hardware routines to send ROW config
  2737. | commands to SocketModems.
  2738. |----------------------------------------------------------------------------*/
  2739. void ModemWriteROW(PSERIAL_DEVICE_EXTENSION ext,USHORT CountryCode)
  2740. {
  2741. int count;
  2742. char *ModemConfigString;
  2743. MyKdPrint(D_Init,("ModemWriteROW: %x, %x\n",(unsigned long)ext,CountryCode)) // DEBUG
  2744. time_stall(10); // DEBUG
  2745. #ifdef S_RK
  2746. sModemWriteROW(ext->ChP,CountryCode);
  2747. #else
  2748. {
  2749. // fix so compiles, 1-18-99 kpb
  2750. static char *ModemConfigString = {"AT*NCxxZ\r"};
  2751. if (CountryCode == 0) {
  2752. // bad country code, skip the write and let modem use power-on default
  2753. MyKdPrint(D_Init,("Undefined ROW Write\n"))
  2754. return;
  2755. }
  2756. if (CountryCode == ROW_NA) {
  2757. MyKdPrint(D_Init,("ROW Write, North America\n"))
  2758. return;
  2759. }
  2760. // create the country config string
  2761. ModemConfigString[5] = '0' + (CountryCode / 10);
  2762. ModemConfigString[6] = '0' + (CountryCode % 10);
  2763. PortFlushTx(ext->Port); /* we just reset, so a flush shouldn't matter */
  2764. q_put(&ext->Port->QOut, ModemConfigString, strlen(ModemConfigString));
  2765. }
  2766. #endif
  2767. }
  2768. #ifdef S_RK
  2769. /********************************************************************
  2770. wrappers around hardware routines to send strings to modems...
  2771. *********************************************************************/
  2772. void
  2773. ModemWrite(PSERIAL_DEVICE_EXTENSION ext,char *string,int length)
  2774. {
  2775. sModemWrite(ext->ChP,string,length);
  2776. }
  2777. /********************************************************************
  2778. wrappers around hardware routines to send strings to modems...
  2779. *********************************************************************/
  2780. int
  2781. ModemRead(PSERIAL_DEVICE_EXTENSION ext,
  2782. char *string,int length,
  2783. int poll_retries)
  2784. {
  2785. return(sModemRead(ext->ChP,string,length,poll_retries));
  2786. }
  2787. /********************************************************************
  2788. wrappers around hardware routines to send strings to modems...
  2789. *********************************************************************/
  2790. int
  2791. ModemReadChoice(PSERIAL_DEVICE_EXTENSION ext,
  2792. char *s0,int len0,
  2793. char *s1,int len1,
  2794. int poll_retries)
  2795. {
  2796. return(sModemReadChoice(ext->ChP,s0,len0,s1,len1,poll_retries));
  2797. }
  2798. /********************************************************************
  2799. wrappers around hardware routines to send strings to modems, one
  2800. byte at a time...
  2801. *********************************************************************/
  2802. void
  2803. ModemWriteDelay(PSERIAL_DEVICE_EXTENSION ext,
  2804. char *string,int length)
  2805. {
  2806. sModemWriteDelay(ext->ChP,string,length);
  2807. }
  2808. /********************************************************************
  2809. wrappers around hardware routines to check FIFO status...
  2810. *********************************************************************/
  2811. int
  2812. RxFIFOReady(PSERIAL_DEVICE_EXTENSION ext)
  2813. {
  2814. return(sRxFIFOReady(ext->ChP));
  2815. }
  2816. int
  2817. TxFIFOReady(PSERIAL_DEVICE_EXTENSION ext)
  2818. {
  2819. return(sTxFIFOReady(ext->ChP));
  2820. }
  2821. int
  2822. TxFIFOStatus(PSERIAL_DEVICE_EXTENSION ext)
  2823. {
  2824. return(sTxFIFOStatus(ext->ChP));
  2825. }
  2826. /********************************************************************
  2827. wrappers around hardware routines to prepare modem ports for IO...
  2828. *********************************************************************/
  2829. void
  2830. ModemIOReady(PSERIAL_DEVICE_EXTENSION ext,int speed)
  2831. {
  2832. if (sSetBaudRate(ext->ChP,speed,FALSE)) {
  2833. MyKdPrint(D_Init,("Unable to set baud rate to %d\n",speed))
  2834. return;
  2835. }
  2836. sFlushTxFIFO(ext->ChP);
  2837. sFlushRxFIFO(ext->ChP);
  2838. ext->BaudRate = speed;
  2839. sSetBaudRate(ext->ChP,ext->BaudRate,TRUE);
  2840. sSetData8(ext->ChP);
  2841. sSetParity(ext->ChP,0); // No Parity
  2842. sSetRxMask(ext->ChP,0xff);
  2843. sClrTxXOFF(ext->ChP) /* destroy any pending stuff */
  2844. sEnRTSFlowCtl(ext->ChP);
  2845. sEnCTSFlowCtl(ext->ChP);
  2846. if (sGetChanStatus(ext->ChP) & STATMODE) {
  2847. sDisRxStatusMode(ext->ChP);
  2848. }
  2849. sGetChanIntID(ext->ChP);
  2850. sEnRxFIFO(ext->ChP);
  2851. sEnTransmit(ext->ChP); /* enable transmitter if not already enabled */
  2852. sSetDTR(ext->ChP);
  2853. sSetRTS(ext->ChP);
  2854. }
  2855. /********************************************************************
  2856. wrappers around hardware routines to shut down modem ports for now...
  2857. *********************************************************************/
  2858. void
  2859. ModemUnReady(PSERIAL_DEVICE_EXTENSION ext)
  2860. {
  2861. sFlushTxFIFO(ext->ChP);
  2862. sFlushRxFIFO(ext->ChP);
  2863. sSetData8(ext->ChP);
  2864. sSetParity(ext->ChP,0);
  2865. sSetRxMask(ext->ChP,0xff);
  2866. ext->BaudRate = 9600;
  2867. sSetBaudRate(ext->ChP,ext->BaudRate,TRUE);
  2868. sClrTxXOFF(ext->ChP) // destroy any pending stuff
  2869. if (sGetChanStatus(ext->ChP) & STATMODE) {
  2870. sDisRxStatusMode(ext->ChP);
  2871. }
  2872. sGetChanIntID(ext->ChP);
  2873. sDisRTSFlowCtl(ext->ChP);
  2874. sDisCTSFlowCtl(ext->ChP);
  2875. sClrRTS(ext->ChP);
  2876. sClrDTR(ext->ChP);
  2877. time_stall(1); // wait for port to quiet...
  2878. }
  2879. #endif // S_RK