Leaked source code of windows server 2003
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.

2431 lines
77 KiB

  1. PAGE ,132
  2. TITLE DXNETBIO.ASM -- Dos Extender NetBIOS API Mapper
  3. ; Copyright (c) Microsoft Corporation 1989-1991. All Rights Reserved.
  4. ;***********************************************************************
  5. ;
  6. ; DXNETBIO.ASM - DOS Extender NetBIOS API Mapper
  7. ;
  8. ;-----------------------------------------------------------------------
  9. ;
  10. ; This module provides the 286 DOS Extender's API mapping of Int 2Ah and
  11. ; 5Ch NetBIOS requests. It allows a protected mode application to
  12. ; issue NetBIOS requests without worrying about segment to selector
  13. ; translations and mapping of buffers between extended and conventional
  14. ; memory.
  15. ;
  16. ;-----------------------------------------------------------------------
  17. ;
  18. ; 11/29/90 amitc Modified code to have the POST routine in GlobalMemory
  19. ; and queue the POST when DOSX is not around.
  20. ; 11/29/90 amitc Call to InitLowHeap moved to this file from DXOEM.ASM
  21. ; 02/01/90 jimmat Update Api mapping table for Ungerman-Bass extensions
  22. ; as per new data from UB.
  23. ; 06/15/89 w-glenns Finished TermNetMapper, added Delay/ResumeNetPosting
  24. ; 04/18/89 jimmat Original version.
  25. ; 18-Dec-1992 sudeepb Changed cli/sti to faster FCLI/FSTI
  26. ;
  27. ;***********************************************************************
  28. .286p
  29. ; -------------------------------------------------------
  30. ; INCLUDE FILE DEFINITIONS
  31. ; -------------------------------------------------------
  32. .xlist
  33. .sall
  34. include segdefs.inc
  35. include gendefs.inc
  36. include pmdefs.inc
  37. include interupt.inc
  38. include netbios.inc
  39. include intmac.inc
  40. include stackchk.inc
  41. include bop.inc
  42. include rdrsvc.inc
  43. include dpmi.inc
  44. include rdrsvc.inc
  45. .list
  46. ; -------------------------------------------------------
  47. ; FLAG FOR PM NCB HANDLING
  48. ; -------------------------------------------------------
  49. PM_NCB_HANDLING equ 1 ; set to 0 for NCB handling in VM
  50. ; -------------------------------------------------------
  51. ; GENERAL SYMBOL DEFINITIONS
  52. ; -------------------------------------------------------
  53. ; The following equates define the codes that map between a NCB Command code
  54. ; and the mapping flags used to process it. To be compatible with Windows/386,
  55. ; these values are all increments of 4 (they use 32 bit offsets). These
  56. ; values should always correspond to the values used by the Windows/386
  57. ; NetBIOS mapping!
  58. ApiMapUnknown EQU 00h
  59. ApiMapNone EQU 04h
  60. ApiMapIn EQU 08h
  61. ApiMapOut EQU 0Ch
  62. ApiMapInOut EQU 10h
  63. ApiChainSend EQU 14h
  64. ApiCancel EQU 18h
  65. ApiBufferIn EQU 1Ch
  66. ApiBufferOut EQU 20h
  67. ApiBufferInOut EQU 24h
  68. ; The following equates define the bit flags which identify the actions
  69. ; to take on entry and exit of a NetBIOS request.
  70. BUFF_IN EQU 01h ;Buffer data to the int handler
  71. BUFF_OUT EQU 02h ;Buffer data from the int handler
  72. BUFF_CHAIN EQU 04h ;Special chain send buffering
  73. BUFF_CANCEL EQU 08h ;Special cancel buffering
  74. REPLACE_MAP_TABLE EQU 1607h ;Int2fh replace net map table service
  75. VNETBIOS_DEV_ID EQU 14h ;VNETBIOS device ID
  76. ; -------------------------------------------------------
  77. ; EXTERNAL SYMBOL DEFINITIONS
  78. ; -------------------------------------------------------
  79. extrn EnterIntHandler:NEAR
  80. extrn LeaveIntHandler:NEAR
  81. extrn EnterRealMode:NEAR
  82. extrn EnterProtectedMode:NEAR
  83. extrn GetSegmentAddress:NEAR
  84. externFP NSetSegmentDscr
  85. extrn Lma2SegOff:NEAR
  86. ; -------------------------------------------------------
  87. ; DATA SEGMENT DEFINITIONS
  88. ; -------------------------------------------------------
  89. DXDATA segment
  90. ifdef NEC_98
  91. extrn fNHmode:BYTE
  92. endif ;NEC_98
  93. extrn pbReflStack:WORD
  94. extrn bReflStack:WORD
  95. extrn regUserSS:WORD
  96. extrn regUserSP:WORD
  97. extrn rgbXfrBuf1:BYTE
  98. extrn segDXCode:WORD
  99. extrn NetHeapSize:WORD
  100. ifdef WOW_x86
  101. extrn FastBop:fword
  102. endif
  103. OldInt73 dd 0
  104. public HCB_List
  105. Cancel_NCB EQU rgbXfrBuf1 ;Easier for commenting/readability
  106. HCB_List dw 0 ;linked list of low HCB/NCB/Buffers
  107. lpfnOldInt2A dd ? ;old int vector 2Ah & 5Ch routines
  108. lpfnOldInt5C dd ?
  109. lpfnRmNetIsr dd ? ;Real Mode vector to Network Int Rtn
  110. SelNetStubCode dw 0 ;sel for stub code
  111. SegNetStubCode dw 0 ;segment for stub code
  112. AddrfStubDelayNetPosting dw ? ;address of fStubDelayNetPosting in StubSeg
  113. AddrfStubTermNetRequest dw ? ;address of fStubTermNetRequest in StubSeg
  114. NBPSp dw 0
  115. ; The ApiMapTbl converts an NCB Command code (0-7F) into a code that
  116. ; identifies the particular mapping routine to execute.
  117. ApiMapTbl label byte
  118. db ApiMapUnknown ; 00h -
  119. db ApiMapUnknown ; 01h -
  120. db ApiMapUnknown ; 02h -
  121. db ApiMapUnknown ; 03h -
  122. db ApiMapUnknown ; 04h -
  123. db ApiMapUnknown ; 05h -
  124. db ApiMapUnknown ; 06h -
  125. db ApiMapUnknown ; 07h -
  126. db ApiMapUnknown ; 08h -
  127. db ApiMapUnknown ; 09h -
  128. db ApiMapUnknown ; 0Ah -
  129. db ApiMapUnknown ; 0Bh -
  130. db ApiMapUnknown ; 0Ch -
  131. db ApiMapUnknown ; 0Dh -
  132. db ApiMapUnknown ; 0Eh -
  133. db ApiMapUnknown ; 0Fh -
  134. db ApiMapNone ; 10h - Call
  135. db ApiMapNone ; 11h - Listen
  136. db ApiMapNone ; 12h - Hang up
  137. db ApiMapUnknown ; 13h -
  138. db ApiBufferIn ; 14h - Send
  139. db ApiBufferOut ; 15h - Receive
  140. db ApiBufferOut ; 16h - Receive any
  141. db ApiChainSend ; 17h - Chain send
  142. db ApiMapUnknown ; 18h -
  143. db ApiMapUnknown ; 19h -
  144. db ApiMapUnknown ; 1Ah -
  145. db ApiMapUnknown ; 1Bh -
  146. db ApiMapUnknown ; 1Ch -
  147. db ApiMapUnknown ; 1Dh -
  148. db ApiMapUnknown ; 1Eh -
  149. db ApiMapUnknown ; 1Fh -
  150. db ApiBufferIn ; 20h - Send datagram
  151. db ApiBufferOut ; 21h - Receive datagram
  152. db ApiBufferIn ; 22h - Send broadcast datagram
  153. db ApiBufferOut ; 23h - Receive broadcast dgram
  154. db ApiMapUnknown ; 24h -
  155. db ApiMapUnknown ; 25h -
  156. db ApiMapUnknown ; 26h -
  157. db ApiMapUnknown ; 27h -
  158. db ApiMapUnknown ; 28h -
  159. db ApiMapUnknown ; 29h -
  160. db ApiMapUnknown ; 2Ah -
  161. db ApiMapUnknown ; 2Bh -
  162. db ApiMapUnknown ; 2Ch -
  163. db ApiMapUnknown ; 2Dh -
  164. db ApiMapUnknown ; 2Eh -
  165. db ApiMapUnknown ; 2Fh -
  166. db ApiMapNone ; 30h - Add name
  167. db ApiMapNone ; 31h - Delete name
  168. db ApiMapNone ; 32h - Reset
  169. db ApiMapOut ; 33h - Adapter status
  170. db ApiMapOut ; 34h - Session status
  171. db ApiCancel ; 35h - Cancel
  172. db ApiMapNone ; 36h - Add group name
  173. db ApiMapUnknown ; 37h -
  174. db ApiMapUnknown ; 38h -
  175. db ApiMapUnknown ; 39h -
  176. db ApiMapUnknown ; 3Ah -
  177. db ApiMapUnknown ; 3Bh -
  178. db ApiMapUnknown ; 3Ch -
  179. db ApiMapUnknown ; 3Dh -
  180. db ApiMapUnknown ; 3Eh -
  181. db ApiMapUnknown ; 3Fh -
  182. db ApiMapUnknown ; 40h -
  183. db ApiMapUnknown ; 41h -
  184. db ApiMapUnknown ; 42h -
  185. db ApiMapUnknown ; 43h -
  186. db ApiMapUnknown ; 44h -
  187. db ApiMapUnknown ; 45h -
  188. db ApiMapUnknown ; 46h -
  189. db ApiMapUnknown ; 47h -
  190. db ApiMapUnknown ; 48h -
  191. db ApiMapUnknown ; 49h -
  192. db ApiMapUnknown ; 4Ah -
  193. db ApiMapUnknown ; 4Bh -
  194. db ApiMapUnknown ; 4Ch -
  195. db ApiMapUnknown ; 4Dh -
  196. db ApiMapUnknown ; 4Eh -
  197. db ApiMapUnknown ; 4Fh -
  198. db ApiMapUnknown ; 50h -
  199. db ApiMapUnknown ; 51h -
  200. db ApiMapUnknown ; 52h -
  201. db ApiMapUnknown ; 53h -
  202. db ApiMapUnknown ; 54h -
  203. db ApiMapUnknown ; 55h -
  204. db ApiMapUnknown ; 56h -
  205. db ApiMapUnknown ; 57h -
  206. db ApiMapUnknown ; 58h -
  207. db ApiMapUnknown ; 59h -
  208. db ApiMapUnknown ; 5Ah -
  209. db ApiMapUnknown ; 5Bh -
  210. db ApiMapUnknown ; 5Ch -
  211. db ApiMapUnknown ; 5Dh -
  212. db ApiMapUnknown ; 5Eh -
  213. db ApiMapUnknown ; 5Fh -
  214. db ApiMapUnknown ; 60h -
  215. db ApiMapUnknown ; 61h -
  216. db ApiMapUnknown ; 62h -
  217. db ApiMapUnknown ; 63h -
  218. db ApiMapUnknown ; 64h -
  219. db ApiMapUnknown ; 65h -
  220. db ApiMapUnknown ; 66h -
  221. db ApiMapUnknown ; 67h -
  222. db ApiMapUnknown ; 68h -
  223. db ApiMapUnknown ; 69h -
  224. db ApiMapUnknown ; 6Ah -
  225. db ApiMapUnknown ; 6Bh -
  226. db ApiMapUnknown ; 6Ch -
  227. db ApiMapUnknown ; 6Dh -
  228. db ApiMapUnknown ; 6Eh -
  229. db ApiMapUnknown ; 6Fh -
  230. db ApiMapNone ; 70h - Unlink
  231. db ApiMapUnknown ; 71h -
  232. db ApiMapNone ; 72h - Ungerman Bass Register
  233. db ApiBufferIn ; 73h - Ungerman Bass SendNmc
  234. db ApiMapNone ; 74h - Ungerman Bass Callniu
  235. db ApiMapNone ; 75h - Ungerman Bass Calladdr
  236. db ApiMapNone ; 76h - Ungerman Bass Listenaddr
  237. db ApiBufferIn ; 77h - Ungerman Bass SendPkt
  238. db ApiBufferOut ; 78h - Ungerman Bass RcvPkt
  239. db ApiBufferIn ; 79h - Ungerman Bass SendAttn
  240. db ApiBufferOut ; 7Ah - Ungerman Bass RcvAttn
  241. db ApiBufferOut ; 7Bh - Ungerman Bass Listenniu
  242. db ApiBufferOut ; 7Ch - Ungerman Bass RcvRaw
  243. db ApiBufferIn ; 7Dh - Ungerman Bass SendNmc2
  244. db ApiMapUnknown ; 7Eh -
  245. db ApiMapNone ; 7Fh - Install check
  246. ; The next table maps the (Windows/386 compatible) code from ApiMapTbl
  247. ; to the bit flags which control our entry/exit mapping.
  248. EntryExitFlags label byte
  249. db BUFF_IN+BUFF_OUT ;ApiMapUnknown
  250. db 0 ;ApiMapNone
  251. db BUFF_IN ;ApiMapIn
  252. db BUFF_OUT ;ApiMapOut
  253. db BUFF_IN+BUFF_OUT ;ApiMapInOut
  254. db BUFF_CHAIN ;ApiChainSend
  255. db BUFF_CANCEL ;ApiCancel
  256. db BUFF_IN ;ApiBufferIn
  257. db BUFF_OUT ;ApiBufferOut
  258. db BUFF_IN+BUFF_OUT ;ApiBufferInOut
  259. DXDATA ends
  260. ; -------------------------------------------------------
  261. ; CODE SEGMENT VARIABLES
  262. ; -------------------------------------------------------
  263. DXCODE segment
  264. extrn selDgroup:WORD
  265. DXCODE ends
  266. DXPMCODE segment
  267. extrn selDgroupPM:WORD
  268. DXPMCODE ends
  269. page
  270. ; ----------------------------------------------------------------------
  271. ;
  272. ; The following routines handle INT 2Ah and 5Ch interrupts that
  273. ; request NetBIOS services. Typically, these interrupts require
  274. ; that a NCB and/or buffer be copied between conventional and
  275. ; extended memory, and register values be modified due to real-
  276. ; mode/protected-mode addressing differences.
  277. ;
  278. ; (Note: this comment copied almost unchanged from DXINTR.ASM)
  279. ;
  280. ; The following conventions are used:
  281. ;
  282. ; A stack is allocated from the interrupt reflector stack for these
  283. ; routines to use. This allows nested servicing of interrupts.
  284. ; A stack frame is built in the allocated stack which contains the
  285. ; following information:
  286. ;
  287. ; original caller's stack address
  288. ; caller's original flags and general registers (in pusha form)
  289. ; caller's original segment registers (DS & ES)
  290. ; flags and general registers to be passed to interrupt routine
  291. ; (initially the same as caller's original values)
  292. ; segment registers (DS & ES) to be passed to interrupt routine
  293. ; (initially set to the Dos Extender data segment address)
  294. ;
  295. ; This stack frame is built by the routine EnterIntHandler, and its
  296. ; format is defined by the structure INTRSTACK. The stack frame is
  297. ; destroyed and the processor registers set up for return to the user
  298. ; by the function LeaveIntHandler.
  299. ;
  300. ; There are two sets of general registers and two sets of segment
  301. ; registers (DS & ES) on the stack frame. One set of register values
  302. ; has member names of the form intUserXX. The values in these stack
  303. ; frame members will be passed to the interrupt service routine when
  304. ; it is called, and will be loaded with the register values returned
  305. ; by the interrupt service routine. The other set of registers values
  306. ; has member names of the form pmUserXX. These stack frame members
  307. ; contain the original values in the registers on entry from the
  308. ; user program that called the interrupt.
  309. ;
  310. ; When we return to the original caller, we want to pass back the
  311. ; general registers as returned by the interrupt routine (and possibly
  312. ; modified by the exit handler), and the same segment registers as
  313. ; on entry, unless the interrupt routine returns a value in a segment
  314. ; register. (in this case, there must be some code in the exit routine
  315. ; to handle this). This means that when we return to the caller, we
  316. ; return the general register values from the intUserXX set of stack
  317. ; frame members, but we return the segment registers from the pmUserXX
  318. ; set of frame members. By doing it this way, we don't have to do
  319. ; any work for the case where the interrupt subfuntion doesn't require
  320. ; any parameter manipulation. NOTE however, this means that when
  321. ; manipulating register values to be returned to the user, the segment
  322. ; registers are treated opposite to the way the general registers are
  323. ; treated. For general registers, to return a value to the user,
  324. ; store it in a intUserXX stack frame member. To return a segment
  325. ; value to the user, store it in a pmUserXX stack frame member.
  326. ;
  327. ; -------------------------------------------------------
  328. subttl NetBIOS API Mapper Initialization Routine
  329. page
  330. ; -------------------------------------------------------
  331. ; NetBIOS API MAPPER INITIALIZATION ROUTINE
  332. ; -------------------------------------------------------
  333. DXPMCODE segment
  334. assume cs:DXPMCODE
  335. ;--------------------------------------------------------
  336. ; InitNetMapper -- This routine initializates the NetBIOS API mapper.
  337. ;
  338. ; Input: none
  339. ; Output: none
  340. ; Errors: none
  341. ; Uses: all registers preserved
  342. ;
  343. ; Note: This routine expects to be called late enough in the DOS
  344. ; extender initialization cycle that it can use other interrupt
  345. ; mapping functions (like INT 21h). It must be called in
  346. ; PROTECTED MODE!
  347. ; And, assumes interrupts are to be enabled.
  348. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  349. public InitNetMapper
  350. InitNetMapper proc near
  351. pusha
  352. push es
  353. ; Do an installation check before doing anything else
  354. SwitchToRealMode
  355. assume ds:DGROUP,es:DGROUP
  356. FSTI
  357. mov ax,355Ch ;make sure the Int 5Ch vector
  358. int 21h ; really points somewhere
  359. assume es:NOTHING
  360. ifdef NEC_98
  361. mov ax,es
  362. test fNHmode, 0FFh ;N/Hmode no kiriwake
  363. jz NetBios_Nmode
  364. cmp ax,60h ;Hmode default(not install)
  365. ;coading no tameni toriaezu 60h wo ireteoku node debug no tokini
  366. ;60h no ataiwo Hmode youni change surukoto!!!!!
  367. jz inm20
  368. jmp NetBio_Install
  369. NetBios_Nmode:
  370. cmp ax,60h ;Nmode default(not install)
  371. jz inm20
  372. NetBio_Install:
  373. endif ;NEC_98
  374. mov ax,es ;can't be installed if 0 vector
  375. or ax,bx
  376. jz inm20
  377. push ds
  378. pop es
  379. assume es:DGROUP
  380. mov cx,(size NCB_Struc)/2 ;build a dummy NCB with an invalid
  381. mov di,offset rgbXfrBuf1 ; 7Fh (Install) command code
  382. mov bx,di
  383. xor ax,ax
  384. cld
  385. rep stosw
  386. mov [bx].NCB_Command,Install ;issue invalid request
  387. int 5Ch
  388. xor bx,bx ;assume not installed
  389. cmp al,RC_Invalid_Cmd ;if it says invalid command, then
  390. jnz inm20 ; it must be installed
  391. dec bx ;bx !=0 means NetBIOS is installed
  392. inm20:
  393. SwitchToProtectedMode
  394. FSTI
  395. or bx,bx ;skip install if no NetBIOS
  396. jnz inm20A ;net bios is there
  397. jmp inm80 ;no NetBios
  398. inm20A:
  399. ; we need to allocate a block of memory in the low heap and copy some code
  400. ; down there which would handle the POST calls from the NetWork. It is
  401. ; necessary to have a piece in global memory do the POST handling because
  402. ; DOSX might have been swapped out by the Switcher when a POST request
  403. ; comes in.
  404. ;
  405. ; -----
  406. ; CAVEAT:
  407. ; This archaic piece of code was only necessary on the real DOSX running
  408. ; standard mode Windows 3.0. On NT, dosx is never switched out. So the
  409. ; relocation performed here could be just thrown away and replaced with a
  410. ; normal piece of RM code.
  411. ;
  412. mov bx,(SIZE_OF_GLOBAL_NET_STUB_CODE+15) SHR 4
  413. mov ax,100h ;allocate block
  414. push ds
  415. FBOP BOP_DPMI, Int31Call, FastBop
  416. jnc inm20C ;allocation succeeded
  417. jmp inm80 ;fail the initialization
  418. inm20C:
  419. xchg ax,dx
  420. mov [SegNetStubCode],dx ;save it
  421. ; DX has a selector pointing to the start of the block. Copy the stub routine
  422. ; down into the block.
  423. push es ;save
  424. mov [SelNetStubCode],ax ;save the selector value
  425. push ds ;save
  426. mov es,ax ;destination sel of the xfer
  427. push cs
  428. pop ds
  429. xor di,di ;destination offset
  430. lea si,NetBiosStubCode ;source offset of xfer
  431. mov cx,SIZE_OF_GLOBAL_NET_STUB_CODE ;size of the block
  432. cld
  433. rep movsb ;copy the block down
  434. pop ds ;restore our DS
  435. ; now copy the FAR address of the RMPostRtn into the stub code segment
  436. lea di,FarAddrOfRMPostRtn ;variable where address to be saved
  437. lea ax,NetBiosStubCode ;offset of the routine
  438. sub di,ax ;DI has the offset in the stub
  439. mov ax,segDXCode ;segment of real mode DosX
  440. mov es:[di][2],ax ;save the segment
  441. lea ax,RMPostRtn ;offset of the POST routine
  442. mov es:[di][0],ax ;save the offset
  443. ; patch the address 'NBS_Patch_CalFarAddr' with the address in DI
  444. mov si,NBS_Patch_CallFarAddr ;address to patch
  445. mov es:[si],di ;patch it.
  446. ; calculate the offset to the other flag bytes in the stub code area that
  447. ; we will have to access.
  448. lea di,fStubDelayNetPosting ;address when assembled
  449. lea ax, NetBiosStubCode ;address of start of routine
  450. sub di,ax ;address after move
  451. mov [AddrfStubDelayNetPosting],di ;save it
  452. ; patch the address 'NBS_Patch_fsDelayNetPosting' with the value in DI
  453. mov si,NBS_Patch_fsDelayNetPosting ;address to patch
  454. mov es:[si],di ;patch it.
  455. lea di,fStubTermNetRequests ;address when assembled
  456. sub di,ax ;address after move
  457. mov [AddrfStubTermNetRequest],di ;save it
  458. ; patch the address 'NBS_Patch_fsTermNetRequests' with the value in DI
  459. mov si,NBS_Patch_fsTermNetRequests ;address to patch
  460. mov es:[si],di ;patch it.
  461. pop es
  462. ; The stub routine in global memory has now been put in place to handle POST
  463. ; calls. We now need to hook the INT 2AH and 5CH PM vectors to trap the network
  464. ; calls.
  465. ; The network seems to be installed, hook the INT 2Ah & 5Ch PM vectors
  466. mov ax,352Ah ;get/store old Int 2Ah vector
  467. int 21h
  468. assume es:NOTHING
  469. mov word ptr lpfnOldInt2A,bx
  470. mov word ptr [lpfnOldInt2A+2],es
  471. mov ax,355Ch ;get/store old Int 5Ch vector
  472. int 21h
  473. mov word ptr lpfnOldInt5C,bx
  474. mov word ptr [lpfnOldInt5C+2],es
  475. push ds
  476. pop es
  477. push cs
  478. pop ds
  479. assume ds:NOTHING,es:DGROUP
  480. mov ax,252Ah ;set new Int 2Ah handler
  481. mov dx,offset DXPMCODE:PMIntr2A
  482. int 21h
  483. mov ax,255Ch ;set new Int 5Ch handler
  484. mov dx,offset DXPMCODE:PMIntr5C
  485. int 21h
  486. push es
  487. pop ds
  488. assume ds:DGROUP
  489. ; See if anybody wants to provide a different NetBIOS mapping table
  490. SwitchToRealMode
  491. assume ds:DGROUP,es:DGROUP
  492. FSTI ;don't need 'em disabled
  493. xor cx,cx ;subf'n zero
  494. mov es,cx ;preset address to copy to NULL
  495. mov di,cx
  496. mov ax,REPLACE_MAP_TABLE
  497. ; DOSX net extender API call to substitute alternate NETBIOS
  498. ; mapping table
  499. mov bx,VNETBIOS_DEV_ID ;VNETBIOS device ID
  500. int 2Fh
  501. ; ES:DI contains address of alternate mapping table or NULL
  502. mov cx,es ;Q: valid table pointer ?
  503. jcxz inm70 ;N: NULL...keep current table
  504. ;Y: copy table pointed to by es:di to table area (simple replace)
  505. mov ax,ds ; string move source (int 2F provided) table
  506. mov es,ax ; in ds:si, and destination ApiMapTbl in the
  507. mov ds,cx ; data segment now in es:di
  508. mov si,di
  509. mov di,offset ApiMapTbl ;ptr to table
  510. mov cx,64 ;copy over 128 byte table
  511. cld
  512. rep movsw
  513. mov ds,ax ;recall data segment
  514. inm70:
  515. SwitchToProtectedMode
  516. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  517. FSTI
  518. clc
  519. jmp short inm90
  520. inm80:
  521. stc ;tell caller we didn't install
  522. inm90:
  523. pop es
  524. popa
  525. ret
  526. InitNetMapper endp
  527. ;-----------------------------------------------------------------------------
  528. ; NetBiosStubCode
  529. ;
  530. ; DESCRIPTION This routine is actually relocated to a block of Global Memory
  531. ; obtained from the Switcher. It handles the POST calls from the
  532. ; NETBIOS layer. If DosX has been swapped out, fStubDelayPosting
  533. ; would be true and this routine would set a flag in the HCB
  534. ; to imply that the POSTing must be done. If DosX is active, this
  535. ; routine will call off to the RMPostRtn in DosX via a far call
  536. ; pointer.
  537. ;
  538. ; ENTRY:
  539. ; ES:BX - HCB
  540. ;
  541. ; EXIT:
  542. ; All registers preserved but for flags.
  543. ;
  544. ; USES:
  545. ; Flags
  546. ;
  547. ; NOTE:
  548. ; This routine will actually be copied to a global memory stub segment
  549. ; and will execute from there. However, since the routine would be moved
  550. ; while we are in protected mode, the routine is being assembled in the
  551. ; protected mode code segment.
  552. ;-----------------------------------------------------------------------------
  553. NetBiosStubCode proc far
  554. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  555. FCLI ;just to be sure
  556. ; Don't post anything if in the process of terminating
  557. ;-----------------------------------------------------------------------------
  558. ; The following instruction will have to be patched after the move:
  559. ;
  560. ; cmp cs:[fStubTermNetRequests],1
  561. ;
  562. ; we will mark the place that has to be patched.
  563. ;-----------------------------------------------------------------------------
  564. db 2eh, 80h, 3eh ;CS: CMP BYTE PTR
  565. NBS_Patch_fsTermNetRequests equ $ - NetBiosStubCode
  566. dw ? ;address to compare
  567. db 1 ;value to comapare
  568. ;-----------------------------------------------------------------------------
  569. je NBSC_post_done
  570. ; Check if posting should be delayed
  571. ;-----------------------------------------------------------------------------
  572. ; The following instruction will have to be patched after the move:
  573. ;
  574. ; cmp cs:[fStubDelayNetPosting],0;Q: delay postings ?
  575. ;
  576. ; we will mark the place that has to be patched.
  577. ;-----------------------------------------------------------------------------
  578. db 2eh, 80h, 3eh ;CS: CMP BYTE PTR
  579. NBS_Patch_fsDelayNetPosting equ $ - NetBiosStubCode
  580. dw ? ;address to compare
  581. db 0 ;value to comapare
  582. ;-----------------------------------------------------------------------------
  583. je NBSC_post_no_delay ;N: don't delay this posting
  584. ; we can do no posting. DosX has been swapped out. Set a flag in the HCB to
  585. ; imply that POSTing must be done later.
  586. or byte ptr es:[bx.HCB_Flags],HCB_DELAY ;Y: mark as delayed
  587. jmp short NBSC_post_done
  588. NBSC_post_no_delay:
  589. ;-----------------------------------------------------------------------------
  590. ; call off to RMPostRtn in DosX. We will have to patch the following
  591. ; instruction after the move.
  592. ;
  593. ; call cs:[FarAddrOfRMPostRtn] ;call routine in DosX proper
  594. ;
  595. ; we will mark the place to match
  596. ;-----------------------------------------------------------------------------
  597. db 2eh,0ffh,1eh ;CALL CS: DWORD PTR
  598. NBS_Patch_CallFarAddr equ $ - NetBiosStubCode
  599. dw ? ;call far address
  600. ;------------------------------------------------------------------------------
  601. NBSC_post_done:
  602. riret
  603. NetBiosStubCode endp
  604. ;----------------------------------------------------------------------------;
  605. ; allocate space for some of the variables that the Stub Code uses. These ;
  606. ; will be filled in by PMODE code in the DosX. ;
  607. ;----------------------------------------------------------------------------;
  608. fStubTermNetRequests db 0 ;DosX is terminating
  609. fStubDelayNetPosting db 0 ;delay posting, DosX swapped
  610. FarAddrOfRMPostRtn dd ? ;address of the actual POST rtn
  611. SIZE_OF_GLOBAL_NET_STUB_CODE equ $ - NetBiosStubCode
  612. ;-----------------------------------------------------------------------------;
  613. DXPMCODE ends
  614. ; -------------------------------------------------------
  615. subttl NetBIOS API Mapper Termination Routine
  616. page
  617. ; -------------------------------------------------------
  618. ; NetBIOS API MAPPER TERMINATION ROUTINE
  619. ; -------------------------------------------------------
  620. DXCODE segment
  621. assume cs:DXCODE
  622. ; TermNetMapper -- This routine is called when the 286 DOS extender
  623. ; is winding down so that any pending network requests from the
  624. ; protected mode application can be canceled.
  625. ;
  626. ; Input: none
  627. ; Output: none
  628. ; Errors: none
  629. ; Uses: ax,bx,cx,dx,si,di,es
  630. ;
  631. ; Note: This routine must be called in REAL MODE!
  632. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  633. public TermNetMapper
  634. TermNetMapper proc near
  635. ; set a flag in the stub code to imply that DosX is terminating and no more
  636. ; POSTs to be done.
  637. mov di,[SelNetStubCode] ;selector for the stub area
  638. or di,di ;is global heap in place ?
  639. jnz @f ;yes.
  640. ret
  641. @@:
  642. SwitchToProtectedMode
  643. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  644. push es
  645. mov es,di
  646. assume es:nothing
  647. ; get the address of the flag byte fStubTermNetRequest after the block was
  648. ; relocated
  649. mov di,[AddrfStubTermNetRequest]
  650. ; ES:DI has the flag byte address. Set the flag
  651. mov byte ptr es:[di],1 ;set flag to delay posting
  652. pop es
  653. assume es:dgroup
  654. ; terminating the net driver interface...no more postings allowed
  655. FSTI
  656. mov cx,size NCB_Struc / 2
  657. mov si,offset Cancel_NCB ;cancel control block buffer
  658. mov di,si
  659. xor ax,ax ;zero fill structure
  660. cld
  661. rep stosw
  662. mov ds:[si.NCB_Command],Cancel ;Cancel command NCB
  663. ; We don't need to release the NCB/buffer(s) from the low heap because
  664. ; the entire low heap will soon be released.
  665. ; Search low heap list looking for copy of target NCB
  666. mov cx,HCB_List
  667. mov di,HCB_Header_Size ;offset of NCB in low heap block
  668. term_next:
  669. jcxz term_done
  670. mov ax,cx
  671. call GetSegmentAddress
  672. add dx,di
  673. adc bx,0 ;BX:DX = lma of low target NCB
  674. call Lma2SegOff ;BX:DX = normalized SEG:OFF
  675. dec bx ;return the same slightly unnormalized
  676. add dx,10h ; SEG:OFF that was used initially
  677. mov ds:[si.NCB_Buffer_Seg],bx ; point to NCB to cancel
  678. mov ds:[si.NCB_Buffer_Off],dx
  679. SwitchToRealMode ;also disables ints for us
  680. assume ds:DGROUP,es:DGROUP
  681. mov bx,si ;ES:BX points to cancelling NCB
  682. pushf
  683. call lpfnRmNetIsr ;do the cancel call
  684. ; return code in AL
  685. SwitchToProtectedMode
  686. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  687. FSTI
  688. mov es,cx
  689. mov cx,es:[di.HCB_Next]
  690. jmp short term_next
  691. term_done:
  692. SwitchToRealMode
  693. assume ds:DGROUP,es:DGROUP
  694. FSTI
  695. ret
  696. TermNetMapper endp
  697. ; -------------------------------------------------------
  698. DXCODE ends
  699. ; -------------------------------------------------------
  700. subttl NetBIOS API Int 2Ah Mapper Interrupt Hook
  701. page
  702. ; -------------------------------------------------------
  703. ; NetBIOS API INT 2Ah MAPPER INTERRUPT HOOK
  704. ; -------------------------------------------------------
  705. DXPMCODE segment
  706. assume cs:DXPMCODE
  707. ; -------------------------------------------------------
  708. ; PMIntr2A -- This routine traps Int 2Ah requests from a
  709. ; protected mode application. NetBIOS requests (ah =
  710. ; 1 or 4) are passed on to the Int 5Ch handler for
  711. ; further processing. Other requests are passed on
  712. ; to the next Int 2Ah handler in the interrupt chain.
  713. ;
  714. ; Input: User regs at time of interrupt
  715. ; Output: none
  716. ; Errors: none
  717. ; Uses: none
  718. ;
  719. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  720. public PMIntr2A
  721. PMIntr2A proc near
  722. cld ;cya...
  723. cmp ah,1 ;we only need to map the Int 2Ah
  724. jz @f ; ah = 1 & 4 services--if it's
  725. cmp ah,4 ; not one of those, just pass it
  726. jz @f ; on down the chain...
  727. sub sp,4 ; build a stack frame
  728. push bp
  729. mov bp,sp
  730. push ax
  731. push ds
  732. mov ds,selDgroupPM
  733. assume ds:DGROUP
  734. mov ax,word ptr [lpfnOldInt2A+2] ; store previous INT 2A
  735. mov word ptr [bp+4],ax ; handler
  736. mov ax,word ptr [lpfnOldInt2A]
  737. mov word ptr [bp+2],ax
  738. pop ds
  739. assume ds:NOTHING
  740. pop ax
  741. pop bp ; SS:SP -> previous handler
  742. ;let someone else deal with it
  743. retf ; (most likely PMIntrReflector)
  744. @@:
  745. if PM_NCB_HANDLING
  746. ;
  747. ; if this is NT then we have decided we are making a NetBIOS call (es:bx points
  748. ; to an NCB in protect-mode memory). INT 0x2A, ah=1 or ah=4 just ends up calling
  749. ; the 0x5C entry point; ah is returned as 1 or 0, depending on whether an error
  750. ; is returned from 0x5C or not
  751. ;
  752. push dx
  753. mov dl,2ah
  754. else
  755. push bx ;save caller's bx
  756. mov bx,4*2Ah ;indicate we came from int 2A handler
  757. endif ; PM_NCB_HANDLING
  758. jmp short DoNetRqst ;int 2Ah/5Ch common code
  759. PMIntr2A endp
  760. ; -------------------------------------------------------
  761. subttl NetBIOS API Int 5Ch Mapper Interrupt Hook
  762. page
  763. ; -------------------------------------------------------
  764. ; NetBIOS API INT 5Ch MAPPER INTERRUPT HOOK
  765. ; -------------------------------------------------------
  766. ; PMIntr5C -- This routine maps Int 5Ch (and selected Int 2Ah)
  767. ; NetBIOS requests between a protected mode application, and
  768. ; the real mode interrupt handler.
  769. ;
  770. ; Input: User regs at time of interrupt
  771. ; Output: regs as returned by interrupt handler
  772. ; Errors:
  773. ; Uses: none
  774. ;
  775. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  776. public PMIntr5C
  777. PMIntr5C proc near
  778. if PM_NCB_HANDLING
  779. ;
  780. ; we no longer want to make the call through the real-mode handler, since all
  781. ; it does is make the BOP
  782. ;
  783. cld ; just in case
  784. push dx
  785. mov dl,5ch
  786. DoNetRqst:
  787. ;
  788. ; Do a sync/async NETBIOS presence check. Don't BOP for this simple case.
  789. ; Also don't do the async call because Delrina WinFax Pro hasn't initialized
  790. ; The post address in the NCB.
  791. ;
  792. cmp byte ptr es:[bx],7fh ; sync NETBIOS presence check
  793. je skip_bop
  794. cmp byte ptr es:[bx],0ffh ; async NETBIOS presence check
  795. je skip_bop
  796. ifdef WOW_x86
  797. .386p
  798. push ds
  799. mov ds,selDgroupPM
  800. assume ds:DGROUP
  801. FBOP BOP_REDIR, SVC_NETBIOS5C, FastBop
  802. pop ds
  803. .286p
  804. else
  805. SVC SVC_NETBIOS5C
  806. endif ; WOW_x86
  807. cmp dl,2ah
  808. jne @f
  809. ;
  810. ; this was a 0x2A call. Return ah = 0 if NetBIOS returned al = 0, else return
  811. ; ah = 1
  812. ;
  813. sub ah,ah
  814. or al,al
  815. jz @f
  816. inc ah
  817. @@: pop dx
  818. riret
  819. skip_bop:
  820. mov al,3 ; INVALID COMMAND error
  821. mov es:[bx].ncb_retcode,al ; returned in NCB_RETCODE && al
  822. mov es:[bx].ncb_cmd_cplt,al ; and NCB_CMD_CPLT
  823. pop dx
  824. riret
  825. else
  826. cld ;cya...
  827. push bx ;save caller's bx
  828. mov bx,4*5Ch ;indicate we came from int 5C
  829. DoNetRqst label near ;start of int 2Ah/5Ch common code
  830. push ax ;move the address of the
  831. push ds ; proper real mode interrupt
  832. mov ds,selDgroupPM ; handler (2A or 5C) to global var
  833. assume ds:DGROUP
  834. push es
  835. mov ax,SEL_RMIVT OR STD_RING
  836. mov es,ax
  837. mov ax,word ptr es:[bx]
  838. mov word ptr lpfnRmNetIsr,ax
  839. mov ax,word ptr es:[bx+2]
  840. mov word ptr [lpfnRmNetIsr+2],ax
  841. pop es
  842. pop ds ;restore caller's environment
  843. assume ds:NOTHING
  844. pop ax
  845. pop bx
  846. call EnterIntHandler ;build an interrupt stack frame
  847. assume ds:DGROUP,es:NOTHING
  848. FSTI ;-----------------------------------------------
  849. ; Allocate space in the low heap for the HCB/NCB and maybe a buffer
  850. xor dx,dx
  851. mov cx,HCB_SIZE ;DX:CX = # bytes low heap required
  852. call GetEntryExitFlags ;AX=Entry flags / ES:BX -> PM NCB
  853. test al,BUFF_IN+BUFF_OUT+BUFF_CHAIN ;need to allocate a low buffer?
  854. jz i5c_alloc
  855. ;
  856. ; RLF 06/09/93
  857. ;
  858. ; from the command type, we think we have a buffer address and size. If either
  859. ; of these is 0, then we actually don't have a buffer; skip it
  860. ;
  861. mov ah,al ; set default no buffer
  862. and al,not (BUFF_IN or BUFF_OUT)
  863. mov dx,es:[bx.NCB_Buffer_Off]
  864. or dx,es:[bx.NCB_Buffer_Seg]
  865. jz i5c_alloc
  866. mov dx,es:[bx.NCB_Length]
  867. or dx,dx
  868. jz i5c_alloc
  869. xor dx,dx ; restore dx to 0
  870. mov al,ah ; restore buffer flags
  871. add cx,es:[bx.NCB_Length] ;if so, add in it's length
  872. adc dx,0
  873. add cx,1fh ;allow space to align buffer
  874. adc dx,0 ; on a paragraph boundry
  875. and cx,not 0fh
  876. test al,BUFF_CHAIN ;a 2nd weird-o buffer?
  877. jz i5c_alloc
  878. add cx,word ptr es:[bx.NCB_CallName] ;yes, add in it's len also
  879. adc dx,0
  880. add cx,1fh ;allow space to align buffer
  881. adc dx,0 ; on a paragraph boundry
  882. and cx,not 0fh
  883. i5c_alloc:
  884. push ax ;save entry/exit flags
  885. FCLI ;treat allocate as critical section ------------
  886. push bx
  887. mov bx,cx ;loword length
  888. mov ax,dx ;hiword length
  889. add bx,15 ;round up
  890. shr bx,4 ;discard last 4 bits
  891. and ax,0fh ;discarded bits were 0
  892. shl al,4 ;get it in MS nibble
  893. or bh,al ;BX has the size in paragraphs
  894. mov ax,100h ;allocate block
  895. push ds
  896. FBOP BOP_DPMI, Int31Call, FastBop
  897. pop bx
  898. jnc @f ; HCB/NCB and maybe buffer
  899. Debug_Out "Low heap allocation failed!"
  900. pop ax ;clear stack
  901. mov byte ptr [bp].intUserAX,RC_Resources
  902. mov es:[bx.NCB_RetCode],RC_Resources
  903. mov es:[bx.NCB_Cmd_Cplt],RC_Resources
  904. jmp i5c_done
  905. @@:
  906. mov ax,dx ;get the selector
  907. ; Copy the PM NCB to the low heap and add our extra HCB fields
  908. mov es,ax
  909. xor di,di ;es:di -> low heap block
  910. cld
  911. stosw ;HCB_Handle
  912. mov ax,bx
  913. stosw ;HCB_PM_NCB_Off
  914. mov ax,[bp].pmUserES
  915. stosw ;HCB_PM_NCB_Seg
  916. mov ax,HCB_List
  917. stosw ;HCB_Next
  918. xor ax,ax
  919. stosw ;HCB_Flags = 0
  920. mov HCB_List,es ;link HCB to head of list
  921. FSTI ;-----------------------------------------------
  922. push ds
  923. mov ds,[bp].pmUserES
  924. assume ds:NOTHING
  925. errnz <size NCB_Struc and 1> ;if odd # bytes, can't just movsw
  926. mov si,bx ;ES:DI->low NCB, DS:SI->PM NCB
  927. mov cx,size NCB_Struc / 2
  928. rep movsw
  929. pop ds
  930. assume ds:DGROUP
  931. ; Update the interrupt handler's registers to point to the low NCB
  932. mov ax,es
  933. call GetSegmentAddress
  934. add dx,HCB_Header_Size
  935. adc bx,0 ;BX:DX = lma of low NCB
  936. pop ax ;refresh entry flags
  937. push ax
  938. push bx ;save lma of NCB
  939. push dx
  940. call Lma2SegOff ;BX:DX = normalized SEG:OFF of low NCB
  941. dec bx ;we want to do a negative offset on the
  942. add dx,10h ; NCB segment, so un-normalize it some
  943. mov [bp].intUserES,bx ;point int handler's ES:BX to low NCB
  944. mov [bp].intUserBX,dx
  945. ; If this is a cancel request, find the target NCB in the low heap
  946. test al,BUFF_CANCEL ;cancel request?
  947. jz i5c_not_cancel
  948. mov di,HCB_Header_Size ;ES:DI -> low heap Cancel NCB
  949. FCLI ;don't want list changing while looking --------
  950. call FindTargetNCB ;BX:DX = SEG:OFF of target NCB
  951. FSTI ;-----------------------------------------------
  952. if DEBUG ;------------------------------------------------------------
  953. jnc @f
  954. Debug_Out "FindTargetNCB didn't!"
  955. @@:
  956. endif ;DEBUG --------------------------------------------------------
  957. jc @f
  958. mov es:[di.NCB_Buffer_Off],dx ;point cancel NCB to low
  959. mov es:[di.NCB_Buffer_Seg],bx ; heap target NCB
  960. @@:
  961. i5c_not_cancel:
  962. pop dx ;restore lma of NCB
  963. pop bx
  964. ; If necessary, update NCB buffer pointer(s) and copy buffer(s) to low heap
  965. pop ax ;recover entry flags
  966. test al,BUFF_IN+BUFF_OUT+BUFF_CHAIN ;a buffer to point to?
  967. jnz @f
  968. jmp i5c_no_buf_in
  969. @@:
  970. add dx,size NCB_Struc + 0fh ;get lma of buffer, rounded up
  971. adc bx,0 ; to the next higher paragraph
  972. and dx,not 0fh
  973. push ds
  974. mov ds,[bp].pmUserES
  975. mov si,[bp].pmUserBX ;DS:SI -> PM NCB
  976. assume ds:NOTHING
  977. push bx
  978. push dx
  979. call Lma2SegOff ;BX:DX = SEG:OFF of low buffer
  980. mov di,HCB_Header_Size ;ES:DI -> low NCB
  981. mov es:[di.NCB_Buffer_Off],dx
  982. mov es:[di.NCB_Buffer_Seg],bx
  983. pop dx
  984. pop bx
  985. test al,BUFF_IN+BUFF_CHAIN ;actually need to copy buffer?
  986. jz i5c_buf_in_done
  987. mov cx,ds:[si.NCB_Length] ;CX = buffer len
  988. lds si,dword ptr ds:[si.NCB_Buffer_Off] ;DS:SI -> buffer
  989. push ax
  990. xor ax,ax
  991. call CopyBuffer ;copies DS:SI to lma BX:DX len CX
  992. pop ax
  993. test al,BUFF_CHAIN
  994. jz i5c_buf_in_done
  995. add dx,es:[di.NCB_Length] ;BX:DX = lma of 2nd low heap buffer
  996. adc bx,0
  997. add dx,0fh
  998. adc bx,0
  999. and dx,not 0fh
  1000. push bx ;update low heap NCB with SEG:OFF
  1001. push dx ; of 2nd buffer
  1002. call Lma2SegOff
  1003. mov word ptr es:[di.NCB_CallName+2],dx ;2nd buffer loc stored
  1004. mov word ptr es:[di.NCB_CallName+4],bx ; at callname + 2
  1005. pop dx
  1006. pop bx
  1007. mov ds,[bp].pmUserES
  1008. mov si,[bp].pmUserBX ;DS:SI -> PM NCB
  1009. mov cx,word ptr ds:[si.NCB_CallName] ;CX = buffer len
  1010. lds si,dword ptr ds:[si.NCB_CallName+2] ;DS:SI -> buffer
  1011. xor ax,ax
  1012. call CopyBuffer ;copies DS:SI to lma BX:DX len CX
  1013. i5c_buf_in_done:
  1014. pop ds
  1015. assume ds:DGROUP
  1016. i5c_no_buf_in:
  1017. ; Switch to real mode, and load the mapped real mode registers.
  1018. SwitchToRealMode ;also disables ints
  1019. assume ss:DGROUP
  1020. ; --------------- START OF REAL MODE CODE ------------------------------
  1021. pop es
  1022. pop ds
  1023. assume ds:NOTHING,es:NOTHING
  1024. popa ;restore all the other registers
  1025. ; If this is a NoWait command, hook the mapped NCB to point to our post
  1026. ; routine. At this time ES:BX -> mapped NCB
  1027. test byte ptr es:[bx.NCB_Command],NoWait
  1028. jz @f
  1029. push ax ;save
  1030. ;
  1031. ; RLF 06/09/93
  1032. ;
  1033. ; although this is an async command, there may be no post address (app just
  1034. ; polls return code until it goes non-0xff). In this case, don't set up our
  1035. ; asynchronous notification routine
  1036. ;
  1037. mov ax,es:[bx.NCB_Post_Off]
  1038. or ax,es:[bx.NCB_Post_Seg]
  1039. jz no_post_routine
  1040. assume ss:DGROUP ;ss has DOSX's data seg
  1041. mov ax,[SegNetStubCode] ;get segment of stub code
  1042. ; the address of the stub code that will handle the POST is AX:0. Save this
  1043. ; in the HCB.
  1044. mov word ptr es:[bx.NCB_Post_Off],0
  1045. mov word ptr es:[bx.NCB_Post_Seg],ax
  1046. no_post_routine:
  1047. pop ax ;restore
  1048. @@:
  1049. or byte ptr es:[bx.HCB_FLAGS],HCB_ISSUED
  1050. ; Invoke the appropriate real mode interrupt handler (2Ah or 5Ch),
  1051. ; reestablish our stack frame with the handler's returned registers,
  1052. ; and then back to protected mode
  1053. call lpfnRmNetIsr ;exectue real mode interrupt handler
  1054. pushf
  1055. FCLI
  1056. pusha
  1057. push ds
  1058. push es
  1059. mov bp,sp ;restore stack frame pointer
  1060. mov ax,es:[bx.HCB_Handle] ;recover selector to current NCB/buff
  1061. push ax
  1062. SwitchToProtectedMode
  1063. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1064. ; --------------- START OF PROTECTED MODE CODE -------------------------
  1065. ; With some network drivers, and some NoWait commands, the operation may
  1066. ; get 'posted' even before the driver IRETs from the issue call. If this
  1067. ; has happened, the HCB_POSTED flag will be set. In this case, the caller's
  1068. ; NCB and (possibly) buffer has already been updated, so we just discard
  1069. ; the low heap block and exit. If the operation hasn't been posted already,
  1070. ; we copy back the updated NCB info, and maybe a buffer. Note that interrupts
  1071. ; are disabled, so we don't get 'posted' half way through this operation--
  1072. ; that would be bad.
  1073. pop ax ;handle (selector) of low heap block
  1074. mov es,ax
  1075. mov di,HCB_Header_Size ;es:di -> low heap NCB
  1076. test byte ptr es:[di.HCB_Flags],HCB_POSTED ;already posted?
  1077. jnz i5c_release ; yes, just discard
  1078. and byte ptr es:[di.HCB_Flags],not HCB_ISSUED ;so post rtn knows
  1079. ;we updated already
  1080. push ax ;save handle for later
  1081. call UpdateNCB ;update the caller's NCB
  1082. call GetEntryExitFlags ;AX=Exit Flags / ES:BX->PM NCB
  1083. test es:[bx.NCB_Command],NoWait ;don't copy buff now if NoWait
  1084. jnz i5c_no_buf_out
  1085. test al,BUFF_OUT
  1086. jz i5c_no_buf_out
  1087. ;
  1088. ; RLF 06/09/93
  1089. ;
  1090. ; although the flags for this command say we have an output buffer, we may
  1091. ; not have one - address or length is 0; check it out
  1092. ;
  1093. mov ax,es:[bx.NCB_Buffer_Off]
  1094. or ax,es:[bx.NCB_Buffer_Seg]
  1095. jz i5c_no_buf_out
  1096. mov ax,es:[bx.NCB_Length]
  1097. or ax,ax
  1098. jz i5c_no_buf_out
  1099. pop ax ;handle to low block back
  1100. push ax
  1101. call CopyBufferOut ;copy low heap buffer to pm app buffer
  1102. i5c_no_buf_out:
  1103. ; If this was a Wait operation (or NoWait that failed), we are finished with
  1104. ; the low heap block and can release it now.
  1105. pop ax ;recover handle to low heap block
  1106. test es:[bx.NCB_Command],NoWait ;if Wait, go release now
  1107. jz i5c_release
  1108. cmp es:[bx.NCB_RetCode],RC_Pending
  1109. jz i5c_done
  1110. ; Most NetBIOS implementations seem to (correctly) set the RetCode to
  1111. ; RC_Pending on NoWait requests. However, it seems that some Novell
  1112. ; NetBIOS implementations can return RetCode == 00 but Cmd_Cplt ==
  1113. ; RC_Pending (FFh). So, if it is a NoWait request, and RetCode isn't
  1114. ; Pending, also check the Cmd_Cplt code.
  1115. cmp es:[bx.NCB_Cmd_Cplt],RC_Pending
  1116. jz i5c_done
  1117. Debug_Out "NoWait cmd with non Pending retcode!"
  1118. i5c_release:
  1119. push ds ;make sure es != low heap block sel
  1120. pop es ; (else FreeLowBlock will GP fault)
  1121. call DeLink ;DeLink HCB/NCB/Buffers from lnk list
  1122. push dx
  1123. mov dx,ax ;selector to free
  1124. mov ax,101h ;free block
  1125. push ds
  1126. FBOP BOP_DPMI, Int31Call, FastBop
  1127. pop dx
  1128. ; Finished! (at least for now) Restore caller's regs/stack and return
  1129. i5c_done:
  1130. mov ax,[bp].pmUserBX ;restore possibly modified BX to
  1131. mov [bp].intUserBX,ax ; PM NCB offset
  1132. call LeaveIntHandler
  1133. riret
  1134. endif ; if PM_NCB_HANDLING
  1135. PMIntr5C endp
  1136. ; -------------------------------------------------------
  1137. DXPMCODE ends
  1138. ; -------------------------------------------------------
  1139. subttl NetBIOS API Mapper Post Routine
  1140. page
  1141. ; -------------------------------------------------------
  1142. ; NetBIOS API MAPPER POST ROUTINE
  1143. ; -------------------------------------------------------
  1144. ;*******************************************************************************
  1145. ;*
  1146. ;* The code from here on down is only used if we are switching between real
  1147. ;* and protect mode when making NetBIOS requests. It is ifdef'd out for WOW
  1148. ;* because we now BOP the NetBIOS requests without switching modes
  1149. ;*
  1150. ;******************************************************************************/
  1151. ;ife PM_NCB_HANDLING
  1152. DXCODE segment
  1153. assume cs:DXCODE
  1154. ; -------------------------------------------------------
  1155. ; RMPostRtn -- This REAL MODE routine is invoked by the network
  1156. ; software when a NoWait NetBIOS command completes. This
  1157. ; routine must update the applications copy of the NCB,
  1158. ; possibly copy a buffer of data to the application, and
  1159. ; possibly invoke the application's own post routine.
  1160. ;
  1161. ; Note, this will now be called when it is OK to POST the request
  1162. ; back to the application. The Stub Code in global mrmory makes
  1163. ; sure that this is OK to do.
  1164. ;
  1165. ; Input:
  1166. ; Output:
  1167. ; Errors:
  1168. ; Uses:
  1169. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1170. public RMPostRtn
  1171. RMPostRtn proc far
  1172. FCLI ;just to be sure
  1173. cld ;cya...
  1174. push ax
  1175. push bx
  1176. push es
  1177. push ds ; NBP assumes ds saved, greaseballs
  1178. mov ds,selDgroup
  1179. assume ds:DGROUP
  1180. ; Allocate a new stack frame, and then switch to the reflector stack
  1181. ; frame.
  1182. mov regUserSP,sp
  1183. mov regUSerSS,ss
  1184. mov ss,selDgroup
  1185. mov sp,pbReflStack
  1186. sub pbReflStack,CB_STKFRAME ;adjust pointer to next stack frame
  1187. FIX_STACK
  1188. push regUserSS ;save current stack loc on our stack
  1189. push regUserSP ; so we can restore it later
  1190. push es:[bx.HCB_Handle] ;selector to low heap block
  1191. ; We are now running on our own stack, so we can switch into protected mode.
  1192. SwitchToProtectedMode ;destroys ax
  1193. ; --------------- START OF PROTECTED MODE CODE -------------------------
  1194. pop ax ;ax = selector to low heap block
  1195. call NetBiosPostRoutine ;do the actual posting
  1196. pop regUserSP ;recover previous stack location
  1197. pop regUserSS
  1198. SwitchToRealMode ; Switch back to real mode.
  1199. ; --------------- START OF REAL MODE CODE ------------------------------
  1200. ; Switch back to the original stack, deallocate the interrupt stack frame,
  1201. ; and return to the network software
  1202. CHECK_STACK
  1203. mov ss,regUserSS
  1204. mov sp,regUserSP
  1205. add pbReflStack,CB_STKFRAME
  1206. pop ds ; give ds back to NBP/XNS
  1207. pop es
  1208. pop bx
  1209. pop ax
  1210. ret
  1211. RMPostRtn endp
  1212. DXCODE ends
  1213. ; -------------------------------------------------------
  1214. subttl NetBIOS API Mapper Utility Routines
  1215. page
  1216. ; -------------------------------------------------------
  1217. ; NetBIOS API MAPPER UTILITY ROUTINES
  1218. ; -------------------------------------------------------
  1219. DXPMCODE segment
  1220. assume cs:DXPMCODE
  1221. ; -------------------------------------------------------
  1222. ; NetBiosPostRoutine -- local routine
  1223. ; This PROTECT MODE routine is called when the network
  1224. ; software completes a NoWait NetBIOS command. This
  1225. ; routine must update the applications copy of the NCB,
  1226. ; possibly copy a buffer of data to the application, and
  1227. ; possibly invoke the application's own post routine.
  1228. ;
  1229. ; Input: ax --> selector to low heap block
  1230. ; Output:
  1231. ; Errors:
  1232. ; Uses: ax,bx,es
  1233. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1234. public NetBiosPostRoutine
  1235. NetBiosPostRoutine proc near
  1236. IFNDEF WOW_x86
  1237. pusha
  1238. else
  1239. .386p
  1240. pushad
  1241. push fs
  1242. push gs
  1243. .286p
  1244. endif
  1245. ; Update the protected mode copy of the NCB and copy buffer if required
  1246. push ax ;handle (selector) of low heap block
  1247. call UpdateNCB ;always update the caller's NCB
  1248. mov es,ax
  1249. mov bx,HCB_Header_Size ;ES:BX -> low heap NCB
  1250. les bx,dword ptr es:[bx.HCB_PM_NCB_Off] ;ES:BX -> PM NCB
  1251. call GetExitFlags2 ;AX=Exit Flags
  1252. test al,BUFF_OUT
  1253. jz postsub_no_buf
  1254. ;
  1255. ; RLF 06/09/93
  1256. ;
  1257. ; once more unto the breach dear friends: although we think this command has
  1258. ; an output buffer, the app may think otherwise; let's check...
  1259. ;
  1260. mov ax,es:[bx.NCB_Buffer_Off]
  1261. or ax,es:[bx.NCB_Buffer_Seg]
  1262. jz postsub_no_buf
  1263. mov ax,es:[bx.NCB_Length]
  1264. or ax,ax
  1265. jz postsub_no_buf
  1266. pop ax ;handle to low block back
  1267. push ax
  1268. call CopyBufferOut ;copy low heap buffer to pm app buffer
  1269. postsub_no_buf:
  1270. ; Release the low heap space, unless the HCB_ISSUED flag is set (meaning
  1271. ; that the net driver called us before returning from the initial Int 5Ch).
  1272. ; In that case, the low heap block will be released by the Int 5Ch mapper.
  1273. pop ax ;recover handle to low heap block
  1274. push ax
  1275. push es
  1276. mov es,ax
  1277. mov di,HCB_Header_Size
  1278. or byte ptr es:[di.HCB_Flags],HCB_POSTED ;mark as posted
  1279. pop es
  1280. ; Invoke the user's PM post routine, if there is one - AL=retcode, ES:BX->NCB
  1281. mov ax,es:[bx.NCB_Post_Off] ;did user specify a post routine?
  1282. or ax,es:[bx.NCB_Post_Seg]
  1283. jnz @f
  1284. jmp postsub_done
  1285. @@:
  1286. mov [NBPSp],sp
  1287. rpushf ;build iret frame for user's
  1288. push cs ; routine to return to us
  1289. push offset postsub_ret
  1290. mov al,es:[bx.NCB_RetCode] ;pass ret code in al
  1291. push es:[bx.NCB_Post_Seg] ;invoke the user's post routine
  1292. push es:[bx.NCB_Post_Off]
  1293. retf
  1294. ; PM app's post routine returns here when finished
  1295. postsub_ret:
  1296. mov ax,SEL_DXDATA OR STD_RING
  1297. mov ds,ax
  1298. mov sp,[NBPSp]
  1299. postsub_done:
  1300. pop ax
  1301. mov es,ax
  1302. test byte ptr es:[di.HCB_Flags],HCB_ISSUED ;still in Int 5C code?
  1303. jnz postsub_no_release ; yes, don't release
  1304. push ds ;make sure es != low heap block sel
  1305. pop es ; (else FreeLowBlock will GP fault)
  1306. call DeLink ;DeLink HCB/NCB/Buffers from lnk list
  1307. push dx
  1308. mov dx,ax ;selector to free
  1309. mov ax,101h ;free block
  1310. push ds
  1311. FBOP BOP_DPMI, Int31Call, FastBop
  1312. pop dx
  1313. postsub_no_release:
  1314. IFNDEF WOW_x86
  1315. popa
  1316. ELSE
  1317. .386p
  1318. pop gs
  1319. pop fs
  1320. popad
  1321. .286p
  1322. ENDIF
  1323. ret
  1324. NetBiosPostRoutine endp
  1325. ; -------------------------------------------------------
  1326. ; DelayNetPostings -- This function is called when NetBIOS completions
  1327. ; are to be delayed. We simply set a flag that causes the async
  1328. ; post routine not to post to the application.
  1329. ;
  1330. ; Input: none
  1331. ; Output: none
  1332. ; Errors: none
  1333. ; Uses: none
  1334. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1335. public DelayNetPosting
  1336. DelayNetPosting proc near
  1337. ; Make sure posting is delayed. We need to set a flag in the StubCode area.
  1338. push es ;save
  1339. push di
  1340. mov di,[SelNetStubCode] ;selector for the stub area
  1341. or di,di ;did we copy to global memory ?
  1342. jz DelayNetPostingRet ;no, nothing to do.
  1343. mov es,di
  1344. ; get the address of the flag byte fStubDelayNetPosting after the block was
  1345. ; relocated
  1346. mov di,[AddrfStubDelayNetPosting]
  1347. ; ES:DI has the flag byte address. Set the flag
  1348. mov byte ptr es:[di],1 ;set flag to delay posting
  1349. DelayNetPostingRet:
  1350. pop di
  1351. pop es ;restore
  1352. ret
  1353. DelayNetPosting endp
  1354. ; -------------------------------------------------------
  1355. ; ResumeNetPostings -- This function is called when completed NetBIOS
  1356. ; postings can be resumed to the application. We traverse the
  1357. ; list of NetBIOS requests, and 'post' the application on any that
  1358. ; completed while posting were delayed.
  1359. ;
  1360. ; Input: none
  1361. ; Output: none
  1362. ; Errors: none
  1363. ; Uses: none
  1364. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1365. public ResumeNetPosting
  1366. ResumeNetPosting proc near
  1367. push es
  1368. push di
  1369. push bx ; used by NetBiosPostRoutine
  1370. push ax
  1371. ; set a flag in the StubCode area to imply that POSTing need not be delayed.
  1372. mov di,[SelNetStubCode] ;selector for the stub area
  1373. or di,di ;global heap in place ?
  1374. jnz dummy1
  1375. jmp ResumeNetPostingRet ;no.
  1376. dummy1:
  1377. mov es,di
  1378. ; get the address of the flag byte fStubDelayNetPosting after the block was
  1379. ; relocated
  1380. mov di,[AddrfStubDelayNetPosting]
  1381. ; ES:DI has the flag byte address. ReSet the flag
  1382. mov byte ptr es:[di],0 ;reset the flag
  1383. FCLI ;protect access to linked list
  1384. mov cx,HCB_List
  1385. mov di,HCB_Header_Size ;offset of NCB in low heap block
  1386. resume_next:
  1387. jcxz resume_done
  1388. mov es,cx
  1389. mov cx,es:[di.HCB_Next]
  1390. test byte ptr es:[di.HCB_Flags],HCB_DELAY ;Has this one completed?
  1391. jz resume_next ; no, skip it
  1392. ;Y: this packet was delayed...post it NOW !
  1393. mov ax,es:[di.HCB_Handle] ;selector to low heap block
  1394. FSTI
  1395. call NetBiosPostRoutine ;post the NCB finally
  1396. FCLI
  1397. ; *** modification warning ***
  1398. ; note: block has just been de-linked from list, so we MUST
  1399. ; get the pointer to the next block before NetBiosPostRoutine
  1400. ; is called (which calls DeLink)!
  1401. jmp short resume_next
  1402. resume_done:
  1403. FSTI
  1404. ResumeNetPostingRet:
  1405. pop ax
  1406. pop bx
  1407. pop di
  1408. pop es
  1409. ret
  1410. ResumeNetPosting endp
  1411. ; ------------------------------------------------------
  1412. ; CopyBufferOut -- This routine copies a buffer from the low heap
  1413. ; block up to the PM app's buffer area.
  1414. ;
  1415. ; Input: AX = Selector to low heap block
  1416. ; ES:BX -> PM NCB
  1417. ; Output: none
  1418. ; Errors: none
  1419. ; Uses: none
  1420. assume ds:DGROUP,es:NOTHING
  1421. public CopyBufferOut
  1422. CopyBufferOut proc near
  1423. pusha
  1424. mov cx,es:[bx.NCB_Buffer_Seg]
  1425. or cx,es:[bx.NCB_Buffer_Off]
  1426. jz CBO_Buffer_Is_Null
  1427. push ds
  1428. mov di,bx ;ES:DI -> PM NCB
  1429. call GetSegmentAddress ;BX:DX = lma of low heap block
  1430. lds si,dword ptr es:[di.NCB_Buffer_Off] ;DS:SI -> PM buffer
  1431. assume ds:NOTHING
  1432. add dx,size NCB_Struc + HCB_Header_Size + 0fh
  1433. adc bx,0
  1434. and dx,not 0fh ;BX:DX = lma of low heap buffer
  1435. mov cx,es:[di.NCB_Length] ;CX = buffer length
  1436. mov al,1
  1437. call CopyBuffer ;copies from lma BX:DX to DS:SI, len CX
  1438. pop ds
  1439. assume ds:DGROUP
  1440. CBO_Buffer_Is_Null:
  1441. popa
  1442. ret
  1443. CopyBufferOut endp
  1444. ; ------------------------------------------------------
  1445. ; CopyBuffer -- This routine copies a buffer of length CX
  1446. ; from DS:SI to the lma in BX:DX _or_ from the lma in
  1447. ; BX:DX to DS:SI.
  1448. ;
  1449. ; Input: AX = direction flag, Z = from DS:SI -> lma,
  1450. ; NZ = from lma -> DS:SI
  1451. ; BX:DX = lma of source or dest
  1452. ; CX = length in bytes
  1453. ; DS:SI = pointer to source or dest
  1454. ; Output: none
  1455. ; Errors: none
  1456. ; Uses: none
  1457. assume ds:NOTHING,es:NOTHING
  1458. public CopyBuffer
  1459. CopyBuffer proc near
  1460. pusha
  1461. push ds
  1462. push es
  1463. rpushf
  1464. FCLI
  1465. ; Setup a selector/descriptor for the linear memory address
  1466. push ax ;save direction flag
  1467. push ds
  1468. mov ds,selDgroupPM ;temp dgroup addressability
  1469. assume ds:DGROUP
  1470. mov ax,SEL_NBSCRATCH or STD_RING ;our scratch selector to use
  1471. dec cx ;length to limit
  1472. cCall NSetSegmentDscr,<ax,bx,dx,0,cx,STD_DATA>
  1473. pop ds
  1474. assume ds:NOTHING
  1475. inc cx ;back to length
  1476. ; If necessary, adjust the length so we don't fault due by overrunning the
  1477. ; DS segment
  1478. mov bx,ds ;get limit for DS segment
  1479. lsl bx,bx
  1480. sub bx,si ;less the DS offset
  1481. inc bx ; (limit is len - 1)
  1482. cmp bx,cx ;at least CX bytes left in segment?
  1483. jae @f
  1484. mov cx,bx ; no, only do # remaining
  1485. @@:
  1486. ; Copy the buffer
  1487. xor di,di ;AX:DI is now SEL:OFF to lma
  1488. pop bx ;recover direction flag
  1489. or bx,bx
  1490. jnz @f
  1491. mov es,ax ;from DS:SI -> AX:DI, almost ready
  1492. jmp short cb_copy
  1493. @@:
  1494. xchg si,di ;from AX:DI -> DS:SI, adjust
  1495. push ds ; regs for movs instruction
  1496. pop es
  1497. mov ds,ax
  1498. cb_copy:
  1499. cld
  1500. shr cx,1 ;byte count to words, low bit to CY
  1501. rep movsw
  1502. jnc @f
  1503. movsb ;get any odd byte
  1504. @@:
  1505. npopf
  1506. pop es
  1507. pop ds
  1508. popa
  1509. ret
  1510. CopyBuffer endp
  1511. ; ------------------------------------------------------
  1512. ; DeLink -- This routine will unlink a HCB/NCB/Buffer low heap
  1513. ; block from the HCB_List linked list.
  1514. ;
  1515. ; Input: AX = selector to block to unlink
  1516. ; Output: block unlinked
  1517. ; Uses: none
  1518. assume ds:DGROUP,es:NOTHING
  1519. public DeLink
  1520. DeLink proc near
  1521. push bx
  1522. push cx
  1523. push es
  1524. mov bx,HCB_Header_Size
  1525. cmp ax,HCB_List ;special case likely condition
  1526. jnz ul_search
  1527. mov es,ax ;ES:BX -> block to unlink
  1528. mov cx,es:[bx.HCB_Next] ;block is first in linked list
  1529. mov HCB_List,cx
  1530. jmp short ul_done
  1531. ul_search:
  1532. mov es,HCB_List ;ES:BX -> first block in list
  1533. ul_loop:
  1534. mov cx,es:[bx.HCB_Next] ;is this just before the block?
  1535. cmp ax,cx
  1536. jz ul_got_it
  1537. mov es,cx ; no, try the next one
  1538. jmp short ul_loop
  1539. ul_got_it:
  1540. push es ;okay, cut the selected block
  1541. mov es,cx ; out of the linked list
  1542. mov cx,es:[bx.HCB_Next]
  1543. pop es
  1544. mov es:[bx.HCB_Next],cx
  1545. ul_done:
  1546. pop es
  1547. pop cx
  1548. pop bx
  1549. ret
  1550. DeLink endp
  1551. ; ------------------------------------------------------
  1552. ; FindTargetNCB -- This routine searches the low memory heap
  1553. ; to locate an NCB pointed to by another user PM NCB.
  1554. ;
  1555. ; Input: ES:DI -> Cancel NCB pointing to PM target NCB
  1556. ; Output: BX:DX = RM SEG:OFF of target NCB in low heap
  1557. ; Error: CY if target NCB can't be found
  1558. ; Uses: none
  1559. assume ds:DGROUP,es:NOTHING
  1560. public FindTargetNCB
  1561. FindTargetNCB proc near
  1562. push ax
  1563. push cx
  1564. push di
  1565. push es
  1566. mov bx,es:[di.NCB_Buffer_Seg] ;get selector:offset of PM
  1567. mov dx,es:[di.NCB_Buffer_Off] ; target NCB to cancel
  1568. ; Search low heap list looking for copy of target NCB
  1569. mov cx,HCB_List
  1570. mov di,HCB_Header_Size ;offset of NCB in low heap block
  1571. ft_next:
  1572. jcxz ft_err
  1573. mov es,cx ;ES:DI -> first/next HCB/NCB in list
  1574. cmp bx,es:[di.HCB_PM_NCB_Seg] ;is this the one?
  1575. jnz ft_not_it
  1576. cmp dx,es:[di.HCB_PM_NCB_Off]
  1577. jz ft_got_it
  1578. ft_not_it: ; no, get ptr to next one
  1579. mov cx,es:[di.HCB_Next]
  1580. jmp short ft_next
  1581. ft_got_it:
  1582. ; ES:DI now points at the low heap copy of the target NCB, convert to SEG:OFF
  1583. mov ax,es
  1584. call GetSegmentAddress
  1585. add dx,di
  1586. adc bx,0 ;BX:DX = lma of low target NCB
  1587. call Lma2SegOff ;BX:DX = normalized SEG:OFF
  1588. dec bx ;return the same slightly unnormalized
  1589. add dx,10h ; SEG:OFF that was used initially
  1590. clc ;found it!
  1591. jmp short ft_done
  1592. ft_err: stc ;couldn't find the target ?!
  1593. ft_done:
  1594. pop es
  1595. pop di
  1596. pop cx
  1597. pop ax
  1598. ret
  1599. FindTargetNCB endp
  1600. ;--------------------------------------------------------
  1601. ; GetEntryExitFlags -- This routine looks up the entry/exit mapping
  1602. ; flags for the current NetBIOS command.
  1603. ;
  1604. ; Input: user regs on stack frame
  1605. ; Output: AX = flags
  1606. ; ES:BX -> caller's PM NCB
  1607. ; Errors: none
  1608. ; Uses:
  1609. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1610. public GetEntryExitFlags
  1611. GetEntryExitFlags proc near
  1612. mov es,[bp].pmUserES ;point ES:BX to pm app's NCB
  1613. mov bx,[bp].pmUserBX ; and get command code
  1614. GetExitFlags2 label near
  1615. push di
  1616. mov al,es:[bx.NCB_Command]
  1617. and al,7Fh
  1618. cbw
  1619. mov di,ax ;map NCB command code to API
  1620. mov al,ApiMapTbl[di] ; mapping code via ApiMapTbl
  1621. shr ax,2 ;use map code to select entry/exit
  1622. mov di,ax ; flags via EntryExitCode
  1623. mov al,EntryExitFlags[di]
  1624. pop di
  1625. ret
  1626. GetEntryExitFlags endp
  1627. ; ------------------------------------------------------
  1628. ; UpdateNCB -- This routine updates the user's PM NCB copy from the
  1629. ; low heap real mode copy.
  1630. ;
  1631. ; Input: AX = selector pointing to low heap HCB/NCB
  1632. ; Output: User's PM NCB updated
  1633. ; Errors: none
  1634. ; Uses: none
  1635. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  1636. public UpdateNCB
  1637. UpdateNCB proc near
  1638. push ax
  1639. push cx
  1640. push si
  1641. push di
  1642. push ds
  1643. push es
  1644. mov ds,ax
  1645. mov si,HCB_Header_Size ;DS:SI -> low heap NCB
  1646. les di,dword ptr [si.HCB_PM_NCB_Off] ;ES:DI -> protect mode NCB
  1647. mov al,[si.NCB_Command] ;want to check the command code later
  1648. and al,not NoWait
  1649. cld
  1650. movsw
  1651. movsw ;copy command, retcode, LSN, Num
  1652. add si,4 ;skip the buffer pointer
  1653. add di,4
  1654. movsw ;move the length
  1655. mov cx,34 / 2 ;len of callname, name, rto, sto (words)
  1656. cmp al,ChainSend ;funkey chain send command?
  1657. jnz @f
  1658. add si,16 ; yes, skip callname
  1659. add di,16
  1660. sub cx,16 / 2
  1661. @@:
  1662. rep movsw ;move name, rto, sto, maybe callname
  1663. add si,4 ;skip the post address
  1664. add di,4
  1665. mov cx,16 / 2 ;move the rest
  1666. rep movsw
  1667. pop es
  1668. pop ds
  1669. pop di
  1670. pop si
  1671. pop cx
  1672. pop ax
  1673. ret
  1674. UpdateNCB endp
  1675. ; -------------------------------------------------------
  1676. DXPMCODE ends
  1677. ;endif ; ife PM_NCB_HANDLING
  1678. DXDATA segment
  1679. my_sp dw ?
  1680. DXDATA ends
  1681. DXPMCODE segment
  1682. assume cs:DXPMCODE
  1683. ;*******************************************************************************
  1684. ;*
  1685. ;* HandleNetbiosAnr
  1686. ;*
  1687. ;* Called when a simulated h/w interrupt for net callback functions occurs.
  1688. ;* Checks if the call is a PM netbios ANR. If it is, we get the NCB
  1689. ;* information and call the PM post routine
  1690. ;*
  1691. ;* ENTRY Nothing
  1692. ;*
  1693. ;* EXIT Nothing
  1694. ;*
  1695. ;* RETURNS Nothing
  1696. ;*
  1697. ;* ASSUMES Nothing
  1698. ;*
  1699. ;******************************************************************************/
  1700. public HandleNetbiosAnr
  1701. HandleNetbiosAnr proc
  1702. assume cs:DXPMCODE
  1703. assume ds:DGROUP
  1704. assume es:nothing
  1705. assume ss:nothing
  1706. ;
  1707. ; perform a BOP to discover if this is a protect mode netbios ANR. If it is then
  1708. ; es and bx will point to the NCB
  1709. ;
  1710. push ds
  1711. push SEL_DXDATA OR STD_RING
  1712. pop ds
  1713. ifdef WOW_x86
  1714. .386p
  1715. FBOP BOP_REDIR, SVC_NETBIOSCHECK, FastBop
  1716. .286p
  1717. else
  1718. SVC SVC_NETBIOSCHECK
  1719. endif ; WOW_x86
  1720. jnz @f
  1721. jmp chain_previous_int ; not PM Netbios ANR
  1722. @@:
  1723. ;
  1724. ; this is a PM Netbios ANR. Save state and call the post routine. There MUST be
  1725. ; a post routine if we're here
  1726. ;
  1727. IFNDEF WOW_x86
  1728. pusha
  1729. ELSE
  1730. .386p
  1731. pushad ; save all 32 bits
  1732. push fs
  1733. push gs
  1734. .286p
  1735. ENDIF
  1736. push es
  1737. ifdef WOW_x86
  1738. .386p
  1739. FBOP BOP_REDIR, SVC_NETBIOS5CINTERRUPT, FastBop
  1740. .286p
  1741. else
  1742. SVC SVC_NETBIOS5CINTERRUPT
  1743. endif ; WOW_x86
  1744. ;
  1745. ; save the stack pointer - apparently some apps will RETF, not IRET from the
  1746. ; ANR. NB - this ISR cannot be re-entered since we only have the one previous
  1747. ; stack pointer saved. This should be okay as long as the EOI is issued at the
  1748. ; end of the ISR
  1749. ;
  1750. mov my_sp,sp
  1751. ;
  1752. ; perform a fake interrupt to the PM post routine. ES:BX point at the NCB, AL is
  1753. ; the return code. Post routine will IRET back (supposedly)
  1754. ;
  1755. mov al,es:[bx.NCB_RetCode] ; pass ret code in al
  1756. pushf
  1757. call dword ptr es:[bx.NCB_Post_Off]
  1758. ;
  1759. ; restore our data segment and stack pointer, lest the app didn't IRET
  1760. ;
  1761. mov ax,SEL_DXDATA OR STD_RING
  1762. mov ds,ax
  1763. mov sp,my_sp
  1764. ;
  1765. ; restore the interrupted state, then perform a BOP to reset the PIC and clean
  1766. ; up any interrupt state
  1767. ;
  1768. pop es
  1769. IFNDEF WOW_x86
  1770. popa
  1771. ELSE
  1772. .386p
  1773. pop gs
  1774. pop fs
  1775. popad
  1776. .286p
  1777. ENDIF
  1778. ;
  1779. ; this BOP will clear the emulated PICs (sends non-specific EOIs), and cause the
  1780. ; next NET interrupt to be generated, if one is queued
  1781. ;
  1782. ifdef WOW_x86
  1783. .386p
  1784. FBOP BOP_REDIR, SVC_RDRINTACK2, FastBop
  1785. .286p
  1786. else
  1787. SVC SVC_RDRINTACK2
  1788. endif ; WOW_x86
  1789. ;
  1790. ; restore the rest of the interrupted context and resume
  1791. ;
  1792. pop ds
  1793. riret
  1794. chain_previous_int:
  1795. push word ptr OldInt73+2 ; selector of previous handler
  1796. push word ptr OldInt73 ; offset of previous handler
  1797. push bp
  1798. mov bp,sp
  1799. mov ds,[bp+6] ; retrieve interrupted ds
  1800. pop bp
  1801. retf 2 ; chain previous handler, removing space
  1802. ; used for ds
  1803. HandleNetbiosAnr endp
  1804. public HookNetBiosHwInt
  1805. HookNetBiosHwInt proc near
  1806. ;
  1807. ; Save everything!!
  1808. ;
  1809. pusha
  1810. push ds
  1811. push es
  1812. ifdef NEC_98 ; '98/6/2 RAID #178452
  1813. mov ax,350dh ; get old handler
  1814. else
  1815. mov ax,3500h + NETWORK_VECTOR ; get old handler
  1816. endif ;NEC_98
  1817. int 21h
  1818. mov word ptr [OldInt73],bx
  1819. mov word ptr [OldInt73 + 2],es
  1820. mov dx,SEL_NBPMCODE OR STD_RING
  1821. mov ds,dx
  1822. mov dx,offset HandleNetbiosAnr
  1823. mov ah,25h
  1824. int 21h ; set new handler
  1825. pop es
  1826. pop ds
  1827. popa
  1828. ret
  1829. HookNetBiosHwInt endp
  1830. DXPMCODE ends
  1831. ;****************************************************************
  1832. end