The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Mark Jones on March 09, 2005, 04:34:14 AM

Title: GobalAlloc --> Edit Control
Post by: Mark Jones on March 09, 2005, 04:34:14 AM
Hi, is it common or even possible to "lie" and pass a GlobalAlloc pointer as a string to an edit control? I'm trying to load a tiny text file into an edit control and everything works right up to the actual call to SetDlgItemText, where it crashes. It will display the string if it is not buffered in a GlobalAlloc.


Invoke CreateFile, Addr ofnBuffer, GENERIC_READ, FILE_SHARE_READ, \ ; open file
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ; handle in eax
Mov hOpenFile, Eax
Invoke GetFileSize, Eax, NULL ; get size
Inc Eax ; add a null
Mov intOpenFileSize, Eax ; save
Invoke GlobalAlloc, GPTR, Eax ; allocate sizeof file + 1
Mov hOpenGlobalAlloc, Eax ; save GlobalAlloc handle
Invoke ReadFile, hOpenFile, Addr hOpenGlobalAlloc,\ ; read file into ram
DWord Ptr intOpenFileSize, Addr intNumBytesRead, 0

; * either of these will cause GPF
Invoke MessageBox, hWnd, Addr hOpenGlobalAlloc, Addr ofnBuffer, MB_OK
Invoke SetDlgItemText, hWnd, IDC_TSC_EDIT1, Addr hOpenGlobalAlloc

Invoke CloseHandle, hOpenFile ; close file
Invoke GlobalFree, hOpenGlobalAlloc ; free memory


Looking at the contents of the GlobalAlloc memory address at runtime, it appears to be entirely valid as a string. But why does SetDlgItemText crash? Thanks. :)
Title: Re: GobalAlloc --> Edit Control
Post by: Dark Schneider on March 09, 2005, 05:43:19 AM
I'm not sure about this one but here it goes...

You didn't called GlobalLock so you can't just pass the handle you get right away.
When calling GlobalAlloc, try using GMEM_FIXED flag to get a passable address returned in EAX and you may pass it to SetDlgItemText.

- - - - - - - - - - - - - - - - - - - -
untested code
- - - - - - - - - - - - - - - - - - - -

Invoke GlobalAlloc, GMEM_FIXED, eax
mov hOpenGlobalAlloc,  eax
   
Invoke ReadFile, hOpenFile, hOpenGlobalAlloc, intOpenFileSize, ADDR intNumBytesRead, 0

; before proceeding you should test EAX here to see if you actually get that data or not

Invoke MessageBox, hWnd, hOpenGlobalAlloc, Addr ofnBuffer, MB_OK
Invoke SetDlgItemText, hWnd, IDC_TSC_EDIT1, hOpenGlobalAlloc

Invoke GlobalFree, hOpenGlobalAlloc
Invoke CloseHandle, hOpenFile

;Try it.  :green
Title: Re: GobalAlloc --> Edit Control
Post by: Tedd on March 09, 2005, 12:37:51 PM
Schneider:
GPTR = (GMEM_FIXED or GMEM_ZEROINIT)
So that's not a problem.

Mark:
I don't see anything immediately wrong with that code (at a glance.)
But have a look at the EM_SETHANDLE and EM_GETHANDLE messages - they allow you to get/set the memory the edit box uses (only works for 'system' edit boxes, not richedit.)
Title: Re: GobalAlloc --> Edit Control
Post by: Relvinian on March 09, 2005, 04:03:26 PM
Mark,

The two things I noticed from your code with using GlobalAlloc and your SetDlgItemText.

1) Make sure you use GlobalLock which will give you a handle back to the "buffer" portion of your memory.
2) With the value you get back from GlobalLock, it is a POINTER so you don't need to use ADDR in your ReadFile or SetDlgItemText calls.

Make sure you unlock it when done.

Relvinian
Title: Re: GobalAlloc --> Edit Control
Post by: Mark Jones on March 09, 2005, 05:29:11 PM
Thanks guys. I originally tried GlobalLock but noticed upon debugging that it did not modify EAX as it returned, so it does not generate a new handle. Reading the Win32.hlp a few times, it sounds like the flag GMEM_FIXED implies that the return value is simply a pointer to the memory (FIXED == already locked.)

hOpenGlobalAlloc at runtime == 0040E0A0, and debugging that offset clearly shows the read filedata there, which consists of a few lines of text. Hmm, aaaha! Found the problem. hOpenGlobalAlloc at runtime is OFFSET 0040E0A0, a dword pointer, not the returned value from GlobalAlloc - the returned value is actually something like 0015E948. So ReadFile was putting the data at the wrong location, overwriting other vars and whatnot. Whoops! Simple confusion between ADDR and Dword PTR. :) Here is the working code:


Invoke CreateFile, Addr ofnBuffer, GENERIC_READ, FILE_SHARE_READ, \  ; open file
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0                           ; handle in eax
Mov hOpenFile, Eax                                                   ; save file handle
Invoke GetFileSize, Eax, NULL                                        ; get size
Inc Eax                                                              ; add a null
Mov intOpenFileSize, Eax                                             ; save
Invoke GlobalAlloc, GPTR, Eax                                        ; allocate sizeof file + 1
Mov hOpenGlobalAlloc, Eax                                            ; save GlobalAlloc handle
Invoke ReadFile, hOpenFile, Dword Ptr hOpenGlobalAlloc,\             ; read file into ram
DWord Ptr intOpenFileSize, Addr intNumBytesRead, 0
Invoke SetDlgItemText, hWnd, IDC_TSC_EDIT1, Dword Ptr hOpenGlobalAlloc
Invoke CloseHandle, hOpenFile                                        ; close file
Invoke GlobalFree, hOpenGlobalAlloc                                  ; free memory
Title: Re: GobalAlloc --> Edit Control
Post by: Grincheux on March 09, 2005, 07:30:31 PM
Why do you use GlobalAlloc/GlobalLock ?
If you used VirtualAlloc you make the same thing with only one call ?

Philippe
Title: Re: GobalAlloc --> Edit Control
Post by: Tedd on March 10, 2005, 11:39:36 AM
Note to everyone who suggests using GlobalLock:

When using GlobalAlloc with GMEM_FIXED (or GPTR) there's no need to lock it - it's allocated immediately and returns the address of the memory block, not the memory handle.
So attempting to lock it will obviously fail.
Title: Re: GobalAlloc --> Edit Control
Post by: Relvinian on March 10, 2005, 06:10:54 PM
Quote from: IDCat on March 09, 2005, 07:30:31 PM
Why do you use GlobalAlloc/GlobalLock ?
If you used VirtualAlloc you make the same thing with only one call ?

Philippe

The only reason I would use GlobalAlloc is for the Win32 APIs which require a HGLOBAL handle. This type of allocation isn't defined with GMEM_FIXED but GMEM_MOVABLE.

Otherwise, for the majority of my allocations, I use HeapAlloc and VirtualAlloc.

There are times when I may use other allocating routines if I know I'm going to use different API calls which may require some other type of allocations.

Relvinian
Title: Re: GobalAlloc --> Edit Control
Post by: Mark Jones on March 11, 2005, 02:32:50 PM
I chose GlobalAlloc because of its simplicity: just feed it a size and it spits out a R/W mem pointer, no fuss. But VirtualAlloc has some cool features.
Title: Re: GobalAlloc --> Edit Control
Post by: Dark Schneider on March 14, 2005, 05:17:49 AM
Tedd:

hmmm... I forgot about that one.

Mark Jones:

I think dword ptr is not needed, did you tried my code above?
Title: Re: GobalAlloc --> Edit Control
Post by: Mark Jones on March 14, 2005, 05:23:17 PM
Indeed, it works without the Dword Ptr. Sometimes assembler is so confusing: addr, offset, dword ptr, dereferencing, etc. Some commands want pointers, some want offsets, some want data... :dazzled:  Sometimes I just try all the qualifiers until one works. That and parse the output in Ollydbg - Ctrl-F, "NOP", enter, F2, F9. Repeat Ad Nauseum. :)

I see that edit boxes have their own default buffer. Apparently this can be directly accessed by:

1. Retrieve the handle of the buffer currently allocated by sending the control an EM_GETHANDLE msg.
2. Free the buffer by calling the LocalFree function.
3. Obtain a new buffer (and buffer handle) by calling LocalAlloc. (GlobalAlloc is the same in Win32)
4. Give the buffer handle to Windows by sending the control an EM_SETHANDLE message.


I'll try that next, to eliminate the redundant buffering. :)

よろしく、
マルク