void DVLib::RegistryDeleteKey(HKEY root, const std::wstring& key, DWORD ulFlags) { DWORD namesize, subkeys, maxkeyname; if (ERROR_SUCCESS != ::RegDeleteKey(root, key.c_str())) { HKEY reg = NULL; CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg), L"Error opening '" << HKEY2wstring(root) << L"\\" << key << L"'"); auto_hkey reg_ptr(reg); // query subkey information CHECK_WIN32_DWORD(::RegQueryInfoKey(reg, NULL, NULL, NULL, & subkeys, & maxkeyname, NULL, NULL, NULL, NULL, NULL, NULL), L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"' for subkeys"); // walk through all subkeys, and recursively delete wchar_t name[MAX_PATH] = {0}; namesize = MAX_PATH; while (ERROR_SUCCESS == ::RegEnumKeyEx(reg, 0, name, & namesize, NULL, NULL, NULL, NULL)) { RegistryDeleteKey(root, key + L"\\" + name, ulFlags); namesize = MAX_PATH; } CHECK_WIN32_DWORD(::RegDeleteKey(root, key.c_str()), L"Error deleting '" << HKEY2wstring(root) << L"\\" << key << L"'"); } }
void MsiDatabase::SetSummary(const MsiDatabaseSummaryEntry summary[], int size) { // http://msdn.microsoft.com/en-us/library/aa372045(VS.85).aspx MsiHandle h_summary; CHECK_WIN32_DWORD(::MsiGetSummaryInformation(m_h, NULL, size, & h_summary), L"Error getting MSI summary information"); for (int i = 0; i < size; i++) { switch(summary[i].varValue.vt) { case VT_BSTR: CHECK_WIN32_DWORD(MsiSummaryInfoSetProperty(h_summary, summary[i].dwPropertyId, summary[i].varPropertyType, 0, NULL, static_cast<LPCWSTR>(summary[i].varValue.bstrVal)), L"Error setting property " << summary[i].dwPropertyId); break; case VT_I2: case VT_I4: CHECK_WIN32_DWORD(MsiSummaryInfoSetProperty(h_summary, summary[i].dwPropertyId, summary[i].varPropertyType, summary[i].varValue.iVal, NULL, NULL), L"Error setting property " << summary[i].dwPropertyId); break; default: THROW("unsupported VT type: " << summary[i].varValue.vt); } } CHECK_WIN32_DWORD(::MsiSummaryInfoPersist(h_summary), L"Error persisting summary information"); }
std::wstring DVLib::MsiProductInfo::GetProperty(const std::wstring& property_name) const { std::wstring product_id_s = DVLib::guid2wstring(product_id); std::vector<wchar_t> property_value; DWORD property_size = 0; DWORD property_rc = ::MsiGetProductInfo(product_id_s.c_str(), property_name.c_str(), NULL, & property_size); if (property_rc != ERROR_MORE_DATA) { CHECK_WIN32_DWORD(property_rc, L"MsiGetProductInfo (" << product_id_s << L", " << property_name << L")"); } if (property_size > 0) { property_value.resize(property_size + 1); property_size = property_value.size(); CHECK_WIN32_DWORD(::MsiGetProductInfo(product_id_s.c_str(), property_name.c_str(), & * property_value.begin(), & property_size), L"MsiGetProductInfo (" << product_id_s << L", " << property_name << L")"); return std::wstring(& * property_value.begin(), property_size); } else { return L""; } }
std::wstring DVLib::RegistryGetStringValue(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags) { HKEY reg = NULL; CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg), L"Error opening " << HKEY2wstring(root) << L"\\" << key); auto_hkey reg_ptr(reg); DWORD dwSize = 0; DWORD dwType = 0; CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, NULL, & dwSize), L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value size:"); CHECK_BOOL(dwType == REG_SZ || dwType == REG_EXPAND_SZ, L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value, unexpected type " << dwType); std::wstring value; if (dwSize > 0) { value.resize(dwSize / sizeof(WCHAR)); CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, reinterpret_cast<LPBYTE>(& * value.begin()), & dwSize), L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value data"); value.resize((dwSize - 1) / sizeof(WCHAR)); } return value; }
void DVLib::RegistryDeleteValue(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags) { HKEY reg = NULL; CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_WRITE, & reg), L"Error opening '" << HKEY2wstring(root) << L"\\" << key << L"'"); auto_hkey reg_ptr(reg); CHECK_WIN32_DWORD(::RegDeleteValue(reg, name.c_str()), L"Error deleting '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"'"); }
void MsiDatabase::Execute(const std::wstring& query) { MsiView msiView; CHECK_WIN32_DWORD(::MsiDatabaseOpenView(m_h, query.c_str(), & msiView), L"Error executing " << query); // fetch the record from the view CHECK_WIN32_DWORD(::MsiViewExecute(msiView, NULL), L"Error executing binary view"); }
void DVLib::RegistrySetDWORDValue(HKEY root, const std::wstring& key, const std::wstring& name, DWORD value, DWORD ulFlags) { HKEY hkey = NULL; CHECK_WIN32_DWORD(::RegCreateKeyEx(root, key.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, ulFlags | KEY_SET_VALUE, NULL, & hkey, NULL), L"Error creating '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"'"); auto_hkey hkey_ptr(hkey); CHECK_WIN32_DWORD(::RegSetValueEx(hkey, name.c_str(), 0L, REG_DWORD, reinterpret_cast<const byte *>(& value), sizeof(DWORD)), L"Error setting '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value"); }
bool DVLib::FileExists(const std::wstring& filename) { DWORD dwAttr = GetFileAttributesW(filename.c_str()); if (dwAttr == INVALID_FILE_ATTRIBUTES) { DWORD dwErr = GetLastError(); switch(dwErr) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: return false; default: CHECK_WIN32_DWORD(dwErr, L"GetFileAttributesW: " << filename); } } else if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) { return false; } return true; }
std::vector<std::wstring> DVLib::RegistryGetMultiStringValue(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags) { HKEY reg = NULL; CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg), L"Error opening " << HKEY2wstring(root) << L"\\" << key); auto_hkey reg_ptr(reg); DWORD dwSize = 0; DWORD dwType = 0; CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, NULL, & dwSize), L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value size"); CHECK_BOOL(dwType == REG_MULTI_SZ, L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value, unexpected type " << dwType); std::vector<std::wstring> result; std::vector<wchar_t> value; if (dwSize > 0) { value.resize(dwSize / sizeof(WCHAR)); CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, reinterpret_cast<LPBYTE>(& * value.begin()), & dwSize), L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value data"); value.resize((dwSize - 1) / sizeof(WCHAR)); std::vector<wchar_t>::iterator l = value.begin(); std::vector<wchar_t>::iterator r = value.begin(); while(r != value.end()) { if (* r == 0) { if (l == r) result.push_back(L""); else result.push_back(std::wstring(l, r)); l = r + 1; } r++; } } return result; }
void MsiDatabase::Import(const std::wstring& path, const std::wstring& file) { CHECK_BOOL(IsOpen(), L"A database must be opened first"); CHECK_WIN32_DWORD(::MsiDatabaseImport(m_h, path.c_str(), file.c_str()), L"Error importing " << path << L"\\" << file); }
void MsiDatabase::Commit() { CHECK_BOOL(IsOpen(), L"A database must be opened first"); CHECK_WIN32_DWORD(::MsiDatabaseCommit(m_h), L"Error committing MSI database \"" << _filepath << "\""); }
DWORD DVLib::RegistryGetValueType(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags) { HKEY reg = NULL; CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg), L"Error opening " << HKEY2wstring(root) << L"\\" << key); auto_hkey reg_ptr(reg); DWORD dwSize = 0; DWORD dwType = 0; CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, NULL, & dwSize), L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"'"); return dwType; }
void DVLib::RegistryCreateKey(HKEY root, const std::wstring& key, DWORD ulFlags) { HKEY hkey = NULL; CHECK_WIN32_DWORD(::RegCreateKeyEx(root, key.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, ulFlags | KEY_WRITE, NULL, & hkey, NULL), L"Error creating '" << HKEY2wstring(root) << L"\\" << key << L"'"); ::RegCloseKey(hkey); }
bool DVLib::RegistryValueExists(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags) { HKEY reg = NULL; DWORD dwErr = ::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg); auto_hkey reg_ptr(reg); bool result = true; switch(dwErr) { case ERROR_SUCCESS: break; case ERROR_FILE_NOT_FOUND: result = false; break; default: CHECK_WIN32_DWORD(dwErr, L"Error checking whether '" << HKEY2wstring(root) << L"\\" << key << L"' exists"); break; } if (result) { DWORD dwSize = 0; DWORD dwType = 0; dwErr = ::RegQueryValueEx(reg, name.c_str(), 0, & dwType, NULL, & dwSize); switch(dwErr) { case ERROR_SUCCESS: case ERROR_INSUFFICIENT_BUFFER: break; case ERROR_FILE_NOT_FOUND: result = false; break; default: CHECK_WIN32_DWORD(dwErr, L"Error checking whether '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' exists"); break; } } return result; }
void MsiDatabase::Open(const std::wstring& filepath, LPCTSTR openmode) { if (IsOpen()) { Close(); } CHECK_WIN32_DWORD(::MsiOpenDatabase(filepath.c_str(), openmode, & m_h), L"Error opening MSI database \"" << filepath << "\""); _filepath = filepath; }
void DVLib::RegistrySetMultiStringValue(HKEY root, const std::wstring& key, const std::wstring& name, const std::vector<std::wstring>& value, DWORD ulFlags) { HKEY hkey = NULL; CHECK_WIN32_DWORD(::RegCreateKeyEx(root, key.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, ulFlags | KEY_SET_VALUE, NULL, & hkey, NULL), L"Error creating '" << HKEY2wstring(root) << L"\\" << key << L"'"); auto_hkey hkey_ptr(hkey); std::vector<wchar_t> data; for (size_t i = 0; i < value.size(); i++) { data.insert(data.end(), value[i].begin(), value[i].end()); data.push_back(0); } data.push_back(0); CHECK_WIN32_DWORD(::RegSetValueEx(hkey, name.c_str(), 0L, REG_MULTI_SZ, reinterpret_cast<const byte *>(& * data.begin()), data.size() * sizeof(WCHAR)), L"Error setting '" << HKEY2wstring(root) << L"\\" << key << L"'" << name << L"' value"); }
DWORD DVLib::RegistryGetDWORDValue(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags) { HKEY reg = NULL; CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg), L"Error opening '" << HKEY2wstring(root) << L"\\" << key << L"'"); auto_hkey reg_ptr(reg); DWORD dwSize = 0; DWORD dwType = 0; CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, NULL, & dwSize), L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' size"); CHECK_BOOL(dwType == REG_DWORD && dwSize == sizeof(DWORD), L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"', unexpected type"); DWORD value = 0; CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, reinterpret_cast<LPBYTE>(& value), & dwSize), L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value"); return value; }
bool DVLib::MsiProductInfo::HasProperty(const std::wstring& property_name) const { std::wstring product_id_s = DVLib::guid2wstring(product_id); DWORD property_size = 0; DWORD property_rc = ::MsiGetProductInfo(product_id_s.c_str(), property_name.c_str(), NULL, & property_size); if (property_rc == ERROR_UNKNOWN_PROPERTY) return false; if (property_rc != ERROR_MORE_DATA) { CHECK_WIN32_DWORD(property_rc, L"MsiGetProductInfo (" << product_id_s << L")"); } return true; }
std::wstring DVLib::GetEnvironmentVariable(const std::wstring& name) { DWORD size = ::GetEnvironmentVariableW(name.c_str(), NULL, 0); if (! size) { DWORD dwErr = ::GetLastError(); // no such environment variable if (dwErr == ERROR_ENVVAR_NOT_FOUND) return L""; // other error CHECK_WIN32_DWORD(dwErr, L"GetEnvironmentVariableW"); } std::vector<wchar_t> value; value.resize(size); CHECK_WIN32_BOOL(0 != (size = ::GetEnvironmentVariableW(name.c_str(), & * value.begin(), value.size())), L"GetEnvironmentVariableW"); return std::wstring(& * value.begin(), value.size() - 1); }
std::vector<DVLib::MsiProductInfo> DVLib::MsiGetRelatedProducts(GUID upgradecode) { std::vector<MsiProductInfo> products; std::wstring upgradecode_s = DVLib::guid2wstring(upgradecode); int index = 0; UINT rc = 0; std::vector<wchar_t> buffer; buffer.resize(39); while ((rc = ::MsiEnumRelatedProducts(upgradecode_s.c_str(), 0, index, & * buffer.begin())) == ERROR_SUCCESS) { MsiProductInfo info(DVLib::string2guid(& * buffer.begin())); products.push_back(info); index++; } if (rc != ERROR_NO_MORE_ITEMS) { CHECK_WIN32_DWORD(rc, L"MsiEnumRelatedProducts (" << upgradecode_s << L")"); } return products; }
bool DVLib::RegistryKeyExists(HKEY root, const std::wstring& key, DWORD ulFlags) { HKEY reg = NULL; DWORD dwErr = ::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg); auto_hkey reg_ptr(reg); bool result = true; switch(dwErr) { case ERROR_SUCCESS: break; case ERROR_FILE_NOT_FOUND: result = false; break; default: CHECK_WIN32_DWORD(dwErr, L"Error checking whether '" << HKEY2wstring(root) << L"\\" << key << L"' exists"); break; } return result; }
std::vector<GUID> DVLib::MsiProductInfo::GetUpgradeCodes() const { std::vector<GUID> upgrade_codes; std::wstring local_package = GetLocalPackage(); MsiHandlePtr h; MsiHandlePtr hView; MSIHANDLE _h = NULL; CHECK_WIN32_DWORD(::MsiOpenDatabase(local_package.c_str(), MSIDBOPEN_READONLY, & _h), L"MsiOpenDatabase (" << local_package << L")"); reset(h, _h); MSIHANDLE _hView = NULL; CHECK_WIN32_DWORD(::MsiDatabaseOpenView(get(h), L"SELECT DISTINCT `UpgradeCode` FROM `Upgrade`", & _hView), L"MsiDatabaseOpenView (" << local_package << L")"); reset(hView, _hView); CHECK_WIN32_DWORD(::MsiViewExecute(get(hView), NULL), L"MsiViewExecute (" << local_package << L")"); while(true) { MsiHandlePtr hRow; MSIHANDLE _hRow = NULL; UINT rc = ::MsiViewFetch(get(hView), & _hRow); reset(hRow, _hRow); if (rc == ERROR_NO_MORE_ITEMS) { break; } else if (rc != ERROR_SUCCESS) { CHECK_WIN32_DWORD(rc, L"MsiViewFetch (" << local_package << L")"); } // read upgrade code std::wstring data; DWORD cbRead = 0; CHECK_WIN32_DWORD(::MsiRecordGetString(get(hRow), 1, NULL, & cbRead), L"MsiRecordGetString (" << local_package << L")"); if (cbRead > 0) { data.resize(cbRead++); CHECK_WIN32_DWORD(::MsiRecordGetString(get(hRow), 1, & * data.begin(), & cbRead), L"MsiRecordGetString (" << local_package << L"/" << cbRead << L")"); data.resize(cbRead); } GUID upgrade_code = DVLib::string2guid(data); upgrade_codes.push_back(upgrade_code); } return upgrade_codes; }
static void close(MSIHANDLE h) { CHECK_WIN32_DWORD(::MsiCloseHandle(h), L"MsiCloseHandle (" << std::hex << (h) << L")"); }