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.

474 lines
20 KiB

  1. /***************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. WDMUTIL.C
  5. Abstract:
  6. Stuff that does not fit well with NDIS header files
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 5/17/99 : created
  17. Author:
  18. Tom Green
  19. ****************************************************************************/
  20. #include "precomp.h"
  21. /****************************************************************************/
  22. /* DeviceObjectToDriverObject */
  23. /****************************************************************************/
  24. /* */
  25. /* Routine Description: */
  26. /* */
  27. /* Get driver object associated with device object. NDIS has no notion */
  28. /* of the shape of a device object, so we put this here for ease of */
  29. /* building *
  30. /* */
  31. /* Arguments: */
  32. /* */
  33. /* DeviceObject - device object we to get associated driver object for */
  34. /* */
  35. /* Return: */
  36. /* */
  37. /* PDRIVER_OBJECT */
  38. /* */
  39. /****************************************************************************/
  40. PDRIVER_OBJECT
  41. DeviceObjectToDriverObject(IN PDEVICE_OBJECT DeviceObject)
  42. {
  43. return DeviceObject->DriverObject;
  44. } // DeviceObjectToDriverObject
  45. /****************************************************************************/
  46. /* GetDeviceFriendlyName */
  47. /****************************************************************************/
  48. /* */
  49. /* Routine Description: */
  50. /* */
  51. /* Return the friendly name associated with the given device object. */
  52. /* */
  53. /* Arguments: */
  54. /* */
  55. /* pDeviceObject - device object we to get associated driver object for */
  56. /* ppName - Place to return a pointer to an ANSI string containing name */
  57. /* pNameLength - Place to return length of above string */
  58. /* */
  59. /* Return: */
  60. /* */
  61. /* NTSTATUS */
  62. /* */
  63. /****************************************************************************/
  64. NTSTATUS
  65. GetDeviceFriendlyName(IN PDEVICE_OBJECT pDeviceObject,
  66. OUT PANSI_STRING pAnsiName,
  67. OUT PUNICODE_STRING pUnicodeName)
  68. {
  69. NTSTATUS NtStatus;
  70. NDIS_STATUS Status;
  71. ULONG ResultLength;
  72. DEVICE_REGISTRY_PROPERTY Property;
  73. UNICODE_STRING UnicodeString;
  74. ANSI_STRING AnsiString;
  75. USHORT AnsiMaxLength;
  76. PWCHAR pValueInfo;
  77. ULONG i;
  78. pValueInfo = NULL;
  79. AnsiString.Buffer = NULL;
  80. do
  81. {
  82. Property = DevicePropertyFriendlyName;
  83. for (i = 0; i < 2; i++)
  84. {
  85. NtStatus = IoGetDeviceProperty(pDeviceObject,
  86. Property,
  87. 0,
  88. NULL,
  89. &ResultLength);
  90. if (NtStatus != STATUS_BUFFER_TOO_SMALL)
  91. {
  92. ASSERT(!NT_SUCCESS(NtStatus));
  93. Property = DevicePropertyDeviceDescription;
  94. }
  95. }
  96. Status = MemAlloc(&pValueInfo, ResultLength);
  97. if (Status != NDIS_STATUS_SUCCESS)
  98. {
  99. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  100. break;
  101. }
  102. NtStatus = IoGetDeviceProperty(pDeviceObject,
  103. Property,
  104. ResultLength,
  105. pValueInfo,
  106. &ResultLength);
  107. if (NtStatus != STATUS_SUCCESS)
  108. {
  109. TRACE1(("IoGetDeviceProperty returned %x\n", NtStatus));
  110. break;
  111. }
  112. RtlInitUnicodeString(&UnicodeString, pValueInfo);
  113. //
  114. // Allocate space for ANSI version.
  115. //
  116. AnsiMaxLength = UnicodeString.MaximumLength / sizeof(WCHAR);
  117. Status = MemAlloc(&AnsiString.Buffer, AnsiMaxLength);
  118. if (Status != NDIS_STATUS_SUCCESS)
  119. {
  120. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  121. break;
  122. }
  123. RtlFillMemory(AnsiString.Buffer, AnsiMaxLength, 0);
  124. AnsiString.MaximumLength = AnsiMaxLength;
  125. AnsiString.Length = 0;
  126. NtStatus = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
  127. if (!NT_SUCCESS(NtStatus))
  128. {
  129. ASSERT(FALSE);
  130. break;
  131. }
  132. *pAnsiName = AnsiString;
  133. *pUnicodeName = UnicodeString;
  134. break;
  135. }
  136. while (FALSE);
  137. if (!NT_SUCCESS(NtStatus))
  138. {
  139. if (pValueInfo)
  140. {
  141. MemFree(pValueInfo, -1);
  142. }
  143. if (AnsiString.Buffer)
  144. {
  145. MemFree(AnsiString.Buffer, AnsiString.MaximumLength);
  146. }
  147. }
  148. return (NtStatus);
  149. }
  150. /****************************************************************************/
  151. /* HookPnpDispatchRoutine */
  152. /****************************************************************************/
  153. /* */
  154. /* Routine Description: */
  155. /* */
  156. /* Set up the driver object for the specified microport driver to */
  157. /* intercept the IRP_MJ_PNP dispatch routine before it gets to NDIS. */
  158. /* This is in order to support surprise removal on platforms where we */
  159. /* don't have NDIS 5.1 support. If we are running on >= NDIS 5.1, don't */
  160. /* do anything. */
  161. /* */
  162. /* Arguments: */
  163. /* */
  164. /* DriverBlock - pointer to driver block structure for this microport. */
  165. /* */
  166. /* Return: */
  167. /* */
  168. /* VOID */
  169. /* */
  170. /****************************************************************************/
  171. VOID
  172. HookPnpDispatchRoutine(IN PDRIVER_BLOCK DriverBlock)
  173. {
  174. if ((DriverBlock->MajorNdisVersion < 5) ||
  175. ((DriverBlock->MajorNdisVersion == 5) && (DriverBlock->MinorNdisVersion < 1)))
  176. {
  177. DriverBlock->SavedPnPDispatch =
  178. DriverBlock->DriverObject->MajorFunction[IRP_MJ_PNP];
  179. DriverBlock->DriverObject->MajorFunction[IRP_MJ_PNP] = PnPDispatch;
  180. }
  181. }
  182. /****************************************************************************/
  183. /* PnPDispatch */
  184. /****************************************************************************/
  185. /* */
  186. /* Routine Description: */
  187. /* */
  188. /* Dispatch routine for IRP_MJ_PNP that is called by the I/O system. */
  189. /* We process surprise removal and query capabilities. */
  190. /* In all cases, we pass on the IRP to NDIS for further processing. */
  191. /* */
  192. /* Arguments: */
  193. /* */
  194. /* pDeviceObject - pointer to Device Object */
  195. /* pIrp - pointer to IRP */
  196. /* */
  197. /* Return: */
  198. /* */
  199. /* VOID */
  200. /* */
  201. /****************************************************************************/
  202. NTSTATUS
  203. PnPDispatch(IN PDEVICE_OBJECT pDeviceObject,
  204. IN PIRP pIrp)
  205. {
  206. PIO_STACK_LOCATION pIrpSp;
  207. NTSTATUS Status;
  208. PDRIVER_BLOCK DriverBlock;
  209. PRNDISMP_ADAPTER pAdapter;
  210. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  211. DeviceObjectToAdapterAndDriverBlock(pDeviceObject, &pAdapter, &DriverBlock);
  212. TRACE3(("PnPDispatch: Adapter %x, MinorFunction %x\n",
  213. pAdapter, pIrpSp->MinorFunction));
  214. switch (pIrpSp->MinorFunction)
  215. {
  216. case IRP_MN_QUERY_CAPABILITIES:
  217. pIrpSp->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = 1;
  218. break;
  219. case IRP_MN_SURPRISE_REMOVAL:
  220. TRACE1(("PnPDispatch: PDO %p, Adapter %p, surprise removal!\n",
  221. pDeviceObject, pAdapter));
  222. if (pAdapter)
  223. {
  224. RndismpInternalHalt((NDIS_HANDLE)pAdapter, FALSE);
  225. }
  226. break;
  227. default:
  228. break;
  229. }
  230. Status = (DriverBlock->SavedPnPDispatch)(
  231. pDeviceObject,
  232. pIrp);
  233. return (Status);
  234. }
  235. #ifdef BUILD_WIN9X
  236. /****************************************************************************/
  237. /* HookNtKernCMHandler */
  238. /****************************************************************************/
  239. /* */
  240. /* Routine Description: */
  241. /* */
  242. /* Swap the CM handler routine within NDIS' data structures such that */
  243. /* we get called when NDIS forwards a CM message. This can only work on */
  244. /* Win98 and Win98SE. */
  245. /* */
  246. /* Arguments: */
  247. /* */
  248. /* Adapter - pointer to our adapter block */
  249. /* */
  250. /* Return: */
  251. /* */
  252. /* VOID */
  253. /* */
  254. /****************************************************************************/
  255. VOID
  256. HookNtKernCMHandler(IN PRNDISMP_ADAPTER pAdapter)
  257. {
  258. PVOID pNdisWrapperAdapterBlock;
  259. PVOID pDetect;
  260. ULONG WrapContextOffset;
  261. pDetect = (PVOID)((ULONG_PTR)pAdapter->MiniportAdapterHandle + 0x29c);
  262. if (*(PVOID *)pDetect == (PVOID)pAdapter->pPhysDeviceObject)
  263. {
  264. // Win98Gold
  265. WrapContextOffset = 0xf8;
  266. pAdapter->bRunningOnWin98Gold = TRUE;
  267. }
  268. else
  269. {
  270. // Win98SE
  271. WrapContextOffset = 0x60;
  272. pAdapter->bRunningOnWin98Gold = FALSE;
  273. }
  274. pAdapter->WrapContextOffset = WrapContextOffset;
  275. pNdisWrapperAdapterBlock = *(PVOID *)((ULONG_PTR)pAdapter->MiniportAdapterHandle + WrapContextOffset);
  276. // Save away the old handler:
  277. pAdapter->NdisCmConfigHandler = (MY_CMCONFIGHANDLER)
  278. (*(PVOID *)((ULONG_PTR)pNdisWrapperAdapterBlock + 0x78));
  279. // Insert our routine:
  280. (*(PVOID *)((ULONG_PTR)pNdisWrapperAdapterBlock + 0x78)) =
  281. (PVOID)RndisCMHandler;
  282. // Save the devnode to use on lookups based on devnode:
  283. pAdapter->DevNode = (MY_DEVNODE)
  284. (*(PVOID *)((ULONG_PTR)pNdisWrapperAdapterBlock + 0x38));
  285. TRACE1(("HookNtKernCMHandler: Adapter %p, NdisHandler %p, DevNode %x\n",
  286. pAdapter, pAdapter->NdisCmConfigHandler, pAdapter->DevNode));
  287. }
  288. /****************************************************************************/
  289. /* UnHookNtKernCMHandler */
  290. /****************************************************************************/
  291. /* */
  292. /* Routine Description: */
  293. /* */
  294. /* Put back the swapped Config Mgr handler in NDIS' data structures */
  295. /* */
  296. /* Arguments: */
  297. /* */
  298. /* Adapter - pointer to our adapter block */
  299. /* */
  300. /* Return: */
  301. /* */
  302. /* VOID */
  303. /* */
  304. /****************************************************************************/
  305. VOID
  306. UnHookNtKernCMHandler(IN PRNDISMP_ADAPTER pAdapter)
  307. {
  308. PVOID pNdisWrapperAdapterBlock;
  309. if (pAdapter->NdisCmConfigHandler)
  310. {
  311. pNdisWrapperAdapterBlock = *(PVOID *)((ULONG_PTR)pAdapter->MiniportAdapterHandle + pAdapter->WrapContextOffset);
  312. (*(PVOID *)((ULONG_PTR)pNdisWrapperAdapterBlock + 0x78)) =
  313. (PVOID)pAdapter->NdisCmConfigHandler;
  314. }
  315. TRACE1(("UnhookNtKernCMHandler: Adapter %p, NdisHandler %p, DevNode %x\n",
  316. pAdapter, pAdapter->NdisCmConfigHandler, pAdapter->DevNode));
  317. }
  318. /****************************************************************************/
  319. /* RndisCMHandler */
  320. /****************************************************************************/
  321. /* */
  322. /* Routine Description: */
  323. /* */
  324. /* Handler to intercept Config Mgr messages forwarded by NDIS. The only */
  325. /* message of interest is a CONFIG_PREREMOVE, which is our only indication */
  326. /* on Win98 and Win98SE that the device is being removed. */
  327. /* */
  328. /* Arguments: */
  329. /* */
  330. /* Various - documented in Win9x CFmgr header. */
  331. /* */
  332. /* Return: */
  333. /* */
  334. /* MY_CONFIGRET */
  335. /* */
  336. /****************************************************************************/
  337. MY_CONFIGRET __cdecl
  338. RndisCMHandler(IN MY_CONFIGFUNC cfFuncName,
  339. IN MY_SUBCONFIGFUNC cfSubFuncName,
  340. IN MY_DEVNODE cfDevNode,
  341. IN ULONG dwRefData,
  342. IN ULONG ulFlags)
  343. {
  344. PRNDISMP_ADAPTER pAdapter, pTmpAdapter;
  345. PDRIVER_BLOCK pDriverBlock;
  346. MY_CONFIGRET crRetCode;
  347. do
  348. {
  349. //
  350. // Find the adapter to which this is addressed.
  351. //
  352. pAdapter = NULL;
  353. NdisAcquireSpinLock(&RndismpGlobalLock);
  354. for (pDriverBlock = RndismpMiniportBlockListHead.NextDriverBlock;
  355. (pDriverBlock != NULL) && (pAdapter == NULL);
  356. pDriverBlock = pDriverBlock->NextDriverBlock)
  357. {
  358. for (pTmpAdapter = pDriverBlock->AdapterList;
  359. pTmpAdapter != NULL;
  360. pTmpAdapter = pTmpAdapter->NextAdapter)
  361. {
  362. if (pTmpAdapter->DevNode == cfDevNode)
  363. {
  364. pAdapter = pTmpAdapter;
  365. break;
  366. }
  367. }
  368. }
  369. NdisReleaseSpinLock(&RndismpGlobalLock);
  370. ASSERT(pAdapter != NULL);
  371. TRACE1(("CMHandler: Adapter %p, CfFuncName %x\n",
  372. pAdapter, cfFuncName));
  373. //
  374. // Forward this on before acting on it.
  375. //
  376. if (pAdapter &&
  377. (pAdapter->NdisCmConfigHandler != NULL))
  378. {
  379. crRetCode = pAdapter->NdisCmConfigHandler(
  380. cfFuncName,
  381. cfSubFuncName,
  382. cfDevNode,
  383. dwRefData,
  384. ulFlags);
  385. if ((cfFuncName == MY_CONFIG_PREREMOVE) ||
  386. ((cfFuncName == MY_CONFIG_PRESHUTDOWN) &&
  387. (pAdapter->bRunningOnWin98Gold)))
  388. {
  389. RndismpInternalHalt((NDIS_HANDLE)pAdapter, FALSE);
  390. }
  391. }
  392. else
  393. {
  394. crRetCode = MY_CR_SUCCESS;
  395. }
  396. }
  397. while (FALSE);
  398. return (crRetCode);
  399. }
  400. #endif // BUILD_WIN9X