////////////////////////////////////////////////////////////////////////////////
//Arquivo com as funções em C++
////////////////////////////////////////////////////////////////////////////////

#include "common.ch"    // para poder redefinir a fun‡Æo type() para ischaracter() e outras
#include "winuser.ch"

   /////////////////////////////////////////////////////////////////////////////
Function GetActiveWindow()
   Return NIL

#pragma BEGINDUMP

   #pragma comment( lib, "shell32.lib" )
   #include <winsock.h>
   #include <windows.h>
   #include "winbase.h"
   #include "winuser.h"
   #include <stdio.h>
   #include <stdlib.h>
   #include <Iphlpapi.h>
   #include <Assert.h>
   #include <sql.h>
   #include <sqlext.h>
   #include "hbapi.h"
   #include "hbapiitm.h"
   #include "item.api"
   //#include <sapi.h>

   #define HB_OS_WIN_32_USED
   #define MAX_DRIVER_COUNT 50

// Função para obter a lista de drivers ODBC
HB_FUNC( GETODBCDRIVERS )
{
    SQLHANDLE henv;
    SQLRETURN ret;
    static char drivers[MAX_DRIVER_COUNT][1024]; // Array para armazenar os nomes dos drivers
    static char result[1024 * MAX_DRIVER_COUNT];
    int count = 0;
    int i;
    
    SQLCHAR driver[1024]; // Declarado no início da função

    SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
    SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);

    ret = SQLDrivers(henv, SQL_FETCH_FIRST, driver, sizeof(driver), NULL, NULL, NULL, NULL);

    while (ret != SQL_NO_DATA && count < MAX_DRIVER_COUNT - 1) {
        snprintf(drivers[count], sizeof(drivers[count]), "%s", driver);
        count++;

        ret = SQLDrivers(henv, SQL_FETCH_NEXT, driver, sizeof(driver), NULL, NULL, NULL, NULL);
    }

    drivers[count][0] = '\0'; // Null-terminate the last string

    SQLFreeHandle(SQL_HANDLE_ENV, henv);

    // Concatenar os nomes dos drivers em uma única string
    result[0] = '\0';

    for (i = 0; i < count; i++) {
        strcat(result, drivers[i]);
        strcat(result, "\n");
    }
    
    hb_retc( result );
    
    return ;
}

   /////////////////////////////////////////////////////////////////////////////
HB_FUNC( _OPENHELPFILE )
   {
   HINSTANCE hInst;
    LPCTSTR lpPath = (LPTSTR) hb_parc( 1 );
    LPCTSTR lpHelpFile = (LPTSTR) hb_parc( 2 );
    hInst = ShellExecute( 0, "Open", lpHelpFile, 0, lpPath, 1 );
    hb_retnl( (LONG) hInst );
    return;
    }


   //------------------------------------------------------------------
   // standard 32 byte's M$ guid
   // Link: http://forums.fivetechsupport.com/viewtopic.php?f=3&t=28026&p=156570&hilit=guid#p156570
   // Link: http://forums.fivetechsupport.com/viewtopic.php?f=3&t=21719&start=30
   //------------------------------------------------------------------
   HB_FUNC( NewGuid32 )
   {
   GUID guid;
    char obuff[38];
    memset( obuff, 0x0, 38 );
    if ( CoCreateGuid(&guid) == NULL )
   {
   OLECHAR tmpbuff[76];
    StringFromGUID2(&guid, tmpbuff, 76);
    WideCharToMultiByte(CP_OEMCP, 0, tmpbuff, -1, obuff, 38, NULL, NULL);
    }
   hb_retclen(obuff, 38);
    }

   //------------------------------------------------------------------
   // standard 32 byte's M$ guid
   // Link: http://forums.fivetechsupport.com/viewtopic.php?f=3&t=28026&p=156570&hilit=guid#p156570
   // Link: http://forums.fivetechsupport.com/viewtopic.php?f=3&t=21719&start=30
   //------------------------------------------------------------------
HB_FUNC( _NEWGUID32 )
   {
   GUID guid;
    char obuff[38];
    memset( obuff, 0x0, 38 );
    if ( CoCreateGuid(&guid) == NULL )
      {
      OLECHAR tmpbuff[76];
       StringFromGUID2(&guid, tmpbuff, 76);
       WideCharToMultiByte(CP_OEMCP, 0, tmpbuff, -1, obuff, 38, NULL, NULL);
       }
   hb_retclen(obuff, 38);
    }


   /////////////////////////////////////////////////////////////////////////////
   //Pressionar a tecla alt
   //https://docs.microsoft.com/pt-br/windows/win32/inputdev/virtual-key-codes
HB_FUNC( _VKALT )
   {
   keybd_event (VK_MENU, 0, 0, 0 );
   keybd_event (VK_MENU, 0, KEYEVENTF_KEYUP, 0);
   }

   /////////////////////////////////////////////////////////////////
   //Pressionar qualquer tecla
HB_FUNC( _VKLETRA )
   {
   keybd_event (hb_parnl(1), 0, 0, 0 );
   keybd_event (hb_parnl(1), 0, KEYEVENTF_KEYUP, 0);
   }

   /////////////////////////////////////////////////////////////////
   //Pressionar seta direita
HB_FUNC( _VKSETADIR )
   {
   keybd_event (VK_RIGHT, 0, 0, 0 );
   keybd_event (VK_RIGHT, 0, KEYEVENTF_KEYUP, 0);
   }

   /////////////////////////////////////////////////////////////////
   //Pressionar seta baixo
HB_FUNC( _VKSETABAI )
   {
   int n; //= 1;
   for(n = 1; n <= hb_parni(1); n++) {
      keybd_event (VK_DOWN, 0, 0, 0 );
      keybd_event (VK_DOWN, 0, KEYEVENTF_KEYUP, 0);
      }
   }


   //////////////////////////////////////////////////////////////////////////////////////
   //
HB_FUNC( _CLI )      //Retorna o nome do usuário do windows
   {

   //ponteiro char[] para o IP retornado no formato string
   char *IP;
    struct in_addr ipGeral;

    //ponteiro para a estrutura que armazena o IP obtido pelo nome do pc
   struct hostent * ipPeloNome;

    char nomeDoPCLocal[255]; 	//armazena o nome do computador local

    WSADATA infoSocket; 			//estrutura para obter as informações básica do socket no windows.

    //inicializa o socket 2.0 no windows - sem essa inicialização, vc não tem
   //permissão para utilizar as funções de rede no windows.
   WSAStartup(MAKEWORD(2,0), &infoSocket);

    gethostname(nomeDoPCLocal, 255); //função obtém o nome da sua máquina local

    //função retorna o endereço para uma estrutura do tipo hostent, que dentre outras opções
   //armazena o endereço de ip referente ao nome do PC passado como argumento para essa função.
   ipPeloNome = gethostbyname(nomeDoPCLocal);

    //copia o IP obtido para uma estrutura do tipo "in_addr"
   memcpy(&ipGeral, ipPeloNome->h_addr_list[0], sizeof(struct in_addr));

    //inet_ntoa() decodifica a estrutura do tipo "in_addr" e retorna o IP em uma string de
   //caracteres legíveis.
   IP = inet_ntoa(ipGeral);

    hb_retc( IP);

    WSACleanup();

    }

   ///////////////////////////////////////////////////////////////////////////////////////////
   // Pega o MAC da placa de Rede
HB_FUNC(_CLM)
   {

   IP_ADAPTER_INFO AdapterInfo[16];       // Allocate information for up to 16 NICs
    DWORD dwBufLen = sizeof(AdapterInfo);       // Save the memory size of buffer
    unsigned char ret[ 20 ] ={0};

   DWORD dwStatus = GetAdaptersInfo(           // Call GetAdapterInfo
    AdapterInfo,       									// [out] buffer to receive data
    &dwBufLen);        									// [in] size of receive data buffer

    PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;// Contains pointer to current adapter info
    //assert(dwStatus == ERROR_SUCCESS);   			// Verify return value is valid, no buffer overflow

    sprintf(ret,"%02X-%02X-%02X-%02X-%02X-%02X",
   pAdapterInfo->Address[0], pAdapterInfo->Address[1],
   pAdapterInfo->Address[2], pAdapterInfo->Address[3],
   pAdapterInfo->Address[4], pAdapterInfo->Address[5]);

    hb_retc(ret);

    }


   /////////////////////////////////////////////////////////////////////////////
   //
HB_FUNC( _CLSHIFT )
   {
   HINSTANCE mRetorno;
    LPCTSTR mString1 = (LPTSTR) hb_parc( 1 );
    LPCTSTR mString2 = (LPTSTR) hb_parc( 2 );

    // temos que converter a string em um valor inteiro válido
   int res1 = atoi(mString1);
    int res2 = atoi(mString2);

    hb_retnl( (LONG) (res1 ^ ( res2 >> 8 )) );

    return;
    }
    

HB_FUNC(SAVE_SCREENSHOT)
{
    const char* filename;
    int screenWidth, screenHeight;
    HDC hScreenDC, hMemoryDC;
    HBITMAP hBitmap;
    BITMAP bmp;
    BITMAPFILEHEADER bmfHeader;
    BITMAPINFOHEADER bi;
    DWORD dwBmpSize, dwSizeofDIB, dwBytesWritten;
    HANDLE hDIB, hFile;
    char* lpbitmap;

    // Obtém o nome do arquivo passado como parâmetro
    filename = hb_parc(1);

    // Obtém as dimensões da tela
    screenWidth = GetSystemMetrics(SM_CXSCREEN);
    screenHeight = GetSystemMetrics(SM_CYSCREEN);

    // Captura o dispositivo da tela (HDC)
    hScreenDC = GetDC(NULL);
    hMemoryDC = CreateCompatibleDC(hScreenDC);

    // Cria um bitmap compatível com o dispositivo da tela
    hBitmap = CreateCompatibleBitmap(hScreenDC, screenWidth, screenHeight);
    SelectObject(hMemoryDC, hBitmap);

    // Copia a tela para o bitmap
    BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, hScreenDC, 0, 0, SRCCOPY);

    // Estrutura para salvar o bitmap como BMP
    GetObject(hBitmap, sizeof(BITMAP), &bmp);

    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = bmp.bmWidth;
    bi.biHeight = -bmp.bmHeight; // Negativo para linha de cima ser a primeira
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;

    dwBmpSize = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmp.bmHeight;

    hDIB = GlobalAlloc(GHND, dwBmpSize);
    lpbitmap = (char*)GlobalLock(hDIB);

    // Copia o bitmap para o buffer
    GetDIBits(hMemoryDC, hBitmap, 0, (UINT)bmp.bmHeight, lpbitmap, (BITMAPINFO*)&bi, DIB_RGB_COLORS);

    // Cria o arquivo BMP
    hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    bmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    bmfHeader.bfSize = dwSizeofDIB;
    bmfHeader.bfType = 0x4D42; // BM

    WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);

    // Libera recursos
    GlobalUnlock(hDIB);
    GlobalFree(hDIB);
    CloseHandle(hFile);

    DeleteObject(hBitmap);
    DeleteDC(hMemoryDC);
    ReleaseDC(NULL, hScreenDC);

    hb_retl(TRUE); // Retorna sucesso
}

#pragma ENDDUMP

