![]() |
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 typedef struct _DBG_OUTPUT_DEBUG_STRING_BUFFER { 00031 ULONG ProcessId; 00032 UCHAR Msg[4096-sizeof(ULONG)]; 00033 } DBG_OUTPUT_DEBUG_STRING_BUFFER, *PDBG_OUTPUT_DEBUG_STRING_BUFFER; 00034 00035 #define DBG_BUFFER_SIZE (4096-sizeof(ULONG)) 00036 00037 HANDLE hDbgSynchEvent = NULL; 00038 00039 int __stdcall winx_debug_print(char *string); 00040 00046 void winx_init_synch_objects(void) 00047 { 00048 short event_name[64]; 00049 00050 /* 00051 * Attach process ID to the event name 00052 * to make it safe for execution 00053 * by many parallel processes. 00054 */ 00055 _snwprintf(event_name,64,L"\\winx_dbgprint_synch_event_%u", 00056 (unsigned int)(DWORD_PTR)(NtCurrentTeb()->ClientId.UniqueProcess)); 00057 event_name[63] = 0; 00058 00059 if(hDbgSynchEvent == NULL){ 00060 (void)winx_create_event(event_name,SynchronizationEvent,&hDbgSynchEvent); 00061 if(hDbgSynchEvent) (void)NtSetEvent(hDbgSynchEvent,NULL); 00062 } 00063 } 00064 00070 void winx_destroy_synch_objects(void) 00071 { 00072 winx_destroy_event(hDbgSynchEvent); 00073 } 00074 00081 void __cdecl winx_dbg_print(char *format, ...) 00082 { 00083 char *buffer = NULL; 00084 va_list arg; 00085 int length; 00086 00087 /* never call winx_dbg_print_ex() here! */ 00088 00089 if(!format) return; 00090 buffer = winx_virtual_alloc(DBG_BUFFER_SIZE); 00091 if(!buffer){ 00092 winx_debug_print("Cannot allocate memory for winx_dbg_print()!"); 00093 return; 00094 } 00095 00096 /* 1a. store resulting ANSI string into buffer */ 00097 va_start(arg,format); 00098 memset(buffer,0,DBG_BUFFER_SIZE); 00099 length = _vsnprintf(buffer,DBG_BUFFER_SIZE - 1,format,arg); 00100 (void)length; 00101 buffer[DBG_BUFFER_SIZE - 1] = 0; 00102 va_end(arg); 00103 00104 /* 1b. send resulting ANSI string to the debugger */ 00105 winx_debug_print(buffer); 00106 00107 winx_virtual_free(buffer,DBG_BUFFER_SIZE); 00108 } 00109 00116 int __stdcall winx_debug_print(char *string) 00117 { 00118 HANDLE hEvtBufferReady = NULL; 00119 HANDLE hEvtDataReady = NULL; 00120 HANDLE hSection = NULL; 00121 LPVOID BaseAddress = NULL; 00122 LARGE_INTEGER SectionOffset; 00123 ULONG ViewSize = 0; 00124 00125 UNICODE_STRING us; 00126 NTSTATUS Status; 00127 OBJECT_ATTRIBUTES oa; 00128 LARGE_INTEGER interval; 00129 00130 DBG_OUTPUT_DEBUG_STRING_BUFFER *dbuffer; 00131 int length; 00132 00133 /* never call winx_dbg_print_ex() here! */ 00134 00135 /* 0. synchronize with other threads */ 00136 if(hDbgSynchEvent){ 00137 interval.QuadPart = -(11000 * 10000); /* 11 sec */ 00138 Status = NtWaitForSingleObject(hDbgSynchEvent,FALSE,&interval); 00139 if(Status != WAIT_OBJECT_0) return (-1); 00140 } 00141 00142 /* 1. Open debugger's objects. */ 00143 RtlInitUnicodeString(&us,L"\\BaseNamedObjects\\DBWIN_BUFFER_READY"); 00144 InitializeObjectAttributes(&oa,&us,0,NULL,NULL); 00145 Status = NtOpenEvent(&hEvtBufferReady,SYNCHRONIZE,&oa); 00146 if(!NT_SUCCESS(Status)) goto failure; 00147 00148 RtlInitUnicodeString(&us,L"\\BaseNamedObjects\\DBWIN_DATA_READY"); 00149 InitializeObjectAttributes(&oa,&us,0,NULL,NULL); 00150 Status = NtOpenEvent(&hEvtDataReady,EVENT_MODIFY_STATE,&oa); 00151 if(!NT_SUCCESS(Status)) goto failure; 00152 00153 RtlInitUnicodeString(&us,L"\\BaseNamedObjects\\DBWIN_BUFFER"); 00154 InitializeObjectAttributes(&oa,&us,0,NULL,NULL); 00155 Status = NtOpenSection(&hSection,SECTION_ALL_ACCESS,&oa); 00156 if(!NT_SUCCESS(Status)) goto failure; 00157 SectionOffset.QuadPart = 0; 00158 Status = NtMapViewOfSection(hSection,NtCurrentProcess(), 00159 &BaseAddress,0,0,&SectionOffset,(SIZE_T *)&ViewSize,ViewShare, 00160 0,PAGE_READWRITE); 00161 if(!NT_SUCCESS(Status)) goto failure; 00162 00163 /* 2. Send a message. */ 00164 /* 00165 * wait a maximum of 10 seconds for the debug monitor 00166 * to finish processing the shared buffer 00167 */ 00168 interval.QuadPart = -(10000 * 10000); 00169 if(NtWaitForSingleObject(hEvtBufferReady,FALSE,&interval) != WAIT_OBJECT_0) 00170 goto failure; 00171 00172 dbuffer = (DBG_OUTPUT_DEBUG_STRING_BUFFER *)BaseAddress; 00173 00174 /* write the process id into the buffer */ 00175 dbuffer->ProcessId = (DWORD)(DWORD_PTR)(NtCurrentTeb()->ClientId.UniqueProcess); 00176 00177 (void)strncpy(dbuffer->Msg,string,4096-sizeof(ULONG)); 00178 dbuffer->Msg[4096-sizeof(ULONG)-1] = 0; 00179 /* ensure that the buffer has new line character */ 00180 length = strlen(dbuffer->Msg); 00181 if(dbuffer->Msg[length-1] != '\n'){ 00182 if(length == (4096-sizeof(ULONG)-1)){ 00183 dbuffer->Msg[length-1] = '\n'; 00184 } else { 00185 dbuffer->Msg[length] = '\n'; 00186 dbuffer->Msg[length+1] = 0; 00187 } 00188 } 00189 00190 /* signal that the buffer contains meaningful data and can be read */ 00191 (void)NtSetEvent(hEvtDataReady,NULL); 00192 00193 NtCloseSafe(hEvtBufferReady); 00194 NtCloseSafe(hEvtDataReady); 00195 if(BaseAddress) 00196 (void)NtUnmapViewOfSection(NtCurrentProcess(),BaseAddress); 00197 NtCloseSafe(hSection); 00198 if(hDbgSynchEvent) (void)NtSetEvent(hDbgSynchEvent,NULL); 00199 return 0; 00200 00201 failure: 00202 NtCloseSafe(hEvtBufferReady); 00203 NtCloseSafe(hEvtDataReady); 00204 if(BaseAddress) 00205 (void)NtUnmapViewOfSection(NtCurrentProcess(),BaseAddress); 00206 NtCloseSafe(hSection); 00207 if(hDbgSynchEvent) (void)NtSetEvent(hDbgSynchEvent,NULL); 00208 return (-1); 00209 } 00210 00211 /* 00212 * winx_dbg_print_ex() code. 00213 */ 00214 00215 typedef struct _NT_STATUS_DESCRIPTION { 00216 unsigned long status; 00217 char *description; 00218 } NT_STATUS_DESCRIPTION, *PNT_STATUS_DESCRIPTION; 00219 00220 NT_STATUS_DESCRIPTION status_descriptions[] = { 00221 { STATUS_SUCCESS, "Operation successful" }, 00222 { STATUS_OBJECT_NAME_INVALID, "Object name invalid" }, 00223 { STATUS_OBJECT_NAME_NOT_FOUND, "Object name not found" }, 00224 { STATUS_OBJECT_NAME_COLLISION, "Object name already exists" }, 00225 { STATUS_OBJECT_PATH_INVALID, "Path is invalid" }, 00226 { STATUS_OBJECT_PATH_NOT_FOUND, "Path not found" }, 00227 { STATUS_OBJECT_PATH_SYNTAX_BAD, "Bad syntax in path" }, 00228 { STATUS_BUFFER_TOO_SMALL, "Buffer is too small" }, 00229 { STATUS_ACCESS_DENIED, "Access denied" }, 00230 { STATUS_NO_MEMORY, "Not enough memory" }, 00231 { STATUS_UNSUCCESSFUL, "Operation failed" }, 00232 { STATUS_NOT_IMPLEMENTED, "Not implemented" }, 00233 { STATUS_INVALID_INFO_CLASS, "Invalid info class" }, 00234 { STATUS_INFO_LENGTH_MISMATCH, "Info length mismatch" }, 00235 { STATUS_ACCESS_VIOLATION, "Access violation" }, 00236 { STATUS_INVALID_HANDLE, "Invalid handle" }, 00237 { STATUS_INVALID_PARAMETER, "Invalid parameter" }, 00238 { STATUS_NO_SUCH_DEVICE, "Device not found" }, 00239 { STATUS_NO_SUCH_FILE, "File not found" }, 00240 { STATUS_INVALID_DEVICE_REQUEST, "Invalid device request" }, 00241 { STATUS_END_OF_FILE, "End of file reached" }, 00242 { STATUS_WRONG_VOLUME, "Wrong volume" }, 00243 { STATUS_NO_MEDIA_IN_DEVICE, "No media in device" }, 00244 { STATUS_UNRECOGNIZED_VOLUME, "Cannot recognize file system" }, 00245 { STATUS_VARIABLE_NOT_FOUND, "Environment variable not found" }, 00246 00247 /* A file cannot be opened because the share access flags are incompatible. */ 00248 { STATUS_SHARING_VIOLATION, "File is locked by another process"}, 00249 00250 { 0xffffffff, NULL } 00251 }; 00252 00266 char * __stdcall winx_get_error_description(unsigned long status) 00267 { 00268 int i; 00269 00270 for(i = 0;; i++){ 00271 if(status_descriptions[i].description == NULL) break; 00272 if(status_descriptions[i].status == status) 00273 return status_descriptions[i].description; 00274 } 00275 return ""; 00276 } 00277 00293 void __cdecl winx_dbg_print_ex(unsigned long status,char *format, ...) 00294 { 00295 #define ERR_MSG_LENGTH 4096 /* because impossible to define exactly */ 00296 char *buffer; 00297 va_list arg; 00298 int length; 00299 00300 /* 00301 * Localized strings sometimes appears on the screen 00302 * in abracadabra form, therefore we should avoid 00303 * FormatMessage() calls in debugging. 00304 * When I tried to get debugging information on NT4/w2k 00305 * systems running under MS Virtual PC emulator, DbgView 00306 * displayed localized text in completely unreadable form 00307 * (as sequence of question characters). 00308 */ 00309 00310 buffer = winx_heap_alloc(ERR_MSG_LENGTH); 00311 if(!buffer){ 00312 DebugPrint("Cannot allocate memory for winx_dbg_print_ex()!\n"); 00313 return; 00314 } 00315 00316 va_start(arg,format); 00317 memset(buffer,0,ERR_MSG_LENGTH); 00318 length = _vsnprintf(buffer,ERR_MSG_LENGTH - 1,format,arg); 00319 (void)length; 00320 buffer[ERR_MSG_LENGTH - 1] = 0; 00321 DebugPrint("%s: 0x%x! %s.\n",buffer,(unsigned int)status, 00322 winx_get_error_description(status)); 00323 va_end(arg); 00324 00325 winx_heap_free(buffer); 00326 } 00327