Kbase 13686: Windows Pointers and memory window handles with DLL calls
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  5/10/1998 |
|
Windows Pointers and memory window handles with DLL calls
When using the DLL callout functionality of Progress, you
may sometimes find that you are returned a handle to some
global Windows memory. The 'global' just means that it's
memory that can be accessed by every running application on
the system - it's part of the shared system resources. If
you need to 'dereference' this handle to get at the data
the global memory contains, you will need to understand a
little bit about the way in which Windows manages it's
global memory pool.
In straight C, a pointer is an actual address in the
programs memory address space. Normally by looking at the
address the pointer 'points' to you get at the data you are
after (or in the succeeding memory locations if the pointer
points to a memory 'structure').
Think of a memory handle as a 'pointer to a pointer to
memory', as the following diagram shows:
HANDLE -------> POINTER ----------> MEMORY
Handles allow Windows to move the memory around in the
global address space, as part of the Windows memory
management scheme. Whenever Windows moves the memory it
just updates the pointer value (which it keeps safely in
it's own internal tables). This means that the value of the
handle remains constant for the life of the memory (it's
just an index to that internal table).
When you actually need to access the memory you can ask
Windows for the current value of the pointer. At this point
Windows 'locks' the actual location of the memory, so that
it doesn't move while your accessing it! When you're
finished with the memory, you tell Windows to 'unlock' the
memory so that it can be moved again.
(For more information on this process, and the following
functions, refer to the manuals or online help for
Microsoft C/C++.)
To 'lock' a handle to some global memory so you can get a
pointer to the memory use:
PROCEDURE GlobalLock EXTERNAL "krnl386.exe":
DEFINE INPUT PARAMETER hmem AS SHORT.
DEFINE RETURN PARAMETER pmem AS MEMPTR.
END PROCEDURE.
GlobalLock accesses the pointer to the memory, and this is
the value of the RETURN PARAMETER of this function.
When you have finished accessing the memory use:
PROCEDURE GlobalUnlock EXTERNAL "krnl386.exe":
DEFINE INPUT PARAMETER hmem AS SHORT.
END PROCEDURE.
This releases the memory so that Windows can move it again
if it wants to. You can call the GlobalLock/GlobalUnlock
function pair as many times as you need to.
When you are finally finished with the memory you must
release the memory back to Windows. This is very important,
or you will get a memory 'leak' and Windows may eventually
run out of memory. The function is:
PROCEDURE GlobalFree EXTERNAL "krnl386.exe":
DEFINE INPUT PARAMETER hmem AS SHORT.
END PROCEDURE.
Below is an example of accessing a global memory handle
which is returned in a printer dialog setup structure, to
get at information about the current printer setup:
def var pprintdlg AS MEMPTR.
def var status-ok as integer.
def var pdevmode as MEMPTR.
PROCEDURE PrintDlg EXTERNAL "commdlg.dll":
DEFINE INPUT-OUTPUT PARAMETER pprintdlg AS MEMPTR.
DEFINE RETURN PARAMETER status-ok AS SHORT.
END PROCEDURE.
PROCEDURE GlobalLock EXTERNAL "krnl386.exe":
DEFINE INPUT PARAMETER hdevmode AS SHORT.
DEFINE RETURN PARAMETER pdevmode AS MEMPTR.
END PROCEDURE.
PROCEDURE GlobalUnlock EXTERNAL "krnl386.exe":
DEFINE INPUT PARAMETER hdevmode AS SHORT.
END PROCEDURE.
PROCEDURE GlobalFree EXTERNAL "krnl386.exe":
DEFINE INPUT PARAMETER hdevmode AS SHORT.
END PROCEDURE.
SET-SIZE(pprintdlg) = 52.
PUT-LONG(pprintdlg,1) = 52.
PUT-SHORT(pprintdlg, 25) = 5.
RUN PrintDlg(INPUT-OUTPUT pprintdlg, OUTPUT status-ok).
RUN GlobalLock(GET-SHORT(pprintdlg, 7),OUTPUT pdevmode).
DISPLAY GET-STRING(pdevmode, 1) LABEL "dmDeviceName".
RUN GlobalUnlock(GET-SHORT(pprintdlg, 7)).
RUN GlobalFree(GET-SHORT(pprintdlg, 7)).
Progress Software Technical Support Note # 13686