Source code of Windows XP (NT5)
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.

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