00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
#include "ntrtlp.h"
00035
00036
00037
00038
00039
00040
#ifndef ROS_DEBUG
00041
#ifndef READ_ULONG
00042 #define READ_ULONG(addr,dest) dest = (*((PULONG)(addr)))
00043 #define READ_DOUBLE(addr,dest) dest = (*((PDOUBLE)(addr)))
00044
#endif
00045
00046
#include "vunwind.c"
00047
#endif // ROS_DEBUG
00048
00049
00050
00051
00052
00053
00054
00055 #define RAISE_EXCEPTION(Status, ExceptionRecordt) { \
00056
EXCEPTION_RECORD ExceptionRecordn; \
00057
\
00058
ExceptionRecordn.ExceptionCode = Status; \
00059
ExceptionRecordn.ExceptionFlags = EXCEPTION_NONCONTINUABLE; \
00060
ExceptionRecordn.ExceptionRecord = ExceptionRecordt; \
00061
ExceptionRecordn.NumberParameters = 0; \
00062
RtlRaiseException(&ExceptionRecordn); \
00063
}
00064
00065
00066
00067
00068
00069
VOID
00070
RtlpRestoreContext (
00071 IN PCONTEXT Context,
00072 IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL
00073 );
00074
00075
VOID
00076
RtlpRaiseException (
00077 IN PEXCEPTION_RECORD ExceptionRecord
00078 );
00079
00080
VOID
00081
RtlpRaiseStatus (
00082 IN NTSTATUS Status
00083 );
00084
00085 ULONG
00086
RtlpVirtualUnwind (
00087 IN ULONG ControlPc,
00088 IN PRUNTIME_FUNCTION FunctionEntry,
00089 IN PCONTEXT ContextRecord,
00090 OUT PBOOLEAN InFunction,
00091 OUT PULONG EstablisherFrame,
00092 IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL,
00093 IN ULONG LowStackLimit,
00094 IN ULONG HighStackLimit
00095 );
00096
00097 BOOLEAN
00098 RtlDispatchException (
00099 IN PEXCEPTION_RECORD ExceptionRecord,
00100 IN PCONTEXT ContextRecord
00101 )
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 {
00136
00137 CONTEXT ContextRecord1;
00138 ULONG ControlPc;
00139
DISPATCHER_CONTEXT DispatcherContext;
00140 EXCEPTION_DISPOSITION Disposition;
00141 ULONG EstablisherFrame;
00142 ULONG ExceptionFlags;
00143 PRUNTIME_FUNCTION FunctionEntry;
00144 BOOLEAN InFunction;
00145 ULONG HighLimit;
00146 ULONG LowLimit;
00147 ULONG NestedFrame;
00148 ULONG NextPc;
00149
00150
00151
00152
00153
00154
00155
00156
RtlpGetStackLimits(&LowLimit, &HighLimit);
00157 RtlMoveMemory(&ContextRecord1, ContextRecord,
sizeof(CONTEXT));
00158 ControlPc = ContextRecord1.Iar;
00159 ExceptionFlags = ExceptionRecord->ExceptionFlags &
EXCEPTION_NONCONTINUABLE;
00160 NestedFrame = 0;
00161
00162
00163
00164
00165
00166
00167
00168
do {
00169
00170
00171
00172
00173
00174
00175 FunctionEntry =
RtlLookupFunctionEntry(ControlPc);
00176
00177
00178
00179
00180
00181
00182 NextPc =
RtlVirtualUnwind(ControlPc,
00183 FunctionEntry,
00184 &ContextRecord1,
00185 &InFunction,
00186 &EstablisherFrame,
00187
NULL,
00188 LowLimit,
00189 HighLimit);
00190
00191
00192
00193
00194
00195
00196
if (FunctionEntry !=
NULL) {
00197
00198
00199
00200
00201
00202
00203
00204
00205
if ((EstablisherFrame < LowLimit) || (EstablisherFrame > HighLimit) ||
00206 ((EstablisherFrame & 0x7) != 0)) {
00207 ExceptionFlags |=
EXCEPTION_STACK_INVALID;
00208
break;
00209
00210 }
else if ((FunctionEntry->ExceptionHandler !=
NULL) && InFunction) {
00211 ULONG
Index;
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 DispatcherContext.ControlPc = ControlPc;
00222 DispatcherContext.FunctionEntry = FunctionEntry;
00223 DispatcherContext.EstablisherFrame = EstablisherFrame;
00224 DispatcherContext.ContextRecord = ContextRecord;
00225 ExceptionRecord->ExceptionFlags = ExceptionFlags;
00226
00227
if (
NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING) {
00228
Index =
RtlpLogExceptionHandler(
00229 ExceptionRecord,
00230 ContextRecord,
00231 ControlPc,
00232 FunctionEntry,
00233
sizeof(RUNTIME_FUNCTION));
00234 }
00235
00236 Disposition =
00237
RtlpExecuteHandlerForException(ExceptionRecord,
00238 EstablisherFrame,
00239 ContextRecord,
00240 &DispatcherContext,
00241 FunctionEntry->ExceptionHandler);
00242
00243
if (
NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING) {
00244
RtlpLogLastExceptionDisposition(
Index, Disposition);
00245 }
00246
00247 ExceptionFlags |=
00248 (ExceptionRecord->ExceptionFlags &
EXCEPTION_NONCONTINUABLE);
00249
00250
00251
00252
00253
00254
00255
00256
00257
if (NestedFrame == EstablisherFrame) {
00258 ExceptionFlags &= (~
EXCEPTION_NESTED_CALL);
00259 NestedFrame = 0;
00260 }
00261
00262
00263
00264
00265
00266
switch (Disposition) {
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
case ExceptionContinueExecution :
00277
if ((ExceptionFlags &
EXCEPTION_NONCONTINUABLE) != 0) {
00278
RAISE_EXCEPTION(STATUS_NONCONTINUABLE_EXCEPTION, ExceptionRecord);
00279
00280 }
else {
00281
return TRUE;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
case ExceptionContinueSearch :
00291
break;
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
case ExceptionNestedException :
00302 ExceptionFlags |=
EXCEPTION_NESTED_CALL;
00303
if (DispatcherContext.EstablisherFrame > NestedFrame) {
00304 NestedFrame = DispatcherContext.EstablisherFrame;
00305 }
00306
00307
break;
00308
00309
00310
00311
00312
00313
00314
00315
default :
00316
RAISE_EXCEPTION(STATUS_INVALID_DISPOSITION, ExceptionRecord);
00317 }
00318 }
00319
00320 }
else {
00321
00322
00323
00324
00325
00326
00327
if (NextPc == ControlPc) {
00328
break;
00329 }
00330 }
00331
00332
00333
00334
00335
00336 ControlPc = NextPc;
00337 }
while (ContextRecord1.Gpr1 < HighLimit);
00338
00339
00340
00341
00342
00343 ExceptionRecord->ExceptionFlags = ExceptionFlags;
00344
return FALSE;
00345 }
00346
00347 PRUNTIME_FUNCTION
00348 RtlLookupFunctionEntry (
00349 IN ULONG ControlPc
00350 )
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 {
00373
00374 PRUNTIME_FUNCTION FunctionEntry;
00375 PRUNTIME_FUNCTION FunctionTable;
00376 ULONG SizeOfExceptionTable;
00377 LONG High;
00378 PVOID ImageBase;
00379 LONG Low;
00380 LONG Middle;
00381
00382
00383
00384
00385
00386 ImageBase =
RtlPcToFileHeader((PVOID)ControlPc, &ImageBase);
00387
00388
00389
00390
00391
00392
00393
if (ImageBase !=
NULL) {
00394 FunctionTable = (PRUNTIME_FUNCTION)
RtlImageDirectoryEntryToData(
00395 ImageBase,
TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION,
00396 &SizeOfExceptionTable);
00397
00398
00399
00400
00401
00402
00403
if (FunctionTable !=
NULL) {
00404
00405
00406
00407
00408
00409 Low = 0;
00410 High = (SizeOfExceptionTable /
sizeof(RUNTIME_FUNCTION)) - 1;
00411
00412
00413
00414
00415
00416
00417
while (High >= Low) {
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 Middle = (Low + High) >> 1;
00428 FunctionEntry = &FunctionTable[Middle];
00429
if (ControlPc < FunctionEntry->BeginAddress) {
00430 High = Middle - 1;
00431
00432 }
else if (ControlPc >= FunctionEntry->EndAddress) {
00433 Low = Middle + 1;
00434
00435 }
else {
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
if (((FunctionEntry->PrologEndAddress < FunctionEntry->BeginAddress) ||
00448 (FunctionEntry->PrologEndAddress > FunctionEntry->EndAddress)) &&
00449 (FunctionEntry->PrologEndAddress & 3) == 0) {
00450 FunctionEntry = (PRUNTIME_FUNCTION)FunctionEntry->PrologEndAddress;
00451 }
00452
return FunctionEntry;
00453 }
00454 }
00455 }
00456 }
00457
00458
00459
00460
00461
00462
return NULL;
00463 }
00464
00465
VOID
00466 RtlRaiseException (
00467 IN PEXCEPTION_RECORD ExceptionRecord
00468 )
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 {
00493
00494
RtlpRaiseException(ExceptionRecord);
00495
return;
00496 }
00497
00498
VOID
00499
RtlpRaiseException (
00500 IN PEXCEPTION_RECORD ExceptionRecord
00501 )
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 {
00521
00522 ULONG ControlPc;
00523 CONTEXT ContextRecord;
00524 ULONG EstablisherFrame;
00525 PRUNTIME_FUNCTION FunctionEntry;
00526 BOOLEAN InFunction;
00527 ULONG NextPc;
00528
NTSTATUS Status;
00529
00530
00531
00532
00533
00534
00535
00536 RtlCaptureContext(&ContextRecord);
00537 ControlPc = ContextRecord.Lr - 4;
00538 FunctionEntry =
RtlLookupFunctionEntry(ControlPc);
00539 NextPc =
RtlVirtualUnwind(ControlPc,
00540 FunctionEntry,
00541 &ContextRecord,
00542 &InFunction,
00543 &EstablisherFrame,
00544 NULL,
00545 0,
00546 0xffffffff);
00547
00548 ContextRecord.Iar = NextPc + 4;
00549 ExceptionRecord->ExceptionAddress = (PVOID)ContextRecord.Iar;
00550
Status = ZwRaiseException(ExceptionRecord, &ContextRecord, TRUE);
00551
00552
00553
00554
00555
00556
00557
00558
RtlRaiseStatus(Status);
00559
return;
00560 }
00561
00562
VOID
00563 RtlRaiseStatus (
00564 IN NTSTATUS Status
00565 )
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 {
00591
00592
RtlpRaiseStatus(
Status);
00593
return;
00594 }
00595
00596
VOID
00597
RtlpRaiseStatus (
00598 IN NTSTATUS Status
00599 )
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 {
00620
00621 ULONG ControlPc;
00622 CONTEXT ContextRecord;
00623 ULONG EstablisherFrame;
00624 EXCEPTION_RECORD ExceptionRecord;
00625 PRUNTIME_FUNCTION FunctionEntry;
00626 BOOLEAN InFunction;
00627 ULONG NextPc;
00628
00629
00630
00631
00632
00633 ExceptionRecord.ExceptionCode =
Status;
00634 ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)
NULL;
00635 ExceptionRecord.NumberParameters = 0;
00636 ExceptionRecord.ExceptionFlags =
EXCEPTION_NONCONTINUABLE;
00637
00638
00639
00640
00641
00642
00643
00644 RtlCaptureContext(&ContextRecord);
00645 ControlPc = ContextRecord.Lr - 4;
00646 FunctionEntry =
RtlLookupFunctionEntry(ControlPc);
00647 NextPc =
RtlVirtualUnwind(ControlPc,
00648 FunctionEntry,
00649 &ContextRecord,
00650 &InFunction,
00651 &EstablisherFrame,
00652 NULL,
00653 0,
00654 0xffffffff);
00655
00656 ContextRecord.Iar = NextPc + 4;
00657 ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Iar;
00658
Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, TRUE);
00659
00660
00661
00662
00663
00664
00665
00666
RtlRaiseStatus(Status);
00667
return;
00668 }
00669
00670
VOID
00671 RtlUnwind (
00672 IN PVOID TargetFrame OPTIONAL,
00673 IN PVOID TargetIp OPTIONAL,
00674 IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
00675 IN PVOID ReturnValue
00676 )
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 {
00719
00720 CONTEXT ContextRecord;
00721
00722
00723
00724
00725
00726
00727
RtlUnwind2(TargetFrame,
00728 TargetIp,
00729 ExceptionRecord,
00730 ReturnValue,
00731 &ContextRecord);
00732
00733
return;
00734 }
00735
00736
VOID
00737 RtlUnwind2 (
00738 IN PVOID TargetFrame OPTIONAL,
00739 IN PVOID TargetIp OPTIONAL,
00740 IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
00741 IN PVOID ReturnValue,
00742 IN PCONTEXT ContextRecord
00743 )
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786 {
00787
00788 ULONG ControlPc;
00789
DISPATCHER_CONTEXT DispatcherContext;
00790 EXCEPTION_DISPOSITION Disposition;
00791 ULONG EstablisherFrame;
00792 ULONG ExceptionFlags;
00793 EXCEPTION_RECORD ExceptionRecord1;
00794 PRUNTIME_FUNCTION FunctionEntry;
00795 BOOLEAN InFunction;
00796 ULONG HighLimit;
00797 ULONG LowLimit;
00798 ULONG NextPc;
00799
00800
00801
00802
00803
00804
00805
00806
RtlpGetStackLimits(&LowLimit, &HighLimit);
00807 RtlCaptureContext(ContextRecord);
00808 ControlPc = ContextRecord->Lr - 4;
00809 FunctionEntry =
RtlLookupFunctionEntry(ControlPc);
00810 NextPc =
RtlVirtualUnwind(ControlPc,
00811 FunctionEntry,
00812 ContextRecord,
00813 &InFunction,
00814 &EstablisherFrame,
00815
NULL,
00816 0,
00817 0xffffffff);
00818
00819 ControlPc = NextPc;
00820 ContextRecord->Iar = (ULONG)TargetIp;
00821
00822
00823
00824
00825
00826
00827
if (ARGUMENT_PRESENT(ExceptionRecord) ==
FALSE) {
00828 ExceptionRecord = &ExceptionRecord1;
00829 ExceptionRecord1.ExceptionCode = STATUS_UNWIND;
00830 ExceptionRecord1.ExceptionRecord =
NULL;
00831 ExceptionRecord1.ExceptionAddress = (PVOID)ControlPc;
00832 ExceptionRecord1.NumberParameters = 0;
00833 }
00834
00835
00836
00837
00838
00839
00840 ExceptionFlags =
EXCEPTION_UNWINDING;
00841
if (ARGUMENT_PRESENT(TargetFrame) ==
FALSE) {
00842 ExceptionRecord->ExceptionFlags |=
EXCEPTION_EXIT_UNWIND;
00843 }
00844
00845
00846
00847
00848
00849
00850
do {
00851
00852
00853
00854
00855
00856
00857 FunctionEntry =
RtlLookupFunctionEntry(ControlPc);
00858
00859
00860
00861
00862
00863
00864
00865
if (FunctionEntry !=
NULL) {
00866 NextPc =
RtlpVirtualUnwind(ControlPc,
00867 FunctionEntry,
00868 ContextRecord,
00869 &InFunction,
00870 &EstablisherFrame,
00871
NULL,
00872 LowLimit,
00873 HighLimit);
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
if ((EstablisherFrame < LowLimit) || (EstablisherFrame > HighLimit) ||
00885 ((ARGUMENT_PRESENT(TargetFrame) !=
FALSE) &&
00886 ((ULONG)TargetFrame < EstablisherFrame)) ||
00887 ((EstablisherFrame & 0x7) != 0)) {
00888
RAISE_EXCEPTION(STATUS_BAD_STACK, ExceptionRecord);
00889
00890 }
else if ((FunctionEntry->ExceptionHandler !=
NULL) && InFunction) {
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 DispatcherContext.ControlPc = ControlPc;
00909 DispatcherContext.FunctionEntry = FunctionEntry;
00910 DispatcherContext.EstablisherFrame = EstablisherFrame;
00911 DispatcherContext.ContextRecord = ContextRecord;
00912
00913
00914
00915
00916
00917
do {
00918
00919
00920
00921
00922
00923
00924
if ((ULONG)TargetFrame == EstablisherFrame) {
00925 ExceptionFlags |=
EXCEPTION_TARGET_UNWIND;
00926 }
00927
00928 ExceptionRecord->ExceptionFlags = ExceptionFlags;
00929
00930
00931
00932
00933
00934
00935 ContextRecord->Gpr3 = (ULONG)ReturnValue;
00936 Disposition =
00937
RtlpExecuteHandlerForUnwind(ExceptionRecord,
00938 EstablisherFrame,
00939 ContextRecord,
00940 &DispatcherContext,
00941 FunctionEntry->ExceptionHandler);
00942
00943
00944
00945
00946
00947 ExceptionFlags &= ~(
EXCEPTION_COLLIDED_UNWIND |
00948
EXCEPTION_TARGET_UNWIND);
00949
00950
00951
00952
00953
00954
switch (Disposition) {
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
case ExceptionContinueSearch :
00966
if (EstablisherFrame != (ULONG)TargetFrame) {
00967 NextPc =
RtlVirtualUnwind(ControlPc,
00968 FunctionEntry,
00969 ContextRecord,
00970 &InFunction,
00971 &EstablisherFrame,
00972
NULL,
00973 0,
00974 0xffffffff);
00975 }
00976
00977
break;
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
case ExceptionCollidedUnwind :
00989 ControlPc = DispatcherContext.ControlPc;
00990 FunctionEntry = DispatcherContext.FunctionEntry;
00991 ContextRecord = DispatcherContext.ContextRecord;
00992 ContextRecord->Iar = (ULONG)TargetIp;
00993 ExceptionFlags |=
EXCEPTION_COLLIDED_UNWIND;
00994 EstablisherFrame = DispatcherContext.EstablisherFrame;
00995
break;
00996
00997
00998
00999
01000
01001
01002
01003
default :
01004
RAISE_EXCEPTION(STATUS_INVALID_DISPOSITION, ExceptionRecord);
01005 }
01006
01007 }
while ((ExceptionFlags &
EXCEPTION_COLLIDED_UNWIND) != 0);
01008
01009 }
else {
01010
01011
01012
01013
01014
01015
01016
if (EstablisherFrame != (ULONG)TargetFrame) {
01017 NextPc =
RtlVirtualUnwind(ControlPc,
01018 FunctionEntry,
01019 ContextRecord,
01020 &InFunction,
01021 &EstablisherFrame,
01022
NULL,
01023 0,
01024 0xffffffff);
01025 }
01026 }
01027
01028 }
else {
01029
01030
01031
01032
01033 NextPc =
RtlVirtualUnwind(ControlPc,
01034 FunctionEntry,
01035 ContextRecord,
01036 &InFunction,
01037 &EstablisherFrame,
01038
NULL,
01039 0,
01040 0xffffffff);
01041
01042
01043
01044
01045
01046
01047
if (NextPc == ControlPc) {
01048
RtlRaiseStatus(STATUS_BAD_FUNCTION_TABLE);
01049 }
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060 ControlPc = NextPc;
01061
01062 }
while ((EstablisherFrame < HighLimit) &&
01063 (EstablisherFrame != (ULONG)TargetFrame));
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
if (EstablisherFrame == (ULONG)TargetFrame) {
01074
01075
01076
01077
01078
01079
01080 CONTEXT TocContext;
01081 RtlMoveMemory((PVOID)&TocContext, ContextRecord,
sizeof(CONTEXT));
01082 ControlPc = ContextRecord->Iar;
01083 FunctionEntry =
RtlLookupFunctionEntry(ControlPc);
01084 NextPc =
RtlVirtualUnwind(ControlPc,
01085 FunctionEntry,
01086 &TocContext,
01087 &InFunction,
01088 &EstablisherFrame,
01089
NULL,
01090 0xffffffff,
01091 0);
01092 ContextRecord->Gpr2 = TocContext.Gpr2;
01093 ContextRecord->Gpr3 = (ULONG)ReturnValue;
01094
RtlpRestoreContext(ContextRecord, ExceptionRecord);
01095
01096 }
else {
01097 ZwRaiseException(ExceptionRecord, ContextRecord,
FALSE);
01098 }
01099 }
01100
01101 ULONG
01102 RtlpVirtualUnwind (
01103 IN ULONG ControlPc,
01104 IN PRUNTIME_FUNCTION FunctionEntry,
01105 IN PCONTEXT ContextRecord,
01106 OUT PBOOLEAN InFunction,
01107 OUT PULONG EstablisherFrame,
01108 IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL,
01109 IN ULONG LowStackLimit,
01110 IN ULONG HighStackLimit
01111 )
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177 {
01178
01179 CONTEXT LocalContext;
01180
01181
01182
01183
01184
01185
01186
01187 RtlMoveMemory((PVOID)&LocalContext, ContextRecord,
sizeof(CONTEXT));
01188
return RtlVirtualUnwind(ControlPc,
01189 FunctionEntry,
01190 &LocalContext,
01191 InFunction,
01192 EstablisherFrame,
01193 ContextPointers,
01194 LowStackLimit,
01195 HighStackLimit);
01196 }