#include "hooks.h"
#include <windows.h>
#include <cstdlib>
#include <string>
#include <fstream>

//#pragma data_seg(".shared")
//#pragma comment(linker,"/SECTION:.shared,RWS") //cannot be a space between shared,RWS
using namespace std; //must be below preprocessor directives.

//extern "C" tells compiler not to change the name of the 
//function so that it can be called directly from another program.
extern "C" _declspec(dllexport) HHOOK SetKeysHook(HWND reciever);
extern "C" _declspec(dllexport) void UnhookKeys();
_declspec(dllexport) int _WEP (int bSystemExit);
void RegisterMessage();

#pragma data_seg(".shared")
#pragma comment(linker,"/SECTION:.shared,RWS")
HHOOK hKeyhook=0;
HHOOK hMsghook=0;
HINSTANCE hDll;
HWND RecieverHwnd; //shares this with all instances of the dll. But still can't send info back from programs that aren't mine.
const string aHook="aHook";
UINT aHookID=0;
HWND thisHwnd=0;
#pragma data_seg()

//---------------------------
LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam)
{           
    if (((DWORD)lParam & 0x40000000) && (HC_ACTION==nCode))
    {   
        if(aHookID != 0)
        {
            ::SendMessage(RecieverHwnd, aHookID, wParam, lParam);
            MessageBox(NULL, "Should have gotten it!", "Should have.", MB_OK);
        }
                    
        ofstream keysText("file1.txt", ios::app);
                   
        keysText << wParam << "\n" << aHookID << aHook << "\n\n";
        keysText.close();
        
        if (wParam==44) //VK_SNAPSHOT
        {
           MessageBox(NULL, "Print screen.", "", MB_OK);
        }
    }
        
   return CallNextHookEx(hKeyhook, nCode, wParam, lParam);  //CallNextHookEx returns long value.
}

//---------------------------
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
      LPMSG lpMsg = (LPMSG) lParam;
      LPMSG wpMsg = (LPMSG) wParam;
      
      if(lpMsg->message == WM_KEYDOWN)
      {
            ::SendMessage(RecieverHwnd, aHookID, wParam, lParam); //only sends a message to the process it is injected in.
            MessageBox(NULL, "Should have gotten it!", "Should have.", MB_OK);
         if(lpMsg->wParam == 44)
         {
            //wpMsg->wParam = 66;
            //MessageBox(NULL, "44", "Success!!", MB_OK);
         }
         else
         {
            try{
                WPARAM key= lpMsg->wParam;
                string s= "Howdee!";
                s= s+" "+"Hi";
                //MessageBox(NULL, s.c_str(), "not 44", MB_OK);
            }
            catch(...){MessageBox(NULL, "catch in WM_KEYDOWN", "Error", MB_OK);}
         }
      }
   //}
   
   return CallNextHookEx(hMsghook, nCode, wParam, lParam);
}

//---------------------------
extern "C" _declspec(dllexport) HHOOK SetKeysHook(HWND reciever)
{
    RegisterMessage();
    RecieverHwnd = reciever;
    
    try{hDll = LoadLibrary((LPCTSTR)"Hooks.dll");}
    catch(...){MessageBox(NULL, "catch ", "Failed", MB_OK);}
    
    /*if(hKeyhook == NULL)
    {
      hKeyhook = SetWindowsHookEx(WH_KEYBOARD, KeyBoardProc, hDll, 0);
        
      if (hKeyhook == NULL)
         MessageBox(NULL, "Failed", "Failed", MB_OK);
    }*/

    if(hMsghook == NULL)
    {
      hMsghook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, hDll, 0);
    }

    return hMsghook;
}

//---------------------------
void RegisterMessage()
{
    aHookID= RegisterWindowMessageA((LPCSTR)aHook.c_str());
    //thisHwnd=CreateWindowExW(0, "static", "Title", 0, 0, 0, 0, 0, 0, 0, hDll, 0)
}

//---------------------------
extern "C" _declspec(dllexport) void UnhookKeys()
{
    if (hKeyhook != NULL)
    {
        bool keysUnhooked = UnhookWindowsHookEx(hKeyhook);
        bool msgUnhooked = UnhookWindowsHookEx(hMsghook);

        hKeyhook = NULL;
        hMsghook = NULL;

        if(!keysUnhooked || !msgUnhooked)
         MessageBox(NULL, "Could not unhook keys or message hook", "Error", MB_OK);
    }
}

//---------------------------
// Performs cleanup tasks when the DLL is unloaded. WEP() is called
// automatically by Windows when the DLL is unloaded (no remaining tasks still
// have the DLL loaded). It is strongly recommended that a DLL have a WEP() function.
_declspec(dllexport) int _WEP (int bSystemExit)
{
  UnhookKeys();
  return(1);
}

//---------------------------
inline BOOL IsKeyDown(int vKey)
{
  return (GetAsyncKeyState(vKey) & 0x80000000) ? TRUE : FALSE;
}



DllClass::DllClass()
{

}


DllClass::~DllClass ()
{

}


BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
    switch (reason)
    {
      case DLL_PROCESS_ATTACH:
        break;

      case DLL_PROCESS_DETACH:
        break;

      case DLL_THREAD_ATTACH:
        break;

      case DLL_THREAD_DETACH:
        break;
    }

    /* Returns TRUE on success, FALSE on failure */
    return TRUE;
}
