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
|
page ,132
if 0
/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
ints.asm
Abstract:
Contains handler for Windows protect-mode NetwareRequest function, exported
by NETWARE.DRV. Code in this file access real mode memory via an LDT descriptor
created especially for this purpose. This selector gives us access to all
code and data contained in the Nw16 TSR
Author:
Richard L Firth 22-Jan-1994
Environment:
Windows protect mode only
Revision History:
22-Jan-1994 rfirth
Created
--*/
endif
include nwdos.inc ; NWDOSTABLE_ASM structure
include isvbop.inc ; DispatchCall
.286
.model medium,pascal
_DATA segment word public 'DATA'
OldInt21Handler dd ?
RMSegment dw ?
RMBase dw ? ; MUST be in this order - loaded
RMSelector dw ? ; via lds dx,word ptr RMBase
.errnz (RMSelector - (RMBase + 2))
_DATA ends
;
; code segment ordering
;
INIT_TEXT segment byte public 'CODE'
INIT_TEXT ends
_TEXT segment byte public 'CODE'
_TEXT ends
;
; macros
;
LOAD_DS macro
push _DATA
pop ds
assume ds:_DATA
endm
SET_DS macro
push ds
LOAD_DS
endm
RESTORE_DS macro
pop ds
assume ds:nothing
endm
LOAD_RM_DS_BX macro
LOAD_DS
lds bx,dword ptr RMBase
assume ds:nothing
endm
RESTORE_DS_BX macro
RESTORE_DS
pop bx
endm
INIT_TEXT segment byte public 'CODE'
assume cs:INIT_TEXT
public GetLowRedirInfo
GetLowRedirInfo proc far
mov ax,9f00h
int 21h ; get the RM data segment in BX
jc @f
SET_DS
mov RMSegment,bx
mov RMBase,dx
mov ax,2
int 31h
jc @f ; can't create selector
mov RMSelector,ax
;
; now that we have the selector, we write the selector value into the low
; memory area. The 32-bit DLL will use this value when setting output DS or ES
; register values if the call originated in Protect Mode
;
lds bx,dword ptr RMBase
mov [bx]._PmSelector,ax
;
; we now hook int 21
;
LOAD_DS
push es
mov ax,3521h
int 21h
mov word ptr OldInt21Handler,bx
mov word ptr OldInt21Handler[2],es
mov cx,_TEXT
mov dx,offset _TEXT:NewInt21Handler
mov ax,205h
mov bl,21h
int 31h
pop es
RESTORE_DS
xor ax,ax ; success: return TRUE
inc ax
ret
@@: xor ax,ax ; failure: return FALSE
ret
GetLowRedirInfo endp
INIT_TEXT ends
_TEXT segment byte public 'CODE'
assume cs:_TEXT
public NewInt21Handler
NewInt21Handler proc far
sti
cmp ah,0e3h
jb @f
call far ptr NetwareRequest
retf 2
@@: sub sp,4
push bp
mov bp,sp
push es
push bx
SET_DS
les bx,OldInt21Handler
mov [bp+2],bx
mov [bp+4],es
RESTORE_DS
pop bx
pop es
pop bp
retf
NewInt21Handler endp
public NetwareRequest
NetwareRequest proc far
push bx
push ds
LOAD_RM_DS_BX
cmp ah,0f0h
jne for_dll
;
; these are the 0xF000, 0xF001, 0xF002, 0xF004, 0xF005 calls that we can handle
; here without having to BOP. All we need do is access the table in the shared
; real-mode/protect-mode (low) memory
;
.errnz (_PrimaryServer - (_PreferredServer + 1))
;
; point bx at PreferredServer in the low memory area. If the request is a
; PrimaryServer request (0xF004, 0xF005) then point bx at PrimaryServer
;
lea bx,[bx]._PreferredServer; bx = offset of PreferredServer
cmp al,3
cmc
adc bx,0 ; bx = &PrimaryServer if F004 or F005
or al,al ; f000 = set preferred server
jz set_server
cmp al,4 ; f004 = set primary server
jnz try_01
;
; 0xF000 or 0xF004: set Preferred or Primary Server to value contained in DL.
; If DL > 8, set respective server index to 0
;
set_server:
xor al,al
cmp dl,8
ja @f
mov al,dl
@@: mov [bx],al
jmp short exit_f0
;
; 0xF001 or 0xF005: get Preferred or Primary Server
;
try_01: cmp al,1 ; f001 = get preferred server
jz get_server
cmp al,5
jnz try_02
get_server:
mov al,[bx]
jmp short exit_f0
try_02: cmp al,2 ; f002 = get default server
jnz for_dll ; try to handle on 32-bit side
mov al,[bx] ; al = PreferredServer
or al,al
jnz exit_f0
mov al,[bx+1] ; al = PrimaryServer
exit_f0:RESTORE_DS_BX
ret
;
; if we're here then the call must go through to the 32-bit DLL. Save any relevant
; info in the low memory area, load the handle and BOP (DispatchCall)
;
for_dll:mov [bx]._SavedAx,ax ; save AX value for DLL
push word ptr [bx]._hVdd ; put VDD handle on top of stack
cmp ah,0BCh ; bc, bd, be need handle mapping
jb @f
cmp ah,0BEh
ja @f
pop ax ; ax = hVdd
RESTORE_DS_BX ; ds, bx = user ds, bx
call MapNtHandle
jmp dispatchola
@@: push bp
cmp ah, 0E3h ; Is it new or old Create Job request?
je lookupcode
cmp ax, 0F217h
jne check_f3
lookupcode:
mov bp,sp
mov ds,[bp+4]
cmp byte ptr [si+2],68h
je createjob
cmp byte ptr [si+2],79h
je createjob
jmp short outtahere
createjob:
LOAD_RM_DS_BX
mov [bx]._SavedAx,9f02h
push ax ; Open \\Server\queue for NCP
mov ax,[bp+2] ; ax = hVdd
mov ds,[bp+4] ; ds = users ds
push ds
push dx ; users dx
DispatchCall ; Set DeNovellBuffer to \\Server\queue
; and registers ready for DOS OpenFile
int 21h ; Open \\server\queue
LOAD_RM_DS_BX
jc openfailed
mov [bx]._JobHandle, al
mov [bx]._CreatedJob, 1 ; Flag JobHandle is valid
push bx
mov bx, ax ; JobHandle
call MapNtHandle ; take bx and find the Nt handle
pop bx
openfailed:
pop dx
pop ds ; Proceed and send the NCP
pop ax
push ds
push bx
LOAD_RM_DS_BX
mov [bx]._SavedAx, ax
pop bx
pop ds ; users DS
jmp short outtahere
check_f3:
cmp ah, 0F3h
jne outtahere
; FileServerCopy, change both
; handles in the structure es:di
push bx
mov bx,word ptr es:[di] ; Map Source Handle
call MapNtHandle
pop bx
mov ax,[bx]._NtHandleHi
mov [bx]._NtHandleSrcHi,ax
mov ax,[bx]._NtHandleLow
mov [bx]._NtHandleSrcLow,ax
mov bx,word ptr es:[di+2] ; Map Destination Handle
call MapNtHandle
outtahere:
pop bp
pop ax ; ax = hVdd
RESTORE_DS_BX ; ds, bx = user ds, bx
dispatchola:
DispatchCall ; BOP: DLL performs action
ret ; return to the application
;
; if the request was not recognized by the DLL, it modifies IP so that control
; will resume at the next int 21. We just fill the intervening space with NOPs
; (space that makes up a retf <n> instruction in the RM TSR)
;
nop
nop
int 21h
ret
NetwareRequest endp
; *** MapNtHandle
; *
; * Given a handle in BX, map it to a 32-bit Nt handle in NtHandle[Hi|Low]
; *
; * ENTRY bx = handle to map
; *
; * EXIT Success - NtHandle set to 32-bit Nt handle from SFT
; *
; * USES ax, bx, flags
; *
; * ASSUMES nothing
; *
; ***
MapNtHandle proc near
push ax
mov ax,9f01h ; call MapNtHandle on (BX) in RM
int 21h ; update NtHandleHi, NtHandleLow
pop ax
@@: ret
MapNtHandle endp
_TEXT ends
end
|