CompileOutput *Compiler::Compile(AMXRef amx) { Prepare(amx); Disassembler disasm(amx); Instruction instr; bool error = false; while (!error && disasm.Decode(instr, error)) { if (!Process(instr)) { error = true; break; } switch (instr.opcode().GetId()) { case OP_LOAD_PRI: load_pri(instr.operand()); break; case OP_LOAD_ALT: load_alt(instr.operand()); break; case OP_LOAD_S_PRI: load_s_pri(instr.operand()); break; case OP_LOAD_S_ALT: load_s_alt(instr.operand()); break; case OP_LREF_PRI: lref_pri(instr.operand()); break; case OP_LREF_ALT: lref_alt(instr.operand()); break; case OP_LREF_S_PRI: lref_s_pri(instr.operand()); break; case OP_LREF_S_ALT: lref_s_alt(instr.operand()); break; case OP_LOAD_I: load_i(); break; case OP_LODB_I: lodb_i(instr.operand()); break; case OP_CONST_PRI: const_pri(instr.operand()); break; case OP_CONST_ALT: const_alt(instr.operand()); break; case OP_ADDR_PRI: addr_pri(instr.operand()); break; case OP_ADDR_ALT: addr_alt(instr.operand()); break; case OP_STOR_PRI: stor_pri(instr.operand()); break; case OP_STOR_ALT: stor_alt(instr.operand()); break; case OP_STOR_S_PRI: stor_s_pri(instr.operand()); break; case OP_STOR_S_ALT: stor_s_alt(instr.operand()); break; case OP_SREF_PRI: sref_pri(instr.operand()); break; case OP_SREF_ALT: sref_alt(instr.operand()); break; case OP_SREF_S_PRI: sref_s_pri(instr.operand()); break; case OP_SREF_S_ALT: sref_s_alt(instr.operand()); break; case OP_STOR_I: stor_i(); break; case OP_STRB_I: strb_i(instr.operand()); break; case OP_LIDX: lidx(); break; case OP_LIDX_B: lidx_b(instr.operand()); break; case OP_IDXADDR: idxaddr(); break; case OP_IDXADDR_B: idxaddr_b(instr.operand()); break; case OP_ALIGN_PRI: align_pri(instr.operand()); break; case OP_ALIGN_ALT: align_alt(instr.operand()); break; case OP_LCTRL: lctrl(instr.operand(), instr.address() + instr.size()); break; case OP_SCTRL: sctrl(instr.operand()); break; case OP_MOVE_PRI: move_pri(); break; case OP_MOVE_ALT: move_alt(); break; case OP_XCHG: xchg(); break; case OP_PUSH_PRI: push_pri(); break; case OP_PUSH_ALT: push_alt(); break; case OP_PUSH_C: push_c(instr.operand()); break; case OP_PUSH: push(instr.operand()); break; case OP_PUSH_S: push_s(instr.operand()); break; case OP_POP_PRI: pop_pri(); break; case OP_POP_ALT: pop_alt(); break; case OP_STACK: // value stack(instr.operand()); break; case OP_HEAP: heap(instr.operand()); break; case OP_PROC: proc(); break; case OP_RET: ret(); break; case OP_RETN: retn(); break; case OP_JUMP_PRI: jump_pri(); break; case OP_CALL: case OP_JUMP: case OP_JZER: case OP_JNZ: case OP_JEQ: case OP_JNEQ: case OP_JLESS: case OP_JLEQ: case OP_JGRTR: case OP_JGEQ: case OP_JSLESS: case OP_JSLEQ: case OP_JSGRTR: case OP_JSGEQ: { cell dest = instr.operand() - reinterpret_cast<cell>(amx.code()); switch (instr.opcode().GetId()) { case OP_CALL: call(dest); break; case OP_JUMP: jump(dest); break; case OP_JZER: jzer(dest); break; case OP_JNZ: jnz(dest); break; case OP_JEQ: jeq(dest); break; case OP_JNEQ: jneq(dest); break; case OP_JLESS: jless(dest); break; case OP_JLEQ: jleq(dest); break; case OP_JGRTR: jgrtr(dest); break; case OP_JGEQ: jgeq(dest); break; case OP_JSLESS: jsless(dest); break; case OP_JSLEQ: jsleq(dest); break; case OP_JSGRTR: jsgrtr(dest); break; case OP_JSGEQ: jsgeq(dest); break; } break; } case OP_SHL: shl(); break; case OP_SHR: shr(); break; case OP_SSHR: sshr(); break; case OP_SHL_C_PRI: shl_c_pri(instr.operand()); break; case OP_SHL_C_ALT: shl_c_alt(instr.operand()); break; case OP_SHR_C_PRI: shr_c_pri(instr.operand()); break; case OP_SHR_C_ALT: shr_c_alt(instr.operand()); break; case OP_SMUL: smul(); break; case OP_SDIV: sdiv(); break; case OP_SDIV_ALT: sdiv_alt(); break; case OP_UMUL: umul(); break; case OP_UDIV: udiv(); break; case OP_UDIV_ALT: udiv_alt(); break; case OP_ADD: add(); break; case OP_SUB: sub(); break; case OP_SUB_ALT: sub_alt(); break; case OP_AND: and_(); break; case OP_OR: or_(); break; case OP_XOR: xor_(); break; case OP_NOT: not_(); break; case OP_NEG: neg(); break; case OP_INVERT: invert(); break; case OP_ADD_C: add_c(instr.operand()); break; case OP_SMUL_C: smul_c(instr.operand()); break; case OP_ZERO_PRI: zero_pri(); break; case OP_ZERO_ALT: zero_alt(); break; case OP_ZERO: zero(instr.operand()); break; case OP_ZERO_S: zero_s(instr.operand()); break; case OP_SIGN_PRI: sign_pri(); break; case OP_SIGN_ALT: sign_alt(); break; case OP_EQ: eq(); break; case OP_NEQ: neq(); break; case OP_LESS: less(); break; case OP_LEQ: leq(); break; case OP_GRTR: grtr(); break; case OP_GEQ: geq(); break; case OP_SLESS: sless(); break; case OP_SLEQ: sleq(); break; case OP_SGRTR: sgrtr(); break; case OP_SGEQ: sgeq(); break; case OP_EQ_C_PRI: eq_c_pri(instr.operand()); break; case OP_EQ_C_ALT: eq_c_alt(instr.operand()); break; case OP_INC_PRI: inc_pri(); break; case OP_INC_ALT: inc_alt(); break; case OP_INC: inc(instr.operand()); break; case OP_INC_S: inc_s(instr.operand()); break; case OP_INC_I: inc_i(); break; case OP_DEC_PRI: dec_pri(); break; case OP_DEC_ALT: dec_alt(); break; case OP_DEC: dec(instr.operand()); break; case OP_DEC_S: dec_s(instr.operand()); break; case OP_DEC_I: dec_i(); break; case OP_MOVS: movs(instr.operand()); break; case OP_CMPS: cmps(instr.operand()); break; case OP_FILL: fill(instr.operand()); break; case OP_HALT: halt(instr.operand()); break; case OP_BOUNDS: bounds(instr.operand()); break; case OP_SYSREQ_PRI: sysreq_pri(); break; case OP_SYSREQ_C: { const char *name = amx.GetNativeName(instr.operand()); if (name == 0) { error = true; } else { sysreq_c(instr.operand(), name); } break; } case OP_SYSREQ_D: { const char *name = amx.GetNativeName(amx.FindNative(instr.operand())); if (name == 0) { error = true; } else { sysreq_d(instr.operand(), name); } break; } case OP_SWITCH: switch_(CaseTable(amx, instr.operand())); break; case OP_CASETBL: casetbl(); break; case OP_SWAP_PRI: swap_pri(); break; case OP_SWAP_ALT: swap_alt(); break; case OP_PUSH_ADR: push_adr(instr.operand()); break; case OP_NOP: nop(); break; case OP_BREAK: break_(); break; default: error = true; } } if (error && error_handler_ != 0) { error_handler_->Execute(instr); } return Finish(error); }
void KeyMap::PCtoX(BYTE virtKey, DWORD keyData, ClientConnection* clientCon) { bool down = ((keyData & 0x80000000) == 0); bool extended = ((keyData & 0x1000000) != 0); bool repeated = ((keyData & 0xc0000000) == 0x40000000); UINT extVkey = virtKey + (extended ? 256 : 0); // exclude winkey when not scroll-lock if (virtKey==91 || virtKey==92) return; vnclog.Print(8, _T("\nPCtoX: %svirtKey 0x%02x%s%s, keyData 0x%08x\n"), (extended ? _T("extended ") : _T("")), virtKey, (repeated ? _T(" repeated") : _T("")), (down ? _T(" down") : _T(" up")), keyData); // If this is a key release then just send the associated sent KeySym when // this key was pressed if (!down) { vnclog.Print(8, _T("Release the associated KeySym when this VirtKey was pressed\n")); if (downUnicode[extVkey]) { vnclog.Print(8, _T(" 0x%04x (%c): "), downUnicode[extVkey], downUnicode[extVkey]); downUnicode[extVkey] = NULL; } else { vnclog.Print(8, _T(" Control character: ")); } releaseKey(clientCon, extVkey); vnclog.Print(8, _T("\n")); GetKeyboardState(KBKeysState); if (!((KBKeysState[VK_MENU] & 0x80) && (KBKeysState[VK_CONTROL] & 0x80))) { if (storedDeadChar && reset) { reset=false; keybd_event(VK_SPACE, 0, 0, 0); keybd_event(VK_SPACE, 0, KEYEVENTF_KEYUP, 0); } } return; } // We try to look it up in our key table // Look up the desired code in the keyMap table try to find the exact match according to // the extended flag, then try the opposite of the extended flag CARD32 foundXCode = XK_VoidSymbol; bool exactMatched = false; vnclog.Print(8, _T("Looking in key table ")); for (UINT i = 0; i < (sizeof(keyMap) / sizeof(vncKeyMapping_t)); i++) { if (keyMap[i].WinCode == virtKey) { foundXCode = keyMap[i].XCode; if (extended == keyMap[i].extVK) { exactMatched = true; break; } } } if (foundXCode != XK_VoidSymbol) { vnclog.Print(8, _T("-> keyMap gives (from %s extended flag) KeySym %u (0x%08x)\n"), (exactMatched ? _T("matched") : _T("opposite")), foundXCode, foundXCode); pressKey(clientCon, extVkey, foundXCode); vnclog.Print(8, _T("\n")); return; } else { vnclog.Print(8, _T("-> not in special keyMap\n")); } // Under CE, we're not so concerned about this bit because we handle a WM_CHAR message later #ifndef UNDER_CE GetKeyboardState(KBKeysState); ModifierKeyReleaser lctrl(clientCon, VK_CONTROL, 0); ModifierKeyReleaser lalt(clientCon, VK_MENU, 0); ModifierKeyReleaser ralt(clientCon, VK_MENU, 1); if ((KBKeysState[VK_MENU] & 0x80) && (KBKeysState[VK_CONTROL] & 0x80)) { // This is a Ctrl-Alt (AltGr) key on international keyboards (= LCtrl-RAlt) // Ex. Ctrl-Alt-Q gives '@' on German keyboards vnclog.Print(8, _T("Ctrl-Alt pressed:\n")); // We must release Control and Alt (AltGr) if they were both pressed, so the character // is seen without them by the VNC server // We don't release the Right Control; this allows German users // to use it for doing Ctrl-AltGr-x, e.g. Ctl-@, etc lctrl.release(downKeysym); lalt.release(downKeysym); ralt.release(downKeysym); } else { // This is not a Ctrl-Alt (AltGr) key vnclog.Print(8, _T("Ctrl-Alt not pressed, fake release any Ctrl key\n")); // There are no KeySym corresponding to control characters, e.g. Ctrl-F // The server has already known whether the Ctrl key is pressed from the previouse key event // So we are interested in the key that would be there if the Ctrl key were not pressed KBKeysState[VK_CONTROL] = KBKeysState[VK_LCONTROL] = KBKeysState[VK_RCONTROL] = 0; } int ret; if (storedDeadChar) { SHORT virtDeadKey; BYTE prevModifierState = 0; vnclog.Print(8, _T("[Storing base character modifier(s)]\n")); StoreModifier(&prevModifierState, KBKeysState); virtDeadKey = VkKeyScanW(storedDeadChar); vnclog.Print(8, _T("[A dead key was stored, restoring the dead key state:") _T(" 0x%02x (%c) using virtDeadKey 0x%02x] "), storedDeadChar, storedDeadChar, virtDeadKey); SetModifier(HIBYTE(virtDeadKey), KBKeysState); vnclog.Print(8, _T("\n")); ToUnicode((virtDeadKey & 0xff), 0, KBKeysState, ucsChar, (sizeof(ucsChar) / sizeof(WCHAR)), 0); vnclog.Print(8, _T("[Restoring base character modifier(s)] ")); SetModifier(prevModifierState, KBKeysState); vnclog.Print(8, _T("\n")); storedDeadChar = 0; ret = ToUnicode(virtKey, 0, KBKeysState, ucsChar, (sizeof(ucsChar) / sizeof(WCHAR)), 0); } else ret = ToUnicode(virtKey, 0, KBKeysState, ucsChar, (sizeof(ucsChar) / sizeof(WCHAR)), 0); if (ucsChar[0]==8364) { //euro // return; } if (ret < 0 || ret==2) { // It is a dead key vnclog.Print(8, _T("ToUnicode returns dead key: 0x%02x (%c) "), *ucsChar, *ucsChar); if (sendDeadKey) { // We try to look it up in our dead key table // Look up the desired code in the deadKeyMap table foundXCode = XK_VoidSymbol; for (UINT i = 0; i < (sizeof(deadKeyMap) / sizeof(vncDeadKeyMapping_t)); i++) { if (deadKeyMap[i].deadKeyChar == *ucsChar) { foundXCode = deadKeyMap[i].XCode; break; } } if (foundXCode != XK_VoidSymbol) { vnclog.Print(8, _T("-> deadKeyMap gives KeySym %u (0x%08x)\n"), foundXCode, foundXCode); pressKey(clientCon, extVkey, foundXCode); } else { vnclog.Print(8, _T("-> not in deadKeyMap\n")); } } else { storedDeadChar = *ucsChar; reset=true; vnclog.Print(8, _T("-> Store the dead key state, wait for next key-stroke\n")); } FlushDeadKey(KBKeysState); } else if (ret > 0) { vnclog.Print(8, _T("ToUnicode returns %d character(s):\n"), ret); for (int i = 0; i < ret; i++) { CARD32 xChar = UCS2X(*(ucsChar+i)); if (xChar != XK_VoidSymbol) { downUnicode[extVkey] = *(ucsChar+i); pressKey(clientCon, extVkey, xChar); } } } else { vnclog.Print(8, _T("No character is generated by this key event\n")); } #endif vnclog.Print(8, _T("\n")); };