|
|
|
Статья
Эта небольшая статья посвящена функции IoCompleteRequest, функции, с помощью которой заканчиваются все запросы ввода-вывода. Предполагается, что читатель уже знаком с внутренней организацией драйверов операционных систем направления Windows NT. Описанию работы данной функции посвящено много статей, но никто не приводит ее код (во всяком случае автор не видел, кроме кода в проекте ReactOS), все просто описывают завершение ввода-вывода словами. С подобным описанием вы можете ознакомиться в статье "Secrets of the Universe Revealed! - How NT Handles I/O Completion" на сайте www.osronline.com (очень рекомендуемый для посещения сайт), эта же статья входит в IFSDK под названием Filter Driver Discussion Paper, желательно ознакомиться с этими статьями перед чтением данной статьи. Также очень полезно ознакомиться с возможными вариантами завершения запросов вввода-вывода, приведенными в книге W.Oney "Programming WDM" (классическая книга, имеется на данном сайте), также описание завершения ввода-вывода есть на сайте Microsoft в Knowledge Base, и, конечно, в DDK. Я считаю, что в дополнение к великолепному описанию в вышеприведенных источниках неплохо увидеть код, поэтому я исследовал ассемблерный листинг функций, связанных с IoCompleteRequest. Дизассемблирование ядра для системы с архитектурой IA-32 было приведено при помощи дизассемблера IDA Pro, дизассемблерный листинг приведен в конце. Необходимо отметить, что функция IoCompleteRequest определена как макрос #define IoCompleteRequest(a,b) IofCompleteRequest(a,b)
А IofCompleteRequest осуществляет безусловный переход на функцию, адрес которой находится в глобальной переменной ядра _pIopfCompleteRequest NTKERNELAPI VOID FASTCALL IofCompleteRequest(PIRP pIrp, USHORT PriorityBoost) { __asm jmp[_pIofCompleteRequest]; }
Подобный вызов функции, вероятно, был сделан с целью легкой замены одной функции завершения на другую, например, запущенный DriverVerifier заменяет стандартную функцию завершения на свою функцию IovSpecialIrpCompleteRequest, для проверки корректного завершения запроса ввода-вывода. На моей системе Windows 2000 Professional SP2, без запущенного DriverVerifier, в переменной _pIofCompleteRequest находится адрес функции IopfCompleteRequest, соответственно, ее и исследуем. Ниже приведен код функции IopfCompleteRequest на языке C, комментарии приведены после кода, можете сразу прочитать комментарии - в них основная цель этой заметки (сразу оговорюсь: приведенный листинг - это не дословный перевод ассемблерного листинга, некоторая часть кода была продублирована, чтобы не писать много операторов goto; в комментариях приведены номера соответствующих строк или имена меток(label) ассемблерного листинга, приведенного в конце статьи) 1. void IopfCompleteRequest(PIRP pIrp, CCHAR PriorityBoost) 2. { 3. CHAR StackCount; 4. CHAR PendingRetuned; 5. PDEVICE_OBJECT pDeviceObject; 6. PCHAR AuxiliaryBuffer; 7. PFILE_OBJECT OriginalFileObject; 8. ULONG Information; 9. struct _IO_STACK_LOCATION *CurrentStackLocation, *PrevStackLocation; 10. 11. //.text:0041F739 12. 13. if((pIrp->CurrentLocation > (pIrp->StackCount+1)) || (Irp->Type != 6)) 14. KeBugCheckEx(44, pIrp, 0CCAh,0,0); 15. 16. //.text:0041F76F 17. if( ++pIrp->CurrentLocation > (pIrp->StackCount+1)) 18. goto after_loop; 19. 20. PrevStackLocation = pIrp->Overlay.CurrentStackLocation; 21. CurrentStackLocation = ++(pIrp->Overlay.CurrentStackLocation); 22. 23. ///////////////////////////////////////////////////////////////////////// 24. // Begin of main loop 25. ///////////////////////////////////////////////////////////////////////// 26. { 27. loop: 28. //.text:0041F779 29. PendingRetuned = PrevStackLocation->Control & SL_PENDING_RETURNED; 30. //.text:0041F77E 31. pIrp->PendingRetuned = PendingRetuned; 32. //.text:0041F786 33. if(pIrp->IoStatus.Status < 0) 34. { 35. if(SL_INVOKE_ON_ERROR & (pIrp->Overlay.CurrentStackLocation-1)->Control) 36. { 37. //.text:0041F791 loc_41F791: 38. PrevStackLocation = pIrp->Overlay.CurrentStackLocation-1; 39. PrevStackLocation->MinorFunction = 0; 40. PrevStackLocation->Flags = 0; 41. PrevStackLocation->Control = 0; 42. PrevStackLocation->Parameters.Argument1 = 0; 43. PrevStackLocation->Parameters.Argument2 = 0; 44. PrevStackLocation->Parameters.Argument3 = 0; 45. PrevStackLocation->Parameters.Argument4 = 0; 46. PrevStackLocation->DeviceObject = 0; 47. PrevStackLocation->FileObject = 0; 48. 49. StackCount = pIrp->StackCount; 50. ++StackCount; 51. if((StackCount+1) != Irp->CurrentLocation) 52. pDeviceObject = pIrp->Overlay.CurrentStackLocation->DeviceObject; 53. else 54. pDeviceObject = NULL; 55. 56. if(STATUS_MORE_PROCESSING_REQUIRED == PrevStackLocation->CompletionRoutine(pDeviceObject,pIrp,PrevStackLocation->Context)) 57. return; 58. } 59. } 60. else if(SL_INVOKE_ON_SUCCESS & (pIrp->Overlay.CurrentStackLocation-1)->Control) 61. { 62. PrevStackLocation = pIrp->Overlay.CurrentStackLocation-1; 63. PrevStackLocation->MinorFunction = 0; 64. PrevStackLocation->Flags = 0; 65. PrevStackLocation->Control = 0; 66. PrevStackLocation->Parameters.Argument1 = 0; 67. PrevStackLocation->Parameters.Argument2 = 0; 68. PrevStackLocation->Parameters.Argument3 = 0; 69. PrevStackLocation->Parameters.Argument4 = 0; 70. PrevStackLocation->DeviceObject = 0; 71. PrevStackLocation->FileObject = 0; 72. 73. StackCount = pIrp->StackCount; 74. ++StackCount; 75. if((StackCount+1) != Irp->CurrentLocation) 76. pDeviceObject = pIrp->Overlay.CurrentStackLocation->DeviceObject; 77. else 78. pDeviceObject = NULL; 79. 80. if(STATUS_MORE_PROCESSING_REQUIRED == PrevStackLocation->CompletionRoutine(pDeviceObject,pIrp,PrevStackLocation->Context)) 81. return; 82. } 83. else if(pIrp->IoStatus.Status >= 0) 84. { 85. //loc_41F796: 86. if(!pIrp->Cancel || (SL_INVOKE_ON_CANCEL & (pIrp->Overlay.CurrentStackLocation-1)->Control)) 87. { 88. //loc_41F839: 89. if(!((pIrp->Overlay.CurrentStackLocation-1)->Control & SL_PENDING_RETURNED)) 90. { 91. if(pIrp->CurrentLocation < pIrp->StackCount) 92. pIrp->Overlay.CurrentStackLocation->Control &= 1;//set SL_PENDING_RETURNED 93. } 94. } 95. //loc_41F849: 96. PrevStackLocation = pIrp->Overlay.CurrentStackLocation-1; 97. PrevStackLocation->MinorFunction = 0; 98. PrevStackLocation->Flags = 0; 99. PrevStackLocation->Control = 0; 100. PrevStackLocation->Parameters.Argument1 = 0; 101. PrevStackLocation->Parameters.Argument2 = 0; 102. PrevStackLocation->Parameters.Argument3 = 0; 103. PrevStackLocation->Parameters.Argument4 = 0; 104. PrevStackLocation->DeviceObject = 0; 105. PrevStackLocation->FileObject = 0; 106. } 107. 108. //.text:0041F7DA loc_41F7DA 109. CurrentLocation = ++pIrp->Overlay.CurrentStackLocation; 110. ++pIrp->CurrentLocation; 111. if(pIrp->CurrentLocation<=(pIrp->StackCount+1)) 112. goto loop; 113. } 114. ///////////////////////////////////////////////////////////////////////// 115. // End of main loop 116. ///////////////////////////////////////////////////////////////////////// 117. 118. after_loop: 119. //.text:0041F7F3 120. if(pIrp->Flags & IRP_ASSOCIATED_IRP) 121. { 122. PIRP MaterIrp = pIrp->MasterIrp; 123. --(pIrp->MasterIrp->IrpCount); 124. pIrp->Thread = pIrp->MasterIrp->Thread; 125. IopFreeIrpAndMdls(pIrp); 126. if(pIrp->MasterIrp->IrpCount != 1) 127. return; 128. IofCompleteRequest(MasterIrp,PriorityBoost); 129. return; 130. } 131. 132. //.loc_41F867: 133. if(pIrp->IoStatus == STATUS_REPARSE) 134. { 135. if(pIrp->IoStatus.Information > 1) 136. { 137. if(IO_REPARSE_TAG_MOUNT_POINT == pIrp->IoStatus.Information) 138. { 139. //.text:0041F87F 140. AuxiliaryBuffer = pIrp->Tail.Overlay.AuxiliaryBuffer; 141. pIrp->Tail.Overlay.AuxiliaryBuffer = NULL; 142. } 143. else 144. { 145. //.loc_41F8DB 146. pIrp->IoStatus = STATUS_IO_REPARSE_TAG_NOT_HANDLED; 147. } 148. } 149. } 150. 151. //.loc_41F888: 152. if( pIrp->Tail.Overlay.AuxiliaryBuffer != NULL) 153. { 154. ExFreePool(pIrp->Tail.Overlay.AuxiliaryBuffer); 155. pIrp->Tail.Overlay.AuxiliaryBuffer = NULL; 156. } 157. //.loc_41F898: 158. if(!(pIrp->Flags & (RP_CLOSE_OPERATION | IRP_PAGING_IO))) 159. { 160. //loc_41F915 161. PMDL pMdl = pIrp->MdlAddress; 162. while(pMdl != NULL) 163. { 164. MmUnlockPages(pMdl); 165. pMdl = pMdl->Next 166. } 167. //loc_41F926: 168. if((pIrp->Flags & IRP_DEFER_IO_COMPLETION) && !pIrp->PendingReturned) 169. { 170. if(pIrp->IoStatus.Status & STATUS_REPARSE) 171. { 172. if(pIrp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT) 173. { 174. pIrp->Tail.Overlay.AuxiliaryBuffer = AuxiliaryBuffer; 175. } 176. } 177. return; 178. } 179. } 180. else if(!(pIrp->Flags & (IRP_CLOSE_OPERATION | IRP_INPUT_OPERATION))) 181. { 182. //loc_41F8E9 183. KeInitializeApc(&pIrp->Tail.Apc,pIrp->Tail.Overlay.Thread,pIrp->ApcEnvironment,IopCompletePageWrite,0,0,0,0); 184. KeInsertQueueApc(&pIrp->Tail.Apc,0,0,PriroityBoost); 185. return; 186. } 187. else 188. { 189. //.text:0041F8A7 190. 191. pIrp->UserIosb.Status = pIrp->IoStatus.Status; 192. pIrp->UserIosb.Information = pIrp->IoSatus.Information; 193. 194. KeSetEvent(pIrp->UserEvent, PriorityBoost); 195. //.text:0041F8C8 196. if(pIrp->Flags & IRP_INPUT_OPERATION) 197. IoFreeIrp(pIrp); 198. 199. return; 200. } 201. //loc_41F956 202. 203. OriginalFileObject = pIrp->Overlay.OriginalFileObject; 204. Information = pIrp->IoStatus.Information; 205. 206. if(pIrp->Cancel) 207. { 208. //loc_41F995 209. KIRQL OldIrql; 210. OldIrql = KeRaiseIrqlToDpcLevel(); 211. if( NULL == pIrp->Tail.Overlay.Thread) 212. { 213. //loc_41F9E2 214. KfLowerIrql(OldIrql); 215. IopDropIrp(pIrp, pIrp->Overlay.OriginalFileObject); 216. return; 217. } 218. KeInitializeApc(&pIrp->Tail.Apc,pIrp->Tail.Overlay.Thread,pIrp->ApcEnvironment,IopCompleteRequest,IopAbortRequest,0,0,0); 219. KeInsertQueueApc(&pIrp->Tail.Apc,OriginalFileObject,Information,PrirorityBoost); 220. KfLowerIrql(OldIrql); 221. return; 222. } 223. //.text:0041F964 224. KeInitializeApc(&pIrp->Tail.Apc,pIrp->Tail.Overlay.Thread,pIrp->ApcEnvironment,IopCompleteRequest,IopAbortRequest,0,0,0); 225. KeInsertQueueApc(&pIrp->Tail.Apc,OriginalFileObject,Information,PrirorityBoost); 226. return; 227. }
Теперь пройдемся по коду. Функция принимает указатель на пакет ввода-вывода, который надо завершить и насколько поднять приоритет потока. Строки 13, 14 - проверка входных параметров, строка 28 - начало цикла, в котором проводится раскрутка стека запроса ввода-вывода, с вызовом зарегистрированных функций завершения ввода-вывода, это так называемая первая стадия завершения ввода-вывода. Как видно из строчек 56, 80 в которых происходит вызов функций завершения, если функция вернет STATUS_MORE_PROCESSING_REQUIRED, произойдет выход из функции IopfCompleteRequest без осуществления второй стадии завершения, то есть без установки APC в очередь потока, сделавшего запрос. После раскрутки стека в строчках 28-112 функция IopfCompleteRequest принимает решение о том, что делать с пакетом Irp, заметьте - она может сама вызвать IoFreeIrp или IopDropIrp явно или путем установки APC с функцией IopCompleteRequest, которая также вызовет IoFreeIrp, все это приведет к уничтожению Irp и освобождению занятой памяти, единственный вариант избежать уничтожения Irp системой - это - Возвратить STATUS_MORE_PROCESSING_REQUIRED из зарегистрированной функции завершения ввода-вывода. Строки 56, 80.
- Создание Irp с флагами IRP_CLOSE_OPERATION или IRP_PAGING_IO и отсутствующим флагом IRP_INPUT_OPERATION. Строки 158, 180, 196.
- Создание Irp с флагом IRP_DEFER_IO_COMPLETION необходимо, чтобы этот Irp не запендили, то есть не отложили его отработку, возвратив STATUS_PENDING.
По некоторым сведениям, флаг IRP_DEFER_IO_COMPLETION любят ставить функции, вызываемые из режима пользователя. Из приведенного выше списка и анализа кода ясно, что гарантию неуничтожения Irp может дать только возврат STATUS_MORE_PROCESSING_REQUIRED из зарегистрированной функции завершения ввода-вывода, попытка самостоятельного уничтожения созданного вами же Irp в большинстве случаев приведет к BSOD (тут полезно посмотреть на способы завершения запросов ввода-вывода, приведенных в книге W. Oney). Заметьте, что в подавляющем большинстве случаев для уничтожения Irp ставится APC в очередь потока, сделавшего запрос, вне зависимости от того, является запрос синхронным или нет. Для синхронного запроса (то есть полностью идущего в контексте потока, сделавшего запрос - именно такой запрос я называю синхронным, в других источниках встречаются другие интерпретации) после установки APC в очередь, при помощи KeInsertQueueApc, сразу будет вызвана процедура очистки очереди APC из функции KeInsertQueueApc (сама поставила в очередь - сама инициировала очистку очереди), то есть последовательность выполнения потока не нарушится - после выхода из IopfCompleteRequest пакет запроса ввода-вывода уже будет уничтожен в функции IopCompleteRequest. Для асинхронных запросов APC будут вызваны сразу после того, как планировщик запланирует поток, в очереди которого они находятся, на выполнение, переключит контекст и начнется понижение уровня IRQL с DISPATCH_LEVEL до PASSIVE_LEVEL, APC будут вызваны на APC_LEVEL. В заключение отмечу, что память под структуру KAPC выделяется из памяти, выделенной для Irp, что означает частичное разрушение нижней части Irp. В строчках 120-129 происходит уничтожение ассоцированных IRP и завершение Master Irp после уничтожения всех потомков, из этого кода видно, почему W.Oney не рекомендует использовать ассоциированные IRP - слишком запутана процедура их уничтожения. Более подробный анализ я оставляю для читателя, также как и проверку правильности проделанной автором работы - между моментом, когда автор дизассемблировал и исследовал функцию IopfCompleteRequest и написал соответствующий код на С, прошло достаточно много времени, некоторые детали могли быть упущены из виду. В заключение ассемблерный листинг, комментарии в нем сделаны как в стиле С и С++(то есть через /* */ и //), так и через принятую в ассемблере точку с запятой. .text:0041F72C @IopfCompleteRequest@8 proc near ; CODE XREF: @IovCompleteRequest@8+A4p .text:0041F72C ; @IovSpecialIrpCompleteRequest@8+C1p .text:0041F72C ; DATA XREF: ... .text:0041F72C .text:0041F72C var_C = dword ptr -0Ch .text:0041F72C var_8 = dword ptr -8 .text:0041F72C var_2 = byte ptr -2 .text:0041F72C var_1 = byte ptr -1 .text:0041F72C .text:0041F72C push ebp .text:0041F72D mov ebp, esp .text:0041F72F sub esp, 0Ch .text:0041F732 push ebx .text:0041F733 push esi .text:0041F734 mov esi, ecx // ecx = pIrp edx = PriorityBoost .text:0041F736 xor ebx, ebx // ebx = 0 .text:0041F738 push edi /* stack from up to bottom /*000*/ ebp /*004*/ 0 <-ebp /*010*/ ebx /*014*/ esi /*018*/ edi /* registers: ebp points to local data esi = ecx = pIrp edx = PriorityBoost */ .text:0041F739 mov [ebp+var_1], dl // [ebp+var1] = PriorityBoost .text:0041F73C mov al, [esi+22h] // al = pIrp->StackCount .text:0041F73F mov [ebp+var_8], ebx // [ebp+var_8] = 0 .text:0041F742 inc al // ++al, see .text:0041F73C .text:0041F744 cmp [esi+23h], al // [esi+23h]=pIrp->CurrentLocation if(pIrp->CurrentLocation > al) .text:0041F747 jg short loc_41F74F // if greater {goto KeBugCheckEx} else .text:0041F749 cmp word ptr [esi], 6// if (pIrp->Type == 6) .text:0041F74D jz short loc_41F75E // if equal {goto loc_41F75E} else {goto KeBugCheckEx} .text:0041F74F .text:0041F74F loc_41F74F: ; CODE XREF: @IopfCompleteRequest@8+1Bj .text:0041F74F push ebx .text:0041F750 push ebx .text:0041F751 push 0CCAh .text:0041F756 push esi .text:0041F757 push 44h .text:0041F759 call _KeBugCheckEx@20 .text:0041F75E .text:0041F75E loc_41F75E: ; CODE XREF: @IopfCompleteRequest@8+21j .text:0041F75E mov edi, [esi+60h] // edi = pIrp->Overlay.CurrentStackLocation .text:0041F761 mov dl, [esi+22h] // dl = pIrp->StackCount .text:0041F764 inc byte ptr [esi+23h] // ++pIrp->CurrentLocation .text:0041F767 mov cl, [esi+23h] //cl = pIrp->CurrentLocation .text:0041F76A inc dl //++dl, see .text:0041F761 .text:0041F76C lea eax, [edi+24h] // eax = pIrp->Overlay.CurrentStackLocation+1 .text:0041F76F cmp cl, dl // if( cl == dl) .text:0041F771 mov [esi+60h], eax // pIrp->Overlay.CurrentStackLocation = pIrp->Overlay.CurrentStackLocation+1 .text:0041F774 jg short loc_41F7F3 .text:0041F776 add edi, 3 //edi = ((PCHAR)(pIrp->Overlay.CurrentStackLocation-1))+3 .text:0041F779 /////////////////////////////////////////////////////////////////////// // Begin of loop_1(see End of loop_1). Go through all stacks and call Completion functions. // esi = pIrp // edi = ((PCHAR)(pIrp->Overlay.CurrentStackLocation-1))+3 // ebx = 0 /////////////////////////////////////////////////////////////////////// .text:0041F779 loc_41F779: ; CODE XREF: @IopfCompleteRequest@8+C5j .text:0041F779 mov cl, [edi] // cl = (pIrp->Overlay.CurrentStackLocation-1)->Control .text:0041F77B mov edx, [esi+18h] //edx = pIrp->IoStatus; .text:0041F77E and cl, 1 //cl = ((pIrp->Overlay.CurrentStackLocation-1)->Control & SL_PENDING_RETURNED) .text:0041F781 cmp edx, ebx //pIrp->IoStatus.Status == 0 .text:0041F783 mov [esi+21h], cl //IoMarkIrpPending(pIrp) .text:0041F786 jl short loc_41F791 //in loop_1, pIrp->IoStatus.Status != STATUSS_SUCCESS .text:0041F788 test byte ptr [edi], 40h //SL_INVOKE_ON_SUCCESS & (pIrp->Overlay.CurrentStackLocation-1)->Control .text:0041F78B jnz short loc_41F7A8 //invoke on success .text:0041F78D cmp edx, ebx .text:0041F78F jge short loc_41F796 //in loop_1 .text:0041F791 .text:0041F791 loc_41F791: ; CODE XREF: @IopfCompleteRequest@8+5Aj .text:0041F791 test byte ptr [edi], 80h //SL_INVOKE_ON_ERROR & (pIrp->Overlay.CurrentStackLocation-1)->Control .text:0041F794 jnz short loc_41F7A8 //in loop_1 .text:0041F796 .text:0041F796 loc_41F796: ; CODE XREF: @IopfCompleteRequest@8+63j .text:0041F796 cmp [esi+24h], bl .text:0041F799 jz loc_41F839 //some work and go to loc_41F7DA in loop_1 .text:0041F79F test byte ptr [edi], 20h //SL_INVOKE_ON_CANCEL & (pIrp->Overlay.CurrentStackLocation-1)->Control .text:0041F7A2 jz loc_41F839 //some work and go to loc_41F7DA in loop_1 .text:0041F7A8 .text:0041F7A8 loc_41F7A8: ; CODE XREF: @IopfCompleteRequest@8+5Fj .text:0041F7A8 ; @IopfCompleteRequest@8+68j // ebx = 0 // edi = &((pIrp->Overlay.CurrentStackLocation-1)->Control) .text:0041F7A8 mov [edi-2], bl .text:0041F7AB mov [edi-1], bl .text:0041F7AE mov [edi], bl .text:0041F7B0 mov [edi+1], ebx .text:0041F7B3 mov [edi+5], ebx .text:0041F7B6 mov [edi+9], ebx .text:0041F7B9 mov [edi+0Dh], ebx .text:0041F7BC mov [edi+15h], ebx .text:0041F7BF mov al, [esi+22h]//pIrp->StackCount; .text:0041F7C2 inc al .text:0041F7C4 cmp [esi+23h], al // if(Irp->CurrentLocation != (Irp->StackCount+1)) go to loc_41F82F .text:0041F7C7 jnz short loc_41F82F//set eax to pIrp->Overlay.CurrentStackLocation->DeviceObject, and go to loc_41F7CB in loop_1 .text:0041F7C9 xor eax, eax //DeviceObject = NULL; Irp->CurrentLocation == (Irp->StackCount+1) .text:0041F7CB .text:0041F7CB loc_41F7CB: ; CODE XREF: @IopfCompleteRequest@8+109j .text:0041F7CB push dword ptr [edi+1Dh] // push (pIrp->Overlay.CurrentStackLocation-1)->Context .text:0041F7CE push esi // push pIrp .text:0041F7CF push eax // push pIrp->Overlay.CurrentStackLocation->DeviceObject or NULL, see .text:0041F7C7 .text:0041F7D0 call dword ptr [edi+19h] // call (pIrp->Overlay.CurrentStackLocation-1)->CompletionRoutine ,see .text:0041F776 .text:0041F7D3 cmp eax, 0C0000016h // STATUS_MORE_PROCESSING_REQUIRED .text:0041F7D8 jz short loc_41F82A // return .text:0041F7DA .text:0041F7DA loc_41F7DA: ; CODE XREF: @IopfCompleteRequest@8+10Bj .text:0041F7DA ; @IopfCompleteRequest@8+134j .text:0041F7DA mov dl, [esi+22h] // dl = pIrp->StackCount .text:0041F7DD add dword ptr [esi+60h], 24h //++pIrp->Overlay.CurrentStackLocation .text:0041F7E1 mov eax, [esi+60h] .text:0041F7E4 add edi, 24h //((PCHAR)(pIrp->Overlay.CurrentStackLocation-1))+3 .text:0041F7E7 inc byte ptr [esi+23h] .text:0041F7EA mov cl, [esi+23h] //pIrp->CurrentLocation .text:0041F7ED inc dl .text:0041F7EF cmp cl, dl // cl == pIrp->CurrentLocation, dl == pIrp->StackCount+1 .text:0041F7F1 jle short loc_41F779 //////////////////////////////////////////////////////////////////////////////////////////// //End of loop_1 //////////////////////////////////////////////////////////////////////////////////////////// .text:0041F7F3 .text:0041F7F3 loc_41F7F3: ; CODE XREF: @IopfCompleteRequest@8+48j .text:0041F7F3 test byte ptr [esi+8], 8 // pIrp->Flags & IRP_ASSOCIATED_IRP .text:0041F7F7 jz short loc_41F867 //process normal IRP //complete associated Irp and return .text:0041F7F9 mov edi, [esi+0Ch] .text:0041F7FC lea eax, [edi+0Ch] //&pIrp->MasterIrp->IrpCount .text:0041F7FF mov [ebp+var_8], eax .text:0041F802 mov eax, 0FFFFFFFFh //-1 .text:0041F807 mov ecx, [ebp+var_8]//&pIrp->MasterIrp->IrpCount .text:0041F80A xadd [ecx], eax //--(pIrp->MasterIrp->IrpCount) .text:0041F80D mov ebx, eax //pIrp->MasterIrp->IrpCount .text:0041F80F mov eax, [edi+50h] //pIrp->MasterIrp->Thread .text:0041F812 push esi //pIrp .text:0041F813 mov [esi+50h], eax //pIrp->Thread = pIrp->MasterIrp->Thread .text:0041F816 call _IopFreeIrpAndMdls@4 .text:0041F81B cmp ebx, 1 .text:0041F81E jnz short loc_41F82A //return .text:0041F820 mov dl, [ebp+var_1] //PriorityBoost .text:0041F823 mov ecx, edi .text:0041F825 call @IofCompleteRequest@8 .text:0041F82A .text:0041F82A loc_41F82A: ; CODE XREF: @IopfCompleteRequest@8+ACj .text:0041F82A ; @IopfCompleteRequest@8+F2j ... .text:0041F82A pop edi .text:0041F82B pop esi .text:0041F82C pop ebx .text:0041F82D leave .text:0041F82E retn .text:0041F82F ; --------------------------------------------------------------------------- .text:0041F82F .text:0041F82F loc_41F82F: ; CODE XREF: @IopfCompleteRequest@8+9Bj .text:0041F82F mov eax, [esi+60h] //pIrp->Overlay.CurrentStackLocation .text:0041F832 mov eax, [eax+14h] //eax = pIrp->Overlay.CurrentStackLocation->DeviceObject .text:0041F835 jmp short loc_41F7CB// goto loop_1 .text:0041F837 ; --------------------------------------------------------------------------- .text:0041F837 jmp short loc_41F7DA .text:0041F839 ; --------------------------------------------------------------------------- .text:0041F839 .text:0041F839 loc_41F839: ; CODE XREF: @IopfCompleteRequest@8+6Dj .text:0041F839 ; @IopfCompleteRequest@8+76j .text:0041F839 cmp cl, bl .text:0041F83B jz short loc_41F849 .text:0041F83D mov cl, [esi+23h] .text:0041F840 cmp cl, [esi+22h] .text:0041F843 jg short loc_41F849 .text:0041F845 or byte ptr [eax+3], 1 .text:0041F849 .text:0041F849 loc_41F849: ; CODE XREF: @IopfCompleteRequest@8+10Fj .text:0041F849 ; @IopfCompleteRequest@8+117j .text:0041F849 mov [edi-2], bl .text:0041F84C mov [edi-1], bl .text:0041F84F mov [edi], bl .text:0041F851 mov [edi+1], ebx .text:0041F854 mov [edi+5], ebx .text:0041F857 mov [edi+9], ebx .text:0041F85A mov [edi+0Dh], ebx .text:0041F85D mov [edi+15h], ebx .text:0041F860 jmp loc_41F7DA //go to loop_1 .text:0041F865 ; --------------------------------------------------------------------------- .text:0041F865 jmp short loc_41F82A //return, we never will be here! .text:0041F867 ; --------------------------------------------------------------------------- .text:0041F867 // go from .text:0041F7F7 .text:0041F867 loc_41F867: ; CODE XREF: @IopfCompleteRequest@8+CBj // check for Reparse Point (Volume Mounted to directory) .text:0041F867 cmp dword ptr [esi+18h], 104h //pIrp->IoStatus == STATUS_REPARSE .text:0041F86E jnz short loc_41F888 .text:0041F870 mov eax, [esi+1Ch] // pIrp->IoStatus.Information .text:0041F873 cmp eax, 1 .text:0041F876 jbe short loc_41F888 .text:0041F878 cmp eax, 0A0000003h //IO_REPARSE_TAG_MOUNT_POINT .text:0041F87D jnz short loc_41F8DB .text:0041F87F mov eax, [esi+54h] .text:0041F882 mov [esi+54h], ebx .text:0041F885 mov [ebp+var_8], eax .text:0041F888 .text:0041F888 loc_41F888: ; CODE XREF: @IopfCompleteRequest@8+142j .text:0041F888 ; @IopfCompleteRequest@8+14Aj ... .text:0041F888 mov eax, [esi+54h] // .text:0041F88B cmp eax, ebx .text:0041F88D jz short loc_41F898 .text:0041F88F push eax .text:0041F890 call _ExFreePool@4 .text:0041F895 mov [esi+54h], ebx .text:0041F898 .text:0041F898 loc_41F898: ; CODE XREF: @IopfCompleteRequest@8+161j .text:0041F898 mov eax, [esi+8] .text:0041F89B test ax, 402h // IRP_CLOSE_OPERATION | IRP_PAGING_IO .text:0041F89F jz short loc_41F915//possible go to KeInsertQueueApc .text:0041F8A1 test ax, 440h // IRP_CLOSE_OPERATION | IRP_INPUT_OPERATION .text:0041F8A5 jz short loc_41F8E9// go to KeInsertQueueApc .text:0041F8A7 mov ecx, [esi+18h] // ecx = pIrp->IoStatus.Status .text:0041F8AA and eax, 40h .text:0041F8AD mov edi, eax //edi = pIrp->Flags & IRP_INPUT_OPERATION .text:0041F8AF mov eax, [esi+28h] //eax = pIrp->UserIosb .text:0041F8B2 push ebx .text:0041F8B3 mov [eax], ecx // pIrp->UserIosb.Status = pIrp->IoStatus.Status .text:0041F8B5 mov ecx, [esi+1Ch] // ecx = pIrp->IoSatus.Information .text:0041F8B8 mov [eax+4], ecx // pIrp->UserIosb.Information = pIrp->IoSatus.Information .text:0041F8BB movsx eax, [ebp+var_1]// PriorityBoost .text:0041F8BF push eax .text:0041F8C0 push dword ptr [esi+2Ch] .text:0041F8C3 call _KeSetEvent@12 .text:0041F8C8 cmp edi, ebx .text:0041F8CA jz loc_41F82A //return .text:0041F8D0 push esi .text:0041F8D1 call _IoFreeIrp@4 .text:0041F8D6 jmp loc_41F82A //return .text:0041F8DB ; --------------------------------------------------------------------------- .text:0041F8DB .text:0041F8DB loc_41F8DB: ; CODE XREF: @IopfCompleteRequest@8+151j .text:0041F8DB mov dword ptr [esi+18h], 0C0000279h //STATUS_IO_REPARSE_TAG_NOT_HANDLED .text:0041F8E2 jmp short loc_41F888 .text:0041F8E4 ; --------------------------------------------------------------------------- .text:0041F8E4 jmp loc_41F82A //return .text:0041F8E9 ; --------------------------------------------------------------------------- .text:0041F8E9 .text:0041F8E9 loc_41F8E9: ; CODE XREF: @IopfCompleteRequest@8+179j .text:0041F8E9 movsx eax, byte ptr [esi+26h] //pIrp->ApcEnvironment .text:0041F8ED push ebx .text:0041F8EE push ebx .text:0041F8EF push ebx .text:0041F8F0 push ebx .text:0041F8F1 push offset _IopCompletePageWrite@20 .text:0041F8F6 push eax .text:0041F8F7 push dword ptr [esi+50h] .text:0041F8FA lea edi, [esi+40h] .text:0041F8FD push edi .text:0041F8FE call _KeInitializeApc@32 .text:0041F903 movsx eax, [ebp+var_1] .text:0041F907 push eax .text:0041F908 push ebx .text:0041F909 push ebx .text:0041F90A .text:0041F90A loc_41F90A: ; CODE XREF: @IopfCompleteRequest@8+25Fj .text:0041F90A push edi .text:0041F90B call _KeInsertQueueApc@16 .text:0041F910 jmp loc_41F82A //return .text:0041F915 ; --------------------------------------------------------------------------- .text:0041F915 .text:0041F915 loc_41F915: ; CODE XREF: @IopfCompleteRequest@8+173j .text:0041F915 mov edi, [esi+4] //pIrp->MdlAddress .text:0041F918 .text:0041F918 loc_41F918: ; CODE XREF: @IopfCompleteRequest@8+1F8j .text:0041F918 cmp edi, ebx // if pIrp->MdlAddress == 0 .text:0041F91A jz short loc_41F926 .text:0041F91C push edi .text:0041F91D call _MmUnlockPages@4// MmUnlockPages(pIrp->MdlAddress) .text:0041F922 mov edi, [edi] // edi = pIrp->MdlAddress.Next .text:0041F924 jmp short loc_41F918 .text:0041F926 ; --------------------------------------------------------------------------- .text:0041F926 .text:0041F926 loc_41F926: ; CODE XREF: @IopfCompleteRequest@8+1EEj .text:0041F926 test byte ptr [esi+9], 8//pIrp->Flags & IRP_DEFER_IO_COMPLETION .text:0041F92A jz short loc_41F956 // go to KeInsertQueueApc .text:0041F92C cmp [esi+21h], bl //PendingRetuned .text:0041F92F jnz short loc_41F956 // pIrp->PendingRetuned == TRUE, go to KeInsertQueueApc .text:0041F931 cmp dword ptr [esi+18h], 104h //STATUS_REPARSE .text:0041F938 jnz loc_41F82A //return .text:0041F93E cmp dword ptr [esi+1Ch], 0A0000003h .text:0041F945 jnz loc_41F82A //return .text:0041F94B mov eax, [ebp+var_8] .text:0041F94E mov [esi+54h], eax .text:0041F951 jmp loc_41F82A //return .text:0041F956 ; --------------------------------------------------------------------------- .text:0041F956 .text:0041F956 loc_41F956: ; CODE XREF: @IopfCompleteRequest@8+1FEj .text:0041F956 ; @IopfCompleteRequest@8+203j .text:0041F956 mov edi, [esi+64h] //edi = pIrp->Overlay.OriginalFileObject .text:0041F959 cmp [esi+24h], bl // pIrp->Cancel .text:0041F95C mov eax, [esi+50h] //eax = pIrp->Tail.Overlay.Thread .text:0041F95F mov [ebp+var_C], edi //pIrp->Overlay.OriginalFileObject .text:0041F962 jnz short loc_41F995 .text:0041F964 movsx ecx, byte ptr [esi+26h]//ecx = pIrp->ApcEnvironment .text:0041F968 push ebx .text:0041F969 push ebx .text:0041F96A push ebx .text:0041F96B push offset _IopAbortRequest@4 .text:0041F970 push offset _IopCompleteRequest@20 .text:0041F975 lea edi, [esi+40h] //&pIrp->Tail.Apc .text:0041F978 push ecx .text:0041F979 push eax .text:0041F97A push edi .text:0041F97B call _KeInitializeApc@32 .text:0041F980 movsx eax, [ebp+var_1] .text:0041F984 push eax .text:0041F985 push [ebp+var_8] .text:0041F988 push [ebp+var_C] .text:0041F98B jmp loc_41F90A //InsertQueueApc .text:0041F990 ; --------------------------------------------------------------------------- .text:0041F990 jmp loc_41F82A //return .text:0041F995 ; --------------------------------------------------------------------------- .text:0041F995 .text:0041F995 loc_41F995: ; CODE XREF: @IopfCompleteRequest@8+236j .text:0041F995 call ds:__imp__KeRaiseIrqlToDpcLevel@0 .text:0041F99B mov cl, al//OldIrql .text:0041F99D mov eax, [esi+50h]//eax = pIrp->Tail.Overlay.Thread /* ebx == 0*/ .text:0041F9A0 cmp eax, ebx .text:0041F9A2 mov [ebp+var_2], cl .text:0041F9A5 jz short loc_41F9E2//IoDropIrp if pIrp->Tail.Overlay.Thread == NULL .text:0041F9A7 movsx ecx, byte ptr [esi+26h] .text:0041F9AB push ebx .text:0041F9AC push ebx .text:0041F9AD push ebx .text:0041F9AE push offset _IopAbortRequest@4 .text:0041F9B3 push offset _IopCompleteRequest@20 .text:0041F9B8 lea edi, [esi+40h] .text:0041F9BB push ecx .text:0041F9BC push eax .text:0041F9BD push edi .text:0041F9BE call _KeInitializeApc@32 .text:0041F9C3 movsx eax, [ebp+var_1] .text:0041F9C7 push eax .text:0041F9C8 push [ebp+var_8] .text:0041F9CB push [ebp+var_C] .text:0041F9CE push edi .text:0041F9CF call _KeInsertQueueApc@16 .text:0041F9D4 mov cl, [ebp+var_2] .text:0041F9D7 call ds:__imp_@KfLowerIrql@4 .text:0041F9DD jmp loc_41F82A //return .text:0041F9E2 ; --------------------------------------------------------------------------- .text:0041F9E2 .text:0041F9E2 loc_41F9E2: ; CODE XREF: @IopfCompleteRequest@8+279j .text:0041F9E2 call ds:__imp_@KfLowerIrql@4 .text:0041F9E8 push edi .text:0041F9E9 push esi .text:0041F9EA call _IopDropIrp@8 .text:0041F9EF jmp loc_41F82A //return .text:0041F9EF @IopfCompleteRequest@8 endp
Автор осознает, что в его работе неизбежно содержатся ошибки и неточности, поэтому с благодарностью примет замечания и исправления, которые можно оставить на форуме этого сайта. SlavaI 09.06.2003. Odintsovo. Moscow region. Russia.
|
|
|