Jump to content
Tuts 4 You

How to walk through resource directory?


LCF-AT

Recommended Posts

Hello mate:

Why don't you try the Unicode version of that API: LoadStringW? As far as I know strings come as Unicode in resources section.

Good luck!

Nacho_dj

Edited: Sorry I wasn't aware that you were using this function also as you stated below.

Maybe that resource could have not been properly mapped/loaded...

Well I would try by debugging any executable when loading resources to find out how it loads its strings,  maybe that could give a litlle light to this enigma...

Edited by Nacho_dj
  • Like 1
Link to comment

Hi Nacho,

I tried this too but also failed.Also I see I did again something wrong and it seems I dont have to use the ID values like FD9 (4057.) you can see on the picture I did post before.I have to use the other values you can see before the string on right side like 64896 for "Control Editor" string.Thats again really PITA and getting more and more complex.I tried to follow a normal loaded file in Olly and checking resources / RT_STRING and I have that... (I use same target as on picture and try to follow first string entry)

RESSTART: 039FB000 VA
$ ==>    039FB000      00000000
$+4      039FB004      497B7549
$+8      039FB008      00000000
$+C      039FB00C      000A0002
....
$+40     039FB040      00000006 RT_STRING
$+44     039FB044      80000428 offset 428 + 039FB000 RESSTART

$+428    039FB428      00000000
$+42C    039FB42C      497B7549
$+430    039FB430      00000000
$+434    039FB434      00280000 < entrys
$+438    039FB438      00000FD9 < 4057 ID
$+43C    039FB43C      80001140 < Offset 1140 + 039FB000 RESSTART
....
$+1140   039FC140      00000000
$+1144   039FC144      497B7549
$+1148   039FC148      00000000
$+114C   039FC14C      00010000 < entrys
$+1150   039FC150      00000000
$+1154   039FC154      00002000 < offset ? 2000 + 039FB000 RESSTART

IMAGE_RESOURCE_DATA_ENTRY STRUCT
    OffsetToData dd ?
    Size1 dd        ?
    CodePage dd     ?
    Reserved dd     ?
IMAGE_RESOURCE_DATA_ENTRY ENDS

$+2000   039FD000      004BCB50 OffsetToData 004BCB50 + 039FB000 RESSTART
$+2004   039FD004      00000364 Size1
$+2008   039FD008      00000000 CodePage
$+200C   039FD00C      00000000 Reserved

..first problem I see is where are the values like 64896 or FD80 in hex stored on that walk?I dont see it on this following.Another problem is that the endoffset to data 004BCB50 does fail to use it for a file which I did loaded with LoadLibraryEx LOAD_LIBRARY_AS_DATAFILE and it points to somewhere else because I need to convert the offset to offset for mapped file etc you know.In normal file the offset does match = this..Base + 004BCB50

008BCB50  0043000E  Resource.0043000E

$ ==>    >0E 00 43 00 6F 00 6E 00 74 00 72 00 6F 00 6C 00  .C.o.n.t.r.o.l.
$+10     >20 00 45 00 64 00 69 00 74 00 6F 00 72 00 0D 00   .E.d.i.t.o.r...
$+20     >44 00 69 00 61 00 6C 00 6F 00 67 00 20 00 45 00  D.i.a.l.o.g. .E.
$+30     >64 00 69 00 74 00 6F 00 72 00 1A 00 26 00 52 00  d.i.t.o.r..&.R.
$+40     >65 00 73 00 69 00 7A 00 65 00 20 00 41 00 6C 00  e.s.i.z.e. .A.l.
....

Next problem I see is handling languages like russian so there I just get ???? signs to see and it seems I need to set locale anyhow or whatever.Slowy it makes no fun anymore and its not so easy to handle with one function LoadString only.LoadIocn etc was simple.Hmmmm. :)

greetz

Link to comment

Mandatory reading: The format of string resources

1) As for 0xFD9 and it's meaning:

Quote

The strings listed in the *.rc file are grouped together in bundles of sixteen. So the first bundle contains strings 0 through 15, the second bundle contains strings 16 through 31, and so on. In general, bundle N contains strings (N-1)*16 through (N-1)*16+15.

2) As for LoadString and its limitations:

Quote

The LoadString function is rather limiting in a few ways:

  • You can't pass a language ID. If your resources are multilingual, you can't load strings from a nondefault language.
  • You can't query the length of a resource string.

Let's write some functions that remove these limitations.

....

 

  • Like 1
Link to comment

Hi kao,

hähhh? :) I see its getting still more complex as I thought already.I dont check that calc process yet and where starts the bundle?

FD9 * 10h = FD90 (64912 dec) - 10h = 64896 dec!?Ok wait....

So I got already the ID of FD9 for example I did read walking the table.Does it mean one ID = a bundle?

4057 (FD9h) * 16 - 16 = 64896 = first ID I can use with LoadString function

4057 (FD9h) * 16 - 15 = 64897

4057 (FD9h) * 16 - 0 =  64912 (16 till 0 or before)

0012FF78   0071AE4C  /CALL to LoadStringA from Resource.0071AE47
0012FF7C   00400000  |hInst = 00400000
0012FF80   0000FD80  |RsrcID = STRING "Control Editor"
0012FF84   00360000  |Buffer = 00360000
0012FF88   00000100  \Count = 100 (256.)

or

4058 (FDAh) * 16 - 16 = 64912

0012FF7C   00400000  |hInst = 00400000
0012FF80   0000FD90  |RsrcID = STRING "Off. %d, Sel. %d"
0012FF84   00360000  |Buffer = 00360000
0012FF88   00000100  \Count = 100 (256.)

Ahhhhh. :) Seems to work anyhow like this.So I see the strings already on that function.Ok,so I just take the ID values and do this calc stuff in a loop from 16 till 0 and use LoadString function with it.I think somehow like this should work then to get all strings of a ID.I will test it out to check whether it also works with my loaded file from LoadLibraryEx Data...etc.

PS: So I think in this case its not possible that RT_STRING entrys have any names like bitmap / icons etc right?So if they had name entrys too then I dont can calc with name anyhow.Just asking.

Thanks again for that hint kao.

@Nacho_dj

I just loaded the file via LoadLibraryEx as data file as evlncrn8 told before to get it work using such resource loading function for icon / bitmap etc.I will try what kao said with that strings and send some feedback whether its working or not so maybe I get some other another new problem issues as aways. :) Thanks again so far guys.

greetz

Link to comment

You still haven't told us what you are trying to achieve in the end. At first you tried to read resource directory manually, so I assumed that you'll be dealing with bad/broken files, possibly with some sort of resource protection applied.

But if you're able to use LoadLibraryEx and LoadString/Icon/etc., maybe you can also use EnumResource* functions? For example EnumResourceNamesEx?

  • Like 1
Link to comment

Hi again,

I am just trying to read the resources and show them.Same like a resource tool can do.Just wanna make a quick preview etc.Ok,about the strings I have done what you said about calculation and it works now so far to load all strings via LoadString function and before just calling FindResourceEx with the ID.But I have  the problem to show diffrent languages typos like russian / china etc so there I just get ??? back.

2018-07-04_171626.png.5e47ca81639c8405e483224d27ecf4f4.png

Not sure how to handle this problem.Is there a way to convert them anyhow with any function to get the right language letters to see?In the resources itself of that example file are also just some random values to see for that russian strings.

greetz

Link to comment

Hi fearless,

ok I did now just use UNICODE functions for that RT_STRINGs.wsprintfW / LoadStringW / SendMessageW.Now I get all languages right to see. :) Just have to double the values I get back from LoadStringW / wsprintfW of the lenght.

2018-07-04_195039.png.9e06d26cd34057610489f3894f7015fe.png

My code for this looks so....not sure whether I can keep the language NEUTRAL = 0 at FindResourceEx function.

                      .elseif TREE_RESOURCES_DATAS.RT[edi] == RT_STRING         
                              .if TREE_RESOURCES_DATAS.ID[edi] != 0h
                                      mov edi, TREE_RESOURCES_DATAS.ID[edi]
                              .else
                                      mov edi, NULL
                              .endif       
                                      .if edi != 0h
                                          invoke VirtualAlloc,NULL,20000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
                                          .if eax != 0h
                                          mov esi,eax
                                          mov RESALLOC, eax
                                          invoke wsprintfW,esi,ucc$("%s%s"),ucc$("{"),addr ABSATZU
                                          add esi,eax
                                          add esi,eax
                                          invoke FindResourceEx,DATAHANDLE,RT_STRING,edi,NULL
                                          .if eax != 0h
                                              mov ebx,16
                                              imul edi,16
                                              .while ebx != 0h
                                              push edi
                                              sub edi,ebx
                                              invoke LoadStringW,DATAHANDLE,edi,addr STRINGBUFFER,sizeof STRINGBUFFER
                                              .if eax == 0h
                                                  jmp @F
                                              .endif
                                              invoke wsprintfW,esi,ucc$('%d, "%s"%s'),edi,addr STRINGBUFFER,addr ABSATZU
                                              add esi,eax
                                              add esi,eax
                                              @@:
                                              pop edi
                                              dec ebx
                                              .endw
                                              invoke wsprintfW,esi,ucc$("%s%s"),ucc$("}"),addr ABSATZU
                                              invoke GetDlgItem,hWnd,IDC_EDITRES
                                              invoke SendMessageW,eax,WM_SETTEXT,NULL,RESALLOC
                                          .endif
                                          invoke VirtualFree,RESALLOC,NULL,MEM_RELEASE
                                          .endif
                                      .endif      


                  
                      .endif 

PS: Just using normal edit control no RichEdit in that case on testing.

greetz

  • Like 1
Link to comment

Hi guys,

now I try to handle the RT_MENU and get again any trouble.Using again FindResourceEx with menu ID / Name then LoadResource.Now I have handle which points to filled Menutemplate which I could use with LoadMenuIndirect function.Question now is how to show it.Seems I need to create a dialog and load this menu in this dialog anyhow right?Has anyone a idea for that how I could handle this correctly?Can I create a  dialog via CreateDialogIndirectParam maybe with that Menutemplate handle I got from LoadMenuIndirect  or so?

greetz

Link to comment

Hi,

ok I did use DialogBoxParam and SetMenu to get it showing.

Next problem I have is reading the MENUITEMTEMPLATEHEADER / MENUITEMTEMPLATE.Seems that there is anything with calclations to do similar as for RT_STRING as kao said before.I check that templates in Olly and see this...

036AFAB8  00 00 00 00 10 00 26 00 46 00 69 00 6C 00 65 00  .....&.F.i.l.e.
036AFAC8  00 00 00 00 D1 07 26 00 4F 00 70 00 65 00 6E 00  ....Ñ&.O.p.e.n.
036AFAD8  09 00 46 00 33 00 00 00 00 00 D2 07 26 00 41 00  ..F.3.....Ò&.A.
036AFAE8  74 00 74 00 61 00 63 00 68 00 00 00 80 00 D3 07  t.t.a.c.h...€.Ó
036AFAF8  26 00 45 00 78 00 69 00 74 00 09 00 41 00 6C 00  &.E.x.i.t...A.l.
036AFB08  74 00 2B 00 58 00 00 00 10 00 26 00 56 00 69 00  t.+.X....&.V.i.
036AFB18  65 00 77 00 00 00 00 00 35 08 26 00 4C 00 6F 00  e.w.....5&.L.o.
036AFB28  67 00 09 00 41 00 6C 00 74 00 2B 00 4C 00 00 00  g...A.l.t.+.L...
036AFB38  00 00 36 08 26 00 45 00 78 00 65 00 63 00 75 00  ..6&.E.x.e.c.u.
036AFB48  74 00 61 00 62 00 6C 00 65 00                    t.a.b.l.e.
etc..

036AFAB8 = MENUITEMTEMPLATEHEADER

MENUITEMTEMPLATEHEADER STRUCT
  versionNumber     WORD      ?
  loffset           WORD      ?
MENUITEMTEMPLATEHEADER ENDS

MENUITEMTEMPLATE STRUCT
  mtOption      WORD      ?
  mtID          WORD      ?
  mtString      WORD      ?
MENUITEMTEMPLATE ENDS

In the loffset WORD is 0000.I think it means that the MENUITEMTEMPLATE starts right after MENUITEMTEMPLATEHEADER size.In first mtOption I have 10h word = MF_POPUP.In mtID I have 0026h "&" and in mtString I have the string in Unicode.No idea why my mtString has a word declaration.

POPUP "&File"

Ok,what then?Seems that the lenght of MENUITEMTEMPLATE struct is dynamic and depends on the string lenght = word + word + mtString = next MENUITEMTEMPLATEHEADER start (not sure of course).Next one starts at 036AFAC8 VA.MENUITEMTEMPLATEHEADER again both 0.Plus 4h = next MENUITEMTEMPLATE start.There I see now 07D1h for mtOption and 0026h as mtID or else.Below the string again.

How to check what is what now?Whether its a menu or menuitem?Just can check for MF_CHECKED till MF_POPUP values = its a menu and else = menuitem?

POPUP "&File"
{
	MENUITEM "&Open\tF3",  2001
	MENUITEM "&Attach",  2002
	MENUITEM "&Exit\tAlt+X",  2003
}

MF_POPUP = 10h in mtOption for "File" menu.Below is mtOption = 07D1h (2001).

So has anyone some infos how to walk in that table correctly?I dont find again anything on internet about it.

greetz

Link to comment

Hi,

I dont have this structs in my windows.inc file!Are you sure?

$ ==>    0395FAB8   00000000 = MENUHEADER If both 0 = use NORMALMENUITEM after
$+4      0395FABC   00260010 = NORMALMENUITEM / resInfo = 0010
$+8      0395FAC0   00690046
$+C      0395FAC4   0065006C
$+10     0395FAC8   00000000


typedef struct {
  WORD    resInfo;
  szOrOrd menuText;
} NORMALMENUITEM;


MFR_END
0x80

MFR_POPUP
0x01

SO what now?Its not 80 or 01 into resInfo.Its 10h.

What here?
$+10     >00000000 MENUHEADER
$+14     >002607D1 NORMALMENUITEM resInfo = 07D1
$+18     >0070004F
$+1C     >006E0065
$+20     >00460009
$+24     >00000033

Thats pretty bad again.Not sure how to handle that structs correctly yet if they are the right ones I need to use here.

greetz

Link to comment

Hi guys,

short question.Can anyone tell me how to work correctly / simple with flags to enable / disable some of them.

Example: I have a window with style xy set flags and now I wanna set some custom flags to add another style flags if they arent present yet.So this seems to simple just using the or operant like or WS_VISIBLE + DS_CENTER.The new flags gettiing added if not already.Now I wanna do same to remove some style flags if they are present but this dosent work same as OR operant without doing any check  before.I tried to use AND / XOR.

WS_VISIBLE  equ 10000000h

or eax, WS_VISIBLE = does add WS_VISIBLE value to eax if lower than WS_VISIBLE or does nothing if higher than WS_VISIBLE vaue

So I cant do same with XOR operant to make the opposite.How to handle that?On internet I found example like this....

invoke  GetWindowLong, hWnd, GWL_STYLE 
mov     ebx, WS_SIZEBOX
not	ebx
and	eax,ebx
invoke  SetWindowLong, hWnd, GWL_STYLE, eax  

...seems to work but is it getting more simple or is there maybe any MASM macro I could use?Just asking if anyone knows.

Next question I have is how to check some flags whether they are present or not like the value I got from GetWindowLog?

greetz

Link to comment
VirtualPuppet
30 minutes ago, LCF-AT said:

Hi guys,

short question.Can anyone tell me how to work correctly / simple with flags to enable / disable some of them.

Example: I have a window with style xy set flags and now I wanna set some custom flags to add another style flags if they arent present yet.So this seems to simple just using the or operant like or WS_VISIBLE + DS_CENTER.The new flags gettiing added if not already.Now I wanna do same to remove some style flags if they are present but this dosent work same as OR operant without doing any check  before.I tried to use AND / XOR.


WS_VISIBLE  equ 10000000h

or eax, WS_VISIBLE = does add WS_VISIBLE value to eax if lower than WS_VISIBLE or does nothing if higher than WS_VISIBLE vaue

So I cant do same with XOR operant to make the opposite.How to handle that?On internet I found example like this....


invoke  GetWindowLong, hWnd, GWL_STYLE 
mov     ebx, WS_SIZEBOX
not	ebx
and	eax,ebx
invoke  SetWindowLong, hWnd, GWL_STYLE, eax  

...seems to work but is it getting more simple or is there maybe any MASM macro I could use?Just asking if anyone knows.

Next question I have is how to check some flags whether they are present or not like the value I got from GetWindowLog?

greetz

 

When working with flags, there's some simple binary operations that are very important to understand fully.

OR : Sets all bits which are set in either of the operands to 1 -> 1001 OR 1110 = 1111.

AND : Sets all bits which are set in both of the operands to 1 -> 1001 AND 1110 = 1000.

NOT : Flips all bits (turns a value into it's direct inverse) -> NOT 1001 1100 = 0110 0011.

 

Now how to use them is another matter. If you want to check for one (or multiple) flags, you have to realize that each flag (albeit being described by a hexadecimal number) is actually represented as a single bit in a sum of flags.

This is why the flags are 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, etc. (because they are respectively 0000 0001, 0000 0010, 0000 0100, 0000 1000, 0001 0000, 0010 0000, and so on.)

 

If you want to simple add a flag (regardless of whether it's already there or not), OR is your solution, as you've already realized.

If you want to check if a flag contains a flag, AND is your solution. If you take a random sum of flags, then AND it with the flag(s) that you want to check for (multiple flags can be checked at once), then the result of that operation is a value containing all the flags (that you were checking) which were found. So if you check for flags 0x0c (which is 0x08 and 0x04 respectively), you'd be actually checking for 0000 1100. If you get a result value being 0x08, it means that 0000 1000 was found. In theory, if you don't care which flag is set, you just need to check if either of them are set, you can compare the result to zero. Non-zero means some flag was found.

For the removal of flags, if you NOT the flag, you basically create a binary value of all flags except this one. For example, if you NOT 0x04, you get : NOT 0000 0100 = 1111 1011. Now, if you AND the flag sum with the result of this NOT-operation, you'll basically find all the flags set in your flag sum, that were not 0x04. And then you can set the flags to this new value, and efficiently have removed the bitflag.

 

  • Like 1
Link to comment
Teddy Rogers

It is good practice to be using GetWindowLongPtr and SetWindowLongPtr.

Regarding changing a windows flags, after SetWindowLongPtr try calling SetWindowPos with the following flags, "SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_ASYNCWINDOWPOS".

To check for the presence of a specific flag you can use something like GetWindowInfo then...

If pwi\dwStyle & WS_SIZEBOX
	...windows contains WS_SIZEBOX, do stuff...
EndIf

Or GetWindowLongPtr...

If GetWindowLongPtr(hWnd, GWL_STYLE) & WS_SIZEBOX
	...windows contains WS_SIZEBOX, do stuff...
EndIf

Ted.

  • Like 1
Link to comment

Hi again,

thanks for your answers so far.Seems I got some problem with that (except OR command) to check that.So maybe I need any simple example for that flag checking thing not only from GetWindowLong function also other 32 bit values (PE struct etc) I need to check someday.

Lets say I have any value xy in register and now I just wanna check whether a setting flag/s are present in eax or not.I did checking the test command for that like this...

	mov eax, WS_VISIBLE + WS_CAPTION + WS_CHILD
	test eax, WS_VISIBLE
	je @F
	test eax, WS_CAPTION
	je @F
	test eax, WS_CHILD
	je @F
	test eax, WS_DISABLED
	je @F
	test eax, WS_VISIBLE + WS_CAPTION + WS_CHILD
	je @F
	nop
	@@:

.... je command does jump if value/s for testing are not present and je jumps if value for testing is present.Somehow else (thought JE would jump if present).So can I use this method for testing all flags or could I get any problem with that now?

Another question about resources again.Today I also tried to handle RT_VERSION and surprise surprise I get next problem again (dont laugh!) ;) It seems I cant use GetFileVersionInfo function for memory block (need filename).I tried to play with VerQueryValue function and I can get string infos out but only if I let check for some strings like CompanyName / FileDescription etc (http://delphidabbler.com/articles?article=20) but what is if custom strings are used?Can I not just check what is present and reading it?The whole stuff to get entire informations out from RT_VERSION content is again very confusing and I dont know how to handle that now completely.On internet I found also no example for the whole RT_VERSION read out.If anyone has some ideas how to do that etc then answers are welcome of course.

greetz

Link to comment
Teddy Rogers

Your code is not going to work as you are using arithmetic on the flags. The flags are really represented as a constant value in hex, check Window Styles. You need to use bitwise AND. You need to check for the flags against the value returned from GetWindowLongPtr.

I would recommend you take a look at MASM Operators Reference and Bitwise Operations.

Regarding your next question, is this what you are after?

;
; ------------------------------------------------------------------
;
;   Example shows how to enumerate the available version languages 
;   and retrieve the FileDescription string-value for each language.
;
;   PureBasic version of code found at:
;   https://docs.microsoft.com/en-us/windows/desktop/api/winver/
;
;   By Teddy Rogers / PureBasic 5.62
;
; ------------------------------------------------------------------
;

; Structure used to store enumerated languages and code pages.

Structure LANGANDCODEPAGE 
  wLanguage.w
  wCodePage.w
EndStructure

*lpTranslate.LANGANDCODEPAGE

; Open a file to retrieve version information from.

lptstrFilename.s = OpenFileRequester("Select file...", "", "EXE (*.exe)|*.exe|DLL (*.dll)|*.dll", #Null)

If lptstrFilename.s
  
  ; Get the size in bytes of the files' version information resource.
  
  dwLen = GetFileVersionInfoSize_(@lptstrFilename.s, @lpdwHandle)
  
  ; Allocate the required memory.
  
  If dwLen
    *pBlock = AllocateMemory(dwLen)
    
    ; Retrieve the file version information resource and store it in allocated memory *pBlock
    
    If *pBlock
      If GetFileVersionInfo_(@lptstrFilename.s, dwHandle, dwLen, *pBlock)
        
        ; Read the list of languages and code pages.
        
        If VerQueryValue_(*pBlock, @"\VarFileInfo\Translation", @*lpTranslate.LANGANDCODEPAGE, @puLen)
          
          ; Store the result in hex, pad four characters wide.
          ; The lang-codepage name must be specified as a hexadecimal string.
          
          wLanguage.s = RSet(Hex(*lpTranslate\wLanguage), 4, "0")
          wCodePage.s = RSet(Hex(*lpTranslate\wCodePage), 4, "0")
          
          ; Loop through all twelve string-name's.
          
          For a = 1 To 12
            
            ; Read the next available string found in the data section.
            
            Read.s stringname.s  
            
            ; Concontenate "\StringFileInfo\" + lang-codepage + string-name
            
            SubBlock.s = "\StringFileInfo\" + wLanguage.s + wCodePage.s + "\" + stringname.s
            
            ; Retrieve file description for language and code page.
            
            If VerQueryValue_(*pBlock, @SubBlock.s, @*lpBuffer, @dwBytes)
              Debug stringname.s + " : " + PeekS(*lpBuffer, dwBytes)
            Else
              Debug stringname.s + " : " + "Description is empty."
            EndIf
          Next
          
        Else
          Debug "Can not read the list of languages and code pages."
        EndIf
      Else
        Debug "Can not retrieve version information from the specified file."
      EndIf
      
      FreeMemory(*pBlock)
    Else
      Debug "Can not allocate the required memory."
    EndIf
  EndIf
Else
  Debug "Can not load the requested file."
EndIf

; The following are predefined version information Unicode strings.
; The string-name must be a predefined string.

DataSection 
  stringname:
  Data.s "Comments",        "InternalName",     "ProductName"
  Data.s "CompanyName",     "LegalCopyright",   "ProductVersion"
  Data.s "FileDescription", "LegalTrademarks",  "PrivateBuild"
  Data.s "FileVersion",     "OriginalFilename", "SpecialBuild"
EndDataSection

Ted.

  • Like 1
Link to comment

Hi again,

hmmm,so that flag issue checking seems to be not so easy (or its me again).Still dont check that yet.Does it mean I always need to AND the whole flag value before I check it with the single flag?

Thanks for the code example Ted,so now I just read out all 12 predef string-names.

I have one more question about RT_DIALOG resources.In this case I also use FindResourceEx / LoadResource etc function till I got the Dialog Template/Ex in my buffer.Now I use CreateDialogIndirectParam function with the template and I see 2 problems.If it works then the dialog gets loaded but not all resources are too see inside this dialog like bitmaps and some others.Have I to load this extra or why dosent load it by itself?Next problem I see is that some dialogs dosent get loaded and CreateDialogIndirectParam does fail with resource not found error.I tried to debug that problem and found out that in some case inside the function CreateDialogIndirectParam it does call LoadMenuW function to load the menu of the Dialog and right there I get the error after.Problem I see is that its using the base of my target and not from the target I did loaded with LoadLibraryEx Datafile.Now I changed the hInstance paramter of CreateDialogIndirectParam to the handle of the file I got from LoadLibraryEx back.Now the LoadMenuW seems to work but after CreateDialogIndirectParam I get the error ERROR_CANNOT_FIND_WND_CLASS.Why this now?

greetz

Link to comment
CodeExplorer
Quote

hmmm,so that flag issue checking seems to be not so easy (or its me again).Still dont check that yet.Does it mean I always need to AND the whole flag value before I check it with the single flag? 

Yes.
You must "annihilate"  the other value from returned value (eax) - the "and" instruction it would be what you want;
since on "and" instruction will only be 1 when both "sides" will be 1:
1 and 1 = 1
1 and 0 = 0
0 and 1 = 0
0 and 0 = 0
When you have the binary mask "1000" and you do an "and" operation with a value like "1010"
the second part after first 1 which is 010 will be completely eliminated (filled with zeros): 000
now if the first binary is zero (0) the result will be zero:
else the result will be non-zero.

instead of wrong code:

mov eax, WS_VISIBLE + WS_CAPTION + WS_CHILD
	test eax, WS_VISIBLE
	je @F
	test eax, WS_CAPTION
	je @F
	test eax, WS_CHILD
	je @F
	test eax, WS_DISABLED
	je @F
	test eax, WS_VISIBLE + WS_CAPTION + WS_CHILD
	je @F
	nop
	@@:

do it like this:
mov edx,eax ; save return value
and edx,WS_VISIBLE
test edx,edx ; test to see if is zero
jnz @F ; if not zero means that WS_VISIBLE is there

; Next value test:
mov edx,eax ; save return value
and edx, WS_CAPTION
test edx,edx ; test to see if is zero
jnz @F ; if not zero means that WS_CAPTION is there


 

  • Like 1
Link to comment
Teddy Rogers

Not sure I can explain it any simpler than this ("&" is bitwise AND in PB)...

hWnd = GetShellWindow_()

gwlResult = GetWindowLongPtr_(hWnd, #GWL_STYLE)

; #WS_CLIPCHILDREN = $2000000
    
Debug gwlResult & #WS_CLIPCHILDREN

; https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx
; Or...

Debug gwlResult & $2000000

Or...

Procedure GetWindowStyle(hWnd)
  ProcedureReturn GetWindowLongPtr_(hWnd, #GWL_STYLE)
EndProcedure

hWnd = GetShellWindow_()

Debug GetWindowStyle(hWnd) & #WS_CLIPCHILDREN

Or...

If OpenWindow(0, 0, 0, 350, 160, "List GetShellWindow GWL_STYLE's", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  EditorGadget(1, 5, 5, 340, 150, #PB_String_ReadOnly)
  
  hWnd = GetShellWindow_()
  gwlResult = GetWindowLongPtr_(hWnd, #GWL_STYLE)
  
  AddGadgetItem(1, -1, "GetShellWindow : " + hWnd + " / " + "$" + Hex(hWnd))
  AddGadgetItem(1, -1, "GetWindowLongPtr : " + gwlResult + " / " + "$" + Hex(gwlResult) + Chr(13))

  Repeat
    Read.l gwlstyle
    
    If gwlstyle
      If gwlResult & gwlstyle
        AddGadgetItem(1, -1, "0x" + RSet(Hex(gwlstyle), 8, "0") + "L")
      EndIf
    Else
      Break
    EndIf
    
  ForEver

  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
  
EndIf

DataSection 
  gwlstyle:
  Data.l #WS_BORDER,        #WS_CAPTION,          #WS_CHILD
  Data.l #WS_CHILDWINDOW,   #WS_CLIPCHILDREN,     #WS_CLIPSIBLINGS
  Data.l #WS_DISABLED,      #WS_DLGFRAME,         #WS_GROUP
  Data.l #WS_HSCROLL,       #WS_ICONIC,           #WS_MAXIMIZE
  Data.l #WS_MAXIMIZEBOX,   #WS_MINIMIZE,         #WS_MINIMIZEBOX
  Data.l #WS_OVERLAPPED,    #WS_OVERLAPPEDWINDOW, #WS_POPUP
  Data.l #WS_POPUPWINDOW,   #WS_SIZEBOX,          #WS_SYSMENU
  Data.l #WS_TABSTOP,       #WS_THICKFRAME,       #WS_TILED
  Data.l #WS_TILEDWINDOW,   #WS_VISIBLE,          #WS_VSCROLL
  Data.l #Null
EndDataSection

Regarding your second question, I am a bit confused as to what it is you are trying to do. Does this help? 🤔

https://msdn.microsoft.com/en-us/library/cc194811.aspx

Ted.

List GetShellWindow GWL_STYLE.exe

  • Like 1
Link to comment
mov eax, WS_VISIBLE + WS_CAPTION + WS_CHILD

also, that above is a bad example.. it really should be

mov eax, (WS_VISIBLE OR WS_CAPTION OR WS_CHILD)
  • Like 1
Link to comment

Hi again,

ok thanks for another infos so far.Ted,your file seems to be only for x64 OS.Dosent work for me.

Question again about DLG boxes.Example: I told above that I in some cases get the error ERROR_CANNOT_FIND_WND_CLASS if I try to call / show a dialog via function CreateDialogIndirectParam using a copy of DLGTEMPLATE of a Dialog from resources.I see it only happens if the DLGTEMPLATEEX has the member pmenu inside.There is a MASM target called "EzProcess.exe" I did check the dialogs in resources and the first one makes this problem.All others are working to show them without to get this class error.In the pmenu member of this first dialog is the ID 03E8FFFF (1000).It does call LoadMenuW with that ID and returns success but after CreateDialogIndirectParam I have the error ERROR_CANNOT_FIND_WND_CLASS.I also tried to zero this pmenu member in the template but also fails.So has anyone a idea how to handle that problem to get this dialog loaded without to get this ERROR_CANNOT_FIND_WND_CLASS error anymore?

Thanks

Link to comment

..and we are supposed to go search for this magical "EzProcess.exe" all over the Internet just to try to help you to find a solution for your problem? :wacko:

 

I would *guess* that it's because either:
1) the dialog uses custom dialog class - but you haven't registered it. Example of such dialog: https://blogs.msdn.microsoft.com/oldnewthing/20031113-00/?p=41843
2) the dialog uses custom control - but you haven't registered the corresponding class of the control. Example of such dialog in ProcessHacker, dialog 104:

104 DIALOGEX 0, 0, 260, 260
STYLE DS_FIXEDSYS | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Modules"
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
FONT 8, "MS Shell Dlg", FW_NORMAL, FALSE, 1
{
   CONTROL "", 1061, "PhTreeNew", 0x5601000A, 7, 7, 246, 246 , 0x00000200
}

Here dialog refers to custom control "PhTreeNew" which gets registered like this (https://github.com/processhacker/processhacker/blob/b66304e5110d3ad47a26ea1358aa1b9d635e6463/phlib/treenew.c#L59-L78)

3) the tool uses extended controls from comctl32.dll - but you didn't load and initialize them using InitCommonControls(Ex);

 

Solution is (probably) to register a fake window class before loading the dialog.

  • Like 1
Link to comment

Hi,

I tried already to use RegisterClassEx what fails if I enter also the pmenu from template to pmenuord of WNDCLASSEX.If I keep it empty then it does success but CreateDialogIndirectParam still fails.In reshacker the dialog I wanna call looks so...

1000 DIALOGEX 10, 10, 500, 307
STYLE DS_MODALFRAME | DS_CENTER | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_DLGMODALFRAME
CAPTION "EzProcess"
MENU 1000
CLASS  "EZPROCESS"
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
FONT 8, "Tahoma"
{
   CONTROL "", 1002, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_TABSTOP, 3, 16, 495, 196 , 0x00000200
   CONTROL "", 1004, "SysListView32", LVS_REPORT | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 397, 214, 101, 79 , 0x00000200
   CONTROL "", 1006, "SysListView32", LVS_REPORT | LVS_SORTASCENDING | LVS_SHAREIMAGELISTS | LVS_AUTOARRANGE | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 3, 214, 392, 80 , 0x00000200
   CONTROL "", 1011, "ToolbarWindow32", 0x50000924, 0, 0, 600, 16 
   CONTROL "", 1180, "msctls_statusbar32", CCS_TOP | WS_CHILD | WS_VISIBLE, 6, 293, 415, 13 
}
                                                                  invoke RtlZeroMemory,addr WNDC,sizeof WNDC
                                                                  lea ebx, WNDC
                                                                  mov WNDCLASSEX.cbSize[ebx],sizeof WNDCLASSEX
                                                                  mov WNDCLASSEX.style[ebx],CS_SAVEBITS or CS_DBLCLKS or CS_BYTEALIGNWINDOW
                                                                  mov WNDCLASSEX.lpfnWndProc[ebx], offset RESDIALOG
                                                                  mov WNDCLASSEX.cbClsExtra[ebx],NULL
                                                                  mov WNDCLASSEX.cbWndExtra[ebx],DLGWINDOWEXTRA
                                                                  push DATAHANDLE
                                                                  pop WNDCLASSEX.hInstance[ebx]
                                                                  mov WNDCLASSEX.hbrBackground[ebx],0;COLOR_WINDOW+1
                                                                  ;push DLGTEMPLATEEX.pmenu[esi]
                                                                 ; pop WNDCLASSEX.lpszMenuName[ebx]
                                                                  lea eax, DLGTEMPLATEEX.pmenuord[esi]
                                                                  nop
                                                                  mov WNDCLASSEX.lpszClassName[ebx],eax
                                                                  mov WNDCLASSEX.hIcon[ebx],NULL
                                                                  mov WNDCLASSEX.hIconSm[ebx],NULL
                                                                  mov WNDCLASSEX.hCursor[ebx],NULL
                                                                  invoke RegisterClassEx, addr WNDC  

in ClassName it points to EZPROCESS name.I also used before in my code InitCommonControlsEx too.

greetz

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...