News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

GlobalFree error

Started by mabdelouahab, March 22, 2015, 04:24:54 AM

Previous topic - Next topic

mabdelouahab

Hi everyone
I wanted to save a PNG file in the RESSOURCE,
But when I wanted to use it, it appeared to me an error makes the program ends, and exactly at GlobalFree : Stream
when used before the function  GlobalFree : buffer or  HeapFree : buffer ,
It concluded that they did not work together, but only one of them
Does one tell me why ?

getPNG proc
LOCAL _hInst,_rcRes,_hResData,_sizeOfRes,_hHeap,_hbuffer,_pIStream,_hIStream,_hBitmap
invoke GetModuleHandle,NULL
mov _hInst,eax
invoke  FindResource, _hInst, 1011, RT_RCDATA
.if eax
mov _rcRes, eax
invoke  LoadResource, _hInst, _rcRes
mov _hResData, eax
invoke  SizeofResource, _hInst, _rcRes
mov _sizeOfRes, eax
invoke  GetProcessHeap
mov _hHeap,eax
invoke  HeapAlloc,_hHeap,0,_sizeOfRes
mov _hbuffer, eax
invoke  RtlMoveMemory, _hbuffer, _hResData, _sizeOfRes
invoke  CreateStreamOnHGlobal, _hbuffer, TRUE, addr _pIStream
;============================================================
;invoke  GdipCreateBitmapFromStream, _pIStream,addr _hBitmap
;============================================================
invoke  HeapFree,_hHeap,0,_hbuffer
invoke  GetHGlobalFromStream, _pIStream, addr _hIStream
;invoke  GlobalFree, _hIStream

;mov eax,_hBitmap
.else
xor eax,eax
.endif
ret
getPNG endp
getPNG2 proc
LOCAL _hInst,_rcRes,_hResData,_sizeOfRes,_hHeap,_hbuffer,_pbuffer,_pIStream,_hIStream,_hBitmap
invoke GetModuleHandle,NULL
mov _hInst,eax
invoke  FindResource, _hInst, 1011, RT_RCDATA
.if eax
mov _rcRes, eax
invoke  LoadResource, _hInst, _rcRes
mov _hResData, eax
invoke  SizeofResource, _hInst, _rcRes
mov _sizeOfRes, eax

invoke GlobalAlloc, GMEM_MOVEABLE, _sizeOfRes
mov _hbuffer, eax
invoke GlobalLock, _hbuffer
mov _pbuffer, eax
invoke  RtlMoveMemory, _pbuffer, _hResData, _sizeOfRes
invoke  CreateStreamOnHGlobal, _pbuffer, TRUE, addr _pIStream
;============================================================
;invoke  GdipCreateBitmapFromStream, _pIStream,addr _hBitmap
;============================================================
invoke  GetHGlobalFromStream, _pIStream, addr _hIStream
invoke  GlobalFree, _hIStream
invoke GlobalUnlock,  _hbuffer
invoke GlobalFree,_pbuffer

;mov eax,_hBitmap
.else
xor eax,eax
.endif
ret
getPNG2 endp

mabdelouahab

Windows 7 32bit ,RadAsm, ML.exe V11

dedndave

http://masm32.com/board/index.php?topic=3124.0

i also seem to recall using GlobalLock and GlobalUnlock - may have been for something else
yah - you're creating a stream on HGLOBAL - not a pointer - locking probably not needed

fearless

Ive used pretty much the same code - to do the same thing, load a png from a resource (resdata) and display it using the gdi+ functions. Corruption of jpeg and png occurs if the hIStream is released with GlobalFree - done some searching on the topic in google and I either read or came to the conclusion (cant remember which) that hIStream needs to be available for the life of the bitmap in use. Once you are finished with that bitmap then hIStream can be freed with GlobalFree.

    invoke    GdipCreateBitmapFromStream, pIStream, pBitmapFromStream
   
    ; ------------------------------------------------------------------
    ; STEP 5: Free all used locks and resources
    ; ------------------------------------------------------------------
    invoke    GetHGlobalFromStream, pIStream, addr hIStream ;  googling shows underlying stream needs to be left open for the life of the bitmap
    ;invoke    GlobalFree, hIStream ; have to comment this to prevent corruption, free elsewhere once done with the bitmap.
    invoke    GlobalUnlock, hbuffer
    invoke    GlobalFree, hbuffer
    mov eax, hIStream

mabdelouahab

hi fearless, dedndave
When I use GlobalFree, hIStream without use of GlobalFree, hbuffer is everything okay, and when I use GlobalFree, hbuffer without use of GlobalFree, hIStream  is everything okay, but the error occurs when used together.
dedndave, I understand from your response it is recommended to use:

mov   ecx,_pIStream
push  ecx
mov   eax,[ecx]
call  DWORD PTR [eax + 8]
invoke GlobalUnlock,  _hbuffer
invoke GlobalFree,_pbuffer

Is it sufficient to Release, only without the use of GlobalFree, hIStream ?
fearless, also it went well with: http://masm32.com/board/index.php?topic=3472.msg36561#msg36561, why did not work this time I think I have neglected something

adeyblue

Since you set the second param of CreateStreamOnHGlobal to TRUE you don't have to GlobalFree anything. Just call Release on the interface and it'll do it automatically. You have to call Release anyway or you leak the interface so you might as well let it do the cleanup.

You can also avoid doing the allocation manually by using the IStream's Write method, which'll do it for you. I don't know the macro trickery used for COM interface calls, so the coinvokes below will need to be modified to that, but this is one way you could rewrite your function.


getPNG2 proc
LOCAL _hInst,_rcRes,_hResData,_sizeOfRes,_hHeap,_hbuffer,_pbuffer,_pIStream,_hIStream,_hBitmap
invoke GetModuleHandle,NULL
mov _hInst,eax
invoke  FindResource, _hInst, 1011, RT_RCDATA
.if eax
mov _rcRes, eax
invoke  LoadResource, _hInst, _rcRes
mov _hResData, eax
invoke  SizeofResource, _hInst, _rcRes
mov _sizeOfRes, eax

invoke  CreateStreamOnHGlobal, 0, TRUE, addr _pIStream ; first zero tells the function to do the allocation
coinvoke IStream_Write, _pIStream, _hResData, _sizeOfRes, 0 ; this copies the resource data to the stream
;============================================================
invoke  GdipCreateBitmapFromStream, _pIStream,addr _hBitmap
;============================================================
coinvoke  IStream_Release, _pIStream

mov eax,_hBitmap
.else
xor eax,eax
.endif
ret
getPNG2 endp


There's some functions in Vista+ shlwapi.dll that can directly wrap the resource in an IStream so no allocation is required at all, but they're undocumented and have to be GetProcAddress-ed, so it doesn't really make the code any shorter.

mabdelouahab

Thank you adeyblue

getPNG2 proc
LOCAL _rcRes,_hResData,_sizeOfRes,_pIStream,_hBitmap

invoke  FindResource, 0, 1011, RT_RCDATA
.if eax
mov _rcRes, eax
mov _hResData, rv(LoadResource, 0, _rcRes)
mov _sizeOfRes, rv(SizeofResource, 0, _rcRes)

invoke  CreateStreamOnHGlobal, 0, TRUE, addr _pIStream ; first zero tells the function to do the allocation
xor eax,eax
push eax
push _sizeOfRes
push _hResData
mov  edx,_pIStream
push  edx
mov    edx,[edx]
call    dword ptr [edx + 16] ;coinvoke IStream_Write, _pIStream, _hResData, _sizeOfRes, 0 ; this copies the resource data to the stream
;============================================================
invoke  GdipCreateBitmapFromStream, _pIStream,addr _hBitmap
;============================================================
mov    edx,_pIStream
push    edx
mov    edx,[edx]
call    dword ptr [edx + 8] ;coinvoke  IStream_Release, _pIStream

mov eax,_hBitmap
.else
xor eax,eax
.endif
ret
getPNG2 endp

:t