#pragma option lst
#pragma option sobj
#pragma option w32
#pragma option wmb

#pragma option ip=vxdlib

#include "vmm.hmm"
#include "vkd.hmm"
#include "vwin32.hmm"
#include "shell.hmm"

dword hookprev;
union {
  dword  extcode;//!!!dword - bug
  byte  code;
};
dword old_virtual_machine;

dword window;
/////////////////////////////////////////////////////////////////////
myhook_pre(){ GOTO myhook; goto hookprev; }
myhook()
{
  //$call hookprev;
  //IF(CARRYFLAG)return;

  $push ECX
  extcode<<=8;
  code=CL;

  if(extcode==0xE0)
  ||(extcode==0xE1)
  ||(extcode&0xFFFFFF00==0x0000E100);
  else
  {
    //-----------------------------------------------------
    //do something
    VxDcall(_SHELL_PostMessage
            ,window
            ,0x400
            ,0
            ,extcode
    ,0,0);
    SWITCH(extcode)
    {
      case 0xE05B://VK_LWIN pressed
      CASE 0xE05C://VK_RWIN pressed
        VxDcall(VKD_Get_Kbd_Owner);
        old_virtual_machine=EBX;
        BREAK;
      CASE 0xE0DB://VK_LWIN released
      CASE 0xE0DC://VK_RWIN released
        VxDcall(VKD_Get_Kbd_Owner);
        IF(EBX!=old_virtual_machine)
        {
          IF(EBX=old_virtual_machine)
          {
            AX=0;
            VxDcall(VKD_Set_Shift_State);
          }
        }
        old_virtual_machine=0;
    }
    //-----------------------------------------------------
    extcode=0;
    $stc
  }
  $pop ECX
}
/////////////////////////////////////////////////////////////////////
int CARRYFLAG deviceioctlproc()
{
  SWITCH(ECX)
  {
    case DIOC_OPEN:
      ESI=#myhook;
      EAX=VKD_Filter_Keyboard_Input;
      VMMcall(Hook_Device_Service)
      EAX=0;
      $clc
      BREAK;
    CASE DIOC_CLOSEHANDLE:
      ESI=#myhook;
      EAX=VKD_Filter_Keyboard_Input;
      VMMcall(Unhook_Device_Service)
      EAX=VXD_SUCCESS;
      $clc
      BREAK;
    case 1:
      window=DSDWORD[ESI.DIOCParams.lpvInBuffer];
      EAX=0;
      $clc
      BREAK;
    default:
      EAX=50;//ERROR_NOT_SUPPORTED
      $clc
  }
}
/////////////////////////////////////////////////////////////////////
int CARRYFLAG DPKBHOOK_Control()
{
  SWITCH(EAX)
  {
    case W32_DeviceIoControl: deviceioctlproc(); return;
    //case SYS_DYNAMIC_DEVICE_INIT:
    //case SYS_DYNAMIC_DEVICE_EXIT:
    default:
      $clc
  }
}
/////////////////////////////////////////////////////////////////////
Declare_Virtual_Device(DPKBHOOK_DDB,"DPKBHOOK",1,0,#DPKBHOOK_Control,UNDEFINED_DEVICE_ID,UNDEFINED_INIT_ORDER,0,0)
