void CryptoManager::changeCryptState(thread_db* tdbb, const Firebird::string& plugName) { if (plugName.length() > 31) { (Arg::Gds(isc_cp_name_too_long) << Arg::Num(31)).raise(); } bool newCryptState = plugName.hasData(); { // window scope Header hdr(tdbb, LCK_write); // Check header page for flags if (hdr->hdr_flags & Ods::hdr_crypt_process) { (Arg::Gds(isc_cp_process_active)).raise(); } bool headerCryptState = hdr->hdr_flags & Ods::hdr_encrypted; if (headerCryptState == newCryptState) { (Arg::Gds(isc_cp_already_crypted)).raise(); } fb_assert(stateLock); // Take exclusive stateLock bool ret = needLock ? LCK_lock(tdbb, stateLock, LCK_PW, LCK_WAIT) : LCK_convert(tdbb, stateLock, LCK_PW, LCK_WAIT); if (!ret) { fb_assert(tdbb->tdbb_status_vector[1]); ERR_punt(); } fb_utils::init_status(tdbb->tdbb_status_vector); needLock = false; // Load plugin if (newCryptState) { loadPlugin(plugName.c_str()); } crypt = newCryptState; // Write modified header page Ods::header_page* header = hdr.write(); if (crypt) { header->hdr_flags |= Ods::hdr_encrypted; plugName.copyTo(header->hdr_crypt_plugin, sizeof header->hdr_crypt_plugin); } else { header->hdr_flags &= ~Ods::hdr_encrypted; } header->hdr_flags |= Ods::hdr_crypt_process; process = true; } // Trigger lock on ChangeCryptState if (!LCK_convert(tdbb, stateLock, LCK_EX, LCK_WAIT)) { ERR_punt(); } if (!LCK_convert(tdbb, stateLock, LCK_SR, LCK_WAIT)) { ERR_punt(); } fb_utils::init_status(tdbb->tdbb_status_vector); // Now we may set hdr_crypt_page for crypt thread { // window scope Header hdr(tdbb, LCK_write); Ods::header_page* header = hdr.write(); header->hdr_crypt_page = 1; } startCryptThread(tdbb); }