Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

495 lines
15 KiB

  1. // advpext.cpp : Defines the entry point for the DLL application.
  2. //
  3. #include <windows.h>
  4. #include <wininet.h>
  5. #include "util.h"
  6. #include "download.h"
  7. #include "patchapi.h"
  8. #include "resource.h"
  9. #include "patchdownload.h"
  10. #include "sdsutils.h"
  11. #define FILECOUNT 50
  12. PDOWNLOAD_FILEINFO g_pDownloadFileList = NULL;
  13. DWORD g_dwFileCount = 0;
  14. DWORD g_dwArraySize = 0;
  15. HRESULT g_hResult;
  16. HINF g_hInf;
  17. BOOL g_fPreparingDir;
  18. BOOL g_QuietMode = FALSE;
  19. BOOL g_fAbort = FALSE;
  20. HWND g_hProgressDlg = NULL;
  21. HINSTANCE g_hInstance;
  22. HINSTANCE g_hSetupLibrary = NULL;
  23. PFSetupDefaultQueueCallback pfSetupDefaultQueueCallback = NULL;
  24. PFSetupInstallFromInfSection pfSetupInstallFromInfSection = NULL;
  25. PFSetupInitDefaultQueueCallbackEx pfSetupInitDefaultQueueCallbackEx = NULL;
  26. PFSetupTermDefaultQueueCallback pfSetupTermDefaultQueueCallback = NULL;
  27. PFSetupGetLineText pfSetupGetLineText = NULL;
  28. PFSetupFindFirstLine pfSetupFindFirstLine = NULL;
  29. PFSetupFindNextLine pfSetupFindNextLine = NULL;
  30. PFSetupGetStringField pfSetupGetStringField = NULL;
  31. PFSetupDecompressOrCopyFile pfSetupDecompressOrCopyFile = NULL;
  32. BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
  33. {
  34. if(DLL_PROCESS_ATTACH == ul_reason_for_call)
  35. {
  36. InitLogFile();
  37. g_hInstance = (HINSTANCE)hModule;
  38. }
  39. if(DLL_PROCESS_DETACH == ul_reason_for_call)
  40. {
  41. if(g_hLogFile)
  42. CloseHandle(g_hLogFile);
  43. if(g_hSetupLibrary)
  44. FreeLibrary(g_hSetupLibrary);
  45. }
  46. return TRUE;
  47. }
  48. HRESULT WINAPI ProcessFileSection(HINF hInf, HWND hWnd, BOOL fQuietMode, LPCSTR lpszSection, LPCSTR lpszSourceDir,
  49. PATCH_DOWNLOAD_CALLBACK pfn, LPVOID lpvContext)
  50. {
  51. HRESULT hr = S_OK;
  52. PDOWNLOAD_FILEINFO pFileList = NULL;
  53. char szUserName[MAX_PATH] = "", szPassword[MAX_PATH] = "", szUrl[INTERNET_MAX_URL_LENGTH];
  54. TCHAR szSrcDir[MAX_PATH];
  55. DWORD dwFileCount=0;
  56. WriteToLog("ProcessFileSection: InfHandle= %1!lx!, Source Directory = %2\n", hInf, lpszSourceDir);
  57. g_hInf = hInf;
  58. g_fPreparingDir = FALSE;
  59. if(fQuietMode)
  60. {
  61. g_QuietMode = TRUE;
  62. }
  63. if(!g_QuietMode)
  64. {
  65. g_hProgressDlg = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_PROGRESSDLG), hWnd, ProgressDlgProc);
  66. if (g_hProgressDlg)
  67. {
  68. ShowWindow(g_hProgressDlg, SW_SHOWNORMAL);
  69. UpdateWindow(g_hProgressDlg);
  70. }
  71. }
  72. SetProgressText(IDS_FILELIST);
  73. hr = GetFileList(hInf, lpszSection, &pFileList, &dwFileCount);
  74. if(FAILED(hr))
  75. {
  76. goto done;
  77. }
  78. if(dwFileCount)
  79. {
  80. if(!pfSetupGetLineText(NULL, hInf, lpszSection, "Url", szUrl, sizeof(szUrl), NULL))
  81. {
  82. hr = HRESULT_FROM_SETUPAPI(GetLastError());
  83. goto done;
  84. }
  85. hr = DownloadAndPatchFiles(dwFileCount, pFileList, szUrl, lpszSourceDir, pfn, lpvContext);
  86. if(FAILED(hr) || g_fAbort)
  87. {
  88. goto done;
  89. }
  90. }
  91. hr = PrepareInstallDirectory(hInf, lpszSection);
  92. done:
  93. if(pFileList)
  94. {
  95. FreeFileList(pFileList);
  96. }
  97. if(g_hProgressDlg)
  98. {
  99. DestroyWindow(g_hProgressDlg);
  100. }
  101. return hr;
  102. }
  103. HRESULT WINAPI GetFileList(HINF hInf, LPCSTR lpszSection, PDOWNLOAD_FILEINFO* pFileList, DWORD* pdwFileCount)
  104. {
  105. HRESULT hr = LoadSetupAPIFuncs();
  106. if(FAILED(hr))
  107. {
  108. return hr;
  109. }
  110. WriteToLog("\nGetting the list of files\n");
  111. g_hResult = S_OK;
  112. //initially we allocate around 50 entries. We reallocate as and when needed
  113. g_dwArraySize = FILECOUNT;
  114. g_pDownloadFileList = (PDOWNLOAD_FILEINFO)ResizeBuffer(NULL, FILECOUNT*sizeof(DOWNLOAD_FILEINFO), FALSE);
  115. if(!g_pDownloadFileList)
  116. {
  117. return HRESULT_FROM_WIN32(GetLastError());
  118. }
  119. g_dwFileCount = 0;
  120. PVOID pContext = pfSetupInitDefaultQueueCallbackEx( NULL, (HWND)INVALID_HANDLE_VALUE, 0, 0, NULL );
  121. if ( pContext == INVALID_HANDLE_VALUE )
  122. {
  123. return HRESULT_FROM_SETUPAPI(GetLastError());
  124. }
  125. WriteToLog("Adding the Following Files\n");
  126. if (!pfSetupInstallFromInfSection( NULL, hInf, lpszSection, SPINST_FILES, NULL,
  127. NULL, SP_COPY_NEWER, (PSP_FILE_CALLBACK)MyFileQueueCallback,
  128. pContext, NULL, NULL ) )
  129. {
  130. pfSetupTermDefaultQueueCallback( pContext );
  131. return HRESULT_FROM_SETUPAPI(GetLastError());
  132. }
  133. pfSetupTermDefaultQueueCallback( pContext );
  134. if(SUCCEEDED(g_hResult))
  135. {
  136. *pFileList = g_pDownloadFileList;
  137. *pdwFileCount = g_dwFileCount;
  138. }
  139. return g_hResult;
  140. }
  141. UINT WINAPI MyFileQueueCallback( PVOID Context,UINT Notification,UINT_PTR parm1,UINT_PTR parm2 )
  142. {
  143. UINT retVal = FILEOP_SKIP;
  144. switch(Notification)
  145. {
  146. case SPFILENOTIFY_STARTDELETE:
  147. case SPFILENOTIFY_STARTRENAME:
  148. case SPFILENOTIFY_COPYERROR:
  149. case SPFILENOTIFY_DELETEERROR:
  150. case SPFILENOTIFY_RENAMEERROR:
  151. break;
  152. case SPFILENOTIFY_STARTCOPY:
  153. {
  154. FILEPATHS *pFilePath;
  155. pFilePath = (FILEPATHS *)parm1;
  156. if (!MyFileSize(pFilePath->Source))
  157. {
  158. DeleteFile(pFilePath->Source);
  159. //If we are preparing the dir for installaion then copy the file to the current path.
  160. //else we are in download mode, add it to the file list if required
  161. if(g_fPreparingDir)
  162. {
  163. if(CopyFile(pFilePath->Target, pFilePath->Source, TRUE))
  164. WriteToLog("Copying %1 file to %2\n", pFilePath->Target, pFilePath->Source);
  165. }
  166. else
  167. {
  168. //Check in the version in inf to see if we need to download
  169. if(IsDownloadedNeeded(pFilePath->Source, pFilePath->Target))
  170. AddToFileList(pFilePath->Source, pFilePath->Target);
  171. }
  172. }
  173. }
  174. break;
  175. case SPFILENOTIFY_NEEDMEDIA:
  176. {
  177. char szFileName[MAX_PATH];
  178. PSOURCE_MEDIA psrcMed;
  179. psrcMed = (PSOURCE_MEDIA)parm1;
  180. wsprintf(szFileName, "%s\\%s", psrcMed->SourcePath, psrcMed->SourceFile);
  181. if(GetFileAttributes(szFileName) == 0xFFFFFFFF )
  182. {
  183. if(g_fPreparingDir)
  184. {
  185. if(GetFileAttributes(szFileName) != 0xFFFFFFFF)
  186. return retVal;
  187. }
  188. HANDLE hTempFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL,
  189. CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, NULL );
  190. if (hTempFile != INVALID_HANDLE_VALUE)
  191. {
  192. CloseHandle( hTempFile );
  193. }
  194. }
  195. }
  196. default:
  197. return (pfSetupDefaultQueueCallback( Context, Notification, parm1, parm2 ) );
  198. }
  199. return( retVal );
  200. }
  201. BOOL IsDownloadedNeeded(LPCTSTR lpszSrcFilePath, LPCTSTR lpszFilePath)
  202. {
  203. char szVersion[MAX_PATH], szSrcFilePath[MAX_PATH];
  204. INFCONTEXT InfContext;
  205. LPTSTR lp;
  206. LPTSTR lpszSrcName = PathFindFileName(lpszSrcFilePath);
  207. if (!pfSetupFindFirstLine(g_hInf, "SourceDisksFiles", lpszSrcName, &InfContext ))
  208. {
  209. //No SourceDisksFiles entry. Assume that this file needs to be downloaded
  210. return TRUE;
  211. }
  212. DWORD dwMSVer = 0, dwLSVer = 0, dwMSNewFileVer = 0, dwLSNewFileVer = 0;
  213. if(pfSetupGetStringField(&InfContext, 4, szVersion, sizeof(szVersion), NULL))
  214. {
  215. //Get version of file on the machine
  216. ConvertVersionStrToDwords(szVersion, &dwMSNewFileVer, &dwLSNewFileVer);
  217. MyGetVersionFromFile((LPTSTR)lpszFilePath, &dwMSVer, &dwLSVer, TRUE);
  218. }
  219. if(dwMSVer == dwMSNewFileVer && dwLSVer == dwLSNewFileVer)
  220. {
  221. TCHAR szHashFromInf[40], szHashFromFile[40];
  222. if(GetHashidFromINF(lpszSrcName, szHashFromInf, sizeof(szHashFromInf)) &&
  223. GetFilePatchSignatureA(lpszFilePath, PATCH_OPTION_SIGNATURE_MD5, NULL, 0, 0, 0, 0,
  224. sizeof(szHashFromFile), szHashFromFile))
  225. {
  226. if (lstrcmpi(szHashFromFile, szHashFromInf) == 0 )
  227. {
  228. return FALSE;
  229. }
  230. }
  231. return TRUE;
  232. }
  233. if(dwMSVer < dwMSNewFileVer || ((dwMSVer == dwMSNewFileVer) && dwLSVer < dwLSNewFileVer))
  234. {
  235. return TRUE;
  236. }
  237. return FALSE;
  238. }
  239. void AddToFileList(LPCSTR lpszSrc, LPCSTR lpszTarget)
  240. {
  241. TCHAR Signature[40] = ""; // MD5 is 32 hex characters plus terminator
  242. if(g_dwFileCount >= g_dwArraySize)
  243. {
  244. g_dwArraySize = g_dwArraySize + FILECOUNT;
  245. g_pDownloadFileList = (PDOWNLOAD_FILEINFO)ResizeBuffer(g_pDownloadFileList,
  246. g_dwArraySize*sizeof(DOWNLOAD_FILEINFO), FALSE);
  247. if(!g_pDownloadFileList)
  248. {
  249. g_hResult = HRESULT_FROM_WIN32(GetLastError());
  250. return;
  251. }
  252. }
  253. GetFilePatchSignatureA(lpszTarget, PATCH_OPTION_USE_LZX_BEST, NULL, 0 , 0, 0, 0,
  254. sizeof(Signature), Signature);
  255. if ( *Signature )
  256. {
  257. g_pDownloadFileList[g_dwFileCount].lpszExistingFilePatchSignature = StrDup(Signature);
  258. }
  259. else
  260. {
  261. g_pDownloadFileList[g_dwFileCount].lpszExistingFilePatchSignature = NULL;
  262. }
  263. WriteToLog("%1 Destination:%2 Patch Signature:%3\n", PathFindFileName(lpszSrc), lpszTarget, Signature);
  264. g_pDownloadFileList[g_dwFileCount].lpszFileNameToDownload = StrDup(PathFindFileName(lpszSrc));
  265. g_pDownloadFileList[g_dwFileCount].lpszExistingFileToPatchFrom = StrDup(lpszTarget);
  266. g_pDownloadFileList[g_dwFileCount].dwFlags = PATCHFLAG_DOWNLOAD_NEEDED;
  267. g_dwFileCount++;
  268. }
  269. void FreeFileList(PDOWNLOAD_FILEINFO pFileList)
  270. {
  271. int i = g_dwFileCount;
  272. while(i--)
  273. {
  274. if(pFileList[i].lpszFileNameToDownload)
  275. {
  276. LocalFree(pFileList[i].lpszFileNameToDownload);
  277. }
  278. if(pFileList[i].lpszExistingFileToPatchFrom)
  279. {
  280. LocalFree(pFileList[i].lpszExistingFileToPatchFrom);
  281. }
  282. if(pFileList[i].lpszExistingFilePatchSignature)
  283. {
  284. LocalFree(pFileList[i].lpszExistingFilePatchSignature);
  285. }
  286. }
  287. ResizeBuffer(pFileList, 0, 0);
  288. }
  289. HRESULT PrepareInstallDirectory(HINF hInf, LPCSTR lpszSection)
  290. {
  291. g_hResult = S_OK;
  292. g_fPreparingDir = TRUE;
  293. PVOID pContext = pfSetupInitDefaultQueueCallbackEx( NULL, (HWND)INVALID_HANDLE_VALUE, 0, 0, NULL );
  294. if ( pContext == INVALID_HANDLE_VALUE )
  295. {
  296. return HRESULT_FROM_SETUPAPI(GetLastError());
  297. }
  298. WriteToLog("Copying the Following Files from src dir\n");
  299. if (!pfSetupInstallFromInfSection( NULL, hInf, lpszSection, SPINST_FILES, NULL,
  300. NULL, SP_COPY_NEWER, (PSP_FILE_CALLBACK)MyFileQueueCallback,
  301. pContext, NULL, NULL ) )
  302. {
  303. pfSetupTermDefaultQueueCallback( pContext );
  304. return HRESULT_FROM_SETUPAPI(GetLastError());
  305. }
  306. pfSetupTermDefaultQueueCallback( pContext );
  307. return g_hResult;
  308. }
  309. INT_PTR CALLBACK ProgressDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  310. {
  311. switch (uMsg)
  312. {
  313. case WM_INITDIALOG:
  314. {
  315. CenterWindow (hDlg, GetDesktopWindow());
  316. }
  317. break;
  318. case WM_COMMAND:
  319. if(LOWORD(wParam) == IDCANCEL)
  320. {
  321. g_fAbort = TRUE;
  322. }
  323. default:
  324. return(FALSE);
  325. }
  326. return(TRUE);
  327. }
  328. BOOL SetProgressText(LPCTSTR lpszText)
  329. {
  330. if(g_hProgressDlg)
  331. {
  332. SetDlgItemText(g_hProgressDlg, IDC_PROGRESSTEXT, lpszText);
  333. }
  334. return TRUE;
  335. }
  336. BOOL SetProgressText(UINT uID)
  337. {
  338. if(g_hProgressDlg)
  339. {
  340. TCHAR szBuffer[MAX_PATH];
  341. LoadString(g_hInstance, uID, szBuffer, sizeof(szBuffer));
  342. SetDlgItemText(g_hProgressDlg, IDC_PROGRESSTEXT, szBuffer);
  343. }
  344. return TRUE;
  345. }
  346. HRESULT LoadSetupAPIFuncs()
  347. {
  348. static BOOL fSetupLibLoaded = -1;
  349. HRESULT hr = S_OK;
  350. if(fSetupLibLoaded != -1)
  351. {
  352. return hr;
  353. }
  354. g_hSetupLibrary = LoadLibrary("SETUPAPI.DLL");
  355. if(!g_hSetupLibrary)
  356. {
  357. hr = HRESULT_FROM_WIN32(GetLastError());
  358. WriteToLog("LoadLibrary for Setuapi.dll failed with error code:%1!lx!\n", hr);
  359. return hr;
  360. }
  361. pfSetupGetStringField = (PFSetupGetStringField) GetProcAddress(g_hSetupLibrary, c_szSetupGetStringField );
  362. pfSetupDefaultQueueCallback = (PFSetupDefaultQueueCallback) GetProcAddress(g_hSetupLibrary, c_szSetupDefaultQueueCallback );
  363. pfSetupInstallFromInfSection = (PFSetupInstallFromInfSection) GetProcAddress(g_hSetupLibrary, c_szSetupInstallFromInfSection );
  364. pfSetupInitDefaultQueueCallbackEx = (PFSetupInitDefaultQueueCallbackEx) GetProcAddress(g_hSetupLibrary, c_szSetupInitDefaultQueueCallbackEx );
  365. pfSetupTermDefaultQueueCallback = (PFSetupTermDefaultQueueCallback) GetProcAddress(g_hSetupLibrary, c_szSetupTermDefaultQueueCallback );
  366. pfSetupGetLineText = (PFSetupGetLineText) GetProcAddress(g_hSetupLibrary, c_szSetupGetLineText );
  367. pfSetupFindFirstLine = (PFSetupFindFirstLine) GetProcAddress(g_hSetupLibrary, c_szSetupFindFirstLine );
  368. pfSetupFindNextLine = (PFSetupFindNextLine) GetProcAddress(g_hSetupLibrary, c_szSetupFindNextLine );
  369. pfSetupDecompressOrCopyFile = (PFSetupDecompressOrCopyFile) GetProcAddress(g_hSetupLibrary, c_szSetupDecompressOrCopyFile );
  370. if (pfSetupDefaultQueueCallback == NULL
  371. || pfSetupInstallFromInfSection == NULL
  372. || pfSetupInitDefaultQueueCallbackEx == NULL
  373. || pfSetupTermDefaultQueueCallback == NULL
  374. || pfSetupGetLineText == NULL
  375. || pfSetupFindFirstLine == NULL
  376. || pfSetupFindNextLine == NULL
  377. || pfSetupDecompressOrCopyFile == NULL
  378. || pfSetupGetStringField == NULL )
  379. {
  380. return HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
  381. }
  382. fSetupLibLoaded = TRUE;
  383. WriteToLog("Setupapi.dll loaded successfully\n");
  384. return hr;
  385. }