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
|
page ,132
if 0
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
nw16.asm
Abstract:
This module contains the stub redir TSR code for NT VDM net support
Author:
Richard L Firth (rfirth) 05-Sep-1991
Colin Watson (colinw) 30-Jun-1993
Environment:
Dos mode only
Revision History:
05-Sep-1991 rfirth
Created
30-Jun-1993 colinw
ported to NetWare
--*/
endif
;
; DOS include files
;
.xlist
.xcref
include isvbop.inc ; NTVDM BOP mechanism
include dossym.inc ; includes MS-DOS version etc
include pdb.inc ; PSP defines
include syscall.inc ; AssignOper
include segorder.inc ; load order of 'redir' segments
include debugmac.inc ; debug display macros
include asmmacro.inc ; jumps which may be short or near
include messages.inc
include nwdos.inc ; NetWare structures and nwapi32 interface
.cref
.list
;
; Define externals in resident code and data
;
ResidentCodeStart
extrn Old21Handler:dword
extrn NwInt21:near
extrn hVDD:dword
extrn quick_jump_to_dos:byte
extrn for_dos_proper:byte
extrn chain_previous_int21:byte
extrn ConnectionIdTable:byte
extrn not_exclusive:byte
ResidentCodeEnd
InitStack segment stack para 'stack'
dw 256 dup (?)
InitStack ends
InitDataStart
bad_ver_msg db NLS_MSG_001,c_CR,c_LF
BAD_VER_MSG_LEN equ $-bad_ver_msg
db '$' ; for INT 21/09 display string
already_loaded_msg db NLS_MSG_004,c_CR,c_LF
ALREADY_LOADED_MSG_LEN equ $-already_loaded_msg
cannot_load_msg db NLS_MSG_005,c_CR, c_LF
CANNOT_LOAD_MSG_LEN equ $-cannot_load_msg
InitDataEnd
InitCodeStart
assume cs:InitCode
assume ds:nothing
assume es:nothing
assume ss:nothing
public DllName
DllName db "NWAPI16.DLL",0
public InitFunc
InitFunc db "Nw16Register",0
public DispFunc
DispFunc db "Nw16Handler",0
public start
start proc near
;
; when we start up we could be on any old PC - even an original, so don't
; assume anything other than a model-T processor
;
.8086
;
; Set the data segment while we're at it - all paths set it sooner
; or later. NOTE: es will point to the PSP until we change it!
;
mov dx,InitData
mov ds,dx
assume ds:InitData
;
; first off, get the DOS version. If we're not running on NT (VDM) then this
; TSR's not going to do much, so exit. Exit using various methods, depending
; on the DOS version (don't you hate compatibility?)
;
mov ah,30h
int 21h
jc ancient_version ; version not even supported
;
; version is 2.0 or higher. Check it out. al = major#, ah = minor#
;
cmp al,major_version
jne invalid_version
;
; what do you know? We're actually running on NT (unless some evil programmer
; has pinched int 21h/30h and broken it!). Enable minimum instruction set
; for NTVDM (286 on RISC).
;
.286c
;
; perform an installation check by calling one of our entry points
; (GetFileServerNameTable). If this returns a table pointer in ES:DI then we
; know this TSR is already active, in which case we bail out now
;
push es
push di
xor di,di
mov es,di
mov ax,0ef03h
int 21h
mov ax,es
or ax,di
pop di
pop es
jnz already_here
;
; OK, the NetWare redir is not already loaded - we're in business.
; Find entrypoints to nwapi16.dll Get and set the various interrupt
; vectors, Calculate the amount of space we want to keep,
; free up any unused space (like the environment segment), display a message
; in the DEBUG version, then terminate and stay resident. Remember: at this
; point we expect ES to point at the PSP
;
call PullInDll
jc already_here ; failed to load
call InstallInterruptHandlers
assume es:nothing
push es
pop ds
call is_c_on_command_line
jz @f
mov dx,ResidentCode
mov ds,dx
assume ds:ResidentCode
mov not_exclusive, 1
assume ds:nothing
@@:
;
; free the environment segment
;
mov es,es:[PDB_environ]
mov ah,49h
int 21h ; free environment segment
;if DEBUG
;ifdef VERBOSE
; DbgPrintString <"NetWare Redir successfully loaded",13,10>
;endif
;endif
;
; finally terminate and stay resident
;
mov dx,ResidentEnd
sub dx,ResidentStart ; number of paragraphs in resident code
add dx,10h ; additional for PSP (PDB)
;if DEBUG
;ifdef VERBOSE
; DbgPrintString "Staying resident with "
; DbgPrintHexWord dx
; DbgPrintString " paragraphs. Load seg is ",NOBANNER
; mov ah,62h
; int 21h
; DbgPrintHexWord bx
; DbgPrintString " current seg is ",NOBANNER
; DbgPrintHexWord cs
; DbgCrLf
;endif
;endif
mov ax,3100h
int 21h ; terminate and stay resident
;
; here if the MS-DOS version check (Ah=30h) call is not supported
;
ancient_version:
mov dx,InitData
mov ds,dx
assume ds:InitData
mov dx,offset bad_ver_msg
mov ah,9 ; cp/m-style write to output
int 21h
;
; safe exit: what we really want to do here is INT 20H, but when you do this,
; CS must be the segment of the PSP of this program. Knowing that CD 20 is
; embedded at the start of the PSP, the most foolproof way of doing this is
; to jump (using far return) to the start of the PSP
;
push es
xor ax,ax
push ax
retf ; terminate
;
; we are running on a version of DOS >= 2.00, but its not NT, so we still can't
; help. Display the familiar message and exit, but using a less programmer-
; hostile mechanism
;
invalid_version:
mov dx,offset bad_ver_msg
mov cx,BAD_VER_MSG_LEN
jmps print_error_message_and_exit
;
; if we cannot initialize 32-bit support (because we can't find/load the DLL)
; then put back the hooked interrupt vectors as they were when this TSR started,
; display a message and fail to load the redir TSR
;
initialization_error:
call RestoreInterruptHandlers
mov dx,offset cannot_load_msg
mov cx,CANNOT_LOAD_MSG_LEN
jmps print_error_message_and_exit
;
; The DOS version's OK, but this TSR is already loaded
;
already_here:
mov dx,offset already_loaded_msg
mov cx,ALREADY_LOADED_MSG_LEN
print_error_message_and_exit:
mov bx,1 ; bx = stdout handle
mov ah,40h ; write to handle
int 21h ; write (cx) bytes @ (ds:dx) to stdout
mov ax,4c01h ; terminate program
int 21h ; au revoir, cruel environment
start endp
;*******************************************************************************
;*
;* InstallInterruptHandlers
;*
;* Sets the interrupt handlers for all the ints we use - 21
;*
;* ENTRY es = PSP segment
;* ds =
;*
;* EXIT Old21Handler contains the original interrupt 21 vector
;*
;* RETURNS nothing
;*
;* ASSUMES
;*
;*******************************************************************************
InstallInterruptHandlers proc
push es ; PSP segment - destroyed by INT 21/35h
push ds
;
; note: if we use ResidentCode here, explicitly, instead of seg OldMultHandler,
; then we can leave out an extraneous load of ds for the ISR address
;
mov dx,ResidentCode
mov ds,dx
assume ds:ResidentCode
;
; Add ourselves to the int 21 chain
;
mov ax,3521h
int 21h
mov word ptr Old21Handler,bx
mov word ptr Old21Handler+2,es
mov word ptr quick_jump_to_dos+1,bx
mov word ptr quick_jump_to_dos+3,es
mov word ptr for_dos_proper+1,bx
mov word ptr for_dos_proper+3,es
mov word ptr chain_previous_int21+1,bx
mov word ptr chain_previous_int21+3,es
mov dx,offset ResidentCode:NwInt21
mov ax,2521h
int 21h
pop ds ; restore segment registers
pop es
ret
InstallInterruptHandlers endp
;*******************************************************************************
;*
;* RestoreInterruptHandlers
;*
;* Resets the interrupt handlers for all the ints we use - 21
;*
;* ENTRY Old21Handler
;* contain the interrupt vectors from before nw16.sys was loaded
;*
;* EXIT Original interrupt vectors are restored
;*
;* RETURNS nothing
;*
;* ASSUMES
;*
;*******************************************************************************
RestoreInterruptHandlers proc
push ds
assume ds:nothing
push es
mov dx,ResidentCode
mov es,dx
assume es:ResidentCode
lds dx,Old21Handler
mov ax,2521h
int 21h
pop es
pop ds
ret
RestoreInterruptHandlers endp
;*******************************************************************************
;*
;* PullInDll
;*
;* Does a RegisterModule to load NWAPI32.DLL into our NTVDM.EXE
;*
;* ENTRY nothing
;*
;* EXIT nothing
;*
;* RETURNS cf if fails.
;*
;* ASSUMES Earth moves round Sun
;*
;******************************************************************************/
PullInDll proc near
pusha ; dispatch code
push dx ; save callers dx,ds,es,ax
push ds
push es
push ax
mov dx,InitCode
mov ds,dx
assume ds:InitCode
push ds
pop es
assume es:InitCode
mov si,offset DllName ; ds:si = nwapi32.dll
mov di,offset InitFunc ; es:di = init routine
mov bx,offset DispFunc ; ds:bx = dispatch routine
mov ax,ResidentCode
mov dx,offset ConnectionIdTable
; ax:dx = shared datastructure
RegisterModule
jc @f
mov dx,ResidentCode
mov ds,dx
assume ds:ResidentCode
mov word ptr hVDD,ax
@@: pop ax ; callers ax
pop es ; callers es
pop ds ; callers ds
pop dx ; callers dx
assume ds:nothing
assume es:nothing
popa ; dispatch code
ret
PullInDll endp
;*******************************************************************************
;*
;* is_c_on_command_line
;*
;* -C or /C means we should open compatiblity mode createfiles as shared
;* instead of exclusive
;*
;* ENTRY ds points to PDB
;*
;* EXIT nothing
;*
;* RETURNS zero if not found.
;*
;* ASSUMES ds points at PSP
;*
;******************************************************************************/
is_c_on_command_line proc near
mov si,80h
lodsb
cbw
mov cx,ax
next: jcxz quit
dec cx
lodsb
check_next:
cmp al,'-'
je check_c
cmp al,'/'
je check_c
cmp al,' '
je next
cmp al,9
je next
find_ws:jcxz quit
dec cx
lodsb
cmp al,' '
je next
cmp al,9
je next
jmp short find_ws
check_c:jcxz quit
dec cx
lodsb
or al,20h
cmp al,'c'
jne find_ws
or cx,ax
quit: or cx,cx
ret
is_c_on_command_line endp
InitCodeEnd
end start
|