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