Hi Guys
Anyone ever succeeded to create a TaskDialog ?
References:
Link1 (https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-taskdialogindirect)
very good reference in VB6 (https://www.vbforums.com/showthread.php?777021-VB6-TaskDialogIndirect-Complete-class-implementation-of-Vista-Task-Dialogs)
Um, I give up: what, exactly, is a "task dialog" and what does it do?
The referenced Micro$oft Learn page doesn't exactly satisfy my curiosity:
QuoteThe TaskDialogIndirect function creates, displays, and operates a task dialog. The task dialog contains application-defined icons, messages, title, verification check box, command links, push buttons, and radio buttons.
Any pictures available?
Looks do-able: if I weren't so damn lazy I'd try to code one up just to see what it looks like. (That
TASKDIALOGCONFIG structure is a bitch, though!)
MS example
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
void __cdecl WinMainCRTStartup(void)
{
HINSTANCE hInst = GetModuleHandle(NULL);
int nButtonPressed = 0;
TASKDIALOGCONFIG config = {0};
const TASKDIALOG_BUTTON buttons[] = {
{ IDOK, L"Change password" }
};
config.cbSize = sizeof(config);
config.hInstance = hInst;
config.dwCommonButtons = TDCBF_CANCEL_BUTTON;
config.pszMainIcon = TD_WARNING_ICON;
config.pszMainInstruction = L"Change Password";
config.pszContent = L"Remember your changed password.";
config.pButtons = buttons;
config.cButtons = ARRAYSIZE(buttons);
TaskDialogIndirect(&config, &nButtonPressed, NULL, NULL);
switch (nButtonPressed)
{
case IDOK:
break; // the user pressed button 0 (change password).
case IDCANCEL:
break; // user canceled the dialog
default:
break; // should never happen
}
ExitProcess(0);
}
Minimal manifest for that MS example
<?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>
(https://i.postimg.cc/PLcTrhzs/Clipboard-04-10-2025-01.png) (https://postimg.cc/PLcTrhzs)
I don't get it.
It's a dialog. Big deal. What's so special about it?
Is it just a way of creating a dialog programmatically, without using a resource editor?
You know, Timo, your "drive-by" style of posting is quite annoying:
You post code (and of course, almost always in C, hardly ever in assembly language), but with absolutely no explanation.
Not helpful.
Quote from: NoCforMe on April 10, 2025, 09:53:13 AMIt's a dialog. Big deal. What's so special about it?
It seems to be a standard Windows MessageBox, but with a lot more that you can do (custom buttons etc,).
How many times have you wished for more than Yes, No, Cancel buttons?
Quote from: sinsi on April 10, 2025, 10:45:52 AMQuote from: NoCforMe on April 10, 2025, 09:53:13 AMIt's a dialog. Big deal. What's so special about it?
It seems to be a standard Windows MessageBox, but with a lot more that you can do (custom buttons etc,).
How many times have you wished for more than Yes, No, Cancel buttons?
True, but when I wish for that, I simply create the dialog I want (using my DialogGen app).
Takes maybe 5-10 min.
When I need more than an "OK" button I'd choose a quick and easy resource dialog box. Especially if many controls are needed. Guga can you post a screenshot of what you have in mind?
Here's another TaskDialog example. I have a few of them in an option trading program I wrote because Excel and some commercial apps could not do the analysis I wanted.
// Warn the user that if the Closed flag is set,
// the current value will be set to 0 and the account
// will be marked as Exclude From Account Totals
int iFlag = theApp.m_oDataSettings.GetDialogFlagsBit(BITPOS_ACCOUNT_CLOSED);
if(iFlag == 0 && m_bClosed)
{
CXTPTaskDialog dlg(this);
// See TaskMessages.xml (IDR_DIALOGS) in the HTML resources for the dialog contents
VERIFY(dlg.CreateFromResource(IDR_DIALOGS, L"DlgAccountClosedWarning"));
dlg.SetWidth(310); // #TaskDialog-width find a way to calculate this
dlg.SetMainInstruction(L"Closing an Account Affects Some Values");
dlg.SetContent(L"When an account is closed, the current value is set to 0 and 'Exclude Account from Totals' is set.\r\nIf this is acceptable, click OK, else click Cancel and do not close the account.");
dlg.SetVerificationText(L"Do not show this again.");
dlg.SetVerifyCheckState(FALSE); // FALSE = the checkbox gets displayed as unchecked
dlg.SetCommonButtons(TRUE, FALSE, FALSE, TRUE, FALSE, FALSE); // the booleans correspond to IDOK, IDYES, IDNO, IDCANCEL, IDRETRY, and IDCLOSE
dlg.SetDefaultButton(IDCANCEL);
INT_PTR iResult = dlg.DoModal();
if(iResult == IDCANCEL)
{
return;
}
BOOL bDoNotShow = dlg.IsVerificiationChecked();
theApp.m_oDataSettings.SetDialogFlagsBit(BITPOS_ACCOUNT_CLOSED, bDoNotShow ? BITPOS_SET : BITPOS_CLEAR);
CNotification oNotify(SENDER_TRADES_VIEW, RM_Settings_Changed, NULL, NULL);
theApp.m_oData.GetFrameWnd()->NotifySubscribers(oNotify);
// The user still wants to close the account,
// so set the current value to 0 and set Exclude Account from Totals to true.
m_sCurrentValue = "0.00";
m_bExcludeFromTotals = true;
}
Any result that has to be remembered, such as "Do not show me this again", is saved in a PostgreSQL database.
The dialog XML in resources looks like this:
<Dialog Name="DlgAccountClosedWarning">
<WindowTitle>Close Account is selected</WindowTitle>
<MainInstruction Image="*Information">msg</MainInstruction>
<Verification Checked="true">Don't show this again</Verification>
<Buttons>
<OK/>
</Buttons>
</Dialog>
This program is (obviously) in C++ now, but I have considered rewriting it in an assembly language just to get back into it.
Quote from: zedd151 on April 10, 2025, 11:28:18 AMWhen I need more than an "OK" button I'd choose a quick and easy resource dialog box. Especially if many controls are needed. Guga can you post a screenshot of what you have in mind?
Hi Zedd, I wasn't thinking about anything specific. I found these links and this "new" class while I was looking for a way to fix a problem in a RosAsm TAB control. I was looking for ways to change the color of a Tab control's header, without having to use subclasses, and I accidentally found these links that seemed interesting to me, especially these examples in VB6. I'm trying to fix a Tab and make it have colors in the header, but I'm not getting it. And worse, since the SysTabControl is in a dialog box, if I use TCS_OWNERDRAWFIXED, it deletes the icons and texts and I would have to redraw them.
(https://i.ibb.co/gZ0WG0sL/fdsaf-Image2.png) (https://ibb.co/gZ0WG0sL)
This class seems interesting, though. But, it seems it is mandatory to use manifest, right Timo ? The examples on the VB6 link are really cool, btw. Perhaps it would be interesting to port to asm eventually.
Quote from: guga on April 10, 2025, 12:32:28 PMThis class seems interesting, though. But, it seems it is mandatory to use manifest, right Timo ? The examples on the VB6 link are really cool, btw. Perhaps it would be interesting to port to asm eventually.
At least Windows 7 needs that manifest for commctrl 6.0, but not sure about Windows 10
Quote from: guga on April 10, 2025, 12:32:28 PMThis class seems interesting, though. But, it seems it is mandatory to use manifest, right Timo ? The examples on the VB6 link are really cool, btw. Perhaps it would be interesting to port to asm eventually.
I can definitely see creating this in assembly language.
If I understand it correctly, the
TaskDialogIndirect() function uses the
TASKDIALOGCONFIG structure to determine what to put into the dialog.
I'm guessing that while you get to choose what all goes in there, you don't really have any control over the layout. Which is good, from the point of view of the poor slob who's writing this in MASM, because you can just plop controls in preset locations and with preset sizes.
I'm wondering, though: is this really easier than just creating a dialog using the resource editor? That way you get to lay it out so it looks nice and works logically.
Maybe being able to create a dialog with a limited set of choices might be a Good Thing.
And you could probably simplify it a bit: that
TASKDIALOGCONFIG structure is pretty horrible.
Plus you wouldn't need no stinkin' manifest ...
Of course, the task dialog function does let you define hyperlinks within the dialog, something that would be a lot of work to implement (I'm guessing).
Quote from: NoCforMe on April 10, 2025, 12:51:22 PMPlus you wouldn't need no stinkin' manifest ...
QuoteMichael Taylor 57,971 Reputation points
Sep 30, 2022, 11:46 PM
It's complicated. The Common Controls library is an OS component. The version you're looking at is the last version (5.82) that was developed before the new CC library came into being. If an app uses the CC library then this is the version it'll get.
However starting with v6 it is now a side-by-side binary. Therefore the actual file resides under the WinSxS folder. If an app needs to use the v6+ version then it must have an app manifest. That is discussed here. If an app uses a manifest then ultimately it will use the SxS version in this folder. If there is no manifest then it is pre-6 and uses the last version which is 5.82.
If you do a quick search for the binary then you'll see that the latest current version appears to be 10.0.22000.1 but that can change and it doesn't really matter unless your app manifest references that version anyway. You should always use the minimal version that your app requires.
https://learn.microsoft.com/en-us/answers/questions/1031264/what-is-the-latest-version-of-windows-os-file-comc (https://learn.microsoft.com/en-us/answers/questions/1031264/what-is-the-latest-version-of-windows-os-file-comc)
linker can write external manifest, if source file have this
.drectve SEGMENT
db "-manifestdependency:""type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"""
.drectve ENDS
newer linker can create resource section too
.drectve SEGMENT
db "-manifest:embed -manifestdependency:""type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"""
.drectve SEGMENT
What the hell are you going on about?
I obviously meant you wouldn't need no stinkin' manifest if you wrote your own "task dialog" procedure (in assembly language, naturally).
Quote from: NoCforMe on April 10, 2025, 12:51:22 PMQuote from: guga on April 10, 2025, 12:32:28 PMThis class seems interesting, though. But, it seems it is mandatory to use manifest, right Timo ? The examples on the VB6 link are really cool, btw. Perhaps it would be interesting to port to asm eventually.
I can definitely see creating this in assembly language.
If I understand it correctly, the TaskDialogIndirect() function uses the TASKDIALOGCONFIG structure to determine what to put into the dialog.
I'm guessing that while you get to choose what all goes in there, you don't really have any control over the layout. Which is good, from the point of view of the poor slob who's writing this in MASM, because you can just plop controls in preset locations and with preset sizes.
I'm wondering, though: is this really easier than just creating a dialog using the resource editor? That way you get to lay it out so it looks nice and works logically.
Maybe being able to create a dialog with a limited set of choices might be a Good Thing.
And you could probably simplify it a bit: that TASKDIALOGCONFIG structure is pretty horrible.
Plus you wouldn't need no stinkin' manifest ...
Of course, the task dialog function does let you define hyperlinks within the dialog, something that would be a lot of work to implement (I'm guessing).
I was reading this structure and indeed, it is horrible. For what i saw so far, as Timo pointed out, it do, in fact, needs this manifest thing. The exported function does not exists on normal comctl32 dll (syswow64 directory), but on newer versions located deep inside some weird paths of windows 10.
I´ll never understand why M$ do such stupidities. Why the hell they put an older version of comclt32 in the default system directory at the 1st place ? The least they could do is put all those newer versions on the default windows system paths.
QuoteI'm wondering, though: is this really easier than just creating a dialog using the resource editor
Probably not, i was mainly wanting to give a try after i saw the images of the results on the VB6 forum, but without ways for me to use those manifest resources, i´ll have to work with this later.
Quote from: guga on April 10, 2025, 03:05:44 PMI´ll never understand why M$ do such stupidities. Why the hell they put an older version of comclt32 in the default system directory at the 1st place ? The least they could do is put all those newer versions on the default windows system paths.
Surely you remember "DLL hell"?
The manifest lets Windows know which version you want.
SxS is a way of letting different versions of the same DLL co-exist
side-by-side :biggrin:
It's also another abstraction away for the poor C++ programmer
Quote from: sinsi on April 10, 2025, 03:50:54 PMQuote from: guga on April 10, 2025, 03:05:44 PMI´ll never understand why M$ do such stupidities. Why the hell they put an older version of comclt32 in the default system directory at the 1st place ? The least they could do is put all those newer versions on the default windows system paths.
Surely you remember "DLL hell"?
The manifest lets Windows know which version you want.
SxS is a way of letting different versions of the same DLL co-exist side-by-side :biggrin:
It's also another abstraction away for the poor C++ programmer
:biggrin: :biggrin: :biggrin:
Anyway...i succeeded to make this stuff working without manifest thingies.
(https://i.ibb.co/5xCTpTWM/aaImage3.png) (https://ibb.co/TqJcjcBv)
I had to use LoadLibraryA and specific the full path to that hidden comctl32 where this Api was located.
I´m posting here the port of this thing to RosAsm. I won´t release the working app, because probably the path of yours should be different than mine. (This could be solved with FindFirstFile pointing to C:\Windows\WinSxS\, then locating all subdirectories where the comctl32 is located and then using GetProcAddress to make sure if that dll contains this damn api). A hell, indeed, without manifest :dazzled:
The equates and structures for this thing are:
; TaskDialog structures, equates and structures displacements
[TASKDIALOGCONFIG:
TASKDIALOGCONFIG.cbSize: D$ len ; UINT (4 bytes)
TASKDIALOGCONFIG.hwndParent: D$ 0 ; HWND (4 bytes, ponteiro)
TASKDIALOGCONFIG.hInstance: D$ 0 ; HINSTANCE (4 bytes, ponteiro)
TASKDIALOGCONFIG.dwFlags: D$ 0 ; TASKDIALOG_FLAGS (4 bytes)
TASKDIALOGCONFIG.dwCommonButtons: D$ 0 ; TASKDIALOG_COMMON_BUTTON_FLAGS (4 bytes)
TASKDIALOGCONFIG.pszWindowTitle: D$ 0 ; LPCWSTR (4 bytes, ponteiro para string Unicode)
TASKDIALOGCONFIG.hMainIcon: D$ 0 ; HICON (4 bytes, union com pszMainIcon)
TASKDIALOGCONFIG.pszMainInstruction: D$ 0 ; LPCWSTR (4 bytes, ponteiro)
TASKDIALOGCONFIG.pszContent: D$ 0 ; LPCWSTR (4 bytes, ponteiro)
TASKDIALOGCONFIG.cButtons: D$ 0 ; UINT (4 bytes)
TASKDIALOGCONFIG.pButtons: D$ 0 ; const TASKDIALOG_BUTTON* (4 bytes, ponteiro)
TASKDIALOGCONFIG.nDefaultButton: D$ 0 ; int (4 bytes)
TASKDIALOGCONFIG.cRadioButtons: D$ 0 ; UINT (4 bytes)
TASKDIALOGCONFIG.pRadioButtons: D$ 0 ; const TASKDIALOG_BUTTON* (4 bytes, ponteiro)
TASKDIALOGCONFIG.nDefaultRadioButton: D$ 0 ; int (4 bytes)
TASKDIALOGCONFIG.pszVerificationText: D$ 0 ; LPCWSTR (4 bytes, ponteiro)
TASKDIALOGCONFIG.pszExpandedInformation: D$ 0 ; LPCWSTR (4 bytes, ponteiro)
TASKDIALOGCONFIG.pszExpandedControlText: D$ 0 ; LPCWSTR (4 bytes, ponteiro)
TASKDIALOGCONFIG.pszCollapsedControlText: D$ 0 ; LPCWSTR (4 bytes, ponteiro)
TASKDIALOGCONFIG.hFooterIcon: D$ 0 ; HICON (4 bytes, union com pszFooterIcon)
TASKDIALOGCONFIG.pszFooter: D$ 0 ; LPCWSTR (4 bytes, ponteiro)
TASKDIALOGCONFIG.pfCallback: D$ 0 ; PFTASKDIALOGCALLBACK (4 bytes, ponteiro para função)
TASKDIALOGCONFIG.lpCallbackData: D$ 0 ; LONG_PTR (4 bytes em 32 bits)
TASKDIALOGCONFIG.cxWidth: D$ 0] ; UINT (4 bytes)
; displacements for TASKDIALOGCONFIG structure
[TASKDIALOGCONFIG.cbSizeDis 0
TASKDIALOGCONFIG.hwndParentDis 4
TASKDIALOGCONFIG.hInstanceDis 8
TASKDIALOGCONFIG.dwFlagsDis 12
TASKDIALOGCONFIG.dwCommonButtonsDis 16
TASKDIALOGCONFIG.pszWindowTitleDis 20
TASKDIALOGCONFIG.hMainIconDis 24
TASKDIALOGCONFIG.pszMainInstructionDis 28
TASKDIALOGCONFIG.pszContentDis 32
TASKDIALOGCONFIG.cButtonsDis 36
TASKDIALOGCONFIG.pButtonsDis 40
TASKDIALOGCONFIG.nDefaultButtonDis 44
TASKDIALOGCONFIG.cRadioButtonsDis 48
TASKDIALOGCONFIG.pRadioButtonsDis 52
TASKDIALOGCONFIG.nDefaultRadioButtonDis 56
TASKDIALOGCONFIG.pszVerificationTextDis 60
TASKDIALOGCONFIG.pszExpandedInformationDis 64
TASKDIALOGCONFIG.pszExpandedControlTextDis 68
TASKDIALOGCONFIG.pszCollapsedControlTextDis 72
TASKDIALOGCONFIG.hFooterIconDis 76
TASKDIALOGCONFIG.pszFooterDis 80
TASKDIALOGCONFIG.pfCallbackDis 84
TASKDIALOGCONFIG.lpCallbackDataDis 88
TASKDIALOGCONFIG.cxWidthDis 92]
[Size_Of_TASKDIALOGCONFIG 96]
; Equates used by this thing (In hexadecimal)
; enum _TASKDIALOG_COMMON_BUTTON_FLAGS ; 4 bytes
[TDCBF_OK_BUTTON 01
TDCBF_YES_BUTTON 02
TDCBF_NO_BUTTON 04
TDCBF_CANCEL_BUTTON 08
TDCBF_RETRY_BUTTON 010
TDCBF_CLOSE_BUTTON 020]
; enum _TASKDIALOG_ELEMENTS ; 4 bytes
[TDE_CONTENT 0
TDE_EXPANDED_INFORMATION 01
TDE_FOOTER 02
TDE_MAIN_INSTRUCTION 03]
; enum _TASKDIALOG_FLAGS ; 4 bytes
[TDF_ENABLE_HYPERLINKS 01
TDF_USE_HICON_MAIN 02
TDF_USE_HICON_FOOTER 04
TDF_ALLOW_DIALOG_CANCELLATION 08
TDF_USE_COMMAND_LINKS 010
TDF_USE_COMMAND_LINKS_NO_ICON 020
TDF_EXPAND_FOOTER_AREA 040
TDF_EXPANDED_BY_DEFAULT 080
TDF_VERIFICATION_FLAG_CHECKED 0100
TDF_SHOW_PROGRESS_BAR 0200
TDF_SHOW_MARQUEE_PROGRESS_BAR 0400
TDF_CALLBACK_TIMER 0800
TDF_POSITION_RELATIVE_TO_WINDOW 01000
TDF_RTL_LAYOUT 02000
TDF_NO_DEFAULT_RADIO_BUTTON 04000
TDF_CAN_BE_MINIMIZED 08000
TDF_SIZE_TO_CONTENT 01000000]
; enum _TASKDIALOG_ICON_ELEMENTS ; 4 bytes
[TDIE_ICON_MAIN 0
TDIE_ICON_FOOTER 01]
; enum _TASKDIALOG_MESSAGES ; 4 bytes
[TDM_NAVIGATE_PAGE 0465
TDM_CLICK_BUTTON 0466
TDM_SET_MARQUEE_PROGRESS_BAR 0467
TDM_SET_PROGRESS_BAR_STATE 0468
TDM_SET_PROGRESS_BAR_RANGE 0469
TDM_SET_PROGRESS_BAR_POS 046A
TDM_SET_PROGRESS_BAR_MARQUEE 046B
TDM_SET_ELEMENT_TEXT 046C
TDM_CLICK_RADIO_BUTTON 046E
TDM_ENABLE_BUTTON 046F
TDM_ENABLE_RADIO_BUTTON 0470
TDM_CLICK_VERIFICATION 0471
TDM_UPDATE_ELEMENT_TEXT 0472
TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE 0473
TDM_UPDATE_ICON 0474]
; enum _TASKDIALOG_NOTIFICATIONS ; 4 bytes
[TDN_CREATED 0
TDN_NAVIGATED 01
TDN_BUTTON_CLICKED 02
TDN_HYPERLINK_CLICKED 03
TDN_TIMER 04
TDN_DESTROYED 05
TDN_RADIO_BUTTON_CLICKED 06
TDN_DIALOG_CONSTRUCTED 07
TDN_VERIFICATION_CLICKED 08
TDN_HELP 09
TDN_EXPANDO_BUTTON_CLICKED 0A]
; enum _TASKPAGE ; 4 bytes
[TASKPAGE_TASK 0
TASKPAGE_SCHEDULE 01
TASKPAGE_SETTINGS 02]
; enum _TASK_ACTION_TYPE ; 4 bytes
[TASK_ACTION_EXEC 0
TASK_ACTION_COM_HANDLER 05
TASK_ACTION_SEND_EMAIL 06
TASK_ACTION_SHOW_MESSAGE 07]
; enum _TASK_COMPATIBILITY ; 4 bytes
[TASK_COMPATIBILITY_AT 0
TASK_COMPATIBILITY_V1 01
TASK_COMPATIBILITY_V2 02
TASK_COMPATIBILITY_V2_1 03
TASK_COMPATIBILITY_V2_2 04
TASK_COMPATIBILITY_V2_3 05
TASK_COMPATIBILITY_V2_4 06]
; enum _TASK_CREATION ; 4 bytes
[TASK_VALIDATE_ONLY 01
TASK_CREATE 02
TASK_UPDATE 04
TASK_CREATE_OR_UPDATE 06
TASK_DISABLE 08
TASK_DONT_ADD_PRINCIPAL_ACE 010
TASK_IGNORE_REGISTRATION_TRIGGERS 020]
; enum _TASK_ENUM_FLAGS ; 4 bytes
[TASK_ENUM_HIDDEN 01]
; enum _TASK_INSTANCES_POLICY ; 4 bytes
[TASK_INSTANCES_PARALLEL 0
TASK_INSTANCES_QUEUE 01
TASK_INSTANCES_IGNORE_NEW 02
TASK_INSTANCES_STOP_EXISTING 03]
; enum _TASK_LOGON_TYPE ; 4 bytes
[TASK_LOGON_NONE 0
TASK_LOGON_PASSWORD 01
TASK_LOGON_S4U 02
TASK_LOGON_INTERACTIVE_TOKEN 03
TASK_LOGON_GROUP 04
TASK_LOGON_SERVICE_ACCOUNT 05
TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD 06]
; enum _TASK_PROCESSTOKENSID ; 4 bytes
[TASK_PROCESSTOKENSID_NONE 0
TASK_PROCESSTOKENSID_UNRESTRICTED 01
TASK_PROCESSTOKENSID_DEFAULT 02]
; enum _TASK_RUNLEVEL ; 4 bytes
[TASK_RUNLEVEL_LUA 0
TASK_RUNLEVEL_HIGHEST 01]
; enum _TASK_RUN_FLAGS ; 4 bytes
[TASK_RUN_NO_FLAGS 0
TASK_RUN_AS_SELF 01
TASK_RUN_IGNORE_CONSTRAINTS 02
TASK_RUN_USE_SESSION_ID 04
TASK_RUN_USER_SID 08]
; enum _TASK_SESSION_STATE_CHANGE_TYPE ; 4 bytes
[TASK_CONSOLE_CONNECT 01
TASK_CONSOLE_DISCONNECT 02
TASK_REMOTE_CONNECT 03
TASK_REMOTE_DISCONNECT 04
TASK_SESSION_LOCK 07
TASK_SESSION_UNLOCK 08]
; enum _TASK_STATE ; 4 bytes
[TASK_STATE_UNKNOWN 0
TASK_STATE_DISABLED 01
TASK_STATE_QUEUED 02
TASK_STATE_READY 03
TASK_STATE_RUNNING 04]
[TD_WARNING_ICON 0FFFF
TD_ERROR_ICON 0FFFE
TD_INFORMATION_ICON 0FFFD
TD_SHIELD_ICON 0FFFC]
; TASKDIALOG_BUTTON structure
[TASKDIALOG_BUTTON:
TASKDIALOG_BUTTON.nButtonID: D$ &IDOK
TASKDIALOG_BUTTON.pszButtonText: D$ Sz_ChangePassword]
; Variables to make this stuff works !
[Sz_ChangePassword: U$ "Change password", 0] ; Unicode String
[Sz_ChangePassword2: U$ "Change Password", 0] ; Unicode String
[Sz_Text: U$ "Remember your changed password.", 0] ; Unicode String
[hInstance: D$ 0]
[nButtonPressed: D$ 0]
[hDll: D$ 0]
[hTaskDialogIndirect: D$ 0]
And the code (Tks, Timo), to make this work. Now without manifest.
Main:
call 'KERNEL32.GetModuleHandleA' &NULL
mov D$hInstance eax
call 'KERNEL32.LoadLibraryA' {"C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.4355_none_a865f0c28672571c\COMCTL32.dll", 0}
mov D$hDll eax
call 'kernel32.GetProcAddress' eax, {B$ "TaskDialogIndirect", 0}
mov D$hTaskDialogIndirect eax
mov D$nButtonPressed 0
mov eax D$hInstance | mov D$TASKDIALOGCONFIG.hInstance eax
mov D$TASKDIALOGCONFIG.dwCommonButtons TDCBF_CANCEL_BUTTON
mov D$TASKDIALOGCONFIG.hMainIcon TD_WARNING_ICON
mov D$TASKDIALOGCONFIG.pszMainInstruction Sz_ChangePassword2
mov D$TASKDIALOGCONFIG.pszContent Sz_Text
mov D$TASKDIALOGCONFIG.pButtons TASKDIALOG_BUTTON
mov D$TASKDIALOGCONFIG.cButtons 1
call D$hTaskDialogIndirect TASKDIALOGCONFIG, nButtonPressed, 0, 0
call 'KERNEL32.ExitProcess' 0
The equates can also be found with wine at:
https://github.com/wine-mirror/wine/blob/master/include/commctrl.h#L5541 (https://github.com/wine-mirror/wine/blob/master/include/commctrl.h#L5541)
And one more examples on how to use this stuff (Sorry, found it in russian, so far - http://www.pmbk.ru/lister/055/4/index.shtml (http://www.pmbk.ru/lister/055/4/index.shtml) )
Some more tests based on the VB link provided earlier
(https://i.ibb.co/9kCNPYKB/fdsaf-Image4.png) (https://ibb.co/B5StksWv)
Main:
call 'KERNEL32.GetModuleHandleA' &NULL
mov D$hInstance eax
call 'KERNEL32.LoadLibraryA' {"C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.4355_none_a865f0c28672571c\COMCTL32.dll", 0}
mov D$hDll eax
call 'kernel32.GetProcAddress' eax, {B$ "TaskDialogIndirect", 0}
mov D$hTaskDialogIndirect eax
mov D$nButtonPressed 0
mov eax D$hInstance | mov D$TASKDIALOGCONFIG.hInstance eax
mov D$TASKDIALOGCONFIG.dwCommonButtons (TDCBF_YES_BUTTON+TDCBF_NO_BUTTON)
mov D$TASKDIALOGCONFIG.hMainIcon TD_SHIELD_ICON
mov D$TASKDIALOGCONFIG.pszMainInstruction {U$ "You're about to do something stupid.", 0};Sz_ChangePassword2
mov D$TASKDIALOGCONFIG.pszContent {U$ "Are you absolutely sure you want to continue with this really bad idea?", 0}
mov D$TASKDIALOGCONFIG.pButtons TASKDIALOG_BUTTON
mov D$TASKDIALOGCONFIG.cButtons 1
mov D$TASKDIALOGCONFIG.pszWindowTitle {U$ "cTaskDialog Project", 0}
call D$hTaskDialogIndirect TASKDIALOGCONFIG, nButtonPressed, 0, 0
call 'KERNEL32.ExitProcess' 0
Next, is similar as above
(https://i.ibb.co/JFygkWCx/fdsfsdf-Image7.png) (https://ibb.co/h1Zw8xCX)
[TASKDIALOG_RADIO_BUTTON:
TASKDIALOG_RADIO_BUTTON1.nButtonID: D$ 110
TASKDIALOG_RADIO_BUTTON1.pszButtonText: D$ Sz_Radio1
TASKDIALOG_RADIO_BUTTON2.nButtonID: D$ 111
TASKDIALOG_RADIO_BUTTON2.pszButtonText: D$ Sz_Radio2
TASKDIALOG_RADIO_BUTTON3.nButtonID: D$ 112
TASKDIALOG_RADIO_BUTTON3.pszButtonText: D$ Sz_Radio3]
[Sz_Radio1: U$ "Let´s do Item1", 0] ; Unicode String
[Sz_Radio2: U$ "Or maybe 2", 0] ; Unicode String
[Sz_Radio3: U$ "Super secret option", 0] ; Unicode String
Main:
call 'KERNEL32.GetModuleHandleA' &NULL
mov D$hInstance eax
call 'KERNEL32.LoadLibraryA' {"C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.4355_none_a865f0c28672571c\COMCTL32.dll", 0}
mov D$hDll eax
call 'kernel32.GetProcAddress' eax, {B$ "TaskDialogIndirect", 0}
mov D$hTaskDialogIndirect eax
mov D$TASKDIALOGCONFIG.dwCommonButtons (TDCBF_YES_BUTTON+TDCBF_NO_BUTTON)
mov D$TASKDIALOGCONFIG.hMainIcon TD_SHIELD_ICON
mov D$TASKDIALOGCONFIG.pszMainInstruction {U$ "You're about to do something stupid.", 0};Sz_ChangePassword2
mov D$TASKDIALOGCONFIG.pszContent {U$ "Are you absolutely sure you want to continue with this really bad idea?", 0}
mov D$TASKDIALOGCONFIG.pRadioButtons TASKDIALOG_RADIO_BUTTON
mov D$TASKDIALOGCONFIG.cRadioButtons 3
mov D$TASKDIALOGCONFIG.pszWindowTitle {U$ "cTaskDialog Project", 0}
call D$hTaskDialogIndirect TASKDIALOGCONFIG, nButtonPressed, 0, 0
call 'KERNEL32.ExitProcess' 0
Not worth all the damn trouble, I'd say.
Quote from: NoCforMe on April 10, 2025, 05:58:26 PMNot worth all the damn trouble, I'd say.
Couldn´t agree more. It´s out of my mind why M$ do such things.
Quote from: guga on April 10, 2025, 06:12:57 PMQuote from: NoCforMe on April 10, 2025, 05:58:26 PMNot worth all the damn trouble, I'd say.
Couldn´t agree more. It´s out of my mind why M$ do such things.
I'm sure it's all a part of Microsoft's
One UI To Rule Them AllTM (https://learn.microsoft.com/en-us/windows/apps/design/)
Now testing a small include-file for TaskDialog.
Test program using ml.64 isn't ready, perhaps never, but working code for poasm is under tests.
;TestTaskDialog2.asm
option dotname
option casemap:none
include TaskDialogMS.inc
includelib kernel32.lib
includelib comctl32.lib
tp_ExitProcess typedef proto :dword
externdef __imp_ExitProcess : ptr tp_ExitProcess
ExitProcess equ <__imp_ExitProcess>
tp_GetModuleHandle typedef proto :qword
externdef __imp_GetModuleHandleA : ptr tp_GetModuleHandle
GetModuleHandle equ <__imp_GetModuleHandleA>
tp_TaskDialogIndirect typedef proto :qword, :qword, :qword, :qword
externdef __imp_TaskDialogIndirect : ptr tp_TaskDialogIndirect
TaskDialogIndirec equ <__imp_TaskDialogIndirect>
.drectve SEGMENT
;db "-largeaddressaware:no "
db "-manifest:embed -manifestdependency:""type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"""
;db "-manifestdependency:""type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"""
.drectve ENDS
.data
hInst qword ?
sText1 dw 'T','e','s','t',0
sContent dw 'T','e','s','t',0
tdc TASKDIALOGCONFIG <sizeof TASKDIALOGCONFIG,0,0,0,TDCBF_CANCEL_BUTTON,0,<TD_WARNING_ICON>,sText1,sContent>
.code
mainCRTStartup proc
sub rsp, 28h
;invoke GetModuleHandle, 0
xor ecx, ecx
call GetModuleHandle
mov hInst, rax
lea rcx, tdc
mov tdc.hInstance, rax
;mov tdc.dwCommonButtons, TDCBF_CANCEL_BUTTON
;mov tdc.pszMainIcon.u1, TD_WARNING_ICON
;mov tdc.pszMainInstruction, offset sText1
;mov tdc.pszContent, offset sContent
;invoke TaskDialogIndirec, addr tdc, 0, 0, 0
xor r9d, r9d
xor r8d, r8d
xor ecx, ecx
lea rcx, tdc
;invoke ExitProcess, 0
xor ecx, ecx
call ExitProcess
mainCRTStartup endp
end
EDIT: add missing option casemap:none
OK, enough with the stupid "task dialog" stuff; what the hell does "task dialog" mean, anyhow?
Here's my homebrew version for you to check out.
It creates a custom dialog, so I'm calling it a "custom dialog creator".
The creation module contains a subroutine to create an in-memory dialog template from a set of simple structures,
CreateCustomDialog(). It also has the dialog procedure you use to deploy the dialog,
CustomDialogProc().
Much, much simpler than the Micro$oft abomination. Here's how you set up a dialog (the one in the attached testbed):
CustomDialogParms $CD_info <DialogTitle, DialogItemList, 9, NULL, $dlgFontSize, "Segoe UI">
DialogItemList LABEL $CD_item
$CD_item <$CD_static1, Static1Text>
$CD_item <$CD_static2, Static2Text>
$CD_item <$CD_check, Radio1Text>
$CD_item <$CD_check, Radio2Text>
$CD_item <$CD_check, Radio3Text>
$CD_item <$CD_buttonOK, OKtext>
$CD_item <$CD_buttonCancel, CancelText>
$CD_item <$CD_button3, Btn3Text>
$CD_item <$CD_button4, Btn4Text>
plus the associated strings referred to there. (See the source.)
This creates a dialog with two static text fields, three checkboxes and four buttons, the first two of which are the familiar "OK" and "Cancel".
You can play around with this and create your own dialog (within limits).
This is only a proof-of-concept thing. The available controls are:
- Two static controls, one a larger one at the top for a big block of text, the second one a single line that displays text in a larger and bolder font
- One to three checkboxes
- One to three radio buttons
- Up to 4 buttons at the bottom
You can have either the radio buttons or the checkboxes, but not both, as they are created in the same location. (You could change this, of course, to accomodate both of these.)
Lots more stuff you could do with this: display a small bitmap image or icon; put in an edit field, etc.
Those other 2 buttons: not really sure what you would want to do with them. It's set up now so that either OK or Cancel closes the dialog, with OK returning the state of controls. (The results are returned in a
$CD_results structure showing the state of all possible settable controls.) So the other 2 buttons are kind of orphaned. I guess you could figure out some kind of hook scheme to transfer control to a custom procedure, but that seems kind of ugly.
Like to hear any ideas of where this could go from here. I think it's a potentially useful thing, more flexible than a
MessageBox.
Now with an icon!
CCD.jpg
All you gotta add is
IconFilename DB "Dice.ico", 0
$CD_item <$CD_icon, IconFilename>
Opened it in Radasm and this is the error i´ve got.
C:\Masm32\Bin\ML.EXE /c /coff /Cp /nologo /I"C:\Masm32\Include" "C:\masm32\examples\David\CreateCustomDialog\CreateCustomDialogTest.asm"
Assembling: C:\masm32\examples\David\CreateCustomDialog\CreateCustomDialogTest.asm
***********
ASCII build
***********
C:\Masm32\Bin\LINK.EXE /SUBSYSTEM:WINDOWS /RELEASE /VERSION:4.0 /LIBPATH:"C:\Masm32\Lib" "C:\masm32\examples\David\CreateCustomDialog\CreateCustomDialogTest.obj"
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
CreateCustomDialogTest.obj : error LNK2001: unresolved external symbol _CustomDialogProc@16
CreateCustomDialogTest.obj : error LNK2001: unresolved external symbol _CreateCustomDialog@4
CreateCustomDialogTest.exe : fatal error LNK1120: 2 unresolved externals
Make error(s) occured.
Total compile time 516 ms
Did you use the "makefile" I included, or copy it correctly?
@echo off
ml /c /coff /Fl /Sn CreateCustomDialog.asm
if errorlevel 1 goto errasm
ml /c /coff /Fl /Sn CreateCustomDialogTest.asm
if errorlevel 1 goto errasm
link /SUBSYSTEM:WINDOWS CreateCustomDialogTest CreateCustomDialog VisualStyles
if errorlevel 1 goto errlink
goto TheEnd
:errlink
echo _
echo Link error
goto TheEnd
:errasm
echo _
echo Assembly Error
:TheEnd
Works fine here.
I'm using link.exe version 5.12.8078
Both
I tried to simplyy click upon the makefile and nothing happened. Then, i tried to open the file in Radasm and this was the erropr it showed to me. I didn´t created another project in Radasm, i opened the file as asm, and tried to compile it directly. I tried to find where include the "includes" in Radasm properties (or something), but couldnt find.
Found the error when i clicked on the batch file. I now opened a command prompt, to see why it was not assembling
"Microsoft Windows [versão 10.0.19045.5737]
(c) Microsoft Corporation. Todos os direitos reservados.
C:\Users\Usuario>cd\
C:\>cd masm32
C:\masm32>cd examples
C:\masm32\examples>cd David
C:\masm32\examples\David>cd CreateCustomDialog
C:\masm32\examples\David\CreateCustomDialog>makeccdtest.bat
'ml' não é reconhecido como um comando interno
ou externo, um programa operável ou um arquivo em lotes.
_
Assembly Error
C:\masm32\examples\David\CreateCustomDialog>
"
It´s not finding the ml.exe. But still, can´t assemble it.
Quote from: NoCforMe on April 16, 2025, 11:09:14 AMWorks fine here.
I'm using link.exe version 5.12.8078
Works fine here using ml&link from the masm32 SDK, after restoring the bin path
in the batch file: "\masm32\bin\ml..."; \masm32\bin\link..." :rolleyes:
I didn't feel like adding the dice icon. I have been doing enough "rolling of the dice here lately" :skrewy:
(https://i.postimg.cc/k4XrxMxy/untitled.png)
guga if you know where ml and link are, just adjust the batch file. :smiley:
You shouldn't have to CD all over the place.
Great. Now it worked from the batch
@echo off
\masm32\bin\ml /c /coff /Fl /Sn CreateCustomDialog.asm
:ml /c /coff /Fl /Sn /Zi CreateCustomDialog.asm
if errorlevel 1 goto errasm
\masm32\bin\ml /c /coff /Fl /Sn CreateCustomDialogTest.asm
:ml /c /coff /Fl /Sn /Zi CreateCustomDialogTest.asm
if errorlevel 1 goto errasm
\masm32\bin\link /SUBSYSTEM:WINDOWS CreateCustomDialogTest CreateCustomDialog VisualStyles
:link /SUBSYSTEM:WINDOWS /debug CreateCustomDialogTest CreateCustomDialog VisualStyles
if errorlevel 1 goto errlink
dir CreateCustomDialog.*
goto TheEnd
:errlink
echo _
echo Link error
goto TheEnd
:errasm
echo _
echo Assembly Error
:TheEnd
How to make it also work with Radasm ?
(https://i.postimg.cc/2bzc16tC/Clipboard-04-15-2025-01.png) (https://postimg.cc/2bzc16tC)
Quote from: zedd151 on April 16, 2025, 11:31:16 AMWorks fine here using ml&link from the masm32 SDK, after restoring the bin path in the batch file: "\masm32\bin\ml..."; \masm32\bin\link..." :rolleyes:
Sorry; I have my
path set so I don't have to include those paths in all my batch files.
That's why [insert name of deity here] invented
path.
I ain't gonna change this ...
Quote from: guga on April 16, 2025, 11:40:48 AMGreat. Now it worked from the batch
\masm32\bin\ml ....
:thumbsup:
@NoCforMe... I never monkey around with any environment variables, even PATH. Thats what [insert ??? here] created make/batch files for. :biggrin:
Quote from: zedd151 on April 16, 2025, 11:44:16 AMQuote from: guga on April 16, 2025, 11:40:48 AMGreat. Now it worked from the batch
\masm32\bin\ml ....
:thumbsup:
I never monkey around wuth and environment variables, even PATH.
Well, you should; they actually make life easier.
I really don't understand the phobia folks here seem to have over this issue.
I suppose I'm going to get chewed out
again: "Don't you know that you're supposed to fully qualify the path to the executables in all the MASM32 batch files?
Why? Because that's the way we've been doing it for all these years."
Sorry; no.
So after this simply fascinating side trip into batch files and path names, can we focus on my project?
Any comments? ideas?
Quote from: NoCforMe on April 16, 2025, 11:48:44 AMSorry; no.
Thats fine. But are you
TABS or
spaces? Same kind of argument.
To each their own I'd suppose. :smiley:
Quote from: NoCforMe on April 16, 2025, 11:51:22 AMSo after ...can we focus on my project?
Absolutely! Correction: I had forgotten this is guga's topic. Maybe start your own? Your project NoCfroMe is interesting on its own :thumbsup: , but not what guga was asking about.
Quote from: zedd151 on April 16, 2025, 11:51:40 AMQuote from: NoCforMe on April 16, 2025, 11:48:44 AMSorry; no.
Thats fine. But are you TABS or spaces? Same kind of argument.
To each their own I'd suppose. :smiley:
That's easy:
Only an idiot would think it reasonable to fill a source code file with zillions of spaces.
Feh.
Ok, guys. Now, how to make it work in Radasm as well ? (Without a batch file, i mean)
About ideas, adding all other classes (listviews, comboboxes, richedit controls etc) would be nice.
All those other controls could be added, true. Not difficult to do.
But think about it: how would you handle all those?
Keep in mind that, at least as it now exists, this is pretty much a fixed-size thing.
If you look at the source, all the positions and sizes of all the controls are absolutely fixed.
So you could have a listbox, but its size would be fixed. And how would you access it? You'd have to export all the items in it, possibly through that $CD_results structure.
At this point what I'm really looking for are some non-programmer's ideas:
What would be the uses of custom dialogs?
What information would be needed in those dialogs (both input and output)?
Stuff like that, rather than nerdy details about controls.
Quote from: guga on April 16, 2025, 11:53:54 AMOk, guys. Now, how to make it work in Radasm as well ? (Without a batch file, i mean)
I don't know; how about you pretend that you just wrote those two assembly-language files and now you want to link them together (with
CreateCustomDialogTest.asm being the main one)? Handle them the way you'd handle any two source files you want to link together. No resource file or nothin'.
And if you can't figure that out--something that's pretty damn simple--maybe you should use something other than RadAsm. I have absolutely no problem doing this with my plain vanilla MASM setup.
So think about this problem with this custom-dialog scheme:
Let's say you want an edit control to gather some user input.
Fine and dandy. Easily implemented: I add an edit control type, and when the user clicks "OK" on the dialog, I get its text, store it in a global and pass a pointer to it in the $CD_results structure.
But wait: aren't we going to need some text before that edit field to tell the user what is supposed to be typed in there?
Yes, so how wide should that static field be? Now we're going to need to dynamically set the length of controls depending on their (text) contents, something that, for example, MessageBox() does for us. See how this complicates things?
This custom-dialog scheme should go to own topic.
Hopefully moderators move it to it's own place.
Quote from: TimoVJL on April 16, 2025, 04:03:34 PMThis custom-dialog scheme should go to own topic.
Hopefully moderators move it to it's own place.
Maybe, maybe not.
Matters not to me.
Looking at it a bit more, it's a lot more than just a message box.
You can get input from the user as it happens via a callback and you can send it messages.
There is a timer which calls the callback at ~50ms intervals, allowing you to e.g. update a progress bar.
It looks like a really good candidate for a Setup Wizard. You can have multiple TASKDIALOGCONFIG structures
and use TDM_NAVIGATE_PAGE to go forward or back.
Quote from: sinsi on April 16, 2025, 09:31:30 PMLooking at it a bit more, it's a lot more than just a message box.
You can get input from the user as it happens via a callback and you can send it messages.
There is a timer which calls the callback at ~50ms intervals, allowing you to e.g. update a progress bar.
It looks like a really good candidate for a Setup Wizard. You can have multiple TASKDIALOGCONFIG structures
and use TDM_NAVIGATE_PAGE to go forward or back.
Interesting. Now that we managed to work this without manifest embedded on the resource section, perhaps, it´w worth give this taskdialog a 2nd try.
Quote from: stoo23 on April 16, 2025, 06:50:02 PMQuotecan we focus on my project?
Pardon me but I thought this Topic was started by Guga and was asking about creating a 'Task Dialogue',...
Perhaps 'Your Project' Could have its Own thread ??
I had forgotten that this was gugas topic. I have corrected my post above:
Quote from: zedd151 on April 16, 2025, 11:51:40 AMQuote from: NoCforMe on April 16, 2025, 11:51:22 AMSo after ...can we focus on my project?
Absolutely! Correction: I had forgotten this is guga's topic. Maybe start your own? Your project NoCforMe is interesting on its own :thumbsup: , but not what guga was asking about.
Quote from: guga on April 16, 2025, 09:38:06 PMNow that we managed to work this without manifest embedded on the resource section
Are you sure? If I omit the manifest I get an error
Untitled.png
Quote from: sinsi on April 16, 2025, 11:18:52 PMQuote from: guga on April 16, 2025, 09:38:06 PMNow that we managed to work this without manifest embedded on the resource section
Are you sure? If I omit the manifest I get an error
Untitled.png
Hi Sinsi. That´s odd. I mean not using manifest on the app that is calling the dll. See reply 16.
You need to find in which directory inside WinSXS contains comctl32 with this Api and uses LoadLibrary to call it.
On my case it is located at: C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.4355_none_a865f0c28672571c\COMCTL32.dll
See here:
https://masm32.com/board/index.php?topic=12688.15 (https://masm32.com/board/index.php?topic=12688.15)
external manifest file may help.
tdi.exe.manifest
<?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>
RosAsm seems to be problem in these cases, if link.exe isn't used with object code.
Alternatively:
PCWSTR pFile = L"C:\\Windows\\WindowsShell.manifest"; // this exists from at least Win7 to Win11
ACTCTX ctx = {sizeof(ctx)};
HANDLE hAct;
ULONG_PTR cookie;
ctx.lpSource = pFile;
hAct = CreateActCtx(&ctx);
if(hAct != INVALID_HANDLE_VALUE)
{
ActivateActCtx(hAct, &cookie);
// great stuff
}
After ActivateActCtx LoadLibrary(comctl32) will be the 6.0 version. and you can GetProcAddress what you want.
Any non-GetProcAddress comctl32 functions will still go to the 5.82 version. You have to use an exe manifest to redirect those.
Quote from: TimoVJL on April 17, 2025, 03:08:54 AMexternal manifest file may help.
tdi.exe.manifest
<?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>
RosAsm seems to be problem in these cases, if link.exe isn't used with object code.
yes, but there ´s no link.exe in RosAsm. Since it doesn´t contains manifest on itself, when it tries to assemble (link) dlls, it uses loadlibrary to get the proper addresses and without the manifest, it will locate comctl with the older version and not the new one required by the manifest. I´ll fix that later .
I tried to port my example without manifest, but i don't remember what is the proper masm syntax. Qeditor keeps showing an error "C:\masm32\examples\TaskDialog\TaskDialog.asm(96) : error A2206: missing operator in expression"
This line is related to:
TaskDialogConfig TASKDIALOGCONFIG \
<96, 0, 0, 0, TDCBF_YES_BUTTON+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>
I did this:
; #########################################################################
.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
.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 0xFFFFh
TD_ERROR_ICON equ 0xFFFEh
TD_INFORMATION_ICON equ 0xFFFDh
TD_SHIELD_ICON equ 0xFFFCh
; 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
Sz_Radio1 TCHAR "Lets do Item1", 0, 0
Sz_Radio2 TCHAR "Or maybe 2", 0, 0
Sz_Radio3 TCHAR "Super secret option", 0, 0
Sz_MainInstruction TCHAR "You're about to do something stupid.", 0, 0
Sz_Content TCHAR "Are you absolutely sure you want to continue with this really bad idea?", 0, 0
Sz_WindowTitle TCHAR "cTaskDialog Project", 0, 0
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+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, OFFSET Sz_Comctl32
mov hDll, eax
; Get TaskDialogIndirect address
invoke GetProcAddress, hDll, OFFSET Sz_TaskDialogIndirect
mov hTaskDialogIndirect, eax
; Call TaskDialogIndirect
invoke TaskDialogIndirect, OFFSET TaskDialogConfig, ADDR nButtonPressed, 0, 0
; Exit process
invoke ExitProcess, 0
end start
Btw, i´m quite sure it won´t work at
invoke TaskDialogIndirect, OFFSET TaskDialogConfig, ADDR nButtonPressed, 0, 0
because TaskDialogIndirect should be replace by the pointer at eax
But, as i dont remember how to use invoke on such situations, i´m posting here my attempt to port this to masm
An external manifest file don't need link.exe
I haven't tested, how it works with dynamic loading dlls.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma comment(lib, "user32.lib")
void __cdecl WinMainCRTStartup(void)
{
TCHAR szTmp[260];
HMODULE hDll = LoadLibrary(TEXT("Comctl32.dll"));
GetModuleFileName(hDll, szTmp, sizeof(szTmp));
MessageBox(0, szTmp, TEXT("Info"), MB_OK);
ExitProcess(0);
}
UAsm example was build with commands:
uasm64.exe -c -win64 TestTaskDialog2MS.asm
link.exe TestTaskDialog2MS.obj -subsystem:windows -manifest:embed
Quote from: guga on April 17, 2025, 04:04:38 AMI did this:
With this test code:
include \masm32\include\masm32rt.inc
.data
hInstance DWORD 0
hDll DWORD 0
hTaskDialogIndirect DWORD 0
Sz_Comctl32 db 'COMCTL32.dll', 0
Sz_TaskDialogIndirect db "TaskDialogIndirect", 0
.code
start:
invoke InitCommonControls
; 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
; Exit process
invoke ExitProcess, 0
end start
I am getting this for "TaskDialogIndirect" using link from the masm32 SDK...
ERROR_PROC_NOT_FOUND (0000007F)
as shown in ollydbg
I tried with and without "invoke InitCommonControls" there is a manifest in the .rc file.
I had to dig into WinSxS for a version that was 32 bit,
and had that function.\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.4355_none_a865f0c28672571c\comctl32.dll
include \masm32\include\masm32rt.inc
.data
hInstance dd 0
hDll dd 0
hTaskDialogIndirect dd 0
Sz_Comctl32 db ".\COMCTL32.dll", 0
Sz_TaskDialogIndirect db "TaskDialogIndirect", 0
.CODE
start:
; Get module handle
invoke GetModuleHandle, 0
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
; Exit process
invoke ExitProcess, 0
end start
Then success it found the function, and it loaded.
No manifest. :smiley: While still using ml & link from the Masm32 SDK. That being said, I obviously did not test whether or not TaskDialogIndirect would actually create the TaskDialog, without a manifest. I am heading outside to do more chores. When I get back inside, I'll try to create a TaskDialog ... :azn:
I copied the .dll to my desktop in a folder where I have the test program. Attached is the second test, where it was a success in loading the function. (but obviously the .dll is not attached)
Quote from: TimoVJL on April 17, 2025, 04:13:29 AMAn external manifest file don't need link.exe
I haven't tested, how it works with dynamic loading dlls.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma comment(lib, "user32.lib")
void __cdecl WinMainCRTStartup(void)
{
TCHAR szTmp[260];
HMODULE hDll = LoadLibrary(TEXT("Comctl32.dll"));
GetModuleFileName(hDll, szTmp, sizeof(szTmp));
MessageBox(0, szTmp, TEXT("Info"), MB_OK);
ExitProcess(0);
}
UAsm example was build with commands:
uasm64.exe -c -win64 TestTaskDialog2MS.asm
link.exe TestTaskDialog2MS.obj -subsystem:windows -manifest:embed
Hi Timo. I now, but you didn´t get it. RosAsm won´t assemble any file, with an external manifest because it will try to find the address but Rosasm.exe itself does not uses manifest in it´s resource section and neither an external manifest for RosAsm itself from where it could bypass the older dll versions. In time i´ll try to update this and make it assemble files with and without manifest.
Although you can insert a manifest in the resources section of the file you arre trying to assemble with RosAsm, if the target dll points to an Api (non existent in older versions) that are being tried to load by RosAsm itself in order to it retrieve the address, then it won´t work. This taskdialog issue is good, so i can try fixing it in the future. I never had such problems before, because all Apis whose dlls uses uses manifests, where also existed on non-manifest (older versions) that was what rosasm uses to assemble.
At then end, the thread turned to be good for me to fix one more thing in RosAsm in the future.
Quote from: zedd151 on April 17, 2025, 04:20:09 AMQuote from: guga on April 17, 2025, 04:04:38 AMI did this:
With this test code:
include \masm32\include\masm32rt.inc
.data
hInstance DWORD 0
hDll DWORD 0
hTaskDialogIndirect DWORD 0
Sz_Comctl32 db 'COMCTL32.dll', 0
Sz_TaskDialogIndirect db "TaskDialogIndirect", 0
.code
start:
invoke InitCommonControls
; 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
; Exit process
invoke ExitProcess, 0
end start
I am getting this for "TaskDialogIndirect" using link from the masm32 SDK...
ERROR_PROC_NOT_FOUND (0000007F)
as shown in ollydbg
I tried with and without "invoke InitCommonControls" there is a manifest in the .rc file.
I had to dig into WinSxS for a verion that was 32 bit, and had that function.
\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.4355_none_a865f0c28672571c\comctl32.dll
include \masm32\include\masm32rt.inc
.data
hInstance dd 0
hDll dd 0
hTaskDialogIndirect dd 0
Sz_Comctl32 db ".\COMCTL32.dll", 0
Sz_TaskDialogIndirect db "TaskDialogIndirect", 0
.CODE
start:
; Get module handle
invoke GetModuleHandle, 0
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
; Exit process
invoke ExitProcess, 0
end start
Then success it found the function, and it loaded. No manifest. :smiley: While still using ml & link from the Masm32 SDK. That being said, I obviously did not test whether or not TaskDialogIndirect would actually create the TaskDialog, without a manifest. I am heading outside to do more chores. When I get back inside, I'll try to create a TaskDialog ... :azn:
I copied the .dll to my desktop in a folder where I have the test program.
Attached is the second test, where it was a success in loading the function. (but obviously the .dll is not attached)
Great work ! :thumbsup: :thumbsup: :thumbsup:
External manifest is just a xml-file with same name as exe and .manifest inserted to it's name.
So if you make an program named test.exe, then copy manifest template file to test.exe.manifest
Quote from: TimoVJL on April 17, 2025, 05:52:26 AMExternal manifest is just a xml-file with same name as exe and .manifest inserted to it's name.
So if you make an program named test.exe, then copy manifest template file to test.exe.manifest
You mean, if i create a RosAsm.exe.manifest, put it onto the same folder as the main RosAsm.exe, it will then assemble other files with newer versions of these dlls ? I´ll give a try later. Never did that before.
Quote from: TimoVJL on April 17, 2025, 05:52:26 AMExternal manifest is just a xml-file with same name as exe and .manifest inserted to it's name.
So if you make an program named test.exe, then copy manifest template file to test.exe.manifest
Great tip. Worked. It assembled the file. - Not working because i didn´t included the manifest file (neither external or internal), but, it is assembling. The problem with this manifest as a external file, is that it changes
(https://i.postimg.cc/3W0rz2r4/Clipboard-04-16-2025-01.png) (https://postimg.cc/3W0rz2r4)
the interface of RosAsm. It became a bit weird (although reveled some more issues that may requires fixes)
Every exe need manifest file, if they need newer 6.0 version of comctl32.dll
Rosasm.exe itself can use 6.0 version dll, if have manifest-file in same folder.
Worked. Now with the manifest embedded in the executable. Too much trouble for a simple thing. I´ll need to review those issues in RosAsm once i have more free time. I don´t like those manifest things, but, it indeed may be helpfull for others.
Quote from: guga on April 17, 2025, 06:19:29 AMWorked.
:thumbsup: :thumbsup:
(https://i.postimg.cc/zG47HnsS/untitled.png)
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.
Quote from: zedd151 on April 17, 2025, 06:27:52 AMQuote from: guga on April 17, 2025, 06:19:29 AMWorked.
:thumbsup: :thumbsup:
(https://i.postimg.cc/zG47HnsS/untitled.png)
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:
: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:
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.
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:
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.
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/application-manifests)
https://learn.microsoft.com/en-us/windows/win32/sbscs/assembly-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.
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) (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
With gugas original code from here (https://masm32.com/board/index.php?msg=138479) where it says "I did this" and with a couple of modifications (for ml compatibilty (marked):
(https://i.postimg.cc/76BhWNMp/untitled.png)
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
(https://i.postimg.cc/tCr0nMC0/untitled.png)
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:
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"
Quote from: sinsi on April 17, 2025, 09:18:28 AMQuote 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.
Excellent !
I knew i could be done without manifest, in masm as well. :thumbsup: :thumbsup: :thumbsup:
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:
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.
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)
(https://i.postimg.cc/J4JD1vNq/untitled.png)
A couple of more things related to the weird name of those directories. I found some info at:
Exploring WinSXS (https://auscitte.github.io/posts/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 (https://hashes.com/en/tools/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
Quote from: zedd151 on April 17, 2025, 09:53:16 AMHow about not using __UNICODE__=1 and write the macro in the source? :azn:
STRING MACRO data_label,quoted_text:VARARG ;; modifed from that in the masm32 SDK
WSTR data_label,quoted_text,0
ENDM
How about simply using WSTR instead of calling one macro that will call it anyway?
; Unicode strings
WSTR Sz_Radio1, "Lets do Item1", 0, 0
WSTR Sz_Radio2, "Or maybe 2", 0, 0
WSTR Sz_Radio3, "Super secret option", 0, 0
WSTR Sz_MainInstruction, "You're about to do something stupid.", 0, 0
WSTR Sz_Content, "Are you absolutely sure you want to continue with this really bad idea?", 0, 0
WSTR Sz_WindowTitle, "cTaskDialog Project", 0
Works the same as the modified STRING macro had in the posted code, without having to put the modified STRING macro directly into the souce code. :rolleyes:
I didn't think of that before I posted the code above in #74. :biggrin:
So did anyone even try my homebrew version of this, beyond just getting it to assemble and link?
Regarding what sinsi posted below, I could add code to allow for a callback to the caller to process input and what not. Could replicate even more of the Task Dialog functionality.
Otherwise I guess I'll just take my toys and go home ...
Quote from: zedd151 on April 17, 2025, 12:06:05 PMQuote from: zedd151 on April 17, 2025, 09:53:16 AMHow about not using __UNICODE__=1 and write the macro in the source? :azn:
STRING MACRO data_label,quoted_text:VARARG ;; modifed from that in the masm32 SDK
WSTR data_label,quoted_text,0
ENDM
How about simply using WSTR instead of calling one macro that will call it anyway?
; Unicode strings
WSTR Sz_Radio1, "Lets do Item1", 0, 0
WSTR Sz_Radio2, "Or maybe 2", 0, 0
WSTR Sz_Radio3, "Super secret option", 0, 0
WSTR Sz_MainInstruction, "You're about to do something stupid.", 0, 0
WSTR Sz_Content, "Are you absolutely sure you want to continue with this really bad idea?", 0, 0
WSTR Sz_WindowTitle, "cTaskDialog Project", 0
Works the same as the modified STRING macro had in the posted code, without having to put the modified STRING macro directly into the souce code. :rolleyes:
I didn't think of that before I posted the code above in #74. :biggrin:
A question about this macros.
WSTR Sz_Radio1, "Lets do Item1", 0, 0
Will it produce 2 zero null terminated string or 4 zero terminated string ?
Each ending 0 also counts as 2 characters on the unicode version or they are left over the macro and counts only 2 zeros anyway ?
Quote from: guga on April 17, 2025, 03:07:03 PMWSTR Sz_Radio1, "Lets do Item1", 0, 0
Will it produce 2 zero null terminated string or 4 zero terminated string ?
Each ending 0 also counts as 2 characters on the unicode version or they are left over the macro and counts only 2 zeros anyway ?
You'll end up with 2 too many zeros. Won't hurt anything but looks stupid.
:rolleyes:
Just remove the extra zeros.
They are obviously leftovers from when I was playing around with the ugly Unicode strings either that or I simply pasted too many. :tongue:
Who cares what it looks like. The string itself is what matters, all characters are present.
I was quickly working to get the example posted, it worked fine so I posted it. It is only test code, not production code. Get a grip and pardon my errors. Jeezus!
At least I did not omit the terminating zeros. :badgrin:
I was mainly testing my theory that no manifest was needed. I had proved that indeed it was not necessary, no matter who disagrees or what the MS docs might say.
Stop picking nits guys. In the end, an extra terminating zero or three will not crash the program after all.
Quote from: zedd151 on April 17, 2025, 03:30:59 PM:rolleyes:
Just remove the extra zeros.
They are obviously leftovers from when I was playing around with the ugly Unicode strings either that or I simply pasted too many. :tongue:
Who cares what it looks like. The string itself is what matters, all characters are present.
I was quickly working to get the example posted, it worked fine so I posted it. It is only test code, not production code. Get a grip and pardon my errors. Jeezus!
At least I did not omit the terminating zeros. :badgrin:
I was mainly testing my theory that no manifest was needed. I had proved that indeed it was not necessary, no matter who disagrees or what the MS docs might say.
Stop picking nits guys.
I wasn't complaining :azn: :azn: :azn: . Just asked to understand how the macros behave in masm. I´m reading what you guys code (specially when they have default masm macros set), to make easier for me when i'll give a try on the translator.
Quote from: guga on April 17, 2025, 03:43:25 PMI wasn't complaining :azn: :azn: :azn: . Just asked to understand how the macros behave in masm. I´m reading what you guys code (specially went they have default masm macros set), to make easier for me when i'll give a try on the translator.
It was just a mistake. No mystery. As I said a couple posts ago, I hardly ever have the need to use Unicode anything, at least not on purpose. So even using a Unicode producing macro is somewhat new to me, too. :smiley:
That manifest thing is quite easy with ml64.exe, rc.exe and link.exe
https://masm32.com/board/index.php?msg=138123 (https://masm32.com/board/index.php?msg=138123)
ml64.exe -c TestTaskDialog2MS.asm
link.exe TestTaskDialog2MS.obj -subsystem:windows -manifest:embed
Quote from: TimoVJL on April 17, 2025, 04:11:05 PMThat manifest thing is quite easy with ml64.exe, rc.exe and link.exe
https://masm32.com/board/index.php?msg=138123 (https://masm32.com/board/index.php?msg=138123)
ml64.exe -c TestTaskDialog2MS.asm
link.exe TestTaskDialog2MS.obj -subsystem:windows -manifest:embed
Hi Timo. It seems it is easy. There was no such thing when we started with RosAsm. When this thing showed up in (from windows XP as far i can remember), we didn´t payed too much attention on develop it further, and included something very very basics in RosAsm. Now, more then two decades later, i´ll need to update this thing.
Quote from: TimoVJL on April 17, 2025, 04:11:05 PMThat manifest thing is quite easy with ml64.exe, rc.exe and link.exe
https://masm32.com/board/index.php?msg=138123 (https://masm32.com/board/index.php?msg=138123)
ml64.exe -c TestTaskDialog2MS.asm
link.exe TestTaskDialog2MS.obj -subsystem:windows -manifest:embed
So far a manifest is not yet needed as shown in my posted examples. That being said, the TaskDialog test code so far is not implementing any callbacks. (The buttons aren't actually doing anything, etc.) it is simply displaying it.
I doubt that the callback code would need a manifest, but I cannot say for certain until an actual (working) TaskDialog is created, with all necessary callbacks being implemented. :smiley:
So guga, how is the next part of your TaskDialog coming along? (The callback procedures)
I'll be around if you need further assistance in making it masm compatible.
Quote from: zedd151 on April 17, 2025, 04:25:15 PMQuote from: TimoVJL on April 17, 2025, 04:11:05 PMThat manifest thing is quite easy with ml64.exe, rc.exe and link.exe
https://masm32.com/board/index.php?msg=138123 (https://masm32.com/board/index.php?msg=138123)
ml64.exe -c TestTaskDialog2MS.asm
link.exe TestTaskDialog2MS.obj -subsystem:windows -manifest:embed
So far a manifest is not yet needed as shown in my posted examples. That being said, the TaskDialog test code so far is not implementing any callbacks. (The buttons aren't actually doing anything, etc.) it is simply displaying it.
I doubt that the callback code would need a manifest, but I cannot say for certain until an actual (working) TaskDialog is created, with all necessary callbacks being implemented. :smiley:
So guga, how is the next part of your TaskDialog coming along? (The callback procedures)
I'll be around if you need further assistance in making it masm compatible.
The callbacks ? I didn´t implemented yet. I´ll give a try tomorrow after read the VB6 and russian forum. They have working examples.
But...most likely, as you said, the callbacks (actions) does not relies on a manifest file appended to it. I took a fast look on the disassembled code of this new comctl32, and despite the fact that it´s internal code is a mess, i didn´t found anything (yet) that suggests any relation between a manifest and the actions. This feature uses a lot of classes, btw, specially those from DirectUI, such as RegisterDUI70BehaviorFactory, and ActivateActCtx to handle the different used GUIDs. The others dlls it uses internally, seems to be the regular ones, such as EnableChildWindowDpiMessage, GetLastError etc.
(https://i.postimg.cc/Fd6xL9Tp/Clipboard-04-17-2025-01.png) (https://postimg.cc/Fd6xL9Tp)
Application manifests (https://learn.microsoft.com/en-us/windows/win32/SbsCs/application-manifests)
Application manifests are for OS loaders and are useful in many ways.
For example, COM user can use COM without registering COM component.
MS link.exe have supported manifest about 20 years.
EDIT: solution #5 use external manifest-file in development phase and add it to release exe with tool like in https://masm32.com/board/index.php?msg=138497 (https://masm32.com/board/index.php?msg=138497) or create similar tool.
Understanding Manifest Generation for C/C++ Programs PDF (http://estelleetchristophe.free.fr/02_informatique/00_documents/Manifestes%20Windows.pdf)