You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
8.5 KiB
226 lines
8.5 KiB
#include <windows.h>
|
|
#include <rpc.h>
|
|
#include <tchar.h>
|
|
|
|
#include "faxutil.h"
|
|
|
|
#ifdef DEBUG
|
|
VOID
|
|
DumpRPCExtendedStatus ()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps the extended RPC error status list to the debug console.
|
|
This function only works in debug builds.
|
|
To enable RPC extended status on the machine do the following:
|
|
1. run mmc.exe
|
|
2. Goto File | Add/Remove Snap-in...
|
|
3. Press "Add..." button
|
|
4. Select "Group Policy" and Press "Add"
|
|
5. Select "Local Computer" and press "Finish"
|
|
6. Press "Close"
|
|
7. Press "Ok"
|
|
8. Expand Local Computer Policy | Computer Configuration | Administrative Templates | System |
|
|
Remote Procedure Call
|
|
9. Select the properties of "Propagation of Extended Error Information"
|
|
10. Select "Enabled"
|
|
11. In the "Propagation of Extended Error Information" combo-box, select "On".
|
|
12. In the "...Exceptions" edit-box, leave the text empty.
|
|
13. Press "Ok".
|
|
14. Close MMC (no need to save anything).
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Remarks:
|
|
|
|
This function should be called as soon as an error / exception
|
|
is returned from calling an RPC function.
|
|
|
|
--*/
|
|
{
|
|
DEBUG_FUNCTION_NAME(TEXT("DumpRPCExtendedStatus"));
|
|
|
|
|
|
typedef RPC_STATUS (RPC_ENTRY *PRPCERRORSTARTENUMERATION) (RPC_ERROR_ENUM_HANDLE *);
|
|
typedef RPC_STATUS (RPC_ENTRY *PRPCERRORGETNEXTRECORD) (RPC_ERROR_ENUM_HANDLE *, BOOL, RPC_EXTENDED_ERROR_INFO *);
|
|
typedef RPC_STATUS (RPC_ENTRY *PRPCERRORENDENUMERATION) (RPC_ERROR_ENUM_HANDLE *);
|
|
|
|
PRPCERRORSTARTENUMERATION pfRpcErrorStartEnumeration = NULL;
|
|
PRPCERRORGETNEXTRECORD pfRpcErrorGetNextRecord = NULL;
|
|
PRPCERRORENDENUMERATION pfRpcErrorEndEnumeration = NULL;
|
|
HMODULE hMod = NULL;
|
|
|
|
|
|
if (!IsWinXPOS())
|
|
{
|
|
//
|
|
// RPC Extended errors are not supported in down-level clients
|
|
//
|
|
return;
|
|
}
|
|
|
|
hMod = LoadLibrary (TEXT("rpcrt4.dll"));
|
|
if (!hMod)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, _T("LoadLibrary(rpcrt4.dll) failed with %ld"), GetLastError ());
|
|
return;
|
|
}
|
|
pfRpcErrorStartEnumeration = (PRPCERRORSTARTENUMERATION)GetProcAddress (hMod, "RpcErrorStartEnumeration");
|
|
pfRpcErrorGetNextRecord = (PRPCERRORGETNEXTRECORD) GetProcAddress (hMod, "RpcErrorGetNextRecord");
|
|
pfRpcErrorEndEnumeration = (PRPCERRORENDENUMERATION) GetProcAddress (hMod, "RpcErrorEndEnumeration");
|
|
if (!pfRpcErrorStartEnumeration ||
|
|
!pfRpcErrorGetNextRecord ||
|
|
!pfRpcErrorEndEnumeration)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, _T("Can't link with rpcrt4.dll - failed with %ld"), GetLastError ());
|
|
FreeLibrary (hMod);
|
|
return;
|
|
}
|
|
|
|
RPC_STATUS Status2;
|
|
RPC_ERROR_ENUM_HANDLE EnumHandle;
|
|
|
|
Status2 = pfRpcErrorStartEnumeration(&EnumHandle);
|
|
if (Status2 == RPC_S_ENTRY_NOT_FOUND)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, _T("RPC_S_ENTRY_NOT_FOUND returned from RpcErrorStartEnumeration."));
|
|
FreeLibrary (hMod);
|
|
return;
|
|
}
|
|
else if (Status2 != RPC_S_OK)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, _T("Couldn't get EEInfo: %d"), Status2);
|
|
FreeLibrary (hMod);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
RPC_EXTENDED_ERROR_INFO ErrorInfo;
|
|
BOOL Result;
|
|
BOOL CopyStrings = TRUE;
|
|
BOOL fUseFileTime = TRUE;
|
|
SYSTEMTIME *SystemTimeToUse;
|
|
SYSTEMTIME SystemTimeBuffer;
|
|
|
|
while (Status2 == RPC_S_OK)
|
|
{
|
|
ErrorInfo.Version = RPC_EEINFO_VERSION;
|
|
ErrorInfo.Flags = 0;
|
|
ErrorInfo.NumberOfParameters = 4;
|
|
if (fUseFileTime)
|
|
{
|
|
ErrorInfo.Flags |= EEInfoUseFileTime;
|
|
}
|
|
|
|
Status2 = pfRpcErrorGetNextRecord(&EnumHandle, CopyStrings, &ErrorInfo);
|
|
if (Status2 == RPC_S_ENTRY_NOT_FOUND)
|
|
{
|
|
break;
|
|
}
|
|
else if (Status2 != RPC_S_OK)
|
|
{
|
|
DebugPrintEx(DEBUG_ERR, _T("Couldn't finish enumeration: %d"), Status2);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
int i;
|
|
|
|
if (ErrorInfo.ComputerName)
|
|
{
|
|
DebugPrintEx(DEBUG_MSG, _T("ComputerName is %s"), ErrorInfo.ComputerName);
|
|
if (CopyStrings)
|
|
{
|
|
Result = HeapFree(GetProcessHeap(), 0, ErrorInfo.ComputerName);
|
|
Assert(Result);
|
|
}
|
|
}
|
|
DebugPrintEx(DEBUG_MSG, _T("ProcessID is %d"), ErrorInfo.ProcessID);
|
|
if (fUseFileTime)
|
|
{
|
|
Result = FileTimeToSystemTime(&ErrorInfo.u.FileTime,
|
|
&SystemTimeBuffer);
|
|
Assert(Result);
|
|
SystemTimeToUse = &SystemTimeBuffer;
|
|
}
|
|
else
|
|
{
|
|
SystemTimeToUse = &ErrorInfo.u.SystemTime;
|
|
}
|
|
DebugPrintEx(DEBUG_MSG, _T("System Time is: %d/%d/%d %d:%d:%d:%d"),
|
|
SystemTimeToUse->wMonth,
|
|
SystemTimeToUse->wDay,
|
|
SystemTimeToUse->wYear,
|
|
SystemTimeToUse->wHour,
|
|
SystemTimeToUse->wMinute,
|
|
SystemTimeToUse->wSecond,
|
|
SystemTimeToUse->wMilliseconds);
|
|
DebugPrintEx(DEBUG_MSG, _T("Generating component is %d"), ErrorInfo.GeneratingComponent);
|
|
DebugPrintEx(DEBUG_MSG, _T("Status is %d"), ErrorInfo.Status);
|
|
DebugPrintEx(DEBUG_MSG, _T("Detection location is %d"), (int)ErrorInfo.DetectionLocation);
|
|
DebugPrintEx(DEBUG_MSG, _T("Flags is %d"), ErrorInfo.Flags);
|
|
DebugPrintEx(DEBUG_MSG, _T("NumberOfParameters is %d"), ErrorInfo.NumberOfParameters);
|
|
for (i = 0; i < ErrorInfo.NumberOfParameters; i ++)
|
|
{
|
|
switch(ErrorInfo.Parameters[i].ParameterType)
|
|
{
|
|
case eeptAnsiString:
|
|
DebugPrintEx(DEBUG_MSG, _T("Ansi string: %S"), ErrorInfo.Parameters[i].u.AnsiString);
|
|
if (CopyStrings)
|
|
{
|
|
Result = HeapFree(GetProcessHeap(), 0,
|
|
ErrorInfo.Parameters[i].u.AnsiString);
|
|
Assert(Result);
|
|
}
|
|
break;
|
|
|
|
case eeptUnicodeString:
|
|
DebugPrintEx(DEBUG_MSG, _T("Unicode string: %s"), ErrorInfo.Parameters[i].u.UnicodeString);
|
|
if (CopyStrings)
|
|
{
|
|
Result = HeapFree(GetProcessHeap(), 0,
|
|
ErrorInfo.Parameters[i].u.UnicodeString);
|
|
Assert(Result);
|
|
}
|
|
break;
|
|
|
|
case eeptLongVal:
|
|
DebugPrintEx(DEBUG_MSG, _T("Long val: %d"), ErrorInfo.Parameters[i].u.LVal);
|
|
break;
|
|
|
|
case eeptShortVal:
|
|
DebugPrintEx(DEBUG_MSG, _T("Short val: %d"), (int)ErrorInfo.Parameters[i].u.SVal);
|
|
break;
|
|
|
|
case eeptPointerVal:
|
|
DebugPrintEx(DEBUG_MSG, _T("Pointer val: %d"), ErrorInfo.Parameters[i].u.PVal);
|
|
break;
|
|
|
|
case eeptNone:
|
|
DebugPrintEx(DEBUG_MSG, _T("Truncated"));
|
|
break;
|
|
|
|
default:
|
|
DebugPrintEx(DEBUG_MSG, _T("Invalid type: %d"), ErrorInfo.Parameters[i].ParameterType);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pfRpcErrorEndEnumeration(&EnumHandle);
|
|
}
|
|
FreeLibrary (hMod);
|
|
} // DumpRPCExtendedStatus
|
|
#else // ifdef DEUBG
|
|
VOID
|
|
DumpRPCExtendedStatus ()
|
|
{
|
|
}
|
|
#endif // ifdef DEBUG
|
|
|