
 ; ============================================================
 ;  COMASM v1.0 (Win32Asm/COM - usage of ITaskbarList interface)
 ;
 ;  Author (if works :)    : Adam Blaszczyk, Poland (Hong Kong)
 ;  Contact:               : adasinhk@yahoo.com.hk
 ;                           pyro@alpha.net.pl
 ;  Home Page              : www.mykakee.com
 ;
 ; ============================================================
 ;
 ;  FOA: sorry for my bad english :)
 ;
 ;  Version of the program created for Iczelion's home page.
 ;
 ;  This little program shows how to use COM technology in
 ;  Win32Asm. When it's run it lets the user freely decide
 ;  about the presence of the program with the WS_EX_TOOLWINDOW
 ;  style on the taskbar. The main goal is to show the easiest
 ;  possible example instead of killing people with the details
 ;  about virtual tables, polymorphism, inheritance and using
 ;  nested macros etc., etc.
 ;
 ;  Requirements:
 ;   - Windows 98 (or Windows 95 + IE 4.0+)
 ;   - Windows 2000 (or Windows NT 4.0 + IE 4.0+)
 ;
 ;  Error handling is reduced to minimum :).
 ;
 ;  This program may be freely distributed as long as it's content
 ;  stays unchanged. Credits always welcomed :)
 ;
 ;  Credits: Iczelion, S.L.Hutchesson and yes, Microsoft :)
 ;
 ; ============================================================

.386
.MODEL FLAT,STDCALL
 OPTION CASEMAP :NONE

 OFS equ OFFSET

 ID_DLG          =   100
 ID_GROUP        =   1001
 ID_CHANGE       =   1002

 include \MASM32\INCLUDE\windows.inc

 include \MASM32\INCLUDE\kernel32.inc
 includelib \MASM32\LIB\kernel32.lib

 include \MASM32\INCLUDE\user32.inc
 includelib \MASM32\LIB\user32.lib

 include \MASM32\INCLUDE\ole32.inc
 includelib \MASM32\LIB\ole32.lib

 ; ============================================================
 ;  Declaration of VTable that includes the pointers to the
 ;  methods. Note that it always includes 3 methods of IUnknown
 ;  In fact, all the COM interfaces are built like this.
 ;  Warning: Always refer to Windows Platform SDK header files
 ;           to check for the sequence of the methods
 ;           the sequence is crucial !!! and don't rely on SDK
 ;           help file, but always on header files!!!
 ; ============================================================

 ITaskBarListVtbl STRUC
    ; These are pointers to IUnknown interface
   QueryInterface         dd ?
   AddRef                 dd ?
   Release                dd ?
    ; and these ones are for ITaskbarlist
   HrInit                 dd ?
   AddTab                 dd ?
   DeleteTab              dd ?
   ActivateTab            dd ?
   SetActiveAlt           dd ?
 ITaskBarListVtbl ENDS

  ; This is, in fact the interface :)
 ITaskBarList STRUC
   lpVtbl dd ?
 ITaskBarList ENDS

.data?
 hInstance dd ?

.data

 ; We need two GUIDs to communicate with the DLL in which the object
 ; is implemented - GUIDs may be found in header files
 ; and ... in the Registry (look for HKCR/CLSID/...)

 ; CLSID_TaskbarList '56FDF344-FD6D-11D0-958A-006097C9A090'
   CLSID_TaskbarList GUID <56FDF344h,0FD6Dh,11D0h,<95h,8Ah,0,60h,97h,0C9h,0A0h,90h>>
 ; IID_ITaskbarList  '56FDF342-FD6D-11D0-958A-006097C9A090'
   IID_ITaskbarList  GUID <56fdf342h,0FD6Dh,11D0h,<95h,8Ah,0,60h,97h,0C9h,0A0h,90h>>

 visible  dd FALSE
 TxShow   db 'Show   ',NULL ; length=8 bytes
 TxHide   db 'Hide   ',NULL ; length=8 bytes

.code

 ; ============================================================
 ;  Macro takes care of calling the proper method; it takes
 ;  a pointer to the instance of the object created by
 ;  CoCreateInstance;  this pointer is one of the pointers
 ;  inside the DLL library loaded to memory; it refers to
 ;  the second pointer and this is a pointer to table of
 ;  pointers to methods [VTable]; These methods can be called
 ;  by a lot of instances of the object, so they need 'this'
 ;  parameter, which in fact is just an offset to our object
 ; ============================================================
 COMETHOD MACRO ppv,metoda
          mov  eax,ppv.lpVtbl   ; pointer to variable in DLL
          mov  eax,[eax]        ; pointer to VTable [in DLL]
          mov  eax,[eax.metoda] ; pointer to a given method
          push ppv              ; we must tell the method
                                ; who's calling [instance]
                                ; it is known as 'this' param.
          call eax              ; we call the method
 ENDM

 ; ============================================================
 ;  This procedure shows/hides program on the taskbar
 ;   IN: hWin = window handle
 ;       bVisible = TRUE (show) or FALSE (hide)
 ;   OUT: void
 ; ============================================================
 ShowOnTaskbar proc hWin, bVisible:DWORD
     LOCAL  ShellTaskBar:ITaskBarList

      invoke CoInitialize,NULL

      invoke CoCreateInstance,OFS CLSID_TaskbarList,NULL,\
             CLSCTX_INPROC_SERVER,OFS IID_ITaskbarList,ADDR ShellTaskBar

      .if eax==S_OK

          COMETHOD ShellTaskBar,ITaskBarListVtbl.HrInit
          .if eax==NOERROR

              .if bVisible==TRUE
                  push hWin
                  COMETHOD ShellTaskBar,ITaskBarListVtbl.AddTab

                  push hWin
                  COMETHOD ShellTaskBar,ITaskBarListVtbl.ActivateTab

              .else
                  push hWin
                  COMETHOD ShellTaskBar,ITaskBarListVtbl.DeleteTab
              .endif

          .endif

          COMETHOD ShellTaskBar,ITaskBarListVtbl.Release
      .endif

      invoke CoUninitialize

      ret
 ShowOnTaskbar  endp

 ; ============================================================
 ;  Dialog's procedure
 ; ============================================================
 DialogProc proc hDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
   pushad

   .if uMsg==WM_INITDIALOG
       invoke SetDlgItemText,hDlg,ID_CHANGE,OFS TxShow

   .elseif  uMsg==WM_CLOSE
       invoke ShowOnTaskbar,hDlg,FALSE
       invoke EndDialog,hDlg,0

   .elseif  uMsg==WM_COMMAND ; BN_CLICKED=0

      .if wParam==IDOK
          invoke SendMessage,hDlg,WM_CLOSE,0,0

      .elseif wParam==ID_CHANGE

          inc   visible        ; \ visible/invisible
          and   visible,1      ; /

          mov   eax,visible    ; eax=0 or 1
          shl   eax,3          ; length is always 8 bytes
          add   eax,OFS TxShow ; eax=offset to the 1-st text

          invoke SetDlgItemText,hDlg,ID_CHANGE,eax

          invoke ShowOnTaskbar,hDlg,visible

      .endif

   .endif

   popad
   xor eax,eax
   ret

 DialogProc endp

 ; ============================================================
 ;  Everything starts and ends here :)
 ; ============================================================
 Start:
   invoke DialogBoxParam,hInstance,ID_DLG,0,OFS DialogProc,0
   invoke ExitProcess,0

END Start
