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.

643 lines
26 KiB

  1. PAGE 60,150
  2. ;***************************************************************************
  3. ;* NOTIFY2.ASM
  4. ;*
  5. ;* Assembly code support routines used for the TOOLHELP.DLL
  6. ;* notification API
  7. ;*
  8. ;***************************************************************************
  9. INCLUDE TOOLPRIV.INC
  10. .286p
  11. ;** Data
  12. sBegin DATA
  13. globalW wCASRqFlag,0 ;Set when an CASRq INT3 has been set
  14. globalD dwCASRqCSIP,0 ;Holds the CS:IP of the CASRq INT3
  15. globalD lpfnOldProc,0 ;Old hook from new PTrace hook
  16. szWinDebug DB 'WINDEBUG', 0
  17. ;** WARNING!!
  18. ;** This structure is set to the size of the largest notification
  19. ;** structure. This is currently NFYLOADSEG which is 16 bytes long.
  20. ;** If a structure is added that is longer than this or if any other
  21. ;** structure is added, this space must be increased to match!!
  22. ReturnStruct DB 16 DUP (?)
  23. sEnd
  24. ;** Imports
  25. externFP GetModuleHandle
  26. externFP RegisterPTrace
  27. externFP OutputDebugString
  28. externFP AllocCStoDSAlias
  29. externFP FreeSelector
  30. externNP HelperHandleToSel
  31. sBegin CODE
  32. assumes CS,CODE
  33. assumes DS,DATA
  34. ; NotifyInit
  35. ; Called when the first app registers a notification handler.
  36. ; Hooks the Register PTrace notification.
  37. ; Returns FALSE if we couldn't initialize, TRUE otherwise
  38. cProc NotifyInit, <NEAR,PUBLIC>, <si,di,ds>
  39. cBegin
  40. ;** In the Windows 3.1 KERNEL, there is a special hook just for
  41. ;* TOOLHELP that lets us get PTrace stuff and still coexist
  42. ;* with old-fashioned debuggers. We can check to see if the
  43. ;* hook exists by simply checking the TOOLHELP flags
  44. ;**
  45. test wTHFlags,TH_GOODPTRACEHOOK ;Good hook around?
  46. jz DNI_UseRegPTrace ;Nope, use the old one
  47. lea si,NotifyHandler ;Point to the routine
  48. push cs ;Parameter is lpfn to callback
  49. push si
  50. call lpfnNotifyHook ;Hook it
  51. mov WORD PTR lpfnOldProc[0],ax ;Save old proc
  52. mov WORD PTR lpfnOldProc[2],dx
  53. jmp SHORT DNI_10 ;We're in
  54. ;** Since there's no way we can see if someone else has Register
  55. ;* PTrace, we just connect and hope for the best!
  56. ;** We do check, however, to see if WINDEBUG.DLL is installed.
  57. DNI_UseRegPTrace:
  58. lea si,szWinDebug ;Get the name of the module
  59. cCall GetModuleHandle, <ds,si> ;Is WINDEBUG present?
  60. or ax,ax ;Check the handle
  61. jnz DNI_Fail ;It's here so fail
  62. or wTHFlags,TH_GOTOLDPTRACE ;Flag that we made the hook
  63. lea si,NotifyHandler ;Point to our routine
  64. cCall RegisterPTrace, <cs,si> ;Tell KERNEL to use it
  65. ;** Connect to the FatalExit hook. We currently ignore
  66. ;** the return value, thus unhooking anyone else
  67. DNI_10: cmp WORD PTR lpfnFatalExitHook + 2,0 ;Can we hook it?
  68. jz DNI_20 ;Can't do it
  69. push cs ;Get the CS:IP of RIP handler
  70. push OFFSET NotifyRIPHandler
  71. call DWORD PTR lpfnFatalExitHook ;Tell KERNEL to insert the hook
  72. DNI_20:
  73. ;** Return OK
  74. mov ax,TRUE ;Return TRUE
  75. jmp SHORT DNI_End ;Get out
  76. DNI_Fail:
  77. xor ax,ax ;FALSE
  78. DNI_End:
  79. cEnd
  80. ; NotifyUnInit
  81. ; Called when the no more apps have hooked notification handlers
  82. ; so the hook to the Register PTrace notification is no longer needed.
  83. cProc NotifyUnInit, <NEAR,PUBLIC>, <si,di,ds>
  84. cBegin
  85. ;** Did we have a new hook to undo?
  86. test wTHFlags,TH_GOODPTRACEHOOK ;Do we have a new hook?
  87. jz DNU_TryOldPTrace ;No
  88. push WORD PTR lpfnOldProc[0] ;Get the old proc
  89. push WORD PTR lpfnOldProc[2]
  90. call lpfnNotifyHook ;Unhook ourself
  91. jmp SHORT DNU_NoOldPTrace
  92. ;** Unhook the old-style hook if necessary
  93. DNU_TryOldPTrace:
  94. test wTHFlags,TH_GOTOLDPTRACE ;Did we have a hook?
  95. jz DNU_NoOldPTrace ;No
  96. push 0
  97. push 0
  98. call RegisterPTrace ;Call KERNEL's routine to unhook
  99. DNU_NoOldPTrace:
  100. ;** Unhook alternate hooks
  101. cmp WORD PTR lpfnFatalExitHook + 2,0 ;Can we unhook it?
  102. jz DNU_NoRIP ;Can't do it
  103. xor ax,ax ;Remove any other hooks
  104. push ax ;NULL procedure
  105. push ax
  106. call DWORD PTR lpfnFatalExitHook
  107. DNU_NoRIP:
  108. cEnd
  109. ; NotifyHandler
  110. ; This routine is called directly by PTrace and is used to
  111. ; dispatch the notifications to all registered callbacks.
  112. cProc NotifyHandler, <FAR,PUBLIC>
  113. cBegin NOGEN
  114. ;** Push a register frame
  115. ;* When done, it should look like this:
  116. ;* ------------
  117. ;* | ES | [BP - 14h]
  118. ;* | DS | [BP - 12h]
  119. ;* | DI | [BP - 10h]
  120. ;* | SI | [BP - 0Eh]
  121. ;* | BP | [BP - 0Ch]
  122. ;* | SP | [BP - 0Ah]
  123. ;* | BX | [BP - 08h]
  124. ;* | DX | [BP - 06h]
  125. ;* | CX | [BP - 04h]
  126. ;* | AX | [BP - 02h]
  127. ;* BP-->| Old BP | [BP - 00h]
  128. ;* | IP | [BP + 02h]
  129. ;* | CS | [BP + 04h]
  130. ;* ------------
  131. ;**
  132. push bp ;Make a stack frame
  133. mov bp,sp
  134. pusha ;Save all registers
  135. push ds ;Save segment registers, too
  136. push es
  137. ;** Get the data segment
  138. mov bx,_DATA ;Get TOOLHELP data segment
  139. mov ds,bx
  140. ;** If in 3.0 std mode and we get this wild notification 69h,
  141. ;** translate it to a inchar notification as this is what it
  142. ;** is supposed to be.
  143. cmp ax,69h ;Bogus notification?
  144. jne NH_NoBogusNotify ;No, don't do this
  145. test wTHFlags,TH_WIN30STDMODE ;3.0 standard mode?
  146. jz NH_NoBogusNotify ;No, might be valid in the future...
  147. mov ax,NI_INCHAR ;Put in real notify value
  148. NH_NoBogusNotify:
  149. ;** Special case notifications:
  150. ;* Notification 63h means that CtlAltSysRq was pressed. For
  151. ;* this, we want to handle as an interrupt, not a notification.
  152. ;* To do this, we set a breakpoint and set a flag so that the
  153. ;** INT3 handler knows what to do with it
  154. cmp ax,63h ;CtlAltSysRq?
  155. jne NH_NoCASRq ;No.
  156. mov ax,[bp + 04h] ;Since we can't use IRET CS:IP, get
  157. mov si,[bp + 02h] ; a safe address in KERNEL
  158. mov WORD PTR dwCASRqCSIP[2],ax ;Save the CS:IP value
  159. cCall AllocCStoDSAlias, <ax> ;Get a data alias to the CS
  160. or ax,ax ;Error?
  161. jnz @F
  162. jmp SHORT DNH_End ;Yes, get out
  163. @@: verw ax ;OK to write to?
  164. jnz DNH_NoWrite ;Yes, so do it
  165. DNH_IRETCSOK:
  166. mov es,ax ;Point with ES
  167. mov WORD PTR dwCASRqCSIP[0],si
  168. mov al,es:[si] ;Get the character there
  169. mov ah,1 ;Make sure there's something in AH
  170. mov wCASRqFlag,ax ;Save the thing for the INT3 handler
  171. mov BYTE PTR es:[si],0cch ;Poke the INT3 in there
  172. mov ax,es ;Get the selector back
  173. DNH_NoWrite:
  174. cCall FreeSelector, <ax> ;Get rid of the alias
  175. jmp SHORT DNH_End ;Get out. This will INT3 soon
  176. NH_NoCASRq: ; Does not return
  177. ;** Notifications to ignore here:
  178. ;** Notification 60h is bogus and should be ignored
  179. cmp ax,60h ;PostLoad notification?
  180. jz DNH_End ;Yes, don't report
  181. ;** Decode the notification
  182. cCall DecodeNotification ;Returns dwData in CX:DX, AX is wID
  183. ; BX is NOTIFYSTRUCT match flags
  184. ;** This is an entry point for notifications from sources other than
  185. ;** PTrace
  186. DNH_Decoded:
  187. ;** Loop through callbacks
  188. mov di,npNotifyHead ;Point to the start of the list
  189. xor si,si ;FALSE return value is default
  190. DNH_Loop:
  191. push ax
  192. mov ax,ds:[di].ns_pNext ;Save the next pointer in a global
  193. mov npNotifyNext,ax ; so we can chain in NotifyUnregister
  194. pop ax
  195. or di,di ;End of list?
  196. jz DNH_Done ;Yep. Get out
  197. ;** If the flags for this notification are zero, we always send it
  198. or bx,bx ;Check the matching flags
  199. jz DNH_DoIt ;Do notification
  200. ;** See if the flags match
  201. test bx,ds:[di].ns_wFlags ;Check against the NOTIFYSTRUCT flags
  202. jz DNH_Continue ;If zero, no match, don't do it
  203. ;** Call the user callback
  204. DNH_DoIt:
  205. push ax ;Save everything we need
  206. push bx
  207. push cx
  208. push dx
  209. push ax ;wID
  210. push cx ;High word of dwData
  211. push dx ;Low word
  212. call DWORD PTR ds:[di].ns_lpfn ;Call the callback (PASCAL style)
  213. mov si,ax ;Get return value in SI
  214. pop dx ;Restore everything
  215. pop cx
  216. pop bx
  217. pop ax
  218. ;** If the return value is nonzero, we don't want to give this to
  219. ;** any more callbacks
  220. or si,si ;TRUE return value?
  221. jnz DNH_Done ;Yes, get out
  222. ;** Get the next callback
  223. DNH_Continue:
  224. mov di,npNotifyNext ;Get next pointer
  225. jmp DNH_Loop ; and loop back
  226. ;** End of callback loop.
  227. DNH_Done:
  228. ;** If this was an InChar message but everyone ignored it, force
  229. ;** the return to be an 'i' for 'ignore' on RIPs. This i
  230. ;** only necessary in 3.0 because the 3.1 KERNEL treats 0
  231. ;** returns just like 'i'
  232. cmp ax,NFY_INCHAR ;Is this an InChar notification?
  233. jne DNH_Default ;No, so ignore
  234. test wTHFlags,TH_WIN30 ;In 3.0?
  235. jz DNH_Default ;No, don't do this
  236. and si,0ffh ;Ignore all but low byte
  237. or si,si ;Non-zero?
  238. jnz DNH_Default ;Yes, return it as the character
  239. mov si,'i' ;Instead of zero, return 'i'gnore.
  240. DNH_Default:
  241. mov [bp - 02h],si ;Return the return code in AX
  242. ;** Clear off the stack and exit
  243. DNH_End:
  244. mov npNotifyNext,0 ;No current next pointer
  245. pop es ;Restore all registers
  246. pop ds
  247. popa
  248. pop bp
  249. retf ;Just return
  250. cEnd NOGEN
  251. ; NotifyRIPHandler
  252. ; Gets called by KERNEL when a RIP occurs. If it returns TRUE,
  253. ; KERNEL will act like the RIP was ignored. Otherwise, the RIP
  254. ; procedes normally.
  255. ; This routine does not need to worry about saving non-C regs
  256. cProc NotifyRIPHandler, <FAR,PUBLIC>
  257. ; parmW wExitCode
  258. cBegin nogen
  259. ;** Clear PASCAL-style parameters
  260. push bp ;Make a stack frame
  261. mov bp,sp
  262. mov bx,[bp + 6] ;Get the BP value
  263. mov dx,[bp + 8] ;Get the Exit code
  264. mov [bp - 2],ax ;Save it out of the way for now
  265. mov ax,[bp + 4] ;Get the RETF CS value
  266. mov [bp + 8],ax ;Shift down to clear parameters
  267. mov ax,[bp + 2] ;Get the RETF IP value
  268. mov [bp + 6],ax ;Shift down to clear parameters
  269. mov ax,[bp + 0] ;Get the old BP value
  270. mov [bp + 4],ax ;Shift down
  271. add bp,4 ;Move BP down on the stack
  272. mov sp,bp ;Point SP there too
  273. pusha ;Save matching register frame
  274. push ds
  275. push es
  276. ;** Get the data segment
  277. mov ax,_DATA ;Get TOOLHELP data segment
  278. mov ds,ax
  279. ;** Prepare to jump into the notification handler.
  280. ;** The trick here is that if a notification callback returns
  281. ;** non-zero, the RIP has been handled. Otherwise, it has not.
  282. ;** DX holds the exit code here, BX has the old BP value
  283. lea si,ReturnStruct ;Get a pointer to the return struct
  284. mov WORD PTR [si].nrp_dwSize[0],SIZE NFYRIP
  285. mov WORD PTR [si].nrp_dwSize[2],0
  286. mov ax,ss:[bx + 4] ;Get old CS value from stack
  287. mov [si].nrp_wCS,ax ; (BX is BP from FatalExit stack)
  288. mov ax,ss:[bx + 2] ;Get old IP value
  289. mov [si].nrp_wIP,ax
  290. mov [si].nrp_wSS,ss ;Save SS:BP for stack trace
  291. mov [si].nrp_wBP,bx
  292. mov [si].nrp_wExitCode,dx
  293. mov cx,ds ;Point to structure
  294. mov dx,si
  295. mov bx,NF_RIP ;Get the NOTIFYINFO match flags
  296. mov ax,NFY_RIP ;TOOLHELP ID
  297. ;** Jump to the real handler
  298. jmp DNH_Decoded ;Jump to alternate entry point
  299. cEnd nogen
  300. ;** Helper routines
  301. ; DecodeNotification
  302. ; Decodes a notification by pointing to a static structure and filling
  303. ; this structure with notification-specific information.
  304. ; The PTrace notification ID is in AX.
  305. ; Returns the ToolHelp ID in AX
  306. ; and the dwData value is in CX:DX.
  307. cProc DecodeNotification, <NEAR,PUBLIC>
  308. cBegin
  309. ;** Point dwData to the structure just in case
  310. mov cx,ds ;Get the segment value
  311. lea dx,ReturnStruct ;Get a pointer to the return struct
  312. xor bx,bx ;Most notifications always match
  313. ;** The stack frame looks like this:
  314. ;* ------------
  315. ;* | ES | [BP - 14h]
  316. ;* | DS | [BP - 12h]
  317. ;* | DI | [BP - 10h]
  318. ;* | SI | [BP - 0Eh]
  319. ;* | BP | [BP - 0Ch]
  320. ;* | SP | [BP - 0Ah]
  321. ;* | BX | [BP - 08h]
  322. ;* | DX | [BP - 06h]
  323. ;* | CX | [BP - 04h]
  324. ;* | AX | [BP - 02h]
  325. ;* BP-->| Old BP | [BP - 00h]
  326. ;* ------------
  327. ;**
  328. FrameES EQU [BP - 14h]
  329. FrameDS EQU [BP - 12h]
  330. FrameDI EQU [BP - 10h]
  331. FrameSI EQU [BP - 0Eh]
  332. FrameBP EQU [BP - 0Ch]
  333. FrameSP EQU [BP - 0Ah]
  334. FrameBX EQU [BP - 08h]
  335. FrameDX EQU [BP - 06h]
  336. FrameCX EQU [BP - 04h]
  337. FrameAX EQU [BP - 02h]
  338. ;** Check for LoadSeg
  339. cmp ax,NI_LOADSEG ;LoadSeg?
  340. jnz DN_10 ;No
  341. ;** LoadSeg:
  342. ;* CX is selector
  343. ;* BX is segment number
  344. ;* SI is type: Low bit set for data segment, clear for code
  345. ;* DX is instance count only for data segments
  346. ;** ES:DI module name
  347. mov si,dx ;Point to NFYLOADSEG struct
  348. mov ax,SIZE NFYLOADSEG ;Get the structure size
  349. mov WORD PTR [si].nls_dwSize,ax ;Save the LOWORD of the size
  350. mov WORD PTR [si].nls_dwSize + 2,0 ;HIWORD is zero
  351. mov ax,FrameCX ;Get selector
  352. mov [si].nls_wSelector,ax ;Save in structure
  353. mov ax,FrameBX ;Get segment number
  354. inc ax ;Segment number is 1-based
  355. mov [si].nls_wSegNum,ax ;Save in structure
  356. mov ax,FrameSI ;Get the segment type
  357. mov [si].nls_wType,ax ;Put in structure
  358. mov ax,FrameDX ;Get instance count
  359. mov [si].nls_wcInstance,ax ;Put in structure
  360. mov ax,FrameDI ;Get offset of module name str
  361. mov WORD PTR [si].nls_lpstrModuleName,ax ;Save it
  362. mov ax,FrameES ;Get segment of module name str
  363. mov WORD PTR [si].nls_lpstrModuleName + 2,ax ;Save it
  364. mov ax,NFY_LOADSEG ;Get the TOOLHELP ID
  365. jmp DN_End
  366. ;** Check for FreeSeg
  367. DN_10: cmp ax,NI_FREESEG ;FreeSeg?
  368. jnz DN_15 ;No
  369. ;** FreeSeg:
  370. ;** BX is selector
  371. xor cx,cx ;Clear high word
  372. mov dx,FrameBX ;Get the selector
  373. test wTHFlags,TH_WIN30STDMODE ;3.0 standard mode?
  374. jz DN_FS_GotSelValue ;No, what we have is correct
  375. mov si,FrameSP ;Point to old stack frame
  376. mov dx, ss:[si + 6] ;Selector is 6 bytes down
  377. lsl ax, dx
  378. jz DN_FS_CheckLen ;Selector is OK
  379. mov dx, FrameBX ;Revert to BX value
  380. jmp SHORT DN_FS_GotSelValue
  381. DN_FS_CheckLen:
  382. cmp ax, 15 ;If the segment is 15 bytes long,
  383. jne DN_FS_GotSelValue ; this is a bogus selector and is
  384. ; really an arena header.
  385. push es
  386. mov es, dx ;Get handle
  387. cCall HelperHandleToSel, <es:[0ah]> ;Convert to selector
  388. mov dx, ax ;Get handle out of arena header
  389. pop es
  390. DN_FS_GotSelValue:
  391. mov ax,NFY_FREESEG ;Get the TOOLHELP ID
  392. jmp DN_End
  393. ;** Check for StartDLL
  394. DN_15: cmp ax,NI_LOADDLL
  395. jnz DN_20
  396. ;** StartDLL:
  397. ;** CX is CS
  398. ;** BX is IP
  399. ;** SI is Module handle
  400. mov si,dx ;Point with SI
  401. mov ax,SIZE NFYSTARTDLL ;Get the size
  402. mov WORD PTR [si].nsd_dwSize,ax ;Save the LOWORD of the size
  403. mov WORD PTR [si].nsd_dwSize + 2,0 ;HIWORD is always zero
  404. mov ax,FrameSI ;Get the hInstance
  405. mov [si].nsd_hModule,ax ;Save in structure
  406. mov ax,FrameCX ;Get the starting CS
  407. mov [si].nsd_wCS,ax ;Save in structure
  408. mov ax,FrameBX ;Get the starting IP
  409. mov [si].nsd_wIP,ax ;Save in structure
  410. mov ax,NFY_STARTDLL
  411. jmp DN_End
  412. ;** Check for StartTask
  413. DN_20: cmp ax,NI_STARTTASK ;StartTask?
  414. jnz DN_30 ;No
  415. ;** StartTask:
  416. ;* CX is CS
  417. ;** BX is IP
  418. mov cx,FrameCX
  419. mov dx,FrameBX
  420. mov ax,NFY_STARTTASK
  421. jmp DN_End
  422. ;** Check for ExitCall
  423. DN_30: cmp ax,NI_EXITCALL ;ExitCall
  424. jnz DN_40 ;No
  425. ;** ExitCall:
  426. ;* Exit code is on stack somewhere if we don't have the new
  427. ;** notification handler. If we do, it's in BL.
  428. xor cx,cx ;Clear all but low byte
  429. xor dh,dh
  430. test wTHFlags,TH_GOODPTRACEHOOK ;Do we have the good hook?
  431. jz DN_DoOldHook ;Nope, grope on the stack
  432. mov dl,BYTE PTR FrameBX ;Get the exit code
  433. mov ax,NFY_EXITTASK ;Get the TOOLHELP ID
  434. jmp DN_End
  435. DN_DoOldHook:
  436. mov si,FrameSP ;Point to old stack frame
  437. mov dl,ss:[si + 6] ;Exit code is 6 bytes down on stack
  438. mov ax,NFY_EXITTASK ;Get the TOOLHELP ID
  439. jmp DN_End
  440. ;** Check for DelModule
  441. DN_40: cmp ax,NI_DELMODULE ;DelModule?
  442. jnz DN_60 ;No
  443. ;** DelModule:
  444. ;** ES is module handle
  445. xor cx,cx ;Clear HIWORD
  446. mov dx,FrameES ;Get the module handle
  447. mov ax,NFY_DELMODULE ;Get the TOOLHELP ID
  448. jmp DN_End
  449. ;** Check for TaskSwitchIn
  450. DN_60: cmp ax,NI_TASKIN ;TaskSwitchIn?
  451. jnz DN_70 ;No
  452. ;** TaskSwitchIn:
  453. ;** No data. Callback should do GetCurrentTask()
  454. xor cx,cx ;Clear data
  455. xor dx,dx
  456. mov ax,NFY_TASKIN ;Get the TOOLHELP ID
  457. mov bx,NF_TASKSWITCH ;Get the NOTIFYSTRUCT match flag
  458. jmp DN_End
  459. ;** Check for TaskSwitchOut
  460. DN_70: cmp ax,NI_TASKOUT ;TaskSwitchOut?
  461. jnz DN_90 ;No
  462. ;** TaskSwitchOut:
  463. ;** No data
  464. xor cx,cx ;Clear data
  465. xor dx,dx
  466. mov ax,NFY_TASKOUT ;Get the TOOLHELP ID
  467. mov bx,NF_TASKSWITCH ;Get the NOTIFYSTRUCT match flag
  468. jmp DN_End
  469. ;** Check for OutStr
  470. DN_90: cmp ax,NI_OUTSTR ;OutStr?
  471. jnz DN_100 ;No
  472. ;** OutStr:
  473. ;** ES:SI points to string to display in 3.1
  474. ;** DS:SI in 3.0
  475. test wTHFlags,TH_WIN30 ;3.0?
  476. jz DN_OS_Win31 ;Nope
  477. mov cx,FrameDS ;Get the segment value
  478. jmp SHORT @F
  479. DN_OS_Win31:
  480. mov cx,FrameES ;Get the segment value
  481. @@: mov dx,FrameSI ; and the offset
  482. mov ax,NFY_OUTSTR ;Get the TOOLHELP ID
  483. jmp DN_End
  484. ;** Check for InChar
  485. DN_100: cmp ax,NI_INCHAR ;InChar?
  486. jnz DN_105 ;No
  487. ;** InChar:
  488. ;** No data passed (it wants data back in AL)
  489. xor cx,cx ;Clear dwData
  490. xor dx,dx
  491. mov ax,NFY_INCHAR ;Get the TOOLHELP ID
  492. jmp SHORT DN_End
  493. ;** NOTE: The following notifications are defined as "NEW" and
  494. ;** are NOT sent through the normal PTrace interface so as to
  495. ;** not break CodeSpew. It stack faults when
  496. ;** it is sent a notification it doesn't understand. So,
  497. ;** here we don't bother decoding any of these unless we have
  498. ;** the new (Win 3.1) style hook
  499. DN_105: test wTHFlags,TH_GOODPTRACEHOOK ;Do we have the advanced hook?
  500. jnz DN_110 ;Yes
  501. jmp SHORT DN_End
  502. ;** Check for the parameter validation notifications
  503. DN_110: cmp ax,NI_LOGERROR ;SDM_LOGERROR?
  504. jne DN_120 ;No
  505. ;** SDM_LOGERROR:
  506. ;* CX is Error code
  507. ;** DX:BX is lpInfo
  508. mov si,dx ;Point with SI
  509. mov ax,SIZE NFYLOGERROR ;Get the size
  510. mov WORD PTR [si].nle_dwSize[0],ax ;Save the LOWORD of the size
  511. mov WORD PTR [si].nle_dwSize[2],0 ;HIWORD is always zero
  512. mov ax,FrameCX ;Get the error code
  513. mov [si].nle_wErrCode,ax ;Save in structure
  514. mov ax,FrameDX ;Get the lpInfo
  515. mov WORD PTR [si].nle_lpInfo[2],ax ;Save in structure
  516. mov ax,FrameBX
  517. mov WORD PTR [si].nle_lpInfo[0],ax ;Save in structure
  518. mov ax,NFY_LOGERROR ;Get the TOOLHELP ID
  519. jmp SHORT DN_End
  520. DN_120: cmp ax,NI_LOGPARAMERROR ;SDM_LOGPARAMERROR?
  521. jne DN_Unknown ;No
  522. ;** SDM_LOGPARAMERROR:
  523. ;** ES:BX points to a structure:
  524. ;** WORD wErr
  525. ;** FARPROC lpfn
  526. ;** VOID FAR* lpBadParam
  527. mov si,dx ;Point with SI
  528. mov ax,SIZE NFYLOGPARAMERROR ;Struct size
  529. mov WORD PTR [si].nlp_dwSize[0],ax ;Save the LOWORD of the size
  530. mov WORD PTR [si].nlp_dwSize[2],0 ;HIWORD is always zero
  531. mov es,FrameES ;Point to the structure
  532. mov bx,FrameBX
  533. mov ax,es:[bx] ;Get wErr
  534. mov [si].nlp_wErrCode,ax ;Save in structure
  535. mov ax,es:[bx + 2] ;Get lpfn[0]
  536. mov WORD PTR [si].nlp_lpfnErrorAddr[0],ax
  537. mov ax,es:[bx + 4] ;Get lpfn[2]
  538. mov WORD PTR [si].nlp_lpfnErrorAddr[2],ax
  539. mov ax,es:[bx + 6] ;Get lpBadParam[0]
  540. mov WORD PTR [si].nlp_lpBadParam[0],ax
  541. mov ax,es:[bx + 8] ;Get lpBadParam[2]
  542. mov WORD PTR [si].nlp_lpBadParam[2],ax
  543. mov ax,NFY_LOGPARAMERROR ;Get the TOOLHELP ID
  544. xor bx,bx ;Always match
  545. jmp SHORT DN_End
  546. ;** Must be unknown, return TOOLHELP ID NFY_UNKNOWN with KERNEL value
  547. ;** in LOWORD(wData)
  548. DN_Unknown:
  549. mov dx,ax ;Get the notification value
  550. mov ax,NFY_UNKNOWN ;Unknown KERNEL notification
  551. xor cx,cx ;Clear high WORD
  552. DN_End:
  553. cEnd
  554. sEnd
  555. END