Source code of Windows XP (NT5)
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.

909 lines
25 KiB

  1. /*****************************************************************************\
  2. * MODULE: gencab.c
  3. *
  4. * The module contains routines for generating a self-extracting CAB file
  5. * for the IExpress utility. This relies on the cdfCreate and infCreate
  6. * to create the objects for the IExpress process.
  7. *
  8. *
  9. * Copyright (C) 1996-1997 Microsoft Corporation
  10. * Copyright (C) 1996-1997 Hewlett Packard
  11. *
  12. * History:
  13. * 22-Nov-1996 <chriswil> Created.
  14. *
  15. \*****************************************************************************/
  16. #include "pch.h"
  17. #include "spool.h"
  18. #include <initguid.h> // To define the IIS Metabase GUIDs used in this file. Every other file defines GUIDs as extern, except here where we actually define them in initguid.h.
  19. #include <iadmw.h> // Interface header
  20. #include <iiscnfg.h> // MD_ & IIS_MD_ defines
  21. #define CAB_TIMEOUT 1000
  22. /*****************************************************************************\
  23. * Critical Section Handling
  24. *
  25. \*****************************************************************************/
  26. DWORD gdwCritOwner = 0;
  27. VOID cab_enter_crit(VOID)
  28. {
  29. EnterCriticalSection(&g_csGenCab);
  30. gdwCritOwner = GetCurrentThreadId();
  31. }
  32. VOID cab_leave_crit(VOID)
  33. {
  34. gdwCritOwner = 0;
  35. LeaveCriticalSection(&g_csGenCab);
  36. }
  37. VOID cab_check_crit(VOID)
  38. {
  39. DWORD dwCurrent = GetCurrentThreadId();
  40. SPLASSERT((dwCurrent == gdwCritOwner));
  41. }
  42. #define EnterCABCrit() cab_enter_crit()
  43. #define LeaveCABCrit() cab_leave_crit()
  44. #define CheckCABCrit() cab_check_crit()
  45. /*****************************************************************************\
  46. * cab_SetClientSecurity (Local Routine)
  47. *
  48. * This routine sets the thread security so that it has max-privileges.
  49. *
  50. \*****************************************************************************/
  51. HANDLE cab_SetClientSecurity(VOID)
  52. {
  53. HANDLE hToken;
  54. HANDLE hThread = GetCurrentThread();
  55. if (OpenThreadToken(hThread, TOKEN_IMPERSONATE, TRUE, &hToken)) {
  56. if (SetThreadToken(&hThread, NULL)) {
  57. return hToken;
  58. }
  59. CloseHandle(hToken);
  60. }
  61. return NULL;
  62. }
  63. /*****************************************************************************\
  64. * cab_ResetClientSecurity (Local Routine)
  65. *
  66. * This routine resets the client-security to the token passed in. This
  67. * is called in order to set the thread to the original security attributes.
  68. *
  69. \*****************************************************************************/
  70. BOOL cab_ResetClientSecurity(
  71. HANDLE hToken)
  72. {
  73. BOOL bRet;
  74. bRet = SetThreadToken(NULL, hToken);
  75. CloseHandle(hToken);
  76. return bRet;
  77. }
  78. /*****************************************************************************\
  79. * cab_iexpress_sync (Local Routine)
  80. *
  81. * This routine sychronizes the process and won't return until the process
  82. * is done generating the CAB executable.
  83. *
  84. \*****************************************************************************/
  85. BOOL cab_iexpress_sync(
  86. HANDLE hProcess)
  87. {
  88. DWORD dwObj;
  89. DWORD dwExitCode;
  90. while (TRUE) {
  91. dwObj = WaitForSingleObject(hProcess, INFINITE);
  92. // Look for the exit type.
  93. //
  94. switch (dwObj) {
  95. // The process handle triggered the wait. Let's get the
  96. // exit-code and return whether the success. Otherwise,
  97. // drop through and return the failure.
  98. //
  99. case WAIT_OBJECT_0:
  100. GetExitCodeProcess(hProcess, &dwExitCode);
  101. if (dwExitCode == 0)
  102. return TRUE;
  103. // Something failed in the call. We failed.
  104. //
  105. case WAIT_FAILED:
  106. return FALSE;
  107. }
  108. }
  109. }
  110. /*****************************************************************************\
  111. * cab_force_delete_file
  112. *
  113. * Reset a files attributes before deleting it. We copied them to the temp dir
  114. * so we can delete them no matter what.
  115. *
  116. \*****************************************************************************/
  117. VOID cab_force_delete_file(
  118. LPCTSTR lpszFileName)
  119. {
  120. SetFileAttributes( lpszFileName, FILE_ATTRIBUTE_NORMAL );
  121. DeleteFile( lpszFileName );
  122. }
  123. /*****************************************************************************\
  124. * cab_cleanup_files
  125. *
  126. * Cleanup any files left-over in our generation process. Particularly,
  127. * this will remove cab-files.
  128. *
  129. \*****************************************************************************/
  130. VOID cab_cleanup_files(
  131. LPCTSTR lpszDstPath)
  132. {
  133. TCHAR szAllExt[MIN_CAB_BUFFER];
  134. HANDLE hFind;
  135. DWORD idx;
  136. DWORD cItems;
  137. LPTSTR lpszCurDir;
  138. WIN32_FIND_DATA wfd;
  139. static LPCTSTR s_szFiles[] = {
  140. g_szDotInf,
  141. g_szDotBin,
  142. g_szDotCat
  143. };
  144. // Put us into the destination directory where we
  145. // want to cleanup the files.
  146. //
  147. if (lpszCurDir = genGetCurDir()) {
  148. SetCurrentDirectory(lpszDstPath);
  149. // Delete the temporary dat-file used in building
  150. // the cdf-file
  151. //
  152. cab_force_delete_file(g_szDatFile);
  153. // Delete certain extension files.
  154. //
  155. cItems = sizeof(s_szFiles) / sizeof(s_szFiles[0]);
  156. for (idx = 0; idx < cItems; idx++) {
  157. wsprintf(szAllExt, TEXT("*%s"), s_szFiles[idx]);
  158. hFind = FindFirstFile(szAllExt, &wfd);
  159. if (hFind && (hFind != INVALID_HANDLE_VALUE)) {
  160. do {
  161. cab_force_delete_file(wfd.cFileName);
  162. } while (FindNextFile(hFind, &wfd));
  163. FindClose(hFind);
  164. }
  165. }
  166. SetCurrentDirectory(lpszCurDir);
  167. genGFree(lpszCurDir, genGSize(lpszCurDir));
  168. }
  169. return;
  170. }
  171. /*****************************************************************************\
  172. * cab_rename_cab
  173. *
  174. * Renames the .CAB to the dstname.
  175. *
  176. \*****************************************************************************/
  177. BOOL cab_rename_cab(
  178. LPCTSTR lpszDstName)
  179. {
  180. LPTSTR lpszSrc;
  181. LPTSTR lpszDst;
  182. BOOL bRet = FALSE;
  183. if (lpszSrc = genBuildFileName(NULL, lpszDstName, g_szDotCab)) {
  184. if (lpszDst = genBuildFileName(NULL, lpszDstName, g_szDotIpp)) {
  185. bRet = MoveFileEx(lpszSrc, lpszDst, MOVEFILE_REPLACE_EXISTING);
  186. genGFree(lpszDst, genGSize(lpszDst));
  187. }
  188. genGFree(lpszSrc, genGSize(lpszSrc));
  189. }
  190. return bRet;
  191. }
  192. /*****************************************************************************\
  193. * cab_iexpress_exec (Local Routine)
  194. *
  195. * This exec's the IExpress utility to generate the self-extracting CAB
  196. * file.
  197. *
  198. \*****************************************************************************/
  199. BOOL cab_iexpress_exec(
  200. LPCTSTR lpszCabDir,
  201. LPCTSTR lpszDstName,
  202. LPCTSTR lpszSedFile)
  203. {
  204. PROCESS_INFORMATION pi;
  205. STARTUPINFO sti;
  206. LPTSTR lpszCmd;
  207. DWORD cbSize;
  208. LPTSTR lpszOldDir;
  209. BOOL bSuccess = FALSE;
  210. TCHAR szWindowDir[MAX_PATH];
  211. DWORD dwWinDirLen = 0;
  212. if (dwWinDirLen = GetSystemWindowsDirectory (szWindowDir, MAX_PATH))
  213. {
  214. if (szWindowDir[dwWinDirLen - 1] == TEXT ('\\'))
  215. {
  216. szWindowDir[dwWinDirLen - 1] = 0;
  217. }
  218. // Calculate enough space to hold the command-line arguments.
  219. //
  220. cbSize = (dwWinDirLen + lstrlen(lpszSedFile) + lstrlen(g_szCabCmd) + 1) * sizeof(TCHAR);
  221. // Allocate the command-line for the create-process call.
  222. //
  223. if (lpszCmd = (LPTSTR)genGAlloc(cbSize)) {
  224. // Initialize startup-info fields.
  225. //
  226. memset(&sti, 0, sizeof(STARTUPINFO));
  227. sti.cb = sizeof(STARTUPINFO);
  228. // Build the command-line string that exec's IExpress.
  229. //
  230. wsprintf(lpszCmd, g_szCabCmd, szWindowDir, lpszSedFile);
  231. // Change the directory to the cab/sed directory. It
  232. // appears that IExpress requires this to generate.
  233. //
  234. if (lpszOldDir = genGetCurDir()) {
  235. SetCurrentDirectory(lpszCabDir);
  236. // Exec the process.
  237. //
  238. if (EXEC_PROCESS(lpszCmd, &sti, &pi)) {
  239. CloseHandle(pi.hThread);
  240. // This will wait until the process if finished generating
  241. // the file. The return from this indicates whether the
  242. // generation succeeded or not.
  243. //
  244. if (cab_iexpress_sync(pi.hProcess))
  245. bSuccess = cab_rename_cab(lpszDstName);
  246. CloseHandle(pi.hProcess);
  247. }
  248. // Restore our current-directory and free up any strings.
  249. //
  250. SetCurrentDirectory(lpszOldDir);
  251. genGFree(lpszOldDir, genGSize(lpszOldDir));
  252. }
  253. genGFree(lpszCmd, cbSize);
  254. }
  255. }
  256. return bSuccess;
  257. }
  258. /*****************************************************************************\
  259. * cab_get_modtime
  260. *
  261. * Returns the modified-time of the CAB file. This can be used to determine
  262. * whether this is out of date with other files.
  263. *
  264. \*****************************************************************************/
  265. BOOL cab_get_modtime(
  266. LPTSTR lpszOutPath,
  267. LPFILETIME lpft)
  268. {
  269. HANDLE hFile;
  270. BOOL bRet = FALSE;
  271. // Open the file for reading.
  272. //
  273. hFile = gen_OpenFileRead(lpszOutPath);
  274. // If the file exists and was opened, go get the time.
  275. //
  276. if (hFile && (hFile != INVALID_HANDLE_VALUE)) {
  277. bRet = GetFileTime(hFile, NULL, NULL, lpft);
  278. CloseHandle(hFile);
  279. }
  280. return bRet;
  281. }
  282. /*****************************************************************************\
  283. * cab_get_drvname (Local Routine)
  284. *
  285. * This routine attempts to open the printer, and retrieve the printer
  286. * driver-name associated with the FriendlyName. This returns to pointers
  287. * to a driver and a share-name.
  288. *
  289. \*****************************************************************************/
  290. BOOL cab_get_drvname(
  291. LPCTSTR lpszFriendlyName,
  292. LPTSTR* lpszDrvName,
  293. LPTSTR* lpszShrName,
  294. DWORD idxPlt
  295. )
  296. {
  297. HANDLE hPrinter;
  298. LPPRINTER_INFO_2 lppi;
  299. DWORD cbBuf;
  300. DWORD cbNeed;
  301. BOOL bRet = FALSE;
  302. // Initialize the pointers for the fail-case.
  303. //
  304. *lpszShrName = NULL;
  305. *lpszDrvName = NULL;
  306. // Open the printer and use the handle to query the printer for
  307. // the driver-name.
  308. //
  309. if (OpenPrinter((LPTSTR)lpszFriendlyName, &hPrinter, NULL)) {
  310. // First let's see how big our buffer will need to
  311. // be in order to hold the PRINTER_INFO_2.
  312. //
  313. cbBuf = 0;
  314. GetPrinter(hPrinter, PRT_LEV_2, NULL, 0, &cbBuf);
  315. // Allocate storage for holding the print-info structure.
  316. //
  317. if (cbBuf && (lppi = (LPPRINTER_INFO_2)genGAlloc(cbBuf))) {
  318. if (GetPrinter(hPrinter, PRT_LEV_2, (LPBYTE)lppi, cbBuf, &cbNeed)) {
  319. //If this is a Win9X client make sure the driver name is correct
  320. if ( genIsWin9X(idxPlt) )
  321. {
  322. // Call get printer driver to get the actual driver name for Win9X
  323. DWORD rc, cbNeeded;
  324. GetPrinterDriver( hPrinter, (LPTSTR) genStrCliEnvironment(idxPlt), 3,
  325. NULL, 0, &cbNeeded);
  326. rc = GetLastError();
  327. if ( rc == ERROR_INSUFFICIENT_BUFFER )
  328. {
  329. LPBYTE pData;
  330. DWORD dwSize = cbNeeded;
  331. if ( pData = (LPBYTE) genGAlloc(cbNeeded) )
  332. {
  333. if ( GetPrinterDriver( hPrinter, (LPTSTR) genStrCliEnvironment(idxPlt), 3,
  334. pData, dwSize, &cbNeeded) )
  335. {
  336. PDRIVER_INFO_3 pDriver = (PDRIVER_INFO_3) pData;
  337. *lpszDrvName = genGAllocStr(pDriver->pName);
  338. }
  339. genGFree( pData, dwSize );
  340. }
  341. }
  342. else
  343. *lpszDrvName = genGAllocStr(lppi->pDriverName);
  344. }
  345. else
  346. *lpszDrvName = genGAllocStr(lppi->pDriverName);
  347. if ( *lpszDrvName ) {
  348. if (*lpszShrName = genGAllocStr(lppi->pShareName)) {
  349. bRet = TRUE;
  350. } else {
  351. genGFree(*lpszDrvName, genGSize(*lpszDrvName));
  352. *lpszDrvName = NULL;
  353. }
  354. }
  355. }
  356. genGFree(lppi, cbBuf);
  357. }
  358. ClosePrinter(hPrinter);
  359. }
  360. return bRet;
  361. }
  362. /*****************************************************************************\
  363. * cab_get_dstname
  364. *
  365. * Returns the then name of the destination-files. The name built
  366. * incorporates the platform/version so that it is not duplicated with
  367. * any other files.
  368. *
  369. * <Share ChkSum><Arch><Ver>.webpnp
  370. *
  371. * i.e. <share chksum>AXP2 - NT Alpha 4.0
  372. * <share chksum>A863 - NT x86 5.0
  373. * <share chksum>AXP3 - NT Alpha 5.0
  374. * <share chksum>W9X0 - Win9X
  375. *
  376. \*****************************************************************************/
  377. LPTSTR cab_get_dstname(
  378. DWORD idxPlt,
  379. DWORD idxVer,
  380. LPCTSTR lpszShr)
  381. {
  382. int cch;
  383. int cchBuf;
  384. LPCTSTR lpszPlt;
  385. LPTSTR lpszName = NULL;
  386. // Get the platform requested for the client.
  387. //
  388. if (lpszPlt = genStrCliCab(idxPlt)) {
  389. cchBuf = lstrlen(lpszPlt) + MIN_CAB_BUFFER;
  390. // Build the cabname according to platform and version.
  391. //
  392. if (lpszName = (LPTSTR)genGAlloc(cchBuf * sizeof(TCHAR))) {
  393. cch = wsprintf(lpszName, g_szCabName, genChkSum(lpszShr), lpszPlt, idxVer);
  394. SPLASSERT((cch < cchBuf));
  395. }
  396. }
  397. return lpszName;
  398. }
  399. /*****************************************************************************\
  400. * cab_get_name
  401. *
  402. * Returns the name of the returned-file.
  403. *
  404. \*****************************************************************************/
  405. VOID cab_get_name(
  406. LPCTSTR lpszDstName,
  407. LPCTSTR lpszShrName,
  408. LPTSTR lpszName)
  409. {
  410. DWORD cch;
  411. cch = wsprintf(lpszName, TEXT("/printers/%s/%s%s"), g_szPrtCabs, lpszDstName, g_szDotIpp);
  412. SPLASSERT((cch < MAX_PATH));
  413. return;
  414. }
  415. /*****************************************************************************\
  416. * cab_get_webdir
  417. *
  418. * Returns the virtual-root-directory where the cab-files are to be generated
  419. * and stored.
  420. *
  421. \*****************************************************************************/
  422. LPTSTR cab_get_webdir(VOID)
  423. {
  424. BOOL bRet = FALSE;
  425. HRESULT hr; // com error status
  426. METADATA_HANDLE hMeta = NULL; // handle to metabase
  427. CComPtr<IMSAdminBase> pIMeta; // ATL smart ptr
  428. DWORD dwMDRequiredDataLen;
  429. METADATA_RECORD mr;
  430. HANDLE hToken = NULL;
  431. LPTSTR lpszDir = NULL;
  432. TCHAR szBuf[MAX_CAB_BUFFER];
  433. // Need to revert to our service credential to be able to read IIS Metabase.
  434. hToken = RevertToPrinterSelf();
  435. // Create a instance of the metabase object
  436. hr=::CoCreateInstance(CLSID_MSAdminBase,
  437. NULL,
  438. CLSCTX_ALL,
  439. IID_IMSAdminBase,
  440. (void **)&pIMeta);
  441. if( SUCCEEDED( hr )) {
  442. // open key to ROOT on website #1 (default)
  443. hr = pIMeta->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  444. g_szMetabasePath,
  445. METADATA_PERMISSION_READ,
  446. CAB_TIMEOUT,
  447. &hMeta);
  448. if( SUCCEEDED( hr )) {
  449. mr.dwMDIdentifier = MD_VR_PATH;
  450. mr.dwMDAttributes = 0;
  451. mr.dwMDUserType = IIS_MD_UT_FILE;
  452. mr.dwMDDataType = STRING_METADATA;
  453. mr.dwMDDataLen = sizeof(szBuf);
  454. mr.pbMDData = reinterpret_cast<unsigned char *>(szBuf);
  455. hr = pIMeta->GetData( hMeta, L"", &mr, &dwMDRequiredDataLen );
  456. pIMeta->CloseKey( hMeta );
  457. if( SUCCEEDED( hr ))
  458. {
  459. lpszDir = genBuildFileName(szBuf, g_szPrtCabs, NULL);
  460. }
  461. }
  462. }
  463. if (hToken)
  464. {
  465. ImpersonatePrinterClient(hToken);
  466. }
  467. return lpszDir;
  468. }
  469. /*****************************************************************************\
  470. * cab_get_dstpath
  471. *
  472. * Returns a directory string where the cabinet files are to be generated.
  473. *
  474. \*****************************************************************************/
  475. LPTSTR cab_get_dstpath(VOID)
  476. {
  477. HANDLE hDir;
  478. LPTSTR lpszDir;
  479. // First, we need to find the virtual-directory-root the cab files
  480. // are located.
  481. //
  482. if (lpszDir = cab_get_webdir()) {
  483. // Make sure the directory exists, or we can create it.
  484. //
  485. hDir = gen_OpenDirectory(lpszDir);
  486. if (hDir && (hDir != INVALID_HANDLE_VALUE)) {
  487. CloseHandle(hDir);
  488. } else {
  489. if (CreateDirectory(lpszDir, NULL) == FALSE) {
  490. genGFree(lpszDir, genGSize(lpszDir));
  491. lpszDir = NULL;
  492. }
  493. }
  494. }
  495. return lpszDir;
  496. }
  497. /*****************************************************************************\
  498. * GenerateCAB
  499. *
  500. * Main entry-point for generating the CAB file.
  501. *
  502. * Parameters
  503. * ----------
  504. * lpszFriendlyName - Name of printer (shared-name).
  505. * lpszPortName - Name of output port.
  506. * dwCliInfo - Client platform/architecture/version information.
  507. * lpszOutName - This is returned to the caller specifying the output.
  508. *
  509. \*****************************************************************************/
  510. DWORD GenerateCAB(
  511. LPCTSTR lpszFriendlyName,
  512. LPCTSTR lpszPortName,
  513. DWORD dwCliInfo,
  514. LPTSTR lpszOutName,
  515. BOOL bSecure)
  516. {
  517. INFGENPARM infParm;
  518. HANDLE hToken;
  519. HANDLE hsed;
  520. HANDLE hinf;
  521. FILETIME ftSED;
  522. FILETIME ftCAB;
  523. DWORD idxVer;
  524. DWORD idxPlt;
  525. BOOL bSed;
  526. BOOL bCab;
  527. LPTSTR lpszFullName;
  528. LPTSTR lpszDrvName = NULL;
  529. LPTSTR lpszShrName = NULL;
  530. LPTSTR lpszDstName = NULL;
  531. LPTSTR lpszDstPath = NULL;
  532. LPTSTR lpszFrnName = NULL;
  533. LPCTSTR lpszSedFile;
  534. DWORD dwRet = HSE_STATUS_ERROR;
  535. DWORD dwFailure = ERROR_SUCCESS;
  536. // Initialize the security-token so that we will have
  537. // max-privileges during the file-creation.
  538. //
  539. if ((hToken = cab_SetClientSecurity()) == NULL) {
  540. DBGMSG(DBG_ERROR, ("GenerateCab : Access Denied"));
  541. goto RetCabDone;
  542. }
  543. // Get the platform and version of the client (map to an index
  544. // into tables). Validate the indexes to assure the information
  545. // is valid.
  546. //
  547. idxPlt = genIdxCliPlatform(dwCliInfo);
  548. idxVer = genIdxCliVersion(dwCliInfo);
  549. #ifdef WIN95TST
  550. // WORK : ChrisWil
  551. if (idxPlt == IDX_W9X) {
  552. lstrcpy(lpszOutName, TEXT("/hplaserj/cab_w9x0.webpnp"));
  553. return HSE_STATUS_SUCCESS;
  554. }
  555. #endif
  556. if ((idxPlt == IDX_UNKNOWN) || (idxVer == IDX_UNKNOWN)) {
  557. dwFailure = ERROR_BAD_ENVIRONMENT;
  558. DBGMSG(DBG_ERROR, ("GenerateCab : Unsupported client architecture/version"));
  559. goto RetCabDone;
  560. }
  561. // Get the directory where the cab-files will be placed.
  562. //
  563. if ((lpszDstPath = cab_get_dstpath()) == NULL)
  564. goto RetCabDone;
  565. // Build a cluster-capable friendly-name.
  566. //
  567. if ((lpszFrnName = genFrnName(lpszFriendlyName)) == NULL)
  568. goto RetCabDone;
  569. // Get the driver information about the friendly-name.
  570. //
  571. if (cab_get_drvname(lpszFrnName, &lpszDrvName, &lpszShrName, idxPlt) == FALSE)
  572. goto RetCabDone;
  573. // Get the destination-name.
  574. //
  575. if ((lpszDstName = cab_get_dstname(idxPlt, idxVer, lpszShrName)) == NULL)
  576. goto RetCabDone;
  577. // Fill in the inf-input-parameters. These values should be
  578. // validated at this point.
  579. //
  580. infParm.lpszFriendlyName = lpszFrnName;
  581. infParm.lpszShareName = lpszShrName;
  582. infParm.lpszPortName = lpszPortName;
  583. infParm.idxPlt = idxPlt;
  584. infParm.idxVer = idxVer;
  585. infParm.dwCliInfo = dwCliInfo;
  586. infParm.lpszDrvName = lpszDrvName;
  587. infParm.lpszDstName = lpszDstName;
  588. infParm.lpszDstPath = lpszDstPath;
  589. // Grab the critical-section while we deal with generating
  590. // the files for the driver-install.
  591. //
  592. EnterCABCrit();
  593. // Call to have the INF/CDF files generated. If
  594. // all goes well, then the SED file can be generated
  595. // using the INF as input.
  596. //
  597. if (hinf = infCreate(&infParm)) {
  598. // We created an INF object. Now process the INF
  599. if ( infProcess(hinf) ) {
  600. // Got good INF so now work on CDF
  601. if (hsed = cdfCreate(hinf, bSecure)) {
  602. // We created a CDF object. Now process the CDF
  603. if ( cdfProcess(hsed) ) {
  604. // Allocate a string representing the full-path-name of
  605. // the generated executable.
  606. //
  607. lpszFullName = genBuildFileName(lpszDstPath, lpszDstName, g_szDotIpp);
  608. if (lpszFullName) {
  609. // Get the name of the directive file that we'll be using
  610. // to lauch the iexpress-package with. Do not delete this
  611. // pointer as it is handled by the SED object.
  612. //
  613. if (lpszSedFile = cdfGetName(hsed)) {
  614. // Retrieve modified dates so that we can determine whether
  615. // to generate a new-CAB or return an existing one. If the
  616. // calls return FALSE, the we can assume a file doesn't
  617. // exist, so we'll generate an new one anyway.
  618. //
  619. bSed = cdfGetModTime(hsed, &ftSED);
  620. bCab = cab_get_modtime(lpszFullName, &ftCAB);
  621. // Get the name of the Cab-File that will be
  622. // generated (or returned). This is relative to the
  623. // wwwroot path and is in the form /share/printer.
  624. //
  625. cab_get_name(lpszDstName, lpszShrName, lpszOutName);
  626. // If the bCabMod is TRUE (meaning we have a CAB), and the
  627. // SED is not newer than the CAB, then we really only need
  628. // to return the existing CAB. Otherwise, some files
  629. // must have changed.
  630. //
  631. if ((bSed && bCab) && (CompareFileTime(&ftSED, &ftCAB) <= 0)) {
  632. goto RetCabName;
  633. } else {
  634. if (cab_iexpress_exec(lpszDstPath, lpszDstName, lpszSedFile)) {
  635. RetCabName:
  636. dwRet = HSE_STATUS_SUCCESS;
  637. }
  638. else
  639. dwFailure = ERROR_CANNOT_MAKE;
  640. }
  641. }
  642. else // If cdfGetName
  643. dwFailure = GetLastError();
  644. genGFree(lpszFullName, genGSize(lpszFullName));
  645. }
  646. else // If lpszFullName
  647. dwFailure = GetLastError();
  648. }
  649. else // If cdfProcess()
  650. dwFailure = cdfGetError(hsed); // Get saved error
  651. cdfCleanUpSourceFiles(hinf); // Even if cdfProcess fails it might have
  652. // partialy generated some temporary files
  653. cdfDestroy(hsed);
  654. }
  655. else // If cdfCreate
  656. dwFailure = GetLastError();
  657. }
  658. else // If infProcess()
  659. dwFailure = infGetError(hinf); // Get saved error
  660. infDestroy(hinf);
  661. }
  662. else // If infCreate
  663. dwFailure = GetLastError();
  664. // Cleanup the files generated during processing.
  665. //
  666. cab_cleanup_files(lpszDstPath);
  667. RetCabDone:
  668. // If something failed but we don't know what yet.. Get the error
  669. if ( (dwRet == HSE_STATUS_ERROR) && ( dwFailure == ERROR_SUCCESS ) )
  670. dwFailure = GetLastError();
  671. // Free our strings allocated through this scope.
  672. //
  673. if (lpszFrnName)
  674. genGFree(lpszFrnName, genGSize(lpszFrnName));
  675. if (lpszDrvName)
  676. genGFree(lpszDrvName, genGSize(lpszDrvName));
  677. if (lpszDstName)
  678. genGFree(lpszDstName, genGSize(lpszDstName));
  679. if (lpszShrName)
  680. genGFree(lpszShrName, genGSize(lpszShrName));
  681. if (lpszDstPath)
  682. genGFree(lpszDstPath, genGSize(lpszDstPath));
  683. if (hToken)
  684. cab_ResetClientSecurity(hToken);
  685. LeaveCABCrit();
  686. if (dwFailure != ERROR_SUCCESS)
  687. SetLastError(dwFailure);
  688. return dwRet;
  689. }