00045 :
00046
00047 This routine returns
the address of
the routine that called
the routine
00048 that called
this routine, and
the routine that called
the routine that
00049 called
this routine. For example,
if A called B called C which called
00050
this routine,
the return addresses in
A and B would be returned.
00051
00052 Arguments:
00053
00054 CallersPc - Supplies a pointer to a variable that receives
the address
00055 of
the caller of
the caller of
this routine (B).
00056
00057 CallersCallersPc - Supplies a pointer to a variable that receives
the
00058 address of
the caller of
the caller of
the caller of
this routine
00059 (
A).
00060
00061 Return Value:
00062
00063 None.
00064
00065 Note:
00066
00067 If either of
the calling stack frames exceeds
the limits of
the stack,
00068 they are set to
NULL.
00069
00070 --*/
00071
00072 {
00073
00074 CONTEXT ContextRecord;
00075 ULONG EstablisherFrame;
00076 PRUNTIME_FUNCTION FunctionEntry;
00077 BOOLEAN InFunction;
00078 ULONG NextPc;
00079 ULONG HighLimit, LowLimit;
00080
00081
00082
00083
00084
00085
00086 *CallersPc =
NULL;
00087 *CallersCallersPc =
NULL;
00088
00089
00090
00091
00092
00093 RtlCaptureContext(&ContextRecord);
00094 NextPc = ContextRecord.Lr;
00095
00096
00097
00098
00099
00100
RtlpGetStackLimits(&LowLimit, &HighLimit);
00101
00102
00103
00104
00105
00106 FunctionEntry =
RtlLookupFunctionEntry(NextPc);
00107
if (FunctionEntry !=
NULL) {
00108
00109
00110
00111
00112
00113
00114 NextPc =
RtlVirtualUnwind(NextPc,
00115 FunctionEntry,
00116 &ContextRecord,
00117 &InFunction,
00118 &EstablisherFrame,
00119 NULL,
00120 0,
00121 0xffffffff);
00122
00123
00124
00125
00126
00127 FunctionEntry =
RtlLookupFunctionEntry(NextPc);
00128
if ((FunctionEntry !=
NULL) && (ContextRecord.Gpr1 < HighLimit)) {
00129
00130
00131
00132
00133
00134
00135
00136 NextPc =
RtlVirtualUnwind(NextPc,
00137 FunctionEntry,
00138 &ContextRecord,
00139 &InFunction,
00140 &EstablisherFrame,
00141 NULL,
00142 0,
00143 0xffffffff);
00144
00145 *CallersPc = (PVOID)NextPc;
00146
00147
00148
00149
00150
00151
00152 FunctionEntry =
RtlLookupFunctionEntry(NextPc);
00153
if ((FunctionEntry !=
NULL) && (ContextRecord.Gpr1 < HighLimit)) {
00154
00155
00156
00157
00158
00159
00160
00161
00162 NextPc =
RtlVirtualUnwind(NextPc,
00163 FunctionEntry,
00164 &ContextRecord,
00165 &InFunction,
00166 &EstablisherFrame,
00167 NULL,
00168 0,
00169 0xffffffff);
00170
00171
00172 *CallersCallersPc = (PVOID)NextPc;
00173 }
00174 }
00175 }
00176
00177
return;
00178 }