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.

880 lines
29 KiB

  1. TITLE LDHEADER - Load Exe Header procedure
  2. .xlist
  3. include gpfix.inc
  4. include kernel.inc
  5. include newexe.inc
  6. .list
  7. externA __AHINCR
  8. externFP IGlobalAlloc
  9. externFP IGlobalFree
  10. externFP FarSetOwner
  11. externFP Int21Handler
  12. externFP FarMyUpper
  13. externFP IsBadStringPtr
  14. externFP _hread
  15. DataBegin
  16. externB fBooting
  17. externB szBozo
  18. externW winVer
  19. externD pSErrProc
  20. DataEnd
  21. externFP IGlobalLock
  22. externFP IGlobalUnLock
  23. sBegin NRESCODE
  24. assumes CS,NRESCODE
  25. externNP NResGetPureName
  26. ;-----------------------------------------------------------------------;
  27. ; LoadExeHeader ;
  28. ; ;
  29. ; Routine to read an EXE header and check for a new format EXE file. ;
  30. ; Returns NULL if not a new format EXE. Otherwise reads the resident ;
  31. ; portion of the new EXE header into allocated storage and returns ;
  32. ; the segment address of the new EXE header. ;
  33. ; ;
  34. ; Arguments: ;
  35. ; parmW fh ;
  36. ; parmW isfh ;
  37. ; parmD pfilename ;
  38. ; ;
  39. ; Returns: ;
  40. ; AX = segment of exe header ;
  41. ; DL = ne_exetyp ;
  42. ; DH = ne_flagsothers ;
  43. ; ;
  44. ; Error Returns: ;
  45. ;LME_MEM = 0 ; Out of memory ;
  46. ;LME_VERS = 10 ; Wrong windows version ;
  47. ;LME_INVEXE = 11 ; Invalid exe ;
  48. ;LME_OS2 = 12 ; OS/2 app ;
  49. ;LME_DOS4 = 13 ; DOS 4 app ;
  50. ;LME_EXETYPE = 14 ; unknown exe type ;
  51. ;LME_COMP = 19 ; Compressed EXE file ;
  52. ;LME_PE = 21 ; Portable EXE ;
  53. ; ;
  54. ; Registers Preserved: ;
  55. ; DI,SI ;
  56. ; ;
  57. ; Registers Destroyed: ;
  58. ; AX,BX,CX,DS,ES ;
  59. ; Calls: ;
  60. ; ;
  61. ; History: ;
  62. ; ;
  63. ; Thu Mar 19, 1987 08:35:32p -by- David N. Weise [davidw] ;
  64. ; Added this nifty comment block. ;
  65. ;-----------------------------------------------------------------------;
  66. cProc LoadExeHeader,<PUBLIC,FAR>,<si,di>
  67. parmW fh
  68. parmW isfh
  69. parmD pfilename
  70. localW pnewexe
  71. localW exetype
  72. localW nchars
  73. localW pseg
  74. localW psegsrc
  75. localW hBlock
  76. localW pBlock
  77. localW NEFileOffset
  78. localD PreloadLen
  79. localW NEBase
  80. localW exeflags
  81. localW expver
  82. localW saveSP
  83. localB fast_fail ; 1 if we can't use fastload block
  84. localV hdrbuf,<SIZE EXE_HDR>
  85. .errnz SIZE EXE_HDR - SIZE NEW_EXE
  86. cBegin
  87. xor ax,ax
  88. mov pseg,ax
  89. mov hBlock, ax
  90. mov fast_fail, al
  91. cmp SEG_pfilename,ax
  92. je re0
  93. IF KDEBUG ; LoadExeHeader is internal
  94. cCall IsBadStringPtr, <pfilename, 128> ; so we assume file pointer is OK
  95. or ax, ax
  96. jnz refailj
  97. ENDIF
  98. lds si,pfilename
  99. mov al,ds:[si].opLen
  100. inc ax ; include null byte
  101. re0:
  102. mov nchars,ax
  103. mov bx,fh ; No, seek backwards over what
  104. cmp isfh,bx
  105. je refile
  106. mov ds,bx
  107. xor si,si
  108. jmp remem
  109. refile: ; Here to load from a file
  110. push ss ; DS:SI points to I/O buffer
  111. pop ds
  112. lea si,hdrbuf ; Read beginning of file
  113. mov dx,si
  114. mov cx,SIZE EXE_HDR
  115. mov bx,fh
  116. mov ah,3Fh
  117. DOSFCALL
  118. jnc @F
  119. refailj:
  120. jmps refail
  121. @@:
  122. cmp ax,cx ; Old EXE file, look for offset
  123. jb refailj ; to new exe header
  124. cmp ds:[si].e_magic,EMAGIC ; Check for old exe file
  125. je @F
  126. cmp ds:[si], 'ZS' ; Is it compressed?
  127. jne refail
  128. cmp ds:[si][2],'DD'
  129. jne refail
  130. cmp ds:[si][4],0F088h
  131. jne refail
  132. cmp ds:[si][6],03327h
  133. jne refail
  134. mov ax, LME_COMP ; Compressed EXE
  135. jmp reexit
  136. @@:
  137. mov ax,ds:[si].e_lfanew.hi
  138. mov dx,ds:[si].e_lfanew.lo
  139. mov pnewexe,dx ; To check for bound OS/2 apps.
  140. or ax,dx
  141. jz refail ; Fail if not there.
  142. mov cx,ds:[si].e_lfanew.hi
  143. mov dx,ds:[si].e_lfanew.lo
  144. mov bx, fh
  145. mov ax,4200h
  146. DOSFCALL
  147. jc refail
  148. mov cx,SIZE NEW_EXE
  149. mov dx,si
  150. mov ah,3Fh
  151. DOSFCALL
  152. jc refail
  153. cmp ax,cx
  154. jne refail
  155. cmp ds:[si].ne_magic,NEMAGIC ; Did we get a valid new EXE header?
  156. je remem
  157. cmp ds:[si].ne_magic,PEMAGIC ; Did we find a Portable EXE (WIN32)
  158. jne refail
  159. mov ax, LME_PE
  160. jmps rej
  161. refail:
  162. mov ax, LME_INVEXE ; invalid NEW EXE file format
  163. rej: jmp reexit
  164. remem:
  165. mov psegsrc,bx ; bx has either fh or seg address
  166. mov di,ds:[si].ne_enttab ; Compute size of resident new header
  167. add di,ds:[si].ne_cbenttab
  168. add di, 6 ; null entry space (bug #8414)
  169. mov cx, ds:[si].ne_cbenttab
  170. mov bx, ds:[si].ne_cmovent
  171. shl bx, 1
  172. sub cx, bx
  173. shl bx, 1
  174. sub cx, bx ; Number of bytes not moveable entries
  175. shl cx, 1 ; Allow triple these bytes
  176. add di, cx
  177. mov cx,ds:[si].ne_cseg ; + 3 * #segments
  178. ; Reserve space for ns_handle field in segment table
  179. shl cx,1
  180. add di,cx
  181. .errnz 10 - SIZE NEW_SEG1
  182. ; Reserve space for file info block at end
  183. add di,nchars ; + size of file info block
  184. xor ax,ax ; Allocate a fixed block for header
  185. mov bx,GA_ZEROINIT or GA_MOVEABLE
  186. cCall IGlobalAlloc,<bx,ax,di> ; that isn't code or data.
  187. or ax,ax
  188. jnz @F
  189. jmps badformat
  190. @@:
  191. push ax
  192. cCall IGlobalLock,<ax>
  193. pop ax
  194. push dx
  195. cCall IGlobalUnlock,<ax>
  196. pop ax
  197. sub di,nchars
  198. mov pseg,ax
  199. mov es,ax ; ES:0 -> new header location
  200. cld ; DS:SI -> old header
  201. mov bx,psegsrc
  202. cmp isfh,bx ; Is header in memory?
  203. jne remem1 ; Yes, continue
  204. mov ax,ds:[si].ne_enttab ; No, read into high end
  205. add ax,ds:[si].ne_cbenttab ; of allocated block
  206. sub di,ax
  207. mov cx,SIZE NEW_EXE ; Copy part read so far
  208. sub ax,cx
  209. rep movsb
  210. mov cx,ax
  211. smov ds,es ; Read rest of header from file
  212. mov dx,di
  213. mov ah,3fh
  214. DOSFCALL
  215. mov bx,ax
  216. jc refail1
  217. lea si,[di-SIZE NEW_EXE] ; DS:SI -> old header
  218. cmp bx,cx
  219. je remem1
  220. badformat:
  221. mov ax, LME_INVEXE ; don't change flags
  222. refail1: ; Here if error reading header
  223. push ax
  224. SetKernelDSNRes ; DS may be = pseg, prevent
  225. cCall IGlobalFree,<pseg> ; GP faults in pmode.
  226. pop ax
  227. jmp reexit
  228. remem1:
  229. UnsetKernelDS
  230. test ds:[si].ne_flags,NEIERR ; Errors in EXE image?
  231. jnz badformat ; Yes, fail
  232. cmp ds:[si].ne_ver,4 ; No, built by LINK4 or above?
  233. jl badformat ; No, error
  234. mov bx,ds:[si].ne_flags ; Make local copies of ne_flags &
  235. and bl,NOT NEPROT ; ne_expver which can be modified
  236. mov exeflags,bx ; (can't change ROM exe headers).
  237. mov bx,ds:[si].ne_expver
  238. mov expver,bx
  239. mov bx,word ptr ds:[si].ne_exetyp ; get exetyp and flagsothers
  240. mov exetype,bx
  241. cmp bl,NE_UNKNOWN
  242. jz windows_exe
  243. cmp bl,NE_WINDOWS ; is it a Windows exe?
  244. jz windows_exe
  245. mov ax,LME_OS2
  246. cmp bl,NE_OS2 ; is it an OS|2 exe?
  247. jnz not_os2
  248. test bh,NEINPROT ; can it be run under Windows?
  249. jz @F
  250. and exeflags,NOT NEAPPLOADER
  251. or exeflags,NEPROT
  252. mov expver,0300h
  253. jmps windows_exe
  254. @@:
  255. cmp pnewexe,0800h ; is it a bound
  256. jb refail1
  257. jmp badformat
  258. not_os2:
  259. inc ax ; AX = 13 - LME_DOS4
  260. cmp bl,NE_DOS4 ; is it a DOS 4 exe?
  261. jz refail1
  262. inc ax ; AX = 14 - LME_EXETYPE
  263. jmp refail1
  264. mgxlib DB 'MGXLIB'
  265. windows_exe:
  266. mov NEBase, si ; Offset of Source header
  267. xor di,di ; ES:DI -> new header location
  268. mov cx,SIZE NEW_EXE ; Copy fixed portion of header
  269. cld
  270. rep movsb
  271. mov ax,exeflags
  272. if ROM
  273. and al,NOT NEMODINROM ; Assume module not in ROM
  274. endif
  275. mov es:[ne_flags],ax
  276. mov ax,expver
  277. mov es:[ne_expver],ax
  278. mov si, NEBase
  279. add si, es:[ne_segtab] ; Real location of segment table
  280. mov cx,es:[ne_cseg] ; Copy segment table, adding
  281. mov es:[ne_segtab],di
  282. jcxz recopysegx
  283. recopyseg:
  284. if ROM
  285. ; If this is a module from ROM, the ROM ns_sector field contains the selector
  286. ; pointing to the ROM segment--this will become the RAM ns_handle value.
  287. .errnz ns_sector
  288. mov dx,ds:[si].ns_flags ; do while si->start of seg info
  289. lodsw ; ns_sector
  290. xor bx,bx ; ns_handle if not in ROM
  291. test dh,(NSINROM SHR 8)
  292. jz store_sector
  293. mov bx,ax ; will be ns_handle
  294. store_sector:
  295. stosw ; ns_sector
  296. else
  297. movsw ; ns_sector
  298. endif
  299. movsw ; ns_cbseg
  300. lodsw ; ns_flags
  301. .errnz 4 - ns_flags
  302. if ROM
  303. mov dl,al
  304. and dl,NSLOADED
  305. and ax,not (NS286DOS XOR (NSGETHIGH OR NSINROM))
  306. else
  307. and ax,not (NS286DOS XOR NSGETHIGH) ; Clear 286DOS bits
  308. endif
  309. ; record in the segment flags if this module is a process, this is for EMS
  310. test ax,NSTYPE ; NSCODE
  311. jnz not_code
  312. or ax,NSWINCODE
  313. not_code:
  314. or ax,NSNOTP
  315. test es:[ne_flags],NSNOTP
  316. jnz not_a_process
  317. xor ax,NSNOTP
  318. or ax,NSMOVE
  319. not_a_process:
  320. if ROM
  321. test ah,(NSINROM SHR 8) ; if sector is in ROM, preserve
  322. jz @f ; NSLOADED flag from ROM builder
  323. or al,dl
  324. @@:
  325. endif
  326. stosw ; ns_flags
  327. movsw ; ns_minalloc
  328. .errnz 8 - SIZE NEW_SEG
  329. if ROM
  330. mov ax,bx ; bx set to selector or 0 above
  331. else
  332. xor ax,ax
  333. endif
  334. stosw ; one word for ns_handle field
  335. .errnz 10 - SIZE NEW_SEG1
  336. loop recopyseg
  337. recopysegx:
  338. test es:[ne_flagsothers], NEGANGLOAD
  339. jz no_gang_loadj
  340. mov bx, fh
  341. cmp bx, isfh
  342. jne no_gang_loadj
  343. mov ax, es:[ne_gang_start]
  344. or ax, ax
  345. jz no_gang_loadj
  346. mov NEFileOffset, ax ; file offset of gang load area
  347. mov ax, es:[ne_gang_length]
  348. or ax, ax
  349. jz no_gang_loadj
  350. mov cx, es:[ne_align]
  351. xor dx, dx
  352. gl_len: ; find length of Gang Load area
  353. shl ax, 1
  354. adc dx, dx
  355. loop gl_len
  356. cmp dx, 10h ; Greater than 1Mb, forget it!!
  357. jb alloc_it ; PS: NEVER go bigger than 1Mb
  358. no_gang_loadj:
  359. jmp no_gang_load ; since LongPtrAdd is limited...
  360. alloc_it:
  361. mov word ptr PreloadLen[0], ax
  362. mov word ptr PreloadLen[2], dx
  363. mov ch, GA_DISCARDABLE
  364. mov cl, GA_MOVEABLE+GA_NODISCARD+GA_NOCOMPACT
  365. push es
  366. cCall IGlobalAlloc,<cx,dx,ax> ; Allocate this much memory
  367. pop es
  368. or ax, ax
  369. jz no_gang_loadj
  370. mov hBlock, ax ; Have memory to read file into
  371. push es
  372. cCall IGlobalLock,<ax>
  373. pop es
  374. mov pBlock, dx
  375. mov dx, NEFileOffset
  376. mov cx, es:[ne_align]
  377. xor bx, bx
  378. gl_pos: ; find pos of Gang Load start
  379. shl dx, 1
  380. adc bx, bx
  381. loop gl_pos
  382. mov cx, bx
  383. mov bx, fh
  384. mov ax,4200h
  385. DOSFCALL ; Seek to new exe header
  386. jc refailgang
  387. mov ax, pBlock
  388. xor bx, bx
  389. farptr memadr,ax,bx
  390. cCall _hread, <fh, memadr, PreloadLen>
  391. cmp dx, word ptr PreloadLen[2]
  392. jnz refailgang
  393. cmp ax, word ptr PreloadLen[0]
  394. jz no_gang_load ; We're OK now
  395. ; push ds
  396. ; xor dx, dx
  397. ; mov ax, pBlock
  398. ; push si
  399. ; push di
  400. ; mov si, word ptr PreloadLen[2]
  401. ; mov di, word ptr PreloadLen[0]
  402. ;read_file:
  403. ; mov cx, 08000h ; Must be factor 64k DON'T CHANGE THIS
  404. ; or si, si
  405. ; jnz big_read
  406. ; cmp cx, di
  407. ; jbe big_read
  408. ; mov cx, di ; all that's left
  409. ; jcxz done_read ; Nothing left, quit.
  410. ;big_read:
  411. ; mov ds, ax
  412. ; mov ah, 3Fh
  413. ; DOSFCALL ; Read chunk from file
  414. ; jc refailgang
  415. ; cmp ax, cx ; All we asked for?
  416. ; jne refailgang ; no, file corrupted
  417. ; sub di, cx
  418. ; sbb si, 0
  419. ; mov ax, ds
  420. ; add dx, cx ; On to next block
  421. ; jnc read_file
  422. ; add ax, __AHINCR
  423. ; jmps read_file
  424. ;
  425. refailgang:
  426. ; pop di
  427. ; pop si
  428. ; pop ds
  429. cCall IGlobalUnlock,<hBlock>
  430. cCall IGlobalFree,<hBlock>
  431. mov hBlock, 0
  432. jmps no_gang_load
  433. BadExeHeader: ; GP fault handler!!!
  434. mov sp, saveSP
  435. ; fix_fault_stack
  436. jmp refail1 ; corrupt exe header (or our bug)
  437. ;done_read:
  438. ; pop di
  439. ; pop si
  440. ; pop ds
  441. no_gang_load:
  442. mov saveSP, sp
  443. beg_fault_trap BadExeHeader
  444. mov cx,es:[ne_restab] ; Copy resource table
  445. sub cx,es:[ne_rsrctab]
  446. mov si, NEBase ; Get correct source address
  447. add si, es:[ne_rsrctab]
  448. mov es:[ne_rsrctab],di
  449. rep movsb
  450. rerestab:
  451. mov cx,es:[ne_modtab] ; Copy resident name table
  452. sub cx,es:[ne_restab]
  453. mov es:[ne_restab],di
  454. rep movsb
  455. push di
  456. mov di, es:[ne_restab] ; Make the module name Upper Case
  457. xor ch, ch
  458. mov cl, es:[di]
  459. inc di
  460. uppercaseit:
  461. mov al, es:[di]
  462. call farMyUpper
  463. stosb
  464. loop uppercaseit
  465. pop di
  466. mov cx,es:[ne_imptab] ; Copy module xref table
  467. sub cx,es:[ne_modtab]
  468. mov es:[ne_modtab],di
  469. rep movsb
  470. mov es:[ne_psegrefbytes],di ; Insert segment reference byte table
  471. mov es:[ne_pretthunks],di ; Setup return thunks
  472. mov cx,es:[ne_enttab] ; Copy imported name table
  473. sub cx,es:[ne_imptab]
  474. mov es:[ne_imptab],di
  475. jcxz reenttab
  476. rep movsb
  477. reenttab:
  478. mov es:[ne_enttab],di
  479. ; Scan current entry table
  480. xor ax, ax ; First entry in block
  481. mov bx, di ; Pointer to info for this block
  482. stosw ; Starts at 0
  483. stosw ; Ends at 0
  484. stosw ; And is not even here!
  485. copy_next_block:
  486. lodsw ; Get # entries and type
  487. xor cx, cx
  488. mov cl, al
  489. jcxz copy_ent_done
  490. mov al, ah
  491. cmp al, ENT_UNUSED
  492. jne copy_used_block
  493. mov ax, es:[bx+2] ; Last entry in current block
  494. cmp ax, es:[bx] ; No current block?
  495. jne end_used_block
  496. add es:[bx], cx
  497. add es:[bx+2], cx
  498. jmps copy_next_block
  499. end_used_block:
  500. mov es:[bx+4], di ; Pointer to next block
  501. mov bx, di
  502. add ax, cx ; Skip unused entries
  503. stosw ; First in new block
  504. stosw ; Last in new block
  505. xor ax, ax
  506. stosw ; End of list
  507. jmps copy_next_block
  508. copy_used_block:
  509. add es:[bx+2], cx ; Add entries in this block
  510. cmp al, ENT_MOVEABLE
  511. je copy_moveable_block
  512. ; absolutes end up here as well
  513. copy_fixed_block:
  514. stosb ; Segno
  515. movsb ; Flag byte
  516. stosb ; segno again to match structure
  517. movsw ; Offset
  518. loop copy_fixed_block
  519. jmps copy_next_block
  520. copy_moveable_block:
  521. stosb ; ENT_MOVEABLE
  522. movsb ; Flag byte
  523. add si, 2 ; Toss int 3Fh
  524. movsb ; Copy segment #
  525. movsw ; and offset
  526. loop copy_moveable_block
  527. jmps copy_next_block
  528. copy_ent_done:
  529. xor bx,bx
  530. cmp es:[bx].ne_ver,5 ; Produced by version 5.0 LINK4
  531. jae remem2a ; or above?
  532. mov es:[bx].ne_expver,bx ; No, clear uninitialized fields
  533. mov es:[bx].ne_swaparea,bx
  534. ; TEMPORARY BEGIN
  535. push ax
  536. push cx
  537. push di
  538. push si
  539. mov si,es:[bx].ne_rsrctab
  540. cmp si,es:[bx].ne_restab
  541. jz prdone
  542. mov di,es:[si].rs_align
  543. add si,SIZE new_rsrc
  544. prtype:
  545. cmp es:[si].rt_id,0
  546. je prdone
  547. mov cx,es:[si].rt_nres
  548. add si,SIZE rsrc_typeinfo
  549. prname:
  550. push cx
  551. mov ax,es:[si].rn_flags
  552. test ah,0F0h ; Is old discard field set?
  553. jz @F
  554. or ax,RNDISCARD ; Yes, convert to bit
  555. @@:
  556. and ax,not RNUNUSED ; Clear unused bits in 4.0 LINK files
  557. mov es:[si].rn_flags,ax
  558. pop cx
  559. add si,SIZE rsrc_nameinfo
  560. loop prname
  561. jmp prtype
  562. prdone: pop si
  563. pop di
  564. pop cx
  565. pop ax
  566. ; TEMPORARY END
  567. FixFlags: ; label for debugging
  568. public FixFlags, leh_slow
  569. public leh_code, leh_patchnext, leh_code_fixed, leh_patchdone, leh_data
  570. remem2a: ; (bx == 0)
  571. mov es:[bx].ne_usage,bx
  572. mov es:[bx].ne_pnextexe,bx
  573. mov es:[bx].ne_pfileinfo,bx
  574. cmp es:[bx].ne_align,bx
  575. jne @F
  576. mov es:[bx].ne_align,NSALIGN
  577. @@:
  578. mov cx,nchars
  579. jcxz @F
  580. mov es:[bx].ne_pfileinfo,di
  581. lds si,pfilename
  582. rep movsb
  583. @@: ; Save pointer to seginfo record
  584. mov bx,es:[bx].ne_autodata ; of automatic data segment
  585. or bx,bx
  586. jz @F
  587. dec bx
  588. shl bx,1
  589. mov cx,bx
  590. shl bx,1
  591. shl bx,1
  592. add bx,cx
  593. .errnz 10 - SIZE NEW_SEG1
  594. add bx,es:[ne_segtab]
  595. @@:
  596. mov es:[ne_pautodata],bx
  597. SetKernelDSNRes
  598. ; Scan seg table, marking nonautomatic DATA segments fixed, preload
  599. mov ax,es:[ne_expver] ; Default expected version to
  600. or ax,ax
  601. jnz @F
  602. mov ax,201h
  603. mov es:[ne_expver],ax ; 2.01
  604. @@:
  605. cmp ax,winVer
  606. jbe @F
  607. cCall IGlobalFree,<pseg>
  608. mov ax, LME_VERS
  609. jmp reexit
  610. @@:
  611. mov bx,es:[ne_segtab]
  612. xor cx,cx
  613. sub bx,SIZE NEW_SEG1
  614. jmps leh_patchnext
  615. leh_test_preload:
  616. test byte ptr es:[bx].ns_flags, NSPRELOAD
  617. jnz leh_patchnext
  618. or byte ptr es:[bx].ns_flags, NSPRELOAD
  619. cmp es:[bx].ns_sector, 0 ; don't whine about empty segments
  620. je leh_patchnext
  621. krDebugOut DEB_WARN, "Segment #CX of %ES0 must be preload"
  622. mov fast_fail, 1
  623. leh_patchnext:
  624. add bx,SIZE NEW_SEG1
  625. inc cx
  626. cmp cx,es:[ne_cseg]
  627. ja leh_patchdone
  628. test byte ptr es:[bx].ns_flags,NSDATA ; Is it a code segment?
  629. jz leh_code ; Yes, next segment
  630. .errnz NSCODE
  631. leh_data: ; Data must be non-discardable, preload
  632. if KDEBUG
  633. test es:[bx].ns_flags, NSDISCARD
  634. jz @F
  635. krDebugOut DEB_WARN, "Data Segment #CX of %ES0 can't be discardable"
  636. @@:
  637. endif
  638. and es:[bx].ns_flags,not NSDISCARD ; Data segments not discardable
  639. jmps leh_test_preload
  640. leh_code:
  641. test byte ptr es:[bx].ns_flags,NSMOVE; Moveable code?
  642. jz leh_code_fixed
  643. ; moveable code must be discardable, or must be preload
  644. if KDEBUG
  645. test es:[ne_flags],NENOTP ; for 3.0 libraries can't have
  646. jz @F ; moveable only code
  647. cmp fBooting,0 ; If not booting
  648. jne @F
  649. test es:[bx].ns_flags,NSDISCARD
  650. jnz @F
  651. krDebugOut DEB_WARN, "Segment #CX of %ES0 was discardable under Win 3.0"
  652. @@:
  653. endif
  654. test es:[bx].ns_flags,NSDISCARD ; Is it discardable?
  655. jnz leh_patchnext
  656. jmp leh_test_preload
  657. leh_code_fixed: ; fixed code must be preload
  658. cmp fBooting,0 ; If not booting
  659. jne leh_patchnext
  660. jmp leh_test_preload
  661. leh_patchdone:
  662. mov bx,word ptr es:[ne_csip+2] ; Is there a start segment?
  663. or bx,bx
  664. jz @F ; No, continue
  665. dec bx
  666. shl bx,1
  667. mov si,bx
  668. shl si,1
  669. shl si,1
  670. add si,bx
  671. .errnz 10 - SIZE NEW_SEG1
  672. add si,es:[ne_segtab] ; Mark start segment as preload
  673. if kdebug
  674. test byte ptr es:[si].ns_flags,NSPRELOAD
  675. jnz scs_pre
  676. krDebugOut DEB_WARN, "Starting Code Segment of %ES0 must be preload"
  677. mov fast_fail, 1
  678. scs_pre:
  679. endif
  680. or byte ptr es:[si].ns_flags,NSPRELOAD
  681. cmp es:[ne_autodata],0 ; Is there a data segment?
  682. je @F
  683. or es:[si].ns_flags,NSUSESDATA ; Yes, then it needs it
  684. mov si,es:[ne_pautodata]
  685. if kdebug
  686. test byte ptr es:[si].ns_flags,NSPRELOAD
  687. jnz sds_pre
  688. cmp es:[bx].ns_sector, 0 ; don't whine about empty segments
  689. je sds_pre
  690. krDebugOut DEB_WARN, "Default Data Segment of %ES0 must be preload"
  691. mov fast_fail, 1
  692. sds_pre:
  693. endif
  694. or byte ptr es:[si].ns_flags,NSPRELOAD ; Mark DS as preload
  695. @@:
  696. test es:[ne_flags],NENOTP ; No stack if not a process
  697. jnz @F
  698. cmp es:[ne_stack],4096+1024
  699. jae @F
  700. mov es:[ne_stack],4096+1024 ; 4k stack is not enough (raor)
  701. @@:
  702. mov cx, es:[ne_heap] ; If the module wants a heap
  703. jcxz leh_heapadjdone ; make sure it's big enough
  704. mov ax, 800h ; ; Environment variables have
  705. cmp cx, ax ; grown, so we need more heap
  706. jae leh_heapadjdone ; space for apps so we use 800h
  707. mov dx, ax
  708. test es:[ne_flags],NENOTP
  709. jnz @F
  710. add dx, es:[ne_stack]
  711. jc leh_heapadjmin
  712. @@:
  713. mov bx,es:[ne_autodata] ; set if no autodata segment
  714. or bx,bx ; we have to do this here
  715. jz leh_heapadjset ; because for certain dlls
  716. dec bx ; pautodata is not initialized
  717. shl bx,1
  718. mov cx,bx
  719. shl bx,1
  720. shl bx,1
  721. add bx,cx
  722. add bx,es:[ne_segtab]
  723. add dx, es:[bx].ns_minalloc
  724. jnc leh_heapadjset
  725. leh_heapadjmin:
  726. ; if 800h is too big fallback to
  727. if KDEBUG ; what win9x code used as minimum
  728. mov ax, 100h + SIZE LocalStats ; heap size 100h
  729. else
  730. mov ax, 100h
  731. endif
  732. mov cx, es:[ne_heap]
  733. cmp cx, ax
  734. jae leh_heapadjdone
  735. leh_heapadjset:
  736. mov es:[ne_heap], ax
  737. leh_heapadjdone:
  738. mov ax,es ; Set owner to be itself
  739. cCall FarSetOwner,<ax,ax>
  740. mov dx,exetype
  741. test dh,NEINFONT ; save the font bit in exehdr
  742. jz reexit ; somewhere
  743. or es:[ne_flags],NEWINPROT
  744. end_fault_trap
  745. reexit:
  746. ; cmp ax, 20h ; translate error messages for ret
  747. ; jae @F
  748. ; mov bx, ax
  749. ; xor ax, ax
  750. ; cmp bl, 1 ; bx is 0, 1, 2, 19, other
  751. ; jz @F ; 1 -> 0 (out of memory)
  752. ; mov al, 11
  753. ; jb @F ; 0 -> 11 (invalid format)
  754. ; cmp bl, 3 ;
  755. ; mov al, 10
  756. ; jb @F ; 2 -> 10 (windows version)
  757. ; mov al, 19 ; 3 -> 19 (compressed EXE)
  758. ; jz @F ; others left alone
  759. ; mov al, bl
  760. ;@@:
  761. push dx
  762. mov bx, hBlock
  763. or bx, bx
  764. je noUnlock ; No block to unlock
  765. push ax
  766. cCall IGlobalUnlock,<bx>
  767. push ss
  768. pop ds ; might be freeing DS
  769. cmp fast_fail, 1 ; is fastload area invalid?
  770. jne @F
  771. leh_slow:
  772. krDebugOut DEB_WARN, "FastLoad area ignored due to incorrect segment flags"
  773. cCall IGlobalFree,<hBlock> ; yes - free it, force slow-load
  774. mov hBlock, 0
  775. @@:
  776. pop ax
  777. cmp ax, LME_MAXERR
  778. jae noFree ; Success, return memory block in bx
  779. push ax
  780. cCall IGlobalFree,<hBlock>
  781. pop ax
  782. noFree:
  783. mov cx, NEFileOffset ; Return offset of header in CX
  784. mov bx, hBlock
  785. noUnlock:
  786. pop dx
  787. UnSetKernelDS
  788. cEnd
  789. sEnd NRESCODE
  790. end