IPX16A.ASM 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
  1. ;
  2. ; Command & Conquer Red Alert(tm)
  3. ; Copyright 2025 Electronic Arts Inc.
  4. ;
  5. ; This program is free software: you can redistribute it and/or modify
  6. ; it under the terms of the GNU General Public License as published by
  7. ; the Free Software Foundation, either version 3 of the License, or
  8. ; (at your option) any later version.
  9. ;
  10. ; This program is distributed in the hope that it will be useful,
  11. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ; GNU General Public License for more details.
  14. ;
  15. ; You should have received a copy of the GNU General Public License
  16. ; along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. ;
  18. ;***************************************************************************
  19. ;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S I N C **
  20. ;***************************************************************************
  21. ;* *
  22. ;* Project Name : Command & Conquer *
  23. ;* *
  24. ;* File Name : IPX16a.asm *
  25. ;* *
  26. ;* Programmer : Steve Tall *
  27. ;* *
  28. ;* Start Date : January 26th, 1996 *
  29. ;* *
  30. ;* Last Update : January 26th, 1996 [ST] *
  31. ;* *
  32. ;*-------------------------------------------------------------------------*
  33. ;* Overview: *
  34. ;* 16-bit protected mode windows code. This code sits in a 16 bit .DLL *
  35. ;* and provides access to IPX functions via the standard DOS interface. *
  36. ;* *
  37. ;* Strangely enough, although you would expect to have to use segment *
  38. ;* addresses when passing data to and from the DOS IPX services, it only *
  39. ;* seems to work with selector addressing. This could be something to do *
  40. ;* with being in a windows .DLL. *
  41. ;* *
  42. ;* It seems that in Win95, the DOS services are stubbed to just pass up *
  43. ;* to NWLINK which is the win95 32bit netware services layer. If we ever *
  44. ;* have direct access to that then all this code can go away. *
  45. ;* *
  46. ;* *
  47. ;*-----------------------------------------------------------------------------------------------*
  48. ;* Functions: *
  49. ;* _IPX_Initialise -- confirms the presence of IPX and gets the entry point for subsequent calls *
  50. ;* _IPX_Open_Socket95 -- opens the given socket number *
  51. ;* IPX_Close_Socket95 -- closes the given socket number *
  52. ;* _IPX_Get_Connection_Number95 -- get the users local 'connection number' *
  53. ;* _IPX_Send_Packet95 -- Send a packet via IPX *
  54. ;* _IPX_Broadcast_Packet95 -- Broadcast a packet via IPX *
  55. ;* _IPX_Get_Local_Target95 -- Gets the node address of a destination or bridge *
  56. ;* _IPX_Get_Outstanding_Buffer95 -- return contents of the next unread buffer in the buffer list *
  57. ;* Receive_Callback -- IPX callback function. Called when a new packet arrives *
  58. ;* Init_Receive_ECB -- initialises an ECB for receiving a packet *
  59. ;* _IPX_Start_Listening95 -- initialise DOS memory for receive buffers and start listening for *
  60. ;* IPX packets *
  61. ;* _IPX_Shut_Down95 -- finish an IPX session. Releases any allocated resources except the socket *
  62. ;* Listen_For_Packet -- Start IPX listening for an incoming packet *
  63. ;* Call_IPX -- Make a call to the IPX entry point *
  64. ;* Call_DOS -- use DPMI to call a DOS interrupt service *
  65. ;* *
  66. ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  67. .8086 ;cant specify .386 until we are into the code segment
  68. .model large
  69. option segment:USE16 ;16-bit segment
  70. option readonly
  71. option oldstructs
  72. assume ds:@data ;ds is defauly segment register for our data segment
  73. assume es:nothing
  74. ;#############################################################################
  75. ;
  76. ; Constants
  77. ;
  78. RECEIVE_BUFFER_LENGTH =1024 ;length of each DOS memory receive buffer
  79. MAX_RECEIVE_BUFFERS =32 ;number of receive buffers allocated
  80. OFFS =0 ;offset of OFFSET part of a far ptr
  81. SEGM =2 ;offset of SEGMENT part of a far ptr
  82. SEND_ECB_OFFSET =0 ;offset of SEND ecb
  83. SEND_HEADER_OFFSET =(sizeof ECB +3) AND 0fffch ;offset of our send header
  84. SEND_BUFFER_OFFSET =(SEND_HEADER_OFFSET + sizeof IPXHeaderType +3) AND 0fffch ;offset of our send buffer
  85. ;---------------------------------------------------------------------------
  86. ;These defines are for the IPX functions. The function number is specified
  87. ;by placing it in BX when IPX is called. There are two ways to invoke IPX:
  88. ;use interrupt 0x7a, or use a function whose address is obtained by calling
  89. ;interrupt 0x2f with AX=0x7a00; the function address is returned in ES:DI.
  90. ;This is the preferred method, since other apps are known to use int 0x7a.
  91. ;---------------------------------------------------------------------------
  92. IPX_OPEN_SOCKET = 0000h
  93. IPX_CLOSE_SOCKET = 0001h
  94. IPX_GET_LOCAL_TARGET = 0002h
  95. IPX_SEND_PACKET = 0003h
  96. IPX_LISTEN_FOR_PACKET = 0004h
  97. IPX_SCHEDULE_EVENT = 0005h
  98. IPX_CANCEL_EVENT = 0006h
  99. IPX_GET_INTERVAL_MARKER = 0008h
  100. IPX_GET_INTERNETWORK_ADDRESS = 0009h
  101. IPX_RELINQUISH_CONTROL = 000Ah
  102. IPX_DISCONNECT_FROM_TARGET = 000Bh
  103. ;/*---------------------------------------------------------------------------
  104. ;These defines are for various IPX error codes:
  105. ;---------------------------------------------------------------------------*/
  106. IPXERR_CONNECTION_SEVERED = 00ech
  107. IPXERR_CONNECTION_FAILED = 00edh
  108. IPXERR_NO_CONNECTION = 00eeh
  109. IPXERR_CONNECTION_TABLE_FULL = 00efh
  110. IPXERR_NO_CANCEL_ECB = 00f9h
  111. IPXERR_NO_PATH = 00fah
  112. IPXERR_ECB_INACTIVE = 00fch
  113. IPXERR_INVALID_PACKET_LENGTH = 00fdh
  114. IPXERR_SOCKET_TABLE_FULL = 00feh
  115. IPXERR_SOCKET_ERROR = 00ffh
  116. ;/*---------------------------------------------------------------------------
  117. ;These defines are for various interrupt vectors and DPMI functions:
  118. ;---------------------------------------------------------------------------*/
  119. IPX_INT = 007ah
  120. DPMI_INT = 0031h
  121. DPMI_ALLOC_DOS_MEM = 0100h
  122. DPMI_FREE_DOS_MEM = 0101h
  123. DPMI_CALL_REAL_INT = 0300h
  124. DPMI_CALL_REAL_PROC = 0301h
  125. DPMI_ALLOCATE_CALLBACK = 0303h
  126. DPMI_RELEASE_CALLBACK = 0304h
  127. DPMI_LOCK_MEM = 0600h
  128. DPMI_UNLOCK_MEM = 0601h
  129. ;#############################################################################
  130. ;
  131. ; Windows API functions
  132. ;
  133. externdef GLOBALDOSALLOC:far
  134. externdef GLOBALDOSFREE:far
  135. ;#############################################################################
  136. ;
  137. ; Global initialised data
  138. ;
  139. .data
  140. IPXCallOffset dw 0
  141. IPXCallSegment dw 0
  142. RegisterDump db 32h dup (0)
  143. NoReenter db 0
  144. ;#############################################################################
  145. ;
  146. ; Global uninitialised data
  147. ;
  148. .data?
  149. MySocket dw ?
  150. ReceiveBufferSegment dw ?
  151. ReceiveBufferSelector dw ?
  152. ReceiveECBOffset dw ?
  153. CurrentReceiveBuffer dw ?
  154. LastPassedReceiveBuffer dw ?
  155. ReceiveDescriptor db 8 dup (?)
  156. OriginalReceiveDescriptor db 8 dup (?)
  157. Listening db ?
  158. ListeningFailed db ?
  159. ;#############################################################################
  160. ;
  161. ; Structures
  162. ;
  163. ;---------------------------------------------------------------------------
  164. ;This is the IPX Packet structure. It's followed by the data itself, which
  165. ;can be up to 546 bytes long. Annotation of 'IPX' means IPX will set this
  166. ;field; annotation of 'APP' means the application must set the field.
  167. ;NOTE: All header fields are ordered high-byte,low-byte.
  168. ;---------------------------------------------------------------------------*/
  169. IPXHeaderType struct
  170. CheckSum dw ? ; IPX: Not used; always 0xffff
  171. IPXLength dw ? ; IPX: Total size, incl header & data
  172. TransportControl db ? ; IPX: # bridges message crossed
  173. PacketType db ? ; APP: Set to 4 for IPX (5 for SPX)
  174. DestNetworkNumber db ?,?,?,? ; APP: destination Network Number
  175. DestNetworkNode db ?,?,?,?,?,? ; APP: destination Node Address
  176. DestNetworkSocket dw ? ; APP: destination Socket Number
  177. SourceNetworkNumber db ?,?,?,? ; IPX: source Network Number
  178. SourceNetworkNode db ?,?,?,?,?,? ; IPX: source Node Address
  179. SourceNetworkSocket dw ? ; IPX: source Socket Number
  180. IPXHeaderType ends
  181. ;/*---------------------------------------------------------------------------
  182. ;This is the IPX Event Control Block. It serves as a communications area
  183. ;between IPX and the application for a single IPX operation. You should set
  184. ;up a separate ECB for each IPX operation you perform.
  185. ;---------------------------------------------------------------------------*/
  186. ECB struct
  187. Link_Address dd ?
  188. Event_Service_Routine dd ? ; APP: event handler (NULL=none)
  189. InUse db ? ; IPX: 0 = event complete
  190. CompletionCode db ? ; IPX: event's return code
  191. SocketNumber dw ? ; APP: socket to send data through
  192. ConnectionID dw ? ; returned by Listen (???)
  193. RestOfWorkspace dw ?
  194. DriverWorkspace db 12 dup (?)
  195. ImmediateAddress db 6 dup (?) ; returned by Get_Local_Target
  196. PacketCount dw ?
  197. PacketAddress0 dd ?
  198. PacketLength0 dw ?
  199. PacketAddress1 dd ?
  200. PacketLength1 dw ?
  201. ECB ends
  202. ;
  203. ; Structures used for Get_Local_Target calls
  204. ;
  205. request_local_target_buffer struct
  206. lt_network_number db ?,?,?,?
  207. lt_physical_node db ?,?,?,?,?,?
  208. lt_socket dw ?
  209. request_local_target_buffer ends
  210. local_target_reply_buffer struct
  211. lt_local_target db ?,?,?,?,?,?
  212. local_target_reply_buffer ends
  213. ;#############################################################################
  214. ;
  215. ; Start of code segment
  216. ;
  217. ;
  218. .code
  219. .386 ;now we can specify 386 instructions. Its still a 16 bit code segment though.
  220. include <pcmacro.16> ;include 16 bit instruction macros
  221. ;*************************************************************************************************
  222. ;* _IPX_Initialise -- confirms the presence of IPX and gets the entry point for subsequent calls *
  223. ;* *
  224. ;* *
  225. ;* INPUT: eax - nothing *
  226. ;* *
  227. ;* OUTPUT: true if IPX was initialised *
  228. ;* *
  229. ;* 32bit PROTO: extern BOOL __stdcall IPX_Initialise(void); *
  230. ;* *
  231. ;* HISTORY: *
  232. ;* 01/29/96 ST: Created. *
  233. ;*===============================================================================================*
  234. _IPX_Initialise proc far pascal
  235. push ebx
  236. push ecx
  237. push edx
  238. push esi
  239. push edi
  240. push ebp
  241. push ds
  242. push es
  243. push fs
  244. push gs
  245. ; Call the multiplex interrupt to confirm the presence of IPX
  246. ; The real mode entry point is returned in es:di if present
  247. ;
  248. mov ax,7a00h
  249. int 2fh
  250. and eax,0ffh
  251. cmp al,-1
  252. setz al
  253. test al,al
  254. jz @f
  255. ; Save the real mode entry point
  256. ;
  257. mov bx,@data
  258. mov ds,bx
  259. mov [IPXCallSegment],es
  260. mov [IPXCallOffset],di
  261. mov [Listening],0
  262. mov [ListeningFailed],0
  263. @@: pop gs
  264. pop fs
  265. pop es
  266. pop ds
  267. pop ebp
  268. pop edi
  269. pop esi
  270. pop edx
  271. pop ecx
  272. pop ebx
  273. ret
  274. _IPX_Initialise endp
  275. ;*************************************************************************************************
  276. ;* _IPX_Open_Socket95 -- opens the given socket number *
  277. ;* *
  278. ;* *
  279. ;* INPUT: socket - socket number to open *
  280. ;* *
  281. ;* OUTPUT: 0 if socket opened successfully *
  282. ;* *
  283. ;* 32bit PROTO: extern int __stdcall IPX_Open_Socket95(int socket); *
  284. ;* *
  285. ;* HISTORY: *
  286. ;* 01/29/96 ST: Created. *
  287. ;*===============================================================================================*
  288. _IPX_Open_Socket95 proc far pascal uses bx cx dx si di ds es fs gs,
  289. socket:word
  290. mov bx,@data
  291. mov ds,bx
  292. mov bx,IPX_OPEN_SOCKET ;open socket
  293. mov_w dx,[socket] ;socket number
  294. mov_w [MySocket],dx ;save it for later
  295. mov ax,0ffh ;long lived
  296. call Call_IPX
  297. ret
  298. _IPX_Open_Socket95 endp
  299. ;*************************************************************************************************
  300. ;* IPX_Close_Socket95 -- closes the given socket number *
  301. ;* *
  302. ;* *
  303. ;* INPUT: socket - socket number to close *
  304. ;* *
  305. ;* OUTPUT: nothing *
  306. ;* *
  307. ;* 32bit PROTO: extern void __stdcall IPX_Close_Socket95(int socket); *
  308. ;* *
  309. ;* HISTORY: *
  310. ;* 01/29/96 ST: Created. *
  311. ;*===============================================================================================*
  312. _IPX_Close_Socket95 proc far pascal uses ax bx cx dx si di ds es fs gs,
  313. socket:word
  314. mov bx,1
  315. mov_w dx,[socket]
  316. call Call_IPX
  317. ret
  318. _IPX_Close_Socket95 endp
  319. ;*************************************************************************************************
  320. ;* _IPX_Get_Connection_Number95 -- get the users local 'connection number' *
  321. ;* *
  322. ;* *
  323. ;* INPUT: nothing *
  324. ;* *
  325. ;* OUTPUT: connection number. 0 if user isnt logged into novell *
  326. ;* *
  327. ;* 32bit PROTO: extern int __stdcall IPX_Get_Connection_Number95(void); *
  328. ;* *
  329. ;* HISTORY: *
  330. ;* 01/29/96 ST: Created. *
  331. ;*===============================================================================================*
  332. _IPX_Get_Connection_Number95 proc far pascal uses bx cx dx si di ds es fs gs
  333. mov ax,0dc00h
  334. call Call_DOS
  335. and eax,255
  336. ret
  337. _IPX_Get_Connection_Number95 endp
  338. ;*************************************************************************************************
  339. ;* _IPX_Send_Packet95 -- Send a packet via IPX *
  340. ;* *
  341. ;* *
  342. ;* INPUT: send_address - ptr to address of destination for packet *
  343. ;* send_buffer - ptr to data to be sent *
  344. ;* send_buffer_len - length of data in send_buffer *
  345. ;* network_num - network number *
  346. ;* node_address - node address *
  347. ;* *
  348. ;* OUTPUT: true if successfully sent *
  349. ;* *
  350. ;* 32bit PROTO: extern int __stdcall IPX_Send_Packet95(unsigned char *, unsigned char *, *
  351. ;* int, unsigned char*, unsigned char*); *
  352. ;* *
  353. ;* HISTORY: *
  354. ;* 01/29/96 ST: Created. *
  355. ;*===============================================================================================*
  356. _IPX_Send_Packet95 proc far pascal uses ebx ecx edx esi edi ds es fs gs,
  357. send_address :far ptr byte,
  358. send_buffer :far ptr byte,
  359. send_buffer_len :word,
  360. network_num :far ptr byte,
  361. node_address :far ptr byte
  362. local selector :word ;DOS memory selector
  363. local segmento :word ;DOS memory segment
  364. local dos_send_ecb :far ptr ECB ;ptr to send ECB
  365. local dos_send_header :far ptr IPXHeaderType ;ptr to IPX header for sending
  366. local dos_send_buffer :far ptr byte ;ptr to copy of buffer to be sent
  367. local completion_code :word ;IPX send packet completion code
  368. ; Allocate required DOS memory
  369. ; GlobalDosAlloc is a win3.1 API function for allocating and locking DOS memory
  370. ; GlobalDosAlloc returns the segment in dx and a selector in ax
  371. xor ax,ax
  372. mov bx,(sizeof ECB + sizeof IPXHeaderType + 1024 +31)
  373. push bp
  374. push ax
  375. push bx
  376. call GLOBALDOSALLOC
  377. pop bp
  378. test ax,ax
  379. jz @@error
  380. mov [segmento],dx ;save the segment pointer
  381. mov [selector],ax ;save the selector pointer
  382. ;
  383. ; Set up the pointers to the dos memory
  384. ;
  385. mov_w [dos_send_ecb+OFFS],SEND_ECB_OFFSET
  386. mov_w [dos_send_ecb+SEGM],ax
  387. mov_w [dos_send_header+OFFS],SEND_HEADER_OFFSET
  388. mov_w [dos_send_header+SEGM],ax
  389. mov_w [dos_send_buffer+OFFS],SEND_BUFFER_OFFSET
  390. mov_w [dos_send_buffer+SEGM],ax
  391. ;
  392. ; Clear out the send ECB
  393. ;
  394. xor al,al
  395. mov cx,sizeof ECB
  396. les di,[dos_send_ecb]
  397. rep stosb
  398. ;
  399. ; Clear out the send IPX header
  400. ;
  401. mov cx,sizeof IPXHeaderType
  402. les di,[dos_send_header]
  403. rep stosb
  404. ;
  405. ; Copy the data to be sent into the DOS memory send buffer
  406. ;
  407. mov cx,546 ;maximum size of IPX data packet
  408. cmp_w cx,[send_buffer_len]
  409. jle @@got_buffer_len
  410. mov_w cx,[send_buffer_len]
  411. @@got_buffer_len:
  412. les di,[dos_send_buffer]
  413. lds si,[send_buffer]
  414. rep movsb
  415. ;
  416. ; Fill in the send ECB
  417. ;
  418. mov ax,@data
  419. mov ds,ax
  420. mov fs,ax ;keep ptr to data seg in fs
  421. les di,[dos_send_ecb]
  422. mov ax,[MySocket]
  423. mov es:[di.SocketNumber],ax
  424. mov es:[di.PacketCount],2
  425. mov ax,[selector]
  426. shl eax,16
  427. mov_w ax,[dos_send_header+OFFS]
  428. mov_d es:[di.PacketAddress0],eax
  429. mov_w es:[di.PacketLength0],sizeof IPXHeaderType
  430. mov_w ax,[dos_send_buffer+OFFS]
  431. mov_d es:[di.PacketAddress1],eax
  432. mov_w ax,[send_buffer_len]
  433. mov_w es:[di.PacketLength1],ax
  434. ;
  435. ; Fill in the address field
  436. ;
  437. lds si,[send_address]
  438. mov eax,[si]
  439. mov_d es:[di.ImmediateAddress],eax
  440. mov ax,[si+4]
  441. mov_w es:[di.ImmediateAddress+4],ax
  442. ;
  443. ; Fill in the outgoing header
  444. ;
  445. les di,[dos_send_header]
  446. mov es:[di.PacketType],4
  447. push fs:[MySocket]
  448. pop es:[di.DestNetworkSocket]
  449. ;
  450. ; Fill in the network number and node address
  451. ;
  452. lds si,[network_num]
  453. mov_d eax,[si]
  454. mov_d es:[di.DestNetworkNumber],eax
  455. lds si,[node_address]
  456. mov_d eax,[si]
  457. mov_d es:[di.DestNetworkNode],eax
  458. mov_w ax,[si+4]
  459. mov_w es:[di.DestNetworkNode+4],ax
  460. ;
  461. ; Send that sucker!
  462. ;
  463. mov es,[selector]
  464. mov si,SEND_ECB_OFFSET
  465. mov bx,IPX_SEND_PACKET
  466. pusha
  467. call Call_IPX
  468. popa
  469. ;
  470. ; Wait for the send to finish by monitoring the 'in use' flag of the ECB
  471. ;
  472. @@wait_send_loop:
  473. lds si,[dos_send_ecb]
  474. cmp [si.InUse],0
  475. jz @@done
  476. ;
  477. ; Let IPX 'breath' if send isnt complete
  478. ;
  479. mov bx,IPX_RELINQUISH_CONTROL
  480. push bp
  481. call Call_IPX
  482. pop bp
  483. jmp @@wait_send_loop
  484. ;
  485. ; Get the completion code and save it for posterity
  486. ;
  487. @@done: lds si,[dos_send_ecb]
  488. mov al,[si.CompletionCode]
  489. xor ah,ah
  490. mov [completion_code],ax
  491. ;
  492. ; Free the DOS memory
  493. ;
  494. mov bx,@data
  495. mov ds,bx
  496. mov es,bx
  497. mov fs,bx
  498. mov gs,bx
  499. mov bx,[selector]
  500. push bp
  501. push bx
  502. call GLOBALDOSFREE
  503. pop bp
  504. ;
  505. ; Set up the return value
  506. ;
  507. cmp [completion_code],0
  508. jnz @@error
  509. @@success: mov ax,1
  510. ret
  511. @@error: xor ax,ax
  512. ret
  513. _IPX_Send_Packet95 endp
  514. ;*************************************************************************************************
  515. ;* _IPX_Broadcast_Packet95 -- Broadcast a packet via IPX *
  516. ;* *
  517. ;* *
  518. ;* INPUT: send_buffer - ptr to data to be sent *
  519. ;* send_buffer_len - length of data in send_buffer *
  520. ;* *
  521. ;* OUTPUT: true if successfully sent *
  522. ;* *
  523. ;* 32bit PROTO: extern int __stdcall IPX_Broadcast_Packet95(unsigned char *, int); *
  524. ;* *
  525. ;* HISTORY: *
  526. ;* 01/29/96 ST: Created. *
  527. ;*===============================================================================================*
  528. _IPX_Broadcast_Packet95 proc far pascal uses ebx ecx edx esi edi ds es fs gs,
  529. send_buffer :far ptr byte,
  530. send_buffer_len :word
  531. local selector :word ;DOS memory selector
  532. local segmento :word ;DOS memory segment
  533. local dos_send_ecb :far ptr ECB ;ptr to send ECB
  534. local dos_send_header :far ptr IPXHeaderType ;ptr to IPX header for sending
  535. local dos_send_buffer :far ptr byte ;ptr to copy of buffer to be sent
  536. local completion_code :word ;IPX send packet completion code
  537. ; Allocate required DOS memory
  538. ; GlobalDosAlloc is a win3.1 API function for allocating and locking DOS memory
  539. ; GlobalDosAlloc returns the segment in dx and a selector in ax
  540. xor ax,ax
  541. mov bx,(sizeof ECB + sizeof IPXHeaderType + 1024 +31)
  542. push bp
  543. push ax
  544. push bx
  545. call GLOBALDOSALLOC
  546. pop bp
  547. test ax,ax
  548. jz @@error
  549. mov [segmento],dx ;save the segment pointer
  550. mov [selector],ax ;save the selector pointer
  551. ;
  552. ; Set up the pointers to the dos memory
  553. ;
  554. mov_w [dos_send_ecb+OFFS],SEND_ECB_OFFSET
  555. mov_w [dos_send_ecb+SEGM],ax
  556. mov_w [dos_send_header+OFFS],SEND_HEADER_OFFSET
  557. mov_w [dos_send_header+SEGM],ax
  558. mov_w [dos_send_buffer+OFFS],SEND_BUFFER_OFFSET
  559. mov_w [dos_send_buffer+SEGM],ax
  560. ;
  561. ; Clear out the send ECB
  562. ;
  563. xor al,al
  564. mov cx,sizeof ECB
  565. les di,[dos_send_ecb]
  566. rep stosb
  567. ;
  568. ; Clear out the send header
  569. ;
  570. mov cx,sizeof IPXHeaderType
  571. les di,[dos_send_header]
  572. rep stosb
  573. ;
  574. ; Copy the data to be sent into the send buffer
  575. ;
  576. mov cx,546 ;maximum size of IPX data packet
  577. cmp_w cx,[send_buffer_len]
  578. jle @@got_buffer_len
  579. mov_w cx,[send_buffer_len]
  580. @@got_buffer_len:
  581. les di,[dos_send_buffer]
  582. lds si,[send_buffer]
  583. rep movsb
  584. ;
  585. ; Fill in the ECB
  586. ;
  587. mov ax,@data
  588. mov ds,ax
  589. mov fs,ax ;keep ptr to data seg in fs
  590. les di,[dos_send_ecb]
  591. mov ax,[MySocket]
  592. mov es:[di.SocketNumber],ax
  593. mov es:[di.PacketCount],2
  594. mov ax,[selector]
  595. shl eax,16
  596. mov_w ax,[dos_send_header+OFFS]
  597. mov_d es:[di.PacketAddress0],eax
  598. mov_w es:[di.PacketLength0],sizeof IPXHeaderType
  599. mov_w ax,[dos_send_buffer+OFFS]
  600. mov_d es:[di.PacketAddress1],eax
  601. mov_w ax,[send_buffer_len]
  602. mov_w es:[di.PacketLength1],ax
  603. ;
  604. ; Fill in the address field
  605. ;
  606. mov_d es:[di.ImmediateAddress],0ffffffffh
  607. mov_w es:[di.ImmediateAddress+4],0ffffh
  608. ;
  609. ; Fill in the outgoing header
  610. ;
  611. les di,[dos_send_header]
  612. mov es:[di.PacketType],4
  613. push fs:[MySocket]
  614. pop es:[di.DestNetworkSocket]
  615. ;
  616. ; Fill in the network number and node address
  617. ;
  618. mov_d es:[di.DestNetworkNumber],0ffffffffh
  619. mov_d es:[di.DestNetworkNode],0ffffffffh
  620. mov_w es:[di.DestNetworkNode+4],0ffffh
  621. ;
  622. ; Send that sucker!
  623. ;
  624. mov es,[selector]
  625. mov si,SEND_ECB_OFFSET
  626. mov bx,IPX_SEND_PACKET
  627. pusha
  628. push fs
  629. call Call_IPX
  630. pop fs
  631. popa
  632. ;
  633. ; Wait for the send to finish by monitoring the 'in use' flag of the ECB
  634. ;
  635. @@wait_send_loop:
  636. lds si,[dos_send_ecb]
  637. cmp [si.InUse],0
  638. jz @@done
  639. ;
  640. ; Let IPX 'breath' if send isnt complete
  641. ;
  642. mov bx,IPX_RELINQUISH_CONTROL
  643. push bp
  644. call Call_IPX
  645. pop bp
  646. jmp @@wait_send_loop
  647. ;
  648. ; Get the completion code and save it for posterity
  649. ;
  650. @@done: lds si,[dos_send_ecb]
  651. mov al,[si.CompletionCode]
  652. xor ah,ah
  653. mov [completion_code],ax
  654. ;
  655. ; Free the DOS memory
  656. ;
  657. mov bx,@data
  658. mov ds,bx
  659. mov es,bx
  660. mov fs,bx
  661. mov gs,bx
  662. mov bx,[selector]
  663. push bp
  664. push bx
  665. call GLOBALDOSFREE
  666. pop bp
  667. ;
  668. ; Set up the return value
  669. ;
  670. cmp [completion_code],0
  671. jnz @@error
  672. @@success: mov ax,1
  673. ret
  674. @@error: xor ax,ax
  675. ret
  676. _IPX_Broadcast_Packet95 endp
  677. ;*************************************************************************************************
  678. ;* _IPX_Get_Local_Target95 -- Gets the node address of a destination or bridge *
  679. ;* *
  680. ;* *
  681. ;* INPUT: dest_network - ptr to network number of target *
  682. ;* dest_node - ptr to node number of target *
  683. ;* socket - socket number *
  684. ;* bridge_address - ptr to buffer to store immediate address in *
  685. ;* *
  686. ;* OUTPUT: IPX result code. -1 if error *
  687. ;* *
  688. ;* 32bit PROTO: extern int __stdcall IPX_Get_Local_Target95(unsigned char *, unsigned char*, *
  689. ;* unsigned short, unsigned char*); *
  690. ;* *
  691. ;* HISTORY: *
  692. ;* 01/29/96 ST: Created. *
  693. ;*===============================================================================================*
  694. _IPX_Get_Local_Target95 proc far pascal uses ebx ecx edx esi edi ds es fs gs,
  695. dest_network :far ptr byte,
  696. dest_node :far ptr byte,
  697. socket :word,
  698. bridge_address :far ptr byte
  699. local segmento :word ; DOS memory segment
  700. local selector :word ; DOS memory selector
  701. local result_code :word ; return code
  702. ; Allocate required DOS memory for data passed to IPX
  703. ; GlobalDosAlloc is a win3.1 API function for allocating and locking DOS memory
  704. ; GlobalDosAlloc returns the segment in dx and a selector in ax
  705. xor ax,ax
  706. mov bx,(sizeof local_target_reply_buffer + \
  707. sizeof request_local_target_buffer + 15)
  708. push bp
  709. push ax
  710. push bx
  711. call GLOBALDOSALLOC
  712. pop bp
  713. test ax,ax
  714. jz @@return_error
  715. mov [segmento],dx ; save the segment
  716. mov [selector],ax ; save the selector
  717. mov fs,ax
  718. xor di,di
  719. ;
  720. ; Init the request structure
  721. ;
  722. lds si,[dest_network]
  723. mov_d eax,[si]
  724. mov_d fs:[di.lt_network_number],eax
  725. lds si,[dest_node]
  726. mov eax,[si]
  727. mov_d fs:[di.lt_physical_node],eax
  728. mov_w ax,[si+4]
  729. mov_w fs:[di.lt_physical_node+4],ax
  730. mov ax,[socket]
  731. mov fs:[di.lt_socket],ax
  732. ;
  733. ; Set up the registers to call IPX
  734. ;
  735. mov bx,IPX_GET_LOCAL_TARGET
  736. mov ax,[selector]
  737. mov ds,ax
  738. xor si,si
  739. mov es,ax
  740. mov di,sizeof request_local_target_buffer
  741. ;
  742. ; Call IPX
  743. ;
  744. push bp
  745. call Call_IPX
  746. pop bp
  747. ;
  748. ; Save the result code so we can return it
  749. ;
  750. mov [result_code],ax
  751. ;
  752. ; Copy the bridge address into the return buffer
  753. ;
  754. mov ds,[selector]
  755. mov si,sizeof request_local_target_buffer + lt_local_target
  756. les di,[bridge_address]
  757. movsd
  758. movsw
  759. ;
  760. ; Free the DOS memory
  761. ;
  762. mov bx,@data
  763. mov ds,bx
  764. mov es,bx
  765. mov fs,bx
  766. mov gs,bx
  767. mov bx,[selector]
  768. push bp
  769. push bx
  770. call GLOBALDOSFREE
  771. pop bp
  772. ;
  773. ; Return the IPX result code
  774. ;
  775. mov ax,[result_code]
  776. ret
  777. @@return_error: mov ax,-1
  778. ret
  779. _IPX_Get_Local_Target95 endp
  780. ;*************************************************************************************************
  781. ;* _IPX_Get_Outstanding_Buffer95 -- return contents of the next unread buffer in the buffer list *
  782. ;* *
  783. ;* *
  784. ;* INPUT: copy_receive_buffer -- ptr to buffer that data will be copied to *
  785. ;* *
  786. ;* OUTPUT: number of buffers returned (0 or 1) *
  787. ;* *
  788. ;* 32bit PROTO: extern BOOL __stdcall IPX_Get_Outstanding_Buffer95(unsigned char *buffer); *
  789. ;* *
  790. ;* HISTORY: *
  791. ;* 01/29/96 ST: Created. *
  792. ;*===============================================================================================*
  793. _IPX_Get_Outstanding_Buffer95 proc far pascal uses ebx ecx edx esi edi ebp ds es fs gs,
  794. copy_receive_buffer:far ptr byte
  795. mov ax,@data
  796. mov ds,ax
  797. ;
  798. ; If the receive buffer pointer is the same as the pointer to the last buffer
  799. ; returned then there is no outstanding data to return so just exit
  800. ;
  801. xor ax,ax
  802. mov si,[LastPassedReceiveBuffer]
  803. cmp si,[CurrentReceiveBuffer]
  804. jz @@done
  805. ;
  806. ; Copy the IPX receive data buffer into the buffer provided by the caller
  807. ;
  808. push ds
  809. mov cx,RECEIVE_BUFFER_LENGTH/4
  810. mov ds,[ReceiveBufferSelector]
  811. les di,[copy_receive_buffer]
  812. rep movsd
  813. pop ds
  814. ;
  815. ; Update the pointer to the last buffer we copied
  816. ;
  817. cmp si,RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS
  818. jc @@no_wrap
  819. xor si,si
  820. @@no_wrap: mov [LastPassedReceiveBuffer],si
  821. mov ax,1
  822. @@done: ret
  823. _IPX_Get_Outstanding_Buffer95 endp
  824. ;*************************************************************************************************
  825. ;* Receive_Callback -- IPX callback function. Called when a new packet arrives *
  826. ;* *
  827. ;* *
  828. ;* INPUT: nothing *
  829. ;* *
  830. ;* OUTPUT: nothing *
  831. ;* *
  832. ;* HISTORY: *
  833. ;* 01/29/96 ST: Created. *
  834. ;*===============================================================================================*
  835. Receive_Callback proc far
  836. ;
  837. ; Save everything
  838. ;
  839. pushf
  840. cli
  841. cld
  842. pushad
  843. push ds
  844. push es
  845. push fs
  846. push gs
  847. ;
  848. ; Dont reenter
  849. ;
  850. mov ax,@data
  851. mov ds,ax
  852. cmp [NoReenter],0
  853. jnz @@out
  854. mov [NoReenter],1
  855. ;
  856. ; Update the receive buffer pointer to point to the next buffer
  857. ;
  858. mov ax,[CurrentReceiveBuffer]
  859. add ax,RECEIVE_BUFFER_LENGTH
  860. cmp ax,RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS
  861. jc @@no_wrap
  862. xor ax,ax
  863. @@no_wrap: mov [CurrentReceiveBuffer],ax
  864. ;
  865. ; Listen for another packet
  866. ;
  867. call Listen_For_Packet
  868. mov ax,@data
  869. mov ds,ax
  870. mov [NoReenter],0
  871. ;
  872. ; Restore everything and exit
  873. ;
  874. @@out: pop gs
  875. pop fs
  876. pop es
  877. pop ds
  878. popad
  879. popf
  880. ret
  881. Receive_Callback endp
  882. ;*************************************************************************************************
  883. ;* Init_Receive_ECB -- initialises an ECB for receiving a packet *
  884. ;* *
  885. ;* *
  886. ;* INPUT: nothing *
  887. ;* *
  888. ;* OUTPUT: nothing *
  889. ;* *
  890. ;* HISTORY: *
  891. ;* 01/29/96 ST: Created. *
  892. ;*===============================================================================================*
  893. Init_Receive_ECB proc near uses eax ebx ecx edx esi edi ebp ds es
  894. mov ax,@data
  895. mov ds,ax
  896. mov es,[ReceiveBufferSelector]
  897. ;
  898. ; Clear out the ECB
  899. ;
  900. mov di,[ReceiveECBOffset]
  901. mov cx,sizeof ECB
  902. xor al,al
  903. rep stosb
  904. ;
  905. ; Set up the ECB
  906. ;
  907. ;
  908. ;General ECB data
  909. mov di,[ReceiveECBOffset]
  910. mov ax,[MySocket]
  911. mov es:[di.SocketNumber],ax
  912. mov es:[di.PacketCount],2
  913. ;
  914. ; Packet address for IPX header
  915. mov ax,[CurrentReceiveBuffer]
  916. mov bx,[ReceiveBufferSelector]
  917. mov_w es:[di.PacketAddress0+OFFS],ax
  918. mov_w es:[di.PacketAddress0+SEGM],bx
  919. mov es:[di.PacketLength0],sizeof IPXHeaderType
  920. ;
  921. ; Packet address for receive buffer
  922. mov ax,[CurrentReceiveBuffer]
  923. add ax,sizeof IPXHeaderType
  924. mov_w es:[di.PacketAddress1+OFFS],ax
  925. mov_w es:[di.PacketAddress1+SEGM],bx
  926. mov es:[di.PacketLength1],546
  927. ;
  928. ; Set up the callback address
  929. mov_w es:[di.Event_Service_Routine+OFFS],offset Receive_Callback
  930. mov_w es:[di.Event_Service_Routine+SEGM],cs
  931. ret
  932. Init_Receive_ECB endp
  933. ;*************************************************************************************************
  934. ;* _IPX_Start_Listening95 -- initialise DOS memory for receive buffers and start listening for *
  935. ;* IPX packets *
  936. ;* *
  937. ;* INPUT: nothing *
  938. ;* *
  939. ;* OUTPUT: true if we started listening *
  940. ;* *
  941. ;* 32bit PROTO: extern BOOL __stdcall IPX_Start_Listening95(void); *
  942. ;* *
  943. ;* HISTORY: *
  944. ;* 01/29/96 ST: Created. *
  945. ;*===============================================================================================*
  946. _IPX_Start_Listening95 proc far pascal uses ebx ecx edx esi edi ebp ds es fs gs
  947. ;
  948. ; Check that we arent already listening
  949. ;
  950. mov ax,@data
  951. mov ds,ax
  952. cmp [ListeningFailed],0
  953. jnz @@restart
  954. cmp [Listening],0
  955. jnz @@out ;already listening
  956. ;
  957. ; Allocate and lock DOS memory for listen ECB and receive buffers
  958. ; GlobalDosAlloc is a win3.1 API function for allocating and locking DOS memory
  959. ; GlobalDosAlloc returns the segment in dx and a selector in ax
  960. mov bx,(RECEIVE_BUFFER_LENGTH*MAX_RECEIVE_BUFFERS + sizeof ECB + 15)
  961. xor ax,ax
  962. save bp,ds
  963. push ax
  964. push bx
  965. call GLOBALDOSALLOC
  966. restore bp,ds
  967. test ax,ax
  968. jz @@error
  969. mov [ReceiveBufferSegment],dx ;save the DOS memory segment in a global
  970. mov [ReceiveBufferSelector],ax ;save the DOS memory selector in a global
  971. saveall
  972. ; int 3
  973. mov ax,@data
  974. mov es,ax
  975. mov ax,0bh
  976. mov bx,es:[ReceiveBufferSelector]
  977. mov di,offset OriginalReceiveDescriptor
  978. int 31h
  979. bcc @f
  980. ; int 3
  981. @@: restall
  982. ;
  983. ; Set up pointers to the DOS memory
  984. ;
  985. mov [ReceiveECBOffset],RECEIVE_BUFFER_LENGTH * MAX_RECEIVE_BUFFERS
  986. mov [CurrentReceiveBuffer],0 ;1st receive buffer
  987. mov [LastPassedReceiveBuffer],0
  988. ;
  989. ; Start listening
  990. ;
  991. @@restart: mov [ListeningFailed],0
  992. push ds
  993. call Listen_For_Packet
  994. pop ds
  995. mov [Listening],1
  996. @@out: mov ax,1
  997. ret
  998. @@error: xor ax,ax
  999. ret
  1000. _IPX_Start_Listening95 endp
  1001. ;*************************************************************************************************
  1002. ;* _IPX_Shut_Down95 -- finish an IPX session. Releases any allocated resources except the socket *
  1003. ;* *
  1004. ;* *
  1005. ;* INPUT: nothing *
  1006. ;* *
  1007. ;* OUTPUT: nothing *
  1008. ;* *
  1009. ;* 32bit PROTO: extern void __stdcall IPX_Shut_Down95(void); *
  1010. ;* *
  1011. ;* HISTORY: *
  1012. ;* 01/29/96 ST: Created. *
  1013. ;*===============================================================================================*
  1014. _IPX_Shut_Down95 proc far pascal uses eax ebx ecx edx esi edi ebp ds es fs gs
  1015. ;
  1016. ; If we aren't listening then we cant stop
  1017. ;
  1018. mov ax,@data
  1019. mov ds,ax
  1020. cmp [Listening],0
  1021. jz @@out
  1022. ;
  1023. ; Stop listening for a packet
  1024. ;
  1025. mov es,[ReceiveBufferSelector]
  1026. mov si,[ReceiveECBOffset]
  1027. mov bx,IPX_CANCEL_EVENT
  1028. save bp,ds
  1029. call Call_IPX
  1030. restore bp,ds
  1031. ;
  1032. ; Free the DOS memory
  1033. ;
  1034. mov ax,@data
  1035. mov ds,ax
  1036. mov es,ax
  1037. mov ax,[ReceiveBufferSelector]
  1038. save bp,ds
  1039. push ax
  1040. call GLOBALDOSFREE
  1041. restore bp,ds
  1042. mov [Listening],0
  1043. @@out: ret
  1044. _IPX_Shut_Down95 endp
  1045. Verify_Selectors proc near uses eax ebx ecx edx esi edi ebp ds es fs gs
  1046. ; int 3
  1047. mov ax,1686h
  1048. int 2fh
  1049. test ax,ax
  1050. jnz @@fail
  1051. mov ax,@data
  1052. mov es,ax
  1053. mov ax,0bh
  1054. mov bx,es:[ReceiveBufferSelector]
  1055. mov di,offset ReceiveDescriptor
  1056. int 31h
  1057. bcs @@fail
  1058. mov ax,@data
  1059. mov ds,ax
  1060. mov_d eax,[ReceiveDescriptor]
  1061. cmp_d eax,[OriginalReceiveDescriptor]
  1062. jnz @@fail
  1063. mov_d eax,[ReceiveDescriptor+4]
  1064. cmp_d eax,[OriginalReceiveDescriptor+4]
  1065. jnz @@fail
  1066. clc
  1067. ret
  1068. @@fail: stc
  1069. ret
  1070. Verify_Selectors endp
  1071. ;*************************************************************************************************
  1072. ;* Listen_For_Packet -- Start IPX listening for an incoming packet *
  1073. ;* *
  1074. ;* *
  1075. ;* INPUT: nothing *
  1076. ;* *
  1077. ;* OUTPUT: nothing *
  1078. ;* *
  1079. ;* HISTORY: *
  1080. ;* 01/29/96 ST: Created. *
  1081. ;*===============================================================================================*
  1082. Listen_For_Packet proc near uses eax ebx ecx edx esi edi ebp ds es fs gs
  1083. call Verify_Selectors
  1084. bcs @@fail
  1085. call Init_Receive_ECB
  1086. mov ax,@data
  1087. mov ds,ax
  1088. mov es,[ReceiveBufferSelector]
  1089. mov si,[ReceiveECBOffset]
  1090. mov bx,IPX_LISTEN_FOR_PACKET
  1091. push ds
  1092. call Call_IPX
  1093. pop ds
  1094. ret
  1095. @@fail: mov ax,@data
  1096. mov ds,ax
  1097. mov [ListeningFailed],1
  1098. ret
  1099. Listen_For_Packet endp
  1100. ;*************************************************************************************************
  1101. ;* Call_IPX -- Make a call to the IPX entry point *
  1102. ;* *
  1103. ;* *
  1104. ;* INPUT: registers set up for the IPX call *
  1105. ;* *
  1106. ;* OUTPUT: registers returned by IPX *
  1107. ;* *
  1108. ;* HISTORY: *
  1109. ;* 01/29/96 ST: Created. *
  1110. ;*===============================================================================================*
  1111. Call_IPX proc far
  1112. push gs
  1113. push ax
  1114. mov ax,@data
  1115. mov gs,ax
  1116. pop ax
  1117. push bp
  1118. mov bp,offset IPXCallOffset
  1119. call dword ptr gs:[bp]
  1120. pop bp
  1121. pop gs
  1122. ret
  1123. Call_IPX endp
  1124. ;*************************************************************************************************
  1125. ;* Call_DOS -- use DPMI to call a DOS interrupt service *
  1126. ;* *
  1127. ;* *
  1128. ;* INPUT: registers set up for the DOS call *
  1129. ;* *
  1130. ;* OUTPUT: registers returned by DOS *
  1131. ;* *
  1132. ;* HISTORY: *
  1133. ;* 01/29/96 ST: Created. *
  1134. ;*===============================================================================================*
  1135. Call_DOS proc far
  1136. push gs
  1137. push ax
  1138. mov ax,@data
  1139. mov gs,ax
  1140. pop ax
  1141. ;
  1142. ; Dump the registers first so we can use them
  1143. ;
  1144. mov_d gs:[RegisterDump],edi
  1145. mov_d gs:[RegisterDump+4],esi
  1146. mov_d gs:[RegisterDump+8],ebp
  1147. mov_d gs:[RegisterDump+10h],ebx
  1148. mov_d gs:[RegisterDump+14h],edx
  1149. mov_d gs:[RegisterDump+18h],ecx
  1150. mov_d gs:[RegisterDump+1ch],eax
  1151. ;
  1152. ; Dump the flags
  1153. ;
  1154. pushf
  1155. pop gs:[word ptr RegisterDump+20h]
  1156. ;
  1157. ; Save the segment registers
  1158. ;
  1159. mov_w gs:[RegisterDump+22h],es
  1160. mov_w gs:[RegisterDump+24h],ds
  1161. mov_w gs:[RegisterDump+26h],fs
  1162. mov_w gs:[RegisterDump+28h],gs
  1163. ;
  1164. ; Set up stack addr to zero - DPMI will supply a real mode stack
  1165. ;
  1166. xor ax,ax
  1167. mov_w gs:[RegisterDump+2eh],ax ;sp
  1168. mov_w gs:[RegisterDump+30h],ax ;ss
  1169. mov ax,DPMI_CALL_REAL_INT ; Simulate real mode interrupt
  1170. xor bh,bh ; flags - should be zero
  1171. mov bl,21h ; interrupt number
  1172. mov ecx,0 ; number of words to copy from the protected mode stack
  1173. mov di,offset RegisterDump
  1174. push gs
  1175. pop es
  1176. push gs
  1177. int 31h ;DPMI interrupt
  1178. pop gs
  1179. ;
  1180. ; Get the return registers
  1181. ;
  1182. mov_d edi,gs:[RegisterDump]
  1183. mov_d esi,gs:[RegisterDump+4]
  1184. mov_d ebp,gs:[RegisterDump+8]
  1185. mov_d ebx,gs:[RegisterDump+10h]
  1186. mov_d edx,gs:[RegisterDump+14h]
  1187. mov_d ecx,gs:[RegisterDump+18h]
  1188. mov_d eax,gs:[RegisterDump+1ch]
  1189. mov_w es,gs:[RegisterDump+22h]
  1190. mov_w ds,gs:[RegisterDump+24h]
  1191. pop gs
  1192. ret
  1193. Call_DOS endp
  1194. end