Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1181 lines
29 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. fake.c
  5. Abstract:
  6. Fake versions of various external calls (ndis, ip...).
  7. Used for debugging and component testing only.
  8. To enable, define ARPDBG_FAKE_APIS in ccdefs.h
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. josephj 03-22-98 Created
  13. Notes:
  14. --*/
  15. #include <precomp.h>
  16. #if ARPDBG_FAKE_APIS
  17. //
  18. // File-specific debugging defaults.
  19. //
  20. #define TM_CURRENT TM_FAKE
  21. //=========================================================================
  22. // L O C A L P R O T O T Y P E S
  23. //=========================================================================
  24. #if RM_EXTRA_CHECKING
  25. #define LOCKROOTOBJ(_pHdr, _pSR) \
  26. RmWriteLockObject( \
  27. (_pHdr)->pRootObject, \
  28. 0, \
  29. (_pSR) \
  30. )
  31. #else // !RM_EXTRA_CHECKING
  32. #define LOCKROOTOBJ(_pHdr, _pSR) \
  33. RmWriteLockObject( \
  34. (_pHdr)->pRootObject, \
  35. (_pSR) \
  36. )
  37. #endif // !RM_EXTRA_CHECKING
  38. #define UNLOCKROOTOBJ(_pHdr, _pSR) \
  39. RmUnlockObject( \
  40. (_pHdr)->pRootObject, \
  41. (_pSR) \
  42. )
  43. typedef
  44. VOID
  45. (*PFN_FAKE_COMPLETIONCALLBACK)(
  46. struct _FAKETASK *pFTask
  47. );
  48. // This task structure holds a union of the information required for the completions
  49. // of the various apis that are being faked.
  50. //
  51. typedef struct _FAKETASK
  52. {
  53. RM_TASK TskHdr;
  54. // Client's context to pass back
  55. //
  56. PVOID pClientContext;
  57. // Client object the call is associated.
  58. //
  59. PRM_OBJECT_HEADER pOwningObject;
  60. // The status to report in the asynchronous completion fn.
  61. //
  62. NDIS_STATUS Status;
  63. // Milliseconds to delay before calling the async completion fn.
  64. //
  65. UINT DelayMs;
  66. // Wheather to call the completion fn at DPC or PASSIVE IRQL level.
  67. //
  68. INT fDpc;
  69. // This is used solely to switch to DPC level when asynchronously
  70. // calling the completion callback.
  71. //
  72. NDIS_SPIN_LOCK NdisLock;
  73. // This is used solely to wait DelayMs ms if required.
  74. //
  75. NDIS_TIMER Timer;
  76. // This is used solely to switch to a different (and PASSIVE) context.
  77. //
  78. NDIS_WORK_ITEM WorkItem;
  79. // This is used only for fake NdisClMakeCall
  80. //
  81. PCO_CALL_PARAMETERS CallParameters;
  82. // This is used only for fake NdisCoSendPackets
  83. //
  84. PNDIS_PACKET pNdisPacket;
  85. // The actual completion callback function;
  86. //
  87. PFN_FAKE_COMPLETIONCALLBACK pfnCompletionCallback;
  88. } FAKETASK;
  89. VOID
  90. arpFakeMakeCallCompletionCallback(
  91. struct _FAKETASK *pFTask
  92. );
  93. VOID
  94. arpFakeCloseCallCompletionCallback(
  95. struct _FAKETASK *pFTask
  96. );
  97. VOID
  98. arpFakeSendPacketsCompletionCallback(
  99. struct _FAKETASK *pFTask
  100. );
  101. NDIS_STATUS
  102. arpDbgAllocateFakeTask(
  103. IN PRM_OBJECT_HEADER pParentObject,
  104. IN PFN_RM_TASK_HANDLER pfnHandler,
  105. IN UINT Timeout,
  106. IN const char * szDescription,
  107. OUT PRM_TASK *ppTask,
  108. IN PRM_STACK_RECORD pSR
  109. );
  110. VOID
  111. arpDbgFakeTaskDelete(
  112. PRM_OBJECT_HEADER pObj,
  113. PRM_STACK_RECORD psr
  114. );
  115. RM_STATIC_OBJECT_INFO
  116. FakeTasks_StaticInfo =
  117. {
  118. 0, // TypeUID
  119. 0, // TypeFlags
  120. "FAKE Task", // TypeName
  121. 0, // Timeout
  122. NULL, // pfnCreate
  123. arpDbgFakeTaskDelete, // pfnDelete
  124. NULL, // pfnVerifier
  125. 0, // length of resource table
  126. NULL // Resource Table
  127. };
  128. NDIS_STATUS
  129. arpDbgFakeCompletionTask(
  130. IN struct _RM_TASK * pTask,
  131. IN RM_TASK_OPERATION Code,
  132. IN UINT_PTR UserParam, // Unused
  133. IN PRM_STACK_RECORD pSR
  134. );
  135. //=========================================================================
  136. // F A K E N D I S E N T R Y P O I N T S
  137. //=========================================================================
  138. NDIS_STATUS
  139. arpDbgFakeNdisClMakeCall(
  140. IN NDIS_HANDLE NdisVcHandle,
  141. IN OUT PCO_CALL_PARAMETERS CallParameters,
  142. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  143. OUT PNDIS_HANDLE NdisPartyHandle, OPTIONAL
  144. IN PRM_OBJECT_HEADER pOwningObject,
  145. IN PVOID pClientContext,
  146. IN PRM_STACK_RECORD pSR
  147. )
  148. /*++
  149. Routine Description:
  150. Fake version of NdisClMakeCall.
  151. --*/
  152. {
  153. ENTER("FakeNdisClMakeCall", 0x3d4195ae)
  154. NDIS_STATUS Status;
  155. NDIS_STATUS AsyncStatus;
  156. UINT DelayMs;
  157. DBGMARK(0xced41a61);
  158. RM_ASSERT_NOLOCKS(pSR);
  159. ASSERT(NdisPartyHandle==NULL);
  160. ASSERT(ProtocolPartyContext==NULL);
  161. ASSERT(NdisVcHandle != NULL);
  162. do
  163. {
  164. static
  165. OUTCOME_PROBABILITY
  166. StatusOutcomes[] =
  167. {
  168. {NDIS_STATUS_SUCCESS, 1}, // Return NDIS_STATUS_SUCCESS
  169. {NDIS_STATUS_FAILURE, 1} // Return NDIS_STATUS_FAILURE
  170. };
  171. static
  172. OUTCOME_PROBABILITY
  173. DelayMsOutcomes[] =
  174. {
  175. {0, 5}, // Delay 0ms, etc...
  176. {10, 5},
  177. {100, 5},
  178. {1000, 1},
  179. {10000, 1}
  180. };
  181. static
  182. OUTCOME_PROBABILITY
  183. AsyncOutcomes[] =
  184. {
  185. {TRUE, 1}, // Complete Async
  186. {FALSE, 1} // Complete Sync
  187. };
  188. static
  189. OUTCOME_PROBABILITY
  190. DpcOutcomes[] =
  191. {
  192. {TRUE, 1}, // Complete at DPC level
  193. {FALSE, 1} // Complete at PASSIVE level
  194. };
  195. FAKETASK *pMCTask;
  196. // We serialize calls to arpGenRandomInt by claiming the root object's
  197. // lock...
  198. //
  199. LOCKROOTOBJ(pOwningObject, pSR);
  200. // Get the status we're supposed to return.
  201. //
  202. Status =
  203. AsyncStatus = (NDIS_STATUS) arpGenRandomInt(
  204. StatusOutcomes,
  205. ARRAY_LENGTH(StatusOutcomes)
  206. );
  207. // Determine if we're to return synchronously or complete
  208. // asynchronously...
  209. //
  210. if (!arpGenRandomInt(AsyncOutcomes, ARRAY_LENGTH(AsyncOutcomes)))
  211. {
  212. // We're to return synchronously.
  213. //
  214. UNLOCKROOTOBJ(pOwningObject, pSR);
  215. break;
  216. }
  217. //
  218. // We're to complete asynchronously...
  219. //
  220. DelayMs = arpGenRandomInt(
  221. DelayMsOutcomes,
  222. ARRAY_LENGTH(DelayMsOutcomes)
  223. );
  224. if (DelayMs == 0)
  225. {
  226. // We're to immediately indicatie async completion...
  227. // (we don't mess with IRQ levels if we're returning here..)
  228. //
  229. UNLOCKROOTOBJ(pOwningObject, pSR);
  230. ArpCoMakeCallComplete(
  231. AsyncStatus,
  232. pClientContext,
  233. NULL,
  234. CallParameters
  235. );
  236. Status = NDIS_STATUS_PENDING;
  237. break;
  238. }
  239. // We're to indicate status sometime in the future -- in a different context.
  240. // Start a task to do this...
  241. //
  242. Status = arpDbgAllocateFakeTask(
  243. pOwningObject, // pParentObject,
  244. arpDbgFakeCompletionTask, // pfnHandler,
  245. 0, // Timeout,
  246. "Task:Fake NdisClMakeCall", // szDescription,
  247. &(PRM_TASK) pMCTask,
  248. pSR
  249. );
  250. if (FAIL(Status))
  251. {
  252. // Couldn't allocate task. Call callback right away...
  253. //
  254. UNLOCKROOTOBJ(pOwningObject, pSR);
  255. ArpCoMakeCallComplete(
  256. AsyncStatus,
  257. pClientContext,
  258. NULL,
  259. CallParameters
  260. );
  261. Status = NDIS_STATUS_PENDING;
  262. break;
  263. }
  264. // Initialize pMCTask...
  265. //
  266. pMCTask->pClientContext = pClientContext;
  267. pMCTask->pOwningObject = pOwningObject;
  268. pMCTask->Status = AsyncStatus;
  269. pMCTask->DelayMs = DelayMs;
  270. pMCTask->fDpc = arpGenRandomInt(
  271. DpcOutcomes,
  272. ARRAY_LENGTH(DpcOutcomes)
  273. );
  274. pMCTask->CallParameters = CallParameters;
  275. pMCTask->pfnCompletionCallback = arpFakeMakeCallCompletionCallback;
  276. UNLOCKROOTOBJ(pOwningObject, pSR);
  277. (void) RmStartTask(
  278. &pMCTask->TskHdr,
  279. 0, // UserParam (unused)
  280. pSR
  281. );
  282. Status = NDIS_STATUS_PENDING;
  283. } while (FALSE);
  284. RM_ASSERT_NOLOCKS(pSR);
  285. EXIT();
  286. return Status;
  287. }
  288. NDIS_STATUS
  289. arpDbgFakeNdisClCloseCall(
  290. IN NDIS_HANDLE NdisVcHandle,
  291. IN NDIS_HANDLE NdisPartyHandle OPTIONAL,
  292. IN PVOID Buffer OPTIONAL,
  293. IN UINT Size, OPTIONAL
  294. IN PRM_OBJECT_HEADER pOwningObject,
  295. IN PVOID pClientContext,
  296. IN PRM_STACK_RECORD pSR
  297. )
  298. /*++
  299. Routine Description:
  300. Fake version of NdisClCloseCall.
  301. --*/
  302. {
  303. ENTER("FakeNdisClCloseCall", 0x7d8bbd3c)
  304. NDIS_STATUS Status;
  305. NDIS_STATUS AsyncStatus;
  306. UINT DelayMs;
  307. DBGMARK(0x228fac3a);
  308. RM_ASSERT_NOLOCKS(pSR);
  309. ASSERT(NdisPartyHandle==NULL);
  310. ASSERT(NdisVcHandle != NULL);
  311. do
  312. {
  313. static
  314. OUTCOME_PROBABILITY
  315. DelayMsOutcomes[] =
  316. {
  317. {0, 5}, // Delay 0ms, etc...
  318. {10, 5},
  319. {100, 5},
  320. {1000, 1},
  321. {10000, 1}
  322. };
  323. static
  324. OUTCOME_PROBABILITY
  325. AsyncOutcomes[] =
  326. {
  327. {TRUE, 1}, // Complete Async
  328. {FALSE, 1} // Complete Sync
  329. };
  330. static
  331. OUTCOME_PROBABILITY
  332. DpcOutcomes[] =
  333. {
  334. {TRUE, 1}, // Complete at DPC level
  335. {FALSE, 1} // Complete at PASSIVE level
  336. };
  337. FAKETASK *pCCTask;
  338. // We serialize calls to arpGenRandomInt by claiming the root object's
  339. // lock...
  340. //
  341. LOCKROOTOBJ(pOwningObject, pSR);
  342. // Get the status we're supposed to return.
  343. //
  344. Status =
  345. AsyncStatus = NDIS_STATUS_SUCCESS; // We never fail this call.
  346. // Determine if we're to return synchronously or complete
  347. // asynchronously...
  348. //
  349. if (!arpGenRandomInt(AsyncOutcomes, ARRAY_LENGTH(AsyncOutcomes)))
  350. {
  351. // We're to return synchronously.
  352. //
  353. UNLOCKROOTOBJ(pOwningObject, pSR);
  354. break;
  355. }
  356. //
  357. // We're to complete asynchronously...
  358. //
  359. DelayMs = arpGenRandomInt(
  360. DelayMsOutcomes,
  361. ARRAY_LENGTH(DelayMsOutcomes)
  362. );
  363. if (DelayMs == 0)
  364. {
  365. // We're to immediately indicatie async completion...
  366. // (we don't mess with IRQ levels if we're returning here..)
  367. //
  368. UNLOCKROOTOBJ(pOwningObject, pSR);
  369. ArpCoCloseCallComplete(
  370. AsyncStatus,
  371. pClientContext,
  372. NULL
  373. );
  374. Status = NDIS_STATUS_PENDING;
  375. break;
  376. }
  377. Status = arpDbgAllocateFakeTask(
  378. pOwningObject, // pParentObject,
  379. arpDbgFakeCompletionTask, // pfnHandler,
  380. 0, // Timeout,
  381. "Task:Fake NdisClCloseCall", // szDescription,
  382. &(PRM_TASK) pCCTask,
  383. pSR
  384. );
  385. if (FAIL(Status))
  386. {
  387. // Couldn't alloc task; lets call callback right now and return pending.
  388. //
  389. UNLOCKROOTOBJ(pOwningObject, pSR);
  390. ArpCoCloseCallComplete(
  391. AsyncStatus,
  392. pClientContext,
  393. NULL
  394. );
  395. Status = NDIS_STATUS_PENDING;
  396. break;
  397. }
  398. // Initialize pCCTask...
  399. //
  400. pCCTask->pClientContext = pClientContext;
  401. pCCTask->pOwningObject = pOwningObject;
  402. pCCTask->Status = AsyncStatus;
  403. pCCTask->DelayMs = DelayMs;
  404. pCCTask->fDpc = arpGenRandomInt(
  405. DpcOutcomes,
  406. ARRAY_LENGTH(DpcOutcomes)
  407. );
  408. pCCTask->pfnCompletionCallback = arpFakeCloseCallCompletionCallback;
  409. UNLOCKROOTOBJ(pOwningObject, pSR);
  410. (void) RmStartTask(
  411. &pCCTask->TskHdr,
  412. 0, // UserParam (unused)
  413. pSR
  414. );
  415. Status = NDIS_STATUS_PENDING;
  416. } while (FALSE);
  417. RM_ASSERT_NOLOCKS(pSR);
  418. EXIT();
  419. return Status;
  420. }
  421. VOID
  422. arpDbgFakeNdisCoSendPackets(
  423. IN NDIS_HANDLE NdisVcHandle,
  424. IN PPNDIS_PACKET PacketArray,
  425. IN UINT NumberOfPackets,
  426. IN PRM_OBJECT_HEADER pOwningObject,
  427. IN PVOID pClientContext
  428. )
  429. /*++
  430. Routine Description:
  431. Fake version of NdisCoSendPackets.
  432. --*/
  433. {
  434. ENTER("FakeNdisCoSendPackets", 0x98c6a8aa)
  435. NDIS_STATUS Status;
  436. NDIS_STATUS AsyncStatus;
  437. UINT DelayMs;
  438. RM_DECLARE_STACK_RECORD(sr)
  439. DBGMARK(0x3be1b902);
  440. ASSERT(NumberOfPackets==1);
  441. do
  442. {
  443. static
  444. OUTCOME_PROBABILITY
  445. StatusOutcomes[] =
  446. {
  447. {NDIS_STATUS_SUCCESS, 1}, // Return NDIS_STATUS_SUCCESS
  448. {NDIS_STATUS_FAILURE, 1} // Return NDIS_STATUS_FAILURE
  449. };
  450. static
  451. OUTCOME_PROBABILITY
  452. DelayMsOutcomes[] =
  453. {
  454. {0, 5}, // Delay 0ms, etc...
  455. {10, 5},
  456. {100, 5},
  457. {1000, 1},
  458. {10000, 1}
  459. };
  460. static
  461. OUTCOME_PROBABILITY
  462. DpcOutcomes[] =
  463. {
  464. {TRUE, 1}, // Complete at DPC level
  465. {FALSE, 1} // Complete at PASSIVE level
  466. };
  467. FAKETASK *pSPTask;
  468. // We serialize calls to arpGenRandomInt by claiming the root object's
  469. // lock...
  470. //
  471. LOCKROOTOBJ(pOwningObject, &sr);
  472. // Get the status we're supposed to return.
  473. //
  474. Status =
  475. AsyncStatus = (NDIS_STATUS) arpGenRandomInt(
  476. StatusOutcomes,
  477. ARRAY_LENGTH(StatusOutcomes)
  478. );
  479. // Compute the delay amount.
  480. //
  481. DelayMs = arpGenRandomInt(
  482. DelayMsOutcomes,
  483. ARRAY_LENGTH(DelayMsOutcomes)
  484. );
  485. if (DelayMs == 0)
  486. {
  487. UNLOCKROOTOBJ(pOwningObject, &sr);
  488. // We're to immediately indicatie async completion...
  489. // (we don't mess with IRQ levels if we're returning here..)
  490. //
  491. ArpCoSendComplete(
  492. AsyncStatus,
  493. pClientContext,
  494. *PacketArray
  495. );
  496. break;
  497. }
  498. //
  499. // Nonzero delay -- start task to complete this.
  500. //
  501. Status = arpDbgAllocateFakeTask(
  502. pOwningObject, // pParentObject,
  503. arpDbgFakeCompletionTask, // pfnHandler,
  504. 0, // Timeout,
  505. "Task:Fake NdisCoSendPackets", // szDescription,
  506. &(PRM_TASK) pSPTask,
  507. &sr
  508. );
  509. if (FAIL(Status))
  510. {
  511. UNLOCKROOTOBJ(pOwningObject, &sr);
  512. // Fail...
  513. //
  514. ArpCoSendComplete(
  515. AsyncStatus,
  516. pClientContext,
  517. *PacketArray
  518. );
  519. break;
  520. }
  521. // Initialize pSPTask...
  522. //
  523. pSPTask->pClientContext = pClientContext;
  524. pSPTask->pOwningObject = pOwningObject;
  525. pSPTask->Status = AsyncStatus;
  526. pSPTask->DelayMs = DelayMs;
  527. pSPTask->fDpc = arpGenRandomInt(
  528. DpcOutcomes,
  529. ARRAY_LENGTH(DpcOutcomes)
  530. );
  531. pSPTask->pNdisPacket = *PacketArray;
  532. pSPTask->pfnCompletionCallback = arpFakeSendPacketsCompletionCallback;
  533. UNLOCKROOTOBJ(pOwningObject, &sr);
  534. (void) RmStartTask(
  535. &pSPTask->TskHdr,
  536. 0, // UserParam (unused)
  537. &sr
  538. );
  539. Status = NDIS_STATUS_PENDING;
  540. } while (FALSE);
  541. RM_ASSERT_NOLOCKS(&sr);
  542. EXIT();
  543. }
  544. NDIS_STATUS
  545. arpDbgFakeCompletionTask(
  546. IN struct _RM_TASK * pTask,
  547. IN RM_TASK_OPERATION Code,
  548. IN UINT_PTR UserParam,
  549. IN PRM_STACK_RECORD pSR
  550. )
  551. /*++
  552. Routine Description:
  553. This task is to complete the fake api asynchronously after the
  554. specified delay, with the specified status, and at the specified
  555. IRQL (passive/dpc).
  556. Arguments:
  557. UserParam for (Code == RM_TASKOP_START) : unused
  558. --*/
  559. {
  560. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  561. FAKETASK * pFTask = (FAKETASK *) pTask;
  562. ENTER("FakeCompletionTask", 0xc319c5c2)
  563. // Following are the list of pending states for this task.
  564. //
  565. enum
  566. {
  567. PEND_ResumedAfterDelay,
  568. PEND_SwitchedToAsync,
  569. };
  570. switch(Code)
  571. {
  572. case RM_TASKOP_START:
  573. {
  574. TR_WARN((
  575. "START: Delay=%lu; fDpc=%lu; Status=%lu\n",
  576. pFTask->DelayMs,
  577. pFTask->fDpc,
  578. pFTask->Status
  579. ));
  580. if (pFTask->DelayMs!=0)
  581. {
  582. // Non-zero delay -- let's resume after the delay...
  583. //
  584. RmSuspendTask(pTask, PEND_ResumedAfterDelay, pSR);
  585. RmResumeTaskDelayed(
  586. pTask,
  587. 0,
  588. pFTask->DelayMs,
  589. &pFTask->Timer,
  590. pSR
  591. );
  592. }
  593. else
  594. {
  595. // No delay is requested. Switch to async right away...
  596. //
  597. RmSuspendTask(pTask, PEND_SwitchedToAsync, pSR);
  598. RmResumeTaskAsync(
  599. pTask,
  600. 0,
  601. &pFTask->WorkItem,
  602. pSR
  603. );
  604. }
  605. RM_ASSERT_NOLOCKS(pSR);
  606. Status = NDIS_STATUS_PENDING;
  607. }
  608. break;
  609. case RM_TASKOP_PENDCOMPLETE:
  610. {
  611. switch(RM_PEND_CODE(pTask))
  612. {
  613. case PEND_ResumedAfterDelay:
  614. {
  615. // We've waited around for pFTask->DelayMs ms; Now
  616. // switch to passive...
  617. //
  618. RmSuspendTask(pTask, PEND_SwitchedToAsync, pSR);
  619. RmResumeTaskAsync(
  620. pTask,
  621. 0,
  622. &pFTask->WorkItem,
  623. pSR
  624. );
  625. Status = NDIS_STATUS_PENDING;
  626. }
  627. break;
  628. case PEND_SwitchedToAsync:
  629. {
  630. //
  631. // We should now be at PASSIVE IRQL.
  632. // Call the completion routine either at DPC or PASSIVE irql.
  633. //
  634. if (pFTask->fDpc)
  635. {
  636. // We need to call the routine at DPC level.
  637. //
  638. NdisAllocateSpinLock(&pFTask->NdisLock);
  639. NdisAcquireSpinLock(&pFTask->NdisLock);
  640. }
  641. // Call the completion routine.
  642. //
  643. pFTask->pfnCompletionCallback(pFTask);
  644. // If required, release the lock we held earlier.
  645. //
  646. if (pFTask->fDpc)
  647. {
  648. NdisReleaseSpinLock(&pFTask->NdisLock);
  649. }
  650. Status = pFTask->Status;
  651. } // end case PEND_OnStart
  652. break;
  653. default:
  654. {
  655. ASSERTEX(!"Unknown pend op", pTask);
  656. }
  657. break;
  658. } // end switch(RM_PEND_CODE(pTask))
  659. } // case RM_TASKOP_PENDCOMPLETE
  660. break;
  661. case RM_TASKOP_END:
  662. {
  663. Status = (NDIS_STATUS) UserParam;
  664. }
  665. break;
  666. default:
  667. {
  668. ASSERTEX(!"Unexpected task op", pTask);
  669. }
  670. break;
  671. } // switch (Code)
  672. RM_ASSERT_NOLOCKS(pSR);
  673. EXIT()
  674. return Status;
  675. }
  676. NDIS_STATUS
  677. arpDbgAllocateFakeTask(
  678. IN PRM_OBJECT_HEADER pParentObject,
  679. IN PFN_RM_TASK_HANDLER pfnHandler,
  680. IN UINT Timeout,
  681. IN const char * szDescription,
  682. OUT PRM_TASK *ppTask,
  683. IN PRM_STACK_RECORD pSR
  684. )
  685. /*++
  686. Routine Description:
  687. Allocates and initializes a task of subtype FAKETASK.
  688. Arguments:
  689. pParentObject - Object that is to be the parent of the allocated task.
  690. pfnHandler - The task handler for the task.
  691. Timeout - Unused.
  692. szDescription - Text describing this task.
  693. ppTask - Place to store pointer to the new task.
  694. Return Value:
  695. NDIS_STATUS_SUCCESS if we could allocate and initialize the task.
  696. NDIS_STATUS_RESOURCES otherwise
  697. --*/
  698. {
  699. FAKETASK *pFTask;
  700. NDIS_STATUS Status;
  701. ARP_ALLOCSTRUCT(pFTask, MTAG_DBGINFO);
  702. Status = NDIS_STATUS_RESOURCES;
  703. *ppTask = NULL;
  704. if (pFTask != NULL)
  705. {
  706. RmInitializeTask(
  707. &(pFTask->TskHdr),
  708. pParentObject,
  709. pfnHandler,
  710. &FakeTasks_StaticInfo,
  711. szDescription,
  712. Timeout,
  713. pSR
  714. );
  715. *ppTask = &(pFTask->TskHdr);
  716. Status = NDIS_STATUS_SUCCESS;
  717. }
  718. return Status;
  719. }
  720. VOID
  721. arpDbgFakeTaskDelete (
  722. PRM_OBJECT_HEADER pObj,
  723. PRM_STACK_RECORD psr
  724. )
  725. /*++
  726. Routine Description:
  727. Actually free the specified task.
  728. Arguments:
  729. pObj - Actually the task to be freed.
  730. --*/
  731. {
  732. ARP_FREE(pObj);
  733. }
  734. INT
  735. arpGenRandomInt(
  736. OUTCOME_PROBABILITY *rgOutcomes,
  737. UINT cOutcomes
  738. )
  739. /*++
  740. Routine Description:
  741. Generate a new sample given the specified probability distribution.
  742. Arguments:
  743. rgOutcomes - Array of outcomes from which to select the random
  744. sample.
  745. cOutcomes - Number of elements in the above array.
  746. Return Value:
  747. Random integer
  748. --*/
  749. {
  750. ULONG u, sum, partsum;
  751. OUTCOME_PROBABILITY *pOp, *pOpEnd;
  752. // Get a nicely-random number.
  753. //
  754. u = ran1x();
  755. // Run through weights, computing the sum of weights...
  756. //
  757. pOp = pOpEnd = rgOutcomes;
  758. pOpEnd += cOutcomes;
  759. sum=0;
  760. for(; pOp<pOpEnd; pOp++)
  761. {
  762. sum += pOp->Weight;
  763. }
  764. // It's really meaningless to pass in a pPD with zero sum of weights.
  765. // We return 0 in this case.
  766. //
  767. if (sum == 0) return 0; // EARLY RETURN
  768. // Make u range from 0..sum-1 inclusive
  769. //
  770. u ^= u>>16; // Get more randomness in the lower 16 bits for mod below...
  771. u %= sum;
  772. // Now go through the array of outcomes, computing the partial sum (partsum)
  773. // of weigths, and picking the FIRST outcome at array position X such that
  774. // u < partsum.
  775. //
  776. partsum=0;
  777. pOp = pOpEnd = rgOutcomes;
  778. pOpEnd += cOutcomes;
  779. for(; pOp<pOpEnd; pOp++)
  780. {
  781. partsum += pOp->Weight;
  782. if (u < partsum)
  783. {
  784. break; // Found it!
  785. }
  786. }
  787. ASSERT(pOp<pOpEnd);
  788. return pOp->Outcome;
  789. }
  790. static long g_idum;
  791. unsigned long ran1x(void)
  792. /*++
  793. Routine Description:
  794. Closely based on ran1() from "Numerical Recipes in C." ISBN 0 521 43108 5
  795. (except that it returns unsigned long instead of float, and uses g_idum
  796. instead of input arg long *idum).
  797. Pretty uniform and uncorrelated from sample to sample; also individual bits are
  798. pretty random. We need these properties.
  799. Return Value:
  800. Random unsigned integer.
  801. --*/
  802. {
  803. #define IA 16807
  804. #define IM RAN1X_MAX
  805. #define IQ 127773
  806. #define IR 2836
  807. #define NTAB 32
  808. #define NDIV (1+(IM-1)/NTAB)
  809. int j;
  810. long k;
  811. static long iy=0;
  812. static long iv[NTAB];
  813. if (g_idum <= 0 || !iy)
  814. {
  815. //
  816. // Initialization code... (I'm not really sure if iy or g_idum can
  817. // go to zero in the course of operation, so I'm leaving this
  818. // initialization code here instead of moving it to sranx1x).
  819. //
  820. if (-g_idum < 1)
  821. {
  822. g_idum = 1;
  823. }
  824. else
  825. {
  826. g_idum = -g_idum;
  827. }
  828. for (j=NTAB+7;j>=0;j--)
  829. {
  830. k = g_idum/IQ;
  831. g_idum = IA*(g_idum-k*IQ)-IR*k;
  832. if (g_idum<0)
  833. {
  834. g_idum += IM;
  835. }
  836. if (j<NTAB)
  837. {
  838. iv[j] = g_idum;
  839. }
  840. }
  841. iy=iv[0];
  842. }
  843. k=g_idum/IQ;
  844. g_idum=IA*(g_idum-k*IQ)-IR*k;
  845. if (g_idum<0)
  846. {
  847. g_idum += IM;
  848. }
  849. j = iy/NDIV;
  850. iy = iv[j];
  851. iv[j] = g_idum;
  852. // iy ranges from 1 .. (IM-1)
  853. //
  854. return (unsigned long) iy;
  855. }
  856. void
  857. sran1x(
  858. unsigned long seed
  859. )
  860. /*++
  861. Routine Description:
  862. Sets the seed used by ran1x.
  863. --*/
  864. {
  865. g_idum = (long) seed;
  866. //
  867. // Make sure the seed is -ve, to trigger ran1x initialization code above.
  868. //
  869. if (g_idum > 0)
  870. {
  871. g_idum = -g_idum;
  872. }
  873. if (g_idum==0)
  874. {
  875. g_idum = -1;
  876. }
  877. }
  878. VOID
  879. arpFakeMakeCallCompletionCallback(
  880. struct _FAKETASK *pFTask
  881. )
  882. /*++
  883. Routine Description:
  884. Calls ARP's makecall completion callback.
  885. Arguments:
  886. pFTask - Task in whose context this callback is to be made. The task
  887. contains information used in calling the makecall completion
  888. callback.
  889. --*/
  890. {
  891. // Call the make call completion routine.
  892. //
  893. ArpCoMakeCallComplete(
  894. pFTask->Status,
  895. (NDIS_HANDLE) pFTask->pClientContext,
  896. NULL,
  897. pFTask->CallParameters
  898. );
  899. }
  900. VOID
  901. arpFakeCloseCallCompletionCallback(
  902. struct _FAKETASK *pFTask
  903. )
  904. /*++
  905. Routine Description:
  906. Calls ARP's closecall completion callback.
  907. Arguments:
  908. pFTask - Task in whose context this callback is to be made. The task
  909. contains information used in calling the closecall completion
  910. callback.
  911. --*/
  912. {
  913. ArpCoCloseCallComplete(
  914. pFTask->Status,
  915. (NDIS_HANDLE) pFTask->pClientContext,
  916. NULL
  917. );
  918. }
  919. VOID
  920. arpFakeSendPacketsCompletionCallback(
  921. struct _FAKETASK *pFTask
  922. )
  923. /*++
  924. Routine Description:
  925. Calls ARP's cosendpackets completion callback.
  926. Arguments:
  927. pFTask - Task in whose context this callback is to be made. The task
  928. contains information used in calling the cosendpackets completion
  929. callback.
  930. --*/
  931. {
  932. ArpCoSendComplete(
  933. pFTask->Status,
  934. (NDIS_HANDLE) pFTask->pClientContext,
  935. pFTask->pNdisPacket
  936. );
  937. }
  938. #endif // ARPDBG_FAKE_APIS