1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
|
TITLE LDUTIL - Loader support procedures
.xlist
include kernel.inc
include newexe.inc
include tdb.inc
include protect.inc
.list
;externFP GetCurrentPDB
if ROM and PMODE32
externFP HocusROMBase
endif
DataBegin
;externB Kernel_Flags
;externW AltfEEMS
externW headTDB
externW hExeHead
;externW pGlobalHeap
;externW MyCSDS
externW topPDB
externW cur_dos_pdb
externW Win_PDB
externW curTDB
;externW segSwapArea
DataEnd
externFP CallWEP
sBegin CODE
assumes CS,CODE
assumes DS,NOTHING
assumes ES,NOTHING
externNP MyUpper
externNP MyLock
externNP LoadNRTable
externNP LoadSegment
externNP GetOwner
externNP GetCachedFileHandle
if SDEBUG
externNP DebugFreeSegment
endif
externFP IGlobalAlloc
externFP IGlobalFree
;externFP IGlobalLock
externFP IGlobalUnfix
externFP IGlobalHandle
externFP GlobalFlags
externFP FreeNRTable
externFP Int21Handler
ifdef DBCS ;declare it.
externNP MyIsDBCSLeadByte ;Use near one as we are in the same seg
endif
if ROM
externFP FreeSelector
externNP alloc_data_sel16
endif
cProc SafeCall,<PUBLIC,FAR>
parmD Addr
cBegin
call Addr
cEnd
;-----------------------------------------------------------------------;
; GetExePtr ;
; ;
; Returns the exe header pointer for the passed handle. ;
; ;
; Arguments: ;
; parmW hinstance ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; AX = 0 ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Mon Aug 03, 1987 04:40:45p -by- David N. Weise [davidw] ;
; Rewrote it to work with expanded memory. Note that if the handle ;
; passed is truly bogus we could still catch a page fault under ;
; Win386. ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc GetExePtr,<PUBLIC,FAR>
parmW hinstance
cBegin
mov ax,hinstance
test ax,GA_FIXED ; Passed a segment address?
jz not_module
mov es,ax
cmp es:[ne_magic],NEMAGIC ; Yes, does it point to a Module?
jz gxdone
not_module:
SetKernelDS es
mov cx,headTDB
assumes es, nothing
find_TDB:
jcxz last_chance
mov es,cx
cmp ax,es:[TDB_module]
jz found_it
mov cx,es:[TDB_next]
jmp find_TDB
found_it:
mov ax,es:[TDB_pModule]
jmps gxdone
last_chance: ; The problem here is that USER
cCall MyLock,<ax> ; KNOWS that hinstance is but
or ax,ax ; the handle to his data segment.
jz gxdone
mov es,ax
cmp es:[ne_magic],NEMAGIC
je gxdone
cCall GetOwner,<ax>
or ax,ax
jz gxfail
mov es,ax
cmp es:[ne_magic],NEMAGIC
je gxdone
; The owner,ax, is now a PDB. We gotta find the TDB
SetKernelDS es
mov cx,headTDB
assumes es, nothing
find_PDB:
jcxz gxfail
mov es,cx
cmp ax,es:[TDB_PDB]
jz found_PDB
mov cx,es:[TDB_next]
jmp find_PDB
found_PDB:
mov ax,es:[TDB_pModule]
jmps gxdone
gxfail:
if KDEBUG
xor cx,cx
kerror ERR_LDMODULE,<Invalid module handle>,cx,hinstance
endif
xor ax,ax
gxdone: mov cx,ax
cEnd
;-----------------------------------------------------------------------;
; ;
; GetExpWinVer - return the expected Windows version for a given ;
; module handle ;
; ;
; Arguments: ;
; parmW hinstance ;
; ;
; Returns: ;
; AX = expected windows version ;
; DX = BOOL proportional font flag ;
; ;
; Error Returns: ;
; AX = 0 ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Fri 06 Jan 1989 -- Written by Sankar. ;
; ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc GetExpWinVer,<PUBLIC,FAR>, <si,di>
parmW hInstance
cBegin
cCall GetExePtr,<hInstance>
or ax,ax
jz err_GetExpWinVer
mov es,ax
mov ax,es:[ne_expver]
mov dx,es:[ne_flags]
and dx,NEWINPROT
; error if offsets don't match our defines - In which case find the right
; offsets and changes the defines in mvdm\inc\tdb16.h
.erre (NE_LOWINVER_OFFSET EQ ne_expver)
.erre (NE_HIWINVER_OFFSET EQ ne_flags)
err_GetExpWinVer:
cEnd
;-----------------------------------------------------------------------;
; MyAlloc ;
; ;
; Private interface to memory manager ;
; ;
; Arguments: ;
; parmW aflags ;
; parmW nsize ;
; parmW nelem ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; AX = Handle ;
; DX = Seg Address ;
; ;
; Registers Preserved: ;
; DI,SI,DS ;
; ;
; Registers Destroyed: ;
; BX,CX,ES ;
; ;
; Calls: ;
; GlobalAlloc ;
; MyLock ;
; ;
; History: ;
; ;
; Wed Apr 08, 1987 06:22:57a -by- David N. Weise [davidw] ;
; Wrote it. ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc MyAllocLinear,<PUBLIC,NEAR>
; Same as MyAlloc, except for non-brain-dead size parameter
parmW aflags
parmD dwBytes
cBegin
jmps MyAllocNotBrainDead
cEnd
assumes ds, nothing
assumes es, nothing
cProc MyAlloc,<PUBLIC,NEAR>
parmW aflags
parmD dwBytes
; parmW nsize
; parmW nelem
cBegin
xor dx,dx
mov ax,seg_dwBytes ;nsize
mov cx,off_dwBytes ;nelem
jcxz ma3
ma2:
shl ax,1
rcl dx,1
loop ma2
ma3:
mov seg_dwBytes, dx
mov off_dwBytes, ax
MyAllocNotBrainDead:
SetKernelDS es
mov cx,aflags
mov al,NSTYPE
and al,cl ; al has SEGTYPE
mov bx,NSDISCARD
and bx,cx
jz @F
shr bx,1
shr bx,1
shr bx,1
shr bx,1 ; BX has GA_DISCARDABLE
cmp al,NSCODE
jne @F
or bl,GA_DISCCODE ; Allocating discardable code
@@:
cmp al,NSDATA
jne @F
and cx,NOT NSWINCODE ; undo Excel bogusness
or bl,GA_DGROUP ; Allocating automatic data segment
@@:
test cl,NSMOVE
jz @F
or bl,GA_MOVEABLE
@@:
cmp al,NSTYPE
jz @F
or bh,GA_CODE_DATA
@@:
cCall IGlobalAlloc,<bx,dwBytes> ;dxax>
assumes es, nothing
push ax
test al,GA_FIXED
jnz @F
cCall MyLock,<ax>
@@:
pop dx
cEnd
;
; MyLock( hseg ) - Procedure to return the physical segment address of
; the passed handle.
;
;;;cProc MyLock,<PUBLIC,NEAR>
;;; parmW hseg
;;;cBegin
;;; cCall IGlobalHandle,<hseg>
;;; xchg dx,ax
;;;cEnd
;-----------------------------------------------------------------------;
; MyFree ;
; ;
; Frees a segment allocated by MyAlloc. ;
; ;
; Arguments: ;
; ;
; Returns: ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; ;
; History: ;
; ;
; Tue Dec 09, 1986 12:48:43p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc MyFree,<PUBLIC,NEAR>
parmW hseg
localW pseg
cBegin
mov bx,hseg
or bx,bx
jz mf3
mov ax,bx
xor cx,cx
test bl,GA_FIXED
jnz mf0a
push bx
cCall GlobalFlags,<bx>
mov cx, ax
xor ax, ax
pop bx
xchg ch, cl
test cl, HE_DISCARDED
jnz mf0a
mov ax, bx
HtoS ax
mf0a:
if KDEBUG
push cx
endif
mov pseg,ax
or ax,ax
jz mf1
mf0:
if SDEBUG
cCall DebugFreeSegment,<pseg,0>
endif
mf1:
if KDEBUG
pop cx
or ch,ch
jz mf2
mf1a:
push cx
cCall IGlobalUnfix,<hseg> ; Prevent RIP if freeing locked DS
pop cx
dec ch
or ch,ch ; If still lock, do it again
jnz mf1a
endif
mf2:
cCall IGlobalFree,<hseg>
mf3:
cEnd
;-----------------------------------------------------------------------;
; EntProcAddress
;
; Returns the fixed address of a procedure.
;
; Entry:
;
; Returns:
; DX:AX = thunk for moveable
; DX:AX = procedure for fixed
; AX = constant, ES:BX => constant for absolutes
; Registers Destroyed:
;
; History:
; Wed 30-Nov-1988 19:39:05 -by- David N. Weise [davidw]
;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
cProc EntProcAddress,<PUBLIC,NEAR>,<si,di>
parmW hExe
parmW entno
if KDEBUG
parmW bNoRip ; if 1 don't RIP for error, 0 -> do the RIP
endif
cBegin
mov es,hExe
mov cx,entno
and cx,7fffh ; clear ResidentName bit (#5108 donc)
jcxz entfail
dec cx
mov si,es:[ne_enttab]
entloop:
mov ax, es:[si.PM_entstart]
cmp cx, ax ; Below this block?
jb entfail ; yes, must be invalid!
cmp cx, es:[si.PM_entend] ; Above this block?
jae entnext ; yes, go to next block
sub cx, ax ; Found the right block, get offset
mov bx, cx
shl cx, 1
add bx, cx
add bx, cx ; bx = cx*5
lea si, [si+bx+size PM_entstruc]
mov bx, si
jmps gotent
entnext:
mov si, es:[si.PM_entnext] ; Next block
or si, si
jnz entloop
jmps entfail
entfail:
if KDEBUG
cmp bNoRip,0
jnz dont_rip_here
mov bx,entno
krDebugOut <DEB_WARN or DEB_krLoadSeg>, "Invalid ordinal reference (##BX) to %ES1"
; kerror ERR_LDORD,<Invalid ordinal reference to >,es,bx
dont_rip_here:
endif
xor dx,dx
xor ax,ax
jmps entdone
; Here if the current block has the entry we want
gotabs:
add bx,pentoffset ; make ES:BX point to constant (SLIME!)
mov dx,-1 ; make != 0 since abs might be!
jmps gotent1 ; Offset is symbol value
gotent:
xor ax, ax
mov al, es:[bx].penttype ; Get segno/type field
mov si,es:[bx].pentoffset
cmp al,ENT_ABSSEG ; If segno field absoulute segment
je gotabs ; Yes, have absolute symbol
cmp al, ENT_MOVEABLE
je gotmoveable
.errnz 10 - SIZE NEW_SEG1
; ax = segno
push bx
mov bx, es:[ne_segtab] ; see if really fixed
mov cx, ax ; look up in seg table
dec cx
shl cx, 1 ; get segtable + (segno-1)*10
add bx, cx
shl cx, 2
add bx, cx
test es:[bx].ns_flags, NSMOVE + NSALLOCED
pop bx
jnz gotmoveable
mov cx,-1 ; Fixed, make sure it's loaded
cCall LoadSegment,<es,ax,cx,cx>
or ax,ax
mov dx,ax
jnz gotent1
jmp entfail
gotmoveable:
xor ax,ax
mov al,es:[bx].pentsegno ; Segment number
dec ax
shl ax,1
mov di,ax
shl ax,2
add di,ax
.errnz 10 - SIZE NEW_SEG1
add di,es:[ne_segtab]
mov dx,es:[di].ns_handle
or dx, dx
jnz ok
mov ax, dx ; No handle, probably from an aborted
jmps entdone ; LoadModule - just return 0:0
ok:
Handle_To_Sel dl
gotent1:
mov ax,si
entdone:
mov cx,ax
or cx,dx
cEnd
;-----------------------------------------------------------------------;
; FindOrdinal ;
; ;
; Searches the resident and non-resident name tables for a procedure ;
; name and return its corresponding entry ordinal. ;
; ;
; Arguments: ;
; parmW hExe ;
; parmD lpname pointer name, strings starts with length ;
; parmW fh file handle NOT to be discarded from cache ;
; ;
; Returns: ;
; AX = ordinal number ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; ;
; Registers Destroyed: ;
; ;
; Calls: ;
; MyUpper ;
; LoadNRTable ;
; FreeNRTable ;
; ;
; History: ;
; ;
; Tue 09-May-1989 18:38:04 -by- David N. Weise [davidw] ;
; Added the batching if out of memory. ;
; ;
; Thu Sep 17, 1987 08:55:05p -by- David N. Weise [davidw] ;
; Added this nifty comment block and fixed it. ;
;-----------------------------------------------------------------------;
assumes ds, nothing
assumes es, nothing
CLNRBUFFER equ 150
cProc FindOrdinal,<PUBLIC,NEAR>,<si,di>
parmW hExe
parmD lpname
parmW fh
if ROM
localW fInROM
endif
localD oNRTable ; if batching, continue here
localV LoadNRbuffer,CLNRBUFFER ; if batching this is temp buffer
cBegin
xor ax,ax
mov oNRTable.hi,ax
mov oNRTable.lo,ax
if ROM
mov fInROM,ax ; assume module not in ROM
endif
les si,lpname
cmp byte ptr es:[si+1],'#'
je foint
fonorm: push ds
mov ds,hExe
if ROM
test ds:[ne_flags],NEMODINROM ; is module actually in ROM?
jz @f
inc fInROM
@@:
endif
mov si,ds:[ne_restab]
cld
foinit: xor ax,ax ; Skip module name or description
lodsb
add si,ax
inc si
inc si
foloop: lodsb ; get length of entry
les di,lpname
mov cx,ax
jcxz fodone ; no more entries?
cmp es:[di],al ; do lengths match?
jne noteq
inc di
fo_find:
mov al,es:[di]
call MyUpper
mov bl,ds:[si]
inc si
inc di
cmp al,bl
jne noteq1
loop fo_find
; repe cmpsb
; jne noteq
lodsw ; get ordinal number!
mov bx,ds
pop ds
cmp hExe,bx ; did we load the nrtable?
jnz foexit_j
jmp foexit1
foexit_j:
jmp foexit
noteq1: dec cx
noteq: add si,cx
inc si
inc si
jmps foloop
; Here if pName points to string of the form: #nnnn
foint: lods byte ptr es:[si] ; nbytes = *pName++
mov cl,al
xor ch,ch
dec cx ; ignore #
inc si
xor ax,ax ; sum = 0
foint0: mov dx,ax
lods byte ptr es:[si] ; c = *pName++
sub al,'0' ; if (!isdigit(c))
cmp al,9
ja fonorm ; treat like normal
xor ah,ah
mov bx,ax ; sum = (sum * 10) + (c - '0')
mov al,10
mul dx
add ax,bx
loop foint0
jmp foexit1
fodone: mov bx,ds
pop ds
;%out help me ; what was this line for?
mov cx,oNRTable.hi
cmp cx,oNRTable.lo
jnz fo_batching
cmp hExe,bx ; have we looked at NRTable yet?
if ROM
jne foexit_j
else
jne foexit
endif
if ROM
cmp fInROM,0 ; this module in ROM?
jz fo_nr_not_in_rom
cCall FindROMNRTable,<hExe> ; yes, get selector to ROM NR Table
mov fInROM,ax
push ds
mov ds,ax ; ds -> ROM NR table
xor bx,bx
mov bl,ds:[0] ; skip over first NR table entry
lea si,[bx+3] ; (the module description string)
xor ax,ax
jmp foloop
fo_nr_not_in_ROM:
endif
fo_batching:
xor bx,bx
mov ax,fh
;;; cmp ax,-1
;;; jz no_file_handle
SetKernelDS ES
;;; mov dx, topPDB
;;; mov es, curTDB
;;; UnSetKernelDS es
;;; mov ax, es:[TDB_PDB]
;;;
;;; cmp dx, cur_dos_pdb
;;; jz @F
;;; mov bx,ax
;;;@@:
mov bx, Win_PDB
UnSetKernelDS
mov dx, -1
cCall GetCachedFileHandle,<hexe,ax,dx>
no_file_handle:
push bx
lea cx,LoadNRbuffer
mov dx,CLNRBUFFER
cCall LoadNRTable,<hexe,ax,oNRTable,ss,cx,dx>
if KDEBUG
push es
push di
les di, [lpName]
krDebugOut <DEB_TRACE or DEB_krLoadSeg>, " looking for @ES:DI"
pop di
pop es
endif
pop si
or si,si
jz @F
;;; push ax
;;; push bx
;;; mov bx,si
;;; mov ah,50h
;;; DOSCALL
;;; pop bx
;;; pop ax
push es
SetKernelDS ES
mov Win_PDB, si
pop es
UnSetKernelDS ES
@@: mov oNRTable.hi,cx
mov oNRTable.lo,bx
push ds
mov ds,dx
mov si,ax
or ax,dx ; did we get a table?
jz @F
xor ax,ax
jmp foloop
@@: pop ds
foexit: push ax
if ROM
cmp fInROM,0 ; this module in ROM
jz @f
cCall FreeSelector,<fInROM> ; yes, free ROM NR table selector
jmps foexit0
@@:
endif
mov ax,ne_nrestab
cCall FreeNRTable,<hExe,ax>
foexit0:
pop ax
foexit1:
;??? commented out 3/7/88 by rong
;??? we should put this back in once everyone has the new keyboard driver
;if KDEBUG
; or ax,ax
; jnz foexit2
; les bx,lpname
; inc bx
; kerror ERR_LDNAME,<Invalid procedure name >,es,bx
; xor ax,ax
;foexit2:
;endif
cEnd
if ROM ;----------------------------------------------------------------
;-----------------------------------------------------------------------
; FindROMNRTable
;
; Returns a selector to the ROM copy of the Non-Resident name table for
; a module stored in ROM.
;
; Arguments:
; parmW hExe
;
; Returns:
; AX = selector mapping NR table
;
;-----------------------------------------------------------------------
assumes ds, nothing
assumes es, nothing
cProc FindROMNRTable,<PUBLIC,NEAR>,<ds>
parmW hExe
cBegin
mov ds,hExe
mov ax,word ptr ds:[ne_nrestab]
mov bx,word ptr ds:[ne_nrestab+2]
cCall alloc_data_sel16,<bx,ax,1000h>
if PMODE32
cCall HocusROMBase, <ax>
endif
if KDEBUG
or ax,ax
jnz @f
int 3
@@:
endif
cEnd
endif ;ROM ---------------------------------------------------------
; Search the list of new EXE headers for the passed executable file name
; (no path)
;
; this must be resident so we can search for modules in the file handle
; cache from the int 21 handler -- craigc
;
cProc ResidentFindExeFile,<PUBLIC,FAR>,<ds,si,di>
parmD pname
cBegin
SetKernelDS
mov ax,hExeHead
ffloop:
or ax,ax
jz ffdone
mov es,ax
mov di,es:[ne_pfileinfo]
or di,di
jz ffnext
;
; Double Byte Character is not able to search from the end of string,
; so this function must search from the top of string.
;
ifdef DBCS
lea si,[di.opFile] ; get address of file name
mov cl,es:[di.opLen] ; get structure length
xor ch,ch
add cx,di
mov di,cx ; save end address
sub cx,si ; get length of file name
mov bx,si ; save top address of file name
cld
delineator_loop:
lods byte ptr es:[si]
call MyIsDBCSLeadByte
jc delineator_notlead ; if not DBCS lead byte
dec cx
jcxz delineator_next
inc si
loop delineator_loop
jmp delineator_next
delineator_notlead:
cmp al,"\"
jz found_delineator
cmp al,":"
jz found_delineator
loop delineator_loop
jmp delineator_next
found_delineator:
mov bx,si ; save delineator address
loop delineator_loop
delineator_next:
xchg bx,di ; set address of file name to di
sub bx,di ; get lenfth of file name
else
mov si,di
xor cx,cx
mov cl,es:[di]
add si,cx
dec si
std
xor bx,bx
delineator_loop: ; look for beginning of name
lods byte ptr es:[si]
cmp al,"\"
jz found_delineator
cmp al,":"
jz found_delineator
inc bx
loop delineator_loop
dec si
found_delineator: ; ES:SI -> before name
mov di,si
inc di
inc di
endif
lds si,pname
UnSetKernelDS
mov cx,bx
cld
repe cmpsb
mov ax,es
je ffdone
ffnext:
mov ax,word ptr es:[ne_pnextexe]
jmp ffloop
ffdone:
cEnd
sEnd CODE
externFP FarLoadSegment
sBegin NRESCODE
assumes CS,NRESCODE
assumes DS,NOTHING
assumes ES,NOTHING
externNP DelModule
externNP MapDStoDATA
cProc FindExeFile,<PUBLIC,NEAR>
parmD pFile
cBegin
cCall ResidentFindExeFile, <pFile>
cEnd
; Search the list of new EXE headers for the passed executable name
cProc FindExeInfo,<PUBLIC,NEAR>,<ds,si,di>
parmD pname
parmW nchars
cBegin
cCall MapDStoDATA
ReSetKernelDS
mov bx,nchars
mov ax,hExeHead
feloop:
or ax,ax
jz fedone
mov es,ax
mov di,es:[ne_restab]
cmp es:[di],bl
jne fenext
inc di
lds si,pname
UnSetKernelDS
mov cx,bx
repe cmpsb
je fedone
fenext:
mov ax,word ptr es:[ne_pnextexe]
jmp feloop
fedone:
cEnd
cProc FarFindExeInfo,<PUBLIC,FAR>
parmD pname
parmW nchars
cBegin
cCall FindExeInfo,<pname,nchars>
cEnd
;
; IncExeUsage( hExe ) - procedure to increment the usage count of this
; EXE header. Indirectly increments the usage count of all the EXE
; headers it points to.
;
cProc IncExeUsage,<PUBLIC,NEAR>,<ax,di>
parmW hexe
cBegin
mov cx,hexe
jcxz iexj
mov es,cx
cmp es:[ne_magic],NEMAGIC
jne iexj
test es:[ne_usage],8000h
jz iego
iexj:
krDebugOut <DEB_ERROR or DEB_KRLOADMOD>, "IncExeUsage(#ES) not DLL"
jmp iex
iego:
cmp es:[ne_usage], 4000h
jb OKusage
krDebugOut DEB_FERROR, "IncExeUsage: ne_usage overflow"
OKusage:
;
; Save time and space by saving stuff on stack
; rather than recursing.
;
or es:[ne_usage], 8000h
NextExe0:
or es:[ne_usage], 4000h ; Mark node visited
inc es:[ne_usage]
;if kdebug
; push ax
; mov ax, es:[ne_usage]
; krDebugOut <DEB_TRACE or DEB_krLoadMod>, "IncExeUsage(%ES0) #ax"
; pop ax
;endif
mov cx,es:[ne_cmod]
jcxz NoDeps0
mov di,es:[ne_modtab]
ieloop:
push es
cmp word ptr es:[di], 0
je ieloop1
lar ax, es:[di] ; Make sure valid selector
jnz ieloop1
mov es, es:[di]
cmp es:[ne_magic],NEMAGIC
jne ieloop1
test es:[ne_usage], 0C000h
jnz ieloop1
push cx
push di ; Fake recursion
jmp NextExe0
NextExeDone0: ; Return from fake recursion
pop di
pop cx
ieloop1:
pop es
add di,2
loop ieloop
NoDeps0:
mov cx, es
cmp cx, hExe
jne NextExeDone0
NextExe1:
and es:[ne_usage], NOT 4000h ; Mark node visited
mov cx,es:[ne_cmod]
jcxz NoDeps1
mov di,es:[ne_modtab]
UnMarkLoop:
push es
cmp word ptr es:[di], 0
je UnMarkLoop1
lar ax, es:[di] ; Make sure valid selector
jnz UnMarkLoop1
mov es, es:[di]
cmp es:[ne_magic],NEMAGIC
jne UnMarkLoop1
test es:[ne_usage], 08000h
jnz UnMarkLoop1
test es:[ne_usage], 04000h
jz UnMarkLoop1
push cx
push di ; Fake recursion
jmp NextExe1
NextExeDone1: ; Return from fake recursion
pop di
pop cx
UnMarkLoop1:
pop es
add di,2
loop UnMarkLoop
NoDeps1:
mov cx, es
cmp cx, hExe
jne NextExeDone1
xor es:[ne_usage], 8000h
iex:
cEnd
;-----------------------------------------------------------------------;
; DecExeUsage ;
; ;
; Decrements the usage count of the given EXE header. Indirectly ;
; decrements the usage count of all the EXE headers it points to. ;
; ;
; Arguments: ;
; parmW hexe ;
; ;
; Returns: ;
; ZF = 1 if usage count is now zero. ;
; ;
; Error Returns: ;
; ;
; Registers Preserved: ;
; DI,SI,DS ;
; ;
; Registers Destroyed: ;
; AX,BX,CX,DX,ES ;
; ;
; Calls: ;
; DecExeUsage ;
; DelModule ;
; ;
; History: ;
; ;
; Mon Sep 21, 1987 01:21:00p -by- David N. Weise [davidw] ;
; Added this nifty comment block. ;
;-----------------------------------------------------------------------;
cProc DecExeUsage,<PUBLIC,NEAR>,<ds,di,si>
parmW hexe
cBegin
call MapDStoDATA
ReSetKernelDS
xor si,si
mov cx,hexe
xor ax,ax
jcxz dexj
mov es,cx
cmp es:[si].ne_magic,NEMAGIC
jne dexj
test es:[si].ne_usage,8000h
jz dego
dexj:
krDebugOut <DEB_ERROR or DEB_KRLOADMOD>, "DecExeUsage(#ES) not DLL"
jmp dex
dego:
;
; Save time and space by saving stuff on stack
; rather than recursing.
;
dec es:[si].ne_usage
or es:[si].ne_usage, 8000h
;if kdebug
; push ax
; mov ax, es:[si].ne_usage
; krDebugOut <DEB_TRACE or DEB_krLoadMod>, "DecExeUsage(%ES0) #ax"
; pop ax
;endif
NextExe2:
or es:[si].ne_usage, 4000h ; Mark node visited
mov cx,es:[si].ne_cmod
jcxz NoDeps2
mov di,es:[si].ne_modtab
MarkLoop2:
push es
cmp si, es:[di]
je MarkLoop3
lar ax, es:[di] ; Make sure valid selector
jnz MarkLoop3
mov es, es:[di]
cmp es:[si].ne_magic,NEMAGIC
jne MarkLoop3
test es:[si].ne_usage, 0C000h
jnz MarkLoop3
push cx
push di ; Fake recursion
jmp NextExe2
NextExeDone2: ; Return from fake recursion
pop di
pop cx
MarkLoop3:
pop es
add di,2
loop MarkLoop2
NoDeps2:
mov cx, es
cmp cx, hExe
jne NextExeDone2
xor cx, cx
push cx ; End of list of Exes to delete
mov di, hExeHead ; Scan Exes once to dec them
scan_exes:
or di, di
jz de_done
mov es, di
mov di, es:[si].ne_pnextexe
test es:[si].ne_usage, 4000h
jz scan_exes
and es:[si].ne_usage, NOT 4000h ; Remove the mark
test es:[si].ne_usage, 8000h ; Skip this one?
jnz scan_exes
; krDebugOut <DEB_TRACE or DEB_krLoadMod>, "DecExeUsage dependent %ES0"
dec es:[si].ne_usage
jnz scan_exes
push es ; We will delete this one
jmps scan_exes
de_done: ; Call WEP each module before
mov bx, sp ; we free any modules
de_done0:
mov cx, ss:[bx]
add bx, 2
jcxz de_done1
push bx
cCall CallWEP, <cx, 0>
pop bx
jmps de_done0
de_done1:
pop cx ; Get next module to delete
jcxz all_deleted
cCall DelModule,<cx> ; Delete him
jmps de_done1
all_deleted:
mov es, hExe
and es:[si].ne_usage,NOT 0C000h
dex:
cEnd
;
; StartProcAddress( hExe ) - procedure to return the fixed address of
; a new EXE start procedure
;
cProc StartProcAddress,<PUBLIC,NEAR>,<di>
parmW hexe
parmW fh
cBegin
mov es,hexe
mov di,ne_csip
xor dx,dx
mov ax,es:[di+2]
or ax,ax
jz sp1
mov di,es:[di]
cCall FarLoadSegment,<es,ax,fh,fh>
jcxz sp1
mov ax,di ; DX:AX is start address of module
sp1: ; (DX is really a handle)
mov cx,ax
or cx,dx
cEnd
; GetStackPtr - returns the initial SS:SP for a module.
;
cProc GetStackPtr,<PUBLIC,NEAR>,<si>
parmW hExe
cBegin
mov es,hExe
if KDEBUG
cmp es:[ne_sssp].sel,0
jnz @F
mov cx,ne_sssp
fkerror 0,<Invalid stack segment>,es,cx
@@:
endif
cmp es:[ne_sssp].off,0
jne re3
mov dx,es:[ne_stack]
mov bx,es:[ne_pautodata]
or bx,bx
jz re2
add dx,es:[bx].ns_minalloc
re2: and dx,0FFFEh ; Word aligned stack
mov word ptr es:[ne_sssp],dx
re3: mov dx,es:[ne_sssp].sel
mov ax,es:[ne_sssp].off
push ax
mov cx,-1
cCall FarLoadSegment,<es,dx,cx,cx>
pop ax ; Handle in DX and offset in AX
cEnd
;
; GetInstance( hExe ) - Procedure to return the instance handle for
; the current automatic data segment associated with the passed exe
;
cProc GetInstance,<PUBLIC,NEAR>
parmW hexe
cBegin
mov es,hexe
mov ax,es:[ne_flags]
test ax,NEINST+NESOLO
mov ax,es
jz gidone
mov bx,es:[ne_pautodata]
or bx,bx
jz gidone
mov ax,es:[bx].ns_handle
gidone:
mov cx,ax
cEnd
sEnd NRESCODE
end
|