#include "stdafx.h" #include #include #include #include #include #include #include "cabfunc.h" #include "resource.h" #include "filestuff.h" #include "fdi.h" #include "setupapi.h" CString g_strExpandToDirectory; LRESULT WINAPI CabinetCallbackToExpand ( IN PVOID pMyInstallData, IN UINT Notification, IN UINT_PTR Param1, IN UINT_PTR Param2 ) { LRESULT lRetVal = NO_ERROR; FILE_IN_CABINET_INFO *pInfo = NULL; CString strTargetName = g_strExpandToDirectory; strTargetName += '\\'; switch(Notification) { case SPFILENOTIFY_FILEINCABINET: pInfo = (FILE_IN_CABINET_INFO *) Param1; lRetVal = FILEOP_DOIT; // Extract the file. strTargetName += pInfo->NameInCabinet; //pInfo->FullTargetName is define as TCHAR FullTargetName[MAX_PATH]; _tcsncpy(pInfo->FullTargetName,strTargetName.GetBuffer(strTargetName.GetLength()),MAX_PATH); break; case SPFILENOTIFY_FILEEXTRACTED: lRetVal = NO_ERROR; break; case SPFILENOTIFY_NEEDNEWCABINET: // Cab file in the cab file we're looking at. Ignore it. lRetVal = NO_ERROR; break; } return lRetVal; } BOOL OpenCABFile(const CString& strCabPath,const CString& strExpandToDirectory) { g_strExpandToDirectory = strExpandToDirectory; if (!SetupIterateCabinet(strCabPath,0,(PSP_FILE_CALLBACK)CabinetCallbackToExpand,0)) { return FALSE; } else { return TRUE; } } //--------------------------------------------------------------------------- // This function looks in the specified directory for an NFO file. If it // finds one, it assigns it to filename and returns TRUE. This function // will only find the first NFO file in a directory. // // If an NFO file cannot be found, then we'll look for another file type // to open. Grab the string entry in the registry = "cabdefaultopen". An // example value would be "*.nfo|hwinfo.dat|*.dat|*.txt" which would be // interpreted as follows: // // 1. First look for any NFO file to open. // 2. Then try to open a file called "hwinfo.dat". // 3. Then try to open any file with a DAT extension. // 4. Then try for any TXT file. // 5. Finally, if none of these can be found, present an open dialog // to the user. //--------------------------------------------------------------------------- LPCTSTR VAL_CABDEFAULTOPEN = _T("cabdefaultopen"); LPCTSTR cszDirSeparator = _T("\\"); BOOL IsDataspecFilePresent(CString strCabExplodedDir) { CStringList filesfound; DirectorySearch(_T("dataspec.xml"), strCabExplodedDir, filesfound); if (filesfound.GetHeadPosition() != NULL) { return TRUE; } return FALSE; } BOOL IsIncidentXMLFilePresent(CString strCabExplodedDir, CString strIncidentFileName) { CStringList filesfound; DirectorySearch(strIncidentFileName, strCabExplodedDir, filesfound); if (filesfound.GetHeadPosition() != NULL) { return TRUE; } return FALSE; } BOOL FindFileToOpen(const CString & destination, CString & filename) { CString strCABDefaultOpen, strRegBase, strDirectory; HKEY hkey; filename.Empty(); strDirectory = destination; if (strDirectory.Right(1) != CString(cszDirSeparator)) strDirectory += CString(cszDirSeparator); // Set up a fallback string of the NFO file type, in case we can't // find the registry entry. strCABDefaultOpen.LoadString(IDS_DEFAULTEXTENSION); strCABDefaultOpen = CString("*.") + strCABDefaultOpen; // Load the string of files and file types to open from the registry. strRegBase.LoadString(IDS_MSI_REG_BASE); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strRegBase, 0, KEY_READ, &hkey) == ERROR_SUCCESS) { char szData[MAX_PATH]; DWORD dwType, dwSize = MAX_PATH; if (RegQueryValueEx(hkey, VAL_CABDEFAULTOPEN, NULL, &dwType, (LPBYTE) szData, &dwSize) == ERROR_SUCCESS) if (dwType == REG_SZ) strCABDefaultOpen = szData; RegCloseKey(hkey); } // Look through each of the potential files and file types. If we find // a match, return TRUE after setting filename appropriately. Note that // we need to recurse down through directories. CString strFileSpec; CStringList filesfound; POSITION pos; while (!strCABDefaultOpen.IsEmpty()) { if (strCABDefaultOpen.Find('|') == -1) strFileSpec = strCABDefaultOpen; else strFileSpec = strCABDefaultOpen.Left(strCABDefaultOpen.Find('|')); filesfound.RemoveAll(); DirectorySearch(strFileSpec, strDirectory, filesfound); pos = filesfound.GetHeadPosition(); if (pos != NULL) { filename = filesfound.GetNext(pos); return TRUE; } strCABDefaultOpen = strCABDefaultOpen.Right(strCABDefaultOpen.GetLength() - strFileSpec.GetLength()); if (strCABDefaultOpen.Find('|') == 0) strCABDefaultOpen = strCABDefaultOpen.Right(strCABDefaultOpen.GetLength() - 1); } //a-kjaw ////Look for incident.xml file. It has to be an unicode file. strCABDefaultOpen = _T("*.XML"); TCHAR pBuf[MAX_PATH]; WCHAR pwBuf[MAX_PATH]; HANDLE handle; DWORD dw; while (!strCABDefaultOpen.IsEmpty()) { if (strCABDefaultOpen.Find('|') == -1) strFileSpec = strCABDefaultOpen; else strFileSpec = strCABDefaultOpen.Left(strCABDefaultOpen.Find('|')); filesfound.RemoveAll(); DirectorySearch(strFileSpec, strDirectory, filesfound); pos = filesfound.GetHeadPosition(); while (pos != NULL) { filename = filesfound.GetNext(pos); handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == handle) continue; ReadFile(handle , pBuf , 1 , &dw , NULL); if( pBuf[0] == _T('<')) { do { ReadFile(handle , pBuf , _tcslen(_T("MachineID")) * sizeof(TCHAR) , &dw , NULL); if(_tcsicmp(pBuf , _T("MachineID")) == 0) { CloseHandle( handle ); return TRUE; } else { SetFilePointer(handle , (1 - _tcslen(_T("MachineID")) )* sizeof(TCHAR) , 0 , FILE_CURRENT ); } }while( dw == _tcslen(_T("MachineID")) ); } else //Unicode? { ReadFile(handle , pwBuf , 1 , &dw , NULL); do { ReadFile(handle , pwBuf , lstrlenW(L"MachineID") * sizeof(WCHAR) , &dw , NULL); pwBuf[ lstrlenW(L"MachineID") ] = L'\0'; if(lstrcmpiW(pwBuf , L"MachineID") == 0) { CloseHandle( handle ); return TRUE; } else { SetFilePointer(handle , (1 - lstrlenW(L"MachineID"))* sizeof(WCHAR) , 0 , FILE_CURRENT ); } }while( dw == _tcslen(_T("MachineID")) * sizeof(WCHAR) ); } CloseHandle( handle ); } strCABDefaultOpen = strCABDefaultOpen.Right(strCABDefaultOpen.GetLength() - strFileSpec.GetLength()); if (strCABDefaultOpen.Find('|') == 0) strCABDefaultOpen = strCABDefaultOpen.Right(strCABDefaultOpen.GetLength() - 1); } return FALSE; } //--------------------------------------------------------------------------- // DirectorySearch is used to locate all of the files in a directory or // one of its subdirectories which match a file spec. //--------------------------------------------------------------------------- void DirectorySearch(const CString & strSpec, const CString & strDir, CStringList &results) { // Look for all of the files which match the file spec in the directory // specified by strDir. WIN32_FIND_DATA finddata; CString strSearch, strDirectory; strDirectory = strDir; if (strDirectory.Right(1) != CString(cszDirSeparator)) strDirectory += CString(cszDirSeparator); strSearch = strDirectory + strSpec; HANDLE hFind = FindFirstFile(strSearch, &finddata); if (hFind != INVALID_HANDLE_VALUE) { do { results.AddHead(strDirectory + CString(finddata.cFileName)); } while (FindNextFile(hFind, &finddata)); FindClose(hFind); } // Now call this function recursively, with each of the subdirectories. strSearch = strDirectory + CString(_T("*")); hFind = FindFirstFile(strSearch, &finddata); if (hFind != INVALID_HANDLE_VALUE) { do { if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (::_tcscmp(finddata.cFileName, _T(".")) != 0 && ::_tcscmp(finddata.cFileName, _T("..")) != 0) DirectorySearch(strSpec, strDirectory + CString(finddata.cFileName), results); } while (FindNextFile(hFind, &finddata)); FindClose(hFind); } } //--------------------------------------------------------------------------- // This function gets the directory in which to put exploded CAB files. // This will be the same directory each time, so this function will create // the directory (if necessary) and delete any files in the directory. //--------------------------------------------------------------------------- BOOL GetCABExplodeDir(CString &destination, BOOL fDeleteFiles, const CString & strDontDelete) { CString strMSInfoDir, strExplodeTo, strSubDirName; // Determine the temporary path and add on a subdir name. TCHAR szTempDir[MAX_PATH]; if (::GetTempPath(MAX_PATH, szTempDir) > MAX_PATH) { destination = _T(""); return FALSE; } strSubDirName.LoadString(IDS_CAB_DIR_NAME); strExplodeTo = szTempDir; if (strExplodeTo.Right(1) == CString(cszDirSeparator)) strExplodeTo = strExplodeTo + strSubDirName; else strExplodeTo = strExplodeTo + CString(cszDirSeparator) + strSubDirName; // Kill the directory if it already exists. if (fDeleteFiles) KillDirectory(strExplodeTo, strDontDelete); // Create the subdirectory. if (!CreateDirectoryEx(szTempDir, strExplodeTo, NULL)) { if (GetLastError() != ERROR_ALREADY_EXISTS) { // MSIError(IDS_GENERAL_ERROR, "couldn't create the target directory"); destination = ""; return FALSE; } } destination = strExplodeTo; return TRUE; } //--------------------------------------------------------------------------- // This functions kills a directory by recursively deleting files and // subdirectories. //--------------------------------------------------------------------------- void KillDirectory(const CString & strDir, const CString & strDontDelete) { CString strDirectory = strDir; if (strDirectory.Right(1) == CString(cszDirSeparator)) strDirectory = strDirectory.Left(strDirectory.GetLength() - 1); // Delete any files in directory. CString strFilesToDelete = strDirectory + CString(_T("\\*.*")); CString strDeleteFile; WIN32_FIND_DATA filedata; BOOL bFound = TRUE; HANDLE hFindFile = FindFirstFile(strFilesToDelete, &filedata); while (hFindFile != INVALID_HANDLE_VALUE && bFound) { if ((filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0L) { strDeleteFile = strDirectory + CString(cszDirSeparator) + filedata.cFileName; if (strDontDelete.CompareNoCase(strDeleteFile) != 0) { ::SetFileAttributes(strDeleteFile, FILE_ATTRIBUTE_NORMAL); ::DeleteFile(strDeleteFile); } } bFound = FindNextFile(hFindFile, &filedata); } FindClose(hFindFile); // Now call this function on any subdirectories in this directory. CString strSearch = strDirectory + CString(_T("\\*")); hFindFile = FindFirstFile(strSearch, &filedata); if (hFindFile != INVALID_HANDLE_VALUE) { do { if (filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (::_tcscmp(filedata.cFileName, _T(".")) != 0 && ::_tcscmp(filedata.cFileName, _T("..")) != 0) KillDirectory(strDirectory + CString(cszDirSeparator) + CString(filedata.cFileName)); } while (FindNextFile(hFindFile, &filedata)); FindClose(hFindFile); } // Finally, remove this directory. ::RemoveDirectory(strDirectory); }