// File: NmMigrat.c // // 16-bit Windows 98 Migration DLL for NetMeeting 3.0 #include "NmMigrat.h" #include "stdio.h" // Win98 ships with NM 2.1 build 2203 and will force it to be installed static const char * g_pcszInfNm = "msnetmtg.inf"; static const char * g_pcszVersion = "; Version 4,3,0,2203"; static const char * g_pcszHeader = ";msnetmtg.inf (removed by NmMigrat.dll)\r\n[Version]\r\nsignature=\"$CHICAGO$\"\r\nSetupClass=Base\r\nLayoutFile=layout.inf, layout1.inf, layout2.inf\r\n"; // In Win98's subase.inf, under [winother.oldlinks] there is a bogus line static const char * g_pcszInfSubase = "subase.inf"; static const char * g_pcszWinOther = "[winother.oldlinks]"; static const char * g_pcszNukeLink = "setup.ini, groupPrograms,, \"\"\"%Old_NetMeeting_DESC%\"\"\""; /////////////////////////////////////////////////////////////////////// typedef struct { HFILE hf; // File Handle LONG lPos; // current position in the file int ichCurr; // current character position in rgch int cchRemain; // number of remaining chars in rgch char rgch[8*1024]; // a really large buffer! } FD; // File Data /////////////////////////////////////////////////////////////////////// // Debug Utilities #ifdef DEBUG VOID ErrMsg2(LPCSTR pszFormat, LPVOID p1, LPVOID p2) { char szMsg[1024]; OutputDebugString("NmMigration: "); wsprintf(szMsg, pszFormat, p1, p2); OutputDebugString(szMsg); OutputDebugString("\r\n"); } VOID ErrMsg1(LPCSTR pszFormat, LPVOID p1) { ErrMsg2(pszFormat, p1, NULL); } #else #define ErrMsg1(psz, p1) #define ErrMsg2(psz, p1, p2) #endif /* DEBUG */ /////////////////////////////////////////////////////////////////////// /* L I B M A I N */ /*------------------------------------------------------------------------- %%Function: LibMain -------------------------------------------------------------------------*/ int FAR PASCAL LibMain(HANDLE hInst, WORD wDataseg, WORD wHeapsize, LPSTR lpszcmdl) { Reference(hInst); Reference(wDataseg); Reference(wHeapsize); Reference(lpszcmdl); return 1; } /* F O P E N F I L E */ /*------------------------------------------------------------------------- %%Function: FOpenFile Open the file from the temporary Win98 INF directory. -------------------------------------------------------------------------*/ BOOL FOpenFile(LPCSTR pszFile, FD * pFd, BOOL fCreate) { char szPath[MAX_PATH]; // LDID_SETUPTEMP = temp INF directory "C:\WININST0.400" UINT retVal = CtlGetLddPath(LDID_SETUPTEMP, szPath); if (0 != retVal) { ErrMsg1("CtlGetLddPath(TEMP) failed. Err=%d", (LPVOID) retVal); return FALSE; } // Nuke the temporary 2.1 inf so it doesn't get installed lstrcat(szPath, "\\"); lstrcat(szPath, pszFile); if (fCreate) { pFd->hf = _lcreat(szPath, 0); // read/write } else { pFd->hf = _lopen(szPath, OF_READWRITE); } if (HFILE_ERROR == pFd->hf) { ErrMsg2("Unable to open [%s] Error=%d", szPath, (LPVOID) GetLastError()); return FALSE; } pFd->lPos = 0; pFd->ichCurr = 0; pFd->cchRemain = 0; ErrMsg1("Opened [%s]", szPath); return TRUE; } /* R E A D L I N E */ /*------------------------------------------------------------------------- %%Function: ReadLine Read a line (up to MAX_PATH chars) from the buffered file. Returns the number of characters read. -------------------------------------------------------------------------*/ int ReadLine(char * pchDest, FD * pFd) { int cch; for (cch = 0; cch < MAX_PATH; cch++) { if (0 == pFd->cchRemain) { pFd->cchRemain = _lread(pFd->hf, pFd->rgch, sizeof(pFd->rgch)); if (HFILE_ERROR == pFd->cchRemain) { ErrMsg1("End of file reached at pos=%d", (LPVOID) pFd->lPos); break; } pFd->ichCurr = 0; } pFd->lPos++; pFd->cchRemain--; *pchDest = pFd->rgch[pFd->ichCurr++]; if ('\n' == *pchDest) { break; } if ('\r' != *pchDest) { pchDest++; } } *pchDest = '\0'; // Always null terminate the string return cch; } /* R E M O V E I N F */ /*------------------------------------------------------------------------- %%Function: RemoveInf Remove the NM2.1 inf from Win98's list of inf's -------------------------------------------------------------------------*/ void RemoveInf(void) { FD fd; if (!FOpenFile(g_pcszInfNm, &fd, FALSE)) { return; } for ( ; ; ) // Find the version comment before the first section { char szLine[MAX_PATH]; if (0 == ReadLine(szLine, &fd)) { break; } if ('[' == szLine[0]) { ErrMsg1("No version number found?", 0); break; } // Must match build 2203 since a Win98 update or an OEM // could ship a newer version than NM 2.11, which we would // want to upgrade us. if (0 == lstrcmp(szLine, g_pcszVersion)) { // Re-write the older MSNETMTG.INF with a empty header _lclose(fd.hf); if (FOpenFile(g_pcszInfNm, &fd, TRUE)) { _llseek(fd.hf, 0, 0); _lwrite(fd.hf, (LPCSTR) g_pcszHeader, lstrlen(g_pcszHeader)+1); ErrMsg1("Removed older NetMeeting INF", 0); } break; } } _lclose(fd.hf); } /* F I X S U B A S E */ /*------------------------------------------------------------------------- %%Function: FixSubase Delete the line from subase.inf that deletes the NetMeeting link. See NM4DB bug 5937, Win98 bug 65154. This code shouldn't be necessary with Win98 SP1 and later. -------------------------------------------------------------------------*/ void FixSubase(void) { FD fd; char szLine[MAX_PATH]; if (!FOpenFile(g_pcszInfSubase, &fd, FALSE)) return; for ( ; ; ) // Find the section { if (0 == ReadLine(szLine, &fd)) { break; } if (('[' == szLine[0]) && (0 == lstrcmp(szLine, g_pcszWinOther))) { ErrMsg1("Found the section at pos=%d", (LPVOID) fd.lPos); break; } } for ( ; ; ) // Find the line { LONG lPosPrev = fd.lPos; // Remember the start of the line if (0 == ReadLine(szLine, &fd)) { break; } if (0 == lstrcmp(szLine, g_pcszNukeLink)) { // comment out the line _llseek(fd.hf, lPosPrev, 0 /* FILE_BEGIN */); _lwrite(fd.hf, (LPCSTR) ";", 1); ErrMsg1("Commented out line at pos=%d", (LPVOID) lPosPrev); break; } if ('[' == szLine[0]) { ErrMsg1("End of section? at pos=%d", (LPVOID) lPosPrev); break; } } _lclose(fd.hf); } /* N M M I G R A T I O N */ /*------------------------------------------------------------------------- %%Function: NmMigration This is called by the Windows 98 setup system. -------------------------------------------------------------------------*/ DWORD FAR PASCAL NmMigration(DWORD dwStage, LPSTR lpszParams, LPARAM lParam) { Reference(lpszParams); Reference(lParam); ErrMsg2("NM Build=[%s] stage=%08X", lpszParams, (LPVOID) dwStage); switch (dwStage) { case SU_MIGRATE_PREINFLOAD: { RemoveInf(); FixSubase(); break; } default: break; } return 0; }