News:

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

Main Menu

HTML to RTF

Started by guga, June 08, 2013, 01:56:26 PM

Previous topic - Next topic

guga

Yves, how many converters are you testing ? (and which ones ?) - If possible can you tell me the version of them ?

Forcing them to or "eax,0FFFF0000h" will work only when the return value is the ones existent on the documentation,i.e. the negative 16 bits values. But it won´t work when they return an address.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

TouEnMasm

values  1 and 0 don't need change
all negative values are in 16 bits,and or eax,0FFFF0000h give the soluce.
Here how to filters the errors:
**** usage ********
put it just after the functions call,he is valid for the three named
He return a chain in pbuffer
eax == 1 ;no error
eax == 0 ;error pbuffer give the text of the error
the movzx instruction failed to transform a negative value of 16 bits in 32 bits.
I don't take care of the undocumented adress they return.
The doc give a good advise,use the registry.This method come in first in the doc.


;IsFormatCorrect32, ForeignToRtf32, and RtfToForeign32.
Errors PROC  uses edi pbuffer:DWORD
Local  retour:DWORD
         mov retour,0
mov edi,pbuffer
.if eax == 1
invoke lstrcpy,edi,TXT("IsFormatCorrect32 recognized the input file.")
mov retour,1
jmp FindeErrors
.elseif eax == 0
invoke lstrcpy,edi,TXT("IsFormatCorrect32 did not recognize the input file.",13,10,"Operation completed successfully for other APIs")
jmp FindeErrors
.endif
or eax,0FFFF0000h   ;16 32 bits
.if eax == -1
invoke lstrcpy,edi,TXT("IsFormatCorrect32 or ForeignToRtf32 was unable to open the input file.")
.elseif eax == -2
invoke lstrcpy,edi,TXT("There was an error reading from a file.")
.elseif eax == -4
invoke lstrcpy,edi,TXT("There was an error writing to a file.")
.elseif eax == -5
invoke lstrcpy,edi,TXT("There was invalid data in a document being",13,10,"imported through ForeignToRtf32.")
.elseif eax == -8
invoke lstrcpy,edi,TXT("The converter was unable to allocate memory for an operation.")
.elseif eax == -12
invoke lstrcpy,edi,TXT("RtfToForeign32 was unable to create its output file")
.elseif eax == -13
invoke lstrcpy,edi,TXT("The user cancelled the conversion operation")
.elseif eax == -14
invoke lstrcpy,edi,TXT("ForeignToRtf32 did not recognize the input file while attempting to convert it.")
.else
invoke lstrcpy,edi,TXT("Unknown error")
mov retour,1
.endif

FindeErrors:
         mov eax,retour
         ret
Errors endp
;################################################################


the doc on the subject
Quote
A converter can define and return additional error codes of its own, with numeric values more negative than -14. An application cannot be expected to know the meaning of any such codes, and should report a generic "Cannot open file" message. However, if the converter supplies the following optional API, the calling application may choose to call it to obtain a textual representation of any return value and use this to provide better diagnostics to the user.
long CchFetchLpszError(long fce, char *lpszError, long cb);
<fce>   ::=   An error code previously returned by the converter.
<lspzError>   ::=   A string into which the textual representation of fce should be copied.
<cb>   ::=   The size of lpszError in bytes.
If a converter chooses to provide this function, it must provide textual representations for all of the error values it returns, including the standard codes defined above. If lpszError is not large enough to contain the textual representation (including a terminating '\0'), or if fce does not refer to a valid error code, the converter should return 0. Otherwise, the converter should return the length of the error text in bytes, not counting the terminating '\0'. Because the strings provided by CchFetchLpszError may be displayed to the user, they need to be localized for foreign language versions of the converter.

all converters respects this:
Quote
When searching for a converter, an application searches this registry information. An application will likely search through its private converters first, and then it will search the shared converters. A converter may store additional information of its own under any class name key associated with it.
Here is an example set of registry entries for a shared converter that reads and writes WordPerfect 5.0 and 5.1 files. When exporting, it is important for the user to be able to select a specific minor version to save to, and so there are separate entries for 5.0 and 5.1. When importing, the converter can handle files of both minor version types, so only one entry is required.
HKEY_LOCAL_MACHINE\Software\Microsoft\Shared Tools\
   Text Converters\
      Export\
         WrdPrfctDos50\
            Extensions   "doc wpd"
            Name         "WordPerfect 5.0"
            Path         "C:\Progra~1\...\TextConv\wpft532.cnv"
         WrdPrfctDos51\
            Extensions   "doc"
            Name         "WordPerfect 5.1 for DOS"
            Path         "C:\Progra~1\...\TextConv\wpft532.cnv"
      Import\
         WrdPrfctDos\
            Extensions   "doc"
            Name         "WordPerfect 5.x"
            Path         "C:\Progra~1\...\TextConv\wpft532.cnv"

Fa is a musical note to play with CL

TouEnMasm

#122
Here my final release

The Imported file in rtf is named test.rtf and is located in the same directory as the execute
Export file will be named testeur with extension needed by the converter.
                                    Same directory as the execute
If one converter failed to initialise,choose another.
Begin by the menu files.Choose an export or import file,then convert menu, choose an export or import converter.

The richedit use the msfedit.dll and is a good converter by copy paste.Images can be added by another copy paste of the image.

Fa is a musical note to play with CL

guga

Yves how you manages to make it works fully ?

I´m stuck on something and i cannot find what a hell i´m doing wrong. I changed my code so many times, and then i reproduces what you did and yet...Nothing.

Some stupid "this file maybe corrupt" shows ups,while on yours, the same file is converted completelly.

This is yours routine
;################################################################
Importe_File PROC  pdll:DWORD,  pfile:DWORD
Local ghszFile:DWORD,ghszClass[50]:BYTE,gardesp:DWORD,ghClass
Local modulefilename[MAX_PATH]:BYTE,outputfile[MAX_PATH]:BYTE
Local  retour:DWORD
      mov retour,1
invoke convert_SearchAdresse,pdll
.if eax == 0
jmp FindeImporte_File
.endif
      mov retour,1
invoke GetModuleFileName,NULL,addr modulefilename,sizeof modulefilename
invoke lstrcpy,addr outputfile,addr modulefilename
invoke lstrlen,addr outputfile
lea edx,outputfile
add edx,eax
@@:
.if byte ptr [edx]!= "\"
dec edx
jmp @B
.endif
inc edx
invoke lstrcpy,edx,TXT("test.rtf")
mov edx,output.Hwnd
invoke InitConverter32,0,addr modulefilename
;invoke InitConverter32,NULL,NULL
.if eax != 0
;écriture de l'import
invoke CreateFile,addr outputfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,\
FILE_FLAG_SEQUENTIAL_SCAN, NULL
mov Converted_File,eax
mov ghClass,Fr(GlobalAlloc,GHND,4096)
invoke StringToGlobal,pfile ;addr parametre ;TXT("C:\Documents and Settings\Luce\Bureau\sansnom1.htm")
mov ghszFile,eax
mov ghBuf,Fr(GlobalAlloc,GHND, 4096)
;pas de istorage ,ghszClass retourne la classe
;verifie
invoke IsFormatCorrect32,ghszFile,ghClass
invoke GlobalToString,ghClass,addr ghszClass
;mov ghszClass,0
invoke MessageBox,NULL,addr ghszClass,TXT("format correct"),MB_OK

;---------------------------------------------------------------------

;--------------------------------------------------------------------
invoke     ForeignToRtf32,ghszFile, NULL, ghBuf,ghClass, NULL,WriteCallback
;--------------------------------------------------------------------
.if eax == 0
invoke MessageBox,NULL,TXT("reussite"),addr ghszClass,MB_OK
.else

invoke MessageBox,NULL,TXT("Failed"),addr ghszClass,MB_OK
.endif
invoke CloseHandle,Converted_File
invoke GlobalFree,ghszFile
invoke GlobalFree,ghBuf
invoke UninitConverter
.endif
invoke convert_FreeLibrary

FindeImporte_File:
         mov eax,retour
         ret
Importe_File endp



Mine is:

Proc DoConvert::
    Arguments @DocFileStruct, @lpszFileName, @FileLen
    Local @hMem, @ghClass
    Uses esi, edi, ecx, ebx
   
    call RegisterApp &NULL, &NULL
    On eax = 0, ExitP

    mov esi D@DocFileStruct
    mov eax D@FileLen | shl eax 8
    call VMemAlloc MemConvertedBuff, eax | mov D$CConverter.m_hBuff eax | mov D@hMem eax

    call 'kernel32.GlobalAlloc' &GHND, 4096 | mov D@ghClass eax
    call StringtoHGlobal D@lpszFileName | mov D$ghszFile eax
    call 'kernel32.GlobalAlloc' &GHND, 4096 | mov D$ghBuf eax
    ; here should be isformatcorrect32 ?
    call StringtoHGlobal D$esi+DocType.pszClassNameDis | mov D@ghClass eax

    call D$CConverter.m_ForeignToRtf  D$ghszFile, &NULL, D$ghBuf, D@ghClass, &NULL, WriteOut

    call 'kernel32.GlobalFree' D$ghszFile
    call 'kernel32.GlobalFree' D$ghBuf
    call 'kernel32.GlobalFree' D@ghclass
    mov eax D@hMem

EndP



Proc WriteOut:
    Arguments @cch, @nPercentComplete
    Local @size, @pMem

    mov eax D$CConverter.m_nPercent
    If eax <> D@nPercentComplete
        ; do something to print the percentage
        move D$CConverter.m_nPercent D@nPercentComplete
    End_If

    ;..If D@nPercentComplete <> 0
        ;move D$CConverter.m_nPercent D@nPercentComplete
        .If D@cch <> 0
            call 'KERNEL32.GlobalLock' D$ghBuf | mov D@pMem eax
            call StrCpyEx eax, D$CConverter.m_hBuff, D@cch
            mov eax D@cch
            add D$CConverter.m_hBuff eax
            If D$CConverter.m_nPercent = 100
                mov eax eax ; do something latwer. After fix this crap
            End_If

            call 'KERNEL32.GlobalUnlock' D$ghBuf
            mov eax 0
        ;.Else;_If eax = 0400

        .End_If
        mov eax 0
    ;..End_If

EndP


I have no more clues why it is refusing to translate completelly.

I´m uploading the file i´m using. The source code is embeded on it. You may open the file in rosasm to see the source code.

Btw: The registerapp makes no difference on the error, neither also the VirtualMemory allocation for the exports (Instead making it export directly, i intended to the rtf shows on the richtextbox, but the error message shows before the VirtualMemory is used - if i remove the VirtualMemoryit won´t change anything. The problem is somewhere else in the ghClass for example. Isn´t ghClass, in fact, part of a structure ?


What i noticed is that on mine callback, the percentage goes directly to 82 (or something), meaning that the converter idn´t parsed 100% of the file, while on yours, it goes from 0 to 2 4 6 8 .... 100

When you open/save a file you will see their classes and extensions and the path. (I´ll remove from the opendialog  filter the path later. I was just leave there to make sure it was using the correct converter
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

TouEnMasm

I don't know very well the rosasm syntax.
I can give you some advices.
-------- Don't use virtualloc to reserve memory,use GlobalAlloc
-------- All prototypes are STDCALL
-------- use dynamic link (getprocadress)
-------- The import functions are the more easy to use,try to made them work at first.
-------- load and unload dll needed to convert one file.

here is the final source code i used



Fa is a musical note to play with CL

guga

That´s weird. I tried on a simpler way using the same routines i made before, and now it worked !

There should be a problem somewhere else inside my code. Maybe a stack error that don´t crash.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

guga

OK, i´m quite done. The previous erroron the message was due to the usage of malloc in one of the routines.

There is a problem with the global alloc. I found where but don´t know how to fix it. The faultive routine is at:

Proc GetReadNames:
    Arguments @pOutName, @pOutDesc, @pOutExt
    Local @hClass, @hDesc, @hExt
    Uses ebx, ecx, edx

    call 'KERNEL32.GlobalAlloc' &GHND, 4096 | mov D@hClass eax
    call 'KERNEL32.GlobalAlloc' &GHND, 4096 | mov D@hDesc eax
    call 'KERNEL32.GlobalAlloc' &GHND, 4096 | mov D@hExt eax
    call D$CConverter.m_GetReadNames D@hClass, D@hDesc, D@hExt
    mov ecx D@hExt
    ...If_And eax >= &FCEWRONGFILETYPE, eax <= &FCEOPENINFILEERR, eax > &FCEUNREGISTERED, ax <= (&FCEOPENINFILEERR  shr 16)

        or eax 0FFFF0000 ; to keep the error in a 32 bits basis
        mov ebx eax

        mov eax D$ecx
        On B$eax <> 0, jmp L1> ; Ok, the extension address contains valid strings go to the proper routine
        mov ebx &FCEUNREGISTERED

    ...Else_If eax = D$ecx

        On B$eax <> 0, jmp L1> ; Ok, the extension address contains valid strings go to the proper routine
        mov ebx &FCEUNREGISTERED

    ...Else_If eax = &FCEUNREGISTERED
        ; aparently unregistered. Let´s check
        mov eax D$ecx
        On B$eax <> 0, jmp L1> ; Ok, the extension address contains valid strings go to the proper routine
        mov ebx &FCEUNREGISTERED

    ...Else_If eax = &FCENOERR
L1:
        mov eax D$ecx
        .If B$eax <> 0
            call GlobalToString D@hClass, D@pOutName; | mov eax D@pOutName
            call GlobalToString D@hDesc, D@pOutDesc
            call GlobalToString D@hExt, D@pOutExt
            mov ebx &FCENOERR
        .Else
            mov ebx &FCEUNREGISTERED ; seems trully unregistered
        .End_If
    ...Else
        ..If eax = ecx
            mov eax D$eax
            On B$eax <> 0, jmp L1<< ; There is a extension string inside, go back and copy to the proper buffers
            mov ebx &FCEUNREGISTERED
        ..Else
            mov ebx eax
        ..End_If
    ...End_If

    call 'kernel32.GlobalFree' D@hExt ; <---- here a internal error is generated
    call 'kernel32.GlobalFree' D@hDesc
    call 'kernel32.GlobalFree' D@hClass

    mov eax ebx
        ;for developments only
        ;call StoreReturnedValues D$PathStore, eax, D@pOutExt, 0
EndP


The function that calls it is:


________________________________________________________________________________________________________________________

[InfoStruct:
InfoStruct.ClassName: B$ 0 #260
InfoStruct.Desc: B$ 0 #260
InfoStruct.Ext: B$ 0 #260]
[Size_Of_InfoStruct 780]

Proc CheckForImportExport:
    Arguments @pDocType
    Local @GetReadNames, @GetWriteNames, @InitConverter, @UnitConverter, @hClass, @hDesc, @hExt, @pBuff
    Uses ebx, ecx, edx, esi, edi, eax

    mov esi D@pDocType
    call ConverterGetLibrary D$esi+DocType.pszPathDis
    ...If eax = &TRUE
                ; for development only
                ;move D$PathStore D$esi+DocType.pszPathDis
        call 'KERNEL32.GetProcAddress' D$CConverter.m_hLibCnv, {B$ "InitConverter32", 0} | mov D@InitConverter eax
        call 'KERNEL32.GetProcAddress' D$CConverter.m_hLibCnv, {B$ "CchFetchLpszError", 0} | mov D$CConverter.m_CchFetchLpszError eax
        call GetModuleName
        call D@InitConverter &NULL, eax
        .If eax <> &FCETRUE
            mov D$esi+DocType.bReadDis &FALSE
            mov D$esi+DocType.bWriteDis &FALSE
            mov D$esi+DocType.IsConverterRegisteredDis &FALSE
            jmp L8>>
        .End_If
        call ZeroMemory InfoStruct, Size_Of_InfoStruct
        call 'KERNEL32.GetProcAddress' D$CConverter.m_hLibCnv, {B$ "GetReadNames", 0} | mov D$CConverter.m_GetReadNames eax
        mov edi D$esi+DocType.pszPathDis
        ..If eax <> &FALSE
            mov edi InfoStruct.ClassName
            mov ebx InfoStruct.Desc
            mov ecx InfoStruct.Ext

            call GetReadNames edi, ebx, ecx
            .If eax = &FCEUNREGISTERED
                mov D$esi+DocType.bReadDis &FALSE
            .Else_If eax = &FCENOERR
                mov edx InfoStruct.Ext
                call AdjustExtensionsforEquality2 esi, edx, 0
                mov D$esi+DocType.bReadDis &TRUE
            .Else
                call ShowError eax
                mov eax D$esi+DocType.pszPathDis
                mov D$esi+DocType.bReadDis &FALSE
            .End_If
            mov eax D$esi+DocType.pszClassNameDis | call StrCpy edi, eax
            mov eax D$esi+DocType.pszDescriptionDis | call StrCpy ebx, eax
        ..Else
            ; special case for docm
            mov eax D$esi+DocType.pszDescriptionDis; | call StrCpy ebx, eax
        ..End_If

        call ZeroMemory InfoStruct, Size_Of_InfoStruct
        call 'KERNEL32.GetProcAddress' D$CConverter.m_hLibCnv, {B$ "GetWriteNames", 0} | mov D$CConverter.m_GetWriteNames eax
        ..If eax <> &FALSE

            mov edi InfoStruct.ClassName
            mov ebx InfoStruct.Desc
            mov ecx InfoStruct.Ext
            call GetWriteNames edi, ebx, ecx
            .If eax = &FCEUNREGISTERED
                mov D$esi+DocType.bWriteDis &FALSE
            .Else_If eax = &FCENOERR
                mov edx InfoStruct.Ext
                call AdjustExtensionsforEquality2 esi, edx, 1
                mov D$esi+DocType.bWriteDis &TRUE
            .Else
                call ShowError eax
                mov D$esi+DocType.bWriteDis &FALSE
            .End_If
            mov eax D$esi+DocType.pszExportClassNameDis | call StrCpy edi, eax
            mov eax D$esi+DocType.pszExportDescriptionDis | call StrCpy ebx, eax
        ..Else
            ; special case for docm
            move D$esi+DocType.pszExportDescriptionDis D$esi+DocType.pszDescriptionDis
        ..End_If

        If_And D$esi+DocType.bReadDis = &FALSE, D$esi+DocType.bWriteDis = &FALSE
            mov D$esi+DocType.IsConverterRegisteredDis &FALSE
        Else
            mov D$esi+DocType.IsConverterRegisteredDis &TRUE
        End_If
L1:

        call 'KERNEL32.GetProcAddress' D$CConverter.m_hLibCnv, {B$ "UninitConverter", 0} | mov D@UnitConverter eax
        If eax <> 0
            call eax
        End_If
    ...End_if
L8:
    call 'KERNEL32.FreeLibrary' D$CConverter.m_hLibCnv

EndP



Proc GlobalToString:
    Arguments @hGlobal, @pOutString
    Uses ecx, esi, edi, edx

    call 'KERNEL32.GlobalLock' D@hGlobal; | mov D@pGlob eax
    If D@pOutString <> 0
        call 'KERNEL32.lstrcpyA' D@pOutString, eax
    End_If
    call 'KERNEL32.GlobalUnlock' D@hGlobal
    mov eax &TRUE

EndP


Yves, the usage of globallloc on GetReadNames is correct ?
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

TouEnMasm

Quote
Yves, the usage of globallloc on GetReadNames is correct ?

Perfectly correct.All parameters in any functions use it.


Fa is a musical note to play with CL

guga

Damn..this globalalloc crappy functions are giving on my nervs :greensml:

I removed all virtuallloc, all thatwas supposedly to make this beats stops, and now..the error message showed up all over again.

Welll..i´ll gave a try recreating  the kernel32 globallloc to see what this thing is doing.

This is teh code i rebuilt so far


[BaseHeap: D$ 0]
[BaseHeapHandleTable:
BaseHeapHandleTable.Data1: D$ 0;0FFFF
BaseHeapHandleTable.Data2: D$ 0;8
BaseHeapHandleTable.Data3: D$ 0
BaseHeapHandleTable.Data4: D$ 0
BaseHeapHandleTable.Data5: D$ 0
BaseHeapHandleTable.Data6: D$ 0
BaseHeapHandleTable.Data7: D$ 0
BaseHeapHandleTable.Data8: D$ 0]
[BaseDllTag: D$ 0] ; always zero
; http://doxygen.reactos.org/d8/de2/heapmem_8c_ac2b59a3cb0f93ded5f4a6a3322ee6530.html#ac2b59a3cb0f93ded5f4a6a3322ee6530
[HeapHandle: D$ 0]

;;
// The handle structure for global heap handles.
// Notice that it nicely overlays with RTL_HANDLE_ENTRY.
// KEEP IT THAT WAY! ;-)
//
typedef struct _BASE_HEAP_HANDLE_ENTRY
{
    USHORT Flags;
    USHORT LockCount;
    union
    {
        PVOID Object;
        ULONG OldSize;
    };
} BASE_HEAP_HANDLE_ENTRY, *PBASE_HEAP_HANDLE_ENTRY;

http://www.ex-designz.net/apidetail.asp?api_id=235
http://pastebin.com/dLsdrRfe
http://typedescriptor.net/browse/members/1537452-System.Windows.Forms.XplatUIWin32+GAllocFlags.GMEM_NODISCARD#
http://doxygen.reactos.org/d1/d03/xdk_2mmtypes_8h_source.html
http://doxygen.reactos.org/d8/de2/heapmem_8c_ac2b59a3cb0f93ded5f4a6a3322ee6530.html#ac2b59a3cb0f93ded5f4a6a3322ee6530
http://doxygen.reactos.org/dd/dee/lib_2rtl_2handle_8c_a6885d17211e5cf96535a91eac5bb555e.html#a6885d17211e5cf96535a91eac5bb555e
_BaseDllInitializeMemoryManager@0 inside kernel32.dll


API Explanation
GlobalAlloc allocates a series of bytes in the computer's global memory. The memory can be used for any purpose necessary.
The function's return value, if successful, depends on the flags specified in wFlags. It will either be a pointer to the block of
allocated memory or a handle to the block of allocated memory. Although they both identify the same thing,
they will most likely not be equal and cannot be used interchangably! If the function fails, a value of 0 will be returned.
Note that Windows will not allocate a memory block starting at base address 0.

Parameter Information
Declare Function GlobalAlloc Lib "kernel32.dll" (ByVal wFlags _As Long, ByVal dwBytes As Long) As Long

wFlags:     One or more of the following flags specifying how to allocate the block of memory:
                GHND = &H40 Same as combining GMEM_MOVEABLE with GMEM_ZEROINIT.
                GMEM_DDESHARE = &H2000 Optimize the allocated memory for use in DDE conversations.
                GMEM_DISCARDABLE = &H100 Allocate discardable memory. (Cannot be combined with GMEM_FIXED.)
                GMEM_FIXED = &H0 Allocate fixed memory. The function's return value is a pointer to the beginning of the memory block. (Cannot be
                                 combined with GMEM_DISCARDABLE or GMEM_MOVEABLE.)
                GMEM_MOVEABLE = &H2 Allocate moveable memory. The memory block's lock count is initialized at 0 (unlocked). The function's return value
                                    is a handle to the beginning of the memory block. (Cannot be combined with GMEM_FIXED.)
                GMEM_NOCOMPACT = &H10 Do not compact any memory or discard any discardable memory to allocate the requested block.
                GMEM_NODISCARD = &H20 Do not discard any discardable memory to allocate the requested block.
                GMEM_SHARE = &H2000 Same as GMEM_DDESHARE.
                GMEM_ZEROINIT = &H40 Initialize the contents of the memory block to 0.
                GPTR = &H42 Same as combining GMEM_FIXED with GMEM_ZEROINIT.

dwBytes:    The number of bytes to allocate; i.e., the size of the memory block to allocate.

;;

[BASE_HEAP_HANDLE_ENTRY:
BASE_HEAP_HANDLE_ENTRY.Flags: W$ 0
BASE_HEAP_HANDLE_ENTRY.LockCount: W$ 0
BASE_HEAP_HANDLE_ENTRY.Object: D$ 0]

[BASE_HEAP_HANDLE_ENTRY.FlagsDis 0
BASE_HEAP_HANDLE_ENTRY.LockCountDis 2
BASE_HEAP_HANDLE_ENTRY.ObjectDis 4]

[Size_Of_BASE_HEAP_HANDLE_ENTRY 8]

[BASE_HEAP_ENTRY_FLAG_REUSABLE 4]
[HEAP_SETTABLE_USER_VALUE 0100]
[HEAP_SETTABLE_USER_FLAG1 0200]
[HEAP_SETTABLE_USER_FLAG2 0400]
[HEAP_SETTABLE_USER_FLAG3 0800]
[HEAP_SETTABLE_USER_FLAG4 0E00]

Proc GlobalAlloc2:
    Arguments @uFlags, @dwBytes
    Local @Flags, @Ptr, @hMemory

    ; probably createheap is better
    call 'kernel32.GetProcessHeap' | mov D$BaseHeap eax
    ;call 'ntdll.RtlInitializeHandleTable' 0FFFF, 8, BaseHeapHandleTable
    call RtlInitializeHandleTable 0FFFF, 8, BaseHeapHandleTable
    ; call 'ntdll.RtlCreateTagHeap' D$BaseHeap, &NULL, {U$ "BASEDLL!", 0}, {U$ "TMP", 0} <---Borrowed this crappy thing from the beginning of kernel32.dll. It simply initializes it and  return the BaseDllTag flags (Which are neeed for this function). Since BaseDllTag is always zero. This can be commented out.

    ; Make sure the flags are valid
    mov eax D@uFlags
    Test_If eax (not &GMEM_VALID_FLAGS)
        call 'KERNEL32.SetLastError' &ERROR_INVALID_PARAMETER
        xor eax eax
        ExitP
    Test_End

    xor edi edi
    mov D@Flags 0

    ; Convert ZEROINIT
    Test_If al &GMEM_ZEROINIT
        mov D@Flags &HEAP_ZERO_MEMORY
    Test_End

    ; Check if we're not movable, which means pointer-based heap
    ...Test_If al &GMEM_MOVEABLE
       
        ; This is heap based, so lock it in first
        call 'ntdll.RtlLockHeap' D$BaseHeap
        ; Disable locking, enable custom flags, and write the movable flag (deprecated)
        or W@Flags (&HEAP_NO_SERIALIZE+HEAP_SETTABLE_USER_VALUE+HEAP_SETTABLE_USER_FLAG1)
        ; Allocate the handle
        mov ebx BaseHeapHandleTable
        call 'ntdll.RtlAllocateHandle' BaseHeapHandleTable, &NULL
        mov esi eax
        mov D$HeapHandle esi

        ; Get the object and make sure we have size
        lea eax D$esi+BASE_HEAP_HANDLE_ENTRY.ObjectDis | mov D@hMemory eax

        ..If_or esi = 0, D@dwBytes = 0
            ; Fail
            call 'KERNEL32.SetLastError' &ERROR_NOT_ENOUGH_MEMORY
            call 'ntdll.RtlUnlockHeap' D$BaseHeap
            xor eax eax
            ExitP
        ..Else
           
            ; Allocate the actual memory for it; &MEM_TOP_DOWN
            mov edx D$BaseDllTag | add edx &MEM_TOP_DOWN | or edx D@Flags
            call 'ntdll.RtlAllocateHeap' D$BaseHeap, edx, D@dwBytes | mov D@Ptr eax
            .If eax = 0
                ;We failed, manually set the allocate flag and free the handle
                mov W$esi+BASE_HEAP_HANDLE_ENTRY.FlagsDis 1
                call 'ntdll.RtlFreeHandle' ebx, esi

                call 'KERNEL32.SetLastError' &ERROR_NOT_ENOUGH_MEMORY;&HEAP_ZERO_MEMORY
                call 'ntdll.RtlUnlockHeap' D$BaseHeap

                ;  For the cleanup case
                mov D$HeapHandle 0
                xor eax eax
                ExitP
            .Else
                ; All worked well, save our heap entry
                call 'ntdll.RtlSetUserValueHeap' D$BaseHeap, &HEAP_NO_SERIALIZE, D@Ptr, D@hMemory
            .End_If

            ; Cleanup! First unlock the heap
            call 'ntdll.RtlUnlockHeap' D$BaseHeap

        ..End_If

        mov edi D@Ptr
        mov D$esi+BASE_HEAP_HANDLE_ENTRY.ObjectDis edi

        If edi = 0
            mov eax (&HEAP_ZERO_MEMORY__&HEAP_NO_SERIALIZE)
        Else
            mov eax &HEAP_NO_SERIALIZE
        End_If


        mov W$esi+BASE_HEAP_HANDLE_ENTRY.FlagsDis ax
   
        Test_If D@uFlags 01 ; &GMEM_DISCARDABLE <---- What a hell this is doing inside WinXP ?????? There are no exceptions routines inside of this function. Except 2 not used local variables. (Remainings from VC compiler options? )
            or W$esi+BASE_HEAP_HANDLE_ENTRY.FlagsDis &HEAP_GENERATE_EXCEPTIONS;BASE_HEAP_ENTRY_FLAG_REUSABLE
        Test_End
   
        Test_If D@uFlags &GMEM_MOVEABLE
            or W$esi+BASE_HEAP_HANDLE_ENTRY.FlagsDis &HEAP_GROWABLE
        Test_End

        Test_If D@uFlags &GMEM_NODISCARD <---- What a hell this is doing inside WinXP ????
            or W$esi+BASE_HEAP_HANDLE_ENTRY.FlagsDis &HEAP_DISABLE_COALESCE_ON_FREE
        Test_End
   
        mov eax D@hMemory

    ...Test_Else
        ; Check if this is GMEM_NODISCARD (obsolete) <---- What a hell this is doing inside WinXP ????
        Test_If ah &GMEM_NODISCARD
            or D@Flags &HEAP_GENERATE_EXCEPTIONS; or BASE_HEAP_ENTRY_FLAG_REUSABLE;B$ebp-01B 04
        Test_End
   
        ; Allocate heap for it
        If D@dwBytes = 0
            inc D@dwBytes
        End_If
        mov edx D$BaseDllTag | add edx &MEM_TOP_DOWN | or edx D@Flags
        call 'ntdll.RtlAllocateHeap' D$BaseHeap, edx, D@dwBytes
        If eax = 0
            call 'KERNEL32.SetLastError' &ERROR_NOT_ENOUGH_MEMORY
            xor eax eax
        End_If
    ...Test_End

EndP




;;
PARAMS
MaxHandleCount  [In] The maximum number of handles the handle table will support.
HandleSize  [In] The size of each handle.
HandleTable  [In/Out] The handle table.

from ntdll.dll RtlInitializeHandleTable
http://source.winehq.org/WineAPI/RtlInitializeHandleTable.html
;;

Proc RtlInitializeHandleTable:
    Arguments @MaxHandleCount, @HandleSize, @pHandleTable
    Uses edi, edx, ecx

    mov edx D@pHandleTable
    mov edi edx
    xor eax eax
    mov ecx 8
    rep stosd
    mov eax D@MaxHandleCount
    mov D$edx eax
    mov eax D@HandleSize
    mov D$edx+4 eax
EndP


The more i saw inside kernel32 the more weird it looks, the globalalloc function is fully framed and contains obsolete flags. Well....i recreated and it was and will try to test and update fix later. Now it is missing globallock, globalfree and globarealloc.

I´ll try to recode at least globallock and globalfree to test on my app those routines. Later i´ll fire RosAsm debugger on all of them to see where exactly it is crashing and why.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

guga

Well..at the end....no matter how i´m struggling with this, i´m also updating RosAsm code as well :bgrin:


Here are some undocumented nt equates added for the NtQuerySystemInformation function

SYS_NFO_MAX_SYSTEM_INFOCLASS 095
SYS_NFO_SYSTEM_ACPIAUDIT_INFORMATION 07A
SYS_NFO_SYSTEM_AITSAMPLINGVALUE 06F
SYS_NFO_SYSTEM_BADPAGE_INFORMATION 080
SYS_NFO_SYSTEM_BASIC_INFORMATION 0
SYS_NFO_SYSTEM_BASICPERFORMANCE_INFORMATION 07B
SYS_NFO_SYSTEM_BIGPOOL_INFORMATION 042
SYS_NFO_SYSTEM_BOOTENTROPY_INFORMATION 075
SYS_NFO_SYSTEM_BOOTENVIRONMENT_INFORMATION 05A
SYS_NFO_SYSTEM_BOOTGRAPHICS_INFORMATION 07E
SYS_NFO_SYSTEM_BOOTLOGO_INFORMATION 08C
SYS_NFO_SYSTEM_CALLCOUNT_INFORMATION 06
SYS_NFO_SYSTEM_CALLTIME_INFORMATION 0A
SYS_NFO_SYSTEM_CODEINTEGRITY_INFORMATION 067
SYS_NFO_SYSTEM_COMBINEPHYSICALMEMORY_INFORMATION 082
SYS_NFO_SYSTEM_COMPLUSPACKAGE 03B
SYS_NFO_SYSTEM_CONSOLE_INFORMATION 084
SYS_NFO_SYSTEM_CONTEXTSWITCH_INFORMATION 024
SYS_NFO_SYSTEM_COVERAGE_INFORMATION 05F
SYS_NFO_SYSTEM_CPUQUOTA_INFORMATION 071
SYS_NFO_SYSTEM_CRASHDUMP_INFORMATION 020
SYS_NFO_SYSTEM_CRASHDUMPSTATE_INFORMATION 022
SYS_NFO_SYSTEM_CURRENTTIMEZONE_INFORMATION 02C
SYS_NFO_SYSTEM_DEVICE_INFORMATION 07
SYS_NFO_SYSTEM_DEVICEDATA_INFORMATION 088
SYS_NFO_SYSTEM_DEVICEDATAENUMERATION_INFORMATION 089
SYS_NFO_SYSTEM_DPCBEHAVIOR_INFORMATION 018
SYS_NFO_SYSTEM_DYNAMICTIMEZONE_INFORMATION 066
SYS_NFO_SYSTEM_EMULATIONBASIC_INFORMATION 03E
SYS_NFO_SYSTEM_EMULATIONPROCESSOR_INFORMATION 03F
SYS_NFO_SYSTEM_ENTROPYINTERRUPTTIMING_INFORMATION 083
SYS_NFO_SYSTEM_ENTROPYINTERRUPTTIMINGRAW_INFORMATION 092
SYS_NFO_SYSTEM_ERRORPORT_INFORMATION 059
SYS_NFO_SYSTEM_ERRORPORTTIMEOUTS 073
SYS_NFO_SYSTEM_EXCEPTION_INFORMATION 021
SYS_NFO_SYSTEM_EXTENDEDHANDLE_INFORMATION 040
SYS_NFO_SYSTEM_EXTENDEDPROCESS_INFORMATION 039
SYS_NFO_SYSTEM_EXTENDSERVICETABLE_INFORMATION 026
SYS_NFO_SYSTEM_FILECACHE_INFORMATION 015
SYS_NFO_SYSTEM_FILECACHEINFORMATIONEX 051
SYS_NFO_SYSTEM_FIRMWARETABLE_INFORMATION 04C
SYS_NFO_SYSTEM_FLAGS_INFORMATION 09
SYS_NFO_SYSTEM_FULLMEMORY_INFORMATION 019
SYS_NFO_SYSTEM_FULLPROCESS_INFORMATION 094
SYS_NFO_SYSTEM_HANDLE_INFORMATION 010
SYS_NFO_SYSTEM_HOTPATCH_INFORMATION 045
SYS_NFO_SYSTEM_HYPERVISOR_INFORMATION 05B
SYS_NFO_SYSTEM_HYPERVISORPROCESSORCOUNT_INFORMATION 087
SYS_NFO_SYSTEM_IMAGEFILEEXECUTIONOPTIONS_INFORMATION 05E
SYS_NFO_SYSTEM_INTERRUPT_INFORMATION 017
SYS_NFO_SYSTEM_KERNELDEBUGGER_INFORMATION 023
SYS_NFO_SYSTEM_LEGACYDRIVER_INFORMATION 02B
SYS_NFO_SYSTEM_LOADGDIDRIVER_INFORMATION 01A
SYS_NFO_SYSTEM_LOADGDIDRIVERIN_SYSTEM_SPACE 036
SYS_NFO_SYSTEM_LOCKS_INFORMATION 0C
SYS_NFO_SYSTEM_LOGICALPROCESSOR_INFORMATION 049
SYS_NFO_SYSTEM_LOGICALPROCESSORANDGROUP_INFORMATION 06B
SYS_NFO_SYSTEM_LOOKASIDE_INFORMATION 02D
SYS_NFO_SYSTEM_LOSTDELAYEDWRITE_INFORMATION 041
SYS_NFO_SYSTEM_LOWPRIORITYIO_INFORMATION 074
SYS_NFO_SYSTEM_MEMORYCHANNEL_INFORMATION 08B
SYS_NFO_SYSTEM_MEMORYLIST_INFORMATION 050
SYS_NFO_SYSTEM_MEMORYTOPOLOGY_INFORMATION 08A
SYS_NFO_SYSTEM_MIRRORMEMORY_INFORMATION 01E
SYS_NFO_SYSTEM_MODULE_INFORMATION 0B
SYS_NFO_SYSTEM_MODULEINFORMATIONEX 04D
SYS_NFO_SYSTEM_NATIVEBASIC_INFORMATION 072
SYS_NFO_SYSTEM_NODEDISTANCE_INFORMATION 079
SYS_NFO_SYSTEM_NONPAGEDPOOL_INFORMATION 0F
SYS_NFO_SYSTEM_NUMAAVAILABLEMEMORY 03C
SYS_NFO_SYSTEM_NUMAPROCESSORMAP 037
SYS_NFO_SYSTEM_NUMAPROXIMITYNODE_INFORMATION 065
SYS_NFO_SYSTEM_OBJECT_INFORMATION 011
SYS_NFO_SYSTEM_OBJECTSECURITYMODE 046
SYS_NFO_SYSTEM_PAGEDPOOL_INFORMATION 0E
SYS_NFO_SYSTEM_PAGEDPOOLINFORMATIONEX 077
SYS_NFO_SYSTEM_PAGEFILE_INFORMATION 012
SYS_NFO_SYSTEM_PAGEFILEINFORMATIONEX 090
SYS_NFO_SYSTEM_PATH_INFORMATION 04
SYS_NFO_SYSTEM_PERFORMANCE_INFORMATION 02
SYS_NFO_SYSTEM_PERFORMANCETRACE_INFORMATION 01F
SYS_NFO_SYSTEM_PLATFORMBINARY_INFORMATION 085
SYS_NFO_SYSTEM_POOLTAG_INFORMATION 016
SYS_NFO_SYSTEM_PORTABLEWORKSPACEEFILAUNCHER_INFORMATION 093
SYS_NFO_SYSTEM_PREFETCHER_INFORMATION 038
SYS_NFO_SYSTEM_PREFETCHPATCH_INFORMATION 060
SYS_NFO_SYSTEM_PRIORITYSEPERATION 027
SYS_NFO_SYSTEM_PROCESS_INFORMATION 05
SYS_NFO_SYSTEM_PROCESSID_INFORMATION 058
SYS_NFO_SYSTEM_PROCESSOR_INFORMATION 01
SYS_NFO_SYSTEM_PROCESSORBRANDSTRING 069
SYS_NFO_SYSTEM_PROCESSORCYCLETIME_INFORMATION 06C
SYS_NFO_SYSTEM_PROCESSORIDLE_INFORMATION 02A
SYS_NFO_SYSTEM_PROCESSORIDLECYCLETIME_INFORMATION 053
SYS_NFO_SYSTEM_PROCESSORMICROCODEUPDATE_INFORMATION 068
SYS_NFO_SYSTEM_PROCESSORPERFORMANCE_INFORMATION 08
SYS_NFO_SYSTEM_PROCESSORPERFORMANCEDISTRIBUTION 064
SYS_NFO_SYSTEM_PROCESSORPERFORMANCEINFORMATIONEX 08D
SYS_NFO_SYSTEM_PROCESSORPOWER_INFORMATION 03D
SYS_NFO_SYSTEM_PROCESSORPOWERINFORMATIONEX 055
SYS_NFO_SYSTEM_PROCESSORPROFILECONTROLAREA 081
SYS_NFO_SYSTEM_QUERYPERFORMANCECOUNTER_INFORMATION 07C
SYS_NFO_SYSTEM_RANGESTART_INFORMATION 032
SYS_NFO_SYSTEM_RECOMMENDEDSHAREDDATAALIGNMENT 03A
SYS_NFO_SYSTEM_REFTRACE_INFORMATION 056
SYS_NFO_SYSTEM_REGISTERFIRMWARETABLEINFORMATIONHANDLER 04B
SYS_NFO_SYSTEM_REGISTRYAPPENDSTRING 06E
SYS_NFO_SYSTEM_REGISTRYQUOTA_INFORMATION 025
SYS_NFO_SYSTEM_SCRUBPHYSICALMEMORY_INFORMATION 07F
SYS_NFO_SYSTEM_SECUREBOOT_INFORMATION 091
SYS_NFO_SYSTEM_SECUREBOOTPOLICY_INFORMATION 08F
SYS_NFO_SYSTEM_SESSION_INFORMATION 031
SYS_NFO_SYSTEM_SESSIONBIGPOOL_INFORMATION 07D
SYS_NFO_SYSTEM_SESSIONCREATE 02F
SYS_NFO_SYSTEM_SESSIONDETACH 030
SYS_NFO_SYSTEM_SESSIONMAPPEDVIEW_INFORMATION 044
SYS_NFO_SYSTEM_SESSIONPOOLTAG_INFORMATION 043
SYS_NFO_SYSTEM_SESSIONPROCESS_INFORMATION 035
SYS_NFO_SYSTEM_SPARE0 08E
SYS_NFO_SYSTEM_SPECIALPOOL_INFORMATION 057
SYS_NFO_SYSTEM_STACKTRACE_INFORMATION 0D
SYS_NFO_SYSTEM_STORE_INFORMATION 06D
SYS_NFO_SYSTEM_SUMMARYMEMORY_INFORMATION 01D
SYS_NFO_SYSTEM_SUPERFETCH_INFORMATION 04F
SYS_NFO_SYSTEM_SYSTEM_DISK_INFORMATION 063
SYS_NFO_SYSTEM_SYSTEM_PARTITION_INFORMATION 062
SYS_NFO_SYSTEM_SYSTEM_PTESINFORMATIONEX 078
SYS_NFO_SYSTEM_THREADPRIORITYCLIENTID_INFORMATION 052
SYS_NFO_SYSTEM_THROTTLENOTIFICATION_INFORMATION 086
SYS_NFO_SYSTEM_TIMEADJUSTMENT_INFORMATION 01C
SYS_NFO_SYSTEM_TIMEOFDAY_INFORMATION 03
SYS_NFO_SYSTEM_TIMESLIPNOTIFICATION 02E
SYS_NFO_SYSTEM_TIMEZONE_INFORMATION 05D
SYS_NFO_SYSTEM_UNLOADGDIDRIVER_INFORMATION 01B
SYS_NFO_SYSTEM_VDMBOP_INFORMATION 014
SYS_NFO_SYSTEM_VDMINSTEMUL_INFORMATION 013
SYS_NFO_SYSTEM_VERIFIER_INFORMATION 033
SYS_NFO_SYSTEM_VERIFIERADDDRIVER_INFORMATION 028
SYS_NFO_SYSTEM_VERIFIERCANCELLATION_INFORMATION 054
SYS_NFO_SYSTEM_VERIFIERCOUNTERS_INFORMATION 076
SYS_NFO_SYSTEM_VERIFIERFAULTS_INFORMATION 061
SYS_NFO_SYSTEM_VERIFIERINFORMATIONEX 05C
SYS_NFO_SYSTEM_VERIFIERREMOVEDRIVER_INFORMATION 029
SYS_NFO_SYSTEM_VERIFIERTHUNKEXTEND 034
SYS_NFO_SYSTEM_VERIFIERTRIAGE_INFORMATION 04E
SYS_NFO_SYSTEM_VHDBOOT_INFORMATION 070
SYS_NFO_SYSTEM_VIRTUALADDRESS_INFORMATION 06A
SYS_NFO_SYSTEM_WATCHDOGTIMER_INFORMATION 048
SYS_NFO_SYSTEM_WATCHDOGTIMERHANDLER 047
SYS_NFO_SYSTEM_WOW64SHAREDINFORMATIONOBSOLETE 04A


Example of usage:

; SYSTEM_RANGE_START_INFORMATION Structure. Only 1 dword
[SystemRangeStart: D$ 0]

[Size_Of_SYSTEM_RANGE_START_INFORMATION 4]

call 'ntdll.NtQuerySystemInformation' &SYS_NFO_SYSTEM_RANGESTART_INFORMATION, SystemRangeStart, Size_Of_SYSTEM_RANGE_START_INFORMATION, 0


Ref: http://www.exploit-monday.com/2013/06/undocumented-ntquerysysteminformation.html
http://home.aubg.bg/students/TNG104/Dev-Cpp/include/ddk/ntapi.h
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724509%28v=vs.85%29.aspx
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

guga

GlobalLock and GlobalHandle functions


Proc GlobalLock:
    Arguments @hMem
    Uses ebx, edi, ecx, esi, edx

    mov ebx D@hMem

    ; Check if this was a simple allocated heap entry. I.e.: this is a simple alignment check for memory aligned at 4 bytes
    .Test_If bl &BASE_HANDLE_MARK_BIT

        call 'ntdll.RtlLockHeap' D$BaseHeap

        lea esi D$ebx-BASE_HANDLE_TABLE_ENTRY.ObjectDis ; points to BASE_HANDLE_TABLE_ENTRY
        call 'ntdll.RtlIsValidHandle' BaseHeapHandleTable, esi

        mov edi D$esi+BASE_HANDLE_TABLE_ENTRY.ObjectDis

        .If al = 0
            call 'KERNEL32.SetLastError' &ERROR_INVALID_HANDLE
            xor edi edi ;i added here
        .Else_If edi = 0
            call 'KERNEL32.SetLastError' &ERROR_DISCARDED
        .Else
            xor eax eax
            mov ax W$esi+BASE_HANDLE_TABLE_ENTRY.LockCountDis
            lea ecx D$eax+1 ;what happens if ecx > &GMEM_LOCKCOUNT ???
            mov W$esi+BASE_HANDLE_TABLE_ENTRY.LockCountDis cx
            If ax = &GMEM_LOCKCOUNT
                dec W$esi+BASE_HANDLE_TABLE_ENTRY.LockCountDis
            End_If
        .End_If

        call 'ntdll.RtlUnlockHeap' D$BaseHeap
        mov eax edi

    .Test_Else
        ; Otherwise, lock the heap
        call 'kernel32.IsBadReadPtr' ebx, 1  ; Make sure it's not a kernel or invalid address
        .If_Or ebx >= D$SystemRangeStart, eax <> 0
            call 'KERNEL32.SetLastError' &ERROR_INVALID_HANDLE
            xor eax eax
        .Else
            ; It's all good
            mov eax ebx
        .End_If

    .Test_End

EndP



Proc GlobalHandle:
    Arguments @pMem
    Local @Flags, @Handle, @ReturnValue
    Uses ebx, ecx, edx, esi

    call 'ntdll.RtlLockHeap' D$BaseHeap
    mov D@ReturnValue 0
    mov D@Handle 0
    mov D@Flags 0
    lea ebx D@Flags
    lea eax D@Handle
    call 'ntdll.RtlGetUserInfoHeap' D$BaseHeap, &HEAP_NO_SERIALIZE, D@pMem, eax, ebx
    .If al = 0
        call 'kernel32.SetLastError' &ERROR_INVALID_HANDLE
    .Else
        If D@Handle <> 0
            Test_If D@Flags &BASE_HEAP_FLAG_MOVEABLE
                move D@ReturnValue D@Handle
            Test_End
        End_If
    .End_If
    call 'ntdll.RtlUnlockHeap' D$BaseHeap
    mov eax D@ReturnValue

EndP



For those equates and structures eventually posted here that are undocumented. I updated it in RosAsm files at:
Portal


The internal variables inside kernel32 are initialized by each system on the user´s current process. For example, the variable BaseHeap is easily achieved with:
call 'kernel32.GetProcessHeap' | mov D$BaseHeap eax
The returned value is the exact same one as inside kernel32.dll that uses this variable to deal with the global/local functions.

Other internal initializtions variables, i inserted on a own function called "InitGlobalMem". This functionshould be initialized any time you want to use the global functions.(or, i´ll create a separated dll for all of them, which is better, IMHO)

Why rebuilding global functions ? Well, because the ones inside kernel32 are utterly faultive. Some apps and dlls still uses them, instead using virtual allocation memory functions or heap functions. And since the RTFtoHTML converters uses them, and it is common to lead to stack problems, i´m rebuilding them to seek exactly why/how/where they are giving randomic errors, fix them so we can use them more easily without so much pain.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

guga

I´m updating GlobalAlloc.Imade a wrong translation of the original source,and i found out that, the older version of it inside windowsNT is exact teh same one as existent in WinXP. The only difference is the amount of allocated bytes for the heap. According to the WindowsNT source code (The one that was leaked) the function is:


Proc GlobalAlloc_NT:
    Arguments @uFlags, @dwBytes
    Local @Flags, @Ptr, @hMemory, @TmpBytes, @HandleEntry
    Uses ebx, ecx, edx, edi, esi

    ; Make sure the flags are valid
    mov eax D@uFlags
    Test_If eax (not &GMEM_VALID_FLAGS)
        call 'KERNEL32.SetLastError' &ERROR_INVALID_PARAMETER
        xor eax eax
        ExitP
    Test_End

    ;xor edi edi
    mov D@Flags 0

    ; Convert ZEROINIT
    Test_If D@Flags &GMEM_ZEROINIT
        mov D@Flags &HEAP_ZERO_MEMORY
    Test_End

    ; Check if we're not movable, which means pointer-based heap
    .Test_If_Not D@uFlags &GMEM_MOVEABLE
        Test_If D@uFlags &GMEM_DDESHARE
            or D@Flags &BASE_HEAP_FLAG_DDESHARE
        Test_End
        If D@dwBytes <> 0
            move D@TmpBytes D@dwBytes
        Else
            mov D@TmpBytes 1
        End_If
        MAKE_TAG &GMEM_TAG | or eax D@Flags
        call 'ntdll.RtlAllocateHeap' D$BaseHeap, eax, D@TmpBytes | mov D@Ptr eax
        If eax = 0
            call 'KERNEL32.SetLastError' &ERROR_NOT_ENOUGH_MEMORY
            mov eax D@Ptr
            ExitP
        End_If
        ExitP
    .Test_End

    mov D@Ptr 0
    ; This is heap based, so lock it in first
    call 'ntdll.RtlLockHeap' D$BaseHeap
    ; Disable locking, enable custom flags, and write the movable flag (deprecated)
    or D@Flags (&HEAP_NO_SERIALIZE+&HEAP_SETTABLE_USER_VALUE+&BASE_HEAP_FLAG_MOVEABLE)
    ; Allocate the handle
    call 'ntdll.RtlAllocateHandle' BaseHeapHandleTable, &NULL | mov D@HandleEntry eax
    If eax = 0
        call 'KERNEL32.SetLastError' &ERROR_NOT_ENOUGH_MEMORY
        jmp @Fail
    End_If
    mov eax D@HandleEntry | add eax BASE_HANDLE_TABLE_ENTRY.ObjectDis | mov D@hMemory eax

    .If D@dwBytes <> 0
        MAKE_TAG &GMEM_TAG | or eax D@Flags
        call 'ntdll.RtlAllocateHeap' D$BaseHeap, eax, D@dwBytes | mov D@Ptr eax
        If eax = 0
            mov esi D@HandleEntry
            mov W$esi+BASE_HANDLE_TABLE_ENTRY.FlagsDis &RTL_HANDLE_ALLOCATED
            call 'ntdll.RtlFreeHandle' BaseHeapHandleTable, esi
            call 'KERNEL32.SetLastError' &ERROR_NOT_ENOUGH_MEMORY
        Else
            call 'ntdll.RtlSetUserValueHeap' D$BaseHeap, &HEAP_NO_SERIALIZE, D@Ptr, D@hMemory
        End_If
    .End_If

@Fail:

    ; Cleanup! First unlock the heap
    call 'ntdll.RtlUnlockHeap' D$BaseHeap
    ...If D@HandleEntry <> 0
        mov edx D@HandleEntry
        mov eax D@Ptr
        mov D$edx+BASE_HANDLE_TABLE_ENTRY.ObjectDis eax
        If D@Ptr <> 0
            mov W$edx+BASE_HANDLE_TABLE_ENTRY.FlagsDis &RTL_HANDLE_ALLOCATED
        Else
            mov W$edx+BASE_HANDLE_TABLE_ENTRY.FlagsDis &RTL_HANDLE_ALLOCATED__&BASE_HANDLE_DISCARDED
        End_If

        Test_If D@Flags &GMEM_DISCARDABLE
            or W$edx+BASE_HANDLE_TABLE_ENTRY.FlagsDis &BASE_HANDLE_DISCARDABLE
        Test_End

        Test_If D@Flags &GMEM_MOVEABLE
            or W$edx+BASE_HANDLE_TABLE_ENTRY.FlagsDis &BASE_HANDLE_MOVEABLE
        Test_End

        Test_If D@Flags &GMEM_DDESHARE
            or W$edx+BASE_HANDLE_TABLE_ENTRY.FlagsDis &BASE_HANDLE_SHARED
        Test_End

        move D@Ptr D@hMemory
    ...End_If
    mov eax D@Ptr

EndP


But, on newer Windows versions the only change Microsoft programmers did was change GMEM_TAG equate from MAKE_TAG macro with HEAP_TAG_SHIFT equate. So, the GloballAlloc function since WindowsXp is translated as:


Proc GlobalAlloc3::
    Arguments @uFlags, @dwBytes
    Local @Flags, @Ptr, @hMemory, @HandleEntry
    Uses ebx, ecx, edx, edi, esi

    ; Make sure the flags are valid
    mov eax D@uFlags
    Test_If D@uFlags (not &GMEM_VALID_FLAGS)
        call 'KERNEL32.SetLastError' &ERROR_INVALID_PARAMETER
        xor eax eax
        ExitP
    Test_End

    xor edi edi
    mov D@Flags 0

    ; Convert ZEROINIT
    Test_If D@uFlags &GMEM_ZEROINIT
        mov D@Flags &HEAP_ZERO_MEMORY
    Test_End

    ; Check if we're not movable, which means pointer-based heap
    .Test_If_Not D@uFlags &GMEM_MOVEABLE
        Test_If D@uFlags &GMEM_DDESHARE
            or D@Flags &BASE_HANDLE_DISCARDABLE
        Test_End
        If D@dwBytes = 0
            inc D@dwBytes
        End_If
        MAKE_TAG &HEAP_TAG_SHIFT | or eax D@Flags
        call 'ntdll.RtlAllocateHeap' D$BaseHeap, eax, D@dwBytes | mov D@Ptr eax
        If eax = 0
            call 'KERNEL32.SetLastError' &ERROR_NOT_ENOUGH_MEMORY
            xor eax eax
            ExitP
        End_If
        mov eax D@Ptr
        ExitP
    .Test_End

    mov D@Ptr 0
    ; This is heap based, so lock it in first
    call 'ntdll.RtlLockHeap' D$BaseHeap
    ; Disable locking, enable custom flags, and write the movable flag (deprecated)
    or D@Flags (&HEAP_NO_SERIALIZE+&HEAP_SETTABLE_USER_VALUE+&BASE_HEAP_FLAG_MOVEABLE)
    ; Allocate the handle
    call 'ntdll.RtlAllocateHandle' BaseHeapHandleTable, &NULL | mov esi eax
    mov D@HandleEntry esi
    ..If eax = 0
        call 'KERNEL32.SetLastError' &ERROR_NOT_ENOUGH_MEMORY
    ..Else

        lea eax D$esi+BASE_HANDLE_TABLE_ENTRY.ObjectDis
        mov D@hMemory eax
   
        .If D@dwBytes <> 0
            MAKE_TAG &HEAP_TAG_SHIFT | or eax D@Flags
            call 'ntdll.RtlAllocateHeap' D$BaseHeap, eax, D@dwBytes | mov edi eax
            mov D@Ptr edi
            If edi = 0
                mov W$esi+BASE_HANDLE_TABLE_ENTRY.FlagsDis &RTL_HANDLE_ALLOCATED
                call 'ntdll.RtlFreeHandle' BaseHeapHandleTable, esi
                xor esi esi
                mov D@HandleEntry 0
                call 'KERNEL32.SetLastError' &ERROR_NOT_ENOUGH_MEMORY
            Else
                call 'ntdll.RtlSetUserValueHeap' D$BaseHeap, &HEAP_NO_SERIALIZE, D@Ptr, D@hMemory
            End_If
        .End_If

    ..End_If
; Fail

    ; Cleanup! First unlock the heap
    call 'ntdll.RtlUnlockHeap' D$BaseHeap
    .If esi = 0
        mov D$esi+BASE_HANDLE_TABLE_ENTRY.ObjectDis edi

        If edi = &NULL
            mov eax (&BASE_HANDLE_DISCARDED__&RTL_HANDLE_ALLOCATED)
        Else
            mov eax &RTL_HANDLE_ALLOCATED
        End_If
        mov W$esi+BASE_HANDLE_TABLE_ENTRY.FlagsDis ax

        Test_If D@Flags &GMEM_DISCARDABLE
            or W$esi+BASE_HANDLE_TABLE_ENTRY.FlagsDis &BASE_HANDLE_DISCARDABLE
        Test_End

        Test_If D@Flags &GMEM_MOVEABLE
            or W$esi+BASE_HANDLE_TABLE_ENTRY.FlagsDis &BASE_HANDLE_MOVEABLE
        Test_End   

        Test_If D@Flags &GMEM_DDESHARE
            or W$esi+BASE_HANDLE_TABLE_ENTRY.FlagsDis &BASE_HANDLE_SHARED
        Test_End

        mov edi D@hMemory
    .End_If
    mov eax edi

EndP


So, the current C source code for globallalloc is:


HGLOBAL
WINAPI
GlobalAlloc(
UINT uFlags,
DWORD dwBytes
)
{
PBASE_HANDLE_TABLE_ENTRY HandleEntry;
HANDLE hMem;
LPSTR p;
ULONG Flags;

if (uFlags & ~GMEM_VALID_FLAGS) {
SetLastError( ERROR_INVALID_PARAMETER );
return( NULL );
}

Flags = 0;
if (uFlags & GMEM_ZEROINIT) {
Flags |= HEAP_ZERO_MEMORY;
}

if (!(uFlags & GMEM_MOVEABLE)) {
if (uFlags & GMEM_DDESHARE) {
Flags |= BASE_HEAP_FLAG_DDESHARE;
}

p = RtlAllocateHeap( BaseHeap,
MAKE_TAG( HEAP_TAG_SHIFT ) | Flags,
dwBytes ? dwBytes : 1
);

if (p == NULL) {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}

return p;
}

p = NULL;
RtlLockHeap( BaseHeap );
Flags |= HEAP_NO_SERIALIZE | HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVEABLE;
try {
HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)RtlAllocateHandle( &BaseHeapHandleTable, NULL );
if (HandleEntry == NULL) {
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
goto Fail;
}

hMem = (HANDLE)&HandleEntry->Object;
if (dwBytes != 0) {
p = (LPSTR)RtlAllocateHeap( BaseHeap, MAKE_TAG( HEAP_TAG_SHIFT ) | Flags, dwBytes );
if (p == NULL) {
HandleEntry->Flags = RTL_HANDLE_ALLOCATED;
RtlFreeHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry );
HandleEntry = NULL;
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
}
else {
RtlSetUserValueHeap( BaseHeap, HEAP_NO_SERIALIZE, p, hMem );
}
}
Fail:   ;
}
except (EXCEPTION_EXECUTE_HANDLER) {
BaseSetLastNTError( GetExceptionCode() );
}

RtlUnlockHeap( BaseHeap );

if (HandleEntry != NULL) {
HandleEntry->Object = p;
if (p != NULL) {
HandleEntry->Flags = RTL_HANDLE_ALLOCATED;
}
else {
HandleEntry->Flags = RTL_HANDLE_ALLOCATED | BASE_HANDLE_DISCARDED;
}

if (uFlags & GMEM_DISCARDABLE) {
HandleEntry->Flags |= BASE_HANDLE_DISCARDABLE;
}

if (uFlags & GMEM_MOVEABLE) {
HandleEntry->Flags |= BASE_HANDLE_MOVEABLE;
}

if (uFlags & GMEM_DDESHARE) {
HandleEntry->Flags |= BASE_HANDLE_SHARED;
}

p = (LPSTR)hMem;
}

return( (HANDLE)p );
}


Kernel32.dll source was compiled with the ommiting FramePoint checkbox enabled on the VisualStudio compiler, this explains the mess inside.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

guga

Finally got it working as expected.

The problem was at IsFormatCorrect function. When it was being used, there was a overloading of global memory usage causing the converter to not convert completely the file. I simply removed this function and will build later a new routine to use it, but it seems that each function to be used for the converter must be uninitialized (at least some of them) ?

Anyway...here is the preliminary tests of the alpha version of the app. Now that it is working i can start building the proper converter dll and apis for us to use on any projects we want.

Note: Rebuilding the kernel32 global functions did not succeeded as expected, probably because to the internal pointers and heap allocations of those functions...But....some of the global functions i made can be used, but as far i saw not in sequence. I removed them from my project anyway, since now it is starting to work as expected.

Btw..the name of the file "finalmente2b.exe" is only a joke which means "finally" in portuguese (It was what i said when this worked)  :greensml:

The next versions will name it accordingly :bgrin:

And..no...it cannot export in html, etc, yet...The exported files will be always in rtf format no matter the extension you name it. (This is another stage)....it was hard enough make this thing import anyway...export is another story ;)
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

jj2007

Quote from: guga on July 07, 2013, 04:57:41 PM
The problem was at IsFormatCorrect function.

Yes, I had noticed that, too. And in fact, you don't need it because ForeignToRtf32 reports errors anyway.

guga

HI JJ

QuoteForeignToRtf32 reports errors anyway

Not always. I have some html files that simply crashes when passing to ForeignToRtf32. Some crashes when the html contains at 1st the string "<xml", because the converter is limited and cannot parse correctly the full file. When it finds this kind of error it simply keeps looping inside it´s own dll untill the crash happens.

Also....it is better to never use registerapp, since it completely ruins the registry. I had a lot of trouble trying to identify the error after the registry was ruined by  this function. I´ll take a look inside this function to see how it alters the registry in order to fix the internal errors.

The file i upload now is able to check the converters for import and export, choose automatically for the last version of them (when you have different versions of the same converter, of course) ,  check if the the converter is  registered (and therefore can be used - specially the new ones that does a registry check internally), and finally can convert html to rtf, doc to rtf, xls to rtf, lotus to rtf, docm/docx to rtf, mcw to rtf, wps/wpt to rtf, wpd to rtf,ans to rtf, outlook scheduler to rtf, doc (word2x untill officeXp (that ins installed here) for windows and Macintosh to RTF.

Also, the app identify the vulnerable converters that are not registered, such as:
    write32.wpc - vulnerable
    mswrd632.wpc - vulnerable
    works432.cnv - vulnerable

I was thinking in enabling a routine to warn the user if he wants to register those kind of files,but after reading M$ security updates and some forums, i choose not to enable them. Better would be write later a converter for wri files.

The next versions i´ll clean up the code, create a function to export the proper config files (to avoid scanning the registry every time the app is loaded.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com