#include #include #include #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