/*++ Copyright (c) 1996, 1997 Microsoft Corporation Module Name: catdbsvc.cpp Abstract: This module contains routines associated with the service side of the catalog database Author: Reid Kuhn (reidk) 19-Nov-97 --*/ /* This comment section gives a picture of an example catalog database, with example catalog files added and the resulting database tables. The database schema can be seen clearly by looking at the picture of the database tables. This comment section also contains psuedo code for the add catalog algorithm. Catalogs added to the catalog database are stored in the FILE SYSTEM -------------------------------------------------------------------- -------- -------- -------- -------- -------- -------- Catname: | CatA | | CatB | | CatC | | CatD | | CatE | | CatF | -------- -------- -------- -------- -------- -------- HashList: | 111 | | 111 | | 444 | | 333 | | 333 | | 555 | | 222 | | 222 | | | | | | 555 | | | | 333 | | | | | | | | | | | -------- -------- -------- -------- -------- -------- Resulting Database Tables (above catalogs where added in order) -------------------------------------------------------------------- HashCatNameTable ---------------------------------- | HashCol | CatNameListCol | |-----------|--------------------| | 111 | CatA - CatB | | 222 | CatA - CatB | | 333 | CatA - CatD - CatE | | 444 | CatC | | 555 | CatE - CatF | ---------------------------------- CatNameBuddyTable --------------------------------------------- | CatNameCol | BuddyListCol | --------------------------------------------- | CatA | CatB - CatD - CatE | | CatB | CatA | | CatD | CatA - CatB - CatE | | CatE | CatA - CatB - CatD - CatF | | CatF | CatE - CatA - CatB - CatD | --------------------------------------------- Add Catalog Algorithm --------------------- AddCat() { For each hash contained in catalog { if ( is not contained in HashCol of HashCatNameTable) { add row to HashCatNameTable with in HashCol and in CatNameListCol } else { create row in CatNameBuddyTable with in CatNameCol for each CatName contained in 's CatNameListCol { if ( is not contained in CatNameCol of CatNameBuddyTable { create row in CatNameBuddyTable with in CatNameCol } add to 's BuddyListCol for each CatName contained in 's BuddyListCol - (may be empty) { add to 's BuddyListCol } add to 's BuddyListCol } add to 's CatNameListCol } } } */ #include #include #include #include #include #include #include #include "catdb.h" // header file generated by MIDL compiler #include "dbutils.h" #include "voidlist.h" #include "catutil.h" #include "resource.h" #include "errlog.h" #include "mscat.h" #define CATDB_MAX_CATNAME_LENGTH 255 #define WSZ_REG_TEMP_FILES_KEY L"Software\\Microsoft\\Cryptography\\CatDBTempFiles" #define WSZ_REG_CATALOGDB_VALUES L"Software\\Microsoft\\Cryptography\\CatalogDB" #define WSZ_REG_CALLBACK_TIMER L"CallbackTime" #define WSZ_REG_DATABASE_TIMEOUT L"DatabaseTimeout" #define SZ_CATALOG_FILE_BASE_DIRECTORY "CatRoot" #define WSZ_CATALOG_FILE_BASE_DIRECTORY L"CatRoot" #define SZ_DATABASE_FILE_BASE_DIRECTORY "CatRoot2" #define WSZ_DATABASE_FILE_BASE_DIRECTORY L"CatRoot2" #define SZ_DBFILE_NAME "catdb" #define WSZ_DBFILE_NAME L"catdb" #define WSZ_TIME_STAMP_FILE L"TimeStamp" #define CATDBSVC_LOGERR_LASTERR() ErrLog_LogError(NULL, \ ERRLOG_CLIENT_ID_CATDBSCV, \ __LINE__, \ 0, \ FALSE, \ FALSE); #define CATDBSVC_SETERR_LOG_RETURN(x, y) SetLastError(x); \ ErrLog_LogError(NULL, \ ERRLOG_CLIENT_ID_CATDBSCV, \ __LINE__, \ 0, \ FALSE, \ FALSE); \ goto y; #define CATDBSVC_LOGERR(x) ErrLog_LogError(NULL, \ ERRLOG_CLIENT_ID_CATDBSCV, \ __LINE__, \ x, \ FALSE, \ FALSE); #define CATDBSVC_LOGWARN(x) ErrLog_LogError(NULL, \ ERRLOG_CLIENT_ID_CATDBSCV, \ __LINE__, \ x, \ TRUE, \ FALSE); #define ALLOCATION_BLOCK_SIZE 8 typedef struct _JET_DB_STRUCT { LPSTR pszDBFileName; JET_SESID JetSesID; JET_DBID JetDBID; // Hash-CatName Table JET_TABLEID JetHashCatNameTableID; JET_COLUMNID JetHashCatNameTable_HashColumnID; JET_COLUMNID JetHashCatNameTable_CatNameColumnID; // CatName Buddy Table JET_TABLEID JetCatNameBuddyTableID; JET_COLUMNID JetCatNameBuddyTable_CatNameColumnID; JET_COLUMNID JetCatNameBuddyTable_BuddyColumnID; } JET_DB_STRUCT, *PJET_DB_STRUCT; typedef struct _CATALOG_DIR_CACHE_STRUCT { JET_DB_STRUCT JetDBStruct; LPWSTR pwszSubSysGUID; BOOL fDBCurrentlyInUse; BOOL fReadOnly; DWORD dwTimeLastTouched; HANDLE hRegisterWaitForServiceShutdown; } CATALOG_DIR_CACHE_STRUCT, *PCATALOG_DIR_CACHE_STRUCT; typedef struct _NOTIFICATION_STRUCT { DWORD ProcessID; HANDLE hClientProcess; HANDLE hRegisterWaitFor; HANDLE hNotificationHandle; HANDLE hDuplicatedNotificationHandle; LONG lNotificationID; } NOTIFICATION_STRUCT, *PNOTIFICATION_STRUCT; // // Global variables // extern HINSTANCE g_hInst; BOOL g_fDBSvcInitialized = FALSE; CRITICAL_SECTION g_CatDBAddDeleteCS; CRITICAL_SECTION g_CatDBRegisterNotifyCS; CRITICAL_SECTION g_CatDirCashCS; CRITICAL_SECTION g_CatClientCountCS; CRITICAL_SECTION g_InitializeJetCS; CRITICAL_SECTION g_CleanupTempFilesCS; LONG g_lOpenedDBCount = 0; BOOL g_fJetInitialized = FALSE; JET_INSTANCE g_JetInstance = 0; BOOL g_fCleaninUpTempFiles = FALSE; NOTIFICATION_STRUCT *g_rgNotificationStructs = NULL; DWORD g_NumNotificationStructs = 0; LIST g_CatalogDBCacheList; HANDLE g_hCatalogCacheCallbackEvent = NULL; BOOL g_fCatalogCacheCallbackEventSet = FALSE; DWORD g_dwClientCount = 0; LONG g_lNotificationID = 0; LPWSTR g_pwszCatalogFileBaseDirectory = NULL; LPWSTR g_pwszDatabaseFileBaseDirectory = NULL; DWORD g_dwCatalogDatabaseCacheTimeout = (1000 * 60); // default one minute DWORD g_dwCatalogDatabaseCacheCallbackTime= (1000 * 60 * 2); // default two minutes // // Forward declarations // // // General supporting DB file functions // BOOL _CatDBClientEnter(void); void _CatDBClientExit(void); void _CatDBTouchTimeStampFile( LPCWSTR pwszSubSysGUID); BOOL _CatDBInitializeJet( BOOL fInRecursiveCall); BOOL _CatDBTermJet(); BOOL _CatDBAcquireOpenDatabaseFromCache( PJET_DB_STRUCT *ppJetDBStruct, LPCWSTR pwszSubSysGUID, BOOL fReadOnly, BOOL fInRecursiveCall ); BOOL _CatDBReleaseDatabaseToCache( PJET_DB_STRUCT pJetDBStruct ); BOOL _CatDBCloseSingleCachedDatabase( CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct ); BOOL _CatDBCloseCachedDatabases(); VOID CALLBACK _CatDBWaitOrTimerCallback( PVOID lpParameter, BOOLEAN fTimedOut ); // // Supporting functions for s_SSCatDBAddCatalog // DWORD _CatDBAddCatalog( handle_t h, DWORD dwFlags, LPCWSTR pwszSubSysGUID, LPCWSTR pwszCatalogFile, LPCWSTR pwszCatName, BOOL fInRecursiveCall, LPWSTR __RPC_FAR *ppwszCatalogNameUsed); BOOL _CatDBAddCatalogEntriesToDatabase( PJET_DB_STRUCT pJetDBStruct, PCCTL_CONTEXT pCTLContext, LPWSTR pwszNewCatalogName ); BOOL _CatDBAddHashCatNamePair( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob, LPWSTR pwszCatBaseName ); BOOL _CatDBAddNewRowToHashCatNameTable( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob, LPWSTR pwszCatBaseName ); BOOL _CatDBAddValueToExistingHashCatNameRow( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob, LPWSTR pwszCatBaseName ); BOOL _CatDBCatnameAlreadyInHashesListOfCats( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob, LPWSTR pwszCatBaseName ); BOOL _CatDBAddNewRowToCatNameBuddyTableIfNotExists( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatBaseName ); BOOL _CatDBAddNewRowToCatNameBuddyTable( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatBaseName ); BOOL _CatDBAddNameToBuddyList( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszNameToAdd, LPWSTR pwszListToAddTo ); BOOL _CatDBAddWholeBuddyList( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszBuddyToAddTo, LPWSTR pwszBuddyListName ); BOOL _CatDBMoveInUseFileToTempLocation( LPWSTR pwszFile ); void _CatDBCleanupTempFiles(); // // Supporting functions for s_SSCatDBDeleteCatalog // BOOL _CatDBDeleteCatalogEntriesFromDatabase( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatalogName ); BOOL _CatDBRemoveCatNameFromHashesListOfCatNames( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob, LPWSTR pwszCatBaseName ); BOOL _CatDBRemoveCatNameFromMultiValuedColumn( PJET_DB_STRUCT pJetDBStruct, JET_TABLEID jetTableID, JET_COLUMNID jetColumnID, LPWSTR pwszCatBaseName ); BOOL _CatDBRemoveCatNameFromCatNameTable( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatBaseName ); BOOL _CatDBRemoveCatNameFromBuddyTable( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatBaseName ); // // Supporting functions for s_SSCatDBEnumCatalogs // BOOL _CatDBAddCatNameAndCatNamesBuddyListToReturnCatNames( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatName, DWORD __RPC_FAR *pdwNumCatalogNames, LPWSTR __RPC_FAR *__RPC_FAR *pppwszCatalogNames, BOOL fRecursiveCall); BOOL _CatDBAddCatNameToReturnBuddyListIfNotExist( LPWSTR pwszBuddy, DWORD __RPC_FAR *pdwNumCatalogNames, LPWSTR __RPC_FAR *__RPC_FAR *pppwszCatalogNames ); // // More general supporting functions // JET_ERR _CatDBSeekInCatNameBuddyTable( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszBuddyRow ); JET_ERR _CatDBSeekInHashCatNameTable( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob ); void _CatDBNotifyClients(void); LPWSTR _CatDBCreateNewCatalogFileName( LPCWSTR pwszCatalogFileDir, LPCWSTR pwszCatName, BOOL *pfFileAlreadyExists ); BOOL _CatDBFindAndDecodeHashInCatEntry( PCTL_ENTRY pctlEntry, SPC_INDIRECT_DATA_CONTENT **ppIndirectData ); DWORD _CatDBMapJetError( JET_ERR jerr); BOOL _CatDBJET_errFailure( JET_ERR jerr); BOOL _CatDBInitJetDatabaseParams( JET_INSTANCE *pJetInstance); BOOL _CatDBAttachAndOpenDatabase( JET_DB_STRUCT *pJetDBStruct, BOOL fReadOnly); BOOL _CatDBCloseDatabaseFile( PJET_DB_STRUCT pJetDBStruct); BOOL _CatDBCatalogFileAlreadyInstalled( LPCWSTR pwszCatalogToBeAdded, LPCWSTR pwszExistingCatalog); #define LOGEVENT_STRING_PARAMTYPE 1 #define LOGEVENT_INT_PARAMTYPE 2 #define LOGEVENT_NONE_PARAMTYPE 3 // // Use these for memory that is transferred across an LRPC call // extern "C" { extern void __RPC_FAR * __RPC_API midl_user_allocate(size_t len); extern void __RPC_API midl_user_free(void __RPC_FAR * ptr); extern void __RPC_FAR * __RPC_API midl_user_reallocate(void __RPC_FAR * ptr, size_t len); } // // general allocation routines // void * _CatDBAlloc(size_t len) { void *temp; temp = LocalAlloc(LMEM_ZEROINIT, len); if (temp == NULL) { SetLastError(E_OUTOFMEMORY); } return(temp); } void * _CatDBReAlloc(void *p, size_t len) { void *temp; temp = LocalReAlloc(p, len, LMEM_MOVEABLE | LMEM_ZEROINIT); if (temp == NULL) { SetLastError(E_OUTOFMEMORY); } return(temp); } void _CatDBFree(void *p) { if (p != NULL) { LocalFree(p); } } LPSTR _CatDBGetCatrootDirA() { LPSTR pszTempPath = NULL; char szDefaultSystemDir[MAX_PATH + 1]; DWORD dwLength; // // Get System default directory // szDefaultSystemDir[0] = NULL; if (0 == GetSystemDirectoryA(&szDefaultSystemDir[0], MAX_PATH)) { CATDBSVC_LOGERR_LASTERR() return (NULL); } // // Calculate length // dwLength = strlen(szDefaultSystemDir) + strlen(SZ_DATABASE_FILE_BASE_DIRECTORY) + 3; // // Allocate space for the full path // if (NULL == (pszTempPath = (LPSTR) malloc(sizeof(char) * dwLength))) { CATDBSVC_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory) return (NULL); } // // Make the path // strcpy(pszTempPath, szDefaultSystemDir); if ((pszTempPath[0]) && (pszTempPath[strlen(&pszTempPath[0]) - 1] != '\\')) { strcat(pszTempPath, "\\"); } strcat(pszTempPath, SZ_DATABASE_FILE_BASE_DIRECTORY); strcat(pszTempPath, "\\"); ErrorMemory: return (pszTempPath); } LPWSTR _CatDBGetCatrootDirW( BOOL fCatroot2) { LPWSTR pwszTempPath = NULL; WCHAR wszDefaultSystemDir[MAX_PATH + 1]; DWORD dwLength; // // Get System default directory // wszDefaultSystemDir[0] = NULL; if (0 == GetSystemDirectoryW(&wszDefaultSystemDir[0], MAX_PATH)) { CATDBSVC_LOGERR_LASTERR() return (NULL); } // // Calculate length // dwLength = wcslen(wszDefaultSystemDir) + 3; if (fCatroot2) { dwLength += wcslen(WSZ_DATABASE_FILE_BASE_DIRECTORY); } else { dwLength += wcslen(WSZ_CATALOG_FILE_BASE_DIRECTORY); } // // Allocate space for the full path // if (NULL == (pwszTempPath = (LPWSTR) malloc(sizeof(WCHAR) * dwLength))) { CATDBSVC_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorMemory) return (NULL); } // // Make the path // wcscpy(pwszTempPath, wszDefaultSystemDir); if ((pwszTempPath[0]) && (pwszTempPath[wcslen(&pwszTempPath[0]) - 1] != L'\\')) { wcscat(pwszTempPath, L"\\"); } if (fCatroot2) { wcscat(pwszTempPath, WSZ_DATABASE_FILE_BASE_DIRECTORY); } else { wcscat(pwszTempPath, WSZ_CATALOG_FILE_BASE_DIRECTORY); } wcscat(pwszTempPath, L"\\"); ErrorMemory: return (pwszTempPath); } LPWSTR _CatDBCreatePath( IN LPCWSTR pwsz1, IN LPCWSTR pwsz2) { LPWSTR pwszTemp = NULL; int nTotalLen = 0; int nLenStr1 = 0; // // Calculate the length of the resultant string as the sum of the length // of psz1, a '\', the length of psz2, and a NULL char // nLenStr1 = wcslen(pwsz1); nTotalLen = nLenStr1 + wcslen(pwsz2) + 2; // // Allocate the string and copy pwsz1 into the buffer // if (NULL == (pwszTemp = (LPWSTR) malloc(sizeof(WCHAR) * nTotalLen))) { CATDBSVC_SETERR_LOG_RETURN(ERROR_NOT_ENOUGH_MEMORY, ErrorReturn) } wcscpy(pwszTemp, pwsz1); // // Add the extra '\' if needed // if (pwsz1[nLenStr1 - 1] != L'\\') { wcscat(pwszTemp, L"\\"); } // // Tack on psz2 // wcscat(pwszTemp, pwsz2); CommonReturn: return (pwszTemp); ErrorReturn: goto CommonReturn; } BOOL _CatDBDeleteFiles( IN LPCWSTR pwszPath, IN LPCWSTR pwszSearch) { BOOL fRet = TRUE; HANDLE hFindHandle = INVALID_HANDLE_VALUE; WIN32_FIND_DATAW FindData; DWORD dwErr; LPWSTR pwszDelete = NULL; // // Do the initial find // hFindHandle = FindFirstFileW(pwszSearch, &FindData); if (hFindHandle == INVALID_HANDLE_VALUE) { // // See if a real error occurred, or just no files // dwErr = GetLastError(); if ((dwErr == ERROR_NO_MORE_FILES) || (dwErr == ERROR_FILE_NOT_FOUND)) { // // There are no files of this type to delete // return (TRUE); } else { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } while (1) { // // Only care about files // if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { pwszDelete = _CatDBCreatePath(pwszPath, FindData.cFileName); if (pwszDelete == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } if (!DeleteFileW(pwszDelete)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } free(pwszDelete); pwszDelete = NULL; } // // Get next file // if (!FindNextFileW(hFindHandle, &FindData)) { if (GetLastError() == ERROR_NO_MORE_FILES) { break; } else { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } } CommonReturn: if (pwszDelete != NULL) { free(pwszDelete); } return (fRet); ErrorReturn: fRet = FALSE; goto CommonReturn; } BOOL _CatDBDeleteJetFiles() { BOOL fRet = TRUE; LPWSTR pwszCatroot2 = NULL; LPWSTR pwszDelete = NULL; LPWSTR pwszSearch = NULL; LPWSTR pwszPathName = NULL; HANDLE hFindHandle = INVALID_HANDLE_VALUE; WIN32_FIND_DATAW FindData; DWORD dwErr; // // Get the directory where the jet files live // pwszCatroot2 = _CatDBGetCatrootDirW(TRUE); if (pwszCatroot2 == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // build the search string for jet log files and delete them // (there are two forms of log files). // pwszDelete = _CatDBCreatePath(pwszCatroot2, L"edb*.log"); if (pwszDelete == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } if (!_CatDBDeleteFiles(pwszCatroot2, pwszDelete)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } free(pwszDelete); pwszDelete = NULL; pwszDelete = _CatDBCreatePath(pwszCatroot2, L"res*.log"); if (pwszDelete == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } if (!_CatDBDeleteFiles(pwszCatroot2, pwszDelete)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } free(pwszDelete); pwszDelete = NULL; // // Delete the "catdb" and "timestamp" files in each directory // // // Build a search string for catdb directories // pwszSearch = _CatDBCreatePath(pwszCatroot2, L"{????????????????????????????????????}"); if (pwszSearch == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Do the initial find // hFindHandle = FindFirstFileW(pwszSearch, &FindData); if (hFindHandle == INVALID_HANDLE_VALUE) { // // See if a real error occurred, or just no directories // dwErr = GetLastError(); if ((dwErr == ERROR_NO_MORE_FILES) || (dwErr == ERROR_PATH_NOT_FOUND) || (dwErr == ERROR_FILE_NOT_FOUND)) { // // There are no directories of this form // goto CommonReturn; } else { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } while (1) { // // Only care about directories // if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { pwszPathName = _CatDBCreatePath(pwszCatroot2, FindData.cFileName); if (pwszPathName == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Delete the "catdb" file // pwszDelete = _CatDBCreatePath(pwszPathName, WSZ_DBFILE_NAME); if (pwszDelete == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } DeleteFileW(pwszDelete); free(pwszDelete); pwszDelete = NULL; // // Delete the "timestamp" file // pwszDelete = _CatDBCreatePath(pwszPathName, WSZ_TIME_STAMP_FILE); if (pwszDelete == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } DeleteFileW(pwszDelete); free(pwszDelete); pwszDelete = NULL; free(pwszPathName); pwszPathName = NULL; } // // Get next file // if (!FindNextFileW(hFindHandle, &FindData)) { if (GetLastError() == ERROR_NO_MORE_FILES) { break; } else { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } } CommonReturn: if (pwszCatroot2 != NULL) { free(pwszCatroot2); } if (pwszDelete != NULL) { free(pwszDelete); } if (pwszSearch != NULL) { free(pwszSearch); } if (pwszPathName != NULL) { free(pwszPathName); } return (fRet); ErrorReturn: fRet = FALSE; goto CommonReturn; } BOOL _CatDBRebuildDB( LPCWSTR pwszPathName, LPCWSTR pwszDatabaseGUID) { BOOL fRet = TRUE; LPWSTR pwszSearch = NULL; LPWSTR pwszCatalog = NULL; HANDLE hFindHandle = INVALID_HANDLE_VALUE; WIN32_FIND_DATAW FindData; DWORD dwErr; LPWSTR __RPC_FAR pwszCatalogNameUsed = NULL; WCHAR wszTempFile[MAX_PATH]; JET_DB_STRUCT *pJetDBStruct = NULL; // // First, just make sure the database gets created by doing // an open and close // if (!_CatDBAcquireOpenDatabaseFromCache( &pJetDBStruct, pwszDatabaseGUID, FALSE, TRUE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } _CatDBReleaseDatabaseToCache(pJetDBStruct); // // Find all catalogs in direcotry and add each one // // // Build a search string for catalog files // pwszSearch = _CatDBCreatePath(pwszPathName, L"*.cat"); if (pwszSearch == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Do the initial find // hFindHandle = FindFirstFileW(pwszSearch, &FindData); if (hFindHandle == INVALID_HANDLE_VALUE) { // // See if a real error occurred, or just no directories // dwErr = GetLastError(); if ((dwErr == ERROR_NO_MORE_FILES) || (dwErr == ERROR_FILE_NOT_FOUND)) { // // There are no files of this form // goto CommonReturn; } else { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } // // Get a temporary file name which will be used to when adding each catalog // if (0 == GetTempFileNameW( g_pwszCatalogFileBaseDirectory, L"TMP", 0, wszTempFile)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // GetTempFileName actually creates the file, so delete it // DeleteFileW(wszTempFile); while (1) { // // Only care about files // if (!(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { pwszCatalog = _CatDBCreatePath(pwszPathName, FindData.cFileName); if (pwszCatalog == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Copy the catalog file to a temporary location and add it from there // if (!CopyFileW(pwszCatalog, wszTempFile, TRUE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } _CatDBAddCatalog( NULL, 0, pwszDatabaseGUID, wszTempFile, FindData.cFileName, TRUE, &pwszCatalogNameUsed); DeleteFileW(wszTempFile); if (pwszCatalogNameUsed != NULL) { MIDL_user_free(pwszCatalogNameUsed); pwszCatalogNameUsed = NULL; } free(pwszCatalog); pwszCatalog = NULL; } // // Get next file // if (!FindNextFileW(hFindHandle, &FindData)) { if (GetLastError() == ERROR_NO_MORE_FILES) { break; } else { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } } CommonReturn: if (pwszSearch != NULL) { free(pwszSearch); } if (pwszCatalog != NULL) { free(pwszCatalog); } return (fRet); ErrorReturn: fRet = FALSE; goto CommonReturn; } BOOL _CatDBRebuildAllDBs() { BOOL fRet = TRUE; LPWSTR pwszCatroot = NULL; LPWSTR pwszSearch = NULL; LPWSTR pwszPathName = NULL; HANDLE hFindHandle = INVALID_HANDLE_VALUE; WIN32_FIND_DATAW FindData; DWORD dwErr; // // Get the directory where the catalog files live // pwszCatroot = _CatDBGetCatrootDirW(FALSE); if (pwszCatroot == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Build a search string for the catalog directories // pwszSearch = _CatDBCreatePath(pwszCatroot, L"{????????????????????????????????????}"); if (pwszSearch == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Do the initial find // hFindHandle = FindFirstFileW(pwszSearch, &FindData); if (hFindHandle == INVALID_HANDLE_VALUE) { // // See if a real error occurred, or just no directories // dwErr = GetLastError(); if ((dwErr == ERROR_NO_MORE_FILES) || (dwErr == ERROR_PATH_NOT_FOUND) || (dwErr == ERROR_FILE_NOT_FOUND)) { // // There are no directories of this form // goto CommonReturn; } else { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } while (1) { // // Only care about directories // if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { pwszPathName = _CatDBCreatePath(pwszCatroot, FindData.cFileName); if (pwszPathName == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } if (!_CatDBRebuildDB(pwszPathName, FindData.cFileName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } free(pwszPathName); pwszPathName = NULL; } // // Get next file // if (!FindNextFileW(hFindHandle, &FindData)) { if (GetLastError() == ERROR_NO_MORE_FILES) { break; } else { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } } CommonReturn: if (pwszCatroot != NULL) { free(pwszCatroot); } if (pwszSearch != NULL) { free(pwszSearch); } if (pwszPathName != NULL) { free(pwszPathName); } return (fRet); ErrorReturn: fRet = FALSE; goto CommonReturn; } ///////////////////////////////////////////////////////////////////////////////////////// // // LPC-exposed functions // // these functions return a DWORD equivalent to GetLastError(). The client side stub // code will check if the return code is not ERROR_SUCCESS, and if this is the case, // the client stub will return FALSE and SetLastError() to this DWORD. // ///////////////////////////////////////////////////////////////////////////////////////// DWORD _CatDBAddCatalog( handle_t h, DWORD dwFlags, LPCWSTR pwszSubSysGUID, LPCWSTR pwszCatalogFile, LPCWSTR pwszCatName, BOOL fInRecursiveCall, LPWSTR __RPC_FAR *ppwszCatalogNameUsed) { DWORD dwRet = ERROR_SUCCESS; RPC_STATUS RpcStatus; LPWSTR pwszCatalogFileDir = NULL; BOOL fImpersonating = FALSE; JET_DB_STRUCT *pJetDBStruct = NULL; BOOL fCatalogDatabaseAcquiredFromCache = FALSE; PCCTL_CONTEXT pCTLContext = NULL; LPWSTR pwszNewCatalogName = NULL; HANDLE hMappedFile = NULL; BYTE *pbMappedFile = NULL; BOOL fTransactionBegun = FALSE; BOOL fFileAlreadyExists = FALSE; WCHAR wszTempFile[MAX_PATH]; JET_ERR jerr; BOOL fTempFileCreated = FALSE; BOOL fCSEntered = FALSE; // // Initialize out param // *ppwszCatalogNameUsed = NULL; // // Only allow one add or delete at a time // __try { EnterCriticalSection(&g_CatDBAddDeleteCS); } __except(EXCEPTION_EXECUTE_HANDLER) { CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorEnterCS) } fCSEntered = TRUE; // // Impersonate client if needed // if (h != NULL) { if (ERROR_SUCCESS != (RpcStatus = RpcImpersonateClient(h))) { CATDBSVC_SETERR_LOG_RETURN(RpcStatus, ErrorImpersonateClient); } fImpersonating = TRUE; } // // Create the path to the catalog files // if (NULL == (pwszCatalogFileDir = _CATDBConstructWSTRPath( g_pwszCatalogFileBaseDirectory, pwszSubSysGUID))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Get the fully qualified path name of the new catalog file // if (NULL == (pwszNewCatalogName = _CatDBCreateNewCatalogFileName( pwszCatalogFileDir, pwszCatName, &fFileAlreadyExists))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } if (NULL == (*ppwszCatalogNameUsed = (LPWSTR) midl_user_allocate((wcslen(pwszNewCatalogName) + 1) * sizeof(WCHAR)))) { CATDBSVC_SETERR_LOG_RETURN(E_OUTOFMEMORY, ErrorMemory) } wcscpy(*ppwszCatalogNameUsed, pwszNewCatalogName); // // Open a CTL context on the catalog being added // if (!CatUtil_CreateCTLContextFromFileName( pwszCatalogFile, &hMappedFile, &pbMappedFile, &pCTLContext, FALSE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // If we are replacing an existing catalog, save a copy of the old one // in case the commit fails // if (fFileAlreadyExists) { if (0 == GetTempFileNameW( g_pwszCatalogFileBaseDirectory, L"TMP", 0, wszTempFile)) { // // If the entries couldn't be deleted because the user doesn't // have write rights, then do a check to see if the catalog // they are trying to add already exists, if it does, then // retrun ERROR_ALREADY_EXISTS instead of ACCESS_DENIED // if (GetLastError() == ERROR_ACCESS_DENIED) { if (_CatDBCatalogFileAlreadyInstalled( pwszCatalogFile, pwszNewCatalogName)) { SetLastError(ERROR_ALREADY_EXISTS); goto ErrorReturn; } } else { CATDBSVC_LOGERR_LASTERR() goto ErrorGetTempFileName; } } // // Copy the old catalog file to a temporary location // if (!CopyFileW(pwszNewCatalogName, wszTempFile, FALSE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorCopyFile; } fTempFileCreated = TRUE; } // // Open the database file // if (!_CatDBAcquireOpenDatabaseFromCache( &pJetDBStruct, pwszSubSysGUID, FALSE, fInRecursiveCall)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } fCatalogDatabaseAcquiredFromCache = TRUE; // // Start transaction // if (_CatDBJET_errFailure(jerr = JetBeginTransaction(pJetDBStruct->JetSesID))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetBeginTransaction) } fTransactionBegun = TRUE; if (fFileAlreadyExists) { if (!_CatDBDeleteCatalogEntriesFromDatabase( pJetDBStruct, pwszNewCatalogName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } // // Add the new DB entries // if (!_CatDBAddCatalogEntriesToDatabase( pJetDBStruct, pCTLContext, pwszNewCatalogName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Don't need the CTL context anymore // CertFreeCTLContext(pCTLContext); pCTLContext = NULL; UnmapViewOfFile(pbMappedFile); pbMappedFile = NULL; CloseHandle(hMappedFile); hMappedFile = NULL; // // Now, copy the new catalog file to its location // if (!CopyFileW(pwszCatalogFile, pwszNewCatalogName, FALSE)) { if (!fFileAlreadyExists) { CATDBSVC_LOGERR_LASTERR() goto ErrorCopyFile; } // // Since that failed, try renaming the destination file, and then re-copy. // BTW, the above copy will fail if another client already has the // destination file memory mapped in their catalog cache. // if (!_CatDBMoveInUseFileToTempLocation(pwszNewCatalogName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Now, retry the copy... this better work! // if (!CopyFileW(pwszCatalogFile, pwszNewCatalogName, FALSE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorCopyFile; } } SetFileAttributesW(pwszNewCatalogName, FILE_ATTRIBUTE_SYSTEM); // // At this stage do the commit. // if (_CatDBJET_errFailure(jerr = JetCommitTransaction( pJetDBStruct->JetSesID, 0))) { // // Since there was an error doing the commit, copy back the original // catalog file // if (0 == CopyFileW(wszTempFile, pwszNewCatalogName, FALSE)) { // THE ABOVE COOPY FAILED... THE DATABASE IS NOW INCONSISTENT!!!!! CATDBSVC_LOGERR_LASTERR() } else { SetFileAttributesW(pwszNewCatalogName, FILE_ATTRIBUTE_SYSTEM); } CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetCommitTransaction) } fTransactionBegun = FALSE; _CatDBTouchTimeStampFile(pwszSubSysGUID); // // Release DB back to the cache // _CatDBReleaseDatabaseToCache(pJetDBStruct); // // Notify client of changes // _CatDBNotifyClients(); CommonReturn: if (fTempFileCreated) { DeleteFileW(wszTempFile); } if (pwszNewCatalogName != NULL) { _CatDBFree(pwszNewCatalogName); } if (pwszCatalogFileDir != NULL) { _CatDBFree(pwszCatalogFileDir); } if (pCTLContext != NULL) { CertFreeCTLContext(pCTLContext); } if (pbMappedFile != NULL) { UnmapViewOfFile(pbMappedFile); } if (hMappedFile != NULL) { CloseHandle(hMappedFile); } if (fImpersonating) { RpcRevertToSelf(); } if (fCSEntered) { LeaveCriticalSection(&g_CatDBAddDeleteCS); } return dwRet; ErrorReturn: dwRet = GetLastError(); if (0 == dwRet) { dwRet = (DWORD) E_UNEXPECTED; } if (fTransactionBegun) { JetRollback(pJetDBStruct->JetSesID, 0); } if (fCatalogDatabaseAcquiredFromCache) { _CatDBReleaseDatabaseToCache(pJetDBStruct); } if (*ppwszCatalogNameUsed != NULL) { midl_user_free(*ppwszCatalogNameUsed); *ppwszCatalogNameUsed = NULL; } goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorImpersonateClient) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetBeginTransaction) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetCommitTransaction) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMemory) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorEnterCS) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorCopyFile) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorGetTempFileName) } DWORD s_SSCatDBAddCatalog( /* [in] */ handle_t h, /* [in] */ DWORD ProcessID, /* [in] */ DWORD dwFlags, /* [in] */ LPCWSTR pwszSubSysGUID, /* [in] */ LPCWSTR pwszCatalogFile, /* [unique][in] */ LPCWSTR pwszCatName, /* [out] */ LPWSTR __RPC_FAR *ppwszCatalogNameUsed) { DWORD dwRet; if (!_CatDBClientEnter()) { CATDBSVC_LOGERR_LASTERR() return (GetLastError()); } // // Check input params // if (h == NULL) { CATDBSVC_SETERR_LOG_RETURN(ERROR_BAD_ARGUMENTS, ErrorReturn) } dwRet = _CatDBAddCatalog( h, dwFlags, pwszSubSysGUID, pwszCatalogFile, pwszCatName, FALSE, ppwszCatalogNameUsed); _CatDBClientExit(); CommonReturn: return (dwRet); ErrorReturn: dwRet = GetLastError(); goto CommonReturn; } DWORD s_SSCatDBDeleteCatalog( /* [in] */ handle_t h, /* [in] */ DWORD ProcessID, /* [in] */ DWORD dwFlags, /* [in] */ LPCWSTR pwszSubSysGUID, /* [in] */ LPCWSTR pwszCatalogFile) { DWORD dwRet = 0; RPC_STATUS RpcStatus; BOOL fImpersonating = FALSE; JET_DB_STRUCT *pJetDBStruct = NULL; BOOL fCatalogDatabaseAcquiredFromCache = FALSE; JET_ERR jerr; BOOL fCSEntered = FALSE; LPWSTR pwszCatalogFileFullPath = NULL; BOOL fTransactionBegun = FALSE; LPWSTR pwszCatalogFileDir = NULL; if (!_CatDBClientEnter()) { CATDBSVC_LOGERR_LASTERR() return (GetLastError()); } // // Check input params // if (h == NULL) { CATDBSVC_SETERR_LOG_RETURN(E_INVALIDARG, ErrorInvalidArg) } // // Only allow one add or delete at a time // __try { EnterCriticalSection(&g_CatDBAddDeleteCS); } __except(EXCEPTION_EXECUTE_HANDLER) { CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorEnterCS) } fCSEntered = TRUE; // // Impersonate client // if (ERROR_SUCCESS != (RpcStatus = RpcImpersonateClient(h))) { CATDBSVC_SETERR_LOG_RETURN(RpcStatus, ErrorImpersonateClient) } fImpersonating = TRUE; // // Create the path to the catalog files // if (NULL == (pwszCatalogFileDir = _CATDBConstructWSTRPath( g_pwszCatalogFileBaseDirectory, pwszSubSysGUID))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Construct full path to catalog being deleted // if (NULL == (pwszCatalogFileFullPath = _CATDBConstructWSTRPath(pwszCatalogFileDir, pwszCatalogFile))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Open the database file // if (!_CatDBAcquireOpenDatabaseFromCache( &pJetDBStruct, pwszSubSysGUID, FALSE, FALSE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } fCatalogDatabaseAcquiredFromCache = TRUE; // // Start transaction // if (_CatDBJET_errFailure(jerr = JetBeginTransaction(pJetDBStruct->JetSesID))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetBeginTransaction) } fTransactionBegun = TRUE; // // Delete the entries of the catalog file from the DB // if (!_CatDBDeleteCatalogEntriesFromDatabase( pJetDBStruct, pwszCatalogFileFullPath)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // At this stage do the commit. // if (_CatDBJET_errFailure(jerr = JetCommitTransaction( pJetDBStruct->JetSesID, 0))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetCommitTransaction) } fTransactionBegun = FALSE; if (!DeleteFileW(pwszCatalogFileFullPath)) { // // Maybe the delete failed since the file doesn't even exist // if (GetLastError() != ERROR_FILE_NOT_FOUND) { // // If the delete failed for a reason other than NOT_FOUND // then another client is probably already accessing the file, // so just copy it to a temp location and log it for deletion // if (!_CatDBMoveInUseFileToTempLocation(pwszCatalogFileFullPath)) { CATDBSVC_LOGERR_LASTERR() // // Don't return an error, since this isn't fatal // } } } // // Release DB back to the cache // _CatDBReleaseDatabaseToCache(pJetDBStruct); // // Notify client of changes // _CatDBNotifyClients(); _CatDBTouchTimeStampFile(pwszSubSysGUID); CommonReturn: if (pwszCatalogFileFullPath != NULL) { _CatDBFree(pwszCatalogFileFullPath); } if (pwszCatalogFileDir != NULL) { _CatDBFree(pwszCatalogFileDir); } if(fImpersonating) { RpcRevertToSelf(); } if (fCSEntered) { LeaveCriticalSection(&g_CatDBAddDeleteCS); } _CatDBClientExit(); return dwRet; ErrorReturn: dwRet = GetLastError(); if (0 == dwRet) { dwRet = (DWORD) E_UNEXPECTED; } if (fTransactionBegun) { JetRollback(pJetDBStruct->JetSesID, 0); } if (fCatalogDatabaseAcquiredFromCache) { _CatDBReleaseDatabaseToCache(pJetDBStruct); } goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorInvalidArg) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorImpersonateClient) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetBeginTransaction) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetCommitTransaction) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorEnterCS) } DWORD s_SSCatDBEnumCatalogs( /* [in] */ handle_t h, /* [in] */ DWORD ProcessID, /* [in] */ DWORD dwFlags, /* [in] */ LPCWSTR pwszSubSysGUID, /* [size_is][in] */ BYTE __RPC_FAR *pbHash, /* [in] */ DWORD cbHash, /* [out] */ DWORD __RPC_FAR *pdwNumCatalogNames, /* [size_is][size_is][out] */ LPWSTR __RPC_FAR *__RPC_FAR *pppwszCatalogNames) { DWORD dwRet = ERROR_SUCCESS; RPC_STATUS RpcStatus; JET_DB_STRUCT *pJetDBStruct; JET_ERR jerr; BOOL fCatalogDatabaseAcquiredFromCache = FALSE; CRYPT_HASH_BLOB HashBlob; JET_RETINFO JetRetInfo; WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH]; DWORD dwLength; DWORD i; if (!_CatDBClientEnter()) { CATDBSVC_LOGERR_LASTERR() return (GetLastError()); } if (h == NULL) { CATDBSVC_SETERR_LOG_RETURN(E_INVALIDARG, ErrorInvalidArg) } // // Init out vars // *pdwNumCatalogNames = 0; *pppwszCatalogNames = NULL; // // Open the database file // if (!_CatDBAcquireOpenDatabaseFromCache( &pJetDBStruct, pwszSubSysGUID, TRUE, FALSE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } fCatalogDatabaseAcquiredFromCache = TRUE; // // Try to find the hash // HashBlob.pbData = pbHash; HashBlob.cbData = cbHash; jerr = _CatDBSeekInHashCatNameTable(pJetDBStruct, &HashBlob); if (jerr == JET_errSuccess) { // // Add all names from the Hashes CatNameList, plus all the buddys // of those CatNames // // NOTE: the order in which the CatNames are added 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. This // is OK because the client side code only assumes the first CatName // contains the hash, and then explicitly searches all others for the hash. // memset(&JetRetInfo, 0, sizeof(JetRetInfo)); JetRetInfo.cbStruct = sizeof(JetRetInfo); JetRetInfo.itagSequence = 1; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_CatNameColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); while (jerr == JET_errSuccess) { if (!_CatDBAddCatNameAndCatNamesBuddyListToReturnCatNames( pJetDBStruct, wszCatalogName, pdwNumCatalogNames, pppwszCatalogNames, FALSE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Setup for next loop // JetRetInfo.itagSequence++; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_CatNameColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); } // // Check to see if a real error occurred and not just a JET_wrnColumnNull // if (_CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } } else if ((jerr != JET_errRecordNotFound) && _CatDBJET_errFailure(jerr)) { // // Some real error occurred // CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: if (fCatalogDatabaseAcquiredFromCache) { _CatDBReleaseDatabaseToCache(pJetDBStruct); } _CatDBClientExit(); return dwRet; ErrorReturn: dwRet = GetLastError(); if (0 == dwRet) { dwRet = (DWORD) E_UNEXPECTED; } for (i=0; i<(*pdwNumCatalogNames); i++) { midl_user_free((*pppwszCatalogNames)[i]); } if ((*pppwszCatalogNames) != NULL) { midl_user_free(*pppwszCatalogNames); *pppwszCatalogNames = NULL; } *pdwNumCatalogNames = 0; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorInvalidArg) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBProcessExitCallback // //--------------------------------------------------------------------------------------- VOID CALLBACK _CatDBProcessExitCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired) { LONG lNotificationID = PtrToLong(lpParameter); DWORD i; HANDLE h; __try { EnterCriticalSection(&g_CatDBRegisterNotifyCS); } __except(EXCEPTION_EXECUTE_HANDLER) { return; } // // Search through the array to make sure the handle wasn't already unregistered // i = 0; while ( (i < g_NumNotificationStructs) && (g_rgNotificationStructs[i].lNotificationID != lNotificationID)) { i++; } // // If it was found, then clean it up. // if (i < g_NumNotificationStructs) { g_rgNotificationStructs[i].ProcessID = 0; CloseHandle(g_rgNotificationStructs[i].hClientProcess); g_rgNotificationStructs[i].hClientProcess = NULL; h = (HANDLE) InterlockedExchangePointer( &(g_rgNotificationStructs[i].hRegisterWaitFor), NULL); if (h != NULL) { UnregisterWait(g_rgNotificationStructs[i].hRegisterWaitFor); } g_rgNotificationStructs[i].hNotificationHandle = INVALID_HANDLE_VALUE; CloseHandle(g_rgNotificationStructs[i].hDuplicatedNotificationHandle); g_rgNotificationStructs[i].hDuplicatedNotificationHandle = INVALID_HANDLE_VALUE; g_rgNotificationStructs[i].lNotificationID = 0; } LeaveCriticalSection(&g_CatDBRegisterNotifyCS); } DWORD s_SSCatDBRegisterForChangeNotification( /* [in] */ handle_t h, /* [in] */ DWORD ProcessID, /* [in] */ DWORD_PTR EventHandle, /* [in] */ DWORD dwFlags, /* [in] */ LPCWSTR pwszSubSysGUID, /* [in] */ BOOL fUnRegister) { DWORD dwRet = ERROR_SUCCESS; HANDLE hDuplicate = INVALID_HANDLE_VALUE; DWORD i, j; BOOL fCSEntered = FALSE; HANDLE hWaitForToUnregister = NULL; HANDLE hClientProcess = NULL; LONG lLocalNotificationID = 0; NOTIFICATION_STRUCT *rghTemp; if (!_CatDBClientEnter()) { CATDBSVC_LOGERR_LASTERR() return (GetLastError()); } if (h == NULL) { CATDBSVC_SETERR_LOG_RETURN(E_INVALIDARG, ErrorInvalidArg) goto ErrorInvalidArg; } // // NOTE: this is a implementation that just notifies // all clients when an add/delete catalog occurs... regardless // of what catalog sub-system has been modified and what sub-system // the client is operating in. Because of this implementation // pwszCatalogDir is NOT USED. If this changes, the client side code // will also need to change. See the NOTE in the // _CatAdminRegisterForChangeNotification() function of catadnew.cpp // __try { EnterCriticalSection(&g_CatDBRegisterNotifyCS); } __except(EXCEPTION_EXECUTE_HANDLER) { CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorEnterCS) } fCSEntered = TRUE; // // First check to see whether we are registering or unregestering // if (!fUnRegister) { // // Make sure we can get a slot to add the handle to // i = 0; while ( (i < g_NumNotificationStructs) && (g_rgNotificationStructs[i].hClientProcess != NULL)) { i++; } // // If no space, allocate more // if (i >= g_NumNotificationStructs) { if (g_NumNotificationStructs == 0) { // // None allocated yet, so allocate and initialize // if (NULL == (g_rgNotificationStructs = (NOTIFICATION_STRUCT *) _CatDBAlloc(sizeof(NOTIFICATION_STRUCT) * ALLOCATION_BLOCK_SIZE))) { CATDBSVC_LOGERR_LASTERR() goto ErrorMemory; } g_NumNotificationStructs = ALLOCATION_BLOCK_SIZE; for (j = 0; j < g_NumNotificationStructs; j++) { g_rgNotificationStructs[j].ProcessID = 0; g_rgNotificationStructs[j].hClientProcess = NULL; g_rgNotificationStructs[j].hRegisterWaitFor = NULL; g_rgNotificationStructs[j].hNotificationHandle = INVALID_HANDLE_VALUE; g_rgNotificationStructs[j].hDuplicatedNotificationHandle = INVALID_HANDLE_VALUE; g_rgNotificationStructs[j].lNotificationID = 0; } // set i so it can just be used as open slot i = 0; } else { rghTemp = g_rgNotificationStructs; if (NULL == (g_rgNotificationStructs = (NOTIFICATION_STRUCT *) _CatDBReAlloc(g_rgNotificationStructs, sizeof(NOTIFICATION_STRUCT) * (g_NumNotificationStructs + ALLOCATION_BLOCK_SIZE)))) { g_rgNotificationStructs = rghTemp; CATDBSVC_LOGERR_LASTERR() goto ErrorMemory; } for ( j = g_NumNotificationStructs; j < (g_NumNotificationStructs + ALLOCATION_BLOCK_SIZE); j++) { g_rgNotificationStructs[j].ProcessID = 0; g_rgNotificationStructs[j].hClientProcess = NULL; g_rgNotificationStructs[j].hRegisterWaitFor = NULL; g_rgNotificationStructs[j].hNotificationHandle = INVALID_HANDLE_VALUE; g_rgNotificationStructs[j].hDuplicatedNotificationHandle = INVALID_HANDLE_VALUE; g_rgNotificationStructs[j].lNotificationID = 0; } // set i so it can just be used as open slot i = g_NumNotificationStructs; g_NumNotificationStructs += ALLOCATION_BLOCK_SIZE; } } // // Open the process' handle that is registering a notification since we need // the process handle to duplicate the event handle that they want signaled, // plus, we wait on it in case of process exit // if (NULL == (hClientProcess = OpenProcess( PROCESS_DUP_HANDLE | SYNCHRONIZE, FALSE, ProcessID))) { CATDBSVC_LOGERR_LASTERR() goto ErrorOpenProcess; } // // Duplicate the handle // if (0 == (DuplicateHandle( hClientProcess, (HANDLE) EventHandle, GetCurrentProcess(), &hDuplicate, EVENT_MODIFY_STATE, //0, FALSE, 0))) //DUPLICATE_SAME_ACCESS))) { CATDBSVC_LOGERR_LASTERR() goto ErrorDuplicateHandle; } // // Register a callback in cass the process exits without unregistering // lLocalNotificationID = InterlockedIncrement(&g_lNotificationID); if (!RegisterWaitForSingleObject( &(g_rgNotificationStructs[i].hRegisterWaitFor), hClientProcess, _CatDBProcessExitCallback, ULongToPtr(lLocalNotificationID), // use ULongToPtr instead of LongToPtr because // ULongToPtr zero extends instead of sign extends INFINITE, WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } g_rgNotificationStructs[i].ProcessID = ProcessID; g_rgNotificationStructs[i].hClientProcess = hClientProcess; hClientProcess = NULL; g_rgNotificationStructs[i].hNotificationHandle = (HANDLE) EventHandle; g_rgNotificationStructs[i].hDuplicatedNotificationHandle = hDuplicate; hDuplicate = INVALID_HANDLE_VALUE; g_rgNotificationStructs[i].lNotificationID = lLocalNotificationID; } else { // // Search through the array to find the handle being unregisterd // i = 0; while (i < g_NumNotificationStructs) { // // Match client based on ProcessID And EventHandle which is a unique pair // if ((g_rgNotificationStructs[i].hNotificationHandle == (HANDLE) EventHandle) && (g_rgNotificationStructs[i].ProcessID == ProcessID)) { break; } i++; } // // Make sure we found the handle // if (i < g_NumNotificationStructs) { g_rgNotificationStructs[i].ProcessID = 0; hWaitForToUnregister = (HANDLE) InterlockedExchangePointer( &(g_rgNotificationStructs[i].hRegisterWaitFor), NULL); hClientProcess = g_rgNotificationStructs[i].hClientProcess; g_rgNotificationStructs[i].hClientProcess = NULL; g_rgNotificationStructs[i].hNotificationHandle = INVALID_HANDLE_VALUE; CloseHandle(g_rgNotificationStructs[i].hDuplicatedNotificationHandle); g_rgNotificationStructs[i].hDuplicatedNotificationHandle = INVALID_HANDLE_VALUE; g_rgNotificationStructs[i].lNotificationID = 0; // // Leave the RegisterNotitifyCS before calling UnregisterWait() // LeaveCriticalSection(&g_CatDBRegisterNotifyCS); fCSEntered = FALSE; if (hWaitForToUnregister != NULL) { UnregisterWaitEx( hWaitForToUnregister, INVALID_HANDLE_VALUE); } CloseHandle(hClientProcess); hClientProcess = NULL; } } CommonReturn: if (fCSEntered) { LeaveCriticalSection(&g_CatDBRegisterNotifyCS); } if (hClientProcess != NULL) { CloseHandle(hClientProcess); } if (hDuplicate != INVALID_HANDLE_VALUE) { CloseHandle(hDuplicate); } _CatDBClientExit(); return dwRet; ErrorReturn: dwRet = GetLastError(); if (0 == dwRet) { dwRet = (DWORD) E_UNEXPECTED; } goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorInvalidArg) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorEnterCS) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMemory) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorOpenProcess) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorDuplicateHandle) } #define CATDB_RETRY_PAUSE_COUNT 10 #define CATDB_PAUSE_RETRY_INTERNVAL 1000 DWORD s_SSCatDBPauseResumeService( /* [in] */ handle_t h, /* [in] */ DWORD ProcessID, /* [in] */ DWORD dwFlags, /* [in] */ BOOL fResume) { return (E_NOTIMPL); } ///////////////////////////////////////////////////////////////////////////////////////// // // Supporting functions // ///////////////////////////////////////////////////////////////////////////////////////// //--------------------------------------------------------------------------------------- // // _CatDBServiceInit // //--------------------------------------------------------------------------------------- BOOL _CatDBServiceInit(BOOL fUnInit) { BOOL fRet = TRUE; DWORD dwErr = 0; JET_ERR jerr; HKEY hKey; DWORD dwDisposition; DWORD dw; WCHAR wszDefaultSystemDir[MAX_PATH + 1]; DWORD dwType; DWORD dwValue = 0; DWORD cbSize; DWORD i; DWORD NumCritSecsInitialized = 0; LIST_NODE *pListNode = NULL; CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct = NULL; PVOID pvoid; BOOL fLeaveCritSec = TRUE; if (fUnInit && g_fDBSvcInitialized) { // // Set the g_fCatalogCacheCallbackEventSet BOOL so that no more // callbacks are registered // fLeaveCritSec = TRUE; __try { EnterCriticalSection(&g_CatDirCashCS); } __except(EXCEPTION_EXECUTE_HANDLER) { fLeaveCritSec = FALSE; g_fCatalogCacheCallbackEventSet = TRUE; } g_fCatalogCacheCallbackEventSet = TRUE; if (fLeaveCritSec) { LeaveCriticalSection(&g_CatDirCashCS); } // // This will force all callback threads to be cleared // SetEvent(g_hCatalogCacheCallbackEvent); // // Cycle through all open DBs and wait for the registered callbacks // to be completed // pListNode = LIST_GetFirst(&g_CatalogDBCacheList); while (pListNode != NULL) { pCatDirCacheStruct = (CATALOG_DIR_CACHE_STRUCT *) LIST_GetElement(pListNode); pvoid = InterlockedExchangePointer( &pCatDirCacheStruct->hRegisterWaitForServiceShutdown, NULL); if (pvoid != NULL) { UnregisterWaitEx((HANDLE) pvoid, INVALID_HANDLE_VALUE); } pListNode = LIST_GetNext(pListNode); } CloseHandle(g_hCatalogCacheCallbackEvent); g_hCatalogCacheCallbackEvent = NULL; // // Cleanup the cached catalog dirs // if (!_CatDBCloseCachedDatabases()) { CATDBSVC_LOGERR_LASTERR() // // Nothing we can do but log an error // } _CatDBTermJet(); if (g_pwszCatalogFileBaseDirectory != NULL) { _CatDBFree(g_pwszCatalogFileBaseDirectory); g_pwszCatalogFileBaseDirectory = NULL; } if (g_pwszDatabaseFileBaseDirectory != NULL) { _CatDBFree(g_pwszDatabaseFileBaseDirectory); g_pwszDatabaseFileBaseDirectory = NULL; } DeleteCriticalSection(&g_CatDBAddDeleteCS); DeleteCriticalSection(&g_CatDBRegisterNotifyCS); DeleteCriticalSection(&g_CatDirCashCS); DeleteCriticalSection(&g_CatClientCountCS); DeleteCriticalSection(&g_InitializeJetCS); DeleteCriticalSection(&g_CleanupTempFilesCS); g_fDBSvcInitialized = FALSE; } else if (!fUnInit) { __try { InitializeCriticalSection(&g_CatDBAddDeleteCS); NumCritSecsInitialized++; InitializeCriticalSection(&g_CatDBRegisterNotifyCS); NumCritSecsInitialized++; InitializeCriticalSection(&g_CatDirCashCS); NumCritSecsInitialized++; InitializeCriticalSection(&g_CatClientCountCS); NumCritSecsInitialized++; InitializeCriticalSection(&g_InitializeJetCS); NumCritSecsInitialized++; InitializeCriticalSection(&g_CleanupTempFilesCS); NumCritSecsInitialized++; } __except(EXCEPTION_EXECUTE_HANDLER) { SetLastError(GetExceptionCode()); CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } g_fCatalogCacheCallbackEventSet = FALSE; // // Get System default directory // wszDefaultSystemDir[0] = NULL; if (0 == GetSystemDirectoryW(wszDefaultSystemDir, MAX_PATH)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Create default dirs for catalog files and CatDB files // if (NULL == (g_pwszCatalogFileBaseDirectory = _CATDBConstructWSTRPath( wszDefaultSystemDir, WSZ_CATALOG_FILE_BASE_DIRECTORY))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } if (NULL == (g_pwszDatabaseFileBaseDirectory = _CATDBConstructWSTRPath( wszDefaultSystemDir, WSZ_DATABASE_FILE_BASE_DIRECTORY))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Get values to be used for timer callback, and database cache timeout // if (RegCreateKeyExW( HKEY_LOCAL_MACHINE, WSZ_REG_CATALOGDB_VALUES, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) { cbSize = sizeof(DWORD); if (RegQueryValueExW( hKey, WSZ_REG_DATABASE_TIMEOUT, NULL, &dwType, (BYTE *) &dwValue, &cbSize) == ERROR_SUCCESS) { g_dwCatalogDatabaseCacheTimeout = dwValue; } dwValue = 0; cbSize = sizeof(DWORD); if (RegQueryValueExW( hKey, WSZ_REG_CALLBACK_TIMER, NULL, &dwType, (BYTE *) &dwValue, &cbSize) == ERROR_SUCCESS) { g_dwCatalogDatabaseCacheCallbackTime = dwValue; } RegCloseKey(hKey); } // // Create the event to be used in the call to RegisterWaitForSingleObject // if (NULL == (g_hCatalogCacheCallbackEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } LIST_Initialize(&g_CatalogDBCacheList); g_fDBSvcInitialized = TRUE; } CommonReturn: return fRet; ErrorReturn: dwErr = GetLastError(); if (NumCritSecsInitialized >= 1) { DeleteCriticalSection(&g_CatDBAddDeleteCS); } if (NumCritSecsInitialized >= 2) { DeleteCriticalSection(&g_CatDBRegisterNotifyCS); } if (NumCritSecsInitialized >= 3) { DeleteCriticalSection(&g_CatDirCashCS); } if (NumCritSecsInitialized >= 4) { DeleteCriticalSection(&g_CatClientCountCS); } if (NumCritSecsInitialized >= 5) { DeleteCriticalSection(&g_InitializeJetCS); } if (NumCritSecsInitialized >= 6) { DeleteCriticalSection(&g_CleanupTempFilesCS); } if (g_pwszCatalogFileBaseDirectory != NULL) { _CatDBFree(g_pwszCatalogFileBaseDirectory); } if (g_pwszDatabaseFileBaseDirectory != NULL) { _CatDBFree(g_pwszDatabaseFileBaseDirectory); } if (g_hCatalogCacheCallbackEvent != NULL) { CloseHandle(g_hCatalogCacheCallbackEvent); g_hCatalogCacheCallbackEvent = NULL; } SetLastError(dwErr); fRet = FALSE; goto CommonReturn; } //--------------------------------------------------------------------------------------- // // _CatDBClientEnter // //--------------------------------------------------------------------------------------- BOOL _CatDBClientEnter(void) { BOOL fRet = TRUE; __try { EnterCriticalSection(&g_CatClientCountCS); } __except(EXCEPTION_EXECUTE_HANDLER) { SetLastError(GetExceptionCode()); CATDBSVC_LOGERR_LASTERR() return FALSE; } g_dwClientCount++; LeaveCriticalSection(&g_CatClientCountCS); return fRet; } //--------------------------------------------------------------------------------------- // // _CatDBClientExit // //--------------------------------------------------------------------------------------- void _CatDBClientExit(void) { __try { EnterCriticalSection(&g_CatClientCountCS); } __except(EXCEPTION_EXECUTE_HANDLER) { SetLastError(GetExceptionCode()); CATDBSVC_LOGERR_LASTERR() assert(0); return; } g_dwClientCount--; LeaveCriticalSection(&g_CatClientCountCS); } //--------------------------------------------------------------------------------------- // // _CatDBTouchTimeStampFile // //--------------------------------------------------------------------------------------- void _CatDBTouchTimeStampFile( LPCWSTR pwszSubSysGUID) { LPWSTR pwsz = NULL; if (NULL != (pwsz = _CATDBConstructWSTRPath( g_pwszDatabaseFileBaseDirectory, pwszSubSysGUID))) { TimeStampFile_Touch(pwsz); _CatDBFree(pwsz); } else { CATDBSVC_LOGERR_LASTERR() } } //--------------------------------------------------------------------------------------- // // _CatDBInitializeJet // //--------------------------------------------------------------------------------------- BOOL _CatDBInitializeJet( BOOL fInRecursiveCall) { BOOL fRet = TRUE; BOOL fCSEntered = FALSE; JET_ERR jerr; __try { EnterCriticalSection(&g_InitializeJetCS); } __except(EXCEPTION_EXECUTE_HANDLER) { CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorReturn) } fCSEntered = TRUE; if (g_fJetInitialized) { goto CommonReturn; } // // Initialize Jets parameters // if (!_CatDBInitJetDatabaseParams(&g_JetInstance)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Jet will start up at this point // jerr = JetInit(&g_JetInstance); // // Check for specific JET errors, if we got one of those errors then // the DB is corrupt in some way and we need to try and cleanup the // catroot2 dir, and rebuild the DB. // // Of course we should only do this if we are not already recursing // if (!fInRecursiveCall && ((jerr == JET_errMissingLogFile) || (jerr == JET_errLogFileCorrupt) || (jerr == JET_errReadVerifyFailure) || (jerr == JET_errPageNotInitialized))) { CATDBSVC_LOGERR(jerr) JetTerm(g_JetInstance); g_JetInstance = 0; // // Cleanup the catroot 2 directory and then rebuild the DB // if (_CatDBDeleteJetFiles() && _CatDBRebuildAllDBs()) { jerr = JET_errSuccess; } } if (_CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(jerr, ErrorReturn) } g_fJetInitialized = TRUE; CommonReturn: if (fCSEntered) { LeaveCriticalSection(&g_InitializeJetCS); } return (fRet); ErrorReturn: fRet = FALSE; goto CommonReturn; } //--------------------------------------------------------------------------------------- // // _CatDBTermJet // //--------------------------------------------------------------------------------------- BOOL _CatDBTermJet() { BOOL fRet = TRUE; BOOL fCSEntered = FALSE; JET_ERR jerr; __try { EnterCriticalSection(&g_InitializeJetCS); } __except(EXCEPTION_EXECUTE_HANDLER) { CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorReturn) } fCSEntered = TRUE; if (!g_fJetInitialized || (g_lOpenedDBCount != 0)) { goto CommonReturn; } // // Shut Jet down!! // jerr = JetTerm(g_JetInstance); g_JetInstance = 0; g_fJetInitialized = FALSE; if (_CatDBJET_errFailure(jerr)) { SetLastError(jerr); CATDBSVC_LOGERR(jerr) } CommonReturn: if (fCSEntered) { LeaveCriticalSection(&g_InitializeJetCS); } return (fRet); ErrorReturn: fRet = FALSE; goto CommonReturn; } //--------------------------------------------------------------------------------------- // // _CatDBAcquireOpenDatabaseFromCache // //--------------------------------------------------------------------------------------- BOOL _CatDBAcquireOpenDatabaseFromCache( PJET_DB_STRUCT *ppJetDBStruct, LPCWSTR pwszSubSysGUID, BOOL fReadOnly, BOOL fInRecursiveCall) { BOOL fRet = TRUE; JET_ERR jerr; LPSTR pszDatabaseFileDir = NULL; LPSTR pszSubSysGUID = NULL; LPSTR pszTemp = NULL; BOOL fJetInitialized = FALSE; BOOL fJetSessionBegun = FALSE; BOOL fJetDBFileOpen = FALSE; BOOL fCSEntered = FALSE; DWORD i; DWORD dwNewCacheStructIndex = 0; BOOL fNewCacheStructUsed = FALSE; PJET_DB_STRUCT pJetDBStruct = NULL; LIST_NODE *pListNode = NULL; CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct = NULL; CATALOG_DIR_CACHE_STRUCT *pNewCatDirCacheStruct = NULL; DWORD dwErr = 0; // // Do this here to ensure that JetTerm isn't called after the // initialize below is called. This reference will be removed // if an actuall cached DB is used. // InterlockedIncrement(&g_lOpenedDBCount); // // Make sure Jet is initialized // if (!_CatDBInitializeJet(fInRecursiveCall)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // First check to see if there is a cached session available // __try { EnterCriticalSection(&g_CatDirCashCS); } __except(EXCEPTION_EXECUTE_HANDLER) { CATDBSVC_SETERR_LOG_RETURN(GetExceptionCode(), ErrorReturn) } fCSEntered = TRUE; pListNode = LIST_GetFirst(&g_CatalogDBCacheList); while (pListNode != NULL) { pCatDirCacheStruct = (CATALOG_DIR_CACHE_STRUCT *) LIST_GetElement(pListNode); if ((!pCatDirCacheStruct->fDBCurrentlyInUse) && (_wcsicmp(pCatDirCacheStruct->pwszSubSysGUID, pwszSubSysGUID) == 0)) /*&& (pCatDirCacheStruct->fReadOnly == fReadOnly))*/ { break; } pListNode = LIST_GetNext(pListNode); } if (pListNode != NULL) { // // Using a cached DB, which already has a ref count, so get rid of the // one added at the beginning of the function // InterlockedDecrement(&g_lOpenedDBCount); pCatDirCacheStruct->fDBCurrentlyInUse = TRUE; pCatDirCacheStruct->dwTimeLastTouched = GetTickCount(); *ppJetDBStruct = &(pCatDirCacheStruct->JetDBStruct); goto CommonReturn; } // // There are either no cached DBs for this dir, or they are already in use... // So open a new instance // if (NULL == (pNewCatDirCacheStruct = (CATALOG_DIR_CACHE_STRUCT *) _CatDBAlloc(sizeof(CATALOG_DIR_CACHE_STRUCT)))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } memset(&(pNewCatDirCacheStruct->JetDBStruct), 0, sizeof(JET_DB_STRUCT)); pNewCatDirCacheStruct->pwszSubSysGUID = NULL; pNewCatDirCacheStruct->fDBCurrentlyInUse = TRUE; pNewCatDirCacheStruct->dwTimeLastTouched = GetTickCount(); pNewCatDirCacheStruct->fReadOnly = fReadOnly; // // Make a copy of the catalog database GUID // if (NULL == (pNewCatDirCacheStruct->pwszSubSysGUID = (LPWSTR) _CatDBAlloc((wcslen(pwszSubSysGUID) + 1) * sizeof(WCHAR)))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } wcscpy(pNewCatDirCacheStruct->pwszSubSysGUID, pwszSubSysGUID); pJetDBStruct = &(pNewCatDirCacheStruct->JetDBStruct); // // Begin a session // if (_CatDBJET_errFailure(jerr = JetBeginSession( g_JetInstance, &(pJetDBStruct->JetSesID), NULL, NULL))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } fJetSessionBegun = TRUE; // // Get the fully qualified name of the database file // pszDatabaseFileDir = _CatDBConvertWszToSz(g_pwszDatabaseFileBaseDirectory); if (pszDatabaseFileDir == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } pszSubSysGUID = _CatDBConvertWszToSz(pwszSubSysGUID); if (pszSubSysGUID == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } if (NULL == (pszTemp = _CATDBConstructPath(pszDatabaseFileDir, pszSubSysGUID))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } if (NULL == (pJetDBStruct->pszDBFileName = _CATDBConstructPath(pszTemp, SZ_DBFILE_NAME))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Open the DB file... create it if it doesn't already exist // if (!_CatDBAttachAndOpenDatabase(pJetDBStruct, fReadOnly)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } fJetDBFileOpen = TRUE; // // Register a close callback for this database // if (!RegisterWaitForSingleObject( &(pNewCatDirCacheStruct->hRegisterWaitForServiceShutdown), g_hCatalogCacheCallbackEvent, _CatDBWaitOrTimerCallback, pNewCatDirCacheStruct, // Context g_dwCatalogDatabaseCacheCallbackTime, WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Add the opened database to the cache list // if (!LIST_AddTail(&g_CatalogDBCacheList, pNewCatDirCacheStruct)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } *ppJetDBStruct = &(pNewCatDirCacheStruct->JetDBStruct); CommonReturn: if (fCSEntered) { LeaveCriticalSection(&g_CatDirCashCS); } if (pszDatabaseFileDir != NULL) { _CatDBFree(pszDatabaseFileDir); } if (pszSubSysGUID != NULL) { _CatDBFree(pszSubSysGUID); } if (pszTemp != NULL) { _CatDBFree(pszTemp); } return fRet; ErrorReturn: dwErr = GetLastError(); if (fJetDBFileOpen) { JetCloseDatabase(pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, 0); } if (fJetSessionBegun) { JetEndSession(pJetDBStruct->JetSesID, 0); } if (pNewCatDirCacheStruct != NULL) { if (pNewCatDirCacheStruct->JetDBStruct.pszDBFileName != NULL) { _CatDBFree(pNewCatDirCacheStruct->JetDBStruct.pszDBFileName); } if (pNewCatDirCacheStruct->pwszSubSysGUID != NULL) { _CatDBFree(pNewCatDirCacheStruct->pwszSubSysGUID); } _CatDBFree(pNewCatDirCacheStruct); } InterlockedDecrement(&g_lOpenedDBCount); SetLastError(dwErr); fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBReleaseDatabaseToCache // //--------------------------------------------------------------------------------------- BOOL _CatDBReleaseDatabaseToCache( PJET_DB_STRUCT pJetDBStruct) { // // This cast works because the JET_DB_STRUCT is the first member of the // CATALOG_DIR_CACHE_STRUCT // CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct = (CATALOG_DIR_CACHE_STRUCT *) pJetDBStruct; pCatDirCacheStruct->dwTimeLastTouched = GetTickCount(); pCatDirCacheStruct->fDBCurrentlyInUse = FALSE; return TRUE; } //--------------------------------------------------------------------------------------- // // _CatDBCloseSingleCachedDatabase // //--------------------------------------------------------------------------------------- BOOL _CatDBCloseSingleCachedDatabase( CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct) { BOOL fRet = TRUE; PVOID pvoid; __try { EnterCriticalSection(&g_CatDirCashCS); } __except(EXCEPTION_EXECUTE_HANDLER) { SetLastError(GetExceptionCode()); CATDBSVC_LOGERR_LASTERR() return FALSE; } // // unregister the callback // pvoid = InterlockedExchangePointer( &pCatDirCacheStruct->hRegisterWaitForServiceShutdown, NULL); if (pvoid != NULL) { UnregisterWait((HANDLE) pvoid); } // // If the DB is not in use and its timed out, then close // if (!(pCatDirCacheStruct->fDBCurrentlyInUse) && (((GetTickCount() - pCatDirCacheStruct->dwTimeLastTouched) > g_dwCatalogDatabaseCacheTimeout))) { if (!_CatDBCloseDatabaseFile(&(pCatDirCacheStruct->JetDBStruct))) { fRet = FALSE; CATDBSVC_LOGERR_LASTERR() } // // if that was the last open DB, then terminate Jet // if (0 == InterlockedDecrement(&g_lOpenedDBCount)) { _CatDBTermJet(); } _CatDBFree(pCatDirCacheStruct->JetDBStruct.pszDBFileName); _CatDBFree(pCatDirCacheStruct->pwszSubSysGUID); LIST_RemoveElement(&g_CatalogDBCacheList, pCatDirCacheStruct); _CatDBFree(pCatDirCacheStruct); } else { if (!g_fCatalogCacheCallbackEventSet) { // // Register for another callback if we aren't in shutdown mode // if (!RegisterWaitForSingleObject( &(pCatDirCacheStruct->hRegisterWaitForServiceShutdown), g_hCatalogCacheCallbackEvent, _CatDBWaitOrTimerCallback, pCatDirCacheStruct, // Context g_dwCatalogDatabaseCacheCallbackTime, WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) { CATDBSVC_LOGERR_LASTERR() } } } LeaveCriticalSection(&g_CatDirCashCS); return fRet; } //--------------------------------------------------------------------------------------- // // _CatDBCloseCachedDatabases // //--------------------------------------------------------------------------------------- BOOL _CatDBCloseCachedDatabases() { BOOL fRet = TRUE; DWORD i; BOOL fDatabaseFoundThatIsInUse = FALSE; BOOL fCloseFailed = FALSE; LIST_NODE *pListNode = NULL; CATALOG_DIR_CACHE_STRUCT *pCatDirCacheStruct = NULL; __try { EnterCriticalSection(&g_CatDirCashCS); } __except(EXCEPTION_EXECUTE_HANDLER) { SetLastError(GetExceptionCode()); CATDBSVC_LOGERR_LASTERR() return FALSE; } // // Cycle through all open DBs and close them // pListNode = LIST_GetFirst(&g_CatalogDBCacheList); while (pListNode != NULL) { pCatDirCacheStruct = (CATALOG_DIR_CACHE_STRUCT *) LIST_GetElement(pListNode); if (!(pCatDirCacheStruct->fDBCurrentlyInUse)) { if (!_CatDBCloseDatabaseFile(&(pCatDirCacheStruct->JetDBStruct))) { fCloseFailed = TRUE; CATDBSVC_LOGERR_LASTERR() } _CatDBFree(pCatDirCacheStruct->JetDBStruct.pszDBFileName); _CatDBFree(pCatDirCacheStruct->pwszSubSysGUID); pListNode = LIST_GetNext(pListNode); LIST_RemoveElement(&g_CatalogDBCacheList, pCatDirCacheStruct); _CatDBFree(pCatDirCacheStruct); } else { fDatabaseFoundThatIsInUse = TRUE; pListNode = LIST_GetNext(pListNode); } } if (fDatabaseFoundThatIsInUse || fCloseFailed) { fRet = FALSE; } LeaveCriticalSection(&g_CatDirCashCS); return fRet; } //--------------------------------------------------------------------------------------- // // _CatDBWaitOrTimerCallback // //--------------------------------------------------------------------------------------- VOID CALLBACK _CatDBWaitOrTimerCallback( PVOID lpParameter, BOOLEAN fTimedOut) { // // If we are being called because we timed out (the event wasn't set), that // means we should close the database if possible... otherwise, the event // was set because we are shutting down, so don't do anything and just let the // shutdown-cleanup code handle it. // if (fTimedOut) { if (!_CatDBCloseSingleCachedDatabase((CATALOG_DIR_CACHE_STRUCT *) lpParameter)) { CATDBSVC_LOGERR_LASTERR() } } // // Since we have a thread, try to clean up the temp files // _CatDBCleanupTempFiles(); } //--------------------------------------------------------------------------------------- // // _CatDBAddCatalogEntriesToDatabase // //--------------------------------------------------------------------------------------- BOOL _CatDBAddCatalogEntriesToDatabase( PJET_DB_STRUCT pJetDBStruct, PCCTL_CONTEXT pCTLContext, LPWSTR pwszNewCatalogName) { BOOL fRet = TRUE; JET_ERR jerr; WCHAR *pwszCatBaseName; DWORD i; CRYPT_DATA_BLOB CryptDataBlob; SPC_INDIRECT_DATA_CONTENT *pIndirectData = NULL; CryptDataBlob.pbData = NULL; // // Extract the base name from the full path name // if (NULL == (pwszCatBaseName = wcsrchr(pwszNewCatalogName, L'\\'))) { pwszCatBaseName = wcsrchr(pwszNewCatalogName, L':'); } if (pwszCatBaseName != NULL) { pwszCatBaseName++; } else { pwszCatBaseName = pwszNewCatalogName; } // // Loop for each hash in the catalog file // for (i=0; ipCtlInfo->cCTLEntry; i++) { if (!_CatDBFindAndDecodeHashInCatEntry( &(pCTLContext->pCtlInfo->rgCTLEntry[i]), &pIndirectData)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } if (!_CatDBAddHashCatNamePair( pJetDBStruct, &(pIndirectData->Digest), pwszCatBaseName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } _CatDBFree(pIndirectData); pIndirectData = NULL; } CommonReturn: return fRet; ErrorReturn: if (pIndirectData != NULL) { _CatDBFree(pIndirectData); } fRet = FALSE; goto CommonReturn; } //--------------------------------------------------------------------------------------- // // _CatDBAddHashCatNamePair // //--------------------------------------------------------------------------------------- BOOL _CatDBAddHashCatNamePair( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob, LPWSTR pwszCatBaseName) { BOOL fRet = TRUE; JET_ERR jerr; // // First, try to find the hash in the HashCatName table. // jerr = _CatDBSeekInHashCatNameTable(pJetDBStruct, pHashBlob); if (jerr == JET_errRecordNotFound) { // // not found // if (!_CatDBAddNewRowToHashCatNameTable( pJetDBStruct, pHashBlob, pwszCatBaseName)) { goto ErrorReturn; } } else if (jerr == JET_errSuccess) { // // found // if (!_CatDBAddValueToExistingHashCatNameRow( pJetDBStruct, pHashBlob, pwszCatBaseName)) { goto ErrorReturn; } } else if (_CatDBJET_errFailure(jerr)) { // // error // CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBAddNewRowToHashCatNameTable // //--------------------------------------------------------------------------------------- BOOL _CatDBAddNewRowToHashCatNameTable( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob, LPWSTR pwszCatBaseName) { BOOL fRet = TRUE; JET_ERR jerr; JET_SETINFO JetSetInfo; // // Create the new row, and insert the values // if (_CatDBJET_errFailure(jerr = JetPrepareUpdate( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, JET_prepInsert))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // hash if (_CatDBJET_errFailure(jerr = JetSetColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_HashColumnID, pHashBlob->pbData, pHashBlob->cbData, 0, NULL))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // catname memset(&JetSetInfo, 0, sizeof(JetSetInfo)); JetSetInfo.cbStruct = sizeof(JetSetInfo); JetSetInfo.itagSequence = 1; if (_CatDBJET_errFailure(jerr = JetSetColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_CatNameColumnID, (BYTE const *) pwszCatBaseName, (wcslen(pwszCatBaseName) + 1) * sizeof(WCHAR), 0, &JetSetInfo))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetUpdate( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, NULL, 0, NULL))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBAddValueToExistingHashCatNameRow // //--------------------------------------------------------------------------------------- BOOL _CatDBAddValueToExistingHashCatNameRow( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob, LPWSTR pwszCatBaseName) { BOOL fRet = TRUE; JET_ERR jerr; JET_SETINFO JetSetInfo; WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH]; DWORD dwLength; JET_RETINFO JetRetInfo; // // Make sure we are not here because a single hash is in the same catalog twice... // // if (_CatDBCatnameAlreadyInHashesListOfCats( pJetDBStruct, pHashBlob, pwszCatBaseName)) { goto CommonReturn; } // // Create a row in the CatNameBuddy Table for the current catalog if it // doesn't already exist // if (!_CatDBAddNewRowToCatNameBuddyTableIfNotExists( pJetDBStruct, pwszCatBaseName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Get each catalog name in the current hashes CatNameList and add it to the // current catalogs buddy list // memset(&JetRetInfo, 0, sizeof(JetRetInfo)); JetRetInfo.cbStruct = sizeof(JetRetInfo); JetRetInfo.itagSequence = 1; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_CatNameColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); while (jerr == JET_errSuccess) { if (!_CatDBAddNewRowToCatNameBuddyTableIfNotExists( pJetDBStruct, wszCatalogName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Add the buddy that was found to the current catalogs buddy list // if (!_CatDBAddNameToBuddyList( pJetDBStruct, wszCatalogName, pwszCatBaseName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Add the buddys of the buddy that was found, to current catalogs buddy list // if (!_CatDBAddWholeBuddyList( pJetDBStruct, pwszCatBaseName, wszCatalogName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Add the current catalog to the buddy list of the buddy that was found // if (!_CatDBAddNameToBuddyList( pJetDBStruct, pwszCatBaseName, wszCatalogName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Setup for next loop // JetRetInfo.itagSequence++; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_CatNameColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); } // // Check to see if a real error occurred and not just a JET_wrnColumnNull // if (_CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // // Add the current catalog to the CatNameList of the current hash // if (_CatDBJET_errFailure(jerr = JetPrepareUpdate( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, JET_prepReplace))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } memset(&JetSetInfo, 0, sizeof(JetSetInfo)); JetSetInfo.cbStruct = sizeof(JetSetInfo); JetSetInfo.itagSequence = 0; // insert into next open position if (_CatDBJET_errFailure(jerr = JetSetColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_CatNameColumnID, (BYTE const *) pwszCatBaseName, (wcslen(pwszCatBaseName) + 1) * sizeof(WCHAR), 0, &JetSetInfo))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetUpdate( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, NULL, 0, NULL))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBCatnameAlreadyInHashesListOfCats // //--------------------------------------------------------------------------------------- BOOL _CatDBCatnameAlreadyInHashesListOfCats( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob, LPWSTR pwszCatBaseName) { JET_ERR jerr; WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH]; DWORD dwLength; JET_RETINFO JetRetInfo; // // Get each catalog name in the current hashes CatNameList see if it is the same // as pwszCatBaseName // memset(&JetRetInfo, 0, sizeof(JetRetInfo)); JetRetInfo.cbStruct = sizeof(JetRetInfo); JetRetInfo.itagSequence = 1; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_CatNameColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); while (jerr == JET_errSuccess) { if (_wcsicmp(wszCatalogName, pwszCatBaseName) == 0) { // // Duplicate found // return TRUE; } // // Setup for next loop // JetRetInfo.itagSequence++; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_CatNameColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); } // // No duplicates were found // return FALSE; } //--------------------------------------------------------------------------------------- // // _CatDBAddNewRowToCatNameBuddyTableIfNotExists // //--------------------------------------------------------------------------------------- BOOL _CatDBAddNewRowToCatNameBuddyTableIfNotExists( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatBaseName) { BOOL fRet = TRUE; JET_ERR jerr; // // Try to find the CatName in the CatNameBuddy table. // jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszCatBaseName); if (jerr == JET_errRecordNotFound) { // // not found, so add the row // if (!_CatDBAddNewRowToCatNameBuddyTable(pJetDBStruct, pwszCatBaseName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } else if (_CatDBJET_errFailure(jerr)) { // // error // CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // else, it was found, so just return successfully CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBAddNewRowToCatNameBuddyTable // //--------------------------------------------------------------------------------------- BOOL _CatDBAddNewRowToCatNameBuddyTable( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatBaseName) { BOOL fRet = TRUE; JET_ERR jerr; JET_SETINFO JetSetInfo; // // Create the new row, and insert the values // if (_CatDBJET_errFailure(jerr = JetPrepareUpdate( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, JET_prepInsert))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // catname if (_CatDBJET_errFailure(jerr = JetSetColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, pJetDBStruct->JetCatNameBuddyTable_CatNameColumnID, (BYTE const *) pwszCatBaseName, (wcslen(pwszCatBaseName) + 1) * sizeof(WCHAR), 0, NULL))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetUpdate( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, NULL, 0, NULL))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBAddNameToBuddyList // //--------------------------------------------------------------------------------------- BOOL _CatDBAddNameToBuddyList( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszNameToAdd, LPWSTR pwszListToAddTo) { BOOL fRet = TRUE; JET_ERR jerr; JET_SETINFO JetSetInfo; JET_RETINFO JetRetInfo; WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH]; DWORD dwLength; // // Don't add the same name to itself // if (_wcsicmp(pwszNameToAdd, pwszListToAddTo) == 0) { goto CommonReturn; } // // seek to the pwszListToAddTo row in the CatNameBuddy table // jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszListToAddTo); if (jerr == JET_errRecordNotFound) { // // this bad, since we know the row should exist // CATDBSVC_SETERR_LOG_RETURN(JET_errRecordNotFound, ErrorJetDatabase) } else if (_CatDBJET_errFailure(jerr)) { // // error // CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // // Check to see if the buddy being added is already there. // memset(&JetRetInfo, 0, sizeof(JetRetInfo)); JetRetInfo.cbStruct = sizeof(JetRetInfo); JetRetInfo.itagSequence = 1; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); while (jerr == JET_errSuccess) { // // Compare to see if this is the name we are supposed to add, // if so, we are done, so get out // if (_wcsicmp(pwszNameToAdd, wszCatalogName) == 0) { goto CommonReturn; } // // Setup for next loop // JetRetInfo.itagSequence++; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); } // // Check to see if a real error occurred and not just a JET_wrnColumnNull // if (_CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // // Prepare, then insert the new buddy name into the list // if (_CatDBJET_errFailure(jerr = JetPrepareUpdate( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, JET_prepReplace))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } memset(&JetSetInfo, 0, sizeof(JetSetInfo)); JetSetInfo.cbStruct = sizeof(JetSetInfo); JetSetInfo.itagSequence = 0; // insert in next open position if (_CatDBJET_errFailure(jerr = JetSetColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID, (BYTE const *) pwszNameToAdd, (wcslen(pwszNameToAdd) + 1) * sizeof(WCHAR), 0, &JetSetInfo))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetUpdate( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, NULL, 0, NULL))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBAddWholeBuddyList // //--------------------------------------------------------------------------------------- BOOL _CatDBAddWholeBuddyList( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszBuddyToAddTo, LPWSTR pwszBuddyListName) { BOOL fRet = TRUE; JET_ERR jerr; JET_RETINFO JetRetInfo; WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH]; DWORD dwLength; // // seek to the pwszBuddyListName row in the CatNameBuddy table // jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszBuddyListName); if (jerr == JET_errRecordNotFound) { // // this bad, since we know the row should exist // CATDBSVC_SETERR_LOG_RETURN(JET_errRecordNotFound, ErrorJetDatabase) } else if (_CatDBJET_errFailure(jerr)) { // // error // CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // // Get each buddy in the list and add it to pwszBuddyToAddTo's buddy list // memset(&JetRetInfo, 0, sizeof(JetRetInfo)); JetRetInfo.cbStruct = sizeof(JetRetInfo); JetRetInfo.itagSequence = 1; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); while (jerr == JET_errSuccess) { // // Add the buddy that was found to the current catalogs buddy list // if (!_CatDBAddNameToBuddyList( pJetDBStruct, wszCatalogName, pwszBuddyToAddTo)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // setup for next loop // // // NOTE - we have to re-seek since the cursor was reset in // the _CatDBAddNameToBuddyList call // jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszBuddyListName); if (jerr == JET_errRecordNotFound) { // // this bad, since we know the row should exist // CATDBSVC_SETERR_LOG_RETURN(JET_errRecordNotFound, ErrorJetDatabase) } else if (jerr != JET_errSuccess) { // // error // CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } JetRetInfo.itagSequence++; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); } // // Check to see if a real error occurred and not just a JET_wrnColumnNull // if (_CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBMoveInUseFileToTempLocation // //--------------------------------------------------------------------------------------- BOOL _CatDBMoveInUseFileToTempLocation( LPWSTR pwszFile ) { BOOL fRet = TRUE; WCHAR wszTempFile[MAX_PATH]; HKEY hKey = NULL; HKEY hKey2 = NULL; DWORD dwDisposition; DWORD i; // // Get the temp file name that the file will be renamed to // if (0 == GetTempFileNameW( g_pwszCatalogFileBaseDirectory, L"TMP", 0, wszTempFile)) { CATDBSVC_LOGERR_LASTERR() goto ErrorGetTempFileName; } // // GetTempFileName actually creates the file, so delete it before doing // the move // DeleteFileW(wszTempFile); // // Move the file to a temporary name // if (!MoveFileW(pwszFile, wszTempFile)) { CATDBSVC_LOGERR_LASTERR() goto ErrorMoveFile; } // // The moved copy is still being accessed, so log the name of the file // to make sure it gets cleaned up later. // if (RegCreateKeyExW( HKEY_LOCAL_MACHINE, WSZ_REG_TEMP_FILES_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) { // // convert all '\\' to '*' // for (i=0; ipCtlInfo->cCTLEntry; i++) { if (!_CatDBFindAndDecodeHashInCatEntry( &(pCTLContext->pCtlInfo->rgCTLEntry[i]), &pIndirectData)) { // // Since this failed, fallback and try to delete the catalog // from the DB using the catalogs name only // fDeleteUsingName = TRUE; break; } if (!_CatDBRemoveCatNameFromHashesListOfCatNames( pJetDBStruct, &(pIndirectData->Digest), pwszCatBaseName)) { // // Since this failed, fallback and try to delete the catalog // from the DB using the catalogs name only // fDeleteUsingName = TRUE; break; } _CatDBFree(pIndirectData); pIndirectData = NULL; } } if (fDeleteUsingName) { // // Since that failed, the catalog is most likely corrupt, so just use // the catalog name to delete its entries from the HashCatName table // if (!_CatDBRemoveCatNameFromCatNameTable( pJetDBStruct, pwszCatBaseName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } // // Delete all occurences of CatName from buddy table // if (!_CatDBRemoveCatNameFromBuddyTable( pJetDBStruct, pwszCatBaseName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } CommonReturn: dwErr = GetLastError(); if (pIndirectData != NULL) { _CatDBFree(pIndirectData); } if (pCTLContext != NULL) { CertFreeCTLContext(pCTLContext); } if (pbMappedFile != NULL) { UnmapViewOfFile(pbMappedFile); } if (hMappedFile != NULL) { CloseHandle(hMappedFile); } SetLastError(dwErr); return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; } //--------------------------------------------------------------------------------------- // // _CatDBRemoveCatNameFromHashesListOfCatNames // //--------------------------------------------------------------------------------------- BOOL _CatDBRemoveCatNameFromHashesListOfCatNames( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob, LPWSTR pwszCatBaseName) { BOOL fRet = TRUE; JET_ERR jerr; // // First, try to find the hash in the HashCatName table. // jerr = _CatDBSeekInHashCatNameTable(pJetDBStruct, pHashBlob); if (jerr == JET_errRecordNotFound) { // // Not found, this is OK since a single catalog may contain the same hash // twice, in which case by the second time the hash is being looked for // the row may already be gone. // goto CommonReturn; } else if (jerr == JET_errSuccess) { // // found // if (!_CatDBRemoveCatNameFromMultiValuedColumn( pJetDBStruct, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_CatNameColumnID, pwszCatBaseName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } else if (_CatDBJET_errFailure(jerr)) { // // error // CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBRemoveCatNameFromMultiValuedColumn // //--------------------------------------------------------------------------------------- BOOL _CatDBRemoveCatNameFromMultiValuedColumn( PJET_DB_STRUCT pJetDBStruct, JET_TABLEID jetTableID, JET_COLUMNID jetColumnID, LPWSTR pwszCatBaseName) { BOOL fRet = TRUE; JET_ERR jerr; JET_SETINFO JetSetInfo; WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH]; DWORD dwLength; JET_RETINFO JetRetInfo; BOOL fDeleteRow = FALSE; unsigned long iValueToDelete = 0; // // Search for the CatName in the current row // memset(&JetRetInfo, 0, sizeof(JetRetInfo)); JetRetInfo.cbStruct = sizeof(JetRetInfo); JetRetInfo.itagSequence = 1; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, jetTableID, jetColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); while (jerr == JET_errSuccess) { // // See if this is the one // if (0 == _wcsicmp(pwszCatBaseName, wszCatalogName)) { iValueToDelete = JetRetInfo.itagSequence; if (JetRetInfo.itagSequence == 1) { // // If this CatName is the only one in the row, then // set a flag to just delete the row // JetRetInfo.itagSequence = 2; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, jetTableID, jetColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); if (jerr == JET_wrnColumnNull) { jerr = JET_errSuccess; fDeleteRow = TRUE; } } break; } // // Setup for next loop // JetRetInfo.itagSequence++; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, jetTableID, jetColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); } // // Make sure the CatName was found // if (jerr == JET_wrnColumnNull) { // // Not found, this is OK // goto CommonReturn; } else if (_CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // // If this CatName is the only one in the row, then just delete the row, // otherwise, remove it from the multi-valued column // if (fDeleteRow) { if (_CatDBJET_errFailure(jerr = JetDelete( pJetDBStruct->JetSesID, jetTableID))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } } else { // // Remove the CatName from the current row // if (_CatDBJET_errFailure(jerr = JetPrepareUpdate( pJetDBStruct->JetSesID, jetTableID, JET_prepReplace))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } memset(&JetSetInfo, 0, sizeof(JetSetInfo)); JetSetInfo.cbStruct = sizeof(JetSetInfo); JetSetInfo.itagSequence = iValueToDelete; if (_CatDBJET_errFailure(jerr = JetSetColumn( pJetDBStruct->JetSesID, jetTableID, jetColumnID, NULL, 0, 0, &JetSetInfo))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetUpdate( pJetDBStruct->JetSesID, jetTableID, NULL, 0, NULL))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBRemoveCatNameFromCatNameTable // //--------------------------------------------------------------------------------------- BOOL _CatDBRemoveCatNameFromCatNameTable( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatBaseName) { BOOL fRet = TRUE; JET_ERR jerr; // // Delete this CatName from every row that contains it // jerr = JetMove( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, JET_MoveFirst, 0); while (jerr == JET_errSuccess) { if (!_CatDBRemoveCatNameFromMultiValuedColumn( pJetDBStruct, pJetDBStruct->JetHashCatNameTableID, pJetDBStruct->JetHashCatNameTable_CatNameColumnID, pwszCatBaseName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Setup for next loop // jerr = JetMove( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, JET_MoveNext, 0); } // // See if this was a real error, or just no more records // if ((jerr != JET_errNoCurrentRecord) && _CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBRemoveCatNameFromBuddyTable // //--------------------------------------------------------------------------------------- BOOL _CatDBRemoveCatNameFromBuddyTable( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatBaseName) { BOOL fRet = TRUE; JET_ERR jerr; // // First, delete this CatName's buddy list // jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszCatBaseName); if (jerr == JET_errSuccess) { if (_CatDBJET_errFailure(jerr = JetDelete( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } } // // Second, delete this CatName from everyone elses buddy list // jerr = JetMove( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, JET_MoveFirst, 0); while (jerr == JET_errSuccess) { if (!_CatDBRemoveCatNameFromMultiValuedColumn( pJetDBStruct, pJetDBStruct->JetCatNameBuddyTableID, pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID, pwszCatBaseName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Setup for next loop // jerr = JetMove( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, JET_MoveNext, 0); } // // See if this was a real error, or just no more records // if ((jerr != JET_errNoCurrentRecord) && _CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBAddCatNameAndCatNamesBuddyListToReturnCatNames // //--------------------------------------------------------------------------------------- BOOL _CatDBAddCatNameAndCatNamesBuddyListToReturnCatNames( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszCatName, DWORD __RPC_FAR *pdwNumCatalogNames, LPWSTR __RPC_FAR *__RPC_FAR *pppwszCatalogNames, BOOL fRecursiveCall) { BOOL fRet = TRUE; JET_ERR jerr; JET_RETINFO JetRetInfo; WCHAR wszCatalogName[CATDB_MAX_CATNAME_LENGTH]; DWORD dwLength; // // First add the original catname // if (!_CatDBAddCatNameToReturnBuddyListIfNotExist( pwszCatName, pdwNumCatalogNames, pppwszCatalogNames)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Seek to the catname's buddy list // jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszCatName); if (jerr == JET_errSuccess) { // // Add all the catname's buddies, and catname's buddies' buddies (only do one recursion) // memset(&JetRetInfo, 0, sizeof(JetRetInfo)); JetRetInfo.cbStruct = sizeof(JetRetInfo); JetRetInfo.itagSequence = 1; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); while (jerr == JET_errSuccess) { if (fRecursiveCall) { if (!_CatDBAddCatNameToReturnBuddyListIfNotExist( wszCatalogName, pdwNumCatalogNames, pppwszCatalogNames)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } else { // // Recurse to get the buddies' buddies // if (!_CatDBAddCatNameAndCatNamesBuddyListToReturnCatNames( pJetDBStruct, wszCatalogName, pdwNumCatalogNames, pppwszCatalogNames, TRUE)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } // // Re-seek to the catname's buddy list, since it could have moved in the // recursive call to this function // jerr = _CatDBSeekInCatNameBuddyTable(pJetDBStruct, pwszCatName); if (_CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // // Setup for next loop // JetRetInfo.itagSequence++; jerr = JetRetrieveColumn( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID, wszCatalogName, CATDB_MAX_CATNAME_LENGTH, &dwLength, JET_bitRetrieveCopy, &JetRetInfo); } // // Check to see if a real error occurred and not just a JET_wrnColumnNull // if (_CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBAddCatNameToReturnBuddyListIfNotExist // //--------------------------------------------------------------------------------------- BOOL _CatDBAddCatNameToReturnBuddyListIfNotExist( LPWSTR pwszBuddy, DWORD __RPC_FAR *pdwNumCatalogNames, LPWSTR __RPC_FAR *__RPC_FAR *pppwszCatalogNames) { BOOL fRet = TRUE; DWORD i; BOOL fAlreadyExists = FALSE; LPWSTR *rgTemp = NULL; // // First, see if the name already exists in the list // for (i=0; i<(*pdwNumCatalogNames); i++) { if (_wcsicmp((*pppwszCatalogNames)[i], pwszBuddy) == 0) { fAlreadyExists = TRUE; break; } } // // Add it if it doesn't already exist // if (!fAlreadyExists) { // // Allocate a new slot in the array of buddy names // if ((*pdwNumCatalogNames) == 0) { *pppwszCatalogNames = (LPWSTR __RPC_FAR *) midl_user_allocate(sizeof(LPWSTR)); } else { rgTemp = *pppwszCatalogNames; *pppwszCatalogNames = (LPWSTR __RPC_FAR *) midl_user_reallocate( *pppwszCatalogNames, ((*pdwNumCatalogNames) + 1) * sizeof(LPWSTR)); } // // Make sure allocation worked // if ((*pppwszCatalogNames) == NULL) { *pppwszCatalogNames = rgTemp; CATDBSVC_SETERR_LOG_RETURN(E_OUTOFMEMORY, ErrorMemory) } (*pppwszCatalogNames)[(*pdwNumCatalogNames)] = (LPWSTR) midl_user_allocate((wcslen(pwszBuddy) + 1) * sizeof(WCHAR)); if ((*pppwszCatalogNames)[(*pdwNumCatalogNames)] == NULL) { CATDBSVC_SETERR_LOG_RETURN(E_OUTOFMEMORY, ErrorMemory) } wcscpy((*pppwszCatalogNames)[(*pdwNumCatalogNames)], pwszBuddy); (*pdwNumCatalogNames)++; } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMemory) } //--------------------------------------------------------------------------------------- // // _CatDBSeekInCatNameBuddyTable // //--------------------------------------------------------------------------------------- JET_ERR _CatDBSeekInCatNameBuddyTable( PJET_DB_STRUCT pJetDBStruct, LPWSTR pwszBuddyRow) { JET_ERR jerr; if (_CatDBJET_errFailure(jerr = JetMakeKey( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, (BYTE const *) pwszBuddyRow, (wcslen(pwszBuddyRow) + 1) * sizeof(WCHAR), JET_bitNewKey))) { return jerr; } jerr = JetSeek( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, JET_bitSeekEQ); return jerr; } //--------------------------------------------------------------------------------------- // // _CatDBSeekInHashCatNameTable // //--------------------------------------------------------------------------------------- JET_ERR _CatDBSeekInHashCatNameTable( PJET_DB_STRUCT pJetDBStruct, PCRYPT_DATA_BLOB pHashBlob) { JET_ERR jerr; if (_CatDBJET_errFailure(jerr = JetMakeKey( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, pHashBlob->pbData, pHashBlob->cbData, JET_bitNewKey))) { return jerr; } jerr = JetSeek( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, JET_bitSeekEQ); return jerr; } //--------------------------------------------------------------------------------------- // // _CatDBNotifyClients // //--------------------------------------------------------------------------------------- void _CatDBNotifyClients(void) { DWORD i = 0; while (i < g_NumNotificationStructs) { if (g_rgNotificationStructs[i].hDuplicatedNotificationHandle != INVALID_HANDLE_VALUE) { SetEvent(g_rgNotificationStructs[i].hDuplicatedNotificationHandle); } i++; } } //--------------------------------------------------------------------------------------- // // _CatDBCreateNewCatalogFileName // //--------------------------------------------------------------------------------------- #define SZ_UNIQUE_CAT_FILENAME_FORMAT L"%X.CAT" #define MAX_UNIQUE_CAT_FILES 0xffffffff LPWSTR _CatDBCreateNewCatalogFileName( LPCWSTR pwszCatalogFileDir, LPCWSTR pwszCatName, BOOL *pfFileAlreadyExists) { LPWSTR pwszFullyQualifiedCatName = NULL; WCHAR pwszTempBaseName[56]; BOOL fUniqueFileNameFound; DWORD dw; HANDLE hTestFile = INVALID_HANDLE_VALUE; DWORD dwLastErr = 0; if (pwszCatName != NULL) { // // The caller specified the cat name to use, so just concatenate the // the path and the name // if (NULL == (pwszFullyQualifiedCatName = _CATDBConstructWSTRPath( pwszCatalogFileDir, pwszCatName))) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // See if this file already exists by trying to create the file // hTestFile = CreateFileW( pwszFullyQualifiedCatName, GENERIC_WRITE | GENERIC_READ, 0, // dwShareMode NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // hTemplateFile dwLastErr = GetLastError(); if ((hTestFile == INVALID_HANDLE_VALUE) && ( (dwLastErr == ERROR_FILE_NOT_FOUND) || (dwLastErr == ERROR_PATH_NOT_FOUND) || (dwLastErr == ERROR_BAD_NETPATH))) { *pfFileAlreadyExists = FALSE; } else if (hTestFile == INVALID_HANDLE_VALUE) { *pfFileAlreadyExists = TRUE; } else { *pfFileAlreadyExists = TRUE; CloseHandle(hTestFile); } } else { *pfFileAlreadyExists = FALSE; // // Create a unique name for the directory in question // fUniqueFileNameFound = FALSE; dw = 1; while ((!fUniqueFileNameFound) && (dw != 0)) // (dw == 0) after rollover. { wsprintfW(pwszTempBaseName, SZ_UNIQUE_CAT_FILENAME_FORMAT, dw); if (NULL == (pwszFullyQualifiedCatName = _CATDBConstructWSTRPath( pwszCatalogFileDir, pwszTempBaseName))) if (pwszFullyQualifiedCatName == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // See if this is a unique file name by trying to create the file // hTestFile = CreateFileW( pwszFullyQualifiedCatName, GENERIC_WRITE | GENERIC_READ, 0, // dwShareMode NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // hTemplateFile if (hTestFile == INVALID_HANDLE_VALUE) { fUniqueFileNameFound = TRUE; } else { CloseHandle(hTestFile); // // Setup for next iteration // _CatDBFree(pwszFullyQualifiedCatName); pwszFullyQualifiedCatName = NULL; dw++; } } } CommonReturn: return pwszFullyQualifiedCatName; ErrorReturn: if (pwszFullyQualifiedCatName != NULL) { _CatDBFree(pwszFullyQualifiedCatName); } pwszFullyQualifiedCatName = NULL; goto CommonReturn; } //--------------------------------------------------------------------------------------- // // _CatDBFindAndDecodeHashInCatEntry // //--------------------------------------------------------------------------------------- BOOL _CatDBFindAndDecodeHashInCatEntry( PCTL_ENTRY pctlEntry, SPC_INDIRECT_DATA_CONTENT **ppIndirectData) { BOOL fRet = TRUE; DWORD i; DWORD cbIndirectData = 0; *ppIndirectData = NULL; // // Search for the hash in the attributes // for (i=0; icAttribute; i++) { if (strcmp(pctlEntry->rgAttribute[i].pszObjId, SPC_INDIRECT_DATA_OBJID) == 0) { break; } } // // Make sure the hash was found // if (i >= pctlEntry->cAttribute) { CATDBSVC_LOGERR_LASTERR() goto ErrorInvalidCatalogFormat; } // // decode the indirect data // if (!CryptDecodeObject( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, SPC_INDIRECT_DATA_CONTENT_STRUCT, pctlEntry->rgAttribute[i].rgValue[0].pbData, pctlEntry->rgAttribute[i].rgValue[0].cbData, 0, NULL, &cbIndirectData)) { CATDBSVC_LOGERR_LASTERR() goto ErrorCryptDecodeObject; } if (NULL == (*ppIndirectData = (SPC_INDIRECT_DATA_CONTENT *) _CatDBAlloc(cbIndirectData))) { CATDBSVC_LOGERR_LASTERR() goto ErrorMemory; } if (!CryptDecodeObject( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, SPC_INDIRECT_DATA_CONTENT_STRUCT, pctlEntry->rgAttribute[i].rgValue[0].pbData, pctlEntry->rgAttribute[i].rgValue[0].cbData, 0, *ppIndirectData, &cbIndirectData)) { CATDBSVC_LOGERR_LASTERR() goto ErrorCryptDecodeObject; } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorInvalidCatalogFormat) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorCryptDecodeObject) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorMemory) } #define SZ_HASH_CATNAME_TABLE "HashCatNameTable" #define SZ_HASH_CATNAME_TABLE_HASHCOL "HashCatNameTable_HashCol" #define SZ_HASH_CATNAME_TABLE_CATNAMECOL "HashCatNameTable_CatNameCol" #define SZ_HASH_CATNAME_TABLE_INDEX "HashCatNameTable_Index" #define SZ_HASH_CATNAME_TABLE_INDEX_DEF "+HashCatNameTable_HashCol\0" #define SZ_CATNAME_BUDDY_TABLE "CatNameBuddyTable" #define SZ_CATNAME_BUDDY_TABLE_CATNAMECOL "CatNameBuddyTable_CatNameCol" #define SZ_CATNAME_BUDDY_TABLE_BUDDYCOL "CatNameBuddyTable_BuddyCol" #define SZ_CATNAME_BUDDY_TABLE_INDEX "CatNameBuddyTable_Index" #define SZ_CATNAME_BUDDY_TABLE_INDEX_DEF "+CatNameBuddyTable_CatNameCol\0" //--------------------------------------------------------------------------------------- // // _CatDBInitJetDatabaseParams // //--------------------------------------------------------------------------------------- typedef struct _DBJETPARAM { DWORD paramid; DWORD lParam; char *pszParam; } DBJETPARAM; DBJETPARAM g_rgJetParams[] = { #define JP_LOGPATH 0 { JET_paramLogFilePath, 0, NULL}, #define JP_SYSTEMPATH 1 { JET_paramSystemPath, 0, NULL}, #define JP_TEMPPATH 2 { JET_paramTempPath, 0, NULL}, { JET_paramEventSource, 0, "Catalog Database"}, { JET_paramMaxVerPages, 1024, NULL}, #if !defined(_M_IA64) && !defined(_M_AXP64) { JET_paramEventLogCache, 32768, NULL}, #endif { JET_paramCircularLog, 1, NULL}, { JET_paramNoInformationEvent, 1, NULL}, { JET_paramAccessDeniedRetryPeriod, 1000, NULL} }; #define CDBPARAM (sizeof(g_rgJetParams)/sizeof(g_rgJetParams[0])) BOOL _CatDBInitJetDatabaseParams( JET_INSTANCE *pJetInstance) { BOOL fRet = TRUE; JET_ERR jerr; DWORD dw; LPSTR pszTempPath = NULL; DBJETPARAM const *pjp; // // Create a temp path for cat db // if (NULL == (pszTempPath = _CatDBGetCatrootDirA())) { CATDBSVC_LOGERR_LASTERR() goto ErrorGetSystemDirectory; } // // Initialize the Jet Parameters // g_rgJetParams[JP_LOGPATH].pszParam = pszTempPath; g_rgJetParams[JP_SYSTEMPATH].pszParam = pszTempPath; g_rgJetParams[JP_TEMPPATH].pszParam = pszTempPath; for (pjp = g_rgJetParams; pjp < &g_rgJetParams[CDBPARAM]; pjp++) { if (_CatDBJET_errFailure(jerr = JetSetSystemParameter( pJetInstance, 0, pjp->paramid, pjp->lParam, pjp->pszParam))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } } CommonReturn: if (pszTempPath != NULL) { free(pszTempPath); } return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorGetSystemDirectory) } //--------------------------------------------------------------------------------------- // // _CatDBGetColumnIDs // //--------------------------------------------------------------------------------------- BOOL _CatDBGetColumnIDs( PJET_DB_STRUCT pJetDBStruct) { BOOL fRet = TRUE; JET_ERR jerr; JET_COLUMNDEF JetColumnDef; BOOL fHashCatNameTableOpen = FALSE; BOOL fCatNameBuddyTableOpen = FALSE; DWORD dwErr = 0; // // Hash-CatName table and columns // if (_CatDBJET_errFailure(jerr = JetOpenTable( pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, SZ_HASH_CATNAME_TABLE, NULL, 0, 0, &(pJetDBStruct->JetHashCatNameTableID)))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } fHashCatNameTableOpen = TRUE; if (_CatDBJET_errFailure(jerr = JetGetColumnInfo( pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, SZ_HASH_CATNAME_TABLE, SZ_HASH_CATNAME_TABLE_HASHCOL, &JetColumnDef, sizeof(JetColumnDef), JET_ColInfo))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } pJetDBStruct->JetHashCatNameTable_HashColumnID = JetColumnDef.columnid; if (_CatDBJET_errFailure(jerr = JetGetColumnInfo( pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, SZ_HASH_CATNAME_TABLE, SZ_HASH_CATNAME_TABLE_CATNAMECOL, &JetColumnDef, sizeof(JetColumnDef), JET_ColInfo))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } pJetDBStruct->JetHashCatNameTable_CatNameColumnID = JetColumnDef.columnid; // // CatNameBuddy table and columns // if (_CatDBJET_errFailure(jerr = JetOpenTable( pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, SZ_CATNAME_BUDDY_TABLE, NULL, 0, 0, &(pJetDBStruct->JetCatNameBuddyTableID)))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } fCatNameBuddyTableOpen = TRUE; if (_CatDBJET_errFailure(jerr = JetGetColumnInfo( pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, SZ_CATNAME_BUDDY_TABLE, SZ_CATNAME_BUDDY_TABLE_CATNAMECOL, &JetColumnDef, sizeof(JetColumnDef), JET_ColInfo))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } pJetDBStruct->JetCatNameBuddyTable_CatNameColumnID = JetColumnDef.columnid; if (_CatDBJET_errFailure(jerr = JetGetColumnInfo( pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, SZ_CATNAME_BUDDY_TABLE, SZ_CATNAME_BUDDY_TABLE_BUDDYCOL, &JetColumnDef, sizeof(JetColumnDef), JET_ColInfo))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } pJetDBStruct->JetCatNameBuddyTable_BuddyColumnID = JetColumnDef.columnid; CommonReturn: return fRet; ErrorReturn: dwErr = GetLastError(); if (fHashCatNameTableOpen) { JetCloseTable(pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID); } if (fCatNameBuddyTableOpen) { JetCloseTable(pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID); } SetLastError(dwErr); fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBCreateDBFile // //--------------------------------------------------------------------------------------- BOOL _CatDBCreateDBFile( PJET_DB_STRUCT pJetDBStruct, LPSTR pszDBFileName) { BOOL fRet = TRUE; JET_ERR jerr; JET_COLUMNDEF JetColumnDef; BOOL fDBFileOpen = FALSE; BOOL fDBFileCreated = FALSE; BOOL fTransactionBegun = FALSE; DWORD dwErr = 0; JET_DBID LocalJetDBID = 0; JET_TABLEID LocalJetHashCatNameTableID = 0; JET_COLUMNID LocalJetHashCatNameTable_HashColumnID = 0; JET_COLUMNID LocalJetHashCatNameTable_CatNameColumnID = 0; JET_TABLEID LocalJetCatNameBuddyTableID = 0; JET_COLUMNID LocalJetCatNameBuddyTable_CatNameColumnID = 0; JET_COLUMNID LocalJetCatNameBuddyTable_BuddyColumnID = 0; // // Create the actual db file // if (_CatDBJET_errFailure(jerr = JetCreateDatabase( pJetDBStruct->JetSesID, pszDBFileName, NULL, &(LocalJetDBID), 0))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } fDBFileCreated = TRUE; fDBFileOpen = TRUE; if (_CatDBJET_errFailure(jerr = JetCloseDatabase( pJetDBStruct->JetSesID, LocalJetDBID, 0))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } fDBFileOpen = FALSE; if (_CatDBJET_errFailure(jerr = JetOpenDatabase( pJetDBStruct->JetSesID, pszDBFileName, NULL, &(LocalJetDBID), 0))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } fDBFileOpen = TRUE; // // Add the whole schema to the db file (tables, columns, indexes) // if (_CatDBJET_errFailure(jerr = JetBeginTransaction(pJetDBStruct->JetSesID))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } fTransactionBegun = TRUE; // // Create the hash-catname table, columns, and indexes // if (_CatDBJET_errFailure(jerr = JetCreateTable( pJetDBStruct->JetSesID, LocalJetDBID, SZ_HASH_CATNAME_TABLE, 4, 100, &(LocalJetHashCatNameTableID)))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetCloseTable( pJetDBStruct->JetSesID, LocalJetHashCatNameTableID))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetOpenTable( pJetDBStruct->JetSesID, LocalJetDBID, SZ_HASH_CATNAME_TABLE, NULL, 0, 0, &(LocalJetHashCatNameTableID)))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // Hash column memset(&JetColumnDef, 0, sizeof(JetColumnDef)); JetColumnDef.cbStruct = sizeof(JetColumnDef); JetColumnDef.langid = 0x409; JetColumnDef.wCountry = 1; JetColumnDef.coltyp = JET_coltypBinary; JetColumnDef.grbit = JET_bitColumnNotNULL; if (_CatDBJET_errFailure(jerr = JetAddColumn( pJetDBStruct->JetSesID, LocalJetHashCatNameTableID, SZ_HASH_CATNAME_TABLE_HASHCOL, &JetColumnDef, NULL, 0, &(LocalJetHashCatNameTable_HashColumnID)))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // CatName column memset(&JetColumnDef, 0, sizeof(JetColumnDef)); JetColumnDef.cbStruct = sizeof(JetColumnDef); JetColumnDef.cp = 1200; // unicode (1200) instead of Ascii (1252) JetColumnDef.langid = 0x409; JetColumnDef.wCountry = 1; JetColumnDef.coltyp = JET_coltypText; JetColumnDef.cbMax = 255; JetColumnDef.grbit = JET_bitColumnMultiValued | JET_bitColumnTagged; if (_CatDBJET_errFailure(jerr = JetAddColumn( pJetDBStruct->JetSesID, LocalJetHashCatNameTableID, SZ_HASH_CATNAME_TABLE_CATNAMECOL, &JetColumnDef, NULL, 0, &(LocalJetHashCatNameTable_CatNameColumnID)))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // Hash-CatName table index if (_CatDBJET_errFailure(jerr = JetCreateIndex( pJetDBStruct->JetSesID, LocalJetHashCatNameTableID, SZ_HASH_CATNAME_TABLE_INDEX, JET_bitIndexPrimary, SZ_HASH_CATNAME_TABLE_INDEX_DEF, strlen(SZ_HASH_CATNAME_TABLE_INDEX_DEF) + 2, 80))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // // Create the CatName-Buddy table, columns, and indexes // if (_CatDBJET_errFailure(jerr = JetCreateTable( pJetDBStruct->JetSesID, LocalJetDBID, SZ_CATNAME_BUDDY_TABLE, 4, 100, &(LocalJetCatNameBuddyTableID)))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetCloseTable( pJetDBStruct->JetSesID, LocalJetCatNameBuddyTableID))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetOpenTable( pJetDBStruct->JetSesID, LocalJetDBID, SZ_CATNAME_BUDDY_TABLE, NULL, 0, 0, &(LocalJetCatNameBuddyTableID)))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // CatName column memset(&JetColumnDef, 0, sizeof(JetColumnDef)); JetColumnDef.cbStruct = sizeof(JetColumnDef); JetColumnDef.cp = 1200; // unicode (1200) instead of Ascii (1252) JetColumnDef.langid = 0x409; JetColumnDef.wCountry = 1; JetColumnDef.coltyp = JET_coltypText; JetColumnDef.cbMax = 255; JetColumnDef.grbit = JET_bitColumnNotNULL; if (_CatDBJET_errFailure(jerr = JetAddColumn( pJetDBStruct->JetSesID, LocalJetCatNameBuddyTableID, SZ_CATNAME_BUDDY_TABLE_CATNAMECOL, &JetColumnDef, NULL, 0, &(LocalJetCatNameBuddyTable_CatNameColumnID)))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // Buddy column memset(&JetColumnDef, 0, sizeof(JetColumnDef)); JetColumnDef.cbStruct = sizeof(JetColumnDef); JetColumnDef.cp = 1200; // unicode (1200) instead of Ascii (1252) JetColumnDef.langid = 0x409; JetColumnDef.wCountry = 1; JetColumnDef.coltyp = JET_coltypText; JetColumnDef.cbMax = 255; JetColumnDef.grbit = JET_bitColumnMultiValued | JET_bitColumnTagged; if (_CatDBJET_errFailure(jerr = JetAddColumn( pJetDBStruct->JetSesID, LocalJetCatNameBuddyTableID, SZ_CATNAME_BUDDY_TABLE_BUDDYCOL, &JetColumnDef, NULL, 0, &(LocalJetCatNameBuddyTable_BuddyColumnID)))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // CatName-Buddy table index if (_CatDBJET_errFailure(jerr = JetCreateIndex( pJetDBStruct->JetSesID, LocalJetCatNameBuddyTableID, SZ_CATNAME_BUDDY_TABLE_INDEX, JET_bitIndexPrimary, SZ_CATNAME_BUDDY_TABLE_INDEX_DEF, strlen(SZ_CATNAME_BUDDY_TABLE_INDEX_DEF) + 2, 80))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } // // Now that all the schema has been successfully added, COMMIT // if (_CatDBJET_errFailure(jerr = JetCommitTransaction( pJetDBStruct->JetSesID, 0))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetCloseDatabase( pJetDBStruct->JetSesID, LocalJetDBID, 0))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: dwErr = GetLastError(); if (fTransactionBegun) { JetRollback(pJetDBStruct->JetSesID, 0); } if (fDBFileOpen) { JetCloseDatabase( pJetDBStruct->JetSesID, LocalJetDBID, 0); } if (fDBFileCreated) { DeleteFileA(pszDBFileName); } SetLastError(dwErr); fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBAttachAndOpenDatabase // //--------------------------------------------------------------------------------------- BOOL _CatDBAttachAndOpenDatabase( JET_DB_STRUCT *pJetDBStruct, BOOL fReadOnly) { BOOL fRet = TRUE; JET_ERR jerr; BOOL fJetDBFileOpen = FALSE; DWORD dwErr = 0; // // Try to attach the existing database, if it doesn't already exist, // then create it // jerr = JetAttachDatabase( pJetDBStruct->JetSesID, pJetDBStruct->pszDBFileName, 0); //fReadOnly ? JET_bitDbReadOnly : 0); if (jerr == JET_errFileNotFound) { // // The DB file doesn't exist yet, so create it // if (!_CatDBCreateDBFile( pJetDBStruct, pJetDBStruct->pszDBFileName)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } } else if (_CatDBJET_errFailure(jerr)) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetOpenDatabase( pJetDBStruct->JetSesID, pJetDBStruct->pszDBFileName, NULL, &(pJetDBStruct->JetDBID), 0))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } fJetDBFileOpen = TRUE; if (!_CatDBGetColumnIDs(pJetDBStruct)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Set the current indexes for both tables so all seeks work // if (_CatDBJET_errFailure(jerr = JetSetCurrentIndex( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID, NULL))) // NULL == primary index { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetSetCurrentIndex( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID, NULL))) // NULL == primary index { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: dwErr = GetLastError(); if (fJetDBFileOpen) { JetCloseDatabase(pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, 0); } SetLastError(dwErr); fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBCloseDatabaseFile // //--------------------------------------------------------------------------------------- BOOL _CatDBCloseDatabaseFile( PJET_DB_STRUCT pJetDBStruct) { BOOL fRet = TRUE; JET_ERR jerr; if (_CatDBJET_errFailure(jerr = JetCloseTable( pJetDBStruct->JetSesID, pJetDBStruct->JetHashCatNameTableID))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetCloseTable( pJetDBStruct->JetSesID, pJetDBStruct->JetCatNameBuddyTableID))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetCloseDatabase( pJetDBStruct->JetSesID, pJetDBStruct->JetDBID, 0))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } if (_CatDBJET_errFailure(jerr = JetDetachDatabase( pJetDBStruct->JetSesID, pJetDBStruct->pszDBFileName))) { // // Only log the error it it isn't a JET_errDatabaseInUse error // if (jerr != JET_errDatabaseInUse) { CATDBSVC_LOGERR(_CatDBMapJetError(jerr)) } } if (_CatDBJET_errFailure(jerr = JetEndSession( pJetDBStruct->JetSesID, 0))) { CATDBSVC_SETERR_LOG_RETURN(_CatDBMapJetError(jerr), ErrorJetDatabase) } CommonReturn: return fRet; ErrorReturn: fRet = FALSE; goto CommonReturn; TRACE_ERROR_EX(DBG_SS_CATDBSVC, ErrorJetDatabase) } //--------------------------------------------------------------------------------------- // // _CatDBCatalogFileAlreadyInstalled // //--------------------------------------------------------------------------------------- BOOL _CatDBCatalogFileAlreadyInstalled( LPCWSTR pwszCatalogToBeAdded, LPCWSTR pwszExistingCatalog) { BOOL fRet = TRUE; HANDLE h1 = NULL; HANDLE h2 = NULL; BYTE rgbHash1[20]; BYTE rgbHash2[20]; DWORD cbHash1 = 20; DWORD cbHash2 = 20; // // Open both files // h1 = CreateFileW( pwszCatalogToBeAdded, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // hTemplateFile if (h1 == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } h2 = CreateFileW( pwszExistingCatalog, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // hTemplateFile if (h1 == NULL) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Get the hash for each file // if (!CryptCATAdminCalcHashFromFileHandle( h1, &cbHash1, rgbHash1, 0)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } if (!CryptCATAdminCalcHashFromFileHandle( h2, &cbHash2, rgbHash2, 0)) { CATDBSVC_LOGERR_LASTERR() goto ErrorReturn; } // // Compare the hashes to see if they are the same // if (memcmp(rgbHash1, rgbHash2, 20) == 0) { fRet = TRUE; } Return: if (h1 != NULL) { CloseHandle(h1); } if (h2 != NULL) { CloseHandle(h2); } return fRet; ErrorReturn: fRet = FALSE; goto Return; } //--------------------------------------------------------------------------------------- // // _CatDBJET_errFailure // //--------------------------------------------------------------------------------------- BOOL _CatDBJET_errFailure( JET_ERR jerr) { if (jerr == JET_errSuccess) { return FALSE; } else if (jerr & 0x80000000) { // // Jet errors are negative numbers, jet warnings are positive // return TRUE; } else { CATDBSVC_LOGWARN(_CatDBMapJetError(jerr)) return FALSE; } } //--------------------------------------------------------------------------------------- // // _CatDBMapJetError // //--------------------------------------------------------------------------------------- DWORD _CatDBMapJetError(JET_ERR jerr) { // FIX FIX return jerr;//ERROR_DATABASE_FAILURE; }