News:

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

Main Menu

TaskDialog

Started by guga, April 10, 2025, 07:17:48 AM

Previous topic - Next topic

guga

Quote from: zedd151 on April 17, 2025, 06:27:52 AM
Quote from: guga on April 17, 2025, 06:19:29 AMWorked.
:thumbsup:  :thumbsup:


Although the text "You're about to do something stupid." was somewhat alarming.  :joking:  :joking:
Of course I tried all 3 options, regardless.  :tongue:

I will still try to make my version.  :azn:  It'll give me something to do later this evening.


@Timo, good tip on the "*.manifest" file. I had seen those files in windows folders in various places, but didn't know how/when they would or could be useful in assembly.  :thumbsup:  :thup:  :thumbsup:  :thup:  :biggrin:   I'll have to explore this new knowledge further at another time.
:mrgreen:  :mrgreen:  :mrgreen:  :mrgreen: Copied the text from the VB forum i used to port those taskdialogs :toothy:  :toothy:  :toothy:
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

zedd151

:biggrin:

guga, do the strings have to be unicode? I just looked at your executable in olly
Nevermind. Of course they do... I hadn't done my homework.  :biggrin:

guga

Btw, Timo. You gave me an idea on a future way to fix those issues in RosAsm without having to rely on a manifest file.

Inside WinSxS we have hundreds of these new dlls, all of them inside directories with weird names.

It turned out that, those weird names are exactly what is inside the manifest files.

Ex:On my case it is located at: C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.4355_none_a865f0c28672571c\COMCTL32.dll

Your manifest contains this:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*' />
    </dependentAssembly>
  </dependency>
</assembly>


So, in xml, name= "Microsoft.Windows.Common-Controls" is the 1st part of the directory to be searched. Then follows the publickKeyToken "6595b64144ccf1df" also present in the directory name, and then followed by the version and language of the dll (or system itself) also existent in the directory name.

This is how windows searches for the dll when it finds a manifest file aside the executable (or embedded on the resources section).

I have a couple of ideas on how to use those information in RosAsm, for both the assembler and disassembler. For the assembler side, add a list of avaliable controls and their versions inside winsxs that requires manifest. On this way, during assembling, the user can choose which dlls versions he wants and generate the manifest file automatically (or add some more complete manifest files updated).

On this way, RosAsm itself may not need a manifest file embedded or as external to assemble 'manifest apps'. All it will take to properly assemble is check if the user is trying to create something that uses manifest, and then scans inside winsxs for the proper dll version.

ON the disassembler side, analyse the manifest inside the resource section and update it according to the versions of the user control inside his winsxs.

And a 3rd option (The easier and lazy way), add a external manifest on RosAsm itself (as i did now to test the taskdialog), and let windows manages this things without the user control.
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

Quote from: zedd151 on April 17, 2025, 06:57:54 AM:biggrin:

guga, do the strings have to be unicode? I just looked at your executable in olly
Nevermind. Of course they do... I hadn't done my homework.  :biggrin:
:bgrin:  :bgrin:  :bgrin:  :bgrin:
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

zedd151

Quote from: guga on April 17, 2025, 07:15:49 AMIt turned out that, those weird names are exactly what is inside the manifest files.
Good detective work. I probably would have not deduced that.
Microsoft works in mysterious (meaning weird  :rolleyes: ) ways.

guga

#65
I wonder if there is an Api that can read (parse) those xml things as described here:
https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests
https://learn.microsoft.com/en-us/windows/win32/sbscs/assembly-manifests

If there is (and i don´t doubt it) then it will be way way easier than hard code a xml parser for manifest apps.
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

#66
Found it.. .. It is called webservices.dll (But...for Win7 only)

https://learn.microsoft.com/en-us/windows/win32/api/webservices/nf-webservices-wscreatewriter


Also another one called xmllite.dll

https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms752822(v=vs.85)


Also this (apparently can be used since vista (or XP with redistributable packages)
msxml6.dll
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

zedd151

With gugas original code  from here  where it says "I did this" and with a couple of modifications (for ml compatibilty (marked):

ml doesn't know what TCHAR is, it was treated as ascii.  :toothy:

Now with the strings in ugly style unicode:  ;; I didn't want to add an ascii to unicorn conversion procedure to the code.
; #########################################################################

      .386
      .model flat, stdcall
      option casemap :none   ; case sensitive

; #########################################################################

      include \masm32\include\windows.inc
      include \masm32\include\user32.inc
      include \masm32\include\kernel32.inc
      include \masm32\include\gdi32.inc
     

      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib
      includelib \masm32\lib\gdi32.lib


; Prototype for TaskDialogIndirect
 ; TaskDialogIndirect PROTO :DWORD, :DWORD, :DWORD, :DWORD ; doesn't work here

    .data
TDCBF_OK_BUTTON     equ 1
TDCBF_YES_BUTTON    equ 2
TDCBF_NO_BUTTON     equ 4
TDCBF_CANCEL_BUTTON equ 8
TDCBF_RETRY_BUTTON  equ 16
TDCBF_CLOSE_BUTTON  equ 32

TD_WARNING_ICON     equ 0FFFFh  ; Don't use 0xFF??h ; only 0FF??h for ml
TD_ERROR_ICON       equ 0FFFEh
TD_INFORMATION_ICON equ 0FFFDh
TD_SHIELD_ICON      equ 0FFFCh


   
; Structure definitions
TASKDIALOG_BUTTON struct
    nButtonID      DWORD ?
    pszButtonText  DWORD ? ; Pointer to Unicode string
TASKDIALOG_BUTTON ends

TASKDIALOGCONFIG struct
    cbSize              DWORD 0
    hwndParent          HWND 0
    hInstance           HINSTANCE 0
    dwFlags             DWORD 0
    dwCommonButtons     DWORD 0
    pszWindowTitle      DWORD 0
    hMainIcon           DWORD 0
    pszMainInstruction  DWORD 0
    pszContent          DWORD 0
    cButtons            DWORD 0
    pButtons            DWORD 0
    nDefaultButton      DWORD 0
    cRadioButtons       DWORD 0
    pRadioButtons       DWORD 0
    nDefaultRadioButton DWORD 0
    pszVerificationText DWORD 0
    pszExpandedInformation DWORD 0
    pszExpandedControlText DWORD 0
    pszCollapsedControlText DWORD 0
    hFooterIcon         DWORD 0
    pszFooter           DWORD 0
    pfCallback          DWORD 0
    lpCallbackData      DWORD 0
    cxWidth             DWORD 0
TASKDIALOGCONFIG ends

.data
    hInstance           DWORD 0
    hDll                DWORD 0
    hTaskDialogIndirect DWORD 0
    nButtonPressed      DWORD 0

    ; Unicode strings ; ml assembles TCHAR strings as ascii
   
    Sz_Radio1               db "L",0,"e",0,"t",0,"s",0," ",0,"d",0,"o",0," ",0,"I",0,"t",0,"e",0,"m",0,"1", 0, 0, 0
    Sz_Radio2               db "O",0,"r",0," ",0,"m",0,"a",0,"y",0,"b",0,"e",0," ",0,"2", 0, 0, 0
    Sz_Radio3               db "S",0,"u",0,"p",0,"e",0,"r",0," ",0,"s",0,"e",0,"c",0,"r",0,"e",0,"t",0," ",0,"o",0,"p",0,"t",0,"i",0,"o",0,"n", 0, 0, 0
   
    Sz_MainInstruction      db "Y",0,"o",0,"u",0,"'",0,"r",0,"e",0," ",0,"a",0,"b",0,"o",0,"u",0,"t",0," ",0,"t",0,"o",0," ",0,"d",0,"o",0," ",0,"s",0
                            db "o",0,"m",0,"e",0,"t",0,"h",0,"i",0,"n",0,"g",0," ",0,"s",0,"t",0,"u",0,"p",0,"i",0,"d",0,".", 0, 0, 0
                                                                                                                                                                                                             
    Sz_Content              db "A",0,"r",0,"e",0," ",0,"y",0,"o",0,"u",0," ",0,"a",0,"b",0,"s",0,"o",0,"l",0,"u",0,"t",0,"e",0,"l",0,"y",0," ",0,"s",0
                            db "u",0,"r",0,"e",0," ",0,"y",0,"o",0,"u",0," ",0,"w",0,"a",0,"n",0,"t",0," ",0,"t",0,"o",0," ",0,"c",0,"o",0,"n",0,"t",0
                            db "i",0,"n",0,"u",0,"e",0," ",0,"w",0,"i",0,"t",0,"h",0," ",0,"t",0,"h",0,"i",0,"s",0," ",0,"r",0,"e",0,"a",0,"l",0,"l",0
                            db "y",0," ",0,"b",0,"a",0,"d",0," ",0,"i",0,"d",0,"e",0,"a",0,"?", 0, 0, 0
    Sz_WindowTitle          db "c",0,"T",0,"a",0,"s",0,"k",0,"D",0,"i",0,"a",0,"l",0,"o",0,"g",0," ",0,"P",0,"r",0,"o",0,"j",0,"e",0,"c",0,"t", 0, 0, 0
    Sz_Comctl32             db ".\COMCTL32.dll", 0 ; path in project folder
    Sz_TaskDialogIndirect   db "TaskDialogIndirect", 0

    ; Radio button array
    RadioButtons        TASKDIALOG_BUTTON \
                        <110, OFFSET Sz_Radio1>,
                        <111, OFFSET Sz_Radio2>,
                        <112, OFFSET Sz_Radio3>

    ; TaskDialog configuration                     ; use 'or' not '+'
   TaskDialogConfig    TASKDIALOGCONFIG \
                        <96, 0, 0, 0, TDCBF_YES_BUTTON or TDCBF_NO_BUTTON, \
                         OFFSET Sz_WindowTitle, TD_SHIELD_ICON, OFFSET Sz_MainInstruction, \
                         OFFSET Sz_Content, 0, 0, 0, 3, OFFSET RadioButtons, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>


.code
start:
    ; Get module handle
    invoke GetModuleHandle, NULL
    mov hInstance, eax

    ; Load COMCTL32.dll
    invoke LoadLibrary, addr Sz_Comctl32
    mov hDll, eax

    ; Get TaskDialogIndirect address
    invoke GetProcAddress, hDll, addr Sz_TaskDialogIndirect
    mov hTaskDialogIndirect, eax ; call using this variable

    ; Call TaskDialogIndirect ; prototype above didn't work - so push/call syntax used
    push 0
    push 0
    push offset nButtonPressed
    push offset TaskDialogConfig
    call hTaskDialogIndirect ; call by variable

    ; Exit process
    invoke ExitProcess, 0

end start



No manifest file used either, in any form. The project built fine with ml.exe and link.exe from the masm32 SDK.

The .dll was placed into the project folder prior to assembly (but is not in the attachment for obvious reasons. {Copyright, etc}, you will have to put the proper version there yourself or change the path to where it is on your computer. It is mentioned in several different places above where to find it).

Finished porting to masm for guga. Corrections made where necessary. Some mistakes may have been overlooked and may still be present in the code.
:azn:  :biggrin:  :smiley:  :undecided:  :sad:


Now you need the callback procedures guga, so the button presses do something.   :biggrin:

sinsi

Quote from: zedd151 on April 17, 2025, 08:43:32 AMNow with the strings in ugly style unicode:  ;; I didn't want to add an ascii to unicorn conversion procedure to the code.
Easily done
__UNICODE__=1
include \masm32\include\masm32rt.inc
.data
STRING mystring,"This will be unicode if __UNICODE__ is declared, otherwise ANSI"


zedd151

Quote from: sinsi on April 17, 2025, 09:18:28 AM
Quote from: zedd151 on April 17, 2025, 08:43:32 AMNow with the strings in ugly style unicode:  ;; I didn't want to add an ascii to unicorn conversion procedure to the code.
Easily done
__UNICODE__=1
include \masm32\include\masm32rt.inc
.data
STRING mystring,"This will be unicode if __UNICODE__ is declared, otherwise ANSI"
I'm not a unicorn guy. I did know that, but seldom use it. My memory fades fast. Thanks.

guga

Excellent !

I knew i could be done without manifest, in masm as well. :thumbsup:  :thumbsup:  :thumbsup:
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

zedd151

Quote from: guga on April 17, 2025, 09:44:08 AMExcellent !

I knew i could be done without manifest, in masm as well. :thumbsup:  :thumbsup:  :thumbsup:
I wish I would have done a better job though, on the Unicode strings. Mine looks very untidy.  :biggrin:

guga

Try the suggestion Sinsi did with
__UNICODE__=1
include \masm32\include\masm32rt.inc
.data
STRING mystring,"This will be unicode if __UNICODE__ is declared, otherwise ANSI"

Btw...it´s good all those different sintaxes for me, because i can understand it better to try a translator. David send me the masm manual to take a look over the syntax as well.
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

zedd151

#73
How about not using __UNICODE__=1 and write the macro in the source:azn: 

Done!
; #########################################################################

    .386
    .model flat, stdcall
    option casemap :none  ; case sensitive

; #########################################################################

    include \masm32\include\windows.inc
    include \masm32\include\user32.inc
    include \masm32\include\kernel32.inc
    include \masm32\include\gdi32.inc
    include \masm32\macros\macros.asm  ;; added for the modified STRINGS macro; has another macro call inside of it
   
   
    includelib \masm32\lib\user32.lib
    includelib \masm32\lib\kernel32.lib
    includelib \masm32\lib\gdi32.lib


STRING MACRO data_label,quoted_text:VARARG ;; modifed from that in the masm32 SDK
    WSTR data_label,quoted_text,0
ENDM

TDCBF_OK_BUTTON        equ 1
TDCBF_YES_BUTTON        equ 2
TDCBF_NO_BUTTON        equ 4
TDCBF_CANCEL_BUTTON    equ 8
TDCBF_RETRY_BUTTON      equ 16
TDCBF_CLOSE_BUTTON      equ 32

TD_WARNING_ICON        equ 0FFFFh
TD_ERROR_ICON          equ 0FFFEh
TD_INFORMATION_ICON    equ 0FFFDh
TD_SHIELD_ICON          equ 0FFFCh


 
; Structure definitions
TASKDIALOG_BUTTON struct
    nButtonID      DWORD ?
    pszButtonText  DWORD ? ; Pointer to Unicode string
TASKDIALOG_BUTTON ends

TASKDIALOGCONFIG struct
    cbSize              DWORD 0
    hwndParent          HWND 0
    hInstance          HINSTANCE 0
    dwFlags            DWORD 0
    dwCommonButtons    DWORD 0
    pszWindowTitle      DWORD 0
    hMainIcon          DWORD 0
    pszMainInstruction  DWORD 0
    pszContent          DWORD 0
    cButtons            DWORD 0
    pButtons            DWORD 0
    nDefaultButton      DWORD 0
    cRadioButtons      DWORD 0
    pRadioButtons      DWORD 0
    nDefaultRadioButton DWORD 0
    pszVerificationText DWORD 0
    pszExpandedInformation DWORD 0
    pszExpandedControlText DWORD 0
    pszCollapsedControlText DWORD 0
    hFooterIcon        DWORD 0
    pszFooter          DWORD 0
    pfCallback          DWORD 0
    lpCallbackData      DWORD 0
    cxWidth            DWORD 0
TASKDIALOGCONFIG ends

.data
    hInstance          DWORD 0
    hDll                DWORD 0
    hTaskDialogIndirect DWORD 0
    nButtonPressed      DWORD 0

    ; Unicode strings
   
    STRING Sz_Radio1, "Lets do Item1", 0, 0
    STRING Sz_Radio2, "Or maybe 2", 0, 0
    STRING Sz_Radio3, "Super secret option", 0, 0
    STRING Sz_MainInstruction, "You're about to do something stupid.", 0, 0
    STRING Sz_Content, "Are you absolutely sure you want to continue with this really bad idea?", 0, 0
    STRING Sz_WindowTitle, "cTaskDialog Project", 0, 0

    ;; ascii strings
    Sz_Comctl32 db ".\COMCTL32.dll", 0
    Sz_TaskDialogIndirect db "TaskDialogIndirect", 0

    ; Radio button array
    RadioButtons        TASKDIALOG_BUTTON \
                        <110, OFFSET Sz_Radio1>,
                        <111, OFFSET Sz_Radio2>,
                        <112, OFFSET Sz_Radio3>

    ; TaskDialog configuration
  TaskDialogConfig    TASKDIALOGCONFIG \
                        <96, 0, 0, 0, TDCBF_YES_BUTTON or TDCBF_NO_BUTTON, \
                        OFFSET Sz_WindowTitle, TD_SHIELD_ICON, OFFSET Sz_MainInstruction, \
                        OFFSET Sz_Content, 0, 0, 0, 3, OFFSET RadioButtons, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>


.code
start:
    ; Get module handle
    invoke GetModuleHandle, NULL
    mov hInstance, eax

    ; Load COMCTL32.dll
    invoke LoadLibrary, addr Sz_Comctl32
    mov hDll, eax

    ; Get TaskDialogIndirect address
    invoke GetProcAddress, hDll, addr Sz_TaskDialogIndirect
    mov hTaskDialogIndirect, eax

    ; Call TaskDialogIndirect
    push 0
    push 0
    push OFFSET nButtonPressed
    push OFFSET TaskDialogConfig
    call hTaskDialogIndirect

    ; Exit process
    invoke ExitProcess, 0

end start

__UNICODE__=1 was a bad idea  :eusa_naughty: . It not only changed the desired strings to unicode, but all of the api function calls as well to '???????????W'. Necessitating the need for more strings to be unicode, etc.

I used a modified STRING macro in this code. (It doesn't depend on __UNICODE__ being set or not, always creates unicode string here - could probably be renamed to something more suitable)

guga

A couple of more things related to the weird name of those directories. I found some info at:
Exploring WinSXS

According to this article the last 8 bytes of the public token that forms the directory name seems to be a hash sha1 <public key token> holds the last 8 bytes (written in hexadecimal format) of the sha1 hash of the public key complementing the private key used to sign the assembly
So, this is what exists in one part of the directory name. But...i was wondering what are the last hexadecimal names "a865f0c28672571c" that forms the directory ?

Well...i 1st thought it could be some part of the SHA-1 hash mentioned on the article, but...a quick look on a decipher tool online at HAsh Identifier reveals that the last part "a865f0c28672571c" may corresponds to a Half MD5 hash.

Why it do matter if we want to find the proper directory ? Well...for us, it won´t change anything, as long we can easily scan for the dll over all directories inside WinSxS that matches to the initial parts of the data existent inside a manifest file (or doing a brute force, simply loading all dlls in those directories until it finds the needed Api. But...it is really interesting to see how complicated M$ do things as simple as write a directory for updated versions of their own dlls, rather than simply put those updates on the proper (main) directory related to x86
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