News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

HeapCreate, HeapAlloc problems

Started by FlySky, October 05, 2013, 05:32:09 PM

Previous topic - Next topic

FlySky

Guys,

Below is a bit of code I am using to allocate memory into my process:

   //Create heap/ allocate memory to use as a buffer, we could also use GetProcessHeap api
   invoke HeapCreate, NULL, 4000h, NULL
   mov [ResultBuffer], eax
   invoke HeapAlloc, [ResultBuffer], HEAP_ZERO_MEMORY, 1000h
   invoke GetLastError
   mov [ResultBufferTemp], eax

HeapCreate returns a handle to the newly created heap just fine.
The problem is that HeapAlloc than refuses to work it always returns 0.
Using GetLastError to determine which error occurs it's also always 0.

Now I've been using google and found an old topic from 2003 from another board link posted:

http://www.asmcommunity.net/forums/topic/?id=10676

The guy in this post also uses GoASM and has the exact same problem.
Although he was using WinNT, I am using Windows 8 Professional 64 bit.
Is this a bug in GoASM or a bug in my code? I can't seem to figure it out.
Using GetProcessHeap instead of HeapCreate the problem is still the same.

jj2007

   invoke HeapAlloc, [ResultBuffer], HEAP_ZERO_MEMORY, 1000h
   invoke GetLastError
   mov [ResultBufferTemp], eax
   invoke GetLastError

dedndave

there's usually no need to create a heap
the OS creates one for each process

        .DATA?
hHeap   HANDLE ?
lpBlock LPVOID ?
dwError DWORD  ?
        .CODE


what i generally do is, during program initialization....
    INVOKE  GetProcessHeap
    mov     hHeap,eax


then, to allocate memory and set an error condition, you might do something like this...
    and     dwError,0
    INVOKE  HeapAlloc,hHeap,HEAP_ZERO_MEMORY,1000h
    mov     lpBlock,eax
    .if !eax
        INVOKE  GetLastError
        mov     dwError,eax
        xor     eax,eax
    .endif

i don't usually store the error condition like that
if the allocation fails, i either provide some other method (like VirtualAlloc)
or give them a MessageBox that says Insufficient Memory and terminate the program

and, to free the allocated block when done...
    mov     eax,lpBlock
    .if eax
        xor     ecx,ecx
        mov     lpBlock,ecx
        INVOKE  HeapFree,hHeap,ecx,eax
    .endif

FlySky

Thanks for the answers guys.

I just installed VMWare with WindowsXP and guess what on WindowsXP the code works perfectly fine.
Although the same code refuses to work on Windows 8 64 bit for me.
I guess GoASM needs to get an update for this 'bug', or windows 8 is just really picky.

sinsi

Quote from: jj2007 on October 05, 2013, 05:36:10 PM
   invoke HeapAlloc, [ResultBuffer], HEAP_ZERO_MEMORY, 1000h
   invoke GetLastError
   mov [ResultBufferTemp], eax
   invoke GetLastError
Sorry jj, according to MSDN "NULL indicates failure. If the function fails, it does not call SetLastError"

dedndave

not like a lot can go wrong - lol
GetLastError isn't really necessary
either you have crummy parameters - or there isn't enough memory

jj2007

Quote from: sinsi on October 05, 2013, 07:50:25 PM
Quote from: jj2007 on October 05, 2013, 05:36:10 PM
   invoke HeapAlloc, [ResultBuffer], HEAP_ZERO_MEMORY, 1000h
   invoke GetLastError
   mov [ResultBufferTemp], eax
   invoke GetLastError
Sorry jj, according to MSDN "NULL indicates failure. If the function fails, it does not call SetLastError"

I didn't check that. I was just a bit worried that using the return value of GetLastError as a buffer address could cause minor problems :greensml:

FlySky

Quote from: dedndave on October 05, 2013, 07:57:51 PM
not like a lot can go wrong - lol
GetLastError isn't really necessary
either you have crummy parameters - or there isn't enough memory

I do tend to believe it's a bug with GoASM. The link I posted to the topic from 10 years ago described the same problem using GoASM.
Doing it in XP fixed it for that guy aswell, the same counts for me.
XP it's working fine so parameters are fine aswell.
Something must be causing GoASM to fail and I have no clue what it could be.

Edit:
I just tested the coding using MASM on Windows 8.
The code on Windows 8 using MASM is working perfectly fine, so it has to be a bug in GoASM darn!.

jj2007

Quote from: FlySky on October 05, 2013, 08:10:39 PMThe code on Windows 8 using MASM is working perfectly fine, so it has to be a bug in GoASM darn!.

Nonsense, there is no bug in GoAsm, there is a horrible fat noob error in your copy & paste code.
Reflect a little bit what you are loading into ResultBufferTemp after a call to GetLastError, and stop guessing around. Instead, read replies to your posts more carefully.

   invoke HeapAlloc, [ResultBuffer], HEAP_ZERO_MEMORY, 1000h
   invoke GetLastError
   mov [ResultBufferTemp], eax

FlySky

jj2007 if you don't know what I am seeing, and you can't because you're not here you can stop pretending that I have no clue what I am talking about.
I am not going to make a freaking movie just to prove I am right.
After the call to HeapAlloc the resulting value in EAX = 00000000.

Using the code in MASM: It works fine no errors and the call is going fine -> WindowsXP and Windows 8
Using the code in GoASM: On WindowsXP it works on Windows 8 it does not.

If it's a bug or not fact is the code does not work on Windows 8, and that's what I am asking help with.
You're reactions are just sh*t so stop making them.

It has nothing to do with the GetLastError API I placed there sheeez mister wise guy.

jj2007

Quote from: FlySky on October 05, 2013, 09:07:42 PM
After the call to HeapAlloc the resulting value in EAX = 00000000.

What I see is your code ...
   invoke GetLastError
   mov [ResultBufferTemp], eax
... and under normal circumstances ResultBufferTemp is indeed zero, because that's what GetLastError normally returns in eax after a simple (and normally successful) HeapAlloc.

Now if HeapAlloc really returns zero, fine, apologies for the misunderstanding, but again, blaming GoAsm is legitimate only if you put an int 3 in front of the HeapAlloc and tell us, according to Olly or WinDbg, what was wrongly assembled by GoAsm. If it assembles fine under Masm, then it shouldn't be too difficult to produce the two disassemblies and post them here so that we can compare them.
:icon14: ?

dedndave

let's view the complete snippet that you originally posted
   //Create heap/ allocate memory to use as a buffer, we could also use GetProcessHeap api
   invoke HeapCreate, NULL, 4000h, NULL
   mov [ResultBuffer], eax
   invoke HeapAlloc, [ResultBuffer], HEAP_ZERO_MEMORY, 1000h
   invoke GetLastError
   mov [ResultBufferTemp], eax


the problem with that snippet is that the EAX result of HeapAlloc is destroyed when the call is made to GetLastError
and, as the HeapAlloc result is not stored first, we can safely assume the code will not work
it doesn't matter if you run it under XP, win 7, or win 8   :P

it may be a successful call, but the allocated memory is unusable because you don't have the address
and - you won't be able to free the allocated block for the same reason

wjr

This may be related to a bug which I recently uncovered while working on the next GoLink update. On the 64-bit side, the application would generally crash, but I saw that under certain circumstances there could be a 32-bit problem as well. This occurs with a forwarded function in a DLL which has the Export Directory Tables not in the .text section (typically the case now for 64-bit system DLLs using .rdata instead).

If you use a tool such as, oh let's see now, how about PEview... on Windows 8, does the SysWOW64 32-bit Kernel32.dll have the "EXPORT Address Table" in the .rdata section?

jj2007


FlySky

Quote from: wjr on October 06, 2013, 04:49:02 AM
This may be related to a bug which I recently uncovered while working on the next GoLink update. On the 64-bit side, the application would generally crash, but I saw that under certain circumstances there could be a 32-bit problem as well. This occurs with a forwarded function in a DLL which has the Export Directory Tables not in the .text section (typically the case now for 64-bit system DLLs using .rdata instead).

If you use a tool such as, oh let's see now, how about PEview... on Windows 8, does the SysWOW64 32-bit Kernel32.dll have the "EXPORT Address Table" in the .rdata section?

I did some more testings aswell, it has indeed to to with the forwarded functions.
When I follow the code inside a debugger it never jumps into the proper kernel32 function.
The HeapAlloc function is forwarded from kernel32.dll to ntdll.dll and it seems GoASM isn't properly building the jump table for it.
So when the call goes to the jump table to read the API, the program does not call HeapAlloc but picks the next API from the Import Address Table.

On Windows 8 (64 bit) the SysWow64 kernel32.dll has the following in the .rdata section:
Export Directory: 000E1D70
Import Directory: 000D9EFC

I solved it by dynamicly linking ntdll.dll to the project and invoke HeapAlloc by using invoke RtlAllocateHeap instead.