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.

555 lines
22 KiB

  1. ;**************************************************************************
  2. ;* HELPER.ASM
  3. ;*
  4. ;* Assembly routines used by more than one module
  5. ;*
  6. ;**************************************************************************
  7. INCLUDE TOOLPRIV.INC
  8. INCLUDE WINDOWS.INC
  9. PMODE32 = 0
  10. PMODE = 1
  11. SWAPPRO = 0
  12. INCLUDE WINKERN.INC
  13. INCLUDE NEWEXE.INC
  14. INCLUDE TDB.INC
  15. ;** External functions
  16. externNP Walk386VerifyLocHeap
  17. externNP Walk286VerifyLocHeap
  18. externFP GetCurrentTask
  19. externFP InterruptUnRegister
  20. externFP NotifyUnRegister
  21. externNP SignalUnRegister
  22. externFP TaskFirst
  23. externFP TaskNext
  24. ;** Functions
  25. sBegin CODE
  26. assumes CS,CODE
  27. .286p
  28. ; HelperVerifySeg
  29. ;
  30. ; Verifies that a selector is valid and that the segment it points
  31. ; to is safe for reading out to wcb bytes offset
  32. ; Returns 0 if too short or the length of the segment.
  33. ; Preserves all used registers except the return value, AX
  34. cProc HelperVerifySeg, <PUBLIC,NEAR>, <dx>
  35. parmW wSeg
  36. parmW wcb
  37. cBegin
  38. ;** Verify that this is a valid selector and that it is long enough
  39. cCall HelperSegLen, <wSeg> ;Check the segment
  40. or dx,dx ;>64K? If so, always return OK
  41. jnz HVS_End
  42. cmp ax,wcb ;Long enough?
  43. ja HVS_End ;Yes, return the length
  44. HVS_Bad:
  45. xor ax,ax ;No. Return FALSE
  46. HVS_End:
  47. cEnd
  48. ; HelperHandleToSel
  49. ; Converts a handle to a selector. This routine knows how to
  50. ; handle 3.0 and 3.1 differences as well as 286 & 386 differences.
  51. cProc HelperHandleToSel, <NEAR,PUBLIC>, <ds>
  52. parmW h ;Handle
  53. cBegin
  54. mov ax,_DATA ;Get the data segment
  55. mov ds,ax ;Point with DS
  56. mov ax,h ;Get the handle
  57. test wTHFlags,TH_WIN30 ;Win3.0?
  58. jz HTS_Win31 ;No
  59. test ax,1 ;Check the low bit
  60. jnz HTS_End ;It's already a selector
  61. dec ax ;Decrement for proper selector
  62. jmp SHORT HTS_End ;Out of here
  63. HTS_Win31:
  64. or ax,1 ;Set the bit
  65. HTS_End:
  66. cEnd
  67. ; HelperVerifyLocHeap
  68. ;
  69. ; Uses the processor-specific local heap verify routine to check the
  70. ; validity of a local heap.
  71. ;
  72. ; Call:
  73. ; AX = Block handle or selector
  74. ; DS must point to TOOLHELP's DGROUP
  75. ; Return:
  76. ; Carry flag set iff NOT a local heap segment
  77. ;
  78. ; Destroys all registers except AX, ESI, EDI, DS, and ES
  79. HelperVerifyLocHeap PROC Near
  80. PUBLIC HelperVerifyLocHeap
  81. test wTHFlags,TH_KERNEL_386 ;Are we using KRNL386?
  82. jz HVL_286 ;No
  83. jmp Walk386VerifyLocHeap ;Jump to the 386 routine
  84. HVL_286:
  85. jmp Walk286VerifyLocHeap ;Jump to the 286 routine
  86. HVL_End:
  87. ret
  88. HelperVerifyLocHeap ENDP
  89. ; HelperGlobalType
  90. ;
  91. ; Given data about a block, gropes around trying to decipher the
  92. ; block type. Parameters are passed and returned in the GLOBALENTRY
  93. ; structure.
  94. cProc HelperGlobalType, <PUBLIC,NEAR>, <si,di,ds>
  95. parmD lpGlobal
  96. localV Task,<SIZE TASKENTRY>
  97. cBegin
  98. lds si,lpGlobal ;Get the pointer
  99. mov [si].ge_wData,0 ;Clear the wData field
  100. ; Zero's not a valid seg # or type #
  101. ;** Check for internal block types
  102. mov bx,[si].ge_hOwner ;Get the owner handle
  103. mov ax,GT_SENTINEL ;Just in case...
  104. cmp bx,GA_SENTINAL ;Is this a sentinel?
  105. jz HGT_JmpEnd ;Yes, get out
  106. mov ax,GT_BURGERMASTER ;Just in case...
  107. cmp bx,GT_BURGERMASTER ;Burgermaster?
  108. jz HGT_JmpEnd ;Yes, get out
  109. cmp bx,-7 ;Lowest number reserved
  110. jb HGT_0 ;Not an internal block
  111. mov ax,GT_INTERNAL ;Internal KERNEL block type
  112. HGT_JmpEnd:
  113. jmp HGT_End ;Get out
  114. HGT_0:
  115. ;** Check for a free block
  116. or bx,bx ;Check for 0: Free block
  117. jnz HGT_2 ;Not zero
  118. mov ax,GT_FREE ;Free blocks have zero owner
  119. jmp HGT_End ;Unknown type
  120. HGT_2:
  121. ;** Check for DGROUP and other data segments
  122. mov ax,[si].ge_wFlags ;Get the block flags
  123. test ax,GAH_DGROUP ;Is this a DGROUP segment
  124. jnz @F
  125. jmp HGT_10 ;Didn't find it so continue
  126. @@:
  127. ;** Save the segment number of the segment
  128. mov ax,[si].ge_hOwner ;Get the module database
  129. push ax ;Save for later
  130. mov bx,[si].ge_hBlock ;Get the handle
  131. cCall HelperGetSegNumber ;Get the segment number
  132. mov [si].ge_wData,ax ;Save the segment number
  133. pop bx ;Get hExe back in BX
  134. ;** Try two methods: First, see if it is the hInst of the FIRST
  135. ;** instance of its module
  136. lsl cx, bx ;Is this segment OK?
  137. jnz HGT_5 ;No, punt and call it unknown data
  138. cmp cx, ne_pautodata ;Long enough?
  139. jbe HGT_5 ;No, get out
  140. mov es,bx ;Point with ES
  141. cmp es:[ne_magic],NEMAGIC ;Make sure we have a module database
  142. jnz HGT_5 ;It isn't so get out
  143. mov bx,es:[ne_pautodata] ;Point to the segment table entry
  144. or bx,bx ;Is there a DGROUP segment?
  145. jz HGT_5 ;No, flag as unknown data
  146. mov ax,es:[bx].ns_handle ;Get the handle from the table
  147. cmp ax,[si].ge_hBlock ;Does the DGROUP handle point here?
  148. jnz HGT_3 ;No, might be multiple instance
  149. mov ax,GT_DGROUP ;Matches, must be DGROUP
  150. jmp HGT_End ;Get out
  151. HGT_3:
  152. ;** It's not the first instance of this module.
  153. ;** All multiple instance things will be on the task list
  154. ;** so try to find it there.
  155. mov bx,[si].ge_hBlock ;Get the handle
  156. cCall HelperHandleToSel,<bx> ;Get the selector for this
  157. mov di,ax ;Save in DI
  158. mov ax,SIZE TASKENTRY ;Get the struct size
  159. mov WORD PTR Task.te_dwSize[0],ax ;Put in struct
  160. mov WORD PTR Task.te_dwSize[2],0 ;Clear high word
  161. lea ax,Task ;Get the structure
  162. cCall TaskFirst, <ss,ax> ;Get the first task's info
  163. or ax,ax ;No tasks?
  164. jz HGT_5 ;Just call it data (not DGROUP)
  165. HGT_TaskLoop:
  166. mov ax,Task.te_hInst ;Get this task's hInst
  167. cCall HelperHandleToSel, <ax> ;Convert to selector
  168. cmp ax,di ;Is this a match?
  169. je HGT_TaskFound ;Yes, do it
  170. lea ax,Task ;Point to the struct
  171. cCall TaskNext, <ss,ax> ;Get the next one
  172. or ax,ax ;End of the line?
  173. jnz HGT_TaskLoop ;Nope, do the next one
  174. HGT_5: mov ax,GT_DATA ;Unknown data segment
  175. jmp HGT_End ;Get out
  176. HGT_TaskFound:
  177. mov ax,GT_DGROUP ;Matches, must be DGROUP
  178. jmp HGT_End ;Get out
  179. HGT_10:
  180. ;** Check for a task database
  181. mov ax,[si].ge_hBlock ;Get the segment
  182. mov bx,TDBSize ;Get the limit to verify
  183. push ax ;Save the segment
  184. cCall HelperVerifySeg <ax,bx> ;Make sure we can check signature
  185. pop bx ;Retrieve the segment value
  186. or ax,ax ;Zero return means bad
  187. jz HGT_20 ;Not a task database
  188. mov es,bx ;Point to the segment
  189. cmp es:[TDB_sig],TDB_SIGNATURE ;Is this really a TDB?
  190. jnz HGT_20 ;Nope, go on
  191. mov ax,GT_TASK ;Set the task flag
  192. jmp HGT_End ;Get out
  193. HGT_20:
  194. ;** Now check for Module database
  195. mov ax,[si].ge_hOwner ;Get the owner handle
  196. cCall HelperHandleToSel, <ax> ;Convert to selector for compare
  197. mov cx,ax ;Save in CX
  198. mov ax,[si].ge_hBlock ;Does this block own itself?
  199. cCall HelperHandleToSel, <ax> ;Convert to selector for compare
  200. cmp ax,cx ;Do the pointers match?
  201. jnz HGT_24 ;No, so it's not a module database
  202. mov ax,GT_MODULE ;Set type
  203. jmp HGT_End ;Get out
  204. HGT_24:
  205. ;** Check for a code segment. If found, return segment number
  206. mov ax,[si].ge_hOwner ;Get the module database
  207. push ax ;Save the selector
  208. cCall HelperVerifySeg <ax,2> ;Make sure this is OK to put in ES
  209. pop bx ;Retrieve in BX
  210. or ax,ax ;Zero means bad
  211. jnz @F
  212. jmp SHORT HGT_Unknown
  213. @@: mov es,bx ;Point with ES
  214. xor dx,dx ;Use DX to count segments
  215. cmp es:[ne_magic],NEMAGIC ;Make sure we have a module database
  216. jz HGT_25 ;Looks good
  217. jmp SHORT HGT_40 ;Not code or resource, try next
  218. HGT_25: mov cx,es:[ne_cseg] ;Get max number of segments
  219. jcxz HGT_30 ;No segments
  220. mov di,es:[ne_segtab] ;Point to the segment table
  221. mov bx,[si].ge_hBlock ;Get the block we're looking for
  222. HGT_SegLoop:
  223. inc dx ;Bump the segment number
  224. cmp bx,es:[di].ns_handle ;Is this the correct segment entry?
  225. jz HGT_27 ;Yes, get out
  226. add di,SIZE new_seg1 ;Bump to next entry
  227. loop HGT_SegLoop ;Loop back to check next entry
  228. jmp SHORT HGT_30 ;Now check resources
  229. HGT_27:
  230. mov [si].ge_wData,dx ;Save the segment count
  231. mov ax,GT_CODE ;Flag that it's a code segment
  232. jmp SHORT HGT_End ;Get out
  233. ;** Check to see if it's a resource. If so, return resource type #
  234. HGT_30: mov di,es:[ne_rsrctab] ;Point to the resource table
  235. cmp di,es:[ne_restab] ;If both point to same place, no rsrc
  236. jz HGT_40 ;No resource table -- unknown type
  237. add di,2 ;Skip past alignment count
  238. HGT_TypeLoop:
  239. mov dx,es:[di].rt_id ;DX holds current type number
  240. or dx,dx ;Zero type means end of res table
  241. jz HGT_40 ;Not found so get out!
  242. mov cx,es:[di].rt_nres ;Get the number of resources
  243. add di,SIZE RSRC_TYPEINFO ;Bump past the structure
  244. HGT_ResLoop:
  245. cmp bx,es:[di].rn_handle ;Is it this resource?
  246. jz HGT_FoundRes ;Yep. This is the one
  247. add di,SIZE RSRC_NAMEINFO ;Bump past this structure
  248. loop HGT_ResLoop ;Loop for next resource structure
  249. jmp HGT_TypeLoop ;Try the next type
  250. ;** Found the resource, now compute the resource type
  251. HGT_FoundRes:
  252. test dx,RSORDID ;If this bit set, must be ordinal type
  253. jnz HGT_32 ;Yep. Ordinal
  254. mov dx,GD_USERDEFINED ;Named resources are all user-def
  255. HGT_32: and dx,NOT RSORDID ;Clear the flag bit
  256. cmp dx,GD_MAX_RESOURCE ;If the type is too big, it's user-def
  257. jbe HGT_34 ;Standard type
  258. mov dx,GD_USERDEFINED ;User-defined resource type
  259. HGT_34: mov [si].ge_wData,dx ;Save the type
  260. mov ax,GT_RESOURCE ;Return that it's a resource
  261. jmp SHORT HGT_End ;Get out
  262. HGT_40:
  263. HGT_Unknown:
  264. mov ax,GT_UNKNOWN ;Unknown type
  265. HGT_End:
  266. mov [si].ge_wType,ax ;Save the type and exit
  267. cEnd
  268. ; HelperGrabSelector
  269. ;
  270. ; Allocates a selector from DPMI.
  271. cProc HelperGrabSelector, <NEAR,PUBLIC>
  272. cBegin
  273. xor ax,ax ;DPMI Function 0, allocate LDT sels
  274. mov cx,1 ;Just 1 sel
  275. int 31h ;Call DPMI. Selector in AX
  276. cEnd
  277. ; HelperReleaseSelector
  278. ;
  279. ; Frees a selector to DPMI
  280. cProc HelperReleaseSelector, <NEAR,PUBLIC>
  281. parmW wSelector
  282. cBegin
  283. mov ax,1 ;DPMI function 1, free LDT sels
  284. mov bx,wSelector ;Get the sel
  285. int 31h ;Free it
  286. cEnd
  287. ; HelperSetSignalProc
  288. ; Puts a signal proc in a task's TDB so that it gets called in place
  289. ; of USER's proc. Returns the old USER proc.
  290. cProc HelperSetSignalProc, <NEAR,PUBLIC>, <si,di>
  291. parmW hTask,
  292. parmD lpfn
  293. cBegin
  294. ;** Point to the TDB
  295. mov es,hTask ;Point with ES
  296. ;** Swap the new with the old and return the old one
  297. mov ax,WORD PTR lpfn ;Get the new signal proc
  298. xchg ax,WORD PTR es:[TDB_USignalProc] ;Switch with the old one
  299. mov dx,WORD PTR lpfn + 2 ;Get HIWORD
  300. xchg dx,WORD PTR es:[TDB_USignalProc + 2] ;Switch with old one
  301. cEnd
  302. ; HelperSignalProc
  303. ; Cleans up when a TOOLHELP-using app is terminated. This proc
  304. ; MUST chain on to USER's signal proc. Note that action is only taken
  305. ; on the death signal (BX = 0666h)
  306. cProc HelperSignalProc, <FAR,PUBLIC>
  307. cBegin NOGEN
  308. ;** Save all registers
  309. sub sp,4
  310. push bp
  311. mov bp,sp ;Make a stack frame
  312. pusha
  313. push ds
  314. push es
  315. ;** Get a pointer to the correct SIGNAL structure
  316. mov ax,_DATA ;Get the TOOLHELP.DLL DS
  317. mov ds,ax ;Point with DS
  318. cCall GetCurrentTask ;Get the current task in AX
  319. mov di,ax ;Save task in DI
  320. mov si,npSignalHead ;Get the first struct
  321. HSP_SigLoop:
  322. or si,si ;End of the list?
  323. jz HSP_Return ;Yes -- This is bad!!
  324. cmp di,[si].si_hTask ;Task match?
  325. je HSP_FoundIt ;Yes
  326. mov si,[si].si_pNext ;Get the next one
  327. jmp HSP_SigLoop ;Loop around
  328. ;** Compute the fake return address (old signal proc)
  329. HSP_FoundIt:
  330. mov ax,WORD PTR [si].si_lpfnOld ;Get LOWORD of old proc
  331. mov [bp + 2],ax ;Put on stack frame
  332. mov dx,WORD PTR [si].si_lpfnOld + 2 ;Get HIWORD of old proc
  333. mov [bp + 4],dx ;Put on stack frame
  334. ;** See if we have the death signal. If not, don't do anything
  335. ;** but just chain on. 20h is the signal for task exit
  336. cmp bx, 20h ;Is this the death signal?
  337. jne HSP_Done ;No. Don't cleanup
  338. ;** Since we have a death signal, use it to clean up everything
  339. push ax ;Save the return address
  340. push dx
  341. cCall InterruptUnRegister, <di> ;Unregister any interrupt callbacks
  342. cCall NotifyUnRegister, <di> ;Unregister any notification callbacks
  343. cCall SignalUnRegister, <di> ;Unregister any signal callbacks
  344. ;** If we have fooled with the LRU lock (we only do this on 286
  345. ;** machines), we must force it unlocked.
  346. cmp wLRUCount, 0 ;Is it set?
  347. je HSP_NoLRUFoolingAround ;No, don't mess with this
  348. mov es, hMaster ;Point to GlobalInfo struct
  349. mov ax, es:[gi_lrulock] ;Get current lock count
  350. sub ax, wLRUCount ;Get rid of the amount we messed it up
  351. jns @F ;Result is OK--no underflow
  352. xor ax, ax ;We don't like negative, so zero it
  353. @@: mov es:[gi_lrulock], ax ;Save the result
  354. mov wLRUCount, 0 ;No more LRU count
  355. HSP_NoLRUFoolingAround:
  356. pop dx
  357. pop ax
  358. ;** Make sure we have a proc to chain to
  359. HSP_Done:
  360. or ax,dx ;NULL pointer?
  361. jz HSP_Return ;Yes, don't chain to this one
  362. HSP_ChainOn:
  363. pop es
  364. pop ds
  365. popa
  366. pop bp
  367. retf ;Jump to next signal proc
  368. HSP_Return:
  369. pop es
  370. pop ds
  371. popa
  372. pop bp
  373. add sp,4 ;Clear fake return address
  374. retf 10 ;Return to signal caller
  375. cEnd NOGEN
  376. ; HelperSegLen
  377. ; Gets the length of a segment, regardless whether it is a 286 or
  378. ; 386 segment.
  379. ; Returns the DWORD length of the segment or zero on error.
  380. ; Doesn't trash registers except DX:AX
  381. cProc HelperSegLen, <NEAR,PUBLIC>, <si,di,cx>
  382. parmW wSeg
  383. cBegin
  384. ;** Make sure the segment is present
  385. mov cx,wSeg ;Get the selector
  386. lar ax,cx ;Get the access rights
  387. jnz HSL_Bad ;If LAR fails, this is bad
  388. test ax,8000h ;Is this segment present?
  389. jz HSL_Bad ;No, call it bad
  390. ;** Do different stuff on 286 and 386/486
  391. mov ax,__WinFlags ;Get the flags
  392. test ax,WF_CPU286 ;286?
  393. jnz HSL_Do286 ;Yes, do 16 bit stuff
  394. ;** Get the 32 bit length
  395. .386p
  396. lsl eax,ecx ;Get the limit
  397. jnz SHORT HSL_Bad ;We have an error
  398. mov edx,eax ;Get HIWORD in DX
  399. shr edx,16
  400. jmp SHORT HSL_End ;Done
  401. .286p
  402. ;** Get the 16 bit length
  403. HSL_Do286:
  404. xor dx,dx ;286 never has >64K segs
  405. lsl ax,cx ;Get the limit
  406. jnz HSL_Bad ;Bad if LSL fails
  407. jmp SHORT HSL_End ;Done
  408. HSL_Bad:
  409. xor ax,ax ;Zero return value
  410. xor dx,dx
  411. HSL_End:
  412. cEnd
  413. ; HelperGetSegNumber
  414. ;
  415. ; Returns the segment number corresponding to a selector given the
  416. ; hExe.
  417. ;
  418. ; Caller: AX=hExe, BX=Handle
  419. ; Exit: AX=Seg Number or 0
  420. cProc HelperGetSegNumber, <NEAR,PUBLIC>, <di>
  421. cBegin
  422. lsl cx, ax ;Is the segment OK to load?
  423. jnz HGSN_Error ;No, don't do it
  424. cmp cx, ne_segtab ;Long enough?
  425. jbe HGSN_Error ;No
  426. mov es,ax ;Point with ES
  427. xor dx,dx ;Use DX to count segments
  428. cmp es:[ne_magic],NEMAGIC ;Make sure we have an hExe
  429. jnz HGSN_Error ;Nope, get out
  430. mov cx,es:[ne_cseg] ;Get max number of segments
  431. jcxz HGSN_Error ;No segments
  432. mov di,es:[ne_segtab] ;Point to the segment table
  433. HGSN_SegLoop:
  434. inc dx ;Bump the segment number
  435. cmp bx,es:[di].ns_handle ;Is this the correct segment entry?
  436. je HGSN_FoundIt ;Yes, get out
  437. add di,SIZE new_seg1 ;Bump to next entry
  438. loop HGSN_SegLoop ;Loop back to check next entry
  439. jmp SHORT HGSN_Error ;Not found
  440. HGSN_FoundIt:
  441. mov ax,dx ;Get segment number
  442. jmp SHORT HGSN_End
  443. HGSN_Error:
  444. xor ax,ax ;Error return
  445. HGSN_End:
  446. cEnd
  447. ;** Internal helper functions
  448. ; HelperPDBtoTDB
  449. ;
  450. ; Takes a PDB handle and finds the task handle associated with it.
  451. ; Caller: AX = PDB Handle
  452. ; Return: AX = TDB handle or zero if no TDB exists for it
  453. cProc HelperPDBtoTDB, <NEAR,PUBLIC>
  454. cBegin
  455. ;** Point to the first TDB
  456. mov dx,_DATA ;Get the library static segment
  457. mov es,dx ;Point with ES
  458. mov bx,es:[npwTDBHead] ;Get pointer to first TDB
  459. mov dx,es:[segKernel] ;Get the KERNEL data segment
  460. mov es,dx ;Point with ES
  461. mov dx,es:[bx] ;Get the first TDB
  462. ;** Check this TDB's PDB to see if it matches
  463. PT_Loop:
  464. mov es,dx ;Get the TDB segment
  465. cmp ax,es:[TDB_PDB] ;Compare PDB pointers
  466. jz PT_Found ;This is it
  467. mov dx,es:[TDB_next] ;Get the next TDB
  468. or dx,dx ;End of the line?
  469. jnz PT_Loop ;Nope, loop back
  470. xor ax,ax ;Return NULL'
  471. jmp SHORT PT_End ;Outta here
  472. PT_Found:
  473. mov ax,es ;Save the found value
  474. PT_End:
  475. cEnd
  476. sEnd
  477. END