PTEXTEND.C
上传用户:zhuzhu0204
上传日期:2020-07-13
资源大小:13165k
文件大小:15k
开发平台:

Visual C++

  1. /////////////////////////////////////////////////
  2. // PTEXTEND.c文件
  3. #include "precomp.h"
  4. #pragma hdrstop
  5. #include "iocommon.h"
  6. extern NDIS_SPIN_LOCK GlobalLock;
  7. extern PADAPT pAdaptList;
  8. //////////////////////////////////////////
  9. // 派遣例程
  10. // 这是处理IRP_MJ_CREATE的派遣例程,我们仅简单的返回成功
  11. NTSTATUS DevOpen(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
  12. {
  13. NTSTATUS status = STATUS_SUCCESS;
  14. PIO_STACK_LOCATION pIrpStack;
  15. // 初始化这个新的文件对象
  16. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  17. pIrpStack->FileObject->FsContext = NULL;
  18. pIrpStack->FileObject->FsContext2 = NULL;
  19. // DBGPRINT(("  DevOpen: FileObject %pn", pIrpStack->FileObject));
  20. // 完成此IRP请求
  21. pIrp->IoStatus.Information = 0;
  22. pIrp->IoStatus.Status = status;
  23. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  24. return status;
  25. }
  26. // 这是处理IRP_MJ_CLEANUP的派遣例程
  27. NTSTATUS DevCleanup(PDEVICE_OBJECT pDeviceObject,PIRP pIrp)
  28. {
  29.     PIO_STACK_LOCATION  pIrpSp;
  30.     NTSTATUS            status = STATUS_SUCCESS;
  31.     POPEN_CONTEXT       pOpenContext;
  32. // 取得句柄
  33.     pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  34.     pOpenContext = pIrpSp->FileObject->FsContext;
  35.     if(pOpenContext)
  36.     {
  37. // 在这里取消所有未决的IRP。这个例子里没有。
  38.     }
  39.     pIrp->IoStatus.Information = 0;
  40.     pIrp->IoStatus.Status = status;
  41.     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  42.     return status;
  43. // 这是处理IRP_MJ_CLOSE的派遣例程,如果是适配器句柄,我们要减小对打开环境的引用
  44. NTSTATUS DevClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
  45. {
  46. NTSTATUS status = STATUS_SUCCESS;
  47. PIO_STACK_LOCATION pIrpStack;
  48. POPEN_CONTEXT pOpenContext;
  49. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  50. pOpenContext = (POPEN_CONTEXT)pIrpStack->FileObject->FsContext;
  51. pIrpStack->FileObject->FsContext = NULL;
  52. pIrpStack->FileObject->FsContext2 = NULL;
  53. if(pOpenContext != NULL) // 关闭的是一个适配器句柄
  54. {
  55. if(pOpenContext->pAdapt != NULL)
  56. {
  57. NdisAcquireSpinLock(&(pOpenContext->pAdapt)->Lock);
  58. (pOpenContext->pAdapt)->pOpenContext = NULL;
  59. NdisReleaseSpinLock(&(pOpenContext->pAdapt)->Lock);
  60. }
  61. DevDerefOpenContext(pOpenContext);
  62. }
  63. // 完成此IRP请求
  64. pIrp->IoStatus.Information = 0;
  65. pIrp->IoStatus.Status = status;
  66. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  67. return status;
  68. }
  69. // 这是处理IRP_MJ_DEVICE_CONTROL的派遣例程,如果是适配器句柄,我们要减小对打开环境的引用
  70. NTSTATUS DevIoControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
  71. {
  72. // 假设失败
  73. NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  74. // 取得此IRP(pIrp)的I/O堆栈指针
  75. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  76. // 取得I/O控制代码
  77. ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
  78. // 取得I/O缓冲区指针和它的长度
  79. PVOID pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  80. ULONG uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  81. ULONG uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  82. ULONG uTransLen = 0;
  83. // DBGPRINT((" DevIoControl... n"));
  84. switch(uIoControlCode)
  85. {
  86. case IOCTL_PTUSERIO_ENUMERATE:
  87. {
  88. status = DevGetBindingList(pIoBuffer, uOutSize, &uTransLen);
  89. }
  90. break;
  91. case IOCTL_PTUSERIO_OPEN_ADAPTER: // 打开一个适配器。实际上是为适配器关联一个OPEN_CONTEXT结构
  92. {
  93. POPEN_CONTEXT pOpenContext;
  94. PADAPT pAdapt = LookupAdaptByName((PUCHAR)pIoBuffer, uInSize);
  95. if(pAdapt == NULL)
  96. {
  97. status = STATUS_OBJECT_NAME_NOT_FOUND;
  98. break;
  99. }
  100. // 如果正在Unbind,则失败
  101. NdisAcquireSpinLock(&pAdapt->Lock);  
  102. if(pAdapt->UnbindingInProcess)
  103. {
  104. NdisReleaseSpinLock(&pAdapt->Lock);
  105. PtDerefAdapter(pAdapt);
  106. status = STATUS_INVALID_DEVICE_STATE;
  107. break;
  108. }
  109. NdisReleaseSpinLock(&pAdapt->Lock);
  110. // 如果适配器已经打开,则失败
  111. if(pAdapt->pOpenContext != NULL)
  112. {
  113. PtDerefAdapter(pAdapt);
  114. status = STATUS_DEVICE_BUSY;
  115. break;
  116. }
  117. // 为新的OPEN_CONTEXT结构申请内存空间
  118. pOpenContext = DevAllocateOpenContext(pAdapt);
  119. if(pOpenContext == NULL)
  120. {
  121. PtDerefAdapter(pAdapt);
  122. status = STATUS_INSUFFICIENT_RESOURCES;
  123. break;
  124. }
  125. // 在ADAPT结构中保存pOpenContext指针
  126. // InterlockedXXX函数执行原子操作:首先它将pAdapt->pOpenContext
  127. // 与NULL检查,如果它们相等,这个函数将pOpenContext放入pAdapt->pOpenContext,
  128. // 返回NULL。否则,它仅返回现存的Adapt->pOpenContext,不改变任何值。
  129. /* 功能上相当于 
  130. if(pAdapt->pOpenContext == NULL)
  131. {
  132. pAdapt->pOpenContext = pOpenContext;
  133. }
  134. else
  135. {
  136. // error 
  137. }*/
  138. if(InterlockedCompareExchangePointer(&(pAdapt->pOpenContext), 
  139. pOpenContext, NULL) != NULL)
  140. {
  141. PtDerefAdapter(pAdapt);
  142. status = STATUS_DEVICE_BUSY;
  143. break;
  144. }
  145. // 将打开环境与句柄关联
  146. pIrpStack->FileObject->FsContext = pOpenContext;
  147. status = STATUS_SUCCESS;
  148. }
  149. break;
  150. case IOCTL_PTUSERIO_QUERY_OID:
  151. case IOCTL_PTUSERIO_SET_OID: 
  152. {
  153. return DevHandleOidRequest(pDeviceObject, pIrp);
  154. }
  155. break;
  156. default:
  157. return FltDevIoControl(pDeviceObject, pIrp);
  158. }
  159. if(status == STATUS_SUCCESS)
  160. pIrp->IoStatus.Information = uTransLen;
  161. else
  162. pIrp->IoStatus.Information = 0;
  163. pIrp->IoStatus.Status = status;
  164. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  165. return status;
  166. }
  167. //////////////////////////////////
  168. // 处理IOCTL时要使用的函数
  169. // 处理用户的OID请求
  170. NTSTATUS DevHandleOidRequest(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
  171. {
  172. // 假设失败
  173. NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  174. // 取得此IRP(pIrp)的I/O堆栈指针
  175. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  176. // 取得I/O控制代码
  177. ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
  178. // 取得I/O缓冲区指针和它的长度
  179. PPTUSERIO_OID_DATA pOidData = (PPTUSERIO_OID_DATA)pIrp->AssociatedIrp.SystemBuffer;
  180. ULONG uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  181. ULONG uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  182. ULONG uTransLen = 0;
  183. POPEN_CONTEXT pOpenContext;
  184. PADAPT pAdapt;
  185. do
  186. {
  187. // 取得与此句柄关联的OPEN_CONTEXT结构的指针 // 首先检查此句柄是否打开适配器
  188. pOpenContext = (POPEN_CONTEXT)pIrpStack->FileObject->FsContext;
  189. if(pOpenContext == NULL)
  190. {
  191. status = STATUS_INVALID_HANDLE;
  192. break;
  193. }
  194. pAdapt = pOpenContext->pAdapt;
  195. if(pAdapt == NULL)
  196. {
  197. status = STATUS_INVALID_HANDLE;
  198. break;
  199. }
  200. // 检查缓冲区
  201. if(uOutSize != uInSize || uOutSize < sizeof(PTUSERIO_OID_DATA) ||
  202. uOutSize < sizeof(PTUSERIO_OID_DATA) - 1 + pOidData->Length)
  203. {
  204. status = STATUS_INVALID_PARAMETER;
  205. break;
  206. }
  207. // 如果Unbind正在进行,则失败
  208. NdisAcquireSpinLock(&pAdapt->Lock);
  209. if( pAdapt->UnbindingInProcess )
  210. {
  211. NdisReleaseSpinLock(&pAdapt->Lock);
  212. DBGPRINT(( "      Unbind In Processn" ));
  213. status = STATUS_INVALID_DEVICE_STATE;
  214. break;
  215. }
  216. //
  217. // All other queries are failed, if the miniport is not at D0,
  218. //
  219. if (pAdapt->MPDeviceState > NdisDeviceStateD0)
  220. {
  221. NdisReleaseSpinLock(&pAdapt->Lock);
  222. DBGPRINT(( "      Invalid Miniport Device Staten" ));
  223. status = STATUS_INVALID_DEVICE_STATE;
  224. break;
  225. }
  226. //
  227. // This is in the process of powering down the system, always fail the request
  228. // 
  229. if (pAdapt->StandingBy == TRUE)
  230. {
  231. NdisReleaseSpinLock(&pAdapt->Lock);
  232. DBGPRINT(( "      Miniport Powering Downn" ));
  233. status = STATUS_INVALID_DEVICE_STATE;
  234. break;
  235. }
  236. NdisReleaseSpinLock(&pAdapt->Lock);
  237. // 检查完毕,最后,进行这个请求
  238. DevRefOpenContext(pOpenContext);
  239. // 初始化NDIS_REQUEST结构
  240. NdisZeroMemory(&pOpenContext->Request, sizeof(pOpenContext->Request));
  241. if(uIoControlCode == IOCTL_PTUSERIO_SET_OID)
  242. pOpenContext->Request.RequestType = NdisRequestSetInformation;
  243. pOpenContext->Request.DATA.SET_INFORMATION.Oid = pOidData->Oid;
  244. pOpenContext->Request.DATA.SET_INFORMATION.InformationBuffer = pOidData->Data;
  245. pOpenContext->Request.DATA.SET_INFORMATION.InformationBufferLength = pOidData->Length;
  246. }
  247. else
  248. {
  249. pOpenContext->Request.RequestType = NdisRequestQueryInformation;
  250. pOpenContext->Request.DATA.QUERY_INFORMATION.Oid = pOidData->Oid;
  251. pOpenContext->Request.DATA.QUERY_INFORMATION.InformationBuffer = pOidData->Data;
  252. pOpenContext->Request.DATA.QUERY_INFORMATION.InformationBufferLength = pOidData->Length;
  253. }
  254. NdisResetEvent( &pOpenContext->RequestEvent);
  255. // 提交这个请求
  256. NdisRequest(&status, pAdapt->BindingHandle, &pOpenContext->Request);
  257. if(status != NDIS_STATUS_PENDING)
  258. {
  259. DevRequestComplete(pAdapt, &pOpenContext->Request, status);
  260. }
  261. // 等待请求的完成,即等待Ndis调用DevRequestComplete例程
  262. NdisWaitEvent(&pOpenContext->RequestEvent, 0);
  263. if(pOpenContext->RequestStatus == NDIS_STATUS_SUCCESS)
  264. {
  265. //  将大小返回到用户缓冲区
  266. if(uIoControlCode == IOCTL_PTUSERIO_SET_OID) 
  267. {
  268. pOidData->Length = pOpenContext->Request.DATA.SET_INFORMATION.BytesRead;
  269. else if(uIoControlCode == IOCTL_PTUSERIO_QUERY_OID) 
  270. {
  271. pOidData->Length = pOpenContext->Request.DATA.QUERY_INFORMATION.BytesWritten;
  272. }
  273. // 设置返回给I/O管理器的信息
  274. uTransLen = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  275. status = STATUS_SUCCESS;
  276. }
  277. else
  278. {
  279. status = STATUS_UNSUCCESSFUL;
  280. }
  281. DevDerefOpenContext(pOpenContext);
  282. }
  283. while(FALSE);
  284. if(status == STATUS_SUCCESS)
  285. pIrp->IoStatus.Information = uTransLen;
  286. else
  287. pIrp->IoStatus.Information = 0;
  288. pIrp->IoStatus.Status = status;
  289. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  290. return status;
  291. }
  292. VOID DevRequestComplete(PADAPT pAdapt, PNDIS_REQUEST NdisRequest,NDIS_STATUS Status)
  293. {
  294. POPEN_CONTEXT pOpenContext = CONTAINING_RECORD(NdisRequest, OPEN_CONTEXT, Request);
  295. pOpenContext->RequestStatus = Status;
  296.     NdisSetEvent(&pOpenContext->RequestEvent);
  297. }
  298. // 获取绑定列表
  299. NTSTATUS DevGetBindingList(
  300.     IN  PVOID              Buffer, // 缓冲区
  301.     IN  ULONG              Length, // 缓冲区大小
  302.     IN  OUT PULONG         DataLength // 返回实际需要的长度
  303.     )
  304. {
  305. PADAPT pAdapt ;
  306. // 遍历列表,计算所需的缓冲区大小
  307. ULONG nRequiredLength = 0;
  308. ULONG nAdapters = 0;
  309. NdisAcquireSpinLock(&GlobalLock);
  310. pAdapt = pAdaptList;
  311. while(pAdapt != NULL)
  312. {
  313. nRequiredLength += pAdapt->DeviceName.Length + sizeof(UNICODE_NULL); 
  314. nRequiredLength += pAdapt->LowerDeviceName.Length + sizeof(UNICODE_NULL);
  315. nAdapters++;
  316. pAdapt = pAdapt->Next;
  317. }
  318. // 我们将要以下面的格式返回数据:
  319. // nAdapters + 一个或者多个("DeviceName" + "LowerDeviceName") + UNICODE_NULL
  320. // 所以,下面要包含上nAapters和UNICODE_NULL的大小
  321. nRequiredLength += sizeof(nAdapters) + sizeof(UNICODE_NULL); 
  322. *DataLength = nRequiredLength;
  323. if(nRequiredLength > Length) 
  324. {
  325.        NdisReleaseSpinLock(&GlobalLock);
  326.        return STATUS_BUFFER_TOO_SMALL;
  327.     }
  328. // 填充缓冲区
  329. // 首先是适配器数量
  330. *(PULONG)Buffer = nAdapters;
  331. Buffer = (PCHAR)Buffer + sizeof(ULONG);
  332. // 然后复制适配器和符号连接名称
  333. pAdapt = pAdaptList;
  334. while(pAdapt != NULL)
  335. {
  336. NdisMoveMemory(Buffer,pAdapt->DeviceName.Buffer, pAdapt->DeviceName.Length + sizeof(WCHAR));
  337. Buffer = (PCHAR)Buffer + pAdapt->DeviceName.Length + sizeof(WCHAR);
  338.         NdisMoveMemory(Buffer,pAdapt->LowerDeviceName.Buffer, pAdapt->LowerDeviceName.Length + sizeof(WCHAR)); 
  339. Buffer = (PCHAR)Buffer + pAdapt->LowerDeviceName.Length + sizeof(WCHAR);    
  340. pAdapt = pAdapt->Next;
  341.     }
  342. // 最后的结束标志
  343.     *(PWCHAR)Buffer = UNICODE_NULL;
  344.     
  345.     NdisReleaseSpinLock(&GlobalLock);
  346. return STATUS_SUCCESS;
  347. }
  348. ////////////////////////////////////////////
  349. // 帮助函数
  350. // 更加适配器名称查找适配器的PADAPT结构
  351. PADAPT LookupAdaptByName(PUCHAR pNameBuffer, ULONG nNameLength)
  352. {
  353. PADAPT pAdapt;
  354. NdisAcquireSpinLock(&GlobalLock);
  355. pAdapt = pAdaptList;
  356. while(pAdapt != NULL)
  357. {
  358. if(pAdapt->LowerDeviceName.Length == nNameLength &&
  359. NdisEqualMemory(pAdapt->LowerDeviceName.Buffer, pNameBuffer, nNameLength))
  360. break;
  361. pAdapt = pAdapt->Next;
  362. }
  363. // 防止在引用适配器期间,系统释放缓冲区
  364. if(pAdapt != NULL)
  365. PtRefAdapter(pAdapt);
  366. NdisReleaseSpinLock(&GlobalLock);
  367. return pAdapt;
  368. }
  369. /*------------------------------------------------------------------------------
  370. // 申请和初始化一个POPEN_CONTEXT结构
  371. POPEN_CONTEXT DevAllocateOpenContext(PADAPT pAdapt)
  372. {
  373. POPEN_CONTEXT pOpenContext = NULL;
  374. // 为OPEN_CONTEXT结构申请内存空间
  375. NdisAllocateMemoryWithTag(&pOpenContext, sizeof(OPEN_CONTEXT), TAG);
  376. if(pOpenContext == NULL)
  377. {
  378. return NULL;
  379. }
  380. // 初始化这个内存空间
  381. NdisZeroMemory(pOpenContext, sizeof(OPEN_CONTEXT));
  382. NdisAllocateSpinLock(&pOpenContext->Lock);
  383. NdisInitializeEvent(&pOpenContext->RequestEvent);
  384. pOpenContext->RefCount = 1;
  385. pOpenContext->pAdapt = pAdapt;
  386. return pOpenContext;
  387. }
  388. ------------------------------------------------------------------------------*/
  389. /*------------------------------------------------------------------------------
  390. // 增加对适配器(PADAPT结构)的引用
  391. VOID PtRefAdapter(PADAPT pAdapt)
  392. {
  393.    NdisInterlockedIncrement(&pAdapt->RefCount);
  394. }
  395. // 减小对适配器(PADAPT结构)的引用,如果减为0,则释放它占用的内存
  396. VOID PtDerefAdapter(PADAPT pAdapt) 
  397. {
  398. if(pAdapt == NULL)
  399. return;
  400.  
  401. if(NdisInterlockedDecrement(&pAdapt->RefCount) == 0) // 已经没有代码再引用它了,释放内存
  402. {
  403. MPFreeAllPacketPools (pAdapt);
  404. // BEGIN_PTEX_FILTER
  405.       //
  406.       // 反初始化此适配器上的过滤相关数据
  407.       //
  408.       FltOnDeinitAdapter(pAdapt);
  409. // END_PTEX_FILTER
  410. NdisFreeMemory(pAdapt, 0, 0);
  411. }
  412. }
  413. ------------------------------------------------------------------------------*/
  414. /*------------------------------------------------------------------------------
  415. // 增加对打开环境的引用
  416. VOID DevRefOpenContext(POPEN_CONTEXT pOpenContext) 
  417. {
  418. // 首先增加对适配器的引用,然后再增加OPEN_CONTEXT的引用计数
  419.    PtRefAdapter(pOpenContext->pAdapt);
  420.    NdisInterlockedIncrement(&pOpenContext->RefCount);
  421. }
  422. // 减少对打开环境的引用,如果减为0,则释放它占用的内存
  423. VOID DevDerefOpenContext(POPEN_CONTEXT pOpenContext) 
  424. {
  425.    PADAPT pAdapt = NULL;
  426.    if(pOpenContext == NULL)
  427.    return;
  428.    // 首先保存对应的适配器指针,以便后面对它调用PtDerefAdapter函数
  429.    pAdapt = pOpenContext->pAdapt;
  430.    // 减小引用计数,如果没有代码再引用它了,则清除资源
  431.    if(NdisInterlockedDecrement(&pOpenContext->RefCount) == 0)
  432.    {
  433.       NdisFreeSpinLock(&pOpenContext->Lock);
  434.       NdisFreeMemory(pOpenContext, 0, 0);
  435.    }
  436.    // 减少对适配器的引用
  437.    PtDerefAdapter(pAdapt);
  438. }
  439. ------------------------------------------------------------------------------*/
  440. /*NTSTATUS DevOpenAdapter(PUCHAR pNameBuffer, ULONG nNameLength, )
  441. {
  442. }*/