// advpext.cpp : Defines the entry point for the DLL application. // #include #include #include "util.h" #include "download.h" #include "patchapi.h" #include "resource.h" #include "patchdownload.h" #include "sdsutils.h" #define FILECOUNT 50 PDOWNLOAD_FILEINFO g_pDownloadFileList = NULL; DWORD g_dwFileCount = 0; DWORD g_dwArraySize = 0; HRESULT g_hResult; HINF g_hInf; BOOL g_fPreparingDir; BOOL g_QuietMode = FALSE; BOOL g_fAbort = FALSE; HWND g_hProgressDlg = NULL; HINSTANCE g_hInstance; HINSTANCE g_hSetupLibrary = NULL; PFSetupDefaultQueueCallback pfSetupDefaultQueueCallback = NULL; PFSetupInstallFromInfSection pfSetupInstallFromInfSection = NULL; PFSetupInitDefaultQueueCallbackEx pfSetupInitDefaultQueueCallbackEx = NULL; PFSetupTermDefaultQueueCallback pfSetupTermDefaultQueueCallback = NULL; PFSetupGetLineText pfSetupGetLineText = NULL; PFSetupFindFirstLine pfSetupFindFirstLine = NULL; PFSetupFindNextLine pfSetupFindNextLine = NULL; PFSetupGetStringField pfSetupGetStringField = NULL; PFSetupDecompressOrCopyFile pfSetupDecompressOrCopyFile = NULL; BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if(DLL_PROCESS_ATTACH == ul_reason_for_call) { InitLogFile(); g_hInstance = (HINSTANCE)hModule; } if(DLL_PROCESS_DETACH == ul_reason_for_call) { if(g_hLogFile) CloseHandle(g_hLogFile); if(g_hSetupLibrary) FreeLibrary(g_hSetupLibrary); } return TRUE; } HRESULT WINAPI ProcessFileSection(HINF hInf, HWND hWnd, BOOL fQuietMode, LPCSTR lpszSection, LPCSTR lpszSourceDir, PATCH_DOWNLOAD_CALLBACK pfn, LPVOID lpvContext) { HRESULT hr = S_OK; PDOWNLOAD_FILEINFO pFileList = NULL; char szUserName[MAX_PATH] = "", szPassword[MAX_PATH] = "", szUrl[INTERNET_MAX_URL_LENGTH]; TCHAR szSrcDir[MAX_PATH]; DWORD dwFileCount=0; WriteToLog("ProcessFileSection: InfHandle= %1!lx!, Source Directory = %2\n", hInf, lpszSourceDir); g_hInf = hInf; g_fPreparingDir = FALSE; if(fQuietMode) { g_QuietMode = TRUE; } if(!g_QuietMode) { g_hProgressDlg = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_PROGRESSDLG), hWnd, ProgressDlgProc); if (g_hProgressDlg) { ShowWindow(g_hProgressDlg, SW_SHOWNORMAL); UpdateWindow(g_hProgressDlg); } } SetProgressText(IDS_FILELIST); hr = GetFileList(hInf, lpszSection, &pFileList, &dwFileCount); if(FAILED(hr)) { goto done; } if(dwFileCount) { if(!pfSetupGetLineText(NULL, hInf, lpszSection, "Url", szUrl, sizeof(szUrl), NULL)) { hr = HRESULT_FROM_SETUPAPI(GetLastError()); goto done; } hr = DownloadAndPatchFiles(dwFileCount, pFileList, szUrl, lpszSourceDir, pfn, lpvContext); if(FAILED(hr) || g_fAbort) { goto done; } } hr = PrepareInstallDirectory(hInf, lpszSection); done: if(pFileList) { FreeFileList(pFileList); } if(g_hProgressDlg) { DestroyWindow(g_hProgressDlg); } return hr; } HRESULT WINAPI GetFileList(HINF hInf, LPCSTR lpszSection, PDOWNLOAD_FILEINFO* pFileList, DWORD* pdwFileCount) { HRESULT hr = LoadSetupAPIFuncs(); if(FAILED(hr)) { return hr; } WriteToLog("\nGetting the list of files\n"); g_hResult = S_OK; //initially we allocate around 50 entries. We reallocate as and when needed g_dwArraySize = FILECOUNT; g_pDownloadFileList = (PDOWNLOAD_FILEINFO)ResizeBuffer(NULL, FILECOUNT*sizeof(DOWNLOAD_FILEINFO), FALSE); if(!g_pDownloadFileList) { return HRESULT_FROM_WIN32(GetLastError()); } g_dwFileCount = 0; PVOID pContext = pfSetupInitDefaultQueueCallbackEx( NULL, (HWND)INVALID_HANDLE_VALUE, 0, 0, NULL ); if ( pContext == INVALID_HANDLE_VALUE ) { return HRESULT_FROM_SETUPAPI(GetLastError()); } WriteToLog("Adding the Following Files\n"); if (!pfSetupInstallFromInfSection( NULL, hInf, lpszSection, SPINST_FILES, NULL, NULL, SP_COPY_NEWER, (PSP_FILE_CALLBACK)MyFileQueueCallback, pContext, NULL, NULL ) ) { pfSetupTermDefaultQueueCallback( pContext ); return HRESULT_FROM_SETUPAPI(GetLastError()); } pfSetupTermDefaultQueueCallback( pContext ); if(SUCCEEDED(g_hResult)) { *pFileList = g_pDownloadFileList; *pdwFileCount = g_dwFileCount; } return g_hResult; } UINT WINAPI MyFileQueueCallback( PVOID Context,UINT Notification,UINT_PTR parm1,UINT_PTR parm2 ) { UINT retVal = FILEOP_SKIP; switch(Notification) { case SPFILENOTIFY_STARTDELETE: case SPFILENOTIFY_STARTRENAME: case SPFILENOTIFY_COPYERROR: case SPFILENOTIFY_DELETEERROR: case SPFILENOTIFY_RENAMEERROR: break; case SPFILENOTIFY_STARTCOPY: { FILEPATHS *pFilePath; pFilePath = (FILEPATHS *)parm1; if (!MyFileSize(pFilePath->Source)) { DeleteFile(pFilePath->Source); //If we are preparing the dir for installaion then copy the file to the current path. //else we are in download mode, add it to the file list if required if(g_fPreparingDir) { if(CopyFile(pFilePath->Target, pFilePath->Source, TRUE)) WriteToLog("Copying %1 file to %2\n", pFilePath->Target, pFilePath->Source); } else { //Check in the version in inf to see if we need to download if(IsDownloadedNeeded(pFilePath->Source, pFilePath->Target)) AddToFileList(pFilePath->Source, pFilePath->Target); } } } break; case SPFILENOTIFY_NEEDMEDIA: { char szFileName[MAX_PATH]; PSOURCE_MEDIA psrcMed; psrcMed = (PSOURCE_MEDIA)parm1; wsprintf(szFileName, "%s\\%s", psrcMed->SourcePath, psrcMed->SourceFile); if(GetFileAttributes(szFileName) == 0xFFFFFFFF ) { if(g_fPreparingDir) { if(GetFileAttributes(szFileName) != 0xFFFFFFFF) return retVal; } HANDLE hTempFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, NULL ); if (hTempFile != INVALID_HANDLE_VALUE) { CloseHandle( hTempFile ); } } } default: return (pfSetupDefaultQueueCallback( Context, Notification, parm1, parm2 ) ); } return( retVal ); } BOOL IsDownloadedNeeded(LPCTSTR lpszSrcFilePath, LPCTSTR lpszFilePath) { char szVersion[MAX_PATH], szSrcFilePath[MAX_PATH]; INFCONTEXT InfContext; LPTSTR lp; LPTSTR lpszSrcName = PathFindFileName(lpszSrcFilePath); if (!pfSetupFindFirstLine(g_hInf, "SourceDisksFiles", lpszSrcName, &InfContext )) { //No SourceDisksFiles entry. Assume that this file needs to be downloaded return TRUE; } DWORD dwMSVer = 0, dwLSVer = 0, dwMSNewFileVer = 0, dwLSNewFileVer = 0; if(pfSetupGetStringField(&InfContext, 4, szVersion, sizeof(szVersion), NULL)) { //Get version of file on the machine ConvertVersionStrToDwords(szVersion, &dwMSNewFileVer, &dwLSNewFileVer); MyGetVersionFromFile((LPTSTR)lpszFilePath, &dwMSVer, &dwLSVer, TRUE); } if(dwMSVer == dwMSNewFileVer && dwLSVer == dwLSNewFileVer) { TCHAR szHashFromInf[40], szHashFromFile[40]; if(GetHashidFromINF(lpszSrcName, szHashFromInf, sizeof(szHashFromInf)) && GetFilePatchSignatureA(lpszFilePath, PATCH_OPTION_SIGNATURE_MD5, NULL, 0, 0, 0, 0, sizeof(szHashFromFile), szHashFromFile)) { if (lstrcmpi(szHashFromFile, szHashFromInf) == 0 ) { return FALSE; } } return TRUE; } if(dwMSVer < dwMSNewFileVer || ((dwMSVer == dwMSNewFileVer) && dwLSVer < dwLSNewFileVer)) { return TRUE; } return FALSE; } void AddToFileList(LPCSTR lpszSrc, LPCSTR lpszTarget) { TCHAR Signature[40] = ""; // MD5 is 32 hex characters plus terminator if(g_dwFileCount >= g_dwArraySize) { g_dwArraySize = g_dwArraySize + FILECOUNT; g_pDownloadFileList = (PDOWNLOAD_FILEINFO)ResizeBuffer(g_pDownloadFileList, g_dwArraySize*sizeof(DOWNLOAD_FILEINFO), FALSE); if(!g_pDownloadFileList) { g_hResult = HRESULT_FROM_WIN32(GetLastError()); return; } } GetFilePatchSignatureA(lpszTarget, PATCH_OPTION_USE_LZX_BEST, NULL, 0 , 0, 0, 0, sizeof(Signature), Signature); if ( *Signature ) { g_pDownloadFileList[g_dwFileCount].lpszExistingFilePatchSignature = StrDup(Signature); } else { g_pDownloadFileList[g_dwFileCount].lpszExistingFilePatchSignature = NULL; } WriteToLog("%1 Destination:%2 Patch Signature:%3\n", PathFindFileName(lpszSrc), lpszTarget, Signature); g_pDownloadFileList[g_dwFileCount].lpszFileNameToDownload = StrDup(PathFindFileName(lpszSrc)); g_pDownloadFileList[g_dwFileCount].lpszExistingFileToPatchFrom = StrDup(lpszTarget); g_pDownloadFileList[g_dwFileCount].dwFlags = PATCHFLAG_DOWNLOAD_NEEDED; g_dwFileCount++; } void FreeFileList(PDOWNLOAD_FILEINFO pFileList) { int i = g_dwFileCount; while(i--) { if(pFileList[i].lpszFileNameToDownload) { LocalFree(pFileList[i].lpszFileNameToDownload); } if(pFileList[i].lpszExistingFileToPatchFrom) { LocalFree(pFileList[i].lpszExistingFileToPatchFrom); } if(pFileList[i].lpszExistingFilePatchSignature) { LocalFree(pFileList[i].lpszExistingFilePatchSignature); } } ResizeBuffer(pFileList, 0, 0); } HRESULT PrepareInstallDirectory(HINF hInf, LPCSTR lpszSection) { g_hResult = S_OK; g_fPreparingDir = TRUE; PVOID pContext = pfSetupInitDefaultQueueCallbackEx( NULL, (HWND)INVALID_HANDLE_VALUE, 0, 0, NULL ); if ( pContext == INVALID_HANDLE_VALUE ) { return HRESULT_FROM_SETUPAPI(GetLastError()); } WriteToLog("Copying the Following Files from src dir\n"); if (!pfSetupInstallFromInfSection( NULL, hInf, lpszSection, SPINST_FILES, NULL, NULL, SP_COPY_NEWER, (PSP_FILE_CALLBACK)MyFileQueueCallback, pContext, NULL, NULL ) ) { pfSetupTermDefaultQueueCallback( pContext ); return HRESULT_FROM_SETUPAPI(GetLastError()); } pfSetupTermDefaultQueueCallback( pContext ); return g_hResult; } INT_PTR CALLBACK ProgressDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { CenterWindow (hDlg, GetDesktopWindow()); } break; case WM_COMMAND: if(LOWORD(wParam) == IDCANCEL) { g_fAbort = TRUE; } default: return(FALSE); } return(TRUE); } BOOL SetProgressText(LPCTSTR lpszText) { if(g_hProgressDlg) { SetDlgItemText(g_hProgressDlg, IDC_PROGRESSTEXT, lpszText); } return TRUE; } BOOL SetProgressText(UINT uID) { if(g_hProgressDlg) { TCHAR szBuffer[MAX_PATH]; LoadString(g_hInstance, uID, szBuffer, sizeof(szBuffer)); SetDlgItemText(g_hProgressDlg, IDC_PROGRESSTEXT, szBuffer); } return TRUE; } HRESULT LoadSetupAPIFuncs() { static BOOL fSetupLibLoaded = -1; HRESULT hr = S_OK; if(fSetupLibLoaded != -1) { return hr; } g_hSetupLibrary = LoadLibrary("SETUPAPI.DLL"); if(!g_hSetupLibrary) { hr = HRESULT_FROM_WIN32(GetLastError()); WriteToLog("LoadLibrary for Setuapi.dll failed with error code:%1!lx!\n", hr); return hr; } pfSetupGetStringField = (PFSetupGetStringField) GetProcAddress(g_hSetupLibrary, c_szSetupGetStringField ); pfSetupDefaultQueueCallback = (PFSetupDefaultQueueCallback) GetProcAddress(g_hSetupLibrary, c_szSetupDefaultQueueCallback ); pfSetupInstallFromInfSection = (PFSetupInstallFromInfSection) GetProcAddress(g_hSetupLibrary, c_szSetupInstallFromInfSection ); pfSetupInitDefaultQueueCallbackEx = (PFSetupInitDefaultQueueCallbackEx) GetProcAddress(g_hSetupLibrary, c_szSetupInitDefaultQueueCallbackEx ); pfSetupTermDefaultQueueCallback = (PFSetupTermDefaultQueueCallback) GetProcAddress(g_hSetupLibrary, c_szSetupTermDefaultQueueCallback ); pfSetupGetLineText = (PFSetupGetLineText) GetProcAddress(g_hSetupLibrary, c_szSetupGetLineText ); pfSetupFindFirstLine = (PFSetupFindFirstLine) GetProcAddress(g_hSetupLibrary, c_szSetupFindFirstLine ); pfSetupFindNextLine = (PFSetupFindNextLine) GetProcAddress(g_hSetupLibrary, c_szSetupFindNextLine ); pfSetupDecompressOrCopyFile = (PFSetupDecompressOrCopyFile) GetProcAddress(g_hSetupLibrary, c_szSetupDecompressOrCopyFile ); if (pfSetupDefaultQueueCallback == NULL || pfSetupInstallFromInfSection == NULL || pfSetupInitDefaultQueueCallbackEx == NULL || pfSetupTermDefaultQueueCallback == NULL || pfSetupGetLineText == NULL || pfSetupFindFirstLine == NULL || pfSetupFindNextLine == NULL || pfSetupDecompressOrCopyFile == NULL || pfSetupGetStringField == NULL ) { return HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND); } fSetupLibLoaded = TRUE; WriteToLog("Setupapi.dll loaded successfully\n"); return hr; }