//+---------------------------------------------------------------------------- // // File: cmfdi.cpp // // Module: CMDL32.EXE // // Synopsis: CFdi class implementations // // Copyright (c) 1996-1999 Microsoft Corporation // // Author: nickball Created 04/08/98 // //+---------------------------------------------------------------------------- #include "cmmaster.h" #include #include const TCHAR* const c_pszExeFile = TEXT("PBUPDATE.EXE"); // for detecting itExeInCab const TCHAR* const c_pszInfFile = TEXT("PBUPDATE.INF"); // for detecting itInfInCab const TCHAR* const c_pszVerFile = TEXT("PBUPDATE.VER"); // version string in .CAB const TCHAR* const c_pszPbr = TEXT("PBR"); // regions file extension // // CFDIFile Implementation // CFDIFile::~CFDIFile() { // nothing } DWORD CFDIFile::Read(LPVOID pv, DWORD cb) { return 0; } DWORD CFDIFile::Write(LPVOID pv, DWORD cb) { return 0; } long CFDIFile::Seek(long dist, int seektype) { return 0; } int CFDIFile::Close() { return 0; } HANDLE CFDIFile::GetHandle() { return (INVALID_HANDLE_VALUE); } // // CFDIFileFile Implementation // CFDIFileFile::CFDIFileFile() { m_hFile = INVALID_HANDLE_VALUE; } CFDIFileFile::~CFDIFileFile() { if (m_hFile != INVALID_HANDLE_VALUE) { MYDBG(("CFDIFileFile::~CFDIFileFile() destructor called while file still open.")); Close(); } } BOOL CFDIFileFile::CreateFile(LPCTSTR pszFile, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDistribution, DWORD dwFlagsAndAttributes, DWORD dwFileSize) { // Make sure the files isn't in use if (m_hFile != INVALID_HANDLE_VALUE) { MYDBG(("CFDIFileFile::CreateFile() file is already open.")); SetLastError(ERROR_OUT_OF_STRUCTURES); return (FALSE); } // Open Create/Open the file m_hFile = ::CreateFile(pszFile,dwDesiredAccess,dwShareMode,NULL,dwCreationDistribution,dwFlagsAndAttributes,NULL); if (m_hFile == INVALID_HANDLE_VALUE) { MYDBG(("CFDIFileFile::CreateFile() CreateFile(pszFile=%s,dwDesiredAccess=%u,dwShareMode=%u,dwCreationDistribution=%u,dwFlagsAndAttributes=%u) failed, GLE=%u.", pszFile,dwDesiredAccess,dwShareMode,dwCreationDistribution,dwFlagsAndAttributes,GetLastError())); return (FALSE); } // If dwFileSize is specified, move the pointer by dwFileSize bytes if (dwFileSize) { BOOL bRes; DWORD dwRes; dwRes = SetFilePointer(m_hFile,dwFileSize,NULL,FILE_BEGIN); MYDBGTST(dwRes==INVALID_SET_FILE_POINTER ,("CFDIFileFile::CreateFile() SetFilePointer() failed, GLE=%u.",GetLastError())); // If that worked, set the end of file at the file pointer position if (dwRes != INVALID_SET_FILE_POINTER) { bRes = SetEndOfFile(m_hFile); MYDBGTST(!bRes,("CFDIFileFile::CreateFile() SetEndOfFile() failed, GLE=%u.",GetLastError())); } // Reset the file pointer to the beginning if ((dwRes != INVALID_SET_FILE_POINTER ) && bRes) { dwRes = SetFilePointer(m_hFile,0,NULL,FILE_BEGIN); MYDBGTST(dwRes==INVALID_SET_FILE_POINTER ,("CFDIFileFile::CreateFile() SetFilePointer() failed, GLE=%u.",GetLastError())); } // Close the file and bail if we failed the above if ((dwRes == INVALID_SET_FILE_POINTER ) || !bRes) { bRes = CloseHandle(m_hFile); MYDBGTST(!bRes,("CFDIFileFile::CreateFile() CloseHandle() failed, GLE=%u.",GetLastError())); m_hFile = INVALID_HANDLE_VALUE; return (-1); } } return (TRUE); } BOOL CFDIFileFile::CreateUniqueFile(LPTSTR pszFile, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwFlagsAndAttributes) { DWORD dwIdx; TCHAR szFile[MAX_PATH+1]; if (m_hFile != INVALID_HANDLE_VALUE) { MYDBG(("CFDIFileFile::CreateUniqueFile() file is already open.")); SetLastError(ERROR_OUT_OF_STRUCTURES); return (FALSE); } dwIdx = 0; while (1) { wsprintf(szFile,"%08u.tmp",dwIdx); m_hFile = ::CreateFile(szFile,dwDesiredAccess,dwShareMode,NULL,CREATE_NEW,dwFlagsAndAttributes,NULL); if (m_hFile != INVALID_HANDLE_VALUE) { break; } if (IsErrorForUnique(GetLastError(), szFile)) { MYDBG(("CFDIFileFile::CreateUniqueFile() CreateFile() failed, GLE=%u.",GetLastError())); return (FALSE); } dwIdx++; } lstrcpy(pszFile,szFile); return (TRUE); } DWORD CFDIFileFile::Read(LPVOID pv, DWORD cb) { BOOL bRes; DWORD dwRes; bRes = ReadFile(m_hFile,pv,cb,&dwRes,NULL); if (!bRes) { MYDBG(("CFDIFileFile::Read() ReadFile() failed, GLE=%u.",GetLastError())); return ((UINT) -1); } return (dwRes); } DWORD CFDIFileFile::Write(LPVOID pv, DWORD cb) { BOOL bRes; DWORD dwRes; bRes = WriteFile(m_hFile,pv,cb,&dwRes,NULL); if (!bRes) { MYDBG(("CFDIFileFile::Write() WriteFile() failed, GLE=%u.",GetLastError())); return ((UINT) -1); } return (dwRes); } long CFDIFileFile::Seek(long dist, int seektype) { DWORD dwRes; dwRes = SetFilePointer(m_hFile,dist,NULL,seektype); if (dwRes == INVALID_SET_FILE_POINTER) { MYDBG(("CFDIFileFile::Seek() SetFilePointer() failed, GLE=%u.",GetLastError())); return (-1); } return ((long) dwRes); } int CFDIFileFile::Close() { BOOL bRes; bRes = CloseHandle(m_hFile); if (!bRes) { MYDBG(("CFDIFileFile::Close() CloseHandle() failed, GLE=%u.",GetLastError())); return (-1); } m_hFile = INVALID_HANDLE_VALUE; return (0); } HANDLE CFDIFileFile::GetHandle() { return (m_hFile); } // // FDI wrapper routines // void HUGE * FAR DIAMONDAPI fdi_alloc(ULONG cb) { return (CmMalloc(cb)); } void FAR DIAMONDAPI fdi_free(void HUGE *pv) { CmFree(pv); } INT_PTR FAR DIAMONDAPI fdi_open(char FAR *pszFile, int oflag, int pmode) { TCHAR szTempFileName[MAX_PATH+1]; DWORD dwDesiredAccess; DWORD dwShareMode = FILE_SHARE_READ; DWORD dwCreationDistribution; DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; DWORD dwFileSize = 0; DWORD dwRes; BOOL bRes; CFDIFileFile *pfff = NULL; pfff = new CFDIFileFile; if (!pfff) { MYDBG(("fdi_open() new CFDIFileFile failed.")); return (-1); } switch (oflag & (_O_RDONLY|_O_WRONLY|_O_RDWR)) { case _O_RDONLY: dwDesiredAccess = GENERIC_READ; break; case _O_WRONLY: dwDesiredAccess = GENERIC_WRITE; break; case _O_RDWR: dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; break; default: MYDBG(("fdi_open() invalid read/write flags, oflag=%u.",oflag)); delete pfff; return (-1); } if (oflag & _O_CREAT) { if (!(pmode & _S_IWRITE)) { dwFlagsAndAttributes |= FILE_ATTRIBUTE_READONLY; } } if (oflag & (_O_CREAT | _O_EXCL)) { dwCreationDistribution = CREATE_NEW; } else if (oflag & (_O_CREAT | _O_TRUNC)) { dwCreationDistribution = CREATE_ALWAYS; } else if (oflag & _O_CREAT) { dwCreationDistribution = OPEN_ALWAYS; } else if (oflag & _O_TRUNC) { dwCreationDistribution = TRUNCATE_EXISTING; } else { dwCreationDistribution = OPEN_EXISTING; } if (*pszFile == '*') { PFDISPILLFILE pfsf = (PFDISPILLFILE) pszFile; TCHAR szTempPath[MAX_PATH+1]; ZeroMemory(szTempPath,sizeof(szTempPath)); ZeroMemory(szTempFileName,sizeof(szTempFileName)); dwRes = GetTempPath(sizeof(szTempPath)/sizeof(TCHAR)-1,szTempPath); MYDBGTST(!dwRes,("fdi_open() GetTempPath() failed, GLE=%u.",GetLastError())); dwRes = GetTempFileName(szTempPath,TEXT("ctf"),0,szTempFileName); MYDBGTST(!dwRes,("fdi_open() GetTempFileName() failed, GLE=%u.",GetLastError())); MYDBGTST(!dwRes,("fdi_open() GetTempFileName() failed, GLE=%u.",GetLastError())); pszFile = szTempFileName; dwFileSize = pfsf->cbFile; dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE; } bRes = pfff->CreateFile(pszFile,dwDesiredAccess,dwShareMode,dwCreationDistribution,dwFlagsAndAttributes,dwFileSize); if (!bRes) { delete pfff; return (-1); } return ((INT_PTR)pfff); } UINT FAR DIAMONDAPI fdi_read(INT_PTR hf, void FAR *pv, UINT cb) { return (((CFDIFile *) hf)->Read(pv,cb)); } UINT FAR DIAMONDAPI fdi_write(INT_PTR hf, void FAR *pv, UINT cb) { return (((CFDIFile *) hf)->Write(pv,cb)); } long FAR DIAMONDAPI fdi_seek(INT_PTR hf, long dist, int seektype) { return (((CFDIFile *) hf)->Seek(dist,seektype)); } int FAR DIAMONDAPI fdi_close(INT_PTR hf) { int nRes; CFDIFile *pff = (CFDIFile *) hf; nRes = pff->Close(); delete pff; return (nRes); } INT_PTR FAR DIAMONDAPI fdi_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) { NotifyArgs *pnaArgs = (NotifyArgs *) pfdin->pv; BOOL bRes; switch (fdint) { case fdintCOPY_FILE: { InstallType itType; TCHAR szTmp[MAX_PATH+1]; LPTSTR pszExt; // file extension PFILEPROCESSINFO pFPI; MYDBG(("fdi_notify() fdint=fdintCOPY_FILE, psz1=%s, cb=%u.",pfdin->psz1,pfdin->cb)); if (lstrlen(pnaArgs->pdaArgs->szCabDir)+lstrlen(pfdin->psz1)+1>sizeof(szTmp)/sizeof(TCHAR)-1) { MYDBG(("fdi_notify() szCabDir=%s+pszFile=%s exceeds MAX_PATH.",pnaArgs->pdaArgs->szCabDir,pfdin->psz1)); return (-1); } lstrcpy(szTmp,pnaArgs->pdaArgs->szCabDir); if (szTmp[0] && (GetLastChar(szTmp) != '\\')) { lstrcat(szTmp,TEXT("\\")); } lstrcat(szTmp,pfdin->psz1); if (!(pnaArgs->dwAppFlags & AF_NO_EXEINCAB) && (lstrcmpi(pfdin->psz1,c_pszExeFile) == 0)) { // // Its a .EXE, note the fact for later processing // itType = itInvalid; // currently an invalid type pnaArgs->pdaArgs->fContainsExeOrInf = TRUE; } else if (!(pnaArgs->dwAppFlags & AF_NO_INFINCAB) && (lstrcmpi(pfdin->psz1,c_pszInfFile) == 0)) { // // Its a .INF, note the fact for later processing // itType = itInvalid; // currently an invalid type pnaArgs->pdaArgs->fContainsExeOrInf = TRUE; } else if (!(pnaArgs->dwAppFlags & AF_NO_PBDINCAB) && (lstrcmpi(pfdin->psz1,c_pszPbdFile) == 0)) { // // Its a .PBD, note the fact for later processing // itType = itPbdInCab; } else if ((pszExt = CmStrchr(pfdin->psz1, TEXT('.'))) && (lstrcmpi(pszExt+1, c_pszPbk) == 0)) { *pszExt = TEXT('\0'); // if the PBK is not for this service, we don't use it. if (lstrcmpi(pfdin->psz1, pnaArgs->pdaArgs->pszPhoneBookName) != 0) { itType = itInvalid; } else { itType = itPbkInCab; } // restore the filename *pszExt = TEXT('.'); } else if ((pszExt = CmStrchr(pfdin->psz1, TEXT('.'))) && (lstrcmpi(pszExt+1, c_pszPbr) == 0)) { *pszExt = TEXT('\0'); // if the PBR is not for this service, we don't use it. if (lstrcmpi(pfdin->psz1, pnaArgs->pdaArgs->pszPhoneBookName) != 0) { itType = itInvalid; } else { itType = itPbrInCab; } // restore the filename *pszExt = TEXT('.'); // save the name in pdaArgs // if (!(pnaArgs->pdaArgs->pszNewPbrFile = CmStrCpyAlloc(pfdin->psz1))) // { // MYDBG((TEXT("fdi_notify(): CmStrCpyAlloc for pszNewPbrFile failed."))); // return -1; // } } else if (lstrcmpi(pfdin->psz1, c_pszVerFile) == 0) { // a version file - we don't process it. We'll read the version in fdintCLOSE_FILE_INFO itType = itInvalid; } else { itType = itInvalid; } // create a file process info. add one to the existing list. if (itType != itInvalid) { if (!pnaArgs->pdaArgs->rgfpiFileProcessInfo) pFPI = (PFILEPROCESSINFO)CmMalloc(sizeof(FILEPROCESSINFO)); else pFPI = (PFILEPROCESSINFO)CmRealloc(pnaArgs->pdaArgs->rgfpiFileProcessInfo, (pnaArgs->pdaArgs->dwNumFilesToProcess+1)*sizeof(FILEPROCESSINFO)); if (!pFPI) { MYDBG((TEXT("fdi_notify(): Malloc(FILEPROCESSINFO) failed."))); return -1; } pnaArgs->pdaArgs->rgfpiFileProcessInfo = pFPI; pnaArgs->pdaArgs->dwNumFilesToProcess++; pFPI[pnaArgs->pdaArgs->dwNumFilesToProcess-1].itType = itType; pFPI[pnaArgs->pdaArgs->dwNumFilesToProcess-1].pszFile = CmStrCpyAlloc(pfdin->psz1); } // Do standard fdintCOPY_FILE processing, create the file and return the handle CFDIFileFile *pfff; pfff = new CFDIFileFile; if (!pfff) { MYDBG(("fdi_notify() new CFDIFileFile failed.")); return (-1); } bRes = pfff->CreateFile(szTmp,GENERIC_WRITE,FILE_SHARE_READ,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,0); if (!bRes) { delete pfff; return (-1); } return ((INT_PTR)pfff); } case fdintCLOSE_FILE_INFO: { int iRes; TCHAR szTmp[MAX_PATH+1]; // Append file name to cab dir lstrcpy(szTmp,pnaArgs->pdaArgs->szCabDir); if (szTmp[0] && (GetLastChar(szTmp) != '\\')) { lstrcat(szTmp,TEXT("\\")); } lstrcat(szTmp,pfdin->psz1); // Set the date and time to the original file time not the current time FILETIME ftTmp; FILETIME ftTime; bRes = DosDateTimeToFileTime(pfdin->date,pfdin->time,&ftTmp); MYDBGTST(!bRes,("fdi_notify() DosDateTimeToFileTime(%u,%u) failed, GLE=%u.",pfdin->date,pfdin->time,GetLastError())); bRes = LocalFileTimeToFileTime(&ftTmp,&ftTime); MYDBGTST(!bRes,("fdi_notify() LocalFileTimeToFileTime() failed, GLE=%u.",GetLastError())); bRes = SetFileTime(((CFDIFile *) (pfdin->hf))->GetHandle(),&ftTime,&ftTime,&ftTime); MYDBGTST(!bRes,("fdi_notify() SetFileTime() failed, GLE=%u.",GetLastError())); iRes = fdi_close(pfdin->hf); // If this is the version file, get the version number if (lstrcmpi(pfdin->psz1,c_pszVerFile) == 0) { pnaArgs->pdaArgs->pszVerNew = GetVersionFromFile(szTmp); } // Set file attributes according to original file attribs bRes = SetFileAttributes(szTmp,pfdin->attribs); MYDBGTST(!bRes,("fdi_notify() SetFileAttributes(%s,%u) failed, GLE=%u.",szTmp,pfdin->attribs,GetLastError())); return ((iRes==0)?TRUE:FALSE); } case fdintNEXT_CABINET: MYDBG(("fdi_notify_scan() spanning cabinets is not supported.")); return (-1); default: MYDBG(("fdi_notify_scan() fdint=%u.",fdint)); break; } return (0); }