I'm writing a logging service that may collect privileges of a process for the purpose of transmitting it to another computer. I use the following code to collect it:
HANDLE hToken;
if(OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
DWORD dwSize = 0;
if(!GetTokenInformation(hToken, TokenPrivileges, NULL, dwSize, &dwSize) &&
::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
BYTE* pb = new (std::nothrow) BYTE[dwSize];
if(pb)
{
TOKEN_PRIVILEGES* pTPs = (TOKEN_PRIVILEGES*)pb;
DWORD dwSize2;
if(GetTokenInformation(hToken, TokenPrivileges, pTPs, dwSize, &dwSize2) &&
dwSize2 <= dwSize)
{
//Got our BYTE array in 'pb' of size 'dwSize2' bytes
memcpy(pByteArrayToTransmit, pb, dwSize2);
}
delete[] pb;
}
}
CloseHandle(hToken);
}
But I'm curious, if I could pass the pByteArrayToTransmit array to another Windows computer and be able to convert it into a readable form using LookupPrivilegeName API?
PS. The reason I'm not calling LookupPrivilegeName on the client machine (where the data is being logged) is to save on the size of the logged data, since this process may repeat many times over.
From the documentation for LookupPrivilegeValue:
The LookupPrivilegeValue function retrieves the locally unique identifier (LUID) used on a specified system to locally represent the specified privilege name.
That strongly suggests that the LUIDs are different on each system. At the very least, there is no guarantee that they will be the same.
Addendum
Assuming that the logging system does not absolutely have to work under every conceivable circumstance, and assuming that the logs will be analyzed in software and that you can update the analysis software every time a new version of Windows comes out, and provided the logs also include the Windows version, it should be safe enough to compress this information into a single 64-bit bitmap as Eryksun suggests in the comments.
If you want to play it as safe as possible, I suggest a bitmap followed by an optional variable-length field. You can have a fixed table of strings (one for each privilege name that we know about) with one bit in the bitmap for each string. If all the privilege names you see are in the table, the bitmap is all you need.
If you see one or more privilege names you didn't know about, set the top bit in the bitmap to indicate that there is more data, then add one or more null-terminated strings, with an additional null at the end to indicate the end of the list.
yes, you can do this. privilege values is invariant.
#define SE_MIN_WELL_KNOWN_PRIVILEGE (2L)
#define SE_CREATE_TOKEN_PRIVILEGE (2L)
#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE (3L)
#define SE_LOCK_MEMORY_PRIVILEGE (4L)
#define SE_INCREASE_QUOTA_PRIVILEGE (5L)
#define SE_MACHINE_ACCOUNT_PRIVILEGE (6L)
#define SE_TCB_PRIVILEGE (7L)
#define SE_SECURITY_PRIVILEGE (8L)
#define SE_TAKE_OWNERSHIP_PRIVILEGE (9L)
#define SE_LOAD_DRIVER_PRIVILEGE (10L)
#define SE_SYSTEM_PROFILE_PRIVILEGE (11L)
#define SE_SYSTEMTIME_PRIVILEGE (12L)
#define SE_PROF_SINGLE_PROCESS_PRIVILEGE (13L)
#define SE_INC_BASE_PRIORITY_PRIVILEGE (14L)
#define SE_CREATE_PAGEFILE_PRIVILEGE (15L)
#define SE_CREATE_PERMANENT_PRIVILEGE (16L)
#define SE_BACKUP_PRIVILEGE (17L)
#define SE_RESTORE_PRIVILEGE (18L)
#define SE_SHUTDOWN_PRIVILEGE (19L)
#define SE_DEBUG_PRIVILEGE (20L)
#define SE_AUDIT_PRIVILEGE (21L)
#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L)
#define SE_CHANGE_NOTIFY_PRIVILEGE (23L)
#define SE_REMOTE_SHUTDOWN_PRIVILEGE (24L)
#define SE_UNDOCK_PRIVILEGE (25L)
#define SE_SYNC_AGENT_PRIVILEGE (26L)
#define SE_ENABLE_DELEGATION_PRIVILEGE (27L)
#define SE_MANAGE_VOLUME_PRIVILEGE (28L)
#define SE_IMPERSONATE_PRIVILEGE (29L)
#define SE_CREATE_GLOBAL_PRIVILEGE (30L)
#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE (31L)
#define SE_RELABEL_PRIVILEGE (32L)
#define SE_INC_WORKING_SET_PRIVILEGE (33L)
#define SE_TIME_ZONE_PRIVILEGE (34L)
#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE (35L)
#define SE_MAX_WELL_KNOWN_PRIVILEGE (SE_CREATE_SYMBOLIC_LINK_PRIVILEGE)
Related
I'm implementing a native host for a browser extension. I designed my implementation around std::cin instead of C-style getchar()
The issue here is that std::cin not opened in binary mode and this has effects on Windows based hosts because Chrome browser don't work well with Windows style \r\n hence I have to read it in binary mode.
To read in binary mode, I have to use _setmode(_fileno(stdin), _O_BINARY);
My IDE can't find definition for _fileno and I found that the workaround is to use the following macro,
#if !defined(_fileno)
#define _fileno(__F) ((__F)->_file)
#endif
However, I'm not confident enough with this macro. I believe something is wrong, but I'm using the latest MinGW compiler and not sure why it's not defined.
Update: it seems the function is behind a __STRICT_ANSI__ and I have no idea how to disable it.
Whatever, the program compiles fine and the browser starts it, and when I send message from browser, the application able to read the length of message, and when it try to read the content, the std::cin.read() operation inserts nothing to the buffer vector and the message is not null terminated, but I don't think that causing the issue.
I also made an attempt to send a dummy message to browser without reading but it seems freezing the browser.
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#ifdef __WIN32
#include <fcntl.h>
#include <io.h>
#endif
#if !defined(_fileno)
#define _fileno(__F) ((__F)->_file)
#endif
enum class Platforms {
macOS = 1,
Windows = 2,
Linux = 3
};
Platforms platform;
#ifdef __APPLE__
constexpr Platforms BuildOS = Platforms::macOS;
#elif __linux__
constexpr Platforms BuildOS = Platforms::Linux;
#elif __WIN32
constexpr Platforms BuildOS = Platforms::Windows;
#endif
void sendMessage(std::string message) {
auto *data = message.data();
auto size = uint32_t(message.size());
std::cout.write(reinterpret_cast<char *>(&size), 4);
std::cout.write(data, size);
std::cout.flush();
}
int main() {
if constexpr(BuildOS == Platforms::Windows) {
// Chrome doesn't deal well with Windows style \r\n
_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);
}
while(true) {
std::uint32_t messageLength;
// First Four contains message legnth
std::cin.read(reinterpret_cast<char*>(&messageLength), 4);
if (std::cin.eof())
{
break;
}
std::vector<char> buffer;
// Allocate ahead
buffer.reserve(std::size_t(messageLength) + 1);
std::cin.read(&buffer[0], messageLength);
std::string message(buffer.data(), buffer.size());
sendMessage("{type: 'Hello World'}");
}
}
Solution:
buffer.reserve(std::size_t(messageLength) + 1);
should be
buffer.resize(std::size_t(messageLength) + 1);
or we can presize the buffer during construction with
std::vector<char> buffer(messageLength +1);
Problem Explanation:
buffer.reserve(std::size_t(messageLength) + 1);
reserves capacity but doesn't change the size of the vector, so technically
std::cin.read(&buffer[0], messageLength);`
is illegal, and at
std::string message(buffer.data(), buffer.size());`
buffer.size() is still 0.
Yes, I mean real MS-DOS, not Windows' cmd.exe shell console.
Is there a way to check if a key is down in MS-DOS, analogically to the GetAsyncKeyState() function in WinAPI?
Currently I'm using kbhit() and getch(), but it's really slow, has a delay after the first character, doesn't allow multiple keys at the same time etc.
I'm using Turbo C++ 3.1. Can anyone help?
(by the way, don't ask why I'm coding my game on such an ancient system)
There is no function provided by Turbo C++, MS-DOS or the BIOS that corresponds to Windows function GetAsyncKeyState. The BIOS only keeps track of which modifier keys (Shift, Ctrl, or Alt) are held down, it doesn't track any of the other keys. If you want to do that you need to talk to the keyboard controller directly and monitor the make (key pressed) and break (key released) scan codes it receives from the keyboard.
To do that you'll need to hook the keyboard interrupt (IRQ 1, INT 0x09), read the scancodes from the keyboard controller and then update your own keyboard state table.
Here's a simple program that demonstrates how do this:
#include <conio.h>
#include <dos.h>
#include <stdio.h>
unsigned char normal_keys[0x60];
unsigned char extended_keys[0x60];
static void interrupt
keyb_int() {
static unsigned char buffer;
unsigned char rawcode;
unsigned char make_break;
int scancode;
rawcode = inp(0x60); /* read scancode from keyboard controller */
make_break = !(rawcode & 0x80); /* bit 7: 0 = make, 1 = break */
scancode = rawcode & 0x7F;
if (buffer == 0xE0) { /* second byte of an extended key */
if (scancode < 0x60) {
extended_keys[scancode] = make_break;
}
buffer = 0;
} else if (buffer >= 0xE1 && buffer <= 0xE2) {
buffer = 0; /* ingore these extended keys */
} else if (rawcode >= 0xE0 && rawcode <= 0xE2) {
buffer = rawcode; /* first byte of an extended key */
} else if (scancode < 0x60) {
normal_keys[scancode] = make_break;
}
outp(0x20, 0x20); /* must send EOI to finish interrupt */
}
static void interrupt (*old_keyb_int)();
void
hook_keyb_int(void) {
old_keyb_int = getvect(0x09);
setvect(0x09, keyb_int);
}
void
unhook_keyb_int(void) {
if (old_keyb_int != NULL) {
setvect(0x09, old_keyb_int);
old_keyb_int = NULL;
}
}
int
ctrlbrk_handler(void) {
unhook_keyb_int();
_setcursortype(_NORMALCURSOR);
return 0;
}
static
putkeys(int y, unsigned char const *keys) {
int i;
gotoxy(1, y);
for (i = 0; i < 0x30; i++) {
putch(keys[i] + '0');
}
}
void
game(void) {
_setcursortype(_NOCURSOR);
clrscr();
while(!normal_keys[1]) {
putkeys(1, normal_keys);
putkeys(2, normal_keys + 0x30);
putkeys(4, extended_keys);
putkeys(5, extended_keys + 0x30);
}
gotoxy(1, 6);
_setcursortype(_NORMALCURSOR);
}
int
main() {
ctrlbrk(ctrlbrk_handler);
hook_keyb_int();
game();
unhook_keyb_int();
return 0;
}
The code above has been compiled with Borland C++ 3.1 and tested under DOSBox and MS-DOS 6.11 running under VirtualBox. It shows the current state of keyboard a string of 0's and 1's, a 1 indicating that the key corresponding to that position's scan code is being pressed. Press the ESC key to exit the program.
Note that the program doesn't chain the original keyboard handler, so the normal MS-DOS and BIOS keyboard functions will not work while the keyboard interrupt is hooked. Also note that it restores original keyboard handler before exiting. This is critical because MS-DOS won't do this itself. It also properly handles extended keys that send two byte scan codes, which was the problem with the code in the question you linked to in your answer here.
Why are you coding your game on su…just kidding!
In MS-DOS, the "API" functions are implemented as interrupt servicers. In x86 assembly language, you use the INT instruction and specify the number of the interrupt that you want to execute. Most of the interrupts require that their "parameters" be set in certain registers before executing the INT. After the INT instruction returns control to your code, its result(s) will have been placed in certain registers and/or flags, as defined by the interrupt call's documentation.
I have no idea how Turbo C++ implements interrupts, since that pre-dates my involvement with programming, but I do know that it allows you to execute them. Google around for the syntax, or check your Turbo C++ documentation.
Knowing that these are interrupts will get you 90% of the way to a solution when you're searching. Ralf Brown compiled and published a famous list of DOS and BIOS interrupt codes. They should also be available in any book on DOS programming—if you're serious about retro-programming, you should definitely consider getting your hands on one. A used copy on Amazon should only set you back a few bucks. Most people consider these worthless nowadays.
Here is a site that lists the sub-functions available for DOS interrupt 21h. The ones that would be relevant to your use are 01, 06, 07, and 08. These are basically what the C standard library functions like getch are going to be doing under the hood. I find it difficult to imagine, but I have heard reports that programmers back in the day found it faster to call the DOS interrupts directly. The reason I question that is that I can't imagine the runtime library implementers would have been so stupid as to provide unnecessarily slow implementations. But maybe they were.
If the DOS interrupts are still too slow for you, your last recourse would be to use BIOS interrupts directly. This might make an appreciable difference in speed because you're bypassing every abstraction layer possible. But it does make your program significantly less portable, which is the reason operating systems like DOS provided these higher level function calls to begin with. Again, check Ralf Brown's list for the interrupt that is relevant to your use. For example, INT 16 with the 01h sub-function.
pressing on the arrows keys shoots two Keyboard interrupts ? ( int 09h )
The implementation in this question works just fine, so if anyone for some reason wants a ready function for this, here you go:
unsigned char read_scancode() {
unsigned char res;
_asm {
in al, 60h
mov res, al
in al, 61h
or al, 128
out 61h, al
xor al, 128
out 61h, al
}
return res;
}
(EDIT: corrected char to unsigned char so putting this function's return value in "if" statements with things like scancode & 0x80 actually works)
When a key is pressed, it returns one of the scancodes listed there http://www.ctyme.com/intr/rb-0045.htm and when it's released it returns the same scancode but ORed with 80h.
If you actually run this in a game loop you'll eventually overflow the BIOS keyboard buffer and the computer will beep at you. A way to free the keyboard buffer is of course while(kbhit()) getch(); but since we are on 286 realmode and we have all of our hardware to f*ck with, here's a more low-level solution:
void free_keyb_buf() {
*(char*)(0x0040001A) = 0x20;
*(char*)(0x0040001C) = 0x20;
}
If you're looking for explanation how and why does it work, here you go:
The BIOS keyboard buffer starts at 0040:001Ah and looks like this: 2-byte "head" pointer, 2-byte "tail" pointer and 32 bytes of 2-byte scancodes. The "tail" pointer indicates where to start reading from the keyboard buffer, the "head" pointer indicates where to stop. So by setting both of these to 0x20 (so they actually point to 0040:0020h) we basically trick the computer into thinking that there are no new keystrokes ready for extraction.
So, I've gone through all this stuff somewhat recently, and just happen to have the code that you need. (Also, I will link you some great books to get information from in pdf format.)
So, the way that this works, is you need to overwrite the Interrupt Vector Table in memory at index 9h. The Interrupt Vector Table is simply a table of memory addresses that point to a piece of code to run when that interrupt is triggered (these are called interrupt handler routines or ISRs). Interrupt 9h is triggered when the keyboard controller has a scancode ready for use.
Anyways, we first need to overwrite the old int9h ISR by calling the KeyboardInstallDriver() function. Now, when int9h is triggered, the KeyboardIsr() function is called, and it gets the scancode from the keyboard controller, and sets a value in the keyStates[] array to either 1 (KEY_PRESSED) or 0 (KEY_RELEASED) based on the value of the scan code that was retrieved from the keyboard controller.
After the corresponding value in the keyStates[] array has been set, then you can call KeyboardGetKey() giving it the scancode of the key that you want to know the state of, and it will look it up in the keyStates[] array and return whatever the state is.
There is a lot of details to this, but it's WAY too much to write on here. All the details can be found in the books that I will link here:
IBM PC Technical Reference, IBM PC XT Technical Reference,
IBM PC AT Technical Reference, Black Art of 3D Game Programming
Hopefully those links stay active for a while. Also, the "Black Art of 3D Game Programming" book is not always completely accurate on every little detail. Sometimes there are typos, and sometimes there is misinformation, but the IBM Technical References have all the details (even if they are a bit cryptic at times), but they have no example code. Use the book to get the general idea, and use the references to get the details.
Here is my code for getting input from the keyboard:
(it's not completely finished for all the possible keys and certain other things, but it works quite well for most programs and games.)
Also, there is some code to handle the "extended" keys. The extended keys have 0xE0 prefixed to their regular scan code. There are even more crazy details with this, so I'm not gonna cover it, but, there is the mostly working code, anyways.
keyboard.h
#ifndef KEYBOARD_H_INCLUDED
#define KEYBOARD_H_INCLUDED
#include "keyboard_scan_codes.h"
unsigned char KeyboardGetKey(unsigned int scanCode);
void KeyboardClearKeys();
void KeyboardInstallDriver();
void KeyboardUninstallDriver();
void KeyboardDumpScancodeLog();
#endif // KEYBOARD_H_INCLUDED
keyboard.c
#define MAX_SCAN_CODES 256
#define KEYBOARD_CONTROLLER_OUTPUT_BUFFER 0x60
#define KEYBOARD_CONTROLLER_STATUS_REGISTER 0x64
#define KEY_PRESSED 1
#define KEY_RELEASED 0
#define PIC_OPERATION_COMMAND_PORT 0x20
#define KEYBOARD_INTERRUPT_VECTOR 0x09
// PPI stands for Programmable Peripheral Interface (which is the Intel 8255A chip)
// The PPI ports are only for IBM PC and XT, however port A is mapped to the same
// I/O address as the Keyboard Controller's (Intel 8042 chip) output buffer for compatibility.
#define PPI_PORT_A 0x60
#define PPI_PORT_B 0x61
#define PPI_PORT_C 0x62
#define PPI_COMMAND_REGISTER 0x63
#include <dos.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include "keyboard.h"
void interrupt (*oldKeyboardIsr)() = (void *)0;
unsigned char keyStates[MAX_SCAN_CODES];
unsigned char keyCodeLog[256] = {0};
unsigned char keyCodeLogPosition = 0;
static unsigned char isPreviousCodeExtended = 0;
unsigned char KeyboardGetKey(unsigned int scanCode)
{
// Check for the extended code
if(scanCode >> 8 == 0xE0)
{
// Get rid of the extended code
scanCode &= 0xFF;
return keyStates[scanCode + 0x7F];
}
else
{
return keyStates[scanCode];
}
}
void KeyboardClearKeys()
{
memset(&keyStates[0], 0, MAX_SCAN_CODES);
}
void interrupt far KeyboardIsr()
{
static unsigned char scanCode;
unsigned char ppiPortB;
_asm {
cli // disable interrupts
};
/* The keyboard controller, by default, will send scan codes
// in Scan Code Set 1 (reference the IBM Technical References
// for a complete list of scan codes).
//
// Scan codes in this set come as make/break codes. The make
// code is the normal scan code of the key, and the break code
// is the make code bitwise "OR"ed with 0x80 (the high bit is set).
//
// On keyboards after the original IBM Model F 83-key, an 0xE0
// is prepended to some keys that didn't exist on the original keyboard.
//
// Some keys have their scan codes affected by the state of
// the shift, and num-lock keys. These certain
// keys have, potentially, quite long scan codes with multiple
// possible 0xE0 bytes along with other codes to indicate the
// state of the shift, and num-lock keys.
//
// There are two other Scan Code Sets, Set 2 and Set 3. Set 2
// was introduced with the IBM PC AT, and Set 3 with the IBM
// PS/2. Set 3 is by far the easiest and most simple set to work
// with, but not all keyboards support it.
//
// Note:
// The "keyboard controller" chip is different depending on
// which machine is being used. The original IBM PC uses the
// Intel 8255A-5, while the IBM PC AT uses the Intel 8042 (UPI-42AH).
// On the 8255A-5, port 0x61 can be read and written to for various
// things, one of which will clear the keyboard and disable it or
// re enable it. There is no such function on the AT and newer, but
// it is not needed anyways. The 8042 uses ports 0x60 and 0x64. Both
// the 8255A-5 and the 8042 give the scan codes from the keyboard
// through port 0x60.
// On the IBM PC and XT and compatibles, you MUST clear the keyboard
// after reading the scancode by reading the value at port 0x61,
// flipping the 7th bit to a 1, and writing that value back to port 0x61.
// After that is done, flip the 7th bit back to 0 to re-enable the keyboard.
//
// On IBM PC ATs and newer, writing and reading port 0x61 does nothing (as far
// as I know), and using it to clear the keyboard isn't necessary.*/
scanCode = 0;
ppiPortB = 0;
ppiPortB = inp(PPI_PORT_B); // get the current settings in PPI port B
scanCode = inp(KEYBOARD_CONTROLLER_OUTPUT_BUFFER); // get the scancode waiting in the output buffer
outp(PPI_PORT_B, ppiPortB | 0x80); // set the 7th bit of PPI port B (clear keyboard)
outp(PPI_PORT_B, ppiPortB); // clear the 7th bit of the PPI (enable keyboard)
// Log scancode
keyCodeLog[keyCodeLogPosition] = scanCode;
if(keyCodeLogPosition < 255)
{
++keyCodeLogPosition;
}
// Check to see what the code was.
// Note that we have to process the scan code one byte at a time.
// This is because we can't get another scan code until the current
// interrupt is finished.
switch(scanCode)
{
case 0xE0:
// Extended scancode
isPreviousCodeExtended = 1;
break;
default:
// Regular scancode
// Check the high bit, if set, then it's a break code.
if(isPreviousCodeExtended)
{
isPreviousCodeExtended = 0;
if(scanCode & 0x80)
{
scanCode &= 0x7F;
keyStates[scanCode + 0x7F] = KEY_RELEASED;
}
else
{
keyStates[scanCode + 0x7F] = KEY_PRESSED;
}
}
else if(scanCode & 0x80)
{
scanCode &= 0x7F;
keyStates[scanCode] = KEY_RELEASED;
}
else
{
keyStates[scanCode] = KEY_PRESSED;
}
break;
}
// Send a "Non Specific End of Interrupt" command to the PIC.
// See Intel 8259A datasheet for details.
outp(PIC_OPERATION_COMMAND_PORT, 0x20);
_asm
{
sti // enable interrupts
};
}
void KeyboardInstallDriver()
{
// Make sure the new ISR isn't already in use.
if(oldKeyboardIsr == (void *)0)
{
oldKeyboardIsr = _dos_getvect(KEYBOARD_INTERRUPT_VECTOR);
_dos_setvect(KEYBOARD_INTERRUPT_VECTOR, KeyboardIsr);
}
}
void KeyboardUninstallDriver()
{
// Make sure the new ISR is in use.
if(oldKeyboardIsr != (void *)0)
{
_dos_setvect(KEYBOARD_INTERRUPT_VECTOR, oldKeyboardIsr);
oldKeyboardIsr = (void *)0;
}
}
void KeyboardDumpScancodeLog()
{
FILE *keyLogFile = fopen("keylog.hex", "w+b");
if(!keyLogFile)
{
printf("ERROR: Couldn't open file for key logging!\n");
}
else
{
int i;
for(i = 0; i < 256; ++i)
{
fputc(keyCodeLog[i], keyLogFile);
}
fclose(keyLogFile);
}
}
keyboard_scan_codes.h (simply defines all the scancodes to the qwerty button layout)
#ifndef KEYBOARD_SCAN_CODES_H_INCLUDED
#define KEYBOARD_SCAN_CODES_H_INCLUDED
// Original 83 Keys from the IBM 83-key Model F keyboard
#define SCAN_NONE 0x00
#define SCAN_ESC 0x01
#define SCAN_1 0x02
#define SCAN_2 0x03
#define SCAN_3 0x04
#define SCAN_4 0x05
#define SCAN_5 0x06
#define SCAN_6 0x07
#define SCAN_7 0x08
#define SCAN_8 0x09
#define SCAN_9 0x0A
#define SCAN_0 0x0B
#define SCAN_MINUS 0x0C
#define SCAN_EQUALS 0x0D
#define SCAN_BACKSPACE 0x0E
#define SCAN_TAB 0x0F
#define SCAN_Q 0x10
#define SCAN_W 0x11
#define SCAN_E 0x12
#define SCAN_R 0x13
#define SCAN_T 0x14
#define SCAN_Y 0x15
#define SCAN_U 0x16
#define SCAN_I 0x17
#define SCAN_O 0x18
#define SCAN_P 0x19
#define SCAN_LEFT_BRACE 0x1A
#define SCAN_RIGHT_BRACE 0x1B
#define SCAN_ENTER 0x1C
#define SCAN_LEFT_CONTROL 0x1D
#define SCAN_A 0x1E
#define SCAN_S 0x1F
#define SCAN_D 0x20
#define SCAN_F 0x21
#define SCAN_G 0x22
#define SCAN_H 0x23
#define SCAN_J 0x24
#define SCAN_K 0x25
#define SCAN_L 0x26
#define SCAN_SEMICOLON 0x27
#define SCAN_APOSTROPHE 0x28
#define SCAN_ACCENT 0x29
#define SCAN_TILDE 0x29 // Duplicate of SCAN_ACCENT with popular Tilde name.
#define SCAN_LEFT_SHIFT 0x2A
#define SCAN_BACK_SLASH 0x2B
#define SCAN_Z 0x2C
#define SCAN_X 0x2D
#define SCAN_C 0x2E
#define SCAN_V 0x2F
#define SCAN_B 0x30
#define SCAN_N 0x31
#define SCAN_M 0x32
#define SCAN_COMMA 0x33
#define SCAN_PERIOD 0x34
#define SCAN_FORWARD_SLASH 0x35
#define SCAN_RIGHT_SHIFT 0x36
#define SCAN_KP_STAR 0x37
#define SCAN_KP_MULTIPLY 0x37 // Duplicate of SCAN_KP_STAR
#define SCAN_LEFT_ALT 0x38
#define SCAN_SPACE 0x39
#define SCAN_CAPS_LOCK 0x3A
#define SCAN_F1 0x3B
#define SCAN_F2 0x3C
#define SCAN_F3 0x3D
#define SCAN_F4 0x3E
#define SCAN_F5 0x3F
#define SCAN_F6 0x40
#define SCAN_F7 0x41
#define SCAN_F8 0x42
#define SCAN_F9 0x43
#define SCAN_F10 0x44
#define SCAN_NUM_LOCK 0x45
#define SCAN_SCROLL_LOCK 0x46
#define SCAN_KP_7 0x47
#define SCAN_KP_8 0x48
#define SCAN_KP_9 0x49
#define SCAN_KP_MINUS 0x4A
#define SCAN_KP_4 0x4B
#define SCAN_KP_5 0x4C
#define SCAN_KP_6 0x4D
#define SCAN_KP_PLUS 0x4E
#define SCAN_KP_1 0x4F
#define SCAN_KP_2 0x50
#define SCAN_KP_3 0x51
#define SCAN_KP_0 0x52
#define SCAN_KP_PERIOD 0x53
// Extended keys for the IBM 101-key Model M keyboard.
#define SCAN_RIGHT_ALT 0xE038
#define SCAN_RIGHT_CONTROL 0xE01D
#define SCAN_LEFT_ARROW 0xE04B
#define SCAN_RIGHT_ARROW 0xE04D
#define SCAN_UP_ARROW 0xE048
#define SCAN_DOWN_ARROW 0xE050
#define SCAN_NUMPAD_ENTER 0xE01C
#define SCAN_INSERT 0xE052
#define SCAN_DELETE 0xE053
#define SCAN_HOME 0xE047
#define SCAN_END 0xE04F
#define SCAN_PAGE_UP 0xE049
#define SCAN_PAGE_DOWN 0xE051
#define SCAN_KP_FORWARD_SLASH 0xE035
#define SCAN_PRINT_SCREEN 0xE02AE037
#endif // KEYBOARD_SCAN_CODES_H_INCLUDED
For my informatics studies I have to write a Space Invaders Clone using Windows API.
One of our tasks is to write and display a Highscore list which works very well.
If you have lost all credits you should be able to write your name into the highscore list (if you have enough points).
Windows API has no easy possibility to get a text input so I wrote an own version that works not as I want it to.
I use pName to write the name and save it into an array called "Name".
This array is used to save the Highscore and the name together into the Highscore.txt.
The Saving progress is working fine so far.
But my problem now is:
I'm able to write letters but they're sorted automatically.
So if i input: asdf
it is sorted: adfs
I can't see any code that does something like that so where's my fault?
Thank you guys!
Greets Michael
bool HighScore::EnterName(HDC hdc)
{
#define VK_A 0x41
#define VK_B 0x42
#define VK_C 0x43
#define VK_D 0x44
#define VK_E 0x45
#define VK_F 0x46
#define VK_G 0x47
#define VK_H 0x48
#define VK_I 0x49
#define VK_J 0x4A
#define VK_K 0x4B
#define VK_L 0x4C
#define VK_M 0x4D
#define VK_N 0x4E
#define VK_O 0x4F
#define VK_P 0x50
#define VK_Q 0x51
#define VK_R 0x52
#define VK_S 0x53
#define VK_T 0x54
#define VK_U 0x55
#define VK_V 0x56
#define VK_W 0x57
#define VK_X 0x58
#define VK_Y 0x59
#define VK_Z 0x5A
string pName;
if(GetKeyState(VK_A)) pName.append("A"); if(GetKeyState(VK_B)) pName.append("B");
if(GetKeyState(VK_C)) pName.append("C"); if(GetKeyState(VK_D)) pName.append("D");
if(GetKeyState(VK_E)) pName.append("E"); if(GetKeyState(VK_F)) pName.append("F");
if(GetKeyState(VK_G)) pName.append("G"); if(GetKeyState(VK_H)) pName.append("H");
if(GetKeyState(VK_I)) pName.append("I"); if(GetKeyState(VK_J)) pName.append("J");
if(GetKeyState(VK_K)) pName.append("K"); if(GetKeyState(VK_L)) pName.append("L");
if(GetKeyState(VK_M)) pName.append("M"); if(GetKeyState(VK_N)) pName.append("N");
if(GetKeyState(VK_O)) pName.append("O"); if(GetKeyState(VK_P)) pName.append("P");
if(GetKeyState(VK_Q)) pName.append("Q"); if(GetKeyState(VK_R)) pName.append("R");
if(GetKeyState(VK_S)) pName.append("S"); if(GetKeyState(VK_T)) pName.append("T");
if(GetKeyState(VK_U)) pName.append("U"); if(GetKeyState(VK_V)) pName.append("V");
if(GetKeyState(VK_W)) pName.append("W"); if(GetKeyState(VK_X)) pName.append("X");
if(GetKeyState(VK_Y)) pName.append("Y"); if(GetKeyState(VK_Z)) pName.append("Z");
TextOut(hdc, 20, 200, "TRAGE DEINEN NAMEN EIN",22);
if(GetAsyncKeyState(VK_BACK)) pName.erase(pName.begin() + pName.length()-1);
sprintf(Name,"%s", pName.c_str());
TextOut(hdc, 50,250,Name, strlen(Name));
return true;
}
Normally text input in Windows is done with an edit control, that allows the user to type into the edit control. To get the contents of the control, you use the GetWindowText API passing in the HWND of the edit control.
Forget about GetKeyState.
If you're doing all custom rendering, handle the WM_CHAR message.
If you can use widgets (child windows), the the EDIT control as Larry suggested would be best.
I found a soultion that was pretty easy.
I made a big fault that I couldn't see after hours of programming:
I initiate my string pName again ang again from the beginning. So I moved it to my constructor and now it all works fine.
To get a better sensibility, you have to change
(GetKeyState(VK_LETTER))
to
(HIWORD(GetAsyncKeyState(VK_LETTER)))
Now it works much better!
I need a cross platform solution for clearing the console in both Linux and Windows written in C++. Are there any functions in doing this? Also make note that I don't want the end-user programmer to have to change any code in my program to get it to clear for Windows vs Linux (for example if it has to pick between two functions then the decision has to be made at run-time or at compile-time autonomously).
There is no generic command to clear the console on both platforms.
#include <cstdlib>
void clear_screen()
{
#ifdef WINDOWS
std::system("cls");
#else
// Assume POSIX
std::system ("clear");
#endif
}
Short answer: you can't.
Longer answer: Use a curses library (ncurses on Unix, pdcurses on Windows). NCurses should be available through your package manager, and both ncurses and pdcurses have the exact same interface (pdcurses can also create windows independently from the console that behave like console windows).
Most difficult answer: Use #ifdef _WIN32 and stuff like that to make your code act differently on different operating systems.
On linux it's possible to clear the console. The finest way is to write the following escape sequence to stdout:
write(1,"\E[H\E[2J",7);
which is what /usr/bin/clear does, without the overhead of creating another process.
A simple trick: Why not checking the OS type by using macros in combination with using the system() command for clearing the console?
This way, you are going to execute a system command with the appropriate console command as parameter.
#ifdef _WIN32
#define CLEAR "cls"
#else //In any other OS
#define CLEAR "clear"
#endif
//And in the point you want to clear the screen:
//....
system(CLEAR);
//....
Short answer
void cls(void)
{
system("cls||clear");
return;
}
Long answer, please read:
system("pause") clarification
The question as posted is unanswerable, because it imposes impossible restrictions. "Clearing the screen" is a very different action across different operating systems, and how one does it is operating system specific. See this Frequently Given Answer for a full explanation of how to do it on several popular platforms with "consoles" and platforms with "terminals". You'll also find in the same place some explanation of the common mistakes to avoid, several of which are — alas! — given above as answers.
This is how you do it on any other platform but it doesn't work in Windows:
cout << "\f";
Perhaps you'll need to make a conditional compilation:
void clrscr()
{
#ifdef _WIN32
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord = {0, 0};
DWORD count;
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hStdOut, &csbi);
FillConsoleOutputCharacter(hStdOut, ' ',
csbi.dwSize.X * csbi.dwSize.Y,
coord, &count);
SetConsoleCursorPosition(hStdOut, coord);
#else
cout << "\f";
#endif
}
I know this isn't answering my own question but!
This works for Windows (#include <windows.h>):
void clrscr()
{
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord = {0, 0};
DWORD count;
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hStdOut, &csbi);
FillConsoleOutputCharacter(hStdOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
SetConsoleCursorPosition(hStdOut, coord);
}
Well there is a very close alternative to clearing the screen. You could try using a for loop that repeats new lines a lot. For example:
for (i = 0; i < 100000; i++)
{
printf ("\n\n\n\n\n");
}
After you do this loop the terminal wan't allow you to scroll back to where you were at the top, an unprofessional approach with common sense pretty much. It does not directly answer what you are asking but it can work.
This code clears the console in BOTH Windows and Unix (Although it's actually compiled differently):
// File: clear_screen.h
#ifndef _CLEAR_SCREEN_H
#define _CLEAR_SCREEN_H
void clearScreen(void); /* Clears the screen */
#endif /* _CLEAR_SCREEN_H */
// File: clear_screen.c
#ifdef _WIN32
#include <windows.h>
void clearScreen(void) {
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
COORD topLeft = {0, 0};
DWORD dwCount, dwSize;
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hOutput, &csbi);
dwSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hOutput, 0x20, dwSize, topLeft, &dwCount);
FillConsoleOutputAttribute(hOutput, 0x07, dwSize, topLeft, &dwCount);
SetConsoleCursorPosition(hOutput, topLeft);
}
#endif /* _WIN32 */
#ifdef __unix__
#include <stdio.h>
void clearScreen(void) {
printf("\x1B[2J");
}
#endif /* __unix__ */
As others have already said, there's no way to have one identical piece of code that clears the console on both Windows and Linux.
I'll also strongly recommend against using std::system:
it makes your program vulnerable to attacks; what if someone replaced clear/cls with their own malicious program
as a consequence of the above, antivirus programs hate std::system. If your code uses it, the resulting binary may test positive for virus even if it's meant to be harmless. (Note that it is not actually harmless.)
Here's my solution:
#ifdef _WIN32
#include <Windows.h>
#endif
void clrscr() {
#ifdef _WIN32
COORD tl = { 0,0 };
CONSOLE_SCREEN_BUFFER_INFO s;
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(console, &s);
DWORD written, cells = s.dwSize.X * s.dwSize.Y;
FillConsoleOutputCharacter(console, ' ', cells, tl, &written);
FillConsoleOutputAttribute(console, s.wAttributes, cells, tl, &written);
SetConsoleCursorPosition(console, tl);
#else
std::cout << "\033[2J\033[1; 1H";
#endif
}
You may follow the pattern shown above, and change the two code segments anyway you like.
Wouldn't
for (int i=0;i<1000;i++){cout<<endl;}
clear the screen in all OSes?
This should work if you're working on console
#include <conio.h>
int main()
{
clrscr();
}
I want to read status information that an application provides via shared memory. I want to use C++ in order to read the content of that named shared memory and then call it with pinvoke from a C#-class.
From the software I know that it has a certain file structure: A struct STATUS_DATA with an array of four structs of SYSTEM_CHARACTERISTICS.
I'm not (yet) familiar with C++, so I tried to follow msdn basically. To find the size of the file to be mapped, I added the sizes of the struct members as to be seen in the code below. This results in a ACCESS DENIED, so I figured, that the result based on the structs is too high. When I use sizeof(STATUS_DATA) (I added the struct to my source), it still ends up in an ACCESS DENIED. If I try something lower, like 1024 Bytes, only thing I can see in pbuf is a <, while debugging.
This is what I got so far:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <iostream>
#pragma comment(lib, "user32.lib")
using namespace std;
signed int BUF_SIZE = 4 * (10368 + 16 + 4 + 16 + 4 + 16 + 4 + 1 + 4); // sizeof(STATUS_DATA);
TCHAR szName[]=TEXT("ENGINE_STATUS");
int main()
{
HANDLE hMapFile;
unsigned char* pBuf;
hMapFile = OpenFileMapping(
FILE_MAP_READ, // read access
FALSE, // do not inherit the name
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not open file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (unsigned char*) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_READ, // read/write permission
0,
0,
BUF_SIZE); // 1024);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
I also made sure that this Shared Mem "is there" by following that hint. Can somebody give me a hint, what I'm missing? Thanks!
The last parameter to MapViewOfFile (dwNumberOfBytesToMap) must be less than the maximum size specified when the mapping was created. Since we don't know what that size is, it seems fair to assume that BUF_SIZE is exceeding it and 1024 isn't. Specifying 0 for this parameter is an easy way to map the entire file into a single view.
Most (all?) C++ debuggers will assume that a pointer to char is a null-terminated string, so when you try and view the mapped data it will only display up until the first byte that is zero. Depending on what data is in the file mapping, this could well be the second byte, which explains why you aren't seeing much information. You would be better to cast the returned pointer to STATUS_DATA* and viewing the individual members.
In short:
Specify zero (0) for dwNumberOfBytesToMap
Cast the returned pointer to STATUS_DATA* instead of unsigned char*