![]() |
ZenWINX Architecture - Reference Manual - Guides |
|
00001 /* 00002 * ZenWINX - WIndows Native eXtended library. 00003 * Copyright (c) 2007-2010 by Dmitri Arkhangelski (dmitriar@gmail.com). 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 00027 #include "ntndk.h" 00028 #include "zenwinx.h" 00029 00030 #define INTERNAL_BUFFER_SIZE 2048 00031 00032 int __stdcall kb_read(PKEYBOARD_INPUT_DATA pKID,int msec_timeout); 00033 void IntTranslateKey(PKEYBOARD_INPUT_DATA InputData, KBD_RECORD *kbd_rec); 00034 00040 void winx_print(char *string) 00041 { 00042 ANSI_STRING aStr; 00043 UNICODE_STRING uStr; 00044 int i, len; 00045 00046 /* never call winx_dbg_print_ex() here */ 00047 if(!string) return; 00048 RtlInitAnsiString(&aStr,string); 00049 if(RtlAnsiStringToUnicodeString(&uStr,&aStr,TRUE) == STATUS_SUCCESS){ 00050 NtDisplayString(&uStr); 00051 RtlFreeUnicodeString(&uStr); 00052 } else { 00053 len = strlen(string); 00054 for(i = 0; i < len; i ++) 00055 winx_putch(string[i]); 00056 } 00057 00058 } 00059 00065 int __cdecl winx_putch(int ch) 00066 { 00067 UNICODE_STRING uStr; 00068 short s[2]; 00069 00070 /* never call winx_dbg_print_ex() here */ 00071 s[0] = (short)ch; s[1] = 0; 00072 RtlInitUnicodeString(&uStr,s); 00073 NtDisplayString(&uStr); 00074 return ch; 00075 } 00076 00082 int __cdecl winx_puts(const char *string) 00083 { 00084 if(!string) return (-1); 00085 return winx_printf("%s\n",string) ? 0 : (-1); 00086 } 00087 00093 int __cdecl winx_printf(const char *format, ...) 00094 { 00095 va_list arg; 00096 int done; 00097 char *small_buffer; 00098 char *big_buffer = NULL; 00099 int size = INTERNAL_BUFFER_SIZE * 2; 00100 00101 /* never call winx_dbg_print_ex() here */ 00102 00103 if(!format) return 0; 00104 00105 small_buffer = winx_heap_alloc(INTERNAL_BUFFER_SIZE); 00106 if(!small_buffer){ 00107 DebugPrint("Not enough memory for winx_printf()!\n"); 00108 winx_print("\nNot enough memory for winx_printf()!\n"); 00109 return 0; 00110 } 00111 00112 /* prepare for _vsnprintf call */ 00113 va_start(arg,format); 00114 memset(small_buffer,0,INTERNAL_BUFFER_SIZE); 00115 done = _vsnprintf(small_buffer,INTERNAL_BUFFER_SIZE,format,arg); 00116 if(done == -1 || done == INTERNAL_BUFFER_SIZE){ 00117 /* buffer is too small; try to allocate two times larger */ 00118 do { 00119 big_buffer = winx_heap_alloc((SIZE_T)size); 00120 if(!big_buffer){ 00121 DebugPrint("Not enough memory for winx_printf()!\n"); 00122 winx_print("\nNot enough memory for winx_printf()!\n"); 00123 va_end(arg); 00124 winx_heap_free(small_buffer); 00125 return 0; 00126 } 00127 memset(big_buffer,0,size); 00128 done = _vsnprintf(big_buffer,size,format,arg); 00129 if(done != -1 && done != size) break; 00130 winx_heap_free(big_buffer); 00131 size = size << 1; 00132 if(!size){ 00133 DebugPrint("winx_printf() failed!\n"); 00134 winx_print("\nwinx_printf() failed!\n"); 00135 va_end(arg); 00136 winx_heap_free(small_buffer); 00137 return 0; 00138 } 00139 } while(1); 00140 } 00141 if(big_buffer){ 00142 winx_print(big_buffer); 00143 winx_heap_free(big_buffer); 00144 } else { 00145 winx_print(small_buffer); 00146 } 00147 va_end(arg); 00148 winx_heap_free(small_buffer); 00149 return done; 00150 } 00151 00165 int __cdecl winx_kbhit(int msec) 00166 { 00167 KEYBOARD_INPUT_DATA kbd; 00168 KBD_RECORD kbd_rec; 00169 00170 if(kb_read(&kbd,msec) < 0) return (-1); 00171 IntTranslateKey(&kbd,&kbd_rec); 00172 if(!kbd_rec.bKeyDown){ 00173 /*winx_printf("\nwinx_kbhit(): The key was released!\n");*/ 00174 return (-1); 00175 } 00176 return (int)kbd_rec.AsciiChar; 00177 } 00178 00192 int __cdecl winx_breakhit(int msec) 00193 { 00194 KEYBOARD_INPUT_DATA kbd; 00195 00196 if(kb_read(&kbd,msec) < 0) return (-1); 00197 if((kbd.Flags & KEY_E1) && (kbd.MakeCode == 0x1d)) return 0; 00198 /*winx_printf("\nwinx_breakhit(): Other key was pressed.\n");*/ 00199 return (-1); 00200 } 00201 00207 int __cdecl winx_getch(void) 00208 { 00209 KEYBOARD_INPUT_DATA kbd; 00210 KBD_RECORD kbd_rec; 00211 00212 do{ 00213 if(kb_read(&kbd,INFINITE) < 0) return (-1); 00214 IntTranslateKey(&kbd,&kbd_rec); 00215 } while(!kbd_rec.bKeyDown); 00216 return (int)kbd_rec.AsciiChar; 00217 } 00218 00226 int __cdecl winx_getche(void) 00227 { 00228 int ch; 00229 00230 ch = winx_getch(); 00231 if(ch != -1 && ch != 0 && ch != 0x08) /* skip backspace */ 00232 winx_putch(ch); 00233 return ch; 00234 } 00235 00248 int __cdecl winx_gets(char *string,int n) 00249 { 00250 int i; 00251 int ch; 00252 00253 if(!string){ 00254 winx_printf("\nwinx_gets() invalid string!\n"); 00255 return (-1); 00256 } 00257 if(n <= 0){ 00258 winx_printf("\nwinx_gets() invalid string length %d!\n",n); 00259 return (-1); 00260 } 00261 00262 for(i = 0; i < n; i ++){ 00263 do { 00264 ch = winx_getche(); 00265 if(ch == -1){ 00266 string[i] = 0; 00267 return (-1); 00268 } 00269 } while(ch == 0 || ch == 0x08); /* skip backspace */ 00270 if(ch == 13){ 00271 winx_putch('\n'); 00272 string[i] = 0; 00273 return (i+1); 00274 } 00275 string[i] = (char)ch; 00276 } 00277 winx_printf("\nwinx_gets() buffer overflow!\n"); 00278 string[n-1] = 0; 00279 return n; 00280 } 00281 00299 int __cdecl winx_prompt(char *prompt,char *string,int n) 00300 { 00301 KEYBOARD_INPUT_DATA kbd; 00302 KBD_RECORD kbd_rec; 00303 char *buffer; 00304 int buffer_length; 00305 char format[16]; 00306 int i, ch, line_length; 00307 00308 if(!string){ 00309 winx_printf("\nwinx_prompt() invalid string!\n"); 00310 return (-1); 00311 } 00312 if(n <= 0){ 00313 winx_printf("\nwinx_prompt() invalid string length %d!\n",n); 00314 return (-1); 00315 } 00316 00317 if(!prompt) prompt = ""; 00318 buffer_length = strlen(prompt) + n; 00319 buffer = winx_heap_alloc(buffer_length); 00320 if(buffer == NULL){ 00321 winx_printf("\nNot enough memory for winx_prompt()!\n"); 00322 return (-1); 00323 } 00324 00325 winx_printf("%s",prompt); 00326 00327 /* keep string always null terminated */ 00328 RtlZeroMemory(string,n); 00329 for(i = 0; i < (n - 1); i ++){ 00330 /* read keyboard until an ordinary character appearance */ 00331 do { 00332 do{ 00333 if(kb_read(&kbd,INFINITE) < 0) goto fail; 00334 IntTranslateKey(&kbd,&kbd_rec); 00335 } while(!kbd_rec.bKeyDown); 00336 ch = (int)kbd_rec.AsciiChar; 00337 /* truncate the string if either backspace or escape pressed */ 00338 if(ch == 0x08 || kbd_rec.wVirtualScanCode == 0x1){ 00339 line_length = strlen(prompt) + strlen(string); 00340 if(kbd_rec.wVirtualScanCode == 0x1){ 00341 /* truncate the string if escape pressed */ 00342 string[0] = 0; 00343 i = 0; 00344 } 00345 if(ch == 0x08){ 00346 /* 00347 * make the string one character shorter 00348 * if backspace pressed 00349 */ 00350 if(i > 0){ 00351 i--; 00352 string[i] = 0; 00353 } 00354 } 00355 /* redraw the prompt */ 00356 _snprintf(buffer,buffer_length,"%s%s",prompt,string); 00357 buffer[buffer_length - 1] = 0; 00358 _snprintf(format,sizeof(format),"\r%%-%us",line_length); 00359 format[sizeof(format) - 1] = 0; 00360 winx_printf(format,buffer); 00361 /* 00362 * redraw the prompt again to set carriage position 00363 * exactly behind the string printed 00364 */ 00365 line_length = strlen(prompt) + strlen(string); 00366 _snprintf(format,sizeof(format),"\r%%-%us",line_length); 00367 format[sizeof(format) - 1] = 0; 00368 winx_printf(format,buffer); 00369 continue; 00370 } 00371 } while(ch == 0 || ch == 0x08 || kbd_rec.wVirtualScanCode == 0x1); 00372 00373 /* print a character read */ 00374 winx_putch(ch); 00375 00376 /* return when \r character appears */ 00377 if(ch == '\r'){ 00378 winx_putch('\n'); 00379 goto done; 00380 } 00381 00382 /* we have an ordinary character, append it to the string */ 00383 string[i] = (char)ch; 00384 } 00385 winx_printf("\nwinx_prompt() buffer overflow!\n"); 00386 00387 done: 00388 winx_heap_free(buffer); 00389 return (i+1); 00390 00391 fail: 00392 winx_heap_free(buffer); 00393 return (-1); 00394 } 00395