summaryrefslogtreecommitdiffstats
path: root/private/nw/nw16/tsr/nw16.asm
blob: ac19beed8b3ff2873470ab383e49d1b418d9b765 (plain) (blame)
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