Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenexcept.c
Go to the documentation of this file.
00001 /* $Id: except.c 54299 2011-11-05 11:39:37Z tfaber $ 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS system libraries 00005 * FILE: lib/kernel32/misc/except.c 00006 * PURPOSE: Exception functions 00007 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) 00008 * modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ] 00009 * UPDATE HISTORY: 00010 * Created 01/11/98 00011 */ 00012 00013 /* INCLUDES *******************************************************************/ 00014 00015 #include <k32.h> 00016 00017 #define NDEBUG 00018 #include <debug.h> 00019 00020 /* 00021 * Private helper function to lookup the module name from a given address. 00022 * The address can point to anywhere within the module. 00023 */ 00024 static const char* 00025 _module_name_from_addr(const void* addr, void **module_start_addr, 00026 char* psz, size_t nChars) 00027 { 00028 MEMORY_BASIC_INFORMATION mbi; 00029 if (VirtualQuery(addr, &mbi, sizeof(mbi)) != sizeof(mbi) || 00030 !GetModuleFileNameA((HMODULE)mbi.AllocationBase, psz, nChars)) 00031 { 00032 psz[0] = '\0'; 00033 *module_start_addr = 0; 00034 } 00035 else 00036 { 00037 *module_start_addr = (void *)mbi.AllocationBase; 00038 } 00039 return psz; 00040 } 00041 00042 00043 static VOID 00044 _dump_context(PCONTEXT pc) 00045 { 00046 #ifdef _M_IX86 00047 /* 00048 * Print out the CPU registers 00049 */ 00050 DbgPrint("CS:EIP %x:%x\n", pc->SegCs&0xffff, pc->Eip ); 00051 DbgPrint("DS %x ES %x FS %x GS %x\n", pc->SegDs&0xffff, pc->SegEs&0xffff, 00052 pc->SegFs&0xffff, pc->SegGs&0xfff); 00053 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", pc->Eax, pc->Ebx, pc->Ecx); 00054 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", pc->Edx, 00055 pc->Ebp, pc->Esi, pc->Esp); 00056 DbgPrint("EDI: %.8x EFLAGS: %.8x\n", pc->Edi, pc->EFlags); 00057 #elif defined(_M_AMD64) 00058 DbgPrint("CS:RIP %x:%I64x\n", pc->SegCs&0xffff, pc->Rip ); 00059 DbgPrint("DS %x ES %x FS %x GS %x\n", pc->SegDs&0xffff, pc->SegEs&0xffff, 00060 pc->SegFs&0xffff, pc->SegGs&0xfff); 00061 DbgPrint("RAX: %I64x RBX: %I64x RCX: %I64x RDI: %I64x\n", pc->Rax, pc->Rbx, pc->Rcx, pc->Rdi); 00062 DbgPrint("RDX: %I64x RBP: %I64x RSI: %I64x RSP: %I64x\n", pc->Rdx, pc->Rbp, pc->Rsi, pc->Rsp); 00063 DbgPrint("R8: %I64x R9: %I64x R10: %I64x R11: %I64x\n", pc->R8, pc->R9, pc->R10, pc->R11); 00064 DbgPrint("R12: %I64x R13: %I64x R14: %I64x R15: %I64x\n", pc->R12, pc->R13, pc->R14, pc->R15); 00065 DbgPrint("EFLAGS: %.8x\n", pc->EFlags); 00066 #else 00067 #warning Unknown architecture 00068 #endif 00069 } 00070 00071 static VOID 00072 PrintStackTrace(struct _EXCEPTION_POINTERS *ExceptionInfo) 00073 { 00074 PVOID StartAddr; 00075 CHAR szMod[128] = ""; 00076 PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord; 00077 PCONTEXT ContextRecord = ExceptionInfo->ContextRecord; 00078 00079 /* Print a stack trace. */ 00080 DbgPrint("Unhandled exception\n"); 00081 DbgPrint("ExceptionCode: %8x\n", ExceptionRecord->ExceptionCode); 00082 00083 if ((NTSTATUS)ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION && 00084 ExceptionRecord->NumberParameters == 2) 00085 { 00086 DbgPrint("Faulting Address: %8x\n", ExceptionRecord->ExceptionInformation[1]); 00087 } 00088 00089 _dump_context (ContextRecord); 00090 _module_name_from_addr(ExceptionRecord->ExceptionAddress, &StartAddr, szMod, sizeof(szMod)); 00091 DbgPrint("Address:\n %8x+%-8x %s\n", 00092 (PVOID)StartAddr, 00093 (ULONG_PTR)ExceptionRecord->ExceptionAddress - (ULONG_PTR)StartAddr, 00094 szMod); 00095 #ifdef _M_IX86 00096 DbgPrint("Frames:\n"); 00097 00098 _SEH2_TRY 00099 { 00100 UINT i; 00101 PULONG Frame = (PULONG)ContextRecord->Ebp; 00102 00103 for (i = 0; Frame[1] != 0 && Frame[1] != 0xdeadbeef && i < 128; i++) 00104 { 00105 if (IsBadReadPtr((PVOID)Frame[1], 4)) 00106 { 00107 DbgPrint(" %8x%9s %s\n", Frame[1], "<invalid address>"," "); 00108 } 00109 else 00110 { 00111 _module_name_from_addr((const void*)Frame[1], &StartAddr, 00112 szMod, sizeof(szMod)); 00113 DbgPrint(" %8x+%-8x %s\n", 00114 (PVOID)StartAddr, 00115 (ULONG_PTR)Frame[1] - (ULONG_PTR)StartAddr, 00116 szMod); 00117 } 00118 00119 if (IsBadReadPtr((PVOID)Frame[0], sizeof(*Frame) * 2)) 00120 break; 00121 00122 Frame = (PULONG)Frame[0]; 00123 } 00124 } 00125 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00126 { 00127 DbgPrint("<error dumping stack trace: 0x%x>\n", _SEH2_GetExceptionCode()); 00128 } 00129 _SEH2_END; 00130 #endif 00131 } 00132 00133 /* GLOBALS ********************************************************************/ 00134 00135 LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter; 00136 DWORD g_dwLastErrorToBreakOn; 00137 00138 /* FUNCTIONS ******************************************************************/ 00139 00140 LONG 00141 WINAPI 00142 BasepCheckForReadOnlyResource(IN PVOID Ptr) 00143 { 00144 PVOID Data; 00145 ULONG Size, OldProtect; 00146 MEMORY_BASIC_INFORMATION mbi; 00147 NTSTATUS Status; 00148 LONG Ret = EXCEPTION_CONTINUE_SEARCH; 00149 00150 /* Check if it was an attempt to write to a read-only image section! */ 00151 Status = NtQueryVirtualMemory(NtCurrentProcess(), 00152 Ptr, 00153 MemoryBasicInformation, 00154 &mbi, 00155 sizeof(mbi), 00156 NULL); 00157 if (NT_SUCCESS(Status) && 00158 mbi.Protect == PAGE_READONLY && mbi.Type == MEM_IMAGE) 00159 { 00160 /* Attempt to treat it as a resource section. We need to 00161 use SEH here because we don't know if it's actually a 00162 resource mapping */ 00163 _SEH2_TRY 00164 { 00165 Data = RtlImageDirectoryEntryToData(mbi.AllocationBase, 00166 TRUE, 00167 IMAGE_DIRECTORY_ENTRY_RESOURCE, 00168 &Size); 00169 00170 if (Data != NULL && 00171 (ULONG_PTR)Ptr >= (ULONG_PTR)Data && 00172 (ULONG_PTR)Ptr < (ULONG_PTR)Data + Size) 00173 { 00174 /* The user tried to write into the resources. Make the page 00175 writable... */ 00176 Size = 1; 00177 Status = NtProtectVirtualMemory(NtCurrentProcess(), 00178 &Ptr, 00179 &Size, 00180 PAGE_READWRITE, 00181 &OldProtect); 00182 if (NT_SUCCESS(Status)) 00183 { 00184 Ret = EXCEPTION_CONTINUE_EXECUTION; 00185 } 00186 } 00187 } 00188 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00189 { 00190 } 00191 _SEH2_END; 00192 } 00193 00194 return Ret; 00195 } 00196 00197 UINT 00198 WINAPI 00199 GetErrorMode(VOID) 00200 { 00201 NTSTATUS Status; 00202 UINT ErrMode; 00203 00204 /* Query the current setting */ 00205 Status = NtQueryInformationProcess(NtCurrentProcess(), 00206 ProcessDefaultHardErrorMode, 00207 (PVOID)&ErrMode, 00208 sizeof(ErrMode), 00209 NULL); 00210 if (!NT_SUCCESS(Status)) 00211 { 00212 /* Fail if we couldn't query */ 00213 BaseSetLastNTError(Status); 00214 return 0; 00215 } 00216 00217 /* Check if NOT failing critical errors was requested */ 00218 if (ErrMode & SEM_FAILCRITICALERRORS) 00219 { 00220 /* Mask it out, since the native API works differently */ 00221 ErrMode &= ~SEM_FAILCRITICALERRORS; 00222 } 00223 else 00224 { 00225 /* OR it if the caller didn't, due to different native semantics */ 00226 ErrMode |= SEM_FAILCRITICALERRORS; 00227 } 00228 00229 /* Return the mode */ 00230 return ErrMode; 00231 } 00232 00233 /* 00234 * @implemented 00235 */ 00236 LONG WINAPI 00237 UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo) 00238 { 00239 LONG RetValue; 00240 HANDLE DebugPort = NULL; 00241 NTSTATUS ErrCode; 00242 ULONG_PTR ErrorParameters[4]; 00243 ULONG ErrorResponse; 00244 PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord; 00245 LPTOP_LEVEL_EXCEPTION_FILTER RealFilter; 00246 00247 if ((NTSTATUS)ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION && 00248 ExceptionRecord->NumberParameters >= 2) 00249 { 00250 switch(ExceptionRecord->ExceptionInformation[0]) 00251 { 00252 case EXCEPTION_WRITE_FAULT: 00253 /* Change the protection on some write attempts, some InstallShield setups 00254 have this bug */ 00255 RetValue = BasepCheckForReadOnlyResource( 00256 (PVOID)ExceptionRecord->ExceptionInformation[1]); 00257 if (RetValue == EXCEPTION_CONTINUE_EXECUTION) 00258 return EXCEPTION_CONTINUE_EXECUTION; 00259 break; 00260 case EXCEPTION_EXECUTE_FAULT: 00261 /* FIXME */ 00262 break; 00263 } 00264 } 00265 00266 /* Is there a debugger running ? */ 00267 ErrCode = NtQueryInformationProcess(NtCurrentProcess(), ProcessDebugPort, 00268 &DebugPort, sizeof(HANDLE), NULL); 00269 if (!NT_SUCCESS(ErrCode) && ErrCode != STATUS_NOT_IMPLEMENTED) 00270 { 00271 BaseSetLastNTError(ErrCode); 00272 return EXCEPTION_EXECUTE_HANDLER; 00273 } 00274 00275 if (DebugPort) 00276 { 00277 /* Pass the exception to debugger. */ 00278 DPRINT("Passing exception to debugger\n"); 00279 return EXCEPTION_CONTINUE_SEARCH; 00280 } 00281 00282 RealFilter = RtlDecodePointer(GlobalTopLevelExceptionFilter); 00283 if (RealFilter) 00284 { 00285 LONG ret = RealFilter(ExceptionInfo); 00286 if (ret != EXCEPTION_CONTINUE_SEARCH) 00287 return ret; 00288 } 00289 00290 if ((GetErrorMode() & SEM_NOGPFAULTERRORBOX) == 0) 00291 PrintStackTrace(ExceptionInfo); 00292 00293 /* Save exception code and address */ 00294 ErrorParameters[0] = (ULONG)ExceptionRecord->ExceptionCode; 00295 ErrorParameters[1] = (ULONG_PTR)ExceptionRecord->ExceptionAddress; 00296 00297 if ((NTSTATUS)ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) 00298 { 00299 /* get the type of operation that caused the access violation */ 00300 ErrorParameters[2] = ExceptionRecord->ExceptionInformation[0]; 00301 } 00302 else 00303 { 00304 ErrorParameters[2] = ExceptionRecord->ExceptionInformation[2]; 00305 } 00306 00307 /* Save faulting address */ 00308 ErrorParameters[3] = ExceptionRecord->ExceptionInformation[1]; 00309 00310 /* Raise the harderror */ 00311 ErrCode = NtRaiseHardError(STATUS_UNHANDLED_EXCEPTION, 00312 4, 0, ErrorParameters, OptionOkCancel, &ErrorResponse); 00313 00314 if (NT_SUCCESS(ErrCode) && (ErrorResponse == ResponseCancel)) 00315 { 00316 /* FIXME: Check the result, if the "Cancel" button was 00317 clicked run a debugger */ 00318 DPRINT1("Debugging is not implemented yet\n"); 00319 } 00320 00321 /* 00322 * Returning EXCEPTION_EXECUTE_HANDLER means that the code in 00323 * the __except block will be executed. Normally this will end up in a 00324 * Terminate process. 00325 */ 00326 00327 return EXCEPTION_EXECUTE_HANDLER; 00328 } 00329 00330 /* 00331 * @implemented 00332 */ 00333 VOID 00334 WINAPI 00335 RaiseException(IN DWORD dwExceptionCode, 00336 IN DWORD dwExceptionFlags, 00337 IN DWORD nNumberOfArguments, 00338 IN CONST ULONG_PTR *lpArguments OPTIONAL) 00339 { 00340 EXCEPTION_RECORD ExceptionRecord; 00341 00342 /* Setup the exception record */ 00343 ExceptionRecord.ExceptionCode = dwExceptionCode; 00344 ExceptionRecord.ExceptionRecord = NULL; 00345 ExceptionRecord.ExceptionAddress = (PVOID)RaiseException; 00346 ExceptionRecord.ExceptionFlags = dwExceptionFlags & EXCEPTION_NONCONTINUABLE; 00347 00348 /* Check if we have arguments */ 00349 if (!lpArguments) 00350 { 00351 /* We don't */ 00352 ExceptionRecord.NumberParameters = 0; 00353 } 00354 else 00355 { 00356 /* We do, normalize the count */ 00357 if (nNumberOfArguments > EXCEPTION_MAXIMUM_PARAMETERS) 00358 { 00359 nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS; 00360 } 00361 00362 /* Set the count of parameters and copy them */ 00363 ExceptionRecord.NumberParameters = nNumberOfArguments; 00364 RtlCopyMemory(ExceptionRecord.ExceptionInformation, 00365 lpArguments, 00366 nNumberOfArguments * sizeof(ULONG)); 00367 } 00368 00369 /* Better handling of Delphi Exceptions... a ReactOS Hack */ 00370 if (dwExceptionCode == 0xeedface || dwExceptionCode == 0xeedfade) 00371 { 00372 DPRINT1("Delphi Exception at address: %p\n", ExceptionRecord.ExceptionInformation[0]); 00373 DPRINT1("Exception-Object: %p\n", ExceptionRecord.ExceptionInformation[1]); 00374 DPRINT1("Exception text: %s\n", ExceptionRecord.ExceptionInformation[2]); 00375 } 00376 00377 /* Trace the wine special error and show the modulename and functionname */ 00378 if (dwExceptionCode == 0x80000100 /*EXCEPTION_WINE_STUB*/) 00379 { 00380 /* Numbers of parameter must be equal to two */ 00381 if (ExceptionRecord.NumberParameters == 2) 00382 { 00383 DPRINT1("Missing function in : %s\n", ExceptionRecord.ExceptionInformation[0]); 00384 DPRINT1("with the functionname : %s\n", ExceptionRecord.ExceptionInformation[1]); 00385 } 00386 } 00387 00388 /* Raise the exception */ 00389 RtlRaiseException(&ExceptionRecord); 00390 } 00391 00392 /* 00393 * @implemented 00394 */ 00395 UINT 00396 WINAPI 00397 SetErrorMode(IN UINT uMode) 00398 { 00399 UINT PrevErrMode, NewMode; 00400 NTSTATUS Status; 00401 00402 /* Get the previous mode */ 00403 PrevErrMode = GetErrorMode(); 00404 NewMode = uMode; 00405 00406 /* Check if failing critical errors was requested */ 00407 if (NewMode & SEM_FAILCRITICALERRORS) 00408 { 00409 /* Mask it out, since the native API works differently */ 00410 NewMode &= ~SEM_FAILCRITICALERRORS; 00411 } 00412 else 00413 { 00414 /* OR it if the caller didn't, due to different native semantics */ 00415 NewMode |= SEM_FAILCRITICALERRORS; 00416 } 00417 00418 /* Always keep no alignment faults if they were set */ 00419 NewMode |= (PrevErrMode & SEM_NOALIGNMENTFAULTEXCEPT); 00420 00421 /* Set the new mode */ 00422 Status = NtSetInformationProcess(NtCurrentProcess(), 00423 ProcessDefaultHardErrorMode, 00424 (PVOID)&NewMode, 00425 sizeof(NewMode)); 00426 00427 /* Return the previous mode */ 00428 return PrevErrMode; 00429 } 00430 00431 /* 00432 * @implemented 00433 */ 00434 LPTOP_LEVEL_EXCEPTION_FILTER 00435 WINAPI 00436 SetUnhandledExceptionFilter(IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) 00437 { 00438 PVOID EncodedPointer, NewPointer; 00439 00440 EncodedPointer = RtlEncodePointer(lpTopLevelExceptionFilter); 00441 NewPointer = InterlockedExchangePointer(&GlobalTopLevelExceptionFilter, 00442 EncodedPointer); 00443 return RtlDecodePointer(EncodedPointer); 00444 } 00445 00446 /* 00447 * @implemented 00448 */ 00449 BOOL 00450 WINAPI 00451 IsBadReadPtr(IN LPCVOID lp, 00452 IN UINT_PTR ucb) 00453 { 00454 ULONG PageSize; 00455 BOOLEAN Result = FALSE; 00456 volatile CHAR *Current; 00457 PCHAR Last; 00458 00459 /* Quick cases */ 00460 if (!ucb) return FALSE; 00461 if (!lp) return TRUE; 00462 00463 /* Get the page size */ 00464 PageSize = BaseStaticServerData->SysInfo.PageSize; 00465 00466 /* Calculate start and end */ 00467 Current = (volatile CHAR*)lp; 00468 Last = (PCHAR)((ULONG_PTR)lp + ucb - 1); 00469 00470 /* Another quick failure case */ 00471 if (Last < Current) return TRUE; 00472 00473 /* Enter SEH */ 00474 _SEH2_TRY 00475 { 00476 /* Do an initial probe */ 00477 *Current; 00478 00479 /* Align the addresses */ 00480 Current = (volatile CHAR *)ROUND_DOWN(Current, PageSize); 00481 Last = (PCHAR)ROUND_DOWN(Last, PageSize); 00482 00483 /* Probe the entire range */ 00484 while (Current != Last) 00485 { 00486 Current += PageSize; 00487 *Current; 00488 } 00489 } 00490 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00491 { 00492 /* We hit an exception, so return true */ 00493 Result = TRUE; 00494 } 00495 _SEH2_END 00496 00497 /* Return exception status */ 00498 return Result; 00499 } 00500 00501 /* 00502 * @implemented 00503 */ 00504 BOOL 00505 NTAPI 00506 IsBadHugeReadPtr(LPCVOID lp, 00507 UINT_PTR ucb) 00508 { 00509 /* Implementation is the same on 32-bit */ 00510 return IsBadReadPtr(lp, ucb); 00511 } 00512 00513 /* 00514 * @implemented 00515 */ 00516 BOOL 00517 NTAPI 00518 IsBadCodePtr(FARPROC lpfn) 00519 { 00520 /* Executing has the same privileges as reading */ 00521 return IsBadReadPtr((LPVOID)lpfn, 1); 00522 } 00523 00524 /* 00525 * @implemented 00526 */ 00527 BOOL 00528 NTAPI 00529 IsBadWritePtr(IN LPVOID lp, 00530 IN UINT_PTR ucb) 00531 { 00532 ULONG PageSize; 00533 BOOLEAN Result = FALSE; 00534 volatile CHAR *Current; 00535 PCHAR Last; 00536 00537 /* Quick cases */ 00538 if (!ucb) return FALSE; 00539 if (!lp) return TRUE; 00540 00541 /* Get the page size */ 00542 PageSize = BaseStaticServerData->SysInfo.PageSize; 00543 00544 /* Calculate start and end */ 00545 Current = (volatile CHAR*)lp; 00546 Last = (PCHAR)((ULONG_PTR)lp + ucb - 1); 00547 00548 /* Another quick failure case */ 00549 if (Last < Current) return TRUE; 00550 00551 /* Enter SEH */ 00552 _SEH2_TRY 00553 { 00554 /* Do an initial probe */ 00555 *Current = *Current; 00556 00557 /* Align the addresses */ 00558 Current = (volatile CHAR *)ROUND_DOWN(Current, PageSize); 00559 Last = (PCHAR)ROUND_DOWN(Last, PageSize); 00560 00561 /* Probe the entire range */ 00562 while (Current != Last) 00563 { 00564 Current += PageSize; 00565 *Current = *Current; 00566 } 00567 } 00568 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00569 { 00570 /* We hit an exception, so return true */ 00571 Result = TRUE; 00572 } 00573 _SEH2_END 00574 00575 /* Return exception status */ 00576 return Result; 00577 } 00578 00579 /* 00580 * @implemented 00581 */ 00582 BOOL 00583 NTAPI 00584 IsBadHugeWritePtr(IN LPVOID lp, 00585 IN UINT_PTR ucb) 00586 { 00587 /* Implementation is the same on 32-bit */ 00588 return IsBadWritePtr(lp, ucb); 00589 } 00590 00591 /* 00592 * @implemented 00593 */ 00594 BOOL 00595 NTAPI 00596 IsBadStringPtrW(IN LPCWSTR lpsz, 00597 IN UINT_PTR ucchMax) 00598 { 00599 BOOLEAN Result = FALSE; 00600 volatile WCHAR *Current; 00601 PWCHAR Last; 00602 WCHAR Char; 00603 00604 /* Quick cases */ 00605 if (!ucchMax) return FALSE; 00606 if (!lpsz) return TRUE; 00607 00608 /* Calculate start and end */ 00609 Current = (volatile WCHAR*)lpsz; 00610 Last = (PWCHAR)((ULONG_PTR)lpsz + (ucchMax * 2) - 2); 00611 00612 /* Enter SEH */ 00613 _SEH2_TRY 00614 { 00615 /* Probe the entire range */ 00616 Char = *Current++; 00617 while ((Char) && (Current != Last)) Char = *Current++; 00618 } 00619 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00620 { 00621 /* We hit an exception, so return true */ 00622 Result = TRUE; 00623 } 00624 _SEH2_END 00625 00626 /* Return exception status */ 00627 return Result; 00628 } 00629 00630 /* 00631 * @implemented 00632 */ 00633 BOOL 00634 NTAPI 00635 IsBadStringPtrA(IN LPCSTR lpsz, 00636 IN UINT_PTR ucchMax) 00637 { 00638 BOOLEAN Result = FALSE; 00639 volatile CHAR *Current; 00640 PCHAR Last; 00641 CHAR Char; 00642 00643 /* Quick cases */ 00644 if (!ucchMax) return FALSE; 00645 if (!lpsz) return TRUE; 00646 00647 /* Calculate start and end */ 00648 Current = (volatile CHAR*)lpsz; 00649 Last = (PCHAR)((ULONG_PTR)lpsz + ucchMax - 1); 00650 00651 /* Enter SEH */ 00652 _SEH2_TRY 00653 { 00654 /* Probe the entire range */ 00655 Char = *Current++; 00656 while ((Char) && (Current != Last)) Char = *Current++; 00657 } 00658 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00659 { 00660 /* We hit an exception, so return true */ 00661 Result = TRUE; 00662 } 00663 _SEH2_END 00664 00665 /* Return exception status */ 00666 return Result; 00667 } 00668 00669 /* 00670 * @implemented 00671 */ 00672 VOID 00673 WINAPI 00674 SetLastError(IN DWORD dwErrCode) 00675 { 00676 /* Break if a debugger requested checking for this error code */ 00677 if ((g_dwLastErrorToBreakOn) && (g_dwLastErrorToBreakOn == dwErrCode)) DbgBreakPoint(); 00678 00679 /* Set last error if it's a new error */ 00680 if (NtCurrentTeb()->LastErrorValue != dwErrCode) NtCurrentTeb()->LastErrorValue = dwErrCode; 00681 } 00682 00683 /* 00684 * @implemented 00685 */ 00686 VOID 00687 WINAPI 00688 BaseSetLastNTError(IN NTSTATUS Status) 00689 { 00690 /* Convert from NT to Win32, then set */ 00691 SetLastError(RtlNtStatusToDosError(Status)); 00692 } 00693 00694 /* 00695 * @implemented 00696 */ 00697 DWORD 00698 WINAPI 00699 GetLastError(VOID) 00700 { 00701 /* Return the current value */ 00702 return NtCurrentTeb()->LastErrorValue; 00703 } 00704 00705 /* EOF */ Generated on Sun May 27 2012 04:24:25 for ReactOS by
1.7.6.1
|