flat assembler
Message board for the users of flat assembler.

Index > Windows > [solved] COM need help

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
Overclick



Joined: 11 Jul 2020
Posts: 670
Location: Ukraine
Overclick 13 Aug 2020, 18:41
Hi
Please help me to make it working
Code:
.data
        struc GUID def
         {
           match d1-d2-d3-d4-d5, def
            \{
              .Data1 dd 0x\#d1
              .Data2 dw 0x\#d2
              .Data3 dw 0x\#d3
              .Data4 db 0x\#d4 shr 8,0x\#d4 and 0FFh
              .Data5 db 0x\#d5 shr 40,0x\#d5 shr 32 and 0FFh,0x\#d5 shr 24 and 0FFh,0x\#d5 shr 16 and 0FFh,0x\#d5 shr 8 and 0FFh,0x\#d5 and 0FFh
            \}
         }
        interface               IMMDeviceEnumerator,\
                                        GetDefaultAudioEndpoint
        interface               IMMDevice,\
                                        Activate,\
                                        IAudioMeterInformation,\
                                        GetPeakValue
                                                
        CLASS_MMDeviceEnumerator        GUID BCDE0395-E52F-467C-8E3D-C4579291692E
        IID_IMMDeviceEnumerator         GUID A95664D2-9614-4F35-A746-DE8DB63617E6
        IAudioMeterInformation          GUID C02216F6-8C67-4B5B-9D00-D008E73E0064
                                        dq 0
        pMeterInfo              dq ?
        peak                    dd ?
        CLSCTX_ALL = 0x00000007
        CLSCTX_INPROC_SERVER = 0x1
        eConsole = 0
        eRender = 0
                
        pEnumerator             IMMDeviceEnumerator
        pDevice                 IMMDevice
.idata
        import                  ole32,\ 
                                        CoInitialize,'CoInitialize',\ 
                                        CoUninitialize,'CoUninitialize',\ 
                                        CoCreateInstance,'CoCreateInstance'
.code
        invoke                  CoInitialize,0
        invoke                  CoCreateInstance,CLASS_MMDeviceEnumerator,0,\
                                        CLSCTX_INPROC_SERVER,IID_IMMDeviceEnumerator,\
                                        pEnumerator
        mov                     rbx,[pEnumerator]
        comcall                 rbx,IMMDeviceEnumerator,GetDefaultAudioEndpoint,eRender,eConsole,pDevice
        mov                     rbx,[pDevice]
        ShowERROR ;it says rbx is empty
        comcall                 rbx,IMMDevice,Activate,IAudioMeterInformation,CLSCTX_ALL,0,pMeterInfo                                                   
        ;will be in timer later:
        mov                     rbx,[pMeterInfo]
        comcall                 rbx,IMMDevice,GetPeakValue,peak    
Post 13 Aug 2020, 18:41
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20517
Location: In your JS exploiting you and your system
revolution 13 Aug 2020, 22:35
Code:
.data
processed: .data
error: illegal instruction.    
We don't know what you have done.
Post 13 Aug 2020, 22:35
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 670
Location: Ukraine
Overclick 14 Aug 2020, 06:23
Do you want to see full header code to understand what I've done? This code demonstrate what is done with COM interfaces. I want to know how to call them correctly.
Code:
flat assembler  version 1.73.24  (1048576 kilobytes memory)
4 passes, 0.8 seconds, 62464 bytes.    
Post 14 Aug 2020, 06:23
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20517
Location: In your JS exploiting you and your system
revolution 14 Aug 2020, 06:30
See the USECOM.ASM demo included with the fasm download for an example of how to use the standard fasm macros. But you maybe inadvertently made some problems with your own macros. We don't know what you have done so it is something to watch out for.

That is why I ask for minimal code to compile, then all those other things can be eliminated. Try stripping out all your added macros and see if it fixes the problem. Or try pasting just your comcall part into this example below.
Code:
; Component Object Model usage demonstration

format PE GUI 4.0
entry start

include 'win32a.inc'

struc GUID def
 {
   match d1-d2-d3-d4-d5, def
    \{
      .Data1 dd 0x\#d1
      .Data2 dw 0x\#d2
      .Data3 dw 0x\#d3
      .Data4 db 0x\#d4 shr 8,0x\#d4 and 0FFh
      .Data5 db 0x\#d5 shr 40,0x\#d5 shr 32 and 0FFh,0x\#d5 shr 24 and 0FFh,0x\#d5 shr 16 and 0FFh,0x\#d5 shr 8 and 0FFh,0x\#d5 and 0FFh
    \}
 }

interface ITaskBarList,\
           QueryInterface,\
           AddRef,\
           Release,\
           HrInit,\
           AddTab,\
           DeleteTab,\
           ActivateTab,\
           SetActiveAlt

CLSCTX_INPROC_SERVER        = 0x1
CLSCTX_INPROC_HANDLER       = 0x2
CLSCTX_LOCAL_SERVER         = 0x4
CLSCTX_INPROC_SERVER16      = 0x8
CLSCTX_REMOTE_SERVER        = 0x10
CLSCTX_INPROC_HANDLER16     = 0x20
CLSCTX_INPROC_SERVERX86     = 0x40
CLSCTX_INPROC_HANDLERX86    = 0x80
CLSCTX_ESERVER_HANDLER      = 0x100
CLSCTX_NO_CODE_DOWNLOAD     = 0x400
CLSCTX_NO_CUSTOM_MARSHAL    = 0x1000
CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000
CLSCTX_NO_FAILURE_LOG       = 0x4000
CLSCTX_DISABLE_AAA          = 0x8000
CLSCTX_ENABLE_AAA           = 0x10000
CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000

ID_EXIT = IDCANCEL
ID_SHOW = 100
ID_HIDE = 101

IDD_COMDEMO = 1

section '.text' code readable executable

 start:

        invoke  CoInitialize,NULL
        invoke  CoCreateInstance,CLSID_TaskbarList,NULL,CLSCTX_INPROC_SERVER,IID_ITaskbarList,ShellTaskBar

        invoke  GetModuleHandle,0
        invoke  DialogBoxParam,eax,IDD_COMDEMO,HWND_DESKTOP,COMDemo,0

        cominvk ShellTaskBar,Release

        invoke  ExitProcess,0

proc COMDemo hwnd,msg,wparam,lparam
        push    ebx esi edi
        cmp     [msg],WM_INITDIALOG
        je      .wminitdialog
        cmp     [msg],WM_COMMAND
        je      .wmcommand
        cmp     [msg],WM_CLOSE
        je      .wmclose
        xor     eax,eax
        jmp     .finish
  .wminitdialog:
        jmp     .processed
  .wmcommand:
        cmp     [wparam],BN_CLICKED shl 16 + ID_EXIT
        je      .wmclose
        cmp     [wparam],BN_CLICKED shl 16 + ID_SHOW
        je      .show
        cmp     [wparam],BN_CLICKED shl 16 + ID_HIDE
        jne     .processed
  .hide:
        cominvk ShellTaskBar,HrInit
        cominvk ShellTaskBar,DeleteTab,[hwnd]
        jmp     .processed
  .show:
        mov     ebx,[ShellTaskBar]
        comcall ebx,ITaskBarList,HrInit
        comcall ebx,ITaskBarList,AddTab,[hwnd]
        comcall ebx,ITaskBarList,ActivateTab,[hwnd]
        jmp     .processed
  .wmclose:
        invoke  EndDialog,[hwnd],0
  .processed:
        mov     eax,1
  .finish:
        pop     edi esi ebx
        ret
endp

section '.data' data readable writeable

 CLSID_TaskbarList GUID 56FDF344-FD6D-11D0-958A-006097C9A090
 IID_ITaskbarList GUID 56FDF342-FD6D-11D0-958A-006097C9A090

 ShellTaskBar ITaskBarList

section '.idata' import data readable

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL',\
          ole,'OLE32.DLL'

  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         ExitProcess,'ExitProcess'

  import user,\
         DialogBoxParam,'DialogBoxParamA',\
         EndDialog,'EndDialog'

  import ole,\
         CoInitialize,'CoInitialize',\
         CoCreateInstance,'CoCreateInstance'

section '.rsrc' resource data readable

  directory RT_DIALOG,dialogs

  resource dialogs,\
           IDD_COMDEMO,LANG_ENGLISH+SUBLANG_DEFAULT,comdemo

  dialog comdemo,'Taskbar item control',70,70,170,24,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME
    dialogitem 'BUTTON','Show',ID_SHOW,4,4,45,15,WS_VISIBLE+WS_TABSTOP
    dialogitem 'BUTTON','Hide',ID_HIDE,54,4,45,15,WS_VISIBLE+WS_TABSTOP
    dialogitem 'BUTTON','Exit',ID_EXIT,120,4,45,15,WS_VISIBLE+WS_TABSTOP
  enddialog    
Post 14 Aug 2020, 06:30
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 670
Location: Ukraine
Overclick 14 Aug 2020, 07:12
You just don't like my multisection solution, don't you? ))
Code:
format PE64 GUI 5.0
include 'WIN64a.INC'
entry start
struc GUID def
 {
   match d1-d2-d3-d4-d5, def
    \{
      .Data1 dd 0x\#d1
      .Data2 dw 0x\#d2
      .Data3 dw 0x\#d3
      .Data4 db 0x\#d4 shr 8,0x\#d4 and 0FFh
      .Data5 db 0x\#d5 shr 40,0x\#d5 shr 32 and 0FFh,0x\#d5 shr 24 and 0FFh,0x\#d5 shr 16 and 0FFh,0x\#d5 shr 8 and 0FFh,0x\#d5 and 0FFh
    \}
 }
interface               IMMDeviceEnumerator,\
                                GetDefaultAudioEndpoint,\
                                Release
interface               IMMDevice,\
                                Activate,\
                                IAudioMeterInformation,\
                                GetPeakValue,\
                                Release

section '.idata' import data readable writeable
        library kernel32,'KERNEL32.DLL',\
                ole32,'ole32.dll'
        import  kernel32,\
                ExitProcess,'ExitProcess'
        import  ole32,\
                CoInitialize,'CoInitialize',\
                CoCreateInstance,'CoCreateInstance',\
                CoUninitialize,'CoUninitialize'

section '.data' data readable writeable 
        CLASS_MMDeviceEnumerator        GUID BCDE0395-E52F-467C-8E3D-C4579291692E
        IID_IMMDeviceEnumerator         GUID A95664D2-9614-4F35-A746-DE8DB63617E6
        IAudioMeterInformation          GUID C02216F6-8C67-4B5B-9D00-D008E73E0064
                        dq 0
        pMeterInfo      dq ?
        peak            dd ?
        
        CLSCTX_ALL = 0x00000007
        CLSCTX_INPROC_SERVER = 0x1
        eConsole = 0
        eRender = 0
        
        pEnumerator     IMMDeviceEnumerator
        pDevice         IMMDevice

section '.text' code readable executable
start:
        sub             rsp,8
        invoke          CoInitialize,0
        invoke          CoCreateInstance,CLASS_MMDeviceEnumerator,0,\
                                        CLSCTX_INPROC_SERVER,IID_IMMDeviceEnumerator,\
                                        pEnumerator
        mov             rbx,[pEnumerator]
        comcall         rbx,IMMDeviceEnumerator,GetDefaultAudioEndpoint,eRender,eConsole,pDevice
        mov             rbx,[pDevice]
        comcall         rbx,IMMDevice,Activate,IAudioMeterInformation,CLSCTX_ALL,0,pMeterInfo   

        mov             rbx,[pMeterInfo]
        comcall         rbx,IMMDevice,GetPeakValue,peak
        
        cominvk         pDevice,Release
        cominvk         pEnumerator,Release
        invoke          CoUninitialize
        invoke          ExitProcess,0    
Post 14 Aug 2020, 07:12
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20517
Location: In your JS exploiting you and your system
revolution 14 Aug 2020, 07:19
So does that work for you? Is there some problem? Please elaborate.

BTW: I don't know what your "multisection solution" is? Was that the cause of your problem?

We aren't mind readers, so we don't know what you are doing unless you tell us.
Post 14 Aug 2020, 07:19
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 670
Location: Ukraine
Overclick 14 Aug 2020, 07:26
This thread created as I did not get it work. I never used COM before. I don't know how to use it proper. If you understand COM you will see some simple mistakes on my code. That what I asking for.
Post 14 Aug 2020, 07:26
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20517
Location: In your JS exploiting you and your system
revolution 14 Aug 2020, 07:37
All calls the the OS API functions return status codes in RAX/EAX. I think it is good practice to check the return status is a success, or show the error code if it fails. This can help to diagnose any execution problems.

For example we don't even know if the call to 'CoCreateInstance' succeeds or fails. If it fails then everything afterwards can't be tested properly.
Post 14 Aug 2020, 07:37
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 670
Location: Ukraine
Overclick 14 Aug 2020, 07:43
As I marked in first message
Code:
comcall                 rbx,IMMDeviceEnumerator,GetDefaultAudioEndpoint,eRender,eConsole,pDevice    

fails with no pDevice creation.
There is no system error messages


Description:
Filesize: 37.66 KB
Viewed: 14304 Time(s)

Capture.PNG


Post 14 Aug 2020, 07:43
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20517
Location: In your JS exploiting you and your system
revolution 14 Aug 2020, 07:53
The error code in RAX is 0x80004003.
Post 14 Aug 2020, 07:53
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1878
Roman 14 Aug 2020, 07:59
I not remember, but check:
invoke CoCreateInstance,CLASS_MMDeviceEnumerator,0,\
CLSCTX_INPROC_SERVER,IID_IMMDeviceEnumerator,\
pEnumerator

In 64 bit CLSCTX_INPROC_SERVER as push qword CLSCTX_INPROC_SERVER !
You need push dword CLSCTX_INPROC_SERVER

invoke CoCreateInstance,CLASS_MMDeviceEnumerator,0,\
dword CLSCTX_INPROC_SERVER,IID_IMMDeviceEnumerator,\
pEnumerator
Post 14 Aug 2020, 07:59
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1878
Roman 14 Aug 2020, 08:01
But i do:
Code:
invoke  CoInitializeEx, NULL, COINIT_MULTITHREADED

invoke CoCreateInstance,CLASS_MMDeviceEnumerator,0,\
CLSCTX_INPROC_SERVER,IID_IMMDeviceEnumerator,pEnumerator
    

And do test to NULL:
Code:
mov             rbx,[pEnumerator]
;this might be macros
test rbx,rbx
jnz ok
invoke MessageBox,0,'pEnumerator is Null ! ',0,0
jmp ExitToWindow
ok:
;------    


Last edited by Roman on 14 Aug 2020, 08:07; edited 3 times in total
Post 14 Aug 2020, 08:01
View user's profile Send private message Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 670
Location: Ukraine
Overclick 14 Aug 2020, 08:02
Got this error code -- E_POINTER
Description:
Parameter ppDevice is NULL.

Nothing new to me.
Post 14 Aug 2020, 08:02
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20517
Location: In your JS exploiting you and your system
revolution 14 Aug 2020, 08:04
Do the calls to CoInitialize and CoCreateInstance succeed? You don't have code to check that.
Post 14 Aug 2020, 08:04
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 670
Location: Ukraine
Overclick 14 Aug 2020, 08:08
pEnumerator is not empty, it is ok. RAX is 0

I think problem is how I declared interfaces or how I use comcall. Are you sure it is correct?

Roman, pDevice still NULL, pEnumerator ok
Post 14 Aug 2020, 08:08
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20517
Location: In your JS exploiting you and your system
revolution 14 Aug 2020, 08:41
I found the best way to ensure the correct order of names for the interface is to compare against the MS API header files. Often C compilers will have those header files as part of their install.
Post 14 Aug 2020, 08:41
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1878
Roman 14 Aug 2020, 08:43
I do this:
Code:
comcall [pEnumerator],IMMDeviceEnumerator,GetDefaultAudioEndpoint,dword 0,dword 0 ,pDevice
    

And get pDevice = NULL !
Post 14 Aug 2020, 08:43
View user's profile Send private message Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 817
Location: Russian Federation, Sochi
ProMiNick 14 Aug 2020, 08:59
this is not COM interfaces:
Code:
interface               IMMDeviceEnumerator,\
                                GetDefaultAudioEndpoint,\
                                Release
interface               IMMDevice,\
                                Activate,\
                                IAudioMeterInformation,\
                                GetPeakValue,\
                                Release    

What 3 methods should be first within any COM interface
Code:
interface IAnyInterface,\
           QueryInterface,\
           AddRef,\
           Release,\
           ...    

Hope it helps (and thours interfaces directly descendants of IUnknown? or some other interfaces? it is matter too: every ancestor method will precede interface own methods).
Post 14 Aug 2020, 08:59
View user's profile Send private message Send e-mail Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 670
Location: Ukraine
Overclick 14 Aug 2020, 09:05
I just trying to translate minimal code from c++ example:
Code:
// Peakmeter.cpp -- WinMain and dialog box functions

#include <windows.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include "resource.h"

static BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
static void DrawPeakMeter(HWND, float);

// Timer ID and period (in milliseconds)
#define ID_TIMER  1
#define TIMER_PERIOD  125

#define EXIT_ON_ERROR(hr)  \
              if (FAILED(hr)) { goto Exit; }
#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

//-----------------------------------------------------------
// WinMain -- Opens a dialog box that contains a peak meter.
//   The peak meter displays the peak sample value that plays
//   through the default rendering device.
//-----------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine,
                     int nCmdShow)
{
    HRESULT hr;
    IMMDeviceEnumerator *pEnumerator = NULL;
    IMMDevice *pDevice = NULL;
    IAudioMeterInformation *pMeterInfo = NULL;

    if (hPrevInstance)
    {
        return 0;
    }

    CoInitialize(NULL);

    // Get enumerator for audio endpoint devices.
    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
                          NULL, CLSCTX_INPROC_SERVER,
                          __uuidof(IMMDeviceEnumerator),
                          (void**)&pEnumerator);
    EXIT_ON_ERROR(hr)

    // Get peak meter for default audio-rendering device.
    hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
    EXIT_ON_ERROR(hr)

    hr = pDevice->Activate(__uuidof(IAudioMeterInformation),
                           CLSCTX_ALL, NULL, (void**)&pMeterInfo);
    EXIT_ON_ERROR(hr)

    DialogBoxParam(hInstance, L"PEAKMETER", NULL, (DLGPROC)DlgProc, (LPARAM)pMeterInfo);

Exit:
    if (FAILED(hr))
    {
        MessageBox(NULL, TEXT("This program requires Windows Vista."),
                   TEXT("Error termination"), MB_OK);
    }
    SAFE_RELEASE(pEnumerator)
    SAFE_RELEASE(pDevice)
    SAFE_RELEASE(pMeterInfo)
    CoUninitialize();
    return 0;
}

//-----------------------------------------------------------
// DlgProc -- Dialog box procedure
//-----------------------------------------------------------

BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    static IAudioMeterInformation *pMeterInfo = NULL;
    static HWND hPeakMeter = NULL;
    static float peak = 0;
    HRESULT hr;

    switch (message)
    {
    case WM_INITDIALOG:
        pMeterInfo = (IAudioMeterInformation*)lParam;
        SetTimer(hDlg, ID_TIMER, TIMER_PERIOD, NULL);
        hPeakMeter = GetDlgItem(hDlg, IDC_PEAK_METER);
        return TRUE;

    case WM_COMMAND:
        switch ((int)LOWORD(wParam))
        {
        case IDCANCEL:
            KillTimer(hDlg, ID_TIMER);
            EndDialog(hDlg, TRUE);
            return TRUE;
        }
        break;

    case WM_TIMER:
        switch ((int)wParam)
        {
        case ID_TIMER:
            // Update the peak meter in the dialog box.
            hr = pMeterInfo->GetPeakValue(&peak);
            if (FAILED(hr))
            {
                MessageBox(hDlg, TEXT("The program will exit."),
                           TEXT("Fatal error"), MB_OK);
                KillTimer(hDlg, ID_TIMER);
                EndDialog(hDlg, TRUE);
                return TRUE;
            }
            DrawPeakMeter(hPeakMeter, peak);
            return TRUE;
        }
        break;

    case WM_PAINT:
        // Redraw the peak meter in the dialog box.
        ValidateRect(hPeakMeter, NULL);
        DrawPeakMeter(hPeakMeter, peak);
        break;
    }
    return FALSE;
}

//-----------------------------------------------------------
// DrawPeakMeter -- Draws the peak meter in the dialog box.
//-----------------------------------------------------------

void DrawPeakMeter(HWND hPeakMeter, float peak)
{
    HDC hdc;
    RECT rect;

    GetClientRect(hPeakMeter, &rect);
    hdc = GetDC(hPeakMeter);
    FillRect(hdc, &rect, (HBRUSH)(COLOR_3DSHADOW+1));
    rect.left++;
    rect.top++;
    rect.right = rect.left +
                 max(0, (LONG)(peak*(rect.right-rect.left)-1.5));
    rect.bottom--;
    FillRect(hdc, &rect, (HBRUSH)(COLOR_3DHIGHLIGHT+1));
    ReleaseDC(hPeakMeter, hdc);
}    
Post 14 Aug 2020, 09:05
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1878
Roman 14 Aug 2020, 09:12
interface IMMDeviceEnumerator,\
QueryInterface,\
AddRef,\
Release,\
EnumAudioEndpoints,\
GetDefaultAudioEndpoint

But i read GetDefaultAudioEndpoint for Windows Vista
Post 14 Aug 2020, 09:12
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.