Solved

Accessing memory allocated in 16-bit DLL from 32-bit DLL

Posted on 1998-03-13
22
293 Views
Last Modified: 2013-12-03
I have a 16-bit DLL which allocates memory via GlobalAlloc(GHND | GMEM_SHARE).  The DLL posts messages with the HGLOBAL returned by GlobalAlloc to an HWND which is created by a 16-bit DLL in the same application.  This gave me access to the memory created by the first DLL.  I am converting the second DLL to 32-bits.  I am having trouble calling GlobalLock in the 32-bit DLL on the handle returned by GlobalAlloc in the first 16-bit DLL (confused yet?).  Does anyone have any idea how I can pull this off?
0
Comment
Question by:glee
  • 11
  • 5
  • 4
  • +2
22 Comments
 
LVL 22

Expert Comment

by:nietod
Comment Utility
The 16 and 32 bit dll's cannot share memory.  In fact two 32 bit DLL's or EXE's cannot share memory.  32 bit Dlls/EXEs use seperate memory spaces.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
You must use dynamic data exchange (DDE) or a similar mechanism to share data between 32 bit EXE's/DLL's  
0
 
LVL 2

Expert Comment

by:mnguyen021997
Comment Utility
1st comment is wrong.  memory can be shared between DLL's in 32 bit via memory mapped files or shared data segments with the former being the preferred method.

i would take a look at ole before doing DDE.  

i've accomplished what you need via VDD (virtual DOS Driver under NT) but it really depends on your requirements.  do you need this to happen in realtime or is it sufficient for you to change the memory in 16 bit and notify 32 bit the change via some IPC mechanism?
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
mnguyen,
   My comment was not wrong, it was, I suppose, a little sloppy.  Seperate 32 bit processes cannot share memory directly because they have seperate address spaces.  Some mechanism, usually provided by the operating system, must be used to share the memory.  Memory mapped files, DDE, etc.
0
 

Author Comment

by:glee
Comment Utility
Source of the data is a motion card which generates an interrupt when there is data available.  Presently I deliver this data to applications asynchronously via a PostMessage.  This is essentially real-time and I would like to keep it this way.  I have been thinking about pushing all of the buffer management into the 16-bit code and then providing access functions that the 32-bit code could call through a thunk.  Short of this solution though, is there a way to convert a handle that was returned from GlobalAlloc in 16-bit code into a handle I can use in 32-bit code?
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Not really, that is what dynamic data exchange, memory mapping, and other inter-process communication system is for.  32 programs are isolated from each other as a security measure.  This makes the operating system more reliable, but means that you must go though extra steps to transfer information between them.  

A memory mapped file might be the easiest solution for this case.  
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Take a look at CreateFileMapping().  You will want to share the file by name (I believe).
0
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
A section in a protected mode executable can be marked "shared". That marking indicates the section is mapped into the address space of any process which loads the image.  The memory is shared directly, there's no ACL-level security, though the memory may be marked read-only.

So, you see, there _is_ a way to have separate 32-bit processes share memory directly: my mapping some physical memory into two different logical address spaces.

.B ekiM

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
I have never heard of this.  How does this mechanism work?

But what do you mean by "mapped into the address space of any process which loads the image"  Isn't every executable loaded into a seperate process.  A process does not load seperate executables, although it can load seperate DLL's, but that's not a probelm sionce the process and Dll's will share the same address space.

What if two seperate executables were both written to share data at the same address, will they step on each other?
0
 

Author Comment

by:glee
Comment Utility
Mike -

Yes, I use this techniquie to share data in my 32-bit DLLs (don't need to worry about this is my 16-bit DLLs).  However, now I need to access data from a 32-bit DLL that was allocated in a 16-bit DLL.  The 16-bit DLL has a thunking DLL associated with it for access from 32-bit applications.  Normally I use PostMessage to send the handle (returned from GlobalAlloc) to the application which then locks the memory (via GlobalLock) and gets the info it needs out of it.  However, since I am crossing the 16/32-bit boundary I don't think this handle is valid in the 32-bit side.  Is there a method I can use to convert or translate it?
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
A pointer (address) from a 16 bi dll is not going to be usable in your 32 bit process because it is in a different address space.  You must get the operating system to map the memory into your 32 bit process (at a potentially different address)  That is what memory mapped files and DDE is for.  Microsoft would not develope these techniques of interprocess comunication (and no one would use them) if they weren't needed.  
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:glee
Comment Utility
I am passing a HANDLE, not a pointer.  I realize this is probably no different, but one can only hope.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
In the case of 16 bit memory handles, there is a little difference, but its not much.

Mike seemed to indicate it could be done, but we've not heard from him yet.  What he might be thinking about is that a dll can have some of its data in a segment that is shared between all the processes that load the dll.  (usually each process has a copy of the data).  However, that does not seem to be of any help to you.

Maybe this will convince you.  If it could be done without using the operating system for some sort of interprocess communicating, then why do you need to be thunking?  What is thunking?
0
 
LVL 15

Expert Comment

by:Tommy Hui
Comment Utility
The most easiest way of accomplishing what you need is to use a 16-bit application that uses the 16-bit DLL to get to the memory. Then you can use the 16-bit application as a server (OLE, DLL, or serialized messages) to send information to a 32-bit application. This is the easiest I say because otherwise you will get into thunking which is much harder because the thunking mechanisms are different between Windows 95 and Windows NT. So you will have extra work to and more stuff to learn if you want your application to work with both OS.

However, if you create a 16-bit DDE server, then you only have to learn DDE. I would recommend DDE only because it is easier to learn if you don't have any experience with OLE. Whichever you choose, note that since you have two programs, the memory access will be slower than an EXE accessing memory from a DLL.

The serialized message can be thought of as follows: When the 16-bit application receives the posted message and locks the memory, it can then turn around and send messages to another window. But this time, it can break down the memory received into 4 byte chunks and send them to another window. The destination window can then put the memory back together.


0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
The (potential) problem with thui's suggestion is that it can be slow if you have a large block of memory to share and/or if it needs to be exchanged frequently.  Thui would have a better idea of what sort of overhead is involved than I, but I suspect you wouldn't want to transfer more than say about 80 bytes (20 transfers * 4 bytes)  And you wouldn't wnat to do that more than a few times a second.  
0
 
LVL 2

Accepted Solution

by:
mnguyen021997 earned 300 total points
Comment Utility
glee,

if your motion card calls you via interrupt and you previously used postmessages, perhaps you should look at the WM_COPYDATA message which will be the easiest for you to use.  simply send this message when your motion card calls you, filling out the appropriate data structure, and receive it at the client end and it will work.  if you need to access any 32 bit api then consider a VDD which is essentially a 32-bit DLL that is loaded the VDM and has simple mechanisms to talk to the 16 bit world and itself be able to access all 32 bit api like threads, memory-mapped files, etc.

nietod,

what mike was referring to was to mark a data section inside of a DLL as being a shared.  when the os loads this image it will try to bring it in to all processes at the same address (advance windows nt by jeffrey richter talks about this) however it is NOT the preferred method since if the OS cannot reserve this "shared" location (it will be the same address for ALL images) it will put it at a different address.  the recommeded memory sharing method is to use a memory mapped file.


0
 
LVL 2

Expert Comment

by:mnguyen021997
Comment Utility
as a followup, your 32 bit process will need to setup a window to receive the WM_COPYDATA message.  i'm not certain if your 16 bit window app can do a findwindow to locate the 32 bit app (i suspect yes) but if it can't your 32 bit app may need to find the 16 bit app and send it the appropriate window handle (window handles are universal under NT).
0
 

Author Comment

by:glee
Comment Utility
Looking at KB article Q105762 "Share Memory Between 32-bit and 16-bit Code on Win32s" it says the following "Memory allocated by a 16-bit Windows-based application via GlobalAlloc() must be fixed via GlobalFix() and translated before it can be passed to a Win32-based application".  This seems to imply that there is a process for "translating" a 16-bit memory reference into a 32-bit pointer (handle, pointer, etc...).  This is the basic process used when thunking between 16/32 bit DLLs.  I wonder if I could write a 16-bit function which took the handle in via a "long" casted it to the proper data type (HANDLE or pointer) and then passed it back as the correct data type.  I could then let the thunk compiler handle the mysterious translation.

This is getting very convoluted.  I think the best things for me to do is to pass an internal handle of my own and then let the 16-bit DLL manage the data buffers.  I would then need a 16-bit function to extract the data correctly and pass it back individually to the 32-bit DLL.
0
 

Author Comment

by:glee
Comment Utility
The 32-bit app already registers a window with the 16-bit DLL as you suggest.  This needs to run under both NT and 95.  Is the WM_COPYDATA message used by anything else?  Do I need to be careful what I do with this message (ie, might something else send my app these messages which are being handled by MFC somewhere out of view)?

P.S.  mnguyen - You don't happen to live in Manhatten?
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Glee the WM_COPYDATA suggestions seems like the best to me (I wasn't aware of it.)  If you are worried about intercepting COPTDATA messages from other sources, I thing that is unlikely, but you can provide a little extra protection by puttings some sort of signature in the dwData field.  It is 32 bits, so the odds of a message sent by another source using the same values is slim, 1 in 4 billion.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
WM_COPYDATA works on win32s, 95, and NT.  I can't tell if works in win16.  Hopefully it does.  Even if it wasn't originally available in win16, you may be able to send the message on a 32 bit system (95 or NT) from a 16 bit program and have it work.  There are lots of cases where this will work because the 16 bit legacy code written as an interface into the 32 bit code.
0
 
LVL 2

Expert Comment

by:mnguyen021997
Comment Utility
egg is this you? ha! naw wm_copydata is safe to use.  it's just like me sending a wm_paint message to your app for no reason. i'm positive it works -- see Q114341.  you may need to define everything that wm_copydata needs for it to work on the 16 bit side (including the message and data structure and such).
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

This article shows how to make a Windows 7 gadget that accepts files dropped from the Windows Explorer.  It also illustrates how to give your gadget a non-rectangular shape and how to add some nifty visual effects to text displayed in a your gadget.…
With most software applications trying to cater to multiple user needs nowadays, the focus is to make them as configurable as possible. For e.g., when creating Silverlight applications which will connect to WCF services, the service end point usuall…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now