[LEGAL]
TaskbarProgress

[API]
OpenProcess
CloseHandle
GetCurrentProcessId
WriteProcessMemory
CLSIDFromString
CoCreateInstance
RtlMoveMemory
GUID

[INCLUDE]
Application
OSVersionDependent
UIntAddUInt

[DEFINE]
Public Enum TBPF_ProgressState
  TBPF_NoProgress = &H0
  TBPF_Indeterminate = &H1
  TBPF_Normal = &H2
  TBPF_Error = &H4
  TBPF_Paused = &H8
  End Enum

Private TaskbarProgress_hInst As Long

[CODE]
Private Sub TaskbarProgress_Init()
  Dim CLSID_TaskbarList As GUID
  Dim IID_ITaskbarList3 As GUID
  Dim hProcess As Long
  Dim vmtPtr As Long
  Dim vfPtr As Long

  hProcess = OpenProcess(&H38&, 0&, GetCurrentProcessId)
  If Not hProcess = 0& Then
    If CLSIDFromString(StrPtr("{56FDF344-FD6D-11d0-958A-006097C9A090}"), CLSID_TaskbarList) = 0& Then
      If CLSIDFromString(StrPtr("{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}"), IID_ITaskbarList3) = 0& Then
        If CoCreateInstance(CLSID_TaskbarList, 0&, &H17&, IID_ITaskbarList3, TaskbarProgress_hInst) = 0& Then
          If Not TaskbarProgress_hInst = 0& Then
            Call RtlMoveMemory(ByVal VarPtr(vmtPtr), ByVal TaskbarProgress_hInst, 4&)
            UIntAddUInt vmtPtr, 8&
            Call RtlMoveMemory(ByVal VarPtr(vfPtr), ByVal vmtPtr, 4&)
            Call TaskbarProgress_InjectJmp(hProcess, AddressOf TaskbarProgress_IURelease, vfPtr)
            UIntAddUInt vmtPtr, 28&
            Call RtlMoveMemory(ByVal VarPtr(vfPtr), ByVal vmtPtr, 4&)
            Call TaskbarProgress_InjectJmp(hProcess, AddressOf TaskbarProgress_ISetProgressValue, vfPtr)
            UIntAddUInt vmtPtr, 4&
            Call RtlMoveMemory(ByVal VarPtr(vfPtr), ByVal vmtPtr, 4&)
            Call TaskbarProgress_InjectJmp(hProcess, AddressOf TaskbarProgress_ISetProgressState, vfPtr)
            End If
          End If
        End If
      End If
    Call CloseHandle(hProcess)
    End If
  End Sub

Private Sub TaskbarProgress_Close()
  If Not TaskbarProgress_hInst = 0& Then
    Call TaskbarProgress_IURelease(TaskbarProgress_hInst)
    TaskbarProgress_hInst = 0&
    End If
  End Sub

Public Sub TaskbarProgress_SetProgressValue(ByVal hWnd As Long, ByVal Completed As Long, ByVal Total As Long)
  If Not TaskbarProgress_hInst = 0& Then
    Call TaskbarProgress_ISetProgressValue(TaskbarProgress_hInst, hWnd, CCur(Completed), CCur(Total))
    End If
  End Sub

Public Function TaskbarProgress_SetProgressState(ByVal hWnd As Long, ByVal tbpFlags As TBPF_ProgressState) As Long
  If Not TaskbarProgress_hInst = 0& Then
    TaskbarProgress_SetProgressState = TaskbarProgress_ISetProgressState(TaskbarProgress_hInst, hWnd, tbpFlags)
    End If
  End Function

Private Function TaskbarProgress_IURelease(ByVal This As Long) As Long
  Call IIf(True, True, False)
  End Function

Private Function TaskbarProgress_ISetProgressValue(ByVal This As Long, ByVal hWnd As Long, ByVal Completed As Currency, ByVal Total As Currency) As Long
  Call IIf(True, True, False)
  End Function

Private Function TaskbarProgress_ISetProgressState(ByVal This As Long, ByVal hWnd As Long, ByVal tbpFlags As TBPF_ProgressState) As Long
  Call IIf(True, True, False)
  End Function

Private Sub TaskbarProgress_InjectJmp(ByVal hProcess As Long, ByVal InjectedProcAddress As Long, ByVal JmpAbsoluteAddress As Long)
  Dim xLong1 As Long
  
  xLong1 = &HE9&
  Call WriteProcessMemory(hProcess, ByVal InjectedProcAddress, ByVal VarPtr(xLong1), 1&, 0&)
  UIntSubUInt JmpAbsoluteAddress, InjectedProcAddress
  UIntSubUInt JmpAbsoluteAddress, 5&
  UIntAddUInt InjectedProcAddress, 1&
  Call WriteProcessMemory(hProcess, ByVal InjectedProcAddress, ByVal VarPtr(JmpAbsoluteAddress), 4&, 0&)
  End Sub
