windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/pkitrust/mscat32/catadnew.cpp
2020-09-26 16:20:57 +08:00

3150 lines
87 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: catadnew.cpp
//
// Contents: Microsoft Internet Security Catalog Utilities
//
// Functions: CryptCATAdminAcquireContext
// CryptCATAdminReleaseContext
// CryptCATAdminAddCatalog
// CryptCATAdminRemoveCatalog
// CryptCATAdminEnumCatalogFromHash
// CryptCATCatalogInfoFromContext
// CryptCATAdminReleaseCatalogContext
// CryptCATAdminResolveCatalogPath
// CryptCATAdminPauseServiceForBackup
// CryptCATAdminCalcHashFromFileHandle
// I_CryptCatAdminMigrateToNewCatDB
// CatAdminDllMain
//
// History: 01-Jan-2000 reidk created
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include "cryptreg.h"
#include "wintrust.h"
#include "softpub.h"
#include "eventlst.h"
#include "sipguids.h"
#include "mscat32.h"
#include "catdb.h"
#include "voidlist.h"
#include "catutil.h"
#include "..\..\common\catdbsvc\catdbcli.h"
#include "errlog.h"
//
// default system guid for apps that just make calls to CryptCATAdminAddCatalog with
// hCatAdmin == NULL...
//
// {127D0A1D-4EF2-11d1-8608-00C04FC295EE}
//
#define DEF_CAT_SUBSYS_ID \
{ \
0x127d0a1d, \
0x4ef2, \
0x11d1, \
{ 0x86, 0x8, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee } \
}
#define WSZ_CATALOG_FILE_BASE_DIRECTORY L"CatRoot"
#define WSZ_DATABASE_FILE_BASE_DIRECTORY L"CatRoot2"
#define WSZ_REG_FILES_NOT_TO_BACKUP L"System\\CurrentControlSet\\Control\\BackupRestore\\FilesNotToBackup"
#define WSZ_REG_CATALOG_DATABASE_VALUE L"Catalog Database"
#define WSZ_PATH_NOT_TO_BACKUP L"%SystemRoot%\\System32\\CatRoot2\\* /s\0"
static WCHAR *gpwszDatabaseFileBaseDirectory = NULL;
static WCHAR *gpwszCatalogFileBaseDirectory = NULL;
#define WSZ_CATALOG_SUBSYTEM_SEARCH_STRING L"{????????????????????????????????????}"
#define CATADMIN_LOGERR_LASTERR() ErrLog_LogError(NULL, \
ERRLOG_CLIENT_ID_CATADMIN, \
__LINE__, \
0, \
FALSE, \
FALSE);
#define CATADMIN_SETERR_LOG_RETURN(x, y) SetLastError(x); \
ErrLog_LogError(NULL, \
ERRLOG_CLIENT_ID_CATADMIN, \
__LINE__, \
0, \
FALSE, \
FALSE); \
goto y;
typedef struct CATALOG_INFO_CONTEXT_
{
HANDLE hMappedFile;
BYTE *pbMappedFile;
WCHAR *pwszCatalogFile;
PCCTL_CONTEXT pCTLContext;
BOOL fResultOfAdd;
} CATALOG_INFO_CONTEXT;
typedef struct CRYPT_CAT_ADMIN_
{
DWORD cbStruct;
BOOL fUseDefSubSysId;
LPWSTR pwszSubSysGUID;
LPWSTR pwszCatalogFileDir; // full path to .cat files
LPWSTR pwszDatabaseFileDir; // full path to CatDB file
DWORD dwLastDBError;
LIST CatalogInfoContextList;
int nOpenCatInfoContexts;
CRITICAL_SECTION CriticalSection;
BOOL fCSInitialized;
BOOL fCSEntered;
HANDLE hClearCacheEvent;
HANDLE hRegisterWaitForClearCache;
BOOL fRegisteredForChangeNotification;
} CRYPT_CAT_ADMIN;
#define CATINFO_CONTEXT_ALLOCATION_SIZE 64
LPWSTR ppwszFilesToDelete[] = {L"hashmast.cbd",
L"hashmast.cbk",
L"catmast.cbd",
L"catmast.cbk",
L"sysmast.cbd",
L"sysmast.cbk"};
#define NUM_FILES_TO_DELETE (sizeof(ppwszFilesToDelete) / \
sizeof(ppwszFilesToDelete[0]))
BOOL
_CatAdminMigrateSingleDatabase(
LPWSTR pwszDatabaseGUID);
BOOL
_CatAdminSetupDefaults(void);
void
_CatAdminCleanupDefaults(void);
BOOL
_CatAdminTimeStampFilesInSync(
LPWSTR pwszDatabaseGUID,
BOOL *pfInSync);
BOOL
_CatAdminRegisterForChangeNotification(
CRYPT_CAT_ADMIN *pCatAdmin
);
BOOL
_CatAdminFreeCachedCatalogs(
CRYPT_CAT_ADMIN *pCatAdmin
);
VOID CALLBACK
_CatAdminWaitOrTimerCallback(
PVOID lpParameter,
BOOLEAN TimerOrWaitFired
);
BOOL
_CatAdminAddCatalogsToCache(
CRYPT_CAT_ADMIN *pCatAdmin,
LPWSTR pwszSubSysGUID,
CRYPT_DATA_BLOB *pCryptDataBlob,
LIST_NODE **ppFirstListNodeAdded
);
BOOL
_CatAdminAddSingleCatalogToCache(
CRYPT_CAT_ADMIN *pCatAdmin,
LPWSTR pwszCatalog,
LIST_NODE **ppListNodeAdded
);
BOOL
_CatAdminMigrateCatalogDatabase(
LPWSTR pwszFrom,
LPWSTR pwszTo
);
void
_CatAdminBToHex (
LPBYTE pbDigest,
DWORD iByte,
LPWSTR pwszHashTag
);
BOOL
_CatAdminCreateHashTag(
BYTE *pbHash,
DWORD cbHash,
LPWSTR *ppwszHashTag,
CRYPT_DATA_BLOB *pCryptDataBlob
);
BOOL
_CatAdminRecursiveCreateDirectory(
IN LPCWSTR pwszDir,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
LPWSTR
_CatAdminCreatePath(
IN LPCWSTR pwsz1,
IN LPCWSTR pwsz2,
IN BOOL fAddEndingSlash
);
void __RPC_FAR * __RPC_API MIDL_user_allocate(size_t len)
{
return(LocalAlloc(LMEM_ZEROINIT, len));
}
void __RPC_API MIDL_user_free(void __RPC_FAR * ptr)
{
if (ptr != NULL)
{
LocalFree(ptr);
}
}
//---------------------------------------------------------------------------------------
//
// CryptCATAdminAcquireContext
//
//---------------------------------------------------------------------------------------
BOOL WINAPI
CryptCATAdminAcquireContext_Internal(
HCATADMIN *phCatAdmin,
const GUID *pgSubsystem,
DWORD dwFlags,
BOOL fCalledFromMigrate)
{
GUID gDefault = DEF_CAT_SUBSYS_ID;
const GUID *pgCatroot = &gDefault;
CRYPT_CAT_ADMIN *pCatAdmin = NULL;
BOOL fRet = TRUE;
DWORD dwErr = 0;
WCHAR wszGUID[256];
BOOL fInSync;
//
// Validata parameters
//
if (phCatAdmin == NULL)
{
CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
}
*phCatAdmin = NULL;
//
// Allocate a new CatAdmin state struct
//
if (NULL == (pCatAdmin = (CRYPT_CAT_ADMIN *) malloc(sizeof(CRYPT_CAT_ADMIN))))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
memset(pCatAdmin, 0, sizeof(CRYPT_CAT_ADMIN));
pCatAdmin->cbStruct = sizeof(CRYPT_CAT_ADMIN);
LIST_Initialize(&(pCatAdmin->CatalogInfoContextList));
//
// Check to see if caller specified the Catroot dir to use
//
if (pgSubsystem == NULL)
{
pCatAdmin->fUseDefSubSysId = TRUE;
}
else
{
pgCatroot = pgSubsystem;
}
guid2wstr(pgCatroot, wszGUID);
//
// Initialize the critical section
//
__try
{
InitializeCriticalSection(&(pCatAdmin->CriticalSection));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
SetLastError(GetExceptionCode());
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
pCatAdmin->fCSInitialized = TRUE;
pCatAdmin->fCSEntered = FALSE;
//
// Save a copy of the GUID as a string
//
if (NULL == (pCatAdmin->pwszSubSysGUID = (LPWSTR)
malloc((wcslen(wszGUID) + 1) * sizeof(WCHAR))))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
wcscpy(pCatAdmin->pwszSubSysGUID, wszGUID);
//
// Get the complete paths for the catalog files and the db file
//
if (NULL == (pCatAdmin->pwszCatalogFileDir = _CatAdminCreatePath(
gpwszCatalogFileBaseDirectory,
wszGUID,
TRUE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
if (NULL == (pCatAdmin->pwszDatabaseFileDir = _CatAdminCreatePath(
gpwszDatabaseFileBaseDirectory,
wszGUID,
TRUE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Make sure catalog file and database file sub-directories exists
//
if (!_CatAdminRecursiveCreateDirectory(
pCatAdmin->pwszCatalogFileDir,
NULL))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
if (!_CatAdminRecursiveCreateDirectory(
pCatAdmin->pwszDatabaseFileDir,
NULL))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Create the event which is notified when the catalog db changes, and register
// a callback for when the event is signaled
//
if (NULL == (pCatAdmin->hClearCacheEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorCreateEvent;
}
if (!RegisterWaitForSingleObject(
&(pCatAdmin->hRegisterWaitForClearCache),
pCatAdmin->hClearCacheEvent,
_CatAdminWaitOrTimerCallback,
pCatAdmin,
INFINITE,
WT_EXECUTEDEFAULT))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorRegisterWaitForSingleObject;
}
//
// If we are being called by a real client (not the migrate code) then make sure
// the TimeStamp files are in a consistent state, and if not, migrate (re-add)
// the catalog files for that database
//
if (!fCalledFromMigrate)
{
if (_CatAdminTimeStampFilesInSync(wszGUID, &fInSync))
{
if (!fInSync)
{
//
// FIX FIX - may need to migrate
// all DBs if the wszGUID is DEF_CAT_SUBSYS_ID
//
if (!_CatAdminMigrateSingleDatabase(wszGUID))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
}
}
else
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
}
//
// NOTE:
// Defer registering with the service for the change notificatation so we
// don't rely on the service during an acquire context
//
*phCatAdmin = (HCATADMIN)pCatAdmin;
CommonReturn:
return(fRet);
ErrorReturn:
if (pCatAdmin != NULL)
{
dwErr = GetLastError();
if (pCatAdmin->hRegisterWaitForClearCache != NULL)
{
UnregisterWaitEx(
pCatAdmin->hRegisterWaitForClearCache,
INVALID_HANDLE_VALUE);
}
// call UnregisterWaitEx before deteling the critical section
// because the cb thread tries to enter it
if (pCatAdmin->fCSInitialized)
{
DeleteCriticalSection(&(pCatAdmin->CriticalSection));
}
if (pCatAdmin->hClearCacheEvent != NULL)
{
CloseHandle(pCatAdmin->hClearCacheEvent);
}
if (pCatAdmin->pwszSubSysGUID != NULL)
{
free(pCatAdmin->pwszSubSysGUID);
}
if (pCatAdmin->pwszCatalogFileDir != NULL)
{
free(pCatAdmin->pwszCatalogFileDir);
}
if (pCatAdmin->pwszDatabaseFileDir != NULL)
{
free(pCatAdmin->pwszDatabaseFileDir);
}
free(pCatAdmin);
SetLastError(dwErr);
}
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorRegisterWaitForSingleObject)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCreateEvent)
}
BOOL WINAPI
CryptCATAdminAcquireContext(
OUT HCATADMIN *phCatAdmin,
IN const GUID *pgSubsystem,
IN DWORD dwFlags)
{
return (CryptCATAdminAcquireContext_Internal(
phCatAdmin,
pgSubsystem,
dwFlags,
FALSE));
}
//---------------------------------------------------------------------------------------
//
// CryptCATAdminReleaseContext
//
//---------------------------------------------------------------------------------------
BOOL WINAPI
CryptCATAdminReleaseContext(
IN HCATADMIN hCatAdmin,
IN DWORD dwFlags)
{
CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
BOOL fRet = TRUE;
int i = 0;
LIST_NODE *pListNode = NULL;
//
// Validate input params
//
if ((pCatAdmin == NULL) ||
(pCatAdmin->cbStruct != sizeof(CRYPT_CAT_ADMIN)))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
}
//
// Un-Register for change notifications from DB process
//
// This needs to happen first thing, so that no callbacks
// happen during cleanup
//
if (pCatAdmin->fRegisteredForChangeNotification)
{
Client_SSCatDBRegisterForChangeNotification(
(DWORD_PTR) pCatAdmin->hClearCacheEvent,
0,
pCatAdmin->pwszSubSysGUID,
TRUE);
}
UnregisterWaitEx(pCatAdmin->hRegisterWaitForClearCache, INVALID_HANDLE_VALUE);
CloseHandle(pCatAdmin->hClearCacheEvent);
_CatAdminFreeCachedCatalogs(pCatAdmin);
free(pCatAdmin->pwszSubSysGUID);
free(pCatAdmin->pwszCatalogFileDir);
free(pCatAdmin->pwszDatabaseFileDir);
DeleteCriticalSection(&(pCatAdmin->CriticalSection));
free(pCatAdmin);
CommonReturn:
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
}
//---------------------------------------------------------------------------------------
//
// CryptCATAdminAddCatalog
//
//---------------------------------------------------------------------------------------
HCATINFO WINAPI
CryptCATAdminAddCatalog(
IN HCATADMIN hCatAdmin,
IN WCHAR *pwszCatalogFile,
IN WCHAR *pwszSelectBaseName,
IN DWORD dwFlags)
{
CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
BOOL fRet;
LPWSTR pwszName = NULL;
DWORD dwErr = 0;
LPWSTR pwszCatalogNameUsed = NULL;
LPWSTR pwszCatalogNameUsedCopy = NULL;
LPWSTR pwszFullyQualifiedCatalogFile = NULL;
DWORD dwLength = 0;
LIST_NODE *pListNode = NULL;
WCHAR wszTmp[1];
if ((pCatAdmin == NULL) ||
(pCatAdmin->cbStruct != sizeof(CRYPT_CAT_ADMIN)) ||
(pwszCatalogFile == NULL) ||
(dwFlags != 0))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
}
ErrLog_LogString(NULL, L"Adding Catalog File: ", pwszSelectBaseName, TRUE);
//
// first, check the catalog...
//
if (!(IsCatalogFile(INVALID_HANDLE_VALUE, pwszCatalogFile)))
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
CATADMIN_SETERR_LOG_RETURN(ERROR_BAD_FORMAT, ErrorBadFileFormat)
}
__try
{
EnterCriticalSection(&(pCatAdmin->CriticalSection));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
SetLastError(GetExceptionCode());
CATADMIN_LOGERR_LASTERR()
return NULL;
}
pCatAdmin->fCSEntered = TRUE;
if (!_CatAdminRegisterForChangeNotification(pCatAdmin))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Clear the cache, since doing the add may change things
//
_CatAdminFreeCachedCatalogs(pCatAdmin);
//
// If the file name specified by pwszCatalogFile is not a fully qualified
// path name, we need to build one before calling the service.
//
if ((wcschr(pwszCatalogFile, L'\\') == NULL) &&
(wcschr(pwszCatalogFile, L':') == NULL))
{
dwLength = GetCurrentDirectoryW(1, wszTmp) * sizeof(WCHAR);
dwLength += (wcslen(pwszCatalogFile) + 1) * sizeof(WCHAR);
if (NULL == (pwszFullyQualifiedCatalogFile = (LPWSTR) malloc(dwLength)))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
if (!GetCurrentDirectoryW(
dwLength / sizeof(WCHAR),
pwszFullyQualifiedCatalogFile))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
if ((pwszFullyQualifiedCatalogFile[wcslen(pwszFullyQualifiedCatalogFile) - 1]
!= L'\\'))
{
wcscat(pwszFullyQualifiedCatalogFile, L"\\");
}
wcscat(pwszFullyQualifiedCatalogFile, pwszCatalogFile);
}
//
// Call the DB process to add the catalog
//
if (0 != (dwErr = Client_SSCatDBAddCatalog(
0,
pCatAdmin->pwszSubSysGUID,
(pwszFullyQualifiedCatalogFile != NULL) ?
pwszFullyQualifiedCatalogFile :
pwszCatalogFile,
pwszSelectBaseName,
&pwszCatalogNameUsed)))
{
CATADMIN_SETERR_LOG_RETURN(dwErr, ErrorCatDBProcess)
}
//
// Touch the TimeStamp file
//
TimeStampFile_Touch(pCatAdmin->pwszCatalogFileDir);
//
// create a psuedo list entry, that really isn't part of the list...
// this is so the caller can call CryptCATCatalogInfoFromContext
//
if (NULL == (pwszCatalogNameUsedCopy = (LPWSTR)
malloc((wcslen(pwszCatalogNameUsed) + 1) * sizeof(WCHAR))))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
wcscpy(pwszCatalogNameUsedCopy, pwszCatalogNameUsed);
if (NULL == (pCatInfoContext = (CATALOG_INFO_CONTEXT *)
malloc(sizeof(CATALOG_INFO_CONTEXT))))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
memset(pCatInfoContext, 0, sizeof(CATALOG_INFO_CONTEXT));
pCatInfoContext->pwszCatalogFile = pwszCatalogNameUsedCopy;
pCatInfoContext->fResultOfAdd = TRUE;
if (NULL == (pListNode = (LIST_NODE *) malloc(sizeof(LIST_NODE))))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
memset(pListNode, 0, sizeof(LIST_NODE));
pListNode->pElement = pCatInfoContext;
CommonReturn:
MIDL_user_free(pwszCatalogNameUsed);
if (pwszFullyQualifiedCatalogFile != NULL)
{
free(pwszFullyQualifiedCatalogFile);
}
if ((pCatAdmin != NULL) &&
(pCatAdmin->fCSEntered))
{
pCatAdmin->fCSEntered = FALSE;
LeaveCriticalSection(&(pCatAdmin->CriticalSection));
}
ErrLog_LogString(NULL, L"DONE Adding Catalog File: ", pwszSelectBaseName, TRUE);
return((HCATINFO) pListNode);
ErrorReturn:
if (pwszCatalogNameUsedCopy != NULL)
{
free(pwszCatalogNameUsedCopy);
}
if (pCatInfoContext != NULL)
{
free(pCatInfoContext);
}
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorBadFileFormat)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCatDBProcess)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory)
}
//---------------------------------------------------------------------------------------
//
// CryptCATAdminRemoveCatalog
//
//---------------------------------------------------------------------------------------
BOOL WINAPI
CryptCATAdminRemoveCatalog(
IN HCATADMIN hCatAdmin,
IN LPCWSTR pwszCatalogFile,
IN DWORD dwFlags)
{
BOOL fRet = TRUE;
DWORD dwErr = 0;
CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
//
// Call the DB process to delete the catalog
//
if (0 != (dwErr = Client_SSCatDBDeleteCatalog(
0,
pCatAdmin->pwszSubSysGUID,
pwszCatalogFile)))
{
CATADMIN_SETERR_LOG_RETURN(dwErr, ErrorCatDBProcess)
}
//
// Touch the TimeStamp file
//
TimeStampFile_Touch(pCatAdmin->pwszCatalogFileDir);
CommonReturn:
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCatDBProcess)
}
//---------------------------------------------------------------------------------------
//
// CryptCATAdminEnumCatalogFromHash
//
//---------------------------------------------------------------------------------------
HCATINFO WINAPI
CryptCATAdminEnumCatalogFromHash(
IN HCATADMIN hCatAdmin,
IN BYTE *pbHash,
IN DWORD cbHash,
IN DWORD dwFlags,
IN HCATINFO *phPrevCatInfo)
{
CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
BOOL fFindFirstOnly;
BOOL fInitializeEnum = FALSE;
int i = 0;
CRYPT_DATA_BLOB CryptDataBlobHash;
CRYPT_DATA_BLOB CryptDataBlobHashTag;
LPWSTR pwszSearch = NULL;
HANDLE hFindHandle = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindData;
LPWSTR pwszHashTag = NULL;
DWORD dwErr = 0;
LIST_NODE *pPrevListNode = NULL;
LIST_NODE *pListNodeToReturn = NULL;
LIST_NODE *pListNode = NULL;
CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
//
// Validate input params
//
if ((pCatAdmin == NULL) ||
(pCatAdmin->cbStruct != sizeof(CRYPT_CAT_ADMIN)) ||
(cbHash == 0) ||
(cbHash > MAX_HASH_LEN) ||
(dwFlags != 0))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
}
if (!_CatAdminRegisterForChangeNotification(pCatAdmin))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// If phPrevCatInfo is NULL then that means the caller is only interested
// in the first catalog that contains the hash, thus no enum state is
// started. If phPrevCatInfo is non NULL, then it contains NULL, or a
// HCATINFO that was returned from a previous call to
// CryptCATAdminEnumCatalogFromHash. If it contains NULL, then this is
// the start of an enum, otherwise it is enuming the next catalog containing
// the hash.
//
if (phPrevCatInfo == NULL)
{
fFindFirstOnly = TRUE;
}
else
{
fFindFirstOnly = FALSE;
pPrevListNode = (LIST_NODE *) *phPrevCatInfo;
}
//
// Only allow one thread to view/modify at a time
//
__try
{
EnterCriticalSection(&(pCatAdmin->CriticalSection));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
SetLastError(GetExceptionCode());
CATADMIN_LOGERR_LASTERR()
return FALSE;
}
pCatAdmin->fCSEntered = TRUE;
__try
{
//
// This data blob is used to do the find in the database
//
CryptDataBlobHash.pbData = pbHash;
CryptDataBlobHash.cbData = cbHash;
//
// Create the tag to be used for calls to CertFindSubjectInSortedCTL
//
if (!_CatAdminCreateHashTag(pbHash, cbHash, &pwszHashTag, &CryptDataBlobHashTag))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// The enum works as follows:
//
// if enum-state is not being initialized OR this is the first call to start an enum
//
// loop through all currently cached catalogs until a catalog containing the
// the hash is found, and return it
//
// if a catalog was not found in the cache, then call the DB process to try and
// find one
//
// else (enum state has already been started)
//
// loop through currently cached catalogs, starting with the catalog just after
// the current catalog, and until a catalog containing the hash is found
//
if ((fFindFirstOnly) || (pPrevListNode == NULL))
{
pListNode = LIST_GetFirst(&(pCatAdmin->CatalogInfoContextList));
while (pListNode != NULL)
{
pCatInfoContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
if (CertFindSubjectInSortedCTL(
&CryptDataBlobHashTag,
pCatInfoContext->pCTLContext,
NULL,
NULL,
NULL))
{
pListNodeToReturn = pListNode;
goto CommonReturn;
}
pListNode = LIST_GetNext(pListNode);
}
//
// If we are here, that means we did not find a cached catalog that contained
// the hash, so call the DB process to try and find one or more.
//
// Call the DB process once if we are not using the default sub-system ID,
// otherwise call the DB process once for each sub-system.
if (!pCatAdmin->fUseDefSubSysId)
{
if (_CatAdminAddCatalogsToCache(
pCatAdmin,
pCatAdmin->pwszSubSysGUID,
&CryptDataBlobHash,
&pListNodeToReturn))
{
if (pListNodeToReturn == NULL)
{
SetLastError(ERROR_NOT_FOUND);
//CATADMIN_LOGERR_LASTERR()
goto CatNotFound;
}
goto CommonReturn;
}
else
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
}
else
{
//
// For each subdir, add all the catalogs that contain the hash
//
//
// Create search string to find all subdirs
//
if (NULL == (pwszSearch = _CatAdminCreatePath(
gpwszDatabaseFileBaseDirectory,
WSZ_CATALOG_SUBSYTEM_SEARCH_STRING,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Do the initial find
//
hFindHandle = FindFirstFileU(pwszSearch, &FindData);
if (hFindHandle == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
//
// no sub dirs found
//
if ((dwErr == ERROR_NO_MORE_FILES) ||
(dwErr == ERROR_PATH_NOT_FOUND) ||
(dwErr == ERROR_FILE_NOT_FOUND))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_FOUND, CatNotFound)
}
else
{
goto ErrorFindFirstFile;
}
}
while (1)
{
//
// Only care about directories
//
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//
// Add all the catalogs in this subdir that contain the hash to
// the catalog cache
//
if (!_CatAdminAddCatalogsToCache(
pCatAdmin,
FindData.cFileName,
&CryptDataBlobHash,
(pListNodeToReturn == NULL) ?
&pListNodeToReturn : NULL))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
}
//
// Get next subdir
//
if (!FindNextFileU(hFindHandle, &FindData))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
break;
}
else
{
goto ErrorFindNextFile;
}
}
}
if (pListNodeToReturn == NULL)
{
SetLastError(ERROR_NOT_FOUND);
//CATADMIN_LOGERR_LASTERR()
goto CatNotFound;
}
}
}
else
{
//
// Enum state already started, so just search through the rest of the cached
// catalogs to try and find one that contains the hash
//
pListNode = LIST_GetNext(pPrevListNode);
while (pListNode != NULL)
{
pCatInfoContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
if (CertFindSubjectInSortedCTL(
&CryptDataBlobHashTag,
pCatInfoContext->pCTLContext,
NULL,
NULL,
NULL))
{
pListNodeToReturn = pListNode;
goto CommonReturn;
}
pListNode = LIST_GetNext(pListNode);
}
//
// If we get here that means no catalog was found
//
SetLastError(ERROR_NOT_FOUND);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
CATADMIN_SETERR_LOG_RETURN(GetExceptionCode(), ErrorException)
}
CommonReturn:
dwErr = GetLastError();
if (pwszHashTag != NULL)
{
free(pwszHashTag);
}
if (pwszSearch != NULL)
{
free(pwszSearch);
}
if (hFindHandle != INVALID_HANDLE_VALUE)
{
FindClose(hFindHandle);
}
if (pListNodeToReturn != NULL)
{
pCatAdmin->nOpenCatInfoContexts++;
}
if (pPrevListNode != NULL)
{
*phPrevCatInfo = NULL;
//
// Decrement, since this is the equivalent of
// calling CryptCATAdminReleaseCatalogContext
//
pCatAdmin->nOpenCatInfoContexts--;
}
if ((pCatAdmin != NULL) &&
(pCatAdmin->fCSEntered))
{
pCatAdmin->fCSEntered = FALSE;
LeaveCriticalSection(&(pCatAdmin->CriticalSection));
}
SetLastError(dwErr);
return((HCATINFO) pListNodeToReturn);
ErrorReturn:
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
TRACE_ERROR_EX(DBG_SS_TRUST, CatNotFound)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindFirstFile)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindNextFile)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorException)
}
//---------------------------------------------------------------------------------------
//
// CryptCATCatalogInfoFromContext
//
//---------------------------------------------------------------------------------------
BOOL WINAPI
CryptCATCatalogInfoFromContext(
IN HCATINFO hCatInfo,
IN OUT CATALOG_INFO *psCatInfo,
IN DWORD dwFlags)
{
BOOL fRet = TRUE;
LIST_NODE *pListNode = (LIST_NODE *) hCatInfo;
CATALOG_INFO_CONTEXT *pContext = NULL;
if ((pListNode == NULL) || (psCatInfo == NULL))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
}
pContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
if (pContext->pwszCatalogFile != NULL)
{
if ((wcslen(pContext->pwszCatalogFile) + 1) > MAX_PATH)
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorTooLong)
}
wcscpy(psCatInfo->wszCatalogFile, pContext->pwszCatalogFile);
}
CommonReturn:
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorTooLong)
}
//---------------------------------------------------------------------------------------
//
// CryptCATAdminReleaseCatalogContext
//
//---------------------------------------------------------------------------------------
BOOL WINAPI
CryptCATAdminReleaseCatalogContext(
IN HCATADMIN hCatAdmin,
IN HCATINFO hCatInfo,
IN DWORD dwFlags)
{
BOOL fRet = TRUE;
CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
LIST_NODE *pListNode = (LIST_NODE *) hCatInfo;
CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
if ((pCatAdmin == NULL) ||
(pCatAdmin->cbStruct != sizeof(CRYPT_CAT_ADMIN)) ||
(pListNode == NULL))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
}
//
// check to see if this is from and add operation, if so, then clean
// up allocated memory, otherwise, just decrement ref count
//
pCatInfoContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
if (pCatInfoContext->fResultOfAdd)
{
free(pCatInfoContext->pwszCatalogFile);
free(pCatInfoContext);
free(pListNode);
}
else
{
// FIX FIX - may need to be smarter about this... like verify
// the node is actually in the list.
pCatAdmin->nOpenCatInfoContexts--;
}
CommonReturn:
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam);
}
//---------------------------------------------------------------------------------------
//
// CryptCATAdminResolveCatalogPath
//
//---------------------------------------------------------------------------------------
BOOL WINAPI
CryptCATAdminResolveCatalogPath(
IN HCATADMIN hCatAdmin,
IN WCHAR *pwszCatalogFile,
IN OUT CATALOG_INFO *psCatInfo,
IN DWORD dwFlags)
{
BOOL fRet = TRUE;
CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *)hCatAdmin;
if ((pCatAdmin == NULL) ||
(pCatAdmin->cbStruct != sizeof(CRYPT_CAT_ADMIN)) ||
(pwszCatalogFile == NULL) ||
(psCatInfo == NULL) ||
(psCatInfo->cbStruct != sizeof(CATALOG_INFO)) ||
(dwFlags != 0))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, ErrorInvalidParam)
}
if ((wcslen(pCatAdmin->pwszCatalogFileDir) +
wcslen(pwszCatalogFile) +
1) > MAX_PATH)
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorTooLong)
}
wcscpy(psCatInfo->wszCatalogFile, pCatAdmin->pwszCatalogFileDir);
wcscat(psCatInfo->wszCatalogFile, pwszCatalogFile);
CommonReturn:
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorInvalidParam)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorTooLong)
}
//---------------------------------------------------------------------------------------
//
// CryptCATAdminPauseServiceForBackup
//
//---------------------------------------------------------------------------------------
BOOL WINAPI
CryptCATAdminPauseServiceForBackup(
IN DWORD dwFlags,
IN BOOL fResume)
{
BOOL fRet = TRUE;
DWORD dwErr = 0;
//
// Call the DB process to delete the catalog
//
if (0 != (dwErr = Client_SSCatDBPauseResumeService(
0,
fResume)))
{
CATADMIN_SETERR_LOG_RETURN(dwErr, ErrorCatDBProcess)
}
CommonReturn:
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCatDBProcess)
}
//---------------------------------------------------------------------------------------
//
// CryptCATAdminCalcHashFromFileHandle
//
//---------------------------------------------------------------------------------------
BOOL WINAPI
CryptCATAdminCalcHashFromFileHandle(
IN HANDLE hFile,
IN OUT DWORD *pcbHash,
IN BYTE *pbHash,
IN DWORD dwFlags)
{
BYTE *pbRet = NULL;
SIP_INDIRECT_DATA *pbIndirectData = NULL;
BOOL fRet;
GUID gSubject;
SIP_DISPATCH_INFO sSip;
if ((hFile == NULL) ||
(hFile == INVALID_HANDLE_VALUE) ||
(pcbHash == NULL) ||
(dwFlags != 0))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_INVALID_PARAMETER, InvalidParam)
}
if (!CryptSIPRetrieveSubjectGuidForCatalogFile(L"CATADMIN", hFile, &gSubject))
{
goto ErrorMemory;
}
memset(&sSip, 0x00, sizeof(SIP_DISPATCH_INFO));
sSip.cbSize = sizeof(SIP_DISPATCH_INFO);
if (!CryptSIPLoad(&gSubject, 0, &sSip))
{
CATADMIN_LOGERR_LASTERR()
goto SIPLoadError;
}
SIP_SUBJECTINFO sSubjInfo;
DWORD cbIndirectData;
memset(&sSubjInfo, 0x00, sizeof(SIP_SUBJECTINFO));
sSubjInfo.cbSize = sizeof(SIP_SUBJECTINFO);
sSubjInfo.DigestAlgorithm.pszObjId = (char *)CertAlgIdToOID(CALG_SHA1);
sSubjInfo.dwFlags = SPC_INC_PE_RESOURCES_FLAG |
SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG |
MSSIP_FLAGS_PROHIBIT_RESIZE_ON_CREATE;
sSubjInfo.pgSubjectType = &gSubject;
sSubjInfo.hFile = hFile;
sSubjInfo.pwsFileName = L"CATADMIN";
sSubjInfo.dwEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
cbIndirectData = 0;
sSip.pfCreate(&sSubjInfo, &cbIndirectData, NULL);
if (cbIndirectData == 0)
{
SetLastError(E_NOTIMPL);
//CATADMIN_LOGERR_LASTERR()
goto SIPError;
}
if (NULL == (pbIndirectData = (SIP_INDIRECT_DATA *) malloc(cbIndirectData)))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
if (!(sSip.pfCreate(&sSubjInfo, &cbIndirectData, pbIndirectData)))
{
if (GetLastError() == 0)
{
SetLastError(ERROR_INVALID_DATA);
}
CATADMIN_LOGERR_LASTERR()
goto SIPError;
}
if ((pbIndirectData->Digest.cbData == 0) ||
(pbIndirectData->Digest.cbData > MAX_HASH_LEN))
{
SetLastError( ERROR_INVALID_DATA );
goto SIPError;
}
if (NULL == (pbRet = (BYTE *) malloc(pbIndirectData->Digest.cbData)))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
memcpy(pbRet, pbIndirectData->Digest.pbData, pbIndirectData->Digest.cbData);
fRet = TRUE;
CommonReturn:
if (pbRet)
{
if (*pcbHash < pbIndirectData->Digest.cbData)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
fRet = FALSE;
}
else if (pbHash)
{
memcpy(pbHash, pbRet, pbIndirectData->Digest.cbData);
}
*pcbHash = pbIndirectData->Digest.cbData;
free(pbRet);
}
if (pbIndirectData)
{
free(pbIndirectData);
}
if ((GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
(pbHash == NULL))
{
fRet = TRUE;
}
return(fRet);
ErrorReturn:
free(pbRet);
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, SIPLoadError)
TRACE_ERROR_EX(DBG_SS_TRUST, SIPError)
TRACE_ERROR_EX(DBG_SS_TRUST, InvalidParam)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory)
}
//---------------------------------------------------------------------------------------
//
// I_CryptCatAdminMigrateToNewCatDB
//
//---------------------------------------------------------------------------------------
BOOL WINAPI
I_CryptCatAdminMigrateToNewCatDB()
{
BOOL fRet = TRUE;
LPWSTR pwszSearchCatDirs = NULL;
LPWSTR pwszDeleteFile = NULL;
LPWSTR pwsz = NULL;
LPWSTR pwszMigrateFromDir = NULL;
HCATADMIN hCatAdmin = NULL;
GUID gDefault = DEF_CAT_SUBSYS_ID;
HANDLE hFindHandleCatDirs = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindDataCatDirs;
DWORD dwErr = 0;
HKEY hKey;
DWORD dwDisposition;
int i;
BOOL fInSync;
WCHAR wszGUID[256];
LPWSTR pwszCatalogFileDir = NULL;
LPWSTR pwszDatabaseFileDir = NULL;
//
// FIRST!!
//
// Clean up the old reg based catroot entry, and if needed, move
// the old style catalog database from its old directory to the new directory,
// then do the migrate from there
//
if (RegCreateKeyExU(
HKEY_LOCAL_MACHINE,
REG_MACHINE_SETTINGS_KEY,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&dwDisposition) == ERROR_SUCCESS)
{
DWORD dwType;
DWORD cbSize;
cbSize = 0;
RegQueryValueExU(
hKey,
WSZ_CATALOG_FILE_BASE_DIRECTORY,
NULL,
&dwType,
NULL,
&cbSize);
if (cbSize > 0)
{
if (NULL == (pwszMigrateFromDir = (LPWSTR)
malloc(sizeof(WCHAR) * ((cbSize / sizeof(WCHAR)) + 3))))
{
RegCloseKey(hKey);
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
pwszMigrateFromDir[0] = NULL;
RegQueryValueExU(
hKey,
WSZ_CATALOG_FILE_BASE_DIRECTORY,
NULL,
&dwType,
(BYTE *)pwszMigrateFromDir,
&cbSize);
if (!_CatAdminMigrateCatalogDatabase(
pwszMigrateFromDir,
gpwszCatalogFileBaseDirectory))
{
RegCloseKey(hKey);
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
RegDeleteValueU(hKey, WSZ_CATALOG_FILE_BASE_DIRECTORY);
}
RegCloseKey(hKey);
}
//
// NOW, that we are in a consistent state
//
// For each catalog sub-system, enumerate all catalogs and add them to the
// new catalog database under the same sub-system GUID.
//
//
// Create search string to find all catalog sub dirs
//
if (NULL == (pwszSearchCatDirs = _CatAdminCreatePath(
gpwszCatalogFileBaseDirectory,
WSZ_CATALOG_SUBSYTEM_SEARCH_STRING,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Do the initial find
//
hFindHandleCatDirs = FindFirstFileU(pwszSearchCatDirs, &FindDataCatDirs);
if (hFindHandleCatDirs == INVALID_HANDLE_VALUE)
{
//
// See if a real error occurred, or just no files
//
dwErr = GetLastError();
if ((dwErr == ERROR_NO_MORE_FILES) ||
(dwErr == ERROR_PATH_NOT_FOUND) ||
(dwErr == ERROR_FILE_NOT_FOUND))
{
//
// There is nothing to do
//
SetLastError(0);
goto RegKeyAdd;
}
else
{
CATADMIN_LOGERR_LASTERR()
goto ErrorFindFirstFile;
}
}
while (1)
{
//
// Only care about directories
//
if (FindDataCatDirs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
_CatAdminMigrateSingleDatabase(FindDataCatDirs.cFileName);
}
//
// Get rid of old files
//
dwErr = GetLastError();
if (NULL != (pwsz = _CatAdminCreatePath(
gpwszCatalogFileBaseDirectory,
FindDataCatDirs.cFileName,
FALSE)))
{
for (i=0; i<NUM_FILES_TO_DELETE; i++)
{
if (NULL != (pwszDeleteFile = _CatAdminCreatePath(
pwsz,
ppwszFilesToDelete[i],
FALSE)))
{
if (!DeleteFileU(pwszDeleteFile))
{
//
// If delete fails, then log for delete after reboot
//
MoveFileExW(pwszDeleteFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
}
free(pwszDeleteFile);
}
}
free(pwsz);
}
SetLastError(dwErr);
//
// Get next subdir
//
if (!FindNextFileU(hFindHandleCatDirs, &FindDataCatDirs))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
SetLastError(0);
break;
}
else
{
CATADMIN_LOGERR_LASTERR()
goto ErrorFindNextFile;
}
}
}
//
// Get rid of old files
//
dwErr = GetLastError();
for (i=0; i<NUM_FILES_TO_DELETE; i++)
{
if (NULL != (pwszDeleteFile = _CatAdminCreatePath(
gpwszCatalogFileBaseDirectory,
ppwszFilesToDelete[i],
FALSE)))
{
if (!DeleteFileU(pwszDeleteFile))
{
//
// If delete fails, then log for delete after reboot
//
MoveFileExW(pwszDeleteFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
}
free(pwszDeleteFile);
}
}
SetLastError(dwErr);
RegKeyAdd:
//
// Set reg key so backup does not backup the catroot2 directory
// which contains jet db files
//
if (RegCreateKeyExW(
HKEY_LOCAL_MACHINE,
WSZ_REG_FILES_NOT_TO_BACKUP,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&dwDisposition) == ERROR_SUCCESS)
{
if (RegSetValueExW(
hKey,
WSZ_REG_CATALOG_DATABASE_VALUE,
0,
REG_MULTI_SZ,
(BYTE *) WSZ_PATH_NOT_TO_BACKUP,
(wcslen(WSZ_PATH_NOT_TO_BACKUP) + 2) * sizeof(WCHAR)) != ERROR_SUCCESS)
{
CATADMIN_LOGERR_LASTERR()
}
RegCloseKey(hKey);
}
else
{
CATADMIN_LOGERR_LASTERR()
}
//
// Force the default DB to be created
//
if (CryptCATAdminAcquireContext_Internal(
&hCatAdmin,
&gDefault,
NULL,
TRUE))
{
BYTE rgHash[20] = {0};
HCATINFO hCatInfo = NULL;
hCatInfo = CryptCATAdminEnumCatalogFromHash(
hCatAdmin,
rgHash,
20,
0,
NULL);
if (hCatInfo != NULL)
{
CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
}
CryptCATAdminReleaseContext(hCatAdmin, 0);
//
// Need to create the timestamp files if they don't exist
//
guid2wstr(&gDefault, wszGUID);
//
// Construct full subdir path to Catalog files TimeStamp location
//
if (NULL == (pwszCatalogFileDir = _CatAdminCreatePath(
gpwszCatalogFileBaseDirectory,
wszGUID,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto CommonReturn; // non fatal for the function, so don't error out
}
//
// Construct full subdir path to Database files TimeStamp location
//
if (NULL == (pwszDatabaseFileDir = _CatAdminCreatePath(
gpwszDatabaseFileBaseDirectory,
wszGUID,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto CommonReturn; // non fatal for the function, so don't error out
}
//
// See if they are in sync (if they don't exist, that equals out of sync)
//
if (TimeStampFile_InSync(
pwszCatalogFileDir,
pwszDatabaseFileDir,
&fInSync))
{
if (!fInSync)
{
TimeStampFile_Touch(pwszCatalogFileDir);
TimeStampFile_Touch(pwszDatabaseFileDir);
}
}
else
{
CATADMIN_LOGERR_LASTERR()
}
}
else
{
CATADMIN_LOGERR_LASTERR()
}
CommonReturn:
dwErr = GetLastError();
if (pwszMigrateFromDir != NULL)
{
free(pwszMigrateFromDir);
}
if (pwszSearchCatDirs != NULL)
{
free(pwszSearchCatDirs);
}
if (hFindHandleCatDirs != INVALID_HANDLE_VALUE)
{
FindClose(hFindHandleCatDirs);
}
if (pwszCatalogFileDir != NULL)
{
free(pwszCatalogFileDir);
}
if (pwszDatabaseFileDir != NULL)
{
free(pwszDatabaseFileDir);
}
SetLastError(dwErr);
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory);
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindFirstFile)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindNextFile)
}
//---------------------------------------------------------------------------------------
//
// _CatAdminMigrateSingleDatabase
//
//---------------------------------------------------------------------------------------
BOOL
_CatAdminMigrateSingleDatabase(
LPWSTR pwszDatabaseGUID)
{
BOOL fRet = TRUE;
LPWSTR pwszCatalogFile = NULL;
LPWSTR pwszSearchCatalogsInDir = NULL;
HANDLE hFindHandleCatalogsInDir = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW FindDataCatalogsInDir;
GUID guid;
HCATINFO hCatInfo = NULL;
HCATADMIN hCatAdmin = NULL;
DWORD dwErr = 0;
LPWSTR pwszSubDir = NULL;
LPWSTR pwszTempDir = NULL;
LPWSTR pwszTempCatalogFile = NULL;
//
// Acquire the catadmin context to add the catalog files to
//
if (!wstr2guid(pwszDatabaseGUID, &guid))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
if (!CryptCATAdminAcquireContext_Internal(&hCatAdmin, &guid, NULL, TRUE))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Construct full subdir path so we can search for all cat files
//
if (NULL == (pwszSubDir = _CatAdminCreatePath(
gpwszCatalogFileBaseDirectory,
pwszDatabaseGUID,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Construct temp directory path, and create the directory to back it
//
if (NULL == (pwszTempDir = _CatAdminCreatePath(
pwszSubDir,
L"TempDir",
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
if (!_CatAdminRecursiveCreateDirectory(
pwszTempDir,
NULL))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Construct the search string
//
if (NULL == (pwszSearchCatalogsInDir = _CatAdminCreatePath(
pwszSubDir,
L"*",
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// First copy all the catalogs to a temp directory, then add each catalog
// to the database from the temporary location
//
//
// Copy each file
//
memset(&FindDataCatalogsInDir, 0, sizeof(FindDataCatalogsInDir));
hFindHandleCatalogsInDir = FindFirstFileU(
pwszSearchCatalogsInDir,
&FindDataCatalogsInDir);
if (hFindHandleCatalogsInDir == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
//
// no files found
//
if ((dwErr == ERROR_NO_MORE_FILES) ||
(dwErr == ERROR_FILE_NOT_FOUND))
{
SetLastError(0);
}
else
{
CATADMIN_LOGERR_LASTERR()
goto ErrorFindFirstFile;
}
}
else
{
while (1)
{
//
// Only care about files
//
if (!(FindDataCatalogsInDir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
//
// Construct fully qualified path name to catalog file
//
if (NULL == (pwszCatalogFile = _CatAdminCreatePath(
pwszSubDir,
FindDataCatalogsInDir.cFileName,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Verify that this is a catalog and then copy it to the temp dir
// which is where it will be installed from
//
if (IsCatalogFile(NULL, pwszCatalogFile))
{
if (NULL == (pwszTempCatalogFile = _CatAdminCreatePath(
pwszTempDir,
FindDataCatalogsInDir.cFileName,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
if (!CopyFileU(pwszCatalogFile, pwszTempCatalogFile, FALSE))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
free(pwszTempCatalogFile);
pwszTempCatalogFile = NULL;
}
free(pwszCatalogFile);
pwszCatalogFile = NULL;
}
//
// Get next catalog file
//
if (!FindNextFileU(hFindHandleCatalogsInDir, &FindDataCatalogsInDir))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
SetLastError(0);
break;
}
else
{
CATADMIN_LOGERR_LASTERR()
goto ErrorFindNextFile;
}
}
}
}
//
// Free up stuff used for find
//
free(pwszSearchCatalogsInDir);
pwszSearchCatalogsInDir = NULL;
FindClose(hFindHandleCatalogsInDir);
hFindHandleCatalogsInDir = INVALID_HANDLE_VALUE;
memset(&FindDataCatalogsInDir, 0, sizeof(FindDataCatalogsInDir));
//
// Construct the new search string which point to the temp dir
//
if (NULL == (pwszSearchCatalogsInDir = _CatAdminCreatePath(
pwszTempDir,
L"*",
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Add each catalog in the temp dir to the database
//
hFindHandleCatalogsInDir = FindFirstFileU(
pwszSearchCatalogsInDir,
&FindDataCatalogsInDir);
if (hFindHandleCatalogsInDir == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
//
// no files found
//
if ((dwErr == ERROR_NO_MORE_FILES) ||
(dwErr == ERROR_FILE_NOT_FOUND))
{
SetLastError(0);
}
else
{
CATADMIN_LOGERR_LASTERR()
goto ErrorFindFirstFile;
}
}
else
{
while (1)
{
//
// Only care about files
//
if (!(FindDataCatalogsInDir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
//
// Construct fully qualified path name to catalog file
//
if (NULL == (pwszCatalogFile = _CatAdminCreatePath(
pwszTempDir,
FindDataCatalogsInDir.cFileName,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
hCatInfo = CryptCATAdminAddCatalog(
hCatAdmin,
pwszCatalogFile,
FindDataCatalogsInDir.cFileName,
NULL);
if (hCatInfo != NULL)
{
CryptCATAdminReleaseCatalogContext(
hCatAdmin,
hCatInfo,
NULL);
hCatInfo = NULL;
}
else
{
// Log error
CATADMIN_LOGERR_LASTERR()
}
free(pwszCatalogFile);
pwszCatalogFile = NULL;
}
//
// Get next catalog file
//
if (!FindNextFileU(hFindHandleCatalogsInDir, &FindDataCatalogsInDir))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
SetLastError(0);
break;
}
else
{
CATADMIN_LOGERR_LASTERR()
goto ErrorFindNextFile;
}
}
}
}
CommonReturn:
dwErr = GetLastError();
if (pwszSubDir != NULL)
{
free(pwszSubDir);
}
if (pwszCatalogFile != NULL)
{
free(pwszCatalogFile);
}
if (pwszSearchCatalogsInDir != NULL)
{
free(pwszSearchCatalogsInDir);
}
if (pwszTempDir != NULL)
{
I_RecursiveDeleteDirectory(pwszTempDir);
free(pwszTempDir);
}
if (pwszTempCatalogFile != NULL)
{
free(pwszTempCatalogFile);
}
if (hFindHandleCatalogsInDir != INVALID_HANDLE_VALUE)
{
FindClose(hFindHandleCatalogsInDir);
}
if (hCatAdmin != NULL)
{
CryptCATAdminReleaseContext(hCatAdmin, NULL);
}
SetLastError(dwErr);
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindFirstFile)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindNextFile)
}
//---------------------------------------------------------------------------------------
//
// CatAdminDllMain
//
//---------------------------------------------------------------------------------------
BOOL WINAPI
CatAdminDllMain(
HANDLE hInstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
BOOL fRet = TRUE;
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
fRet = _CatAdminSetupDefaults();
break;
case DLL_PROCESS_DETACH:
_CatAdminCleanupDefaults();
break;
}
return(fRet);
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
// Internal functions
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//
// _CatAdminSetupDefaults
//
//---------------------------------------------------------------------------------------
BOOL
_CatAdminSetupDefaults(void)
{
BOOL fRet = TRUE;
WCHAR wszDefaultSystemDir[MAX_PATH + 1];
//
// Get System default directory
//
wszDefaultSystemDir[0] = NULL;
if (0 == GetSystemDirectoryW(wszDefaultSystemDir, MAX_PATH))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorSystemError;
}
//
// Get catalog file base directory
//
if (NULL == (gpwszCatalogFileBaseDirectory =
_CatAdminCreatePath(
wszDefaultSystemDir,
WSZ_CATALOG_FILE_BASE_DIRECTORY,
TRUE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Get database file base directory
//
if (NULL == (gpwszDatabaseFileBaseDirectory =
_CatAdminCreatePath(
wszDefaultSystemDir,
WSZ_DATABASE_FILE_BASE_DIRECTORY,
TRUE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
CommonReturn:
return(fRet);
ErrorReturn:
if (gpwszCatalogFileBaseDirectory != NULL)
{
free(gpwszCatalogFileBaseDirectory);
gpwszCatalogFileBaseDirectory = NULL;
}
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorSystemError);
}
//---------------------------------------------------------------------------------------
//
// _CatAdminCleanupDefaults
//
//---------------------------------------------------------------------------------------
void _CatAdminCleanupDefaults(void)
{
if (gpwszCatalogFileBaseDirectory != NULL)
{
free(gpwszCatalogFileBaseDirectory);
gpwszCatalogFileBaseDirectory = NULL;
}
if (gpwszDatabaseFileBaseDirectory != NULL)
{
free(gpwszDatabaseFileBaseDirectory);
gpwszDatabaseFileBaseDirectory = NULL;
}
}
//---------------------------------------------------------------------------------------
//
// _CatAdminTimeStampFilesInSync
//
//---------------------------------------------------------------------------------------
BOOL
_CatAdminTimeStampFilesInSync(
LPWSTR pwszDatabaseGUID,
BOOL *pfInSync)
{
LPWSTR pwszCatalogFileDir = NULL;
LPWSTR pwszDatabaseFileDir = NULL;
BOOL fRet = TRUE;
*pfInSync = FALSE;
//
// Construct full subdir path to Catalog files TimeStamp location
//
if (NULL == (pwszCatalogFileDir = _CatAdminCreatePath(
gpwszCatalogFileBaseDirectory,
pwszDatabaseGUID,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Construct full subdir path to Database files TimeStamp location
//
if (NULL == (pwszDatabaseFileDir = _CatAdminCreatePath(
gpwszDatabaseFileBaseDirectory,
pwszDatabaseGUID,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
fRet = TimeStampFile_InSync(
pwszCatalogFileDir,
pwszDatabaseFileDir,
pfInSync);
CommonReturn:
if (pwszCatalogFileDir != NULL)
{
free(pwszCatalogFileDir);
}
if (pwszDatabaseFileDir != NULL)
{
free(pwszDatabaseFileDir);
}
return(fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
}
//---------------------------------------------------------------------------------------
//
// _CatAdminRegisterForChangeNotification
//
//---------------------------------------------------------------------------------------
BOOL
_CatAdminRegisterForChangeNotification(
CRYPT_CAT_ADMIN *pCatAdmin
)
{
BOOL fRet = TRUE;
DWORD dwErr = 0;
//
// See if already registered
//
if (pCatAdmin->fRegisteredForChangeNotification)
{
goto CommonReturn;
}
//
// NOTE:
// Currently the service ignores the pwszSubSysGUID when registering a change
// notification because it DOES NOT do notifications on a per pwszSubSysDir basis...
// it really should at some point.
// When it does start to do notifications on per pwszSubSysGUID this will need to
// change. CryptCatAdminAcquireContext can be called with a NULL subSysGUID,
// in which case all SubSysDirs are used, so we would need to register a
// change notification for all of them.
//
//
// Register the event with the DB process, so the DB process can SetEvent() it
// when a changed occurs
//
if (0 != (dwErr = Client_SSCatDBRegisterForChangeNotification(
(DWORD_PTR) pCatAdmin->hClearCacheEvent,
0,
pCatAdmin->pwszSubSysGUID,
FALSE)))
{
CATADMIN_SETERR_LOG_RETURN(dwErr, ErrorCatDBProcess)
}
pCatAdmin->fRegisteredForChangeNotification = TRUE;
CommonReturn:
return fRet;
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCatDBProcess)
}
//---------------------------------------------------------------------------------------
//
// _CatAdminFreeCachedCatalogs
//
//---------------------------------------------------------------------------------------
BOOL
_CatAdminFreeCachedCatalogs(
CRYPT_CAT_ADMIN *pCatAdmin)
{
BOOL fRet = TRUE;
LIST_NODE *pListNode = NULL;
CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
//
// NOTE: the caller of this function must have entered the Critical Section for
// the CatAdminContext
//
//
// Enumerate through all the cached CATALOG_INFO_CONTEXTs and free all the
// resources for each
//
pListNode = LIST_GetFirst(&(pCatAdmin->CatalogInfoContextList));
while (pListNode != NULL)
{
pCatInfoContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
free(pCatInfoContext->pwszCatalogFile);
CertFreeCTLContext(pCatInfoContext->pCTLContext);
UnmapViewOfFile(pCatInfoContext->pbMappedFile);
CloseHandle(pCatInfoContext->hMappedFile);
free(pCatInfoContext);
pListNode = LIST_GetNext(pListNode);
}
LIST_RemoveAll(&(pCatAdmin->CatalogInfoContextList));
return(fRet);
}
//---------------------------------------------------------------------------------------
//
// _CatAdminWaitOrTimerCallback
//
//---------------------------------------------------------------------------------------
VOID CALLBACK
_CatAdminWaitOrTimerCallback(
PVOID lpParameter,
BOOLEAN TimerOrWaitFired)
{
CRYPT_CAT_ADMIN *pCatAdmin = (CRYPT_CAT_ADMIN *) lpParameter;
int i = 0;
LIST_NODE *pListNode = NULL;
CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
//
// Enter the CS before wacking anything
//
__try
{
EnterCriticalSection(&(pCatAdmin->CriticalSection));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
SetLastError(GetExceptionCode());
CATADMIN_LOGERR_LASTERR()
return;
}
pCatAdmin->fCSEntered = TRUE;
//
// If there is an open ref count, then we can't clean up
//
if (pCatAdmin->nOpenCatInfoContexts != 0)
{
pCatAdmin->fCSEntered = FALSE;
LeaveCriticalSection(&(pCatAdmin->CriticalSection));
return;
}
//
// Cleanup all the cached CATALOG_INFO_CONTEXTs
//
_CatAdminFreeCachedCatalogs(pCatAdmin);
pCatAdmin->fCSEntered = FALSE;
LeaveCriticalSection(&(pCatAdmin->CriticalSection));
}
//---------------------------------------------------------------------------------------
//
// _CatAdminAddCatalogsToCache
//
//---------------------------------------------------------------------------------------
BOOL
_CatAdminAddCatalogsToCache(
CRYPT_CAT_ADMIN *pCatAdmin,
LPWSTR pwszSubSysGUID,
CRYPT_DATA_BLOB *pCryptDataBlob,
LIST_NODE **ppFirstListNodeAdded)
{
BOOL fRet = TRUE;
LPWSTR pwszCopy = NULL;
DWORD i;
DWORD dwNumCatalogNames = 0;
LPWSTR *ppwszCatalogNames = NULL;
DWORD dwErr = 0;
LIST_NODE *pListNode = NULL;
LPWSTR pwszSubSysDir = NULL;
BOOL fFirstCatalogAdded = FALSE;
if (ppFirstListNodeAdded != NULL)
{
*ppFirstListNodeAdded = NULL;
}
if (NULL == (pwszSubSysDir = _CatAdminCreatePath(
gpwszCatalogFileBaseDirectory,
pwszSubSysGUID,
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// Call DB process and get list of catalogs into ppwszCatalogNames
//
// NOTE: the order in which the service adds CatNames to the list results in
// only the first CatName of the list being guaranteed to contain the
// hash... all other CatNames may or may not contain the hash. Which
// is OK because this code only assumes the first CatName contains the
// hash, and then searches all other CatNames for the hash before returning them.
//
if (0 != (dwErr = Client_SSCatDBEnumCatalogs(
0,
pwszSubSysGUID,
pCryptDataBlob->pbData,
pCryptDataBlob->cbData,
&dwNumCatalogNames,
&ppwszCatalogNames)))
{
CATADMIN_SETERR_LOG_RETURN(dwErr, ErrorServiceError)
}
//
// Loop for each catalog and create the CTL context
//
for (i=0; i<dwNumCatalogNames; i++)
{
//
// Make a copy of the catalog file name
//
if (NULL == (pwszCopy = _CatAdminCreatePath(
pwszSubSysDir,
ppwszCatalogNames[i],
FALSE)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
if (!_CatAdminAddSingleCatalogToCache(
pCatAdmin,
pwszCopy,
&pListNode))
{
//
// if this isn't the first catalog, then continue since the
// macro operation may still succeed without the current catalog
//
if (i != 0)
{
CATADMIN_LOGERR_LASTERR()
continue;
}
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
//
// This will only be set for the first catalog added,
// as per the NOTE above
//
if ((ppFirstListNodeAdded != NULL) &&
(*ppFirstListNodeAdded == NULL))
{
*ppFirstListNodeAdded = pListNode;
}
}
CommonReturn:
if (ppwszCatalogNames != NULL)
{
for (i=0; i<dwNumCatalogNames; i++)
{
MIDL_user_free(ppwszCatalogNames[i]);
}
MIDL_user_free(ppwszCatalogNames);
}
if (pwszSubSysDir != NULL)
{
free(pwszSubSysDir);
}
return(fRet);
ErrorReturn:
if (pwszCopy != NULL)
{
free(pwszCopy);
}
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorServiceError)
}
//---------------------------------------------------------------------------------------
//
// _CatAdminAddSingleCatalogToCache
//
//---------------------------------------------------------------------------------------
BOOL
_CatAdminAddSingleCatalogToCache(
CRYPT_CAT_ADMIN *pCatAdmin,
LPWSTR pwszCatalog,
LIST_NODE **ppListNodeAdded)
{
BOOL fRet = TRUE;
DWORD dwErr = 0;
LIST_NODE *pListNode = NULL;
CATALOG_INFO_CONTEXT *pCatInfoContext = NULL;
CATALOG_INFO_CONTEXT *pCatInfoContextAdd = NULL;
*ppListNodeAdded = NULL;
//
// If there is already a copy of this catalog, then just get out
//
pListNode = LIST_GetFirst(&(pCatAdmin->CatalogInfoContextList));
while (pListNode != NULL)
{
pCatInfoContext = (CATALOG_INFO_CONTEXT *) LIST_GetElement(pListNode);
if (_wcsicmp(pCatInfoContext->pwszCatalogFile, pwszCatalog) == 0)
{
*ppListNodeAdded = pListNode;
goto CommonReturn;
}
pListNode = LIST_GetNext(pListNode);
}
//
// Allocate space for a new cached catalog context
//
if (NULL == (pCatInfoContextAdd = (CATALOG_INFO_CONTEXT *)
malloc(sizeof(CATALOG_INFO_CONTEXT))))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
memset(pCatInfoContextAdd, 0, sizeof(CATALOG_INFO_CONTEXT));
pCatInfoContextAdd->fResultOfAdd = FALSE;
//
// Open, create a file mapping, and create the CTL context for
// the catalog file
//
if (!CatUtil_CreateCTLContextFromFileName(
pwszCatalog,
&pCatInfoContextAdd->hMappedFile,
&pCatInfoContextAdd->pbMappedFile,
&pCatInfoContextAdd->pCTLContext,
TRUE))
{
CATADMIN_LOGERR_LASTERR()
ErrLog_LogString(NULL, L"The following file was not found - ", pwszCatalog, TRUE);
goto ErrorReturn;
}
pCatInfoContextAdd->pwszCatalogFile = pwszCatalog;
//
// Add to the list of cached catalog contexts
//
if (NULL == (pListNode = LIST_AddTail(
&(pCatAdmin->CatalogInfoContextList),
pCatInfoContextAdd)))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
*ppListNodeAdded = pListNode;
CommonReturn:
return(fRet);
ErrorReturn:
dwErr = GetLastError();
if (pCatInfoContextAdd != NULL)
{
if (pCatInfoContextAdd->pCTLContext != NULL)
{
CertFreeCTLContext(pCatInfoContextAdd->pCTLContext);
}
if (pCatInfoContextAdd->pbMappedFile != NULL)
{
UnmapViewOfFile(pCatInfoContextAdd->pbMappedFile);
}
if (pCatInfoContextAdd->hMappedFile != NULL)
{
CloseHandle(pCatInfoContextAdd->hMappedFile);
}
free(pCatInfoContextAdd);
}
SetLastError(dwErr);
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory)
}
//---------------------------------------------------------------------------------------
//
// _CatAdminMigrateCatalogDatabase
//
// This migration code deals with very old catalog databases. In the olden days, the
// catroot dir location could be specified by a particular registry key... that is no
// longer true. So, if an old system is being upgraded that has the registry key, this
// code moves all the catalog files from the location specified by the registry key to
// the %SystemDefaultDir%\Catroot dir. Then it shwacks the registry key.
//
//---------------------------------------------------------------------------------------
BOOL
_CatAdminMigrateCatalogDatabase(
LPWSTR pwszFrom,
LPWSTR pwszTo)
{
DWORD dwAttr = 0;
WCHAR wszFrom[MAX_PATH];
WCHAR wszTo[MAX_PATH];
//
// If they are the same dir then just get out
//
if (((wcslen(pwszFrom) + 1) > MAX_PATH) ||
((wcslen(pwszFrom) + 1) > MAX_PATH))
{
return TRUE;
}
wcscpy(wszFrom, pwszFrom);
wcscpy(wszTo, pwszTo);
if (wszFrom[wcslen(wszFrom) - 1] != L'\\')
{
wcscat(wszFrom, L"\\");
}
if (wszTo[wcslen(wszTo) - 1] != L'\\')
{
wcscat(wszTo, L"\\");
}
if (_wcsicmp(wszFrom, wszTo) == 0)
{
return TRUE;
}
//
// if the pwszTo dir already exists, then don't do a thing.
//
dwAttr = GetFileAttributesU(pwszTo);
if (0xFFFFFFFF != dwAttr)
{
if (FILE_ATTRIBUTE_DIRECTORY & dwAttr)
{
//
// dir already exists...
//
return TRUE;
}
else
{
//
// something exists with pwszTo name, but it isn't a dir
//
CATADMIN_LOGERR_LASTERR()
return FALSE;
}
}
//
// if the pwszFrom dir does not exist, then don't do a thing.
//
dwAttr = GetFileAttributesU(pwszFrom);
if ((0xFFFFFFFF == dwAttr) || (!(FILE_ATTRIBUTE_DIRECTORY & dwAttr)))
{
return TRUE;
}
if (!_CatAdminRecursiveCreateDirectory(pwszTo, NULL))
{
CATADMIN_LOGERR_LASTERR()
return FALSE;
}
if (!I_RecursiveCopyDirectory(pwszFrom, pwszTo))
{
CATADMIN_LOGERR_LASTERR()
return FALSE;
}
//
// Don't check for error on delete since this operation is NOT mandatory
//
I_RecursiveDeleteDirectory(pwszFrom);
return TRUE;
}
//---------------------------------------------------------------------------------------
//
// _CatAdminBToHex
//
//---------------------------------------------------------------------------------------
WCHAR rgHexDigit[] = { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7',
L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' };
void
_CatAdminBToHex (
LPBYTE pbDigest,
DWORD iByte,
LPWSTR pwszHashTag)
{
DWORD iTag;
DWORD iHexDigit1;
DWORD iHexDigit2;
iTag = iByte * 2;
iHexDigit1 = (pbDigest[iByte] & 0xF0) >> 4;
iHexDigit2 = (pbDigest[iByte] & 0x0F);
pwszHashTag[iTag] = rgHexDigit[iHexDigit1];
pwszHashTag[iTag + 1] = rgHexDigit[iHexDigit2];
}
//---------------------------------------------------------------------------------------
//
// _CatAdminCreateHashTag
//
//---------------------------------------------------------------------------------------
BOOL
_CatAdminCreateHashTag(
BYTE *pbHash,
DWORD cbHash,
LPWSTR *ppwszHashTag,
CRYPT_DATA_BLOB *pCryptDataBlob)
{
DWORD cwTag;
DWORD cCount;
cwTag = ((cbHash * 2) + 1);
if (NULL == (*ppwszHashTag = (LPWSTR) malloc(cwTag * sizeof(WCHAR))))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
CATADMIN_LOGERR_LASTERR()
return(FALSE);
}
for (cCount = 0; cCount < cbHash; cCount++)
{
_CatAdminBToHex(pbHash, cCount, *ppwszHashTag);
}
(*ppwszHashTag)[cwTag - 1] = L'\0';
pCryptDataBlob->pbData = (BYTE *) *ppwszHashTag;
pCryptDataBlob->cbData = cwTag * sizeof(WCHAR);
return (TRUE);
}
//---------------------------------------------------------------------------------------
//
// _CatAdminRecursiveCreateDirectory
//
//---------------------------------------------------------------------------------------
BOOL
_CatAdminRecursiveCreateDirectory(
IN LPCWSTR pwszDir,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
{
BOOL fResult;
DWORD dwAttr;
DWORD dwErr;
LPCWSTR pwsz;
DWORD cch;
WCHAR wch;
LPWSTR pwszParent = NULL;
//
// if last char is a '\', then just strip it and recurse
//
if (pwszDir[wcslen(pwszDir) - 1] == L'\\')
{
cch = wcslen(pwszDir);
if (NULL == (pwszParent = (LPWSTR) malloc(cch * sizeof(WCHAR))))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
memcpy(pwszParent, pwszDir, (cch - 1) * sizeof(WCHAR));
pwszParent[cch - 1] = L'\0';
fResult = _CatAdminRecursiveCreateDirectory(
pwszParent,
lpSecurityAttributes);
goto CommonReturn;
}
//
// See if dir already exists
//
dwAttr = GetFileAttributesU(pwszDir);
if (0xFFFFFFFF != dwAttr)
{
if (FILE_ATTRIBUTE_DIRECTORY & dwAttr)
{
return TRUE;
}
CATADMIN_LOGERR_LASTERR()
goto InvalidDirectoryAttr;
}
//
// If it was an error other than file/path not found, error out
//
dwErr = GetLastError();
if (!(ERROR_PATH_NOT_FOUND == dwErr || ERROR_FILE_NOT_FOUND == dwErr))
{
CATADMIN_LOGERR_LASTERR()
goto GetFileAttrError;
}
//
// Try creating the new dir
//
if (CreateDirectoryU(
pwszDir,
lpSecurityAttributes))
{
SetFileAttributesU(pwszDir, FILE_ATTRIBUTE_NORMAL);
return TRUE;
}
dwErr = GetLastError();
if (!(ERROR_PATH_NOT_FOUND == dwErr || ERROR_FILE_NOT_FOUND == dwErr))
{
CATADMIN_LOGERR_LASTERR()
goto CreateDirectoryError;
}
//
// Peal off the last path name component
//
cch = wcslen(pwszDir);
pwsz = pwszDir + cch;
while (L'\\' != *pwsz)
{
if (pwsz == pwszDir)
{
// Path didn't have a \.
CATADMIN_SETERR_LOG_RETURN(ERROR_BAD_PATHNAME, BadDirectoryPath)
}
pwsz--;
}
cch = (DWORD)(pwsz - pwszDir);
if (0 == cch)
{
// Detected leading \Path
CATADMIN_SETERR_LOG_RETURN(ERROR_BAD_PATHNAME, BadDirectoryPath)
}
// Check for leading \\ or x:\.
wch = *(pwsz - 1);
if ((1 == cch && L'\\' == wch) || (2 == cch && L':' == wch))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_BAD_PATHNAME, BadDirectoryPath)
}
if (NULL == (pwszParent = (LPWSTR) malloc((cch + 1) * sizeof(WCHAR))))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
memcpy(pwszParent, pwszDir, cch * sizeof(WCHAR));
pwszParent[cch] = L'\0';
if (!_CatAdminRecursiveCreateDirectory(pwszParent, lpSecurityAttributes))
{
CATADMIN_LOGERR_LASTERR()
goto ErrorReturn;
}
if (!CreateDirectoryU(
pwszDir,
lpSecurityAttributes))
{
CATADMIN_LOGERR_LASTERR()
goto CreateDirectory2Error;
}
SetFileAttributesU(pwszDir, FILE_ATTRIBUTE_NORMAL);
fResult = TRUE;
CommonReturn:
if (pwszParent != NULL)
{
free(pwszParent);
}
return fResult;
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_TRUST, InvalidDirectoryAttr)
TRACE_ERROR_EX(DBG_SS_TRUST, GetFileAttrError)
TRACE_ERROR_EX(DBG_SS_TRUST, CreateDirectoryError)
TRACE_ERROR_EX(DBG_SS_TRUST, BadDirectoryPath)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorMemory)
TRACE_ERROR_EX(DBG_SS_TRUST, CreateDirectory2Error)
}
//---------------------------------------------------------------------------------------
//
// _CatAdminCreatePath
//
//---------------------------------------------------------------------------------------
LPWSTR
_CatAdminCreatePath(
IN LPCWSTR pwsz1,
IN LPCWSTR pwsz2,
IN BOOL fAddEndingSlash
)
{
LPWSTR pwszTemp = NULL;
int nTotalLen = 0;
int nLenStr1 = 0;
//
// Calculate the length of the resultant string as the sum of the length
// of pwsz1, length of pwsz2, a NULL char, and a possible extra '\' char
//
nLenStr1 = wcslen(pwsz1);
nTotalLen = nLenStr1 + wcslen(pwsz2) + 2;
if (fAddEndingSlash)
{
nTotalLen++;
}
//
// Allocate the string and copy pwsz1 into the buffer
//
if (NULL == (pwszTemp = (LPWSTR) malloc(sizeof(WCHAR) * nTotalLen)))
{
CATADMIN_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory)
}
wcscpy(pwszTemp, pwsz1);
//
// Add the extra '\' if needed
//
if (pwsz1[nLenStr1 - 1] != L'\\')
{
wcscat(pwszTemp, L"\\");
}
//
// Tack on pwsz2
//
wcscat(pwszTemp, pwsz2);
if (fAddEndingSlash)
{
wcscat(pwszTemp, L"\\");
}
CommonReturn:
return (pwszTemp);
ErrorReturn:
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMemory)
}