// Msie.cpp : Implementation of CMsieApp and DLL registration. #include "stdafx.h" #include "Msie.h" #include "regkeys.h" #include "resdefs.h" #include #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif CMsieApp theApp; const GUID CDECL BASED_CODE _tlid = { 0x25959bec, 0xe700, 0x11d2, { 0xa7, 0xaf, 0, 0xc0, 0x4f, 0x80, 0x62, 0 } }; const WORD _wVerMajor = 1; const WORD _wVerMinor = 0; const LPCSTR CLSID_MSIE = "{25959BEF-E700-11D2-A7AF-00C04F806200}"; const LPCSTR IE_REPAIR_CMD = "rundll32 setupwbv.dll,IE6Maintenance \"%s\\Setup\\SETUP.EXE\" /g \"%s\\%s\""; const LPCSTR OCX_FILE_IN_COMMON = "Microsoft Shared\\MSInfo\\ieinfo5.ocx"; const LPCSTR MOF_FILE_PATH = "%SystemRoot%\\System32\\WBEM\\MOF"; const LPCSTR MOF_FILE = "ieinfo5.mof"; const MAX_KEY_LENGTH = 256; //////////////////////////////////////////////////////////////////////////// // CMsieApp::InitInstance - DLL initialization BOOL CMsieApp::InitInstance() { BOOL bInit = COleControlModule::InitInstance(); if (bInit) { m_fTemplateLoaded = FALSE; m_pTemplateInfo = NULL; m_dwTemplateInfoLen = 0; } return bInit; } //////////////////////////////////////////////////////////////////////////// // CMsieApp::ExitInstance - DLL termination int CMsieApp::ExitInstance() { if (m_pTemplateInfo != NULL) { delete m_pTemplateInfo; m_pTemplateInfo = NULL; } return COleControlModule::ExitInstance(); } //----------------------------------------------------------------------------- // AppGetTemplate is the entry point for the app object from outside the DLL. // It's called by the exported function GetTemplate. The reconstructed template // file should be returned to the caller as a pointer in the pBuffer parameter. // // If a NULL pointer is passed for pBuffer, we are free to delete the internal // buffer storing the template file. //----------------------------------------------------------------------------- DWORD CMsieApp::AppGetTemplate(void ** ppBuffer) { if (!m_fTemplateLoaded) { LoadTemplate(); m_fTemplateLoaded = TRUE; } if (ppBuffer == NULL) { if (m_pTemplateInfo) delete m_pTemplateInfo; m_pTemplateInfo = NULL; m_dwTemplateInfoLen = 0; m_fTemplateLoaded = FALSE; return 0; } *ppBuffer = (void *)m_pTemplateInfo; return m_dwTemplateInfoLen; } //----------------------------------------------------------------------------- // This table of keywords is used during the reconstruction process. It matches // exactly the table used during the conversion from NFT to resources, and it // MUST NOT be modified, or the reconstructed information will be bogus. //----------------------------------------------------------------------------- #define KEYWORD_COUNT 19 char * KEYWORD_STRING[KEYWORD_COUNT] = { "node", "columns", "line", "field", "enumlines", "(", ")", "{", "}", ",", "\"basic\"", "\"advanced\"", "\"BASIC\"", "\"ADVANCED\"", "\"static\"", "\"LEXICAL\"", "\"VALUE\"", "\"NONE\"", "\"\"" }; //----------------------------------------------------------------------------- // The LoadTemplate function needs to load the template information out of // our resources, and create a buffer which contains the restored template // file to return to our caller (through AppGetTemplate). //----------------------------------------------------------------------------- void CMsieApp::LoadTemplate() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CMapWordToPtr mapNonLocalized; HRSRC hrsrcNFN; HGLOBAL hglbNFN; unsigned char *pData; WORD wID; CString strToken, *pstrToken; // In debug mode, we'll reconstruct the original template file for comparison. /*#ifdef DBG CFile fileRestore(_T("ie-restore.nft"), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite); #endif*/ // Load the non-localized strings from the custom resource type and create // a map of ID to strings. Because these are non-localized strings, they // will not be stored as Unicode. Each item in the stream is a 2 byte word // ID followed by a null-terminated string. A zero ID indicates the end of // the stream. hrsrcNFN = FindResource(AfxGetResourceHandle(), _T("#1"), _T("MSINonLocalizedTokens")); hglbNFN = LoadResource(AfxGetResourceHandle(), hrsrcNFN); pData = (unsigned char *)LockResource(hglbNFN); while (pData && *((WORD UNALIGNED *)pData)) { wID = (WORD)(((WORD)*pData++) << 8); // deal with the byte order explicitly to avoid wID |= (WORD)*pData++; // endian problems. pstrToken = new CString((char *)pData); pData += strlen((char *)pData) + 1; if (pstrToken) mapNonLocalized.SetAt(wID, (void *)pstrToken); } // Load the binary stream of token identifiers into memory. HRSRC hrsrcNFB = FindResource(AfxGetResourceHandle(), _T("#1"), _T("MSITemplateStream")); HGLOBAL hglbNFB = LoadResource(AfxGetResourceHandle(), hrsrcNFB); unsigned char *pStream = (unsigned char *) LockResource(hglbNFB); if (pStream) { // The first DWORD in the stream is the size of the original text file. We'll // use this to allocate our buffer to store the reconstituted file. DWORD dwSize; dwSize = ((DWORD)*pStream++) << 24; dwSize |= ((DWORD)*pStream++) << 16; dwSize |= ((DWORD)*pStream++) << 8; dwSize |= ((DWORD)*pStream++); // The size stored is for an Ansi text file. We need to adjust for the // fact that our reconstituted file will be Unicode. We also want to add // a word to the front of the stream to hold the Unicode file marker (so // MSInfo can use the same functions to read a file or this stream). dwSize *= sizeof(WCHAR); // adjust for Unicode dwSize += sizeof(WORD); // add room for Unicode file marker m_pTemplateInfo = new unsigned char[dwSize]; m_dwTemplateInfoLen = 0; if (m_pTemplateInfo == NULL) return; // Write the Unicode file marker. wID = 0xFEFF; memcpy(&m_pTemplateInfo[m_dwTemplateInfoLen], (void *)&wID, sizeof(WORD)); m_dwTemplateInfoLen += sizeof(WORD); // Process the stream a token at a time. For each new item in the stream, we // process it as follows: // // 1. If ((byte & 0x80) == 0x00), use the byte to lookup a KEYWORD_STRING. // 2. If ((byte & 0xC0) == 0x80), use the byte and the next byte as a word // ID to lookup a non-localized token from mapNonLocalized. // 3. Else ((byte & 0xC0) == 0xC0), use the byte and the next byte as a word // ID to lookup a localized token from the resources of this DLL. while (pStream && *pStream) { if ((*pStream & 0x80) == 0x00) { // A byte with the high bit clear refers to a keyword. Look up the keyword // from the table, and add it to the restored file. wID = (WORD)(((WORD)*pStream++) - 1); ASSERT(wID <= KEYWORD_COUNT); if (wID <= KEYWORD_COUNT) strToken = KEYWORD_STRING[wID]; } else { wID = (WORD)(((WORD)*pStream++) << 8); // deal with the byte order explicitly to avoid wID |= (WORD)*pStream++; // endian problems. if ((wID & 0xC000) == 0x8000) { // A byte with the high bit set, but the next to high bit clear indicates // the ID is actually a word, and should be used to get a non-localized // string. Get the string out of the map we created and add it to the file. if (mapNonLocalized.Lookup(((WORD)(wID & 0x7FFF)), (void *&)pstrToken)) strToken = *pstrToken; else ASSERT(FALSE); } else { // A byte with the two MSB set indicates that the ID is a word, and should // be used to reference a localized string out of the string table in this // module's resources. This string will be UNICODE. VERIFY(strToken.LoadString((wID & 0x3FFF) + IDS_MSITEMPLATEBASE)); strToken = _T("\"") + strToken + _T("\""); } } // Store the token on the end of our buffer. The data in this buffer must // be Unicode, so we'll need to convert the string if necessary. //v-stlowe if (m_dwTemplateInfoLen + strToken.GetLength() * sizeof(WCHAR) < dwSize) if (m_dwTemplateInfoLen + strToken.GetLength() < dwSize) { // Converting to strToken to Unicode WCHAR *pwchToken; pwchToken = new WCHAR[strToken.GetLength() + 1]; //v-stlowe ::MultiByteToWideChar(CP_ACP, 0, strToken, -1, pwchToken, (strToken.GetLength() + 1) * sizeof(WCHAR)); USES_CONVERSION; wcscpy(pwchToken,T2W((LPTSTR)(LPCTSTR)strToken)); // Copying Unicode string to buffer memcpy(&m_pTemplateInfo[m_dwTemplateInfoLen], (void *)pwchToken, wcslen(pwchToken) * sizeof(WCHAR)); m_dwTemplateInfoLen += wcslen(pwchToken) * sizeof(WCHAR); delete pwchToken; /*memcpy(&m_pTemplateInfo[m_dwTemplateInfoLen],(void *) strToken.GetBuffer(strToken.GetLength()),strToken.GetLength()); strToken.ReleaseBuffer();*/ } else ASSERT(FALSE); /*#ifdef DBG if (strToken == CString(_T("}")) || strToken == CString(_T("{")) || strToken == CString(_T(")"))) strToken += CString(_T("\r\n")); fileRestore.Write((void *)(LPCTSTR)strToken, strToken.GetLength() * sizeof(TCHAR)); #endif*/ } } // Delete the contents of the lookup table. #ifdef DBG CFile fileRestore(_T("test.nft"), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite); fileRestore.Write(m_pTemplateInfo,m_dwTemplateInfoLen); #endif for (POSITION pos = mapNonLocalized.GetStartPosition(); pos != NULL;) { mapNonLocalized.GetNextAssoc(pos, wID, (void *&)pstrToken); if (pstrToken) delete pstrToken; } } //////////////////////////////////////////////////////////////////////////// // WriteNode - Helper function for writing an MSInfo node to the registry void WriteNode(HKEY hKey, LPCTSTR pszSubKey, int idsDefault, DWORD dwView, DWORD dwRank) { HKEY hNewKey; DWORD dwDisposition; CString strDefault; if (ERROR_SUCCESS == RegCreateKeyEx(hKey, pszSubKey, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hNewKey, &dwDisposition)) { strDefault.LoadString(idsDefault); RegSetValueEx(hNewKey, NULL, 0, REG_SZ, (const LPBYTE)(LPCTSTR)strDefault, strDefault.GetLength() + sizeof(TCHAR)); RegSetValueEx(hNewKey, REG_CLSID, 0, REG_SZ, (const LPBYTE)CLSID_MSIE, strlen(CLSID_MSIE) + 1); RegSetValueEx(hNewKey, REG_MSINFO_VIEW, 0, REG_BINARY, (const LPBYTE)&dwView, sizeof(DWORD)); RegSetValueEx(hNewKey, REG_RANK, 0, REG_BINARY, (const LPBYTE)&dwRank, sizeof(DWORD)); RegCloseKey(hNewKey); } } //////////////////////////////////////////////////////////////////////////// // RegDeleteKeyRecusive - Helper function for deleting reg keys DWORD RegDeleteKeyRecusive(HKEY hStartKey, LPCTSTR pKeyName) { DWORD dwRtn, dwSubKeyLength; LPTSTR pSubKey = NULL; TCHAR szSubKey[MAX_KEY_LENGTH]; // (256) this should be dynamic. HKEY hKey; // Do not allow NULL or empty key name if ( pKeyName && lstrlen(pKeyName)) { if( (dwRtn = RegOpenKeyEx(hStartKey, pKeyName, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hKey )) == ERROR_SUCCESS) { while (dwRtn == ERROR_SUCCESS) { dwSubKeyLength = MAX_KEY_LENGTH; dwRtn=RegEnumKeyEx( hKey, 0, // always index zero szSubKey, &dwSubKeyLength, NULL, NULL, NULL, NULL ); if(dwRtn == ERROR_NO_MORE_ITEMS) { dwRtn = RegDeleteKey(hStartKey, pKeyName); break; } else if(dwRtn == ERROR_SUCCESS) dwRtn = RegDeleteKeyRecusive(hKey, szSubKey); } RegCloseKey(hKey); // Do not save return code because error // has already occurred } } else dwRtn = ERROR_BADKEY; return dwRtn; } //////////////////////////////////////////////////////////////////////////// // GetIERepairToolCmdLine - Helper function for creating command line for // launching IE Repair Tool. CString GetIERepairToolCmdLine() { CString strRet, strIEPath, strIEPathExpanded, strWindowsPath, strRepairLog; HKEY hKey; DWORD cbData; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_IE_SETUP_KEY, 0, KEY_QUERY_VALUE, &hKey)) { cbData = MAX_PATH; RegQueryValueEx(hKey, REG_PATH, NULL, NULL, (LPBYTE)strIEPath.GetBuffer(MAX_PATH), &cbData); strIEPath.ReleaseBuffer(); ExpandEnvironmentStrings(strIEPath, strIEPathExpanded.GetBuffer(MAX_PATH), MAX_PATH); strIEPathExpanded.ReleaseBuffer(); RegCloseKey(hKey); } GetWindowsDirectory(strWindowsPath.GetBuffer(MAX_PATH), MAX_PATH); strWindowsPath.ReleaseBuffer(); strRepairLog.LoadString(IDS_REPAIR_LOG); strRet.Format((LPCTSTR) IE_REPAIR_CMD, strIEPathExpanded, strWindowsPath, strRepairLog); return strRet; } ///////////////////////////////////////////////////////////////////////////// // DllRegisterServer - Adds entries to the system registry STDAPI DllRegisterServer(void) { AFX_MANAGE_STATE(_afxModuleAddrThis); OSVERSIONINFO osver; HKEY hCatKey, hIE6Key, hCacheKey, hContentKey, hRepairKey, hMsinfoKey, hTemplatesKey, hIeinfo5Key; HKEY hMicrosoftKey, hSharedToolsKey, hCurrentVersionKey; CString strCatKey, strKey, strValue, strFullPath, strMofPathSrc, strMofPathDest; BYTE szBuffer[MAX_PATH]; DWORD dwDisposition, dwType, dwSize; int nIndex; HRESULT hr = S_OK; if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid)) return ResultFromScode(SELFREG_E_TYPELIB); if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE)) return ResultFromScode(SELFREG_E_CLASS); // check OS ver osver.dwOSVersionInfoSize = sizeof(osver); VERIFY(GetVersionEx(&osver)); if ((osver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osver.dwMajorVersion >= 5)) { //***** Windows 2000 ***** // add template reg entry if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_MICROSOFT_KEY, 0, KEY_CREATE_SUB_KEY, &hMicrosoftKey)) { if (ERROR_SUCCESS == RegCreateKeyEx(hMicrosoftKey, REG_SHARED_TOOLS, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hSharedToolsKey, &dwDisposition)) { if (ERROR_SUCCESS == RegCreateKeyEx(hSharedToolsKey, REG_MSINFO, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hMsinfoKey, &dwDisposition)) { if (ERROR_SUCCESS == RegCreateKeyEx(hMsinfoKey, REG_TEMPLATES, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, NULL, &hTemplatesKey, &dwDisposition)) { if (ERROR_SUCCESS == RegCreateKeyEx(hTemplatesKey, REG_IEINFO5, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hIeinfo5Key, &dwDisposition)) { if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CURRENT_VERSION_KEY, 0, KEY_QUERY_VALUE, &hCurrentVersionKey)) { dwType = REG_SZ; dwSize = MAX_PATH; if (ERROR_SUCCESS == RegQueryValueEx(hCurrentVersionKey, REG_COMMON_FILES_DIR, NULL, &dwType, (LPBYTE)strFullPath.GetBuffer(MAX_PATH), &dwSize)) { strFullPath.ReleaseBuffer(); strFullPath += _T('\\'); strFullPath += OCX_FILE_IN_COMMON; if (strFullPath[0] == _T('"')) strFullPath = strFullPath.Right(strFullPath.GetLength() - 1); RegSetValueEx(hIeinfo5Key, NULL, 0, REG_SZ, (const LPBYTE)(LPCTSTR)strFullPath, strFullPath.GetLength() * sizeof(TCHAR)); } RegCloseKey(hCurrentVersionKey); } RegCloseKey(hIeinfo5Key); } RegCloseKey(hTemplatesKey); } RegCloseKey(hMsinfoKey); } RegCloseKey(hSharedToolsKey); } RegCloseKey(hMicrosoftKey); } // copy ieinfo5.mof to mof dir if (!strFullPath.IsEmpty() && false) //12/13/2000. a-sanka. do not compile mof. { WCHAR strPathMof[MAX_PATH]; strMofPathSrc = strFullPath; nIndex = strMofPathSrc.ReverseFind(_T('\\')); strMofPathSrc = strMofPathSrc.Left(nIndex + 1); strMofPathSrc += MOF_FILE; if (strMofPathSrc[0] == _T('"')) strMofPathSrc = strMofPathSrc.Right(strMofPathSrc.GetLength() - 1); #ifdef UNICODE wsprintfW(strPathMof, L"%ls", strMofPathSrc); #else wsprintfW(strPathMof, L"%hs", strMofPathSrc); #endif HRESULT hrInit = CoInitialize(NULL); IMofCompiler * pMofComp; hr = CoCreateInstance(CLSID_MofCompiler, NULL, CLSCTX_INPROC_SERVER, IID_IMofCompiler, (void**)&pMofComp); if (SUCCEEDED(hr)) { WBEM_COMPILE_STATUS_INFO Info; hr = pMofComp->CompileFile(strPathMof,NULL,NULL,NULL,NULL,WBEM_FLAG_AUTORECOVER,0,0,&Info); pMofComp->Release(); } if (SUCCEEDED(hrInit)) CoUninitialize(); } } else { //***** NT4, Win 9x ***** // Set all MSInfo category reg values for this extension strCatKey = REG_MSINFO_KEY; strCatKey += '\\'; strCatKey += REG_CATEGORIES; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, strCatKey, 0, KEY_WRITE, &hCatKey)) { WriteNode(hCatKey, REG_INTERNET_EXPLORER_6, IDS_INTERNET_EXPLORER_6, 1, 0x35); if (ERROR_SUCCESS == RegOpenKeyEx(hCatKey, REG_INTERNET_EXPLORER_6, 0, KEY_WRITE, &hIE6Key)) { WriteNode(hIE6Key, REG_FILE_VERSIONS, IDS_FILE_VERSIONS, 2, 0x10); WriteNode(hIE6Key, REG_CONNECTIVITY, IDS_CONNECTIVITY, 3, 0x20); WriteNode(hIE6Key, REG_CACHE, IDS_CACHE, 4, 0x30); if (ERROR_SUCCESS == RegOpenKeyEx(hIE6Key, REG_CACHE, 0, KEY_WRITE, &hCacheKey)) { WriteNode(hCacheKey, REG_OBJECT_LIST, IDS_OBJECT_LIST, 5, 0x10); RegCloseKey(hCacheKey); } WriteNode(hIE6Key, REG_CONTENT, IDS_CONTENT, 6, 0x40); if (ERROR_SUCCESS == RegOpenKeyEx(hIE6Key, REG_CONTENT, 0, KEY_WRITE, &hContentKey)) { WriteNode(hContentKey, REG_PERSONAL_CERTIFICATES, IDS_PERSONAL_CERTIFICATES, 7, 0x10); WriteNode(hContentKey, REG_OTHER_PEOPLE_CERTIFICATES, IDS_OTHER_PEOPLE_CERTIFICATES, 8, 0x20); WriteNode(hContentKey, REG_PUBLISHERS, IDS_PUBLISHERS, 9, 0x30); RegCloseKey(hContentKey); } WriteNode(hIE6Key, REG_SECURITY, IDS_SECURITY, 10, 0x50); RegCloseKey(hIE6Key); } RegCloseKey(hCatKey); } // Add MSInfo tool reg values for IE Repair Tool strKey = REG_MSINFO_KEY; strKey += '\\'; strKey += REG_TOOLS; strKey += '\\'; strKey += REG_IE_REPAIR; if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, strKey, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hRepairKey, &dwDisposition)) { strValue.LoadString(IDS_IE_REPAIR_TOOL); RegSetValueEx(hRepairKey, NULL, 0, REG_SZ, (const LPBYTE)(LPCTSTR)strValue, strValue.GetLength() + sizeof(TCHAR)); strValue = GetIERepairToolCmdLine(); RegSetValueEx(hRepairKey, REG_COMMAND, 0, REG_SZ, (const LPBYTE)(LPCTSTR)strValue, strValue.GetLength() + sizeof(TCHAR)); strValue.LoadString(IDS_RUNS_IE_REPAIR_TOOL); RegSetValueEx(hRepairKey, REG_DESCRIPTION, 0, REG_SZ, (const LPBYTE)(LPCTSTR)strValue, strValue.GetLength() + sizeof(TCHAR)); RegCloseKey(hRepairKey); } } return hr; } ///////////////////////////////////////////////////////////////////////////// // DllUnregisterServer - Removes entries from the system registry STDAPI DllUnregisterServer(void) { AFX_MANAGE_STATE(_afxModuleAddrThis); OSVERSIONINFO osver; CString strKey; if (!AfxOleUnregisterTypeLib(_tlid /*, _wVerMajor, _wVerMinor*/)) return ResultFromScode(SELFREG_E_TYPELIB); if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE)) return ResultFromScode(SELFREG_E_CLASS); osver.dwOSVersionInfoSize = sizeof(osver); VERIFY(GetVersionEx(&osver)); if ((osver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osver.dwMajorVersion >= 5)) { // Windows 2000 } else { // NT4, Win 9x // Remove all MSInfo category reg values for this extension strKey = REG_MSINFO_KEY; strKey += '\\'; strKey += REG_CATEGORIES; strKey += '\\'; strKey += REG_INTERNET_EXPLORER_6; RegDeleteKeyRecusive(HKEY_LOCAL_MACHINE, strKey); // Remove MSInfo tool reg values for IE Repair Tool strKey = REG_MSINFO_KEY; strKey += '\\'; strKey += REG_TOOLS; strKey += '\\'; strKey += REG_IE_REPAIR; RegDeleteKey(HKEY_LOCAL_MACHINE, strKey); } return NOERROR; } ///////////////////////////////////////////////////////////////////////////// // GetTemplate - exported function for NT5 template dll DWORD __cdecl GetTemplate(void ** ppBuffer) { DWORD dwReturn = 0; TRY { dwReturn = theApp.AppGetTemplate(ppBuffer); } CATCH_ALL(e) { #ifdef DBG e->ReportError(); #endif dwReturn = 0; } END_CATCH_ALL return dwReturn; }