[comp.windows.ms.programmer] HELP with GlobalDosAlloc

go3@prism.gatech.EDU (OLIVE JR,GEORGE A) (04/13/91)

We are trying to use GlobalDosAlloc to allocate a block of memory to be
shared by a Windows application and a DOS application which has been
started using WinExec.  The following code shows the basic calls that
we are using.  wDosSeg is the real mode segment which is being sent as
a parameter to the DOS program.  hDos is a global memory handle which
is created from the selector in the LOWORD of the value returned by
GlobalDosAlloc and is used to access the memory from within Windows.
Unfortunately, this doesn't seem to work.  Data written to the memory
area pointed to by lpDos doesn't appear in the memory area wDosSeg:0000
when read by the DOS application.  We would be extremely grateful to 
anyone who can point out what we are doing wrong.


/***************************************************/
DWORD dwGlobalDos;
WORD wDosSeg;
HANDLE hDos;
LPSTR lpDos;

dwGlobalDos = GlobalDosAlloc(DOS_ALLOC_SIZE);
wDosSeg = HIWORD(dwGlobalDos);
hDos = LOWORD(GlobalHandle(LOWORD(dwGlobalDos)));
lpDos = (LPSTR) GlobalLock(hDos);
/***************************************************/



The DOS application is creating a pointer using wDosSeg with the following
code:

/***************************************************/
FP_SEG(ptr) = wDosSeg;  /* wDosSeg is passed as a parameter */
FP_OFF(ptr) = 0;
/***************************************************/


-- 
OLIVE JR,GEORGE A
Georgia Institute of Technology, Atlanta Georgia, 30332
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!go3
Internet: go3@prism.gatech.edu

tonyg@polari.UUCP (Tony Gosling) (04/14/91)

In article <26158@hydra.gatech.EDU>, go3@prism.gatech.EDU (OLIVE JR,GEORGE A) writes:
> 
> We are trying to use GlobalDosAlloc to allocate a block of memory to be
> shared by a Windows application and a DOS application which has been
> started using WinExec.  The following code shows the basic calls that
> we are using.  wDosSeg is the real mode segment which is being sent as
> a parameter to the DOS program.  hDos is a global memory handle which
> is created from the selector in the LOWORD of the value returned by
> GlobalDosAlloc and is used to access the memory from within Windows.
> Unfortunately, this doesn't seem to work.  Data written to the memory
> area pointed to by lpDos doesn't appear in the memory area wDosSeg:0000
> when read by the DOS application.  We would be extremely grateful to 
> anyone who can point out what we are doing wrong.

Sorry, but this is not going to work.  GlobalDOSAlloc only allocates memory
addressable in the Windows context.  This complete context is swapped
when you run a DOS application.  The name 'Global' in GlobalDOSAlloc is
misleading in this case.

So now you ask, how can memory be shared between a DOS application
and Windows.  The only way I know of is to write a TSR which is run
BEFORE Windows is started.  This TSR reserves the memory required
and passes the memory address via some private interface to either
Windows or DOS applications.

There is a DPMI call to allocate DOS memory in protected mode.
This is unlikely to succeed since Windows takes all the DOS memory
it can find.  Don't bother trying to use this.

Tony Gosling,
aka tonyg@microsoft

The above are my opinions only and may not agree with those of Microsoft.

rommel@Informatik.TU-Muenchen.DE (Kai-Uwe Rommel) (04/15/91)

In article <26158@hydra.gatech.EDU> go3@prism.gatech.EDU (OLIVE JR,GEORGE A) writes:
>
>We are trying to use GlobalDosAlloc to allocate a block of memory to be
>shared by a Windows application and a DOS application which has been
>started using WinExec.  The following code shows the basic calls that
....
>when read by the DOS application.  We would be extremely grateful to 
>anyone who can point out what we are doing wrong.
>

>DWORD dwGlobalDos;
>WORD wDosSeg;
>HANDLE hDos;
>LPSTR lpDos;
>
>dwGlobalDos = GlobalDosAlloc(DOS_ALLOC_SIZE);
>wDosSeg = HIWORD(dwGlobalDos);
>hDos = LOWORD(GlobalHandle(LOWORD(dwGlobalDos)));
>lpDos = (LPSTR) GlobalLock(hDos);

The last two lines should be replaced by:

lpDos = (LPSTR) MAKELONG(0, LOWORD(dwGlobalDos));

because the low word of the result of GlobalDosAlloc() is a valid
protected mode segment selector which only has to be converted to a 
far pointer by adding an offset of zero to it.

This works well for me.

Kai Uwe Rommel

/* Kai Uwe Rommel, Munich ----- rommel@lan.informatik.tu-muenchen.dbp.de */

DOS ... is still a real mode only non-reentrant interrupt
handler, and always will be.                -Russell Williams (MS)

rommel@Informatik.TU-Muenchen.DE (Kai-Uwe Rommel) (04/15/91)

In my first followup to this question I forgot to mention that this
method is designed to work with TSR's loaded before Windows is started,
as explained by someone else in a different article.

Kai Uwe Rommel

/* Kai Uwe Rommel, Munich ----- rommel@lan.informatik.tu-muenchen.dbp.de */

DOS ... is still a real mode only non-reentrant interrupt
handler, and always will be.                -Russell Williams (MS)

jjw@hpcndpc.CND.HP.COM (Jimmy Wright) (04/16/91)

	I have used GlobalDosAlloc successfully to communicate between
	a DLL and a DOS TSR.  I don't make the GlobalHandle() call though.
	I just copy stuff in/out of the buffer using the Selector from
	the DLL and use the Segment from the DOS Tsr.  I don't know if
	the code you posted is exactly the same as your program but you
	really should be checking the return codes.  If GlobalHandle() fails
	with a NULL pointer then this would explain the behaviour you have
	seen.

	JJ