PRB: 401Comupd.exe Makes System Unbootable

ID: Q221836


The information in this article applies to:
  • Microsoft Win32 Software Development Kit (SDK), on platform(s):
    • Microsoft Windows versions 95, 98
    • Microsoft Windows NT 4.0


SYMPTOMS

There is a problem with the 401Comupd.exe installer. If the version of Comctl32.dll currently installed on the target system does not need to be updated, the installer marks the existing Comctl32.dll for deletion on the next reboot, but does not replace the DLL. This results in a system that has no Comctl32.dll, and therefore the system can not boot.

This problem occurs only if the existing Comctl32.dll is version 4.72.3110 or later. If the existing DLL is an earlier version, the installer works correctly by replacing the DLL on the next reboot.


RESOLUTION

To work around this problem, determine if the existing version of Comctl32.dll needs to be updated before running the 401Comupd.exe installer. The code below demonstrates how to do this. The code below can be used as a standalone EXE that determines if the common controls DLL needs to be updated, and runs the 401Comupd.exe installer if necessary.


/**************************************************************************
   #include statements
**************************************************************************/ 

#include <windows.h>
#include <shlwapi.h>

/**************************************************************************
   private function prototypes
**************************************************************************/ 

int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
HRESULT ShouldInstallUpdate(VOID);
HRESULT GetComCtlVersion(LPDWORD, LPDWORD, LPDWORD);

/**************************************************************************

   WinMain()

**************************************************************************/ 

int PASCAL WinMain(  HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine,
                     int nCmdShow)
{
BOOL  fSilent = FALSE;
LPSTR pszTemp;
HRESULT hr;

//See if this should be run in silent mode.
for(pszTemp = lpCmdLine; pszTemp && *pszTemp; pszTemp = CharNext(pszTemp))
   {
   if(('/' == *pszTemp) || ('-' == *pszTemp))
      {
      pszTemp = CharNext(pszTemp);
      if(('q' == *pszTemp) || ('Q' == *pszTemp))
         {
         fSilent = TRUE;
         break;
         }
      }
   }

hr = ShouldInstallUpdate();

if (SUCCEEDED(hr))
   {
   if(S_OK == hr)
      {
      if(!fSilent)
         {
         MessageBox( NULL, 
                     "The COMCTL32.DLL is an older version. 401COMUPD.EXE should be run to update the common controls on this system.", 
                     "Install Updated Common Controls?", 
                     MB_OK | MB_ICONINFORMATION);
         }

	   //ShellExecute(NULL, NULL, TEXT("401COMUPD.EXE"), lpCmdLine, NULL, SW_SHOWNORMAL);
      }
	else
      {
      if(!fSilent)
         {
         MessageBox( NULL, 
                     "The COMCTL32.DLL installed on this system does not need to be updated.", 
                     "Install Updated Common Controls?", 
                     MB_OK | MB_ICONINFORMATION);
         }
      }
   }
else  // ShouldInstallUpdate failed due to unexpected reason.
   {
      MessageBox( NULL, 
                  "Program error - COMCTL32.DLL version undetermined.", 
                  "Install Updated Common Controls?", 
                  MB_OK | MB_ICONINFORMATION);
   }

return 0;
}

/**************************************************************************

   ShouldInstallUpdate()

   returns:  
     S_OK    if current version of COMCTL32.DLL is <  4.72.3110
     S_FALSE if current version of COMCTL32.DLL is >= 4.72.3110
     E_xxx   if current version of COMCTL32.DLL could not be determined

     E_xxx is an error code depending on return value of GetComCtlVersion

**************************************************************************/ 

HRESULT ShouldInstallUpdate(VOID)
{
HRESULT  hr;
DWORD dwMajor,
      dwMinor,
      dwBuildNumber;

hr = GetComCtlVersion(&dwMajor, &dwMinor, &dwBuildNumber);

if(SUCCEEDED(hr))
   {
   if(dwMajor < 4)
      return S_OK;

   if(dwMajor > 4)
      return S_FALSE;

   if(dwMinor < 72)
      return S_OK;

   if(dwMinor > 72)
      return S_FALSE;

      if(dwBuildNumber < 3110)
         return S_OK;
      
      return S_FALSE;
      }

return hr;
}

/**************************************************************************

   GetComCtlVersion()

**************************************************************************/ 

HRESULT GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor, LPDWORD pdwBuildNumber)
{
HINSTANCE   hComCtl;

if(   IsBadWritePtr(pdwMajor, sizeof(DWORD)) || 
      IsBadWritePtr(pdwMinor, sizeof(DWORD)) ||
      IsBadWritePtr(pdwBuildNumber, sizeof(DWORD)))
   return E_INVALIDARG;

//Load the DLL.
hComCtl = LoadLibrary("comctl32.dll");

if(hComCtl)
   {
   HRESULT           hr = S_OK;
   DLLGETVERSIONPROC pDllGetVersion;
   
   /*
   You must get this function explicitly because earlier versions of the DLL 
   don't implement this function. That makes the lack of implementation of the 
   function a version marker in itself.
   */ 
   pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hComCtl, "DllGetVersion");
   
   if(pDllGetVersion)
      {
      DLLVERSIONINFO    dvi;
      
      ZeroMemory(&dvi, sizeof(dvi));
      dvi.cbSize = sizeof(dvi);
   
      hr = (*pDllGetVersion)(&dvi);
      
      if(SUCCEEDED(hr))
         {
         *pdwMajor = dvi.dwMajorVersion;
         *pdwMinor = dvi.dwMinorVersion;
         *pdwBuildNumber = dvi.dwBuildNumber;
         }
      else
         {
         hr = E_FAIL;
         }   
      }
   else
      {
      /*
      If GetProcAddress failed, then the DLL is a version previous to the one 
      shipped with IE 3.x.
      */ 
      *pdwMajor = 4;
      *pdwMinor = 0;
      *pdwBuildNumber = 950;
      }
   
   FreeLibrary(hComCtl);

   return hr;
   }

return E_FAIL;
}
 


STATUS

This problem has been corrected in the version of 401Comupd.exe currently available from Microsoft's web site. This version installs version 4.72.3611.1900 or later of Comctl32.dll. You should download the latest version of 401Comupd.exe to avoid this problem.


REFERENCES

For additional information, please see the following article in the Microsoft Knowledge Base:

Q186176 INFO: Redistribution of Comctl32.dll

Additional query words: 401COMUPD

Keywords : kbCtrl kbNTOS400 kbSDKPlatform kbWinOS95 kbWinOS98
Version : WINDOWS:95,98
Platform : WINDOWS
Issue type : kbprb


Last Reviewed: September 28, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.