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.

534 lines
16 KiB

  1. ;/*
  2. ; Flags for Heap Header
  3. L32F_NOHUSED equ 1
  4. ; Heap signature
  5. L32_SIGNATURE equ 3233484Ch ; 'LH32'
  6. ; Flags for Local32Init
  7. LINIT_MAX16HEAP equ 1
  8. LINIT_TILEHEAP equ 2
  9. ; Flags for Local32Alloc
  10. LMEM32_64K equ 1
  11. LMEM32_ZEROINIT equ 2
  12. ; Address types
  13. NOHPTR16 equ -2
  14. NOHPTR32 equ -1
  15. HANDLE16 equ 0
  16. PTR16 equ 1
  17. PTR32 equ 2
  18. ; if address type is < MINHTYPE, there is no handle associated with address
  19. MINHTYPE equ 0
  20. ;-----------------------------------------------------------------------;
  21. ; Heap Header (lives at 64K-(SIZE L32HeapHeader))
  22. ;-----------------------------------------------------------------------;
  23. L32HeapHeader struc
  24. FreeLists dw 16 dup(?) ; array of ptrs to free handles in each page
  25. FreeCounts dw 16 dup(?) ; array of counts of free handles in each page
  26. FreeTails dw 16 dup(?) ; array of ptrs to tail of free lists
  27. dwSelTable dd ? ; 32bit offset of handle->sel mapping table
  28. wMaxBaseDelta dw ? ; # of 64K blocks in heap * 8
  29. wSelAdjust dw ? ; (see L32FindHandleEntry, NOHPTR16 code)
  30. dwBaseSel dd ? ; base selector
  31. linBaseAddr dd ? ; base linear address of heap
  32. hCommit dd ? ; highest committed handle
  33. L32Flags dd ? ; flags field (L32F_*)
  34. L32Signature dd ? ; heap signature (L32_SIGNATURE)
  35. hHeap dd ? ; handle to heap
  36. L32HeapHeader ends
  37. L32HdrSize equ (size L32HeapHeader)
  38. ;Translation macro for fast handle->pointer conversion
  39. .386p
  40. EnumArgs macro arglist,prefix
  41. argctr = 0
  42. for arg,<arglist>
  43. argctr = argctr + 1
  44. @CatStr(prefix,%argctr) TEXTEQU <arg>
  45. endm
  46. @CatStr(prefix,<Cnt>) = argctr
  47. endm
  48. ProcessOptions macro optlist
  49. ; Initialize options to default values
  50. THOptFULL = 0
  51. THOffset = 10000h
  52. THForce32 = 0
  53. THNoValid = 0
  54. irp opt,<optlist>
  55. ifidni <opt>,<FULL>
  56. THOptFULL = 1
  57. endif
  58. ifidni <opt>,<SEPARATE>
  59. THOffset = 0
  60. endif
  61. ifidni <opt>,<FORCE32>
  62. THForce32 = 1
  63. endif
  64. ifidni <opt>,<NOVALID>
  65. THNoValid = 1
  66. endif
  67. endm
  68. THHdrPos = THOffset
  69. endm
  70. InList macro reg,reglist
  71. ifnb <reglist>
  72. IsInList INSTR <reglist>,<reg>
  73. exitm %IsInList
  74. else
  75. exitm %0
  76. endif
  77. endm
  78. ChooseSegReg macro wSel
  79. PopDS=1
  80. ifidni <wSel>,<0>
  81. sptr TEXTEQU <ds>
  82. PopDS=0
  83. else
  84. irp creg,<ds,es,fs,gs>
  85. ifidni <creg>,<wSel>
  86. sptr TEXTEQU <wSel>
  87. PopDS=0
  88. endif
  89. endm
  90. endif
  91. endm
  92. UseSegReg macro wSel
  93. if PopDS
  94. push ds
  95. mov ds,wSel
  96. sptr TEXTEQU <ds>
  97. endif
  98. ; Hack: We need to generate instructions like mov eax,[10000h]
  99. ; and MASM won't generate a 32-bit offset unless the
  100. ; segment is not assumed to be a 16-bit segment. We only
  101. ; need this for ds since we only generate these instructions
  102. ; for merged segments.
  103. ifidni sptr,<ds>
  104. assume ds:nothing
  105. endif
  106. endm
  107. RestoreSegReg macro
  108. if PopDS
  109. pop ds
  110. endif
  111. ; See note in UseSegReg.
  112. ifidni sptr,<ds>
  113. assumes ds,data
  114. endif
  115. endm
  116. ParseDestReg macro hMem
  117. ; Sigh. elseif InList(...) doesn't compile so
  118. ; NoDestReg is a workaround. Somebody please
  119. ; get rid of it if they can figure out how!
  120. NoDestReg = 1
  121. if InList(<hMem>,<ax,bx,cx,dx>)
  122. destreg32 TEXTEQU @CatStr(<e>, <hMem>)
  123. destreg16 TEXTEQU <hMem>
  124. destreg8 TEXTEQU @CatStr(@SubStr(<hMem>,1,1),<l>)
  125. NoDestReg = 0
  126. endif
  127. if ((NoDestReg NE 0) AND (InList(<hMem>,<eax,ebx,ecx,edx>) NE 0))
  128. destreg32 TEXTEQU <hMem>
  129. destreg16 TEXTEQU @SubStr(<hMem>,2,2)
  130. destreg8 TEXTEQU @CatStr(@SubStr(<hMem>,2,1),<l>)
  131. NoDestReg = 0
  132. endif
  133. if ((NoDestReg NE 0) AND (InList(<hMem>,<si,di,esi,edi>) NE 0))
  134. ; these regs only work if opts is blank
  135. destreg32 TEXTEQU <>
  136. destreg16 TEXTEQU <hMem>
  137. destreg8 TEXTEQU <>
  138. NoDestReg = 0
  139. endif
  140. if NoDestReg
  141. destreg32 TEXTEQU <eax>
  142. destreg16 TEXTEQU <ax>
  143. destreg8 TEXTEQU <al>
  144. movzx destreg32,hMem
  145. endif
  146. endm
  147. ; Table to determine if two registers overlap
  148. ??al = 00000001b
  149. ??ah = 00000001b
  150. ??ax = 00000001b
  151. ??eax = 00000001b
  152. ??bl = 00000010b
  153. ??bh = 00000010b
  154. ??bx = 00000010b
  155. ??ebx = 00000010b
  156. ??cl = 00000100b
  157. ??ch = 00000100b
  158. ??cx = 00000100b
  159. ??ecx = 00000100b
  160. ??dl = 00001000b
  161. ??dh = 00001000b
  162. ??dx = 00001000b
  163. ??edx = 00001000b
  164. ??si = 00010000b
  165. ??esi = 00010000b
  166. ??di = 00100000b
  167. ??edi = 00100000b
  168. ??Paste macro arg1:req, arg2:req
  169. exitm <arg1&arg2>
  170. endm
  171. TranslateHandle macro wSel,dwMem,wMemType,wRetType,reglist,dreg,opts
  172. local THErr
  173. local THOk
  174. local DestOk
  175. if (wMemType EQ HANDLE16)
  176. EnumArgs <dreg>,regs
  177. ProcessOptions <opts>
  178. ; choose appropriate segment register based on wSel
  179. ChooseSegReg wSel
  180. ; choose appropriate destination register based on dreg
  181. if (regsCnt EQ 1)
  182. destreg TEXTEQU <regs1>
  183. ??destreg = ??Paste(??,%regs1)
  184. else
  185. destreg TEXTEQU <eax>
  186. ??destreg = ??eax
  187. endif
  188. ??dwMem = ??Paste(??,dwMem)
  189. ; if trivial conversion (HANDLE->HANDLE) do it & exit
  190. if (wRetType EQ HANDLE16)
  191. mov destreg,dwMem
  192. exitm
  193. endif
  194. ; if wSel isn't in segment register load it in ds
  195. UseSegReg wSel
  196. if THForce32
  197. mov ecx, THHdrPos
  198. endif
  199. ;if full validation requested do it now
  200. if THOptFULL
  201. ParseDestReg <dwMem>
  202. test destreg8,3 ; make sure hMem % 4 == 0
  203. jnz THErr
  204. cmp destreg16,L32HdrSize
  205. jb THErr
  206. if THForce32
  207. cmp destreg16,word ptr sptr:[ecx].hCommit ; see if handle is below commit
  208. else
  209. cmp destreg16,word ptr sptr:[THHdrPos].hCommit ; see if handle is below commit
  210. endif
  211. ja THErr
  212. ifdifi destreg32,<bx>
  213. movzx ebx,destreg16
  214. endif
  215. if THForce32
  216. mov destreg,sptr:[ebx+ecx] ; get 32bit offset in destreg
  217. else
  218. mov destreg,sptr:[ebx+THOffset] ; get 32bit offset in destreg
  219. endif
  220. cmp destreg,10000h ; see if its free
  221. jb THErr
  222. else
  223. ; fetch the address (assume dwMem is valid)
  224. if THForce32
  225. mov destreg,sptr:[dwMem+ecx]
  226. else
  227. mov destreg,sptr:[dwMem+THOffset]
  228. endif
  229. endif
  230. ifdef DEBUG
  231. ife THNoValid
  232. cmp destreg,10000h ; see if its free
  233. jae DestOk
  234. int 3
  235. endif
  236. DestOk:
  237. endif
  238. ; if HANDLE16->PTR16 compute the selector
  239. if (wRetType EQ PTR16)
  240. if InList(<bx>,<reglist>) OR InList(<ebx>,<reglist>)
  241. push ebx
  242. endif
  243. if THForce32
  244. mov ebx,sptr:[ecx].dwSelTable
  245. else
  246. mov ebx,sptr:[THHdrPos].dwSelTable
  247. endif
  248. ; determine which registers to use...
  249. if (regsCnt EQ 0)
  250. ; eax,dx:ax = PTR16
  251. mov edx,eax
  252. shr edx,15
  253. and ax,7fffh
  254. mov dx,sptr:[ebx+edx*2]
  255. rol eax,16
  256. mov ax,dx
  257. rol eax,16
  258. elseif (regsCnt EQ 1)
  259. ; regs1 = PTR16
  260. destreg16 TEXTEQU @SubStr(dreg,2)
  261. if InList(<dx>,<reglist>) OR InList(<edx>,<reglist>)
  262. push edx
  263. endif
  264. mov edx,destreg
  265. shr edx,15
  266. and destreg16,7fffh
  267. mov dx,sptr:[ebx+edx*2]
  268. rol destreg,16
  269. mov destreg16,dx
  270. rol destreg,16
  271. if InList(<dx>,<reglist>) OR InList(<edx>,<reglist>)
  272. pop edx
  273. endif
  274. elseif (regsCnt EQ 2)
  275. ; regs1:regs2 = PTR16
  276. if InList(<dx>,<reglist>) OR InList(<edx>,<reglist>)
  277. push edx
  278. endif
  279. mov edx,eax
  280. shr edx,15
  281. mov regs1,sptr:[ebx+edx*2]
  282. ifdifi <ax>,regs2
  283. mov regs2,ax
  284. endif
  285. and regs2,7fffh
  286. if InList(<dx>,<reglist>) OR InList(<edx>,<reglist>)
  287. pop edx
  288. endif
  289. else
  290. .err Too many destination regs passed to TranslateHandle
  291. endif
  292. if InList(<bx>,<reglist>) OR InList(<ebx>,<reglist>)
  293. pop ebx
  294. endif
  295. endif
  296. if THOptFULL
  297. jmp THOk
  298. THErr:
  299. ; determine which registers to use...
  300. if (regsCnt EQ 0)
  301. ; eax,dx:ax = PTR16
  302. xor eax,eax
  303. xor edx,edx
  304. elseif (regsCnt EQ 1)
  305. ; regs1 = PTR16
  306. xor regs1,regs1
  307. elseif (regsCnt EQ 2)
  308. ; regs1:regs2 = PTR16
  309. xor regs2,regs2
  310. mov regs1,regs2
  311. else
  312. .err Too many destination regs passed to TranslateHandle
  313. endif
  314. THOk:
  315. endif
  316. ; if wSel wasn't in segment register restore ds
  317. RestoreSegReg
  318. elseif ((wMemType EQ PTR32) AND (wRetType EQ PTR16))
  319. ; input: eax = 32-bit offset
  320. ; output: eax = 16:16 ptr (ebx,ecx,edx trashed)
  321. mov ebx,THHdrPos
  322. mov edx,eax
  323. shr edx,15
  324. mov ecx,sptr:[ebx].dwSelTable
  325. and eax,7fffh
  326. rol eax,16
  327. mov ax,sptr:[ecx+edx*2]
  328. rol eax,16
  329. else
  330. ifnb <reglist>
  331. Save <reglist>
  332. endif
  333. int 3
  334. cCall Local32Translate,<wSel,dwMem,wMemType,wRetType>
  335. ifnb <dreg>
  336. mov dreg,eax
  337. endif
  338. endif
  339. endm
  340. ;Validation macro for fast 32bit handle validation
  341. ValidHandle32 macro wSel,hMem,opts
  342. local VH32_Err
  343. local VH32_End
  344. ifb <opts>
  345. test hMem,2 ; ZF=0 => 32-bit, ZF=1 => 16-bit
  346. else
  347. ParseDestReg <hMem>
  348. ProcessOptions <opts>
  349. ChooseSegReg wSel
  350. UseSegReg wSel
  351. if THForce32
  352. mov ecx, THHdrPos
  353. endif
  354. test destreg8,3 ; make sure hMem % 4 = 0
  355. jnz VH32_Err ; if not we know it isn't valid
  356. cmp destreg16,L32HdrSize ; see if handle points in header
  357. jb VH32_Err ;
  358. if THForce32
  359. cmp destreg32,sptr:[ecx].hCommit ; see if handle is
  360. else
  361. cmp destreg32,sptr:[THHdrPos].hCommit ; see if handle is
  362. endif
  363. ; below commit line
  364. ja VH32_Err
  365. if THForce32
  366. mov destreg32,sptr:[destreg32+ecx]
  367. else
  368. mov destreg32,sptr:[destreg32+THHdrPos]
  369. endif
  370. cmp destreg32,10000h ; see if its free
  371. jae VH32_End ; if not we're happy
  372. VH32_Err:
  373. xor ax,ax ; set zero flag
  374. VH32_End:
  375. RestoreSegReg
  376. endif
  377. ; cCall Local32ValidHandle,<wSel,hMem>
  378. endm
  379. ifndef ?INHEAP32
  380. .286p
  381. externFP Local32Init
  382. externFP Local32Alloc
  383. externFP Local32ReAlloc
  384. externFP Local32Size
  385. externFP Local32Translate
  386. externFP Local32ValidHandle
  387. externFP Local32Free
  388. externFP Local32GetSel
  389. endif
  390. if 0
  391. ;*/
  392. /* Flags for Local32Init */
  393. #define LINIT_MAX16HEAP 1
  394. #define LINIT_TILEHEAP 2
  395. #define LINIT_EMS16HEAP 4
  396. /* Flags for Local32Alloc */
  397. #define LMEM32_64K 1
  398. #define LMEM32_ZEROINIT 2
  399. /* Address types */
  400. #define NOHPTR16 (WORD) (-2)
  401. #define NOHPTR32 (WORD) (-1)
  402. #define HANDLE16 0
  403. #define PTR16 1
  404. #define PTR32 2
  405. DWORD FAR PASCAL Local32Init(WORD wSel, DWORD dwcbInit, DWORD dwcbMax, DWORD dwFlags);
  406. DWORD FAR PASCAL Local32Alloc(DWORD linHdr, DWORD dwcbRequest, WORD wType, DWORD dwFlags);
  407. DWORD FAR PASCAL Local32ReAlloc(DWORD linHdr, DWORD dwMem, WORD wType, DWORD dwcbNew, DWORD dwFlags);
  408. DWORD FAR PASCAL Local32Size(DWORD linHdr, DWORD dwMem, WORD wType);
  409. DWORD FAR PASCAL Local32Translate(DWORD linHdr, DWORD dwMem, WORD wMemType,
  410. WORD wRetType);
  411. BOOL FAR PASCAL Local32ValidHandle(DWORD linHdr, HANDLE hMem);
  412. BOOL FAR PASCAL Local32Free(DWORD linHdr, DWORD dwMem, WORD wMemType);
  413. WORD FAR PASCAL Local32GetSel(DWORD linHdr);
  414. #define TranslateHandle(a,b,c,d) Local32Translate((a),(b),(c),(d))
  415. #ifndef _flat
  416. #define _flat __based32(__segname("_DATA"))
  417. #endif
  418. #define HTOFLAT(p,h) \
  419. { \
  420. DWORD _flat* _tp_ = (DWORD _flat*)((h)+0x10000); \
  421. (p) = ((void _flat*)*_tp_); \
  422. }
  423. ;/*
  424. endif
  425. ;*/