Dynamic TaskDialog call

posted Aug 17, 2012, 1:44 PM by Unknown user   [ updated Aug 17, 2012, 1:55 PM ]
Below is an example of backward compatible programme on flat assembler, which shows Message Box on 2000/XP and TaskDialog on Vista/7. It utilizes the following algorithm:
  1. Determine Windows version
  2. If version < 6 then skip to 5
  3. Load COMCTL32.DLL
  4. Retrieve TaskDialog proc address and save its handle
  5. Proceed further
The algorithm of message displaying procedure:
  1. If TaskDialog handle = NULL skip to 4
  2. Display Task Dialogue
  3. Skip to 5
  4. Display Message Box
  5. Return
Note: the manifest section in resource data is mandatory, otherwise the old Common Control library will be used and no Task Dialogue address would be received


I tried to make the code simple:

dynTaskDlg.asm

;Example of a dynamic task dialog

format PE GUI 4.0
entry start
include 'win32w.inc' ; WideCharacter must be used for TaskDialog to work correctly
include 'encoding\win1251.inc'

; Task Dialog Stuff
TD_WARNING_ICON = -1
TD_ERROR_ICON = -2
TD_INFORMATION_ICON = -3
TD_SHIELD_ICON = -4

TDCBF_OK_BUTTON = 1
TDCBF_YES_BUTTON = 2
TDCBF_NO_BUTTON = 4
TDCBF_CANCEL_BUTTON = 8
TDCBF_RETRY_BUTTON = $10
TDCBF_CLOSE_BUTTON = $20


section '.text' code readable executable
start:
; invoke InitCommonControls

;get windows version
invoke GetVersion
cmp al,06h ;Won't even try to load library on < Windows Vista
jb notvista
;vista+
invoke LoadLibrary,_comctl32 ;Loading COMCTL32.DLL. If already included in library section,
;one can use GetModuleHandle instead of LoadLibrary
cmp eax,0
je notvista ;COMCTL32.DLL not in memory

invoke GetProcAddress,eax,_taskDlg ;Trying to get and address of TaskDialog API
cmp eax,0 ;NULL - no taskdialog for today.
je notvista
mov [TaskDialog],eax ;if eax != 0, saving address of the TaskDialog API


  notvista:
stdcall TaskBox,HWND_DESKTOP,_randomStuff,_hello,_mainInstr  

invoke ExitProcess,0


; hWnd      - parent window handle
; lpszMsg   - message body,
; lpszTitle - title
; lpszInstr - main instruction, used only in TaskDialog.

; return:
; eax - ID of the button pressed

proc TaskBox hWnd:DWORD,lpszMsg:DWORD,lpszWndTitle:DWORD,lpszInstr:DWORD
  local dwResult:DWORD
cmp [TaskDialog],0 ;if no TaskDialog handle
jz .xp ;proceed to MessageBox

;http://msdn.microsoft.com/en-us/library/windows/desktop/bb760540(v=vs.85).aspx
;HRESULT TaskDialog(
;  _In_   HWND hWndParent,
;  _In_   HINSTANCE hInstance,
;  _In_   PCWSTR pszWindowTitle,
;  _In_   PCWSTR pszMainInstruction,
;  _In_   PCWSTR pszContent,
;  _In_   TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons,
;  _In_   PCWSTR pszIcon,
;  _Out_  int *pnButton
;);
lea eax,[dwResult] ;button information will be stored in dwResult
;pszIcon must contain icon id in Lo-WORD, otherwise it will be treated as a string resource identifier
;hence "and 0FFFFh"
invoke TaskDialog,[hWnd],NULL,[lpszWndTitle],[lpszInstr],[lpszMsg],TDCBF_OK_BUTTON,TD_INFORMATION_ICON and 0FFFFh,eax
mov eax,[dwResult]
jmp .finish
  .xp:
invoke MessageBox,[hWnd],[lpszMsg],[lpszWndTitle],MB_OK+MB_ICONINFORMATION

  .finish:
ret
endp

section '.data' data readable writeable

  _hello TCHAR 'Hello World!',0
  _mainInstr TCHAR 'Every day I''m shufflin''',0
  _randomStuff TCHAR 'Humpty Dumpty sat on a wall, Humpty Dumpty had a great fall',13,10,\
     'И вся королевская конница, и вся королевская рать не может Шалтая Болтая собрать',0

  _comctl32 TCHAR 'COMCTL32.DLL',0
  _taskDlg db 'TaskDialog',0

  winver dd ? ; windows version
  TaskDialog dd ? ; API address will be stored here

section '.idata' import data readable
  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL'

  import kernel,\
      ExitProcess,'ExitProcess',\
      GetProcAddress,'GetProcAddress',\
      GetVersion,'GetVersion',\
      LoadLibrary,'LoadLibraryW'

  import user,\
      MessageBox,'MessageBoxW'            


  ;the comctl32.dll doesn't have to be included, since it would be loaded dynamically

section '.rsrc' resource data readable
  directory RT_MANIFEST,manifest 
  resource manifest,\ 
1,LANG_NEUTRAL,man 
  resdata man 
db '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',13,10 
db '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">',13,10 
db '<assemblyIdentity name="x.x.x" processorArchitecture="x86" version="5.1.0.0" type="win32"/> ',13,10 
db '<description>no</description>',13,10 
db '<dependency>',13,10 
db '<dependentAssembly>',13,10 
db '<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*" />',13,10 
db '</dependentAssembly>',13,10 
db '</dependency>',13,10 
db '</assembly>',13,10 
  endres 

Comments