| /* |
| * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #ifndef MsiDb_h |
| #define MsiDb_h |
| |
| #include <windows.h> |
| #include <msiquery.h> |
| |
| #include "MsiUtils.h" |
| |
| |
| class Guid; |
| |
| namespace msi { |
| |
| void closeDatabaseView(MSIHANDLE h); |
| |
| class CA; |
| class DatabaseView; |
| class DatabaseRecord; |
| |
| |
| /** |
| * Opens product's database to query properties. |
| * The database is opened in R/O mode, i.e. it is safe to call this method |
| * even if there is active install/uninstall session. Unlike MsiOpenProduct(), |
| * it never fails with 1618 ('Another installation is |
| * already in progress') error code. |
| * |
| * Database can be opened from product code GUID, path to msi package or from |
| * custom action. |
| * |
| * If opened from CA the database is opened in R/W mode, however only adding |
| * new temporary records is supported. It is forbidden to change data in |
| * existing records. |
| */ |
| class Database { |
| public: |
| /** |
| * Opens msi database from the given product code GUID. |
| * Throws exception if fails. |
| */ |
| explicit Database(const Guid& productCode); |
| |
| /** |
| * Opens msi database from the given path to .msi file. |
| * Throws exception if fails. |
| */ |
| explicit Database(const tstring& msiPath); |
| |
| /** |
| * Opens msi database from the given custom action. |
| * Throws exception if fails. |
| */ |
| explicit Database(const CA& ca); |
| |
| ~Database() { |
| if (dbHandle != 0) { |
| closeMSIHANDLE(dbHandle); |
| } |
| } |
| |
| /** |
| * Returns value of property with the given name. |
| * Throws NoMoreItemsError if property with the given name doesn't exist |
| * or Error if some error occurred. |
| */ |
| tstring getProperty(const tstring& name) const; |
| |
| /** |
| * Returns value of property with the given name. |
| * Returns empty string if property with the given name doesn't exist or |
| * if some error occurred. |
| */ |
| tstring getProperty(const std::nothrow_t&, const tstring& name) const; |
| |
| friend class DatabaseView; |
| |
| private: |
| Database(const Database&); |
| Database& operator=(const Database&); |
| private: |
| const tstring msiPath; |
| MSIHANDLE dbHandle; |
| }; |
| |
| typedef std::unique_ptr<Database> DatabasePtr; |
| |
| |
| class DatabaseRecord { |
| public: |
| DatabaseRecord(): handle(MSIHANDLE(0)) { |
| } |
| |
| DatabaseRecord(const DatabaseRecord& other): handle(MSIHANDLE(0)) { |
| handle = other.handle; |
| other.handle = 0; |
| } |
| |
| DatabaseRecord& operator=(const DatabaseRecord& other); |
| |
| friend class DatabaseView; |
| |
| explicit DatabaseRecord(unsigned fieldCount); |
| |
| explicit DatabaseRecord(DatabaseView& view) : handle(MSIHANDLE(0)) { |
| fetch(view); |
| } |
| |
| ~DatabaseRecord() { |
| if (handle != 0) { |
| closeMSIHANDLE(handle); |
| } |
| } |
| |
| DatabaseRecord& fetch(DatabaseView& view); |
| |
| DatabaseRecord& tryFetch(DatabaseView& view); |
| |
| DatabaseRecord& setString(unsigned idx, const tstring& v); |
| |
| DatabaseRecord& setInteger(unsigned idx, int v); |
| |
| DatabaseRecord& setStreamFromFile(unsigned idx, const tstring& v); |
| |
| unsigned getFieldCount() const; |
| |
| tstring getString(unsigned idx) const; |
| |
| int getInteger(unsigned idx) const; |
| |
| void saveStreamToFile(unsigned idx, const tstring& path) const; |
| |
| bool empty() const { |
| return 0 == handle; |
| } |
| |
| MSIHANDLE getHandle() const { |
| return handle; |
| } |
| |
| private: |
| mutable MSIHANDLE handle; |
| }; |
| |
| |
| class DatabaseView { |
| public: |
| DatabaseView(const Database& db, const tstring& sqlQuery, |
| const DatabaseRecord& queryParam=DatabaseRecord()); |
| |
| ~DatabaseView() { |
| if (handle != 0) { |
| closeMSIHANDLE(handle); |
| } |
| } |
| |
| DatabaseRecord fetch(); |
| |
| DatabaseRecord tryFetch(); |
| |
| DatabaseView& modify(const DatabaseRecord& record, MSIMODIFY mode); |
| |
| private: |
| tstring sqlQuery; |
| const Database& db; |
| MSIHANDLE handle; |
| }; |
| |
| } // namespace msi |
| |
| #endif // #ifndef MsiDb_h |