Jump to content

[Release] Gho$t - Window Hider App Coded In C++!


Steve8x

Recommended Posts

Ghost.png

Hey, I made this program for myself, but I thought other people might think its useful as well so I thought I'd post it and share it...

Its called Gho$t because it makes windows disappear! well not forever! you can bring them back at anytime...

Features:

*hides up to 32 windows(not that youll ever need that many but I just like to make it high)

*Start up with windows option - makes it start when the computer starts, you'll likely want the next option with it

*Start hidden - when it starts when the computer starts the window wont show up it will be hidden to start with

*Encrypted Password Protect - If the secret hotkey isn't enough just pick a password and enable it, it will encrypt the password using a basic encryption method and when you unhide the window you will need to enter the password to get to the main GUI

You can either type in all or part of a window name, and it will enumerate all windows and hide the window if found... If it has been hidden by the program it adds the window's title and handle, into an array for storage... as you can see in the window title between the [] it shows you how many windows the program has hidden... in the picture above there was two windows hidden when I took it... on the main GUI pressing enter while focus is on the edit box is the same as pressing Ok!

To unhide a window that you've hidden either type in all or part of the window name, and click undo(or press tab) or you can clear the edit box and click undo/press tab and it will unhide the windows you've hidden in the order you've hidden them in reversed... (in case you forget some titles)

In the options menu you can make it start up with windows, I use that option + start hidden, so when my computer starts its window is hidden, and can only appear by pressing the secret hotkey CTRL + ALT + G

to set password protection , from the options menu, type a password in the box, and then tick the "Password Protection" checkbox. You will see the encrypted form of the password in the box which is now locked...

next time you unhide the window with the hotkey, you'll see the password window, pressing enter while the edit box is in focus is the same as pressing OK! It won't let you get to the main GUI unless the password is correct, useful just for extra security in case someone might figure out the hotkey ctrl + alt + g they still wont be able to figure out what the program actually does...

The password typed in is encrypted the same as your saved password, and compared, only if they are the same will it go to the next screen!

Yeah its a weak encryption and its easy to bypass even without the password, by knowing the registry key where program data is stored, but its likely to be good enough for this program...

although I would like any suggestions for a better encryption method, and maybe I was thinking instead of storing the password + program data in the registry, to do it in a more secret location, but then again it wouldn't matter anyone with a debugger would be able to find out quickly... So It all depends on how smart the people using your computer are whether this simple password protection will be strong enough or not... for me it is...

I find it very annoying when I'm running a game server or something and I don't want the window to be closed and someone who uses my computer will just close the window on me not caring about my windows... So I just hide them when I'm away and they'll never be closed on me! :)

Lets see how fast someone can decrypt this password ;)

:: GhostOptions.png ::

v1.1 - there was a small bug that allowed the last window hidden to be unhidden without entering a password simply by pressing tab at the password screen! I fixed it now... let me know if you find any bugs... ;)

downloads updated:

Binary:

http://popeax.com/downloads/Ghost.zip

http://rapidshare.com/files/123497364/Ghost.zip.html

Source Code: (MSVC++ 2008 project)

http://popeax.com/downloads/GhostSource.zip

http://rapidshare.com/files/123497456/GhostSource.zip.html

Ghost.cpp Source Code: (it will compile by it self it just wont have an icon or xp theme support)

// Ghost v1.1 - by Steve8x
// small bug fix
#include <windows.h>
#include <stdio.h>

#ifndef WS_EX_LAYERED
#define WS_EX_LAYERED 0×00080000
#endif

typedef BOOL (CALLBACK* SETLAYEREDWINDOWATTRIBUTES)(HWND, COLORREF, BYTE, DWORD);
HWND CreateEditEx(HWND h, char Text[64], int x, int y, int wd, int ht, int id);
HWND CreateButtonEx(HWND h, char Text[64], int x, int y, int wd, int ht, int id);
HWND CreateCheckEx(HWND h, char Text[64], int x, int y, int wd, int ht, int id);
HWND CreateTextEx(HWND h, char Text[64], int x, int y, int wd, int ht, int id);

HINSTANCE hInst;
HWND hWnd, OhWnd, phWnd, EditBox, StartUpChk, SHChk, PWprotect, PW, PWbox;
HKEY hk;
DWORD BufSize = 256;

char WndTitle[256];
char WndText[64];
char HideWnd[64];
char exePath[256];
char Password[32];
char Password2[32];
int id = 0, enablepw = 0, ShowHide = 0, hideGUI = 0;

struct HiddenWindows
{
    HWND handle;
    char name[256];
};

HiddenWindows Windows[32]; // youll never hide 32 windows but its good to be covered

void AlphaBlend() // sets window transparency
{
    SETLAYEREDWINDOWATTRIBUTES pSetLayered;

    HMODULE u32 = LoadLibraryA("user32.dll");
    pSetLayered = (SETLAYEREDWINDOWATTRIBUTES)GetProcAddress(u32, "SetLayeredWindowAttributes");
    pSetLayered(hWnd, 0, 170, LWA_ALPHA);

    FreeLibrary(u32);
}

void movsb(void* dst, void* src, int bSize) // ASM movsb == Faster than memcpy
{
    _asm
    {
        pushad
        mov esi, [src]
        mov edi, [dst]
        mov ecx, [bSize]
        rep movsb
        popad
    }
}

BOOL CALLBACK SearchWnd(HWND h, LPARAM lParam)
{
    int i = 0, sSize = 0;
    ZeroMemory(&WndTitle, 256);

    GetWindowTextA(h, WndTitle, 256);
    sSize = lstrlenA(WndTitle);

    // convert string to lowercase
    while (i < sSize)
    {
        char up = WndTitle[i];
        up = tolower(up);
        WndTitle[i] = up;
        i++;
    }

    if(strstr(WndTitle, HideWnd))
    {
        ZeroMemory(Windows[id].name, 256);

        //OutputDebugStringA("Window Hidden!");
        Windows[id].handle = h;
        movsb(Windows[id].name, WndTitle, sSize+1);

        ShowWindow(Windows[id].handle, SW_HIDE);
        id++;
        return FALSE;
    }
    return TRUE;
}

void GrabSearchString()
{
    int sSize = 0, i = 0;

    ZeroMemory(&HideWnd, 64);
    GetWindowTextA(EditBox, HideWnd, 64);

    sSize = lstrlenA(HideWnd);

    // convert string to lowercase
    while (i < sSize)
    {
        char up = HideWnd[i];
        up = tolower(up);
        HideWnd[i] = up;
        i++;
    }
}


bool Hide()
{
    GrabSearchString();

    if(id == 32)
    {
        //OutputDebugStringA("Maximum Number Of Hidden Windows Reached!");
        return 0;
    }

    if(HideWnd[0] == 0)
    {
        //nothing typed in box so do nothing
        return 0;
    }

    for(int x = 0; x < id; x++) // if window already hidden do nothing
    {
        if(strstr(Windows[x].name, HideWnd))
        {
            //OutputDebugStringA("Window Already Hidden!");
            return 0;
        }
    }

    //Enumerate all windows and hide if found
    EnumWindows(SearchWnd, 0);

    sprintf_s(WndText, 64, "Gho$t [%i]", id);
    SetWindowTextA(hWnd, WndText);

    return 1;
}

bool UnHide()
{
    GrabSearchString();

    if(HideWnd[0] == 0) // unhide last entry
    {
        if(id == 0)
            return 0;

        ShowWindow(Windows[id-1].handle, SW_MINIMIZE);
        Windows[id-1].handle = 0;
        ZeroMemory(&Windows[id-1].name, 256);
        id--;

        sprintf_s(WndText, 64, "Gho$t [%i]", id);
        SetWindowTextA(hWnd, WndText);

        //OutputDebugStringA("Window Unhidden!");
        return 1;
    }

    for(int x = 0; x < id; x++) // check hidden windows
    {

        if(strstr(Windows[x].name, HideWnd))
        {
            ShowWindow(Windows[x].handle, SW_MINIMIZE);

            // keep array tightly packed
            // if we delete an entry from somewhere
            // then copy the last entry to its place
            if(id > 0)
            {
                Windows[x].handle = 0;
                ZeroMemory(&Windows[x].name, 256);

                Windows[x] = Windows[id-1];
                id--;
            }

            sprintf_s(WndText, 64, "Gho$t [%i]", id);
            SetWindowTextA(hWnd, WndText);

            //OutputDebugStringA("Window Unhidden!");
            return 1;
        }
    }

    // window has not been hidden by this program
    //OutputDebugStringA("Window Not Hidden!");

    return 0;
}

void EncryptPassword(char passw[32]) // lol
{
    int pSize = lstrlenA(passw);

    for(int c = 0; c < pSize; c++)
    {
        passw[c] += 137;
    }
}

void AddToStartupWithHide()
{
    char Path[256];
    HKEY hak5;

    RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_ALL_ACCESS, &hak5);

    GetModuleFileNameA(GetModuleHandle(0), Path, sizeof(Path));
    strcat_s(Path, " -hide");

    int pathSize = lstrlenA(Path);
    RegSetValueExA(hak5, "Ghost", 0, REG_SZ, (const unsigned char*)Path, pathSize);

    RegCloseKey(hak5);
}



LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) 
    {
        case WM_COMMAND:
            if(wParam == 420) // Ok!
                Hide();
            if(wParam == 421) // Undo
                UnHide();
            if(wParam == 422) // Options
                ShowWindow(OhWnd, SW_SHOWNORMAL);

            break;

        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

LRESULT CALLBACK PWWndProc(HWND h, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) 
    {
        case WM_COMMAND:
            if(wParam == 423) // OK!
            {
                GetWindowTextA(PWbox, Password2, 32);

                EncryptPassword(Password2);

                if(strcmp(Password, Password2) == 0)
                {
                    hideGUI = 1;
                    ShowWindow(phWnd, SW_HIDE);
                    ShowWindow(hWnd, SW_SHOWNORMAL);
                    ShowHide = 0;
                }
                else
                {
                    SetWindowTextA(phWnd, "INVALID PW!");
                    FlashWindow(phWnd, 1);
                }
            }
            break;

        case WM_CLOSE:
            ShowWindow(phWnd, SW_HIDE);
            ShowHide = 0;
            break;

        default:
            return DefWindowProc(h, message, wParam, lParam);
   }
   return 0;
}

LRESULT CALLBACK OptionsWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) 
    {
        case WM_COMMAND:
            if(wParam == 500) // start with windows checkbox
            {
                LRESULT startwithwindows = SendMessage(StartUpChk, BM_GETCHECK, 0, 0);

                RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_ALL_ACCESS, &hk);
                if(startwithwindows == BST_CHECKED)
                {
                    GetModuleFileNameA(GetModuleHandle(0), exePath, sizeof(exePath));
                    int pathSize = lstrlenA(exePath);
            
                    RegSetValueExA(hk, "Ghost", 0, REG_SZ, (const unsigned char*)exePath, pathSize);
                    EnableWindow(SHChk, 1);

                    RegCloseKey(hk);
                }
                else
                {
                    RegDeleteValueA(hk, "Ghost");
                    EnableWindow(SHChk, 0);
                    SendMessage(SHChk, BM_SETCHECK, 0, 0);

                    RegCloseKey(hk);

                    RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Steve8x\\Ghost",0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hk, 0);
                    DWORD yes = 0;
                    RegSetValueExA(hk, "StartHidden", 0, REG_DWORD, (BYTE*)&yes, sizeof(yes));

                    RegCloseKey(hk);
                }

                
            }
            if(wParam == 501) // start hidden checkbox
            {
                LRESULT starthidden = SendMessage(SHChk, BM_GETCHECK, 0, 0);

                RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Steve8x\\Ghost",0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hk, 0);
                if(starthidden == BST_CHECKED)
                {
                    DWORD yes = 1;
                    RegSetValueExA(hk, "StartHidden", 0, REG_DWORD, (BYTE*)&yes, sizeof(yes));
                    AddToStartupWithHide();
                }
                else
                {
                    DWORD yes = 0;
                    RegSetValueExA(hk, "StartHidden", 0, REG_DWORD, (BYTE*)&yes, sizeof(yes));
                }

                RegCloseKey(hk);
            }
            if(wParam == 502) // password protect checkbox
            {
                ZeroMemory(&Password, 32);
                GetWindowTextA(PW, Password, 32);

                RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Steve8x\\Ghost",0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hk, 0);

                LRESULT pwprotect = SendMessage(PWprotect, BM_GETCHECK, 0, 0);
                if(pwprotect == BST_UNCHECKED)
                {
                    DWORD yes = 0;
                    RegSetValueExA(hk, "PasswordProtect", 0, REG_DWORD, (BYTE*)&yes, sizeof(yes));
                    SetWindowTextA(PW, "");
                    EnableWindow(PW, 1);
                    enablepw = 0;
                    ShowHide = 1;
                    break;
                }

                if(Password[0] == 0)
                {
                    SendMessage(PWprotect, BM_SETCHECK, 0, 0);
                    MessageBoxA(0, "You Need To Enter A Password First!", "!", 0);
                    break;
                }

                
                if(pwprotect == BST_CHECKED)
                {
                    EncryptPassword(Password);
                    SetWindowTextA(PW, Password);

                    DWORD yes = 1;
                    RegSetValueExA(hk, "PasswordProtect", 0, REG_DWORD, (BYTE*)&yes, sizeof(yes));
                    RegSetValueExA(hk, "Password", 0, REG_SZ, (BYTE*)Password, sizeof(Password));        

                    EnableWindow(PW, 0);
                    enablepw = 1;
                }
            

                RegCloseKey(hk);
            }

            break;

        case WM_CLOSE:
            ShowWindow(OhWnd, SW_HIDE);
            break;

        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

void HotkeyHandler(void* nCmdShow)
{
    // so that if its hidden on start it will unhide at the first hotkey press / vice versa
    ShowHide = *(int*)nCmdShow;

    for(;; Sleep(10))
    {
        // CTRL + ALT + G
        if((GetKeyState(VK_CONTROL) & 0x8000) && (GetKeyState(VK_MENU) & 0x8000) && (GetKeyState(0x47) < 0))
        {
            _asm xor [ShowHide], 1

            if(enablepw == 1 && hideGUI == 1)
            {
                ShowWindow(phWnd, ShowHide);
                ShowWindow(hWnd, 0);

                SetWindowTextA(PWbox, "");
                SetWindowTextA(phWnd, "Password:");
                SetForegroundWindow(phWnd);
            }
            else if(enablepw == 1 && hideGUI == 0)
            {
                hideGUI = 1;
                ShowWindow(hWnd, ShowHide);
            }
            else if(enablepw == 0)
            {
                ShowWindow(hWnd, ShowHide);
            }

            Sleep(200);
            
        }
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    int WndWidth = 170, WndHeight = 80, ScreenPosX, ScreenPosY;

    hInst = hInstance;

    WNDCLASSEX wc;
    MSG Msg;

    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(101));
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(DEFAULT_PALETTE);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = L"Ghost_Class";
    wc.hIconSm       = LoadIcon(hInstance, MAKEINTRESOURCE(101));

    RegisterClassEx(&wc);

    wc.lpszClassName = L"Ghost_Options_Class";
    wc.lpfnWndProc = OptionsWndProc;

    RegisterClassEx(&wc);

    wc.lpszClassName = L"Ghost_PW_Class";
    wc.lpfnWndProc = PWWndProc;

    RegisterClassEx(&wc);

    int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
    ScreenPosX = (ScreenWidth / 2) - WndWidth;
    ScreenPosY = (ScreenHeight / 2) - WndHeight;

    hWnd = CreateWindowExA(WS_EX_LAYERED, "Ghost_Class", "Gho$t",  WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_CLIPSIBLINGS,
        ScreenPosX, ScreenPosY, WndWidth, WndHeight, 0, 0, hInstance, 0);

    OhWnd = CreateWindowExA(0, "Ghost_Options_Class", "Gho$t Options",  WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_CLIPSIBLINGS,
        (ScreenPosX+50), (ScreenPosY+20), WndWidth, 168, 0, 0, hInstance, 0);

    phWnd = CreateWindowExA(0, "Ghost_PW_Class", "Password:",  WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_CLIPSIBLINGS,
        ScreenPosX, ScreenPosY, WndWidth, (WndHeight-4), 0, 0, hInstance, 0);

    // Main Window Controls
    EditBox = CreateEditEx(hWnd, 0, 2, 2, 158, 25, 300);
    CreateButtonEx(hWnd, "Ok!", 1, 30, 50, 22, 420);
    CreateButtonEx(hWnd, "Undo", 51, 30, 50, 22, 421);
    CreateButtonEx(hWnd, "Options", 101, 30, 60, 22, 422);

    //Options Window Controls
    StartUpChk = CreateCheckEx(OhWnd, "Start With Windows", 2, 2, 160, 25, 500);
    SHChk = CreateCheckEx(OhWnd, "Start Hidden", 2, 27, 160, 25, 501);
    PWprotect = CreateCheckEx(OhWnd, "Password Protect", 2, 52, 160, 25, 502);
    CreateTextEx(OhWnd, "Password:", 2, 77, 160, 20, 600);
    PW = CreateEditEx(OhWnd, 0, 2, 95, 160, 25, 301);
    CreateTextEx(OhWnd, "Coded By Steve8x", 2, 122, 160, 25, 601);

    //Password Window Controls
    PWbox = CreateEditEx(phWnd, 0, 2, 2, 160, 25, 302);
    CreateButtonEx(phWnd, "OK!", 55, 28, 50, 22, 423);

    RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_READ, &hk);
    RegQueryValueExA(hk, "Ghost", 0, 0, (LPBYTE)exePath, &BufSize);
    if(exePath[1] == 0x3A) // 0x3A == ":"
    {
        SendMessage(StartUpChk, BM_SETCHECK, 1, 0);
        EnableWindow(SHChk, 1);
    }
    else
    {
        EnableWindow(SHChk, 0);
    }

    RegCloseKey(hk);

    DWORD vSize = 4, pSize = 32, StartHidden = 0, PWpro = 0;

    RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Steve8x\\Ghost", 0, KEY_READ, &hk);
    RegQueryValueExA(hk, "StartHidden", 0, 0, (LPBYTE)&StartHidden, &vSize);
    RegQueryValueExA(hk, "PasswordProtect", 0, 0, (LPBYTE)&PWpro, &vSize);
    RegQueryValueExA(hk, "Password", 0, 0, (LPBYTE)&Password, &pSize);
    RegCloseKey(hk);

    if(StartHidden == 1)
    {
        SendMessage(SHChk, BM_SETCHECK, 1, 0);
    }
    if(PWpro == 1)
    {
        SendMessage(PWprotect, BM_SETCHECK, 1, 0);
        SetWindowTextA(PW, Password);
        EnableWindow(PW, 0);
        enablepw = 1;
    }
        
    if(_strcmpi(lpCmdLine, "-hide") == 0) // start hidden
    {
        nCmdShow = SW_HIDE;    
    }
    if(enablepw == 1)
    {
        hideGUI = 1;
        ShowWindow(phWnd, nCmdShow);
        SetFocus(PWbox);
    }
    else
    {
        ShowWindow(hWnd, nCmdShow);
        SetFocus(EditBox);
    }

    UpdateWindow(hWnd);

    AlphaBlend();

    CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&HotkeyHandler, (void*)&nCmdShow, 0, 0);

    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        if(Msg.message == WM_KEYDOWN)
        {
            if(Msg.wParam == VK_RETURN)
            {
                if(PWbox == GetFocus()) // if enter is pressed on password box then hit OK!
                {
                    SendMessageA(phWnd, WM_COMMAND, 423, 0);
                }

                if(EditBox == GetFocus()) // if enter is pressed on main GUI's edit box then hit Ok!
                {
                    SendMessageA(hWnd, WM_COMMAND, 420, 0);
                }
            }

            if(Msg.wParam == VK_TAB)
            {
                if(EditBox == GetFocus()) // if tab is pressed on main GUI's edit box then hit undo button
                {
                    SendMessageA(hWnd, WM_COMMAND, 421, 0);
                }
            }
        }

        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

HWND CreateButtonEx(HWND h, char Text[64], int x, int y, int wd, int ht, int id)
{
    return CreateWindowExA(0, "BUTTON", Text, WS_CHILD | WS_VISIBLE | WS_TABSTOP, x, y, wd, ht, h, (HMENU)id, hInst, 0);
}

HWND CreateEditEx(HWND h, char Text[64], int x, int y, int wd, int ht, int id)
{
    return CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", Text, ES_WANTRETURN | ES_NOHIDESEL | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP, x, y, wd, ht, h, (HMENU)id, hInst, 0);
}

HWND CreateCheckEx(HWND h, char Text[64], int x, int y, int wd, int ht, int id)
{
    return CreateWindowExA(0, "BUTTON", Text, WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, x, y, wd, ht, h, (HMENU)id, hInst, 0);
}

HWND CreateTextEx(HWND h, char Text[64], int x, int y, int wd, int ht, int id)
{
    return CreateWindowExA(0, "STATIC", Text, WS_CHILD | WS_VISIBLE | SS_LEFT, x, y, wd, ht, h, (HMENU)id, hInst, 0);
}

Link to comment
Share on other sites

  • 3 weeks later...
  • 2 weeks later...

This looks great. I was hoping that in the new version you could maybe put in an option for customizing the hotkey or even adding a specific hotkey to a certain window. These are just thoughts. Anyway, it looks great.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...