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
Windows 7 32bit ,RadAsm, ML.exe V11
http://masm32.com/board/index.php?topic=3124.0 (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
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
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
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.
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