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