- 自己在編寫驅動程序的時候 遇到一些疑問: IoBuildSynchronousFsdRequest 和IoBuildAsynchronousFsdRequest之間創建的同步異步IRP有什麼區別?
- 爲什麼這兩個函數只能創建幾種IRP?調用IoAllocateIrp後 初始化IRP時哪些域是要填充的 哪些是不要填充的?
- 偏偏書上講的都很模糊 驅動新手 一切只能自己動手。
- 先來看下 IoBuildSynchronousFsdRequest
- .text:004191D6 _IoBuildSynchronousFsdRequest@28 proc near
- .text:004191D6 ; CODE XREF: HalExamineMBR(x,x,x,x)+70p
- .text:004191D6 ; IopShutdownBaseFileSystems(x)+7Ap ...
- .text:004191D6
- .text:004191D6 MajorFunction = dword ptr 8
- .text:004191D6 DeviceObject = dword ptr 0Ch
- .text:004191D6 Buffer = dword ptr 10h
- .text:004191D6 Length = dword ptr 14h
- .text:004191D6 StartingOffset = dword ptr 18h
- .text:004191D6 Event = dword ptr 1Ch
- .text:004191D6 IoStatusBlock = dword ptr 20h
- .text:004191D6
- .text:004191D6 mov edi, edi
- .text:004191D8 push ebp
- .text:004191D9 mov ebp, esp
- .text:004191DB push edi
- .text:004191DC push [ebp+IoStatusBlock] ; IoStatusBlock
- .text:004191DF push [ebp+StartingOffset] ; StartingOffset
- .text:004191E2 push [ebp+Length] ; Length
- .text:004191E5 push [ebp+Buffer] ; Buffer
- .text:004191E8 push [ebp+DeviceObject] ; DeviceObject
- .text:004191EB push [ebp+MajorFunction] ; MajorFunction
- .text:004191EE call _IoBuildAsynchronousFsdRequest@24 ; 創建同步IRP 實質上還是創建異步IRP
- .text:004191F3 mov edi, eax ; pIrp送EDI 檢驗IRP是否創建成功
- .text:004191F5 test edi, edi ; pIrp
- .text:004191F7 jz short loc_41922D
- .text:004191F9 mov eax, [ebp+Event] ; event
- .text:004191FC push ebx
- .text:004191FD push esi
- .text:004191FE mov cl, 1
- .text:00419200 mov [edi+2Ch], eax ; pIrp->UserEvent = event
- .text:00419203 call ds:__imp_@KfRaiseIrql@4 ; movzx edx,cl
- .text:00419203 ; movzx ecx,byte ptr [edx-7F92EDA8h]
- .text:00419203 ; mov eax,dword ptr ds:[FFFE0080h];TPR寄存器中當前任務優先級送eax
- .text:00419203 ; mov dword ptr ds:[0FFFE0080h],ecx;裝入新的任務優先級
- .text:00419203 ; shr eax,4;任務優先級/16
- .text:00419203 ; movzx eax,byte ptr [eax-7F923F78h]返回優先級
- .text:00419203 ; ret 中斷級和任務優先級的換算 還要依靠806D1258和806DC088這兩個地方的表或者結構
- .text:00419203 ; 對任務優先級不甚明白 以後有時間再仔細看看
- .text:00419203 ;
- .text:00419209 mov edx, [edi+50h] ; pIrp->Tail.overlay.Thread
- .text:00419209 ; edx值爲ETHREAD的指針
- .text:0041920C add edx, 210h ; ÐREAD.IrpList
- .text:0041920C ; edx值爲ETHREAD.IrpList的指針
- .text:00419212 mov ebx, [edx] ; ETHREAD.IrpList.flink
- .text:00419214 lea esi, [edi+10h] ; &pIrp->ThreadFlink
- .text:00419217 mov [esi], ebx ; pIrp->ThreadListEntry.flink = ETHREAD.IrpList.flink
- .text:00419219 mov [esi+4], edx ; pIrp->ThreadListEntry.blink = ÐREAD.IrpList
- .text:0041921C mov [ebx+4], esi ; ETHREAD.IrpList.flink = &pIrp->ThreadListEntry.flink
- ;IRP與線程關聯
- .text:0041921F mov cl, al
- .text:00419221 mov [edx], esi
- .text:00419223 call ds:__imp_@KfLowerIrql@4 ; 恢復原IRQL
- .text:00419229 pop esi
- .text:0041922A mov eax, edi
- .text:0041922C pop ebx
- .text:0041922D
- .text:0041922D loc_41922D: ; CODE XREF: IoBuildSynchronousFsdRequest(x,x,x,x,x,x,x)+21j
- .text:0041922D pop edi
- .text:0041922E pop ebp
- .text:0041922F retn 1Ch
- .text:0041922F _IoBuildSynchronousFsdRequest@28 endp
- 從上面可以看出同步IRP和異步IRP 區別不是很大 IoBuildSynchronousFsdRequest內部調用了IoBuildAsynchronousFsdRequest 雖然同步IRP填充了IRP.UserEvent
- 但是 在編寫驅動時 爲了知道異步IRP操作什麼時候真正完成 有時候同樣要手動填充irp.UserEvent域。真正有點區別的估計就是同步IRP與線程關聯了
- 而異步IRP沒有。
- 再來看下IoBuildAsynchronousFsdRequest
- .text:00418E96 _IoBuildAsynchronousFsdRequest@24 proc near
- .text:00418E96 ; CODE XREF: IoBuildSynchronousFsdRequest(x,x,x,x,x,x,x)+18p
- .text:00418E96 ; IovBuildAsynchronousFsdRequest(x,x,x,x,x,x)+22p
- .text:00418E96
- .text:00418E96 var_20 = dword ptr -20h
- .text:00418E96 Irp = dword ptr -1Ch
- .text:00418E96 ms_exc = CPPEH_RECORD ptr -18h
- .text:00418E96 MajorFunction = dword ptr 8
- .text:00418E96 DeviceObject = dword ptr 0Ch
- .text:00418E96 VirtualAddress = dword ptr 10h
- .text:00418E96 Length = dword ptr 14h
- .text:00418E96 StartingOffset = dword ptr 18h
- .text:00418E96 IoStatusBlock = dword ptr 1Ch
- .text:00418E96
- .text:00418E96 push 10h
- .text:00418E98 push offset stru_401748
- .text:00418E9D call __SEH_prolog
- .text:00418EA2 mov edi, [ebp+DeviceObject]
- .text:00418EA5 mov al, [edi+30h] ; pDeviceObject->StackSize 送al
- .text:00418EA8 mov byte ptr [ebp+var_20], al
- .text:00418EAB push 0 ; FALSE
- .text:00418EAD push [ebp+var_20]
- .text:00418EB0 call _pIoAllocateIrp ; 分配IRP 通過調用IopAllocateIrpPrivate
- .text:00418EB6 mov esi, eax ; pIrp送esi
- .text:00418EB8 mov [ebp+Irp], esi
- .text:00418EBB test esi, esi
- .text:00418EBD jz loc_418FCC
- .text:00418EC3 mov eax, large fs:124h ; &_KPCR.KPRCB.CurrentThread
- .text:00418EC9 mov [esi+50h], eax ; pIrp->Thread = &KTHREAD KTHREAD 的地址就是ETHREAD地址
- .text:00418ECC mov ebx, [esi+60h] ; pIrp->IoStackLocation
- .text:00418ECF sub ebx, 24h ; IoStackLocation指向一個IO_STACK_LOCATION數組
- .text:00418ECF ; -24h 就是當前IO_STACK_LOCATION[i-1] 這裏開始初始
- .text:00418ECF ; 下一層驅動的IO_STACK_LOCATION
- .text:00418ED2 mov eax, [ebp+MajorFunction]
- .text:00418ED5 mov [ebx], al ; IO_STACK_LOCATION.MajorFunction
- .text:00418ED7 cmp eax, 9 ; IRP_MJ_FLUSH_BUFFERS
- .text:00418EDA jz loc_418F62
- .text:00418EE0 cmp eax, 10h ; IRP_MJ_SHUTDOWN
- .text:00418EE3 jz short loc_418F62
- .text:00418EE5 cmp eax, 1Bh ; IRP_MJ_PNP
- .text:00418EE8 jz short loc_418F62
- .text:00418EEA cmp eax, 16h ; IRP_MJ_POWER
- .text:00418EED jz short loc_418F62
- .text:00418EEF mov eax, [edi+1Ch] ; pDeviceObject->flag 初始flag是C8H
- .text:00418EF2 test al, 4 ; DO_BUFFER_IO置位 是CCH
- .text:00418EF4 jz short loc_418F72
- .text:00418EF6 push 20206F49h ; Tag
- .text:00418EFB push [ebp+Length] ; NumberOfBytes
- .text:00418EFE push 4 ; PoolType
- .text:00418F00 call _ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)
- .text:00418F05 mov [esi+0Ch], eax ; pIrp->AssociatedIrp.SystemBuffer
- .text:00418F08 test eax, eax
- .text:00418F0A jnz short loc_418F17
- .text:00418F0C
- .text:00418F0C loc_418F0C: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+F5j
- .text:00418F0C push esi ; Irp
- .text:00418F0D call _IoFreeIrp@4 ; IoFreeIrp(x)
- .text:00418F12 jmp loc_418FCC
- .text:00418F17 ; ---------------------------------------------------------------------------
- .text:00418F17
- .text:00418F17 loc_418F17: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+74j
- .text:00418F17 cmp [ebp+MajorFunction], 4 ; IRP_MJ_WRITE
- .text:00418F1B jnz short loc_418F41
- .text:00418F1D mov ecx, [ebp+Length] ; 如果是寫請求的話
- .text:00418F20 mov esi, [ebp+VirtualAddress]
- .text:00418F23 mov edi, eax ; 把 參數中PVOID提供的內存 複製到 分配出來的內存中的內容 中去
- .text:00418F25 mov eax, ecx
- .text:00418F27 shr ecx, 2
- .text:00418F2A rep movsd
- .text:00418F2C mov ecx, eax
- .text:00418F2E and ecx, 3
- .text:00418F31 rep movsb
- .text:00418F33 mov eax, [ebp+Irp]
- .text:00418F36 mov dword ptr [eax+8], 30h ; pIrp->Flags
- .text:00418F3D mov esi, eax
- .text:00418F3F jmp short loc_418F4E
- .text:00418F41 ; ---------------------------------------------------------------------------
- .text:00418F41
- .text:00418F41 loc_418F41: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+85j
- .text:00418F41 mov dword ptr [esi+8], 70h
- .text:00418F48
- .text:00418F48 loc_418F48: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+DEj
- .text:00418F48 mov eax, [ebp+VirtualAddress]
- .text:00418F4B mov [esi+3Ch], eax
- .text:00418F4E
- .text:00418F4E loc_418F4E: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+A9j
- .text:00418F4E ; IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+113j
- .text:00418F4E mov eax, [ebp+Length]
- .text:00418F4B mov [esi+3Ch], eax ; pIrp->UserBuffer IRP_MJ_READ 時 DO_BUFFERED_IO模式下保存參數中的內存首地址
- .text:00418F4B ; 看了下整個函數只有這裏 和IRP_MJ_READ提供的內存有關 猜測驅動在完成IRP後
- .text:00418F4B ; 系統會尋找UserBuffer域然後 複製systembuffer裏的東西
- .text:00418F4E
- .text:00418F4E loc_418F4E: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+A9j
- .text:00418F4E ; IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+113j
- .text:00418F4E mov eax, [ebp+Length]
- .text:00418F51 mov [ebx+4], eax ; IO_STACK_LOCATION.Write.Length
- .text:00418F51 mov [ebx+4], eax ; IO_STACK_LOCATION.Write.Length
- .text:00418F54 mov eax, [ebp+StartingOffset]
- .text:00418F57 mov ecx, [eax]
- .text:00418F59 mov [ebx+0Ch], ecx ; IO_STACK_LOCATION.Write.ByteOffset.u.LowPart
- .text:00418F5C mov eax, [eax+4]
- .text:00418F5F mov [ebx+10h], eax ; IO_STACK_LOCATION.Write.ByteOffset.u.HighPart
- .text:00418F62
- .text:00418F62 loc_418F62: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+44j
- .text:00418F62 ; IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+4Dj ...
- .text:00418F62 mov eax, [ebp+IoStatusBlock]
- .text:00418F65 mov [esi+28h], eax ; pIrp->UserIosb
- .text:00418F68 mov eax, esi
- .text:00418F6A
- .text:00418F6A loc_418F6A: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+138j
- .text:00418F6A call __SEH_epilog
- .text:00418F6F retn 18h
- .text:00418F72 ; ---------------------------------------------------------------------------
- .text:00418F72
- .text:00418F72 loc_418F72: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+5Ej
- .text:00418F72 test al, 10h ; DO_DIRECT_IO
- .text:00418F74 jz short loc_418F48
- .text:00418F76 xor edi, edi
- .text:00418F78 push edi ; Irp
- .text:00418F79 push edi ; ChargeQuota
- .text:00418F7A push edi ; SecondaryBuffer
- .text:00418F7B push [ebp+Length] ; Length
- .text:00418F7E push [ebp+VirtualAddress] ; VirtualAddress
- .text:00418F81 call _IoAllocateMdl@20 ; 分配一個MDL
- .text:00418F86 mov [esi+4], eax ; pIrp->MdlAddress
- .text:00418F89 cmp eax, edi
- .text:00418F8B jz loc_418F0C
- .text:00418F91 mov [ebp+ms_exc.disabled], edi
- .text:00418F94 xor ecx, ecx
- .text:00418F96 cmp [ebp+MajorFunction], 3 ; IRP_MJ_READ
- .text:00418F9A setz cl ; 如果是IRP_MJ_READ cl置位
- .text:00418F9D push ecx ; Operation
- .text:00418F9E push edi ; AccessMode
- .text:00418F9F push eax ; MemoryDescriptorList
- .text:00418FA0 call _MmProbeAndLockPages@12 ; 鎖定MDL
- .text:00418FA5 or [ebp+ms_exc.disabled], 0FFFFFFFFh
- .text:00418FA9 jmp short loc_418F4E
- .text:00418FAB ; ---------------------------------------------------------------------------
- .text:00418FAB
- .text:00418FAB loc_418FAB: ; DATA XREF: .text:stru_401748o
- .text:00418FAB xor eax, eax
- .text:00418FAD inc eax
- .text:00418FAE retn
- .text:00418FAF ; ---------------------------------------------------------------------------
- .text:00418FAF
- .text:00418FAF loc_418FAF: ; DATA XREF: .text:stru_401748o
- .text:00418FAF mov esp, [ebp+ms_exc.old_esp]
- .text:00418FB2 mov esi, [ebp+Irp]
- .text:00418FB5 mov eax, [esi+4]
- .text:00418FB8 test eax, eax
- .text:00418FBA jz short loc_418FC2
- .text:00418FBC push eax ; Mdl
- .text:00418FBD call _IoFreeMdl@4 ; IoFreeMdl(x)
- .text:00418FC2
- .text:00418FC2 loc_418FC2: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+124j
- .text:00418FC2 push esi ; Irp
- .text:00418FC3 call _IoFreeIrp@4 ; IoFreeIrp(x)
- .text:00418FC8 or [ebp+ms_exc.disabled], 0FFFFFFFFh
- .text:00418FCC
- .text:00418FCC loc_418FCC: ; CODE XREF: IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+27j
- .text:00418FCC ; IoBuildAsynchronousFsdRequest(x,x,x,x,x,x)+7Cj
- .text:00418FCC xor eax, eax
- .text:00418FCE jmp short loc_418F6A
- .text:00418FCE _IoBuildAsynchronousFsdRequest@24 endp
- IoBuildAsynchronousFsdRequest內部不算很複雜 通過調用IoAllocateIrp來分配IRP
- 對於IRP_MJ_SHUTDOWN,IRP_MJ_PNP,IRP_MJ_POWER,IRP_MJ_FLUSH_BUFFERS 這樣的不對設備讀寫的請求
- MajorFunction送入IO_STACK_LOCATION後就直接返回了。。。
- 而對於IRP_MJ_READ或者IRP_MJ_WRITE還要對緩衝區進行處理
- 對於緩衝區讀寫的設備 MajorFunction爲IRP_MJ_WRITE時IoBuildAsynchronousFsdRequest調用ExAllocatePoolWithTag分配內存 填充到
- pIrp->AssociatedIrp.SystemBuffer域中 同時複製要寫入的數據到SystemBuffer中去(看到這裏 估計就明白IO管理器是怎麼管理SystemBuffer
- 的) MajorFunction爲IRP_MJ_READ時 只分配好內存,最後IO_STACK_LOCATION域填充好 返回
- 對於直接讀寫的設備 爲參數中提供的內存創建一個MDL MmProbeAndLockPages函數校驗那個數據緩衝區是否有效,是否可以按適當模式訪問。
- 如果我們向設備寫數據,我們必須能讀緩衝區。如果我們從設備讀數據,我們必須能寫緩衝區。
- 分析到這裏其實已經差不多了 IoBuildAsynchronousFsdRequest和IoBuildSynchronousFsdRequest之所以只能分配少數幾種IRP 只是因爲內部
- 只對這幾種IRP進行了 封裝(廢話啊)至於調用IoAllocateIrp後應該填充的域顯然 應該和IoBuildAsynchronousFsdRequest中做的差不多(當然根據
- 具體的MajorFunction具體填充) 比如:IoStackLocation,UserIosb
IRP的創建
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.