Skip to content

Latest commit

 

History

History
102 lines (75 loc) · 3.36 KB

sample_156.md

File metadata and controls

102 lines (75 loc) · 3.36 KB

Home

Copying strings through the global memory block

Code:

#DEFINE GMEM_FIXED     0
#DEFINE GMEM_MOVEABLE  2
DO decl

	LOCAL lcTarget, lcSource, lnAllocSize, hMem, lnAddr

	lcSource = "Copying a string through an allocated memory object"
	lnAllocSize = Len(lcSource)
	lcTarget = SPACE(lnAllocSize) && the destination string is empty

	? "*** Before"
	? "Source string:     ", lcSource
	? "Destination string:", lcTarget
	?

	* allocating an amount of memory capable of storing
	* the source string (not Unicode)
	hMem = GlobalAlloc (GMEM_MOVEABLE, lnAllocSize)

	IF hMem <> 0
	
		* lock the memory block to get its address
		* WinNT: both can be identical
		lnAddr = GlobalLock (hMem)
		? "Memory object handle:", hMem
		? "Memory block address:", lnAddr
		?

		DECLARE RtlMoveMemory IN kernel32 As String2Heap;
			INTEGER Destination, STRING @ Source,;
			INTEGER nLength

		* copying source string -> allocated memory object
		= String2Heap (lnAddr, @lcSource, lnAllocSize)

		* every time you must re-declare this function
		* because this time you call with different parameter types
		DECLARE RtlMoveMemory IN kernel32 As Heap2String;
			STRING @ Destination, INTEGER Source,;
			INTEGER nLength

		* copying allocated memory object -> destination string
		= Heap2String (@lcTarget, lnAddr, lnAllocSize)

		* testing the results
		? "*** After"
		? "Source string:     ", lcSource
		? "Destination string:", lcTarget

		* releasing the medium
		= GlobalUnlock (hMem)
		= GlobalFree (hMem)
	ENDIF

PROCEDURE  decl
	DECLARE INTEGER GlobalFree IN kernel32 INTEGER hMem

	DECLARE INTEGER GlobalAlloc IN kernel32;
		INTEGER wFlags, INTEGER dwBytes

	DECLARE INTEGER GlobalLock IN kernel32 INTEGER hMem
	DECLARE INTEGER GlobalUnlock IN kernel32 INTEGER hMem  

Listed functions:

GlobalAlloc
GlobalFree
GlobalLock
GlobalUnlock

Comment:

This code demonstrates how to move binary data to and from global memory blocks. The source VFP string is copied into an allocated global memory block. Then content of this block is copied into the destination string. There is no direct usefulness in this code -- just a demonstration.

In some situations you need to pass to a structure (not to a function, that is easy) the 4-byte pointer to a string -- LPCSTR, or LPCTSTR.

As an example, to run some printer functions you must supply the DOCINFO structure:

typedef struct {   
    int     cbSize;   
    LPCTSTR lpszDocName;   
    LPCTSTR lpszOutput;   
    LPCTSTR lpszDatatype;  
    DWORD   fwType;   
} DOCINFO, *LPDOCINFO;

Within this structure lpszDocName is not a string, but a pointer to a string with a defined document name -- e.g. "My Printer Job".

That means, you must allocate this string in memory and pass the pointer to the structure. Using global memory functions makes this task possible. At that time -- to my knowledge -- there is no regular function in VFP to return a pointer to a string.

If GMEM_FIXED being used instead of GMEM_MOVEABLE you can avoid using the GlobalLock and GlobalUnlock couple. With GMEM_FIXED you receive a pointer comparing to a handle to the memory object for the GMEM_MOVEABLE.