Monthly Archives: April 2008

Available hotfixes for VC2005-SP1 / VC2008 RTM / VC2008-SP1

There are already several hotfixes available for VC2005 SP1 and VC2008 RTM. Here is a short overview:

Updated: 2008-11-06
Updated: 2009-03-09
Updated: 2009-03-13
Updated: 2009-03-18
Updated: 2009-05-08
Updated: 2009-05-13
Updated: 2009-05-23
Updated: 2009-10-06

MFCNext / VS2008 VC++ Feature Pack is RTM

The feature Pack for VC++ 2008 is now available for download.

It is some kind of confusing:
You can download the feature Pack for the englisch version only (ENU)!

If you have installed a localized version of VS (e.g. german), you must wait until the release of SP1. Hopefully the ENU-SP1 will also include the Feature Pack…

If you have a non-english OS the installation will fail! You need to change the system-language and formats to “en-us” and re-run the installation… this is a typically US bug…

Also one note: If you want to use the new Ribbon UI (Office 2007 UI, also known as Fluent UI), you must agree to the Office 2007 license!

Here are the links:
Download-Site
Direct download link
Redistributable package (x86)
Docu: MFC Feature Pack
Docu: TR1 Extensions

Just upgrade to VS2008! Even without an existing license!

According to the Microsoft Website Visual Studio 2008 Pricing there is no need to buy the full product. You can always buy the upgrade for VS2008 Standard or Professional if you have:

  • An earlier version of Microsoft Visual Studio
  • Any other developer tool (including free developer tools, such as Visual Studio Express Editions or Eclipse)

That looks interesting! So, download the express edition, then you can buy the upgrade version of VS2008!

I just made a copy of the page to be sure, that if MS removes this sentense in the future, I have a copy to witness:
VisualStudio2008Pricing_2008-04-04.xps

Unhandled exceptions in VC8 and above… for x86 and x64

Starting with VC8 (VS2005) it is not possible to catch all unhandled exceptions with your installed exception-filter (via SetUnhandledExceptionFilter). In some situations, the CRT forces the call of WER (Windows Error Reporting). One situation (/GS buffer overruns) can never be catched in your filter. If you want to catch all exception inside your filter, you need to intercept calls to SetUnhandledExceptionFilter to prevent the removing of all previous installed filters.

See also my previous post about this problem:
“SetUnhandledExceptionFilter” and VC8″

Here is the code to “hook” the SetUnhandledExceptionFilter which works now for x86 and x64:

#include 
#include 
#include 

#if defined _M_X64 || defined _M_IX86
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI 
  MyDummySetUnhandledExceptionFilter(
  LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
{
  return NULL;
}
#else
#error "This code works only for x86 and x64!"
#endif

BOOL PreventSetUnhandledExceptionFilter()
{
  HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
  if (hKernel32 == NULL) return FALSE;
  void *pOrgEntry = GetProcAddress(hKernel32, 
    "SetUnhandledExceptionFilter");
  if(pOrgEntry == NULL) return FALSE;

  DWORD dwOldProtect = 0;
  SIZE_T jmpSize = 5;
#ifdef _M_X64
  jmpSize = 13;
#endif
  BOOL bProt = VirtualProtect(pOrgEntry, jmpSize, 
    PAGE_EXECUTE_READWRITE, &dwOldProtect);
  BYTE newJump[20];
  void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
#ifdef _M_IX86
  DWORD dwOrgEntryAddr = (DWORD) pOrgEntry;
  dwOrgEntryAddr += jmpSize; // add 5 for 5 op-codes for jmp rel32
  DWORD dwNewEntryAddr = (DWORD) pNewFunc;
  DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
  // JMP rel32: Jump near, relative, displacement relative to next instruction.
  newJump[0] = 0xE9;  // JMP rel32
  memcpy(&newJump[1], &dwRelativeAddr, sizeof(pNewFunc));
#elif _M_X64
  // We must use R10 or R11, because these are "scratch" registers 
  // which need not to be preserved accross function calls
  // For more info see: Register Usage for x64 64-Bit
  // http://msdn.microsoft.com/en-us/library/ms794547.aspx
  // Thanks to Matthew Smith!!!
  newJump[0] = 0x49;  // MOV R11, ...
  newJump[1] = 0xBB;  // ...
  memcpy(&newJump[2], &pNewFunc, sizeof (pNewFunc));
  //pCur += sizeof (ULONG_PTR);
  newJump[10] = 0x41;  // JMP R11, ...
  newJump[11] = 0xFF;  // ...
  newJump[12] = 0xE3;  // ...
#endif
  SIZE_T bytesWritten;
  BOOL bRet = WriteProcessMemory(GetCurrentProcess(),
    pOrgEntry, newJump, jmpSize, &bytesWritten);

  if (bProt != FALSE)
  {
    DWORD dwBuf;
    VirtualProtect(pOrgEntry, jmpSize, dwOldProtect, &dwBuf);
  }
  return bRet;
}

LONG WINAPI MyUnhandledExceptionFilter(
struct _EXCEPTION_POINTERS *lpTopLevelExceptionFilter)
{
  // TODO: MiniDumpWriteDump
  FatalAppExit(0, _T("Unhandled Exception occured!"));
  return EXCEPTION_CONTINUE_SEARCH;
}

int _tmain()
{
  SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
  BOOL bRet = PreventSetUnhandledExceptionFilter();
  _tprintf(_T("Prevented: %d"), bRet);

  abort();  // force Dr.Watson in release!
}