Microsoft KB Archive/221836

{|
 * width="100%"|

PRB: 401Comupd.exe Makes System Unbootable

 * }

Q221836

-

The information in this article applies to:


 * Microsoft Win32 Software Development Kit (SDK), on platform(s):
 * Microsoft Windows 98
 * Microsoft Windows 95
 * Microsoft Windows NT Server version 4.0
 * Microsoft Windows NT Workstation version 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


 * 1) include 
 * 2) include 

/**************************************************************************  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.