|
|
/*****************************************************************************\
* MODULE: gencdf.c * * The module contains routines for generating a CDF (Cabinet Directive File) * for the IExpress utility. * * Work Items: * ---------- * 1) Redo item-allocations to use single block-heap and append information * to reduce heap-overhead. * * * Copyright (C) 1996-1997 Microsoft Corporation * Copyright (C) 1996-1997 Hewlett Packard * * History: * 22-Nov-1996 HWP-Guys Created. * \*****************************************************************************/
#include "pch.h"
/*****************************************************************************\
* cdf_NextStr (Local Routine) * * Proceeds to the next string in a section-list. * \*****************************************************************************/ _inline LPTSTR cdf_NextStr( LPTSTR lpszStr) { return (lpszStr + (lstrlen(lpszStr) + 1)); }
/******************************************************************************\
* * GetDirectory (Local Routine) * * Returns the directory portion of a full pathname. * \******************************************************************************/ LPTSTR cdf_GetDirectoryWithSlash(LPTSTR lpszFile) {
LPTSTR lpszSlash; LPTSTR lpszDir;
lpszSlash = genFindRChar(lpszFile, TEXT('\\'));
if (lpszSlash != NULL) {
if (NULL != (lpszDir = (LPTSTR)genGAlloc((UINT32) (lpszSlash - lpszFile + 2) * sizeof(TCHAR)))) {
StringCchCopy(lpszDir, (UINT32) (lpszSlash - lpszFile + 2), lpszFile); return lpszDir; } }
return NULL; }
/******************************************************************************\
* * cdf_GetName (Local Routine) * * Returns the filename portion of a full pathname. * \******************************************************************************/ LPTSTR cdf_GetName(LPTSTR lpszFile) {
LPTSTR lpszSlash; LPTSTR lpszName; int nLength;
lpszSlash = genFindRChar(lpszFile, TEXT('\\'));
if (lpszSlash != NULL) {
nLength = lstrlen(lpszSlash);
if (NULL != (lpszName = (LPTSTR)genGAlloc((nLength * sizeof(TCHAR))))) {
StringCchCopy(lpszName, nLength, ++lpszSlash); return lpszName; } } return NULL; }
/*****************************************************************************\
* cdf_SFLAdd (Local Routine) * * Adds a new section to our linked-list of sections. This adds it to the * head of the list and returns a pointer to the new item (head). * \*****************************************************************************/ LPSRCFILES cdf_SFLAdd( LPSRCFILES psfList, LPCTSTR lpszPath) { LPSRCFILES psfItem;
if (psfItem = (LPSRCFILES)genGAlloc(sizeof(SRCFILES))) {
if (psfItem->lpszPath = genGAllocStr(lpszPath)) {
// Allocate the files-list buffer.
//
if (psfItem->lpszFiles = (LPTSTR)genGAlloc(CDF_SRCFILE_BLOCK)) {
// Position our item at the head.
//
psfItem->cbMax = CDF_SRCFILE_BLOCK; psfItem->cbSize = 0; psfItem->pNext = psfList;
// Make sure our file beginning is zeroed.
//
*(psfItem->lpszFiles) = TEXT('\0');
return psfItem; }
genGFree(psfItem->lpszPath, genGSize(psfItem->lpszPath)); }
genGFree(psfItem, sizeof(SRCFILES)); }
DBGMSG(DBG_ERROR, ("cdf_SFLAdd : Out of memory"));
return NULL; }
/*****************************************************************************\
* cdf_SFLAddFile (Local Routine) * * Adds a file-item to the specified section-pointer. * \*****************************************************************************/ BOOL cdf_SFLAddFile( LPSRCFILES psfList, LPCTSTR lpszFile) { LPTSTR lpszList; LPTSTR lpszPtr; LPTSTR lpszNew; DWORD cbSize; DWORD cbOldSize; DWORD cbNewSize; HRESULT hr;
// Determine if adding this file exceeds our current maximum
// buffer. If so, then realloc a bigger chunk. We are adding
// two extra characters to account for the '%' which are to
// be added to the lpszFile.
//
cbSize = (lstrlen(lpszFile) + 1 + 2) * sizeof(TCHAR);
if ((psfList->cbSize + cbSize) >= psfList->cbMax) {
cbOldSize = genGSize(psfList->lpszFiles); cbNewSize = cbOldSize + CDF_SRCFILE_BLOCK;
lpszNew = (LPTSTR)genGRealloc(psfList->lpszFiles, cbOldSize, cbNewSize);
if (lpszNew == NULL) {
DBGMSG(DBG_ERROR, ("cdf_SFLAddFile : Out of memory"));
return FALSE; }
// Set new limit criteria.
//
psfList->lpszFiles = lpszNew; psfList->cbMax = cbNewSize; }
// We are appending the file to the end of the list.
//
lpszPtr = (LPTSTR)(((LPBYTE)psfList->lpszFiles) + psfList->cbSize);
if (SUCCEEDED(hr = StringCbPrintf(lpszPtr, cbSize, TEXT("%%%s%%\0"), lpszFile))) { psfList->cbSize += cbSize; }
return SUCCEEDED(hr); }
/*****************************************************************************\
* cdf_SFLFind (Local Routine) * * Looks for the existence of a section-name. * \*****************************************************************************/ LPSRCFILES cdf_SFLFind( LPSRCFILES psfList, LPCTSTR lpszPath) { while (psfList) {
if (lstrcmpi(psfList->lpszPath, lpszPath) == 0) return psfList;
psfList = psfList->pNext; }
return NULL; }
/*****************************************************************************\
* cdf_SFLFree (Local Routine) * * Frees up memory associated with the source-file-list. * \*****************************************************************************/ BOOL cdf_SFLFree( LPSRCFILES psfList) { LPSRCFILES psfItem;
while (psfList) {
genGFree(psfList->lpszFiles, genGSize(psfList->lpszFiles)); genGFree(psfList->lpszPath , genGSize(psfList->lpszPath));
psfItem = psfList; psfList = psfList->pNext;
genGFree(psfItem, genGSize(psfItem)); }
return TRUE; }
/*****************************************************************************\
* cdf_WriteStrings * * Outputs a string to the [Strings] section. * \*****************************************************************************/ _inline BOOL cdf_WriteStrings( LPCTSTR lpszCdfFile, LPCTSTR lpszKey, LPCTSTR lpszStr) { return WritePrivateProfileString(g_szStrings, lpszKey, lpszStr, lpszCdfFile); }
/*****************************************************************************\
* itm_InitList (Local Routine) * * Initializes the file-item-list. * \*****************************************************************************/ _inline VOID itm_InitList( PCDFINFO pCdfInfo) { pCdfInfo->pTop = NULL; }
/*****************************************************************************\
* itm_GetFirst (Local Routine) * * Returns the first PMYITEM in the list * \*****************************************************************************/ _inline PFILEITEM itm_GetFirst( PCDFINFO pCdfInfo) { return pCdfInfo->pTop; }
/*****************************************************************************\
* itm_GetNext (Local Routine) * * Given the current item, returns the next item in the list. * \*****************************************************************************/ _inline PFILEITEM itm_GetNext( PFILEITEM pMyItem) { SPLASSERT((pMyItem != NULL));
return pMyItem->pNext; }
/*****************************************************************************\
* itm_GetString (Local Routine) * * Returns a string associated with an item. You pick the * string by passing the number of the string. * \*****************************************************************************/ _inline LPTSTR itm_GetString( PFILEITEM pMyItem, UINT nItem) { SPLASSERT((pMyItem != NULL)); SPLASSERT((nItem <= FI_COL_LAST));
return pMyItem->aszCols[nItem]; }
/*****************************************************************************\
* itm_FullPath (Local Routine) * * Return a fully-qualified pathname for the item. * \*****************************************************************************/ _inline LPTSTR itm_FullPath( PFILEITEM pItem) { LPTSTR lpszPath; LPTSTR lpszFile;
// Gather the strings and build the name.
//
lpszPath = itm_GetString(pItem, FI_COL_PATH); lpszFile = itm_GetString(pItem, FI_COL_FILENAME);
return genBuildFileName(NULL, lpszPath, lpszFile); }
/*****************************************************************************\
* itm_GetTime (Local Routine) * * Returns a time associated with an item. * \*****************************************************************************/ _inline FILETIME itm_GetTime( PFILEITEM pMyItem) { SPLASSERT((pMyItem != NULL));
return pMyItem->ftLastModify; }
/*****************************************************************************\
* itm_SetTime (Local Routine) * * Sets the last modified time of the item. * \*****************************************************************************/ VOID itm_SetTime( PFILEITEM pMyItem, FILETIME ftLastModify) { SPLASSERT((pMyItem != NULL));
pMyItem->ftLastModify = ftLastModify; }
/*****************************************************************************\
* itm_Last (Local Routine) * * Used to end a while loop when we've reached the end of list * \*****************************************************************************/ _inline BOOL itm_Last( PFILEITEM pMyItem) { return (pMyItem == NULL); }
/*****************************************************************************\
* itm_Free (Local Routine) * * Frees the memory associated with an item. * \*****************************************************************************/ VOID itm_Free( PFILEITEM pItem) { LPTSTR lpszStr;
if (lpszStr = itm_GetString(pItem, FI_COL_FILENAME)) genGFree(lpszStr, genGSize(lpszStr));
if (lpszStr = itm_GetString(pItem, FI_COL_PATH)) genGFree(lpszStr, genGSize(lpszStr));
genGFree(pItem, sizeof(FILEITEM)); }
/*****************************************************************************\
* itm_DeleteAll (Local Routine) * * Deletes all the items from our file list. * \*****************************************************************************/ VOID itm_DeleteAll( PCDFINFO pCdfInfo) { PFILEITEM pMyItem; PFILEITEM pTempItem;
pMyItem = itm_GetFirst(pCdfInfo);
while (itm_Last(pMyItem) == FALSE) {
pTempItem = pMyItem; pMyItem = itm_GetNext(pMyItem);
itm_Free(pTempItem); }
itm_InitList(pCdfInfo); }
/*****************************************************************************\
* itm_Add (Local Routine) * * Adds an item to the list. * \*****************************************************************************/ PFILEITEM itm_Add( LPCTSTR lpszFilename, LPCTSTR lpszPath, PCDFINFO pCdfInfo) { PFILEITEM pMyItem;
SPLASSERT((lpszFilename != NULL)); SPLASSERT((lpszPath != NULL));
if (pMyItem = (PFILEITEM)genGAlloc(sizeof(FILEITEM))) {
// Allocate the strings for the path/filename.
//
if (pMyItem->aszCols[FI_COL_FILENAME] = genGAllocStr(lpszFilename)) {
if (pMyItem->aszCols[FI_COL_PATH] = genGAllocStr(lpszPath)) {
pMyItem->pNext = pCdfInfo->pTop; pCdfInfo->pTop = pMyItem;
return pMyItem; }
genGFree(pMyItem->aszCols[FI_COL_FILENAME], genGSize(pMyItem->aszCols[FI_COL_FILENAME])); }
genGFree(pMyItem, sizeof(FILEITEM)); }
return NULL; }
/*****************************************************************************\
* itm_Find (Local Routine) * * To see if file is already in list * \*****************************************************************************/ PFILEITEM itm_Find( LPCTSTR lpszFindFile, PCDFINFO pCdfInfo, BOOL bMatchFullPath) { PFILEITEM pItem = itm_GetFirst(pCdfInfo); LPTSTR lpszItmFile; BOOL bRet = FALSE;
// Loop through our list of items looking for a file
// match.
//
while (pItem) {
// Build the file-name from the stored-strings.
//
if (bMatchFullPath) lpszItmFile = itm_FullPath(pItem); else lpszItmFile = itm_GetString(pItem, FI_COL_FILENAME);
if (lpszItmFile) {
// Check for match.
//
if (lstrcmpi(lpszFindFile, lpszItmFile) == 0) {
// Found.
//
if (bMatchFullPath) genGFree(lpszItmFile, genGSize(lpszItmFile));
return pItem; }
if (bMatchFullPath) genGFree(lpszItmFile, genGSize(lpszItmFile));
} else {
return NULL; }
pItem = itm_GetNext(pItem); }
return NULL; }
/*****************************************************************************\
* cdf_WriteTimeStamps * * Outputs a struct to the [TimeStamps] section. * \*****************************************************************************/ _inline BOOL cdf_WriteTimeStamps( LPCTSTR lpszCdfFile, LPCTSTR lpszKey, LPFILEITEM pFileItem) { FILETIME ft = itm_GetTime(pFileItem);
return WritePrivateProfileStruct(g_szTimeStamps, lpszKey, &ft, sizeof(FILETIME), lpszCdfFile); }
/*****************************************************************************\
* cdf_WriteSourceFiles * * Outputs a struct to the [SourceFiles] section. * \*****************************************************************************/ _inline BOOL cdf_WriteSourceFiles( LPCTSTR lpszCdfFile, LPCTSTR lpszKey, LPCTSTR lpszStr) { return WritePrivateProfileString(g_szSourceFiles, lpszKey, lpszStr, lpszCdfFile); }
/*****************************************************************************\
* cdf_GetSection (Local Routine) * * Allocate a buffer which stores either all section-names or the list of * items specified by (lpszSection) in an INF file. Currently, we attempt * a realloc if the buffer is not big enough. * * NOTE: should we provide a limit for the amount of allocations before * we accept failure? * * 09-Dec-1996 : ChrisWil * \*****************************************************************************/ LPTSTR cdf_GetSection( LPCTSTR lpszSct, BOOL bString, LPCTSTR lpszCdfFile) { DWORD dwCnt; DWORD cch; DWORD dwSize; DWORD dwLimit; LPTSTR lpszNames = NULL;
dwSize = 0; dwLimit = 0;
while (dwLimit < CDF_SECTION_LIMIT) {
// We'll start this allocation with an assumed max-size. Upon
// successive tries, this buffer is increased each time by the
// original buffer allocation.
//
dwSize += (CDF_SECTION_BLOCK * sizeof(TCHAR)); dwLimit++;
// Alloc the buffer and attempt to get the names.
//
if (lpszNames = (LPTSTR)genGAlloc(dwSize)) {
// If a section-name is profided, use that. Otherwise,
// enumerate all section-names.
//
cch = dwSize / sizeof(TCHAR);
if (bString) {
dwCnt = GetPrivateProfileString(lpszSct, NULL, g_szEmptyStr, lpszNames, cch, lpszCdfFile);
} else {
dwCnt = GetPrivateProfileSection(lpszSct, lpszNames, cch, lpszCdfFile); }
// If the call says the buffer was OK, then we can
// assume the names are retrieved. According to spec's,
// if the return-count is equal to size-2, then buffer
// isn't quite big-enough (two NULL chars).
//
if (dwCnt < (cch - 2)) goto GetSectDone;
genGFree(lpszNames, dwSize); lpszNames = NULL; } }
GetSectDone:
SPLASSERT((dwLimit < CDF_SECTION_LIMIT));
return lpszNames; }
/*****************************************************************************\
* cdf_GetValue (Local Routine) * * \*****************************************************************************/ LPTSTR cdf_GetValue( LPCTSTR lpszSection, LPCTSTR lpszKey, LPCTSTR lpszCdfFile) { TCHAR szBuffer[STD_CDF_BUFFER]; DWORD cch; LPTSTR lpszVal = NULL;
cch = GetPrivateProfileString(lpszSection, lpszKey, g_szEmptyStr, szBuffer, COUNTOF(szBuffer), lpszCdfFile);
SPLASSERT((cch < STD_CDF_BUFFER));
return (cch ? genGAllocStr(szBuffer) : NULL); }
/*****************************************************************************\
* cdf_GetCdfFile (Local Routine) * * Returns an allocated string to the CDF file (Full-Path) * \*****************************************************************************/ LPTSTR cdf_GetCdfFile( PCDFINFO pCdfInfo) { LPCTSTR lpszDstPath; LPCTSTR lpszDstName;
// Retrieve the strings representing the destination path and name
// of the output file. These strings have already been validated
// by the INF object.
//
lpszDstPath = infGetDstPath(pCdfInfo->hInf); lpszDstName = infGetDstName(pCdfInfo->hInf);
return genBuildFileName(lpszDstPath, lpszDstName, g_szDotSed); }
/*****************************************************************************\
* cdf_GetUncName (Local Routine) * * Returns an allocated string to the unc-name. * \*****************************************************************************/ LPTSTR cdf_GetUncName( PCDFINFO pCdfInfo) { DWORD cchSize; LPCTSTR lpszShrName; LPTSTR lpszUncName = NULL;
static CONST TCHAR s_szFmt[] = TEXT("\\\\%s\\%s");
if (lpszShrName = infGetShareName(pCdfInfo->hInf)) {
cchSize= lstrlen(g_szPrintServerName) + lstrlen(lpszShrName) + lstrlen(s_szFmt) + 1;
if (lpszUncName = (LPTSTR)genGAlloc((cchSize * sizeof(TCHAR)))) { if (FAILED(StringCchPrintf(lpszUncName, cchSize, s_szFmt, g_szPrintServerName, lpszShrName))) { genGFree(lpszUncName, genGSize(lpszUncName)); lpszUncName = NULL; } } }
return lpszUncName; }
/*****************************************************************************\
* cdf_BuildFriendlyName (Local Routine) * * Builds a \\machinename\friendly type string so that the client can * refer to the printer as "friendly on machinename". * \*****************************************************************************/ LPTSTR cdf_BuildFriendlyName( PCDFINFO pCdfInfo) { DWORD cchSize; LPCTSTR lpszFrnName; LPTSTR lpszPtr; LPTSTR lpszFmt; LPTSTR lpszName = NULL;
static TCHAR s_szFmt0[] = TEXT("\\\\http://%s\\%s"); static TCHAR s_szFmt1[] = TEXT("\\\\https://%s\\%s");
if (lpszFrnName = infGetFriendlyName(pCdfInfo->hInf)) {
if (lpszPtr = genFindChar((LPTSTR)lpszFrnName, TEXT('\\'))) {
lpszPtr++; lpszPtr++;
if (lpszPtr = genFindChar(lpszPtr, TEXT('\\'))) {
// Check if this is a secure request.
//
lpszFmt = (pCdfInfo->bSecure ? s_szFmt1 : s_szFmt0);
// This is the friendly name, not the port name, so we don't
// call GetWebpnpUrl to encode it.
//
cchSize= lstrlen(g_szHttpServerName) + lstrlen(++lpszPtr) + lstrlen(lpszFmt) + 1;
if (lpszName = (LPTSTR)genGAlloc(cchSize * sizeof(TCHAR))) { if (FAILED(StringCchPrintf(lpszName, cchSize, lpszFmt, g_szHttpServerName, lpszPtr))) { genGFree(lpszName, genGSize(lpszName)); lpszName = NULL; } } } } }
return lpszName; }
/*****************************************************************************\
* cdf_ReadFiles (Local Routine) * * Reads in the files under the specified src-path-key. * \*****************************************************************************/ BOOL cdf_ReadFiles( LPCTSTR lpszSrcPathKey, LPCTSTR lpszSrcFiles, PCDFINFO pCdfInfo) { FILETIME ftFileTime; PFILEITEM pFileItem; LPTSTR lpszPath; LPTSTR lpszFiles; LPTSTR lpszFile; LPTSTR lpszStr; BOOL bRet = FALSE;
// For the specified SrcKeyPath, read in the list of files
// associated with the path.
//
lpszFiles = cdf_GetSection(lpszSrcPathKey, FALSE, pCdfInfo->lpszCdfFile);
if (lpszFiles) {
// Get the path-value associated with the SrcPathKey.
//
if (lpszPath = cdf_GetValue(lpszSrcFiles, lpszSrcPathKey, pCdfInfo->lpszCdfFile)) {
lpszFile = lpszFiles;
while (*lpszFile) {
// If the first-character doesn't specify a string-type
// then we can add it directly. Otherwise, we're going
// to have to get the file referenced by the string.
//
if (lpszFile[0] != TEXT('%')) {
// Store the path and filename in the list.
//
pFileItem = itm_Add(lpszFile, lpszPath, pCdfInfo); //
// Fail if we have run out of memory
//
if (!pFileItem) { goto ReadFileError; }
// Read in file timestamp from .cdf.
//
if (GetPrivateProfileStruct(g_szTimeStamps, lpszFile, &ftFileTime, sizeof(FILETIME), pCdfInfo->lpszCdfFile)) { // Store the timestamp.
//
itm_SetTime(pFileItem, ftFileTime);
lpszFile = cdf_NextStr(lpszFile);
} else {
goto ReadFileError; }
} else {
// Handle %filename% names (localizable strings)
// If the filename is delimited by two percent (%)
// signs,it is not a literal, but needs to be
// looked up [Strings] section of the .cdf file.
//
// Replace the % on the end of the string
// with a null char, then move past the end-char.
//
lpszFile[lstrlen(lpszFile) - 1] = TEXT('\0'); lpszFile++;
lpszStr = cdf_GetValue(g_szStrings, lpszFile, pCdfInfo->lpszCdfFile);
if (lpszStr) {
pFileItem = itm_Add(lpszStr, lpszPath, pCdfInfo); //
// Fail if we have run out of memory
//
if (!pFileItem) { genGFree(lpszStr, genGSize(lpszStr)); goto ReadFileError; }
// Read in file timestamp from .cdf
//
GetPrivateProfileStruct(g_szTimeStamps, lpszFile, &ftFileTime, sizeof(FILETIME), pCdfInfo->lpszCdfFile);
genGFree(lpszStr, genGSize(lpszStr));
itm_SetTime(pFileItem, ftFileTime);
// We add 2 + len of string, because we put in an
// extra null to replace the % char
//
lpszFile = cdf_NextStr(lpszFile) + 1;
} else {
goto ReadFileError; } } }
bRet = TRUE;
ReadFileError:
genGFree(lpszPath, genGSize(lpszPath)); }
genGFree(lpszFiles, genGSize(lpszFiles)); }
return bRet; }
/*****************************************************************************\
* cdf_ReadFileList (Local Routine) * * Reads in the file-list from the CDF-File. * \*****************************************************************************/ BOOL cdf_ReadFileList( PCDFINFO pCdfInfo) { LPTSTR lpszSrcFiles; LPTSTR lpszSrcPaths; LPTSTR lpszPathKey; BOOL bRet = FALSE;
// Initialize the head of the list.
//
itm_InitList(pCdfInfo);
// Get source files section of .cdf file
//
lpszSrcFiles = cdf_GetValue(g_szOptions, g_szSourceFiles, pCdfInfo->lpszCdfFile);
if (lpszSrcFiles) {
// Read in the entire SourceFiles section (as a list of keys).
//
lpszSrcPaths = cdf_GetSection(lpszSrcFiles, TRUE, pCdfInfo->lpszCdfFile);
if (lpszPathKey = lpszSrcPaths) {
// Each section name has a path associated with it.
// For each section name, read in and add all the
// files to the list
//
while (*lpszPathKey) {
if (cdf_ReadFiles(lpszPathKey, lpszSrcFiles, pCdfInfo) == FALSE) goto ReadListExit;
lpszPathKey = cdf_NextStr(lpszPathKey); }
bRet = TRUE;
ReadListExit:
genGFree(lpszSrcPaths, genGSize(lpszSrcPaths)); }
genGFree(lpszSrcFiles, genGSize(lpszSrcFiles)); }
return bRet; }
/*****************************************************************************\
* cdf_AddCATFile (Local Routine) * * This is called by cdf_GetFileList for each file being added to the cdf. * It uses the Catalog File Admin APIs to determine if the driver file was installed * with an associated catalog file. If a corresponding catalog file (or files) * is found, the catalog filename (or filenames), along with its timestamp, * is added to the cdf file list. * \*****************************************************************************/ BOOL cdf_AddCATFile(LPTSTR lpszFile, LPCDFINFO pCdfInfo ) {
HCATADMIN hCatAdmin = pCdfInfo->hCatAdmin; HCATINFO hCatInfo = NULL; CATALOG_INFO CatInfo; BYTE * pbHash; DWORD dwBytes; WIN32_FIND_DATA ffd; PFILEITEM pFileItem; HANDLE hFind, hFile; LPTSTR pFullPath, pPath, pName;
// Find the catalog file associated with this file.
// If we can't find one, that's OK, it's not an error, just a file
// with no associated .cat file. The user can decide on the client-end
// whether or not he wants to install without the verification a .cat file
// would provide...
//
if (INVALID_HANDLE_VALUE != (HANDLE)hCatAdmin) {
hFind = FindFirstFile(lpszFile, &ffd);
if (hFind && (hFind != INVALID_HANDLE_VALUE)) {
FindClose(hFind);
// Open the file in order to hash it.
//
if (INVALID_HANDLE_VALUE != (hFile = CreateFile(lpszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))) {
// Determine how many bytes we need for the hash
//
dwBytes = 0; pbHash = NULL; CryptCATAdminCalcHashFromFileHandle(hFile, &dwBytes, pbHash, 0);
if (NULL != (pbHash = (BYTE *)genGAlloc(dwBytes))) {
// Compute the hash for this file
//
if (CryptCATAdminCalcHashFromFileHandle(hFile, &dwBytes, pbHash, 0)) {
// Get the catalog file(s) associated with this file hash
//
hCatInfo = NULL;
do {
hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, pbHash, dwBytes, 0, &hCatInfo);
if (NULL != hCatInfo) {
// Split the cat name into file and path here
//
if (CryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, NULL)) {
if (NULL != (pFullPath = genTCFromWC(CatInfo.wszCatalogFile))) {
if (NULL != (pPath = cdf_GetDirectoryWithSlash(pFullPath))) {
if (NULL != (pName = cdf_GetName(pFullPath))) {
// Make sure the file is not already in the cdf, so
// IExpress doesn't give out (see BUG: explanation in cdf_GetFileList() )
//
if (NULL == itm_Find(pName, pCdfInfo, FALSE)) { // Add the catalog file and timestamp
pFileItem = itm_Add(pName, pPath, pCdfInfo);
if (pFileItem) { itm_SetTime(pFileItem, ffd.ftLastWriteTime); } }
genGFree(pName, genGSize(pName) ); }
genGFree(pPath, genGSize(pPath) ); }
genGFree(pFullPath, genGSize(pFullPath) ); }
}
}
} while (NULL != hCatInfo);
}
genGFree(pbHash, dwBytes); }
CloseHandle(hFile); } } }
return TRUE; }
/*****************************************************************************\
* cdf_GetFileList (Local Routine) * * This is a callback function passed to infEnumItems() * It reads in the list of files from the INF object, and reads * the filetimes from the disk and adds these to the list also. * \*****************************************************************************/ BOOL CALLBACK cdf_GetFileList( LPCTSTR lpszName, LPCTSTR lpszPath, BOOL bInf, LPVOID lpData) { PCDFINFO pCdfInfo = (PCDFINFO)lpData; HANDLE hFind; PFILEITEM pFileItem; LPTSTR lpszFile; LPTSTR lpszPtr; WIN32_FIND_DATA FindFileData; BOOL bRet = FALSE;
// Build fully qualified file name.
//
if (lpszFile = genBuildFileName(lpszPath, lpszName, NULL)) {
hFind = FindFirstFile(lpszFile, &FindFileData);
if (hFind && (hFind != INVALID_HANDLE_VALUE)) {
FindClose(hFind);
// IExpress fails when it encounters the
// same filename twice. To work-around this,
// we will prevent the inclusion of the second
// file. We will match the name-only.
//
if (itm_Find(lpszName, pCdfInfo, FALSE) == NULL) {
// Add the item to the list of CDF-Files. We
// store the path-name with the trailing '\'
// because the CDF format requires such.
//
lpszPtr = genFindRChar(lpszFile, TEXT('\\'));
// Is filename of right format?
//
if ( lpszPtr != NULL ) {
*(++lpszPtr) = TEXT('\0'); pFileItem = itm_Add(lpszName, lpszFile, pCdfInfo);
// Set the item-time. This should only fail if we couldn't allocate memory
//
if (pFileItem != NULL) { itm_SetTime(pFileItem, FindFileData.ftLastWriteTime); bRet = TRUE; } } else SetLastError(ERROR_INVALID_PARAMETER); } else bRet = TRUE; // Item already exits, so TRUE
}
genGFree(lpszFile, genGSize(lpszFile)); }
return bRet; }
/*****************************************************************************\
* cdf_CheckFiles (Local Routine) * * This is a callback function passed to infEnumItems() * It checks each filename to see if it is in the .cdf list, * and if it is up to date. * \*****************************************************************************/ BOOL CALLBACK cdf_CheckFiles( LPCTSTR lpszName, LPCTSTR lpszPath, BOOL bInfFile, LPVOID lpData) { PCDFINFO pCdfInfo = (PCDFINFO)lpData; HANDLE hFind; PFILEITEM pFileItem; LPTSTR lpszFile; LPTSTR lpszPtr; WIN32_FIND_DATA FindFileData; LONG lCompare; BOOL bRet = FALSE;
// Build fully qualified filename.
//
if (lpszFile = genBuildFileName(lpszPath, lpszName, NULL)) {
// Locate the item, and see if the dates are out-of-sync.
//
if (pFileItem = itm_Find(lpszFile, pCdfInfo, TRUE)) {
hFind = FindFirstFile(lpszFile, &FindFileData);
if (hFind && (hFind != INVALID_HANDLE_VALUE)) {
FindClose(hFind);
// Compare the file-times.
//
lCompare = CompareFileTime(&FindFileData.ftLastWriteTime, &pFileItem->ftLastModify);
// Skip over INF files since we are generating
// these in the INF object.
//
if (bInfFile || (lCompare == 0)) bRet = TRUE; } }
genGFree(lpszFile, genGSize(lpszFile)); }
return bRet; }
/*****************************************************************************\
* cdf_get_datfile * * Returns the then name of the dat-file. The name built incorporates * the sharename to distinguish it from other dat-files in the directory. * any other files. * * <path>\<Share ChkSum>.dat * \*****************************************************************************/ LPTSTR cdf_get_datfile( LPCTSTR lpszDstPath, LPCTSTR lpszShrName) { TCHAR szName[MIN_CDF_BUFFER];
// Build the name using the checksum.
//
StringCchPrintf(szName, COUNTOF(szName), g_szDatName, genChkSum(lpszShrName));
return genBuildFileName(lpszDstPath, szName, g_szDotDat); }
/*****************************************************************************\
* cdf_IsDatCurrent (Local Routine) * * Checks the port-name in the dat-file for match. If they do not, then we * need to return FALSE to proceed with a new cab-generation. * \*****************************************************************************/ BOOL cdf_IsDatCurrent( PCDFINFO pCdfInfo) { LPCTSTR lpszPrtName; LPCTSTR lpszDstPath; LPCTSTR lpszShrName; LPTSTR lpszDatFile; LPTSTR lpszDat; LPTSTR lpszPtr; LPTSTR lpszEnd; DWORD cbSize; DWORD cbRd; HANDLE hFile; BOOL bRet = FALSE;
// Get the information from the INF-object so we can determine the
// age of the dat-file.
//
lpszDstPath = infGetDstPath(pCdfInfo->hInf); lpszPrtName = infGetPrtName(pCdfInfo->hInf); lpszShrName = infGetShareName(pCdfInfo->hInf);
// Build the dat-file-name and open for reading.
//
if (lpszDatFile = cdf_get_datfile(lpszDstPath, lpszShrName)) {
hFile = gen_OpenFileRead(lpszDatFile);
if (hFile && (hFile != INVALID_HANDLE_VALUE)) {
cbSize = GetFileSize(hFile, NULL);
if (lpszDat = (LPTSTR)genGAlloc(cbSize)) {
if (ReadFile(hFile, lpszDat, cbSize, &cbRd, NULL)) {
lpszPtr = lpszDat;
while (lpszPtr = genFindChar(lpszPtr, TEXT('/'))) {
if (*(++lpszPtr) == TEXT('r')) {
lpszPtr++; // space
lpszPtr++; // quote
if (lpszEnd = genFindChar(++lpszPtr, TEXT('\"'))) {
*lpszEnd = TEXT('\0');
if (lstrcmpi(lpszPtr, lpszPrtName) == 0) bRet = TRUE;
*lpszEnd = TEXT('\"'); }
break; }
// Position pointer to the next flag.
//
lpszPtr = genFindChar(lpszPtr, TEXT('\n')); } }
genGFree(lpszDat, cbSize); }
CloseHandle(hFile); }
genGFree(lpszDatFile, genGSize(lpszDatFile)); }
return bRet; }
/*****************************************************************************\
* cdf_IsUpToDate (Local Routine) * * Determines if the CDF is up-to-date, or needs to be regenerated for * this printer * \*****************************************************************************/ BOOL cdf_IsUpToDate( PCDFINFO pCdfInfo) { BOOL bCurrent = FALSE;
if (genUpdIPAddr()) {
if (cdf_IsDatCurrent(pCdfInfo)) {
// Read filelist into CdfInfo structure from .cdf file
//
if (cdf_ReadFileList(pCdfInfo)) {
// Check files in .inf file to see if .cdf is still valid.
//
if (infEnumItems(pCdfInfo->hInf, cdf_CheckFiles, (LPVOID)pCdfInfo)) bCurrent = TRUE; } } }
return bCurrent; }
/*****************************************************************************\
* cdf_EnumICM (Local Routine) * * Callback to enumerate all ICM profiles in the BIN-File. We only need to * add these profiles to our list of CDF-Files that we package up. * \*****************************************************************************/ BOOL CALLBACK cdf_EnumICM( LPCTSTR lpszPath, LPCTSTR lpszFile, LPVOID lpParm) { return cdf_GetFileList(lpszFile, lpszPath, FALSE, lpParm); }
/*****************************************************************************\
* cdf_WriteSourceFilesSection (Local Routine) * * \*****************************************************************************/ BOOL cdf_WriteSourceFilesSection( PCDFINFO pCdfInfo, LPSRCFILES psfList) { TCHAR szSection[STD_CDF_BUFFER]; int idx; BOOL bRet;
for (idx = 0, bRet = TRUE; psfList; psfList = psfList->pNext) {
// Build the section name (i.e. SourceFilesX).
//
bRet = SUCCEEDED(StringCchPrintf(szSection, COUNTOF(szSection), TEXT("%s%i"), g_szSourceFiles, idx++));
// Write the source file section name in the [SourceFiles]
// section.
//
if (bRet) { bRet = cdf_WriteSourceFiles(pCdfInfo->lpszCdfFile, szSection, psfList->lpszPath); }
// Write out the [SourceFilesX] section.
//
if (bRet) {
bRet = WritePrivateProfileSection(szSection, psfList->lpszFiles, pCdfInfo->lpszCdfFile); } }
return bRet; }
/*****************************************************************************\
* cdf_WriteBinFile (Local Routine) * * Writes the .BIN file. * \*****************************************************************************/ BOOL cdf_WriteBinFile( PCDFINFO pCdfInfo, LPCTSTR lpszDstPath, LPCTSTR lpszDstName) { LPCTSTR lpszFriendlyName; LPTSTR lpszBinFile; LPTSTR lpszBinName; HANDLE hPrinter; DWORD dwCliInfo; BOOL bRet = FALSE;
if (lpszBinFile = genBuildFileName(lpszDstPath, lpszDstName, g_szDotBin)) {
if (lpszBinName = genFindRChar(lpszBinFile, TEXT('\\'))) {
// Increment to the next character for the name.
//
lpszBinName++;
// Retrieve the printer-handle and proceed
// to write the information to the BIN-File.
//
if (lpszFriendlyName = infGetFriendlyName(pCdfInfo->hInf)) {
if (OpenPrinter((LPTSTR)lpszFriendlyName, &hPrinter, NULL)) {
dwCliInfo = infGetCliInfo(pCdfInfo->hInf);
// Call the routine to generate the BIN-File.
//
if (webWritePrinterInfo(hPrinter, lpszBinFile)) {
// Add the bin-file to the list of CDF-Files.
// Then add ICM-profiles to our list.
//
if (cdf_GetFileList(lpszBinName, lpszDstPath, FALSE, (LPVOID)pCdfInfo)) {
bRet = webEnumPrinterInfo(hPrinter, dwCliInfo, WEB_ENUM_ICM, (FARPROC)cdf_EnumICM, (LPVOID)pCdfInfo); } }
// Close the printer.
//
ClosePrinter(hPrinter); } } }
genGFree(lpszBinFile, genGSize(lpszBinFile)); }
return bRet; }
/*****************************************************************************\
* cdf_WriteCdfCmd (Local Routine) * * Writes the .DAT file. * \*****************************************************************************/ BOOL cdf_WriteCdfCmd( PCDFINFO pCdfInfo, LPCTSTR lpszUncName, LPCTSTR lpszDstPath, LPCTSTR lpszDstName) { HANDLE hFile; LPWSTR lpszCmd; LPTSTR lpszTmp; LPTSTR lpszBinName; LPTSTR lpszDatFile; LPTSTR lpszDatTmp; LPTSTR lpszFrnName; LPCTSTR lpszDrvName; LPCTSTR lpszPrtName; LPCTSTR lpszInfName; LPCTSTR lpszShrName; DWORD dwWr; DWORD cchSize; BOOL bRet = FALSE;
// Retrive the destination-file info. These strings have
// already been validated by the INF object.
//
lpszDrvName = infGetDrvName(pCdfInfo->hInf); lpszPrtName = infGetPrtName(pCdfInfo->hInf); lpszInfName = infGetInfName(pCdfInfo->hInf); lpszShrName = infGetShareName(pCdfInfo->hInf);
// Build the dat-file.
//
if (lpszDatFile = cdf_get_datfile(lpszDstPath, lpszShrName)) {
// This is a temporary duplicate of the (lpszDatFile) that
// will be written to the cdf-command. This is necessary so
// that the client can have a static-name to use when the
// cab is expanded.
//
if (lpszDatTmp = genBuildFileName(lpszDstPath, g_szDatFile, NULL)) {
if (lpszBinName = genBuildFileName(NULL, lpszDstName, g_szDotBin)) {
if (lpszFrnName = cdf_BuildFriendlyName(pCdfInfo)) {
// Write out the devmode. If the DEVMODE-file (BIN) was
// written correctly, then we will go ahead and generate the
// dat-command-file.
//
if (cdf_WriteBinFile(pCdfInfo, lpszDstPath, lpszDstName)) {
cchSize= lstrlen(lpszFrnName) + lstrlen(lpszInfName) + lstrlen(lpszPrtName) + lstrlen(lpszDrvName) + lstrlen(lpszUncName) + lstrlen(lpszBinName) + lstrlen(g_szDatCmd) + sizeof(WCHAR);
if (lpszTmp = (LPTSTR)genGAlloc(cchSize * sizeof(TCHAR))) {
// Build the Data-command.
//
StringCchPrintf(lpszTmp, cchSize, g_szDatCmd, lpszFrnName, lpszInfName, lpszPrtName, lpszDrvName, lpszUncName, lpszBinName);
// Open the file for writing.
//
hFile = gen_OpenFileWrite(lpszDatFile);
if (hFile && (hFile != INVALID_HANDLE_VALUE)) {
// This is here to assure the file written
// is in byte-format. Otherwise, our strings
// written to the file would be in unicode
// format.
//
if (lpszCmd = genGAllocStr(lpszTmp)) { DWORD cbSize;
cbSize = (DWORD)SIGNATURE_UNICODE; WriteFile(hFile, &cbSize, sizeof(WORD), &dwWr, NULL);
cbSize = genGSize(lpszCmd); WriteFile(hFile, lpszCmd, cbSize, &dwWr, NULL);
genGFree(lpszCmd, genGSize(lpszCmd)); }
CloseHandle(hFile);
// Make a copy of the file to a static name
// that will be used in the cdf/cab file.
//
CopyFile(lpszDatFile, lpszDatTmp, FALSE);
// Add the DAT-File to the list of CDF-Files. Use
// the temporary file so that it is a static name
// as opposed to our check-sum generated file.
//
bRet = cdf_GetFileList(g_szDatFile, lpszDstPath, FALSE, (LPVOID)pCdfInfo); }
genGFree(lpszTmp, genGSize(lpszTmp)); } }
genGFree(lpszFrnName, genGSize(lpszFrnName)); }
genGFree(lpszBinName, genGSize(lpszBinName)); }
genGFree(lpszDatTmp, genGSize(lpszDatTmp)); }
genGFree(lpszDatFile, genGSize(lpszDatFile)); }
return bRet; }
/******************************************************************************
** cdf_GenerateSourceFiles (local routine) ** ** Find cases where the source and installed file names are diferent, copy the ** installed file to the cabs directory and rename it to the original target file ** name. ** *******************************************************************************/ BOOL cdf_GenerateSourceFiles( HANDLE hInf, LPCTSTR lpszDstDir) {
LPINFINFO lpInf = (LPINFINFO)hInf; BOOL bRet = lpInf != NULL;
if (bRet) { DWORD dwItems = lpInf->lpInfItems->dwCount; LPINFITEMINFO lpII = lpInf->lpInfItems;
for (DWORD idx = 0; idx < dwItems && bRet; idx++) { // We check to see if the file exists as advertised, if it does then we don't
// change anything, otherwise, we search the system and windows directories to
// find it, if it exists, we change the path accordingly
LPTSTR lpszSource = lpII->aItems[idx].szSource;
if (*lpszSource) { // There was a source name, we know it is different
// from the target
LPTSTR lpszFile = genBuildFileName( lpII->aItems[idx].szPath, lpII->aItems[idx].szName, NULL); LPTSTR lpszDestFile = genBuildFileName( lpszDstDir, lpszSource, NULL);
if (lpszFile && lpszDestFile) { StringCchCopy( lpII->aItems[idx].szPath, COUNTOF(lpII->aItems[idx].szPath), lpszDstDir); StringCchCopy( lpII->aItems[idx].szName, COUNTOF(lpII->aItems[idx].szName), lpszSource);
bRet = CopyFile( lpszFile, lpszDestFile, FALSE); } else bRet = FALSE;
if (lpszFile) genGFree(lpszFile, genGSize(lpszFile));
if (lpszDestFile) genGFree(lpszDestFile, genGSize(lpszDestFile) ); } } } return bRet; }
/*****************************************************************************\
* cdf_WriteFilesSection (Local Routine) * * Writes the dynamic file information. * \*****************************************************************************/ BOOL cdf_WriteFilesSection( PCDFINFO pCdfInfo) { TCHAR szFileX[MIN_CDF_BUFFER]; LPCTSTR lpszDstName; LPCTSTR lpszDstPath; LPTSTR lpszUncName; LPTSTR lpszTmp; LPTSTR lpszItem; DWORD cchSize; int idx; int idxFile; PFILEITEM pFileItem; LPSRCFILES psfList; LPSRCFILES psfItem; BOOL bRet = FALSE;
static CONST TCHAR s_szFmt0[] = TEXT("\"%s\\%s.webpnp\""); static CONST TCHAR s_szFmt1[] = TEXT("\"%s\"");
if (lpszUncName = cdf_GetUncName(pCdfInfo)) {
// Retreive the necessary strings from the INF object. These
// should already be validated as existing. Otherwise, the creation
// of the INF object would've failed.
//
lpszDstName = infGetDstName(pCdfInfo->hInf); lpszDstPath = infGetDstPath(pCdfInfo->hInf);
// Build the TargetName and write to the CDF.
//
cchSize= lstrlen(lpszDstPath) + lstrlen(lpszDstName) + lstrlen(s_szFmt0) + 1;
if (lpszTmp = (LPTSTR)genGAlloc(cchSize * sizeof(TCHAR))) { StringCchPrintf(lpszTmp, cchSize, s_szFmt0, lpszDstPath, lpszDstName); bRet = cdf_WriteStrings(pCdfInfo->lpszCdfFile, g_szTargetName, lpszTmp); genGFree(lpszTmp, genGSize(lpszTmp)); }
// Now build cdf-install command; Write it to the CDF.
//
cchSize = lstrlen(lpszDstName) + lstrlen(g_szSedCmd) + 1;
if (bRet && (lpszTmp = (LPTSTR)genGAlloc(cchSize * sizeof(TCHAR)))) { StringCchPrintf(lpszTmp, cchSize, g_szSedCmd, lpszDstName); bRet = cdf_WriteStrings(pCdfInfo->lpszCdfFile, g_szAppLaunched, lpszTmp); genGFree(lpszTmp, genGSize(lpszTmp)); }
// Read in all files and filetimes from .inf file (inf object)
// Initialize the list.
//
itm_DeleteAll(pCdfInfo); itm_InitList(pCdfInfo);
// Add all the files enumerated by the inf object.
// Note: This enumeration includes the inf file itself, so
// no need to make a special case for it.
//
if (bRet) bRet = cdf_GenerateSourceFiles( pCdfInfo->hInf, lpszDstPath );
if (bRet) { if (infEnumItems(pCdfInfo->hInf, cdf_GetFileList, (LPVOID)pCdfInfo)) {
// Generate the command-line for the URL rundll interface.
//
bRet = cdf_WriteCdfCmd(pCdfInfo, lpszUncName, lpszDstPath, lpszDstName);
// Initialize the pointers/indexes that are used
// to track our section information.
//
idxFile = 0; pFileItem = itm_GetFirst(pCdfInfo); psfList = NULL;
// If the enumeration succeeded and we have files in the
// list to process, then proceed to build our sections.
//
while (bRet && pFileItem) {
// Build our FILEx string.
//
StringCchPrintf(szFileX, COUNTOF(szFileX), TEXT("FILE%i"), idxFile++);
// Write out the quoted-item.
//
lpszItem = itm_GetString(pFileItem, FI_COL_FILENAME);
cchSize = lstrlen(lpszItem) + lstrlen(s_szFmt1) + 1;
if (lpszTmp = (LPTSTR)genGAlloc(cchSize * sizeof(TCHAR))) { StringCchPrintf(lpszTmp, cchSize, s_szFmt1, lpszItem); bRet = cdf_WriteStrings(pCdfInfo->lpszCdfFile, szFileX, lpszTmp); genGFree(lpszTmp, genGSize(lpszTmp)); }
// Add timestamp to [TimeStamps] section for this file.
//
if (bRet) {
bRet = cdf_WriteTimeStamps(pCdfInfo->lpszCdfFile, szFileX, pFileItem); }
// Look for existence of section (path). If it exists,
// add the file to the section. Otherwise, create a
// new section and add the file.
//
if (bRet) {
lpszItem = itm_GetString(pFileItem, FI_COL_PATH);
if ((psfItem = cdf_SFLFind(psfList, lpszItem)) == NULL) {
if (psfItem = cdf_SFLAdd(psfList, lpszItem)) {
psfList = psfItem;
} else {
bRet = FALSE; } } }
// Add the file to the appropriate section.
//
if (bRet) bRet = cdf_SFLAddFile(psfItem, szFileX);
// Get next file-item.
//
pFileItem = itm_GetNext(pFileItem);
}
// If all went OK in the enumeration, then we can write
// the sections to the CDF file.
//
if (bRet) bRet = cdf_WriteSourceFilesSection(pCdfInfo, psfList);
// Free up the Source-Files-List.
//
cdf_SFLFree(psfList);
} else bRet = FALSE;
} genGFree(lpszUncName, genGSize(lpszUncName)); }
return bRet; }
/*****************************************************************************\
* cdf_WriteVersionSection (Local Routine) * * Writes the [Version] section in the CDF file. * \*****************************************************************************/ BOOL cdf_WriteVersionSection( PCDFINFO pCdfInfo) { UINT uCount; UINT idx; BOOL bRet;
static struct {
LPCTSTR lpszKey; LPCTSTR lpszStr;
} aszVer[] = {
g_szClass , g_szIExpress, g_szSEDVersion, g_szSEDVersionNumber };
// Write out [Version] values.
//
uCount = sizeof(aszVer) / sizeof(aszVer[0]);
for (idx = 0, bRet = TRUE; (idx < uCount) && bRet; idx++) {
bRet = WritePrivateProfileString(g_szVersionSect, aszVer[idx].lpszKey, aszVer[idx].lpszStr, pCdfInfo->lpszCdfFile); }
return bRet; }
/*****************************************************************************\
* cdf_WriteOptionsSection (Local Routine) * * Writess the [Options] section in the CDF file. * \*****************************************************************************/ BOOL cdf_WriteOptionsSection( PCDFINFO pCdfInfo) { UINT uCount; UINT idx; BOOL bRet;
static struct {
LPCTSTR lpszKey; LPCTSTR lpszStr;
} aszOpt[] = {
g_szPackagePurpose , g_szCreateCAB, g_szExtractorStub , g_szNone, g_szShowWindow , g_sz0, g_szUseLongFileName , g_sz1, g_szHideAnimate , g_sz1, g_szRebootMode , g_szNoReboot, g_szCompressionQuantum, g_szCompressionQuantVal, g_szTargetName , g_szTargetNameSection, g_szAppLaunched , g_szAppLaunchedSection, g_szSourceFiles , g_szSourceFiles, g_szPostInstallCmd , g_szNone, g_szCompressionType , g_szCompressTypeVal, g_szCompressionMemory , g_szCompressionValue };
// Write out [Options] values.
//
uCount = sizeof(aszOpt) / sizeof(aszOpt[0]);
for (idx = 0, bRet = TRUE; (idx < uCount) && bRet; idx++) {
bRet = WritePrivateProfileString(g_szOptions, aszOpt[idx].lpszKey, aszOpt[idx].lpszStr, pCdfInfo->lpszCdfFile); }
return bRet; }
/*****************************************************************************\
* cdf_Generate * * Creates a CDF file and writes it to disk. * \*****************************************************************************/ BOOL cdf_Generate( PCDFINFO pCdfInfo) { if (cdf_WriteVersionSection(pCdfInfo) && cdf_WriteOptionsSection(pCdfInfo) && cdf_WriteFilesSection(pCdfInfo)) {
return TRUE; }
return FALSE; }
/*****************************************************************************\
* cdfCreate * * Creates a CDF object. * * Parameters * ---------- * hinf - Handle to a INF object. The CDF will inherit information from * the INF. * \*****************************************************************************/ HANDLE cdfCreate( HANDLE hinf, BOOL bSecure) { PCDFINFO pCdfInfo;
if (pCdfInfo = (PCDFINFO)genGAlloc(sizeof(CDFINFO))) {
// Initialize object-variables.
//
pCdfInfo->hInf = hinf; pCdfInfo->bSecure = bSecure;
return (HANDLE) pCdfInfo; }
return NULL; }
/*****************************************************************************\
* cdfProcess * * Process the CDF object. * \*****************************************************************************/ BOOL cdfProcess( HANDLE hcdf) { HANDLE hFile; PCDFINFO pCdfInfo; DWORD dwErr;
if (pCdfInfo = (PCDFINFO)hcdf) {
if (pCdfInfo->lpszCdfFile = cdf_GetCdfFile(pCdfInfo)) {
// Check for existence of .cdf file
//
hFile = gen_OpenFileRead(pCdfInfo->lpszCdfFile);
if (hFile && (hFile != INVALID_HANDLE_VALUE)) {
// If we DO have a .cdf for this printer/architecture,
// check if it is up to date.
//
CloseHandle(hFile);
// If the .cdf we have is still up to
// date, we are done.
//
if (cdf_IsUpToDate(pCdfInfo)) {
return TRUE;
} else {
// Delete the old .cdf if it exists
//
DeleteFile(pCdfInfo->lpszCdfFile);
CdfGenerate: // Generate a new one.
//
if (cdf_Generate(pCdfInfo)) return TRUE; }
} else {
dwErr = GetLastError();
// Force an update of our machine ip-addr. Usually,
// this is called in the cdf_IsUpToDat() to verify
// the machine hasn't changed ip-addresses.
//
genUpdIPAddr();
// If we don't have a CDF already, generate one now.
//
if (dwErr == ERROR_FILE_NOT_FOUND) goto CdfGenerate; } }
cdfSetError(pCdfInfo,GetLastError()); }
return FALSE; }
/*****************************************************************************\
* cdfDestroy * * Destroys the CDF object. * \*****************************************************************************/ BOOL cdfDestroy( HANDLE hcdf) { PCDFINFO pCdfInfo; BOOL bFree = FALSE;
if (pCdfInfo = (PCDFINFO)hcdf) {
// Free up any allocated objects.
//
if (pCdfInfo->lpszCdfFile) genGFree(pCdfInfo->lpszCdfFile, genGSize(pCdfInfo->lpszCdfFile));
// Walk the list and free the file-item information.
//
itm_DeleteAll(pCdfInfo);
bFree = genGFree(pCdfInfo, sizeof(CDFINFO)); }
return bFree; }
/*****************************************************************************\
* cdfGetName * * Returns the name of the CDF file. This will not include any path * information. This routine derives the filename from the stored full-path * name in the CDF object. * \*****************************************************************************/ LPCTSTR cdfGetName( HANDLE hcdf) { PCDFINFO pCdfInfo; LPCTSTR lpszName = NULL;
if (pCdfInfo = (PCDFINFO)hcdf) {
if (lpszName = genFindRChar(pCdfInfo->lpszCdfFile, TEXT('\\'))) lpszName++; }
return lpszName; }
/*****************************************************************************\
* cdfGetModTime * * Returns the time the CDF file was last modified. * \*****************************************************************************/ BOOL cdfGetModTime( HANDLE hcdf, LPFILETIME lpftMod) { HANDLE hFile; PCDFINFO pCdfInfo; BOOL bRet = FALSE;
// Fill in struct-info.
//
lpftMod->dwLowDateTime = 0; lpftMod->dwHighDateTime = 0;
// Check the pointer for validity.
//
if (pCdfInfo = (PCDFINFO)hcdf) {
// File should exist at this time, since cdfCreate should always
// create the file. Return false (error) if can't open file.
//
hFile = gen_OpenFileRead(pCdfInfo->lpszCdfFile);
if (hFile && (hFile != INVALID_HANDLE_VALUE)) {
// Get the file creation time.
//
bRet = GetFileTime(hFile, NULL, NULL, lpftMod);
CloseHandle(hFile); } }
return bRet; }
/*************************************************************************************
** cdfCleanUpSourceFiles ** ** This runs through all of the files that we returned from the inf file and in the ** case where there was a source we see if it is in the PrtCabs directory, if it is ** we delete it ** *************************************************************************************/ VOID cdfCleanUpSourceFiles( HANDLE hInf) {
LPINFINFO lpInf = (LPINFINFO)hInf;
if (lpInf) { DWORD dwItems = lpInf->lpInfItems->dwCount; LPINFITEMINFO lpII = lpInf->lpInfItems; LPCTSTR lpszDstPath = infGetDstPath(hInf); // This can't be NULL or we wouldn't have allocated the INF structure
if (*lpszDstPath) { // Might not have been set though
for (DWORD idx = 0; idx < dwItems; idx++) { // We check to see if the file exists as advertised, if it does then we don't
// change anything, otherwise, we search the system and windows directories to
// find it, if it exists, we change the path accordingly
LPTSTR lpszSource = lpII->aItems[idx].szSource;
if (*lpszSource) { // If there was a source file different to the target
LPTSTR lpszName = lpII->aItems[idx].szName;
if (!lstrcmp(lpszName,lpszSource)) { // If we renamed the target to the source
LPTSTR lpszPath = lpII->aItems[idx].szPath;
if (!lstrcmp(lpszPath,lpszDstPath)) { // If we set the path on the source
LPTSTR lpszFile = (LPTSTR)genBuildFileName(lpszPath, lpszName, NULL);
if (lpszFile) { WIN32_FIND_DATA FindFileData; HANDLE hFind = FindFirstFile(lpszFile, &FindFileData);
if (hFind && (hFind != INVALID_HANDLE_VALUE)) { FindClose(hFind); DeleteFile(lpszFile); }
genGFree(lpszFile, genGSize(lpszFile)); } // This is cleanup code, no point in failing it
} } } } } } }
|