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