ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

except.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.