Last active
August 29, 2023 14:16
-
-
Save Nek-/118cc36d0d075febf614c53a48470490 to your computer and use it in GitHub Desktop.
Windows PHP FFI handle creation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
********You pressed A |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
define('STD_INPUT_HANDLE', -10); | |
// https://docs.microsoft.com/fr-fr/windows/console/setconsolemode | |
define('ENABLE_ECHO_INPUT', 0x0004); | |
define('ENABLE_PROCESSED_INPUT', 0x0001); | |
define('ENABLE_WINDOW_INPUT', 0x0008); | |
// https://docs.microsoft.com/fr-fr/windows/console/input-record-str | |
define('KEY_EVENT', 0x0001); | |
$windows = \FFI::load('windows.h'); | |
$handle = $windows->GetStdHandle(STD_INPUT_HANDLE); | |
$oldMode = $windows->new('DWORD'); | |
if(!$windows->GetConsoleMode($handle, \FFI::addr($oldMode))) { | |
echo "Failure A\n"; | |
exit; | |
} | |
$newConsoleMode = ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT; | |
if (!$windows->SetConsoleMode($handle, $newConsoleMode)) { | |
echo "Impossible to change the console mode\n"; | |
exit; | |
} | |
function printToCoordinates(int $x, int $y, string $text) { | |
//fprintf(STDOUT,"\x1b7\x1b[".$y.';'.$x.'f'.$text."\x1b8"); | |
fprintf(STDOUT, "\033[%d;%dH%s", $y, $x, $text); | |
} | |
$i = 0; | |
$bufferSize = $windows->new('DWORD'); | |
$s = '*'; | |
$arrayBufferSize = 128; | |
$inputBuffer = $windows->new("INPUT_RECORD[$arrayBufferSize]"); | |
$cNumRead = $windows->new('DWORD'); | |
fprintf(STDOUT,"\033[H\033[J"); | |
while ($i < 60) { | |
printToCoordinates($i, 5, $s); | |
$i++; | |
$windows->GetNumberOfConsoleInputEvents( | |
$handle, | |
\FFI::addr($bufferSize) | |
); | |
if ($bufferSize->cdata > 1) { | |
if (! $windows->ReadConsoleInputW( | |
$handle, // input buffer handle | |
$inputBuffer, // buffer to read into | |
$arrayBufferSize, // size of read buffer | |
\FFI::addr($cNumRead)) ) { // number of records read | |
echo "Read console input failing\n"; | |
exit; | |
} | |
for($j = $cNumRead->cdata - 1; $j >= 0; $j--) { | |
if ($inputBuffer[$j]->EventType === KEY_EVENT) { | |
$keyEvent = $inputBuffer[$j]->Event->KeyEvent; | |
if ($keyEvent->uChar->AsciiChar === 'a') { | |
echo "You pressed A\n"; | |
exit; | |
} | |
} | |
} | |
} | |
usleep(100000); | |
} | |
$windows->CloseHandle($handle); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define FFI_LIB "C:\\Windows\\System32\\kernel32.dll" | |
// Does FFI work on windows ? https://github.com/dstogov/php-ffi/issues/15 | |
// This is a microsoft specific type, here is its definition for gcc | |
// https://github.com/Alexpux/mingw-w64/blob/d0d7f784833bbb0b2d279310ddc6afb52fe47a46/mingw-w64-headers/crt/time.h#L36 | |
typedef unsigned short wchar_t; | |
// Source for data correpsondance | |
// https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types | |
typedef int BOOL; | |
typedef unsigned long DWORD; | |
typedef void *PVOID; | |
typedef PVOID HANDLE; | |
typedef DWORD *LPDWORD; | |
typedef unsigned short WORD; | |
typedef wchar_t WCHAR; | |
typedef short SHORT; | |
typedef unsigned int UINT; | |
typedef char CHAR; | |
typedef struct _COORD { | |
SHORT X; | |
SHORT Y; | |
} COORD, *PCOORD; | |
typedef struct _WINDOW_BUFFER_SIZE_RECORD { | |
COORD dwSize; | |
} WINDOW_BUFFER_SIZE_RECORD; | |
typedef struct _MENU_EVENT_RECORD { | |
UINT dwCommandId; | |
} MENU_EVENT_RECORD, *PMENU_EVENT_RECORD; | |
typedef struct _KEY_EVENT_RECORD { | |
BOOL bKeyDown; | |
WORD wRepeatCount; | |
WORD wVirtualKeyCode; | |
WORD wVirtualScanCode; | |
union { | |
WCHAR UnicodeChar; | |
CHAR AsciiChar; | |
} uChar; | |
DWORD dwControlKeyState; | |
} KEY_EVENT_RECORD; | |
typedef struct _MOUSE_EVENT_RECORD { | |
COORD dwMousePosition; | |
DWORD dwButtonState; | |
DWORD dwControlKeyState; | |
DWORD dwEventFlags; | |
} MOUSE_EVENT_RECORD; | |
typedef struct _FOCUS_EVENT_RECORD { | |
BOOL bSetFocus; | |
} FOCUS_EVENT_RECORD; | |
typedef struct _INPUT_RECORD { | |
WORD EventType; | |
union { | |
KEY_EVENT_RECORD KeyEvent; | |
MOUSE_EVENT_RECORD MouseEvent; | |
WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; | |
MENU_EVENT_RECORD MenuEvent; | |
FOCUS_EVENT_RECORD FocusEvent; | |
} Event; | |
} INPUT_RECORD; | |
typedef INPUT_RECORD *PINPUT_RECORD; | |
// Original definition is | |
// WINBASEAPI HANDLE WINAPI GetStdHandle (DWORD nStdHandle); | |
// https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-headers/include/processenv.h#L31 | |
HANDLE GetStdHandle(DWORD nStdHandle); | |
// https://docs.microsoft.com/fr-fr/windows/console/getconsolemode | |
BOOL GetConsoleMode( | |
/* _In_ */HANDLE hConsoleHandle, | |
/* _Out_ */ LPDWORD lpMode | |
); | |
// https://docs.microsoft.com/fr-fr/windows/console/setconsolemode | |
BOOL SetConsoleMode( | |
/* _In_ */ HANDLE hConsoleHandle, | |
/* _In_ */ DWORD dwMode | |
); | |
// https://docs.microsoft.com/fr-fr/windows/console/getnumberofconsoleinputevents | |
BOOL GetNumberOfConsoleInputEvents( | |
/* _In_ */ HANDLE hConsoleInput, | |
/* _Out_ */ LPDWORD lpcNumberOfEvents | |
); | |
// https://docs.microsoft.com/fr-fr/windows/console/readconsoleinput | |
BOOL ReadConsoleInputA( | |
/* _In_ */ HANDLE hConsoleInput, | |
/* _Out_ */ PINPUT_RECORD lpBuffer, | |
/* _In_ */ DWORD nLength, | |
/* _Out_ */ LPDWORD lpNumberOfEventsRead | |
); | |
BOOL ReadConsoleInputW( | |
/* _In_ */ HANDLE hConsoleInput, | |
/* _Out_ */ PINPUT_RECORD lpBuffer, | |
/* _In_ */ DWORD nLength, | |
/* _Out_ */ LPDWORD lpNumberOfEventsRead | |
); | |
BOOL CloseHandle(HANDLE hObject); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment