diff options
author | Rob Mensching <rob@firegiant.com> | 2021-04-08 14:06:21 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2021-04-12 12:29:11 -0700 |
commit | b2c4600453f926fbfdc63219126930ad39601f25 (patch) | |
tree | b7c8429ffcfe4f1f8b98f9e43b00d671b2d3a1d6 /src/dutil/sqlutil.cpp | |
parent | 0c2b4cf3a439eda3e19d20fadfc65ddc7d0394c0 (diff) | |
download | wix-b2c4600453f926fbfdc63219126930ad39601f25.tar.gz wix-b2c4600453f926fbfdc63219126930ad39601f25.tar.bz2 wix-b2c4600453f926fbfdc63219126930ad39601f25.zip |
Port missing WiX v3 changes
Diffstat (limited to 'src/dutil/sqlutil.cpp')
-rw-r--r-- | src/dutil/sqlutil.cpp | 171 |
1 files changed, 145 insertions, 26 deletions
diff --git a/src/dutil/sqlutil.cpp b/src/dutil/sqlutil.cpp index 63ee80ac..782c7088 100644 --- a/src/dutil/sqlutil.cpp +++ b/src/dutil/sqlutil.cpp | |||
@@ -10,7 +10,22 @@ | |||
10 | #include "sqlutil.h" | 10 | #include "sqlutil.h" |
11 | 11 | ||
12 | 12 | ||
13 | //Please note that only SQL native client 11 has TLS1.2 support | ||
14 | #define _SQLNCLI_OLEDB_DEPRECATE_WARNING | ||
15 | |||
16 | #if !defined(SQLNCLI_VER) | ||
17 | #define SQLNCLI_VER 1100 | ||
18 | #endif | ||
19 | |||
20 | #if SQLNCLI_VER >= 1100 | ||
21 | #if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_) | ||
22 | #define SQLNCLI_CLSID CLSID_SQLNCLI11 | ||
23 | #endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_) | ||
24 | extern const GUID OLEDBDECLSPEC _SQLNCLI_OLEDB_DEPRECATE_WARNING CLSID_SQLNCLI11 = { 0x397C2819L,0x8272,0x4532,{ 0xAD,0x3A,0xFB,0x5E,0x43,0xBE,0xAA,0x39 } }; | ||
25 | #endif // SQLNCLI_VER >= 1100 | ||
26 | |||
13 | // Exit macros | 27 | // Exit macros |
28 | #define SqlExitTrace(x, s, ...) ExitTraceSource(DUTIL_SOURCE_SQLUTIL, x, s, __VA_ARGS__) | ||
14 | #define SqlExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_SQLUTIL, x, s, __VA_ARGS__) | 29 | #define SqlExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_SQLUTIL, x, s, __VA_ARGS__) |
15 | #define SqlExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_SQLUTIL, x, s, __VA_ARGS__) | 30 | #define SqlExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_SQLUTIL, x, s, __VA_ARGS__) |
16 | #define SqlExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_SQLUTIL, x, s, __VA_ARGS__) | 31 | #define SqlExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_SQLUTIL, x, s, __VA_ARGS__) |
@@ -25,11 +40,18 @@ | |||
25 | #define SqlExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_SQLUTIL, g, x, s, __VA_ARGS__) | 40 | #define SqlExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_SQLUTIL, g, x, s, __VA_ARGS__) |
26 | 41 | ||
27 | // private prototypes | 42 | // private prototypes |
43 | static HRESULT InitializeDatabaseConnection( | ||
44 | __in REFCLSID rclsid, | ||
45 | __in_z LPCSTR szFriendlyClsidName, | ||
46 | __in DBPROPSET rgdbpsetInit[], | ||
47 | __in_ecount(rgdbpsetInit) DWORD cdbpsetInit, | ||
48 | __out IDBCreateSession** ppidbSession | ||
49 | ); | ||
50 | HRESULT DumpErrorRecords(); | ||
28 | static HRESULT FileSpecToString( | 51 | static HRESULT FileSpecToString( |
29 | __in const SQL_FILESPEC* psf, | 52 | __in const SQL_FILESPEC* psf, |
30 | __out LPWSTR* ppwz | 53 | __out LPWSTR* ppwz |
31 | ); | 54 | ); |
32 | |||
33 | static HRESULT EscapeSqlIdentifier( | 55 | static HRESULT EscapeSqlIdentifier( |
34 | __in_z LPCWSTR wzDatabase, | 56 | __in_z LPCWSTR wzDatabase, |
35 | __deref_out_z LPWSTR* ppwz | 57 | __deref_out_z LPWSTR* ppwz |
@@ -55,22 +77,11 @@ extern "C" HRESULT DAPI SqlConnectDatabase( | |||
55 | Assert(wzServer && wzDatabase && *wzDatabase && ppidbSession); | 77 | Assert(wzServer && wzDatabase && *wzDatabase && ppidbSession); |
56 | 78 | ||
57 | HRESULT hr = S_OK; | 79 | HRESULT hr = S_OK; |
58 | IDBInitialize* pidbInitialize = NULL; | ||
59 | IDBProperties* pidbProperties = NULL; | ||
60 | |||
61 | LPWSTR pwzServerInstance = NULL; | 80 | LPWSTR pwzServerInstance = NULL; |
62 | DBPROP rgdbpInit[4]; | 81 | DBPROP rgdbpInit[4] = { }; |
63 | DBPROPSET rgdbpsetInit[1]; | 82 | DBPROPSET rgdbpsetInit[1] = { }; |
64 | ULONG cProperties = 0; | 83 | ULONG cProperties = 0; |
65 | 84 | ||
66 | memset(rgdbpInit, 0, sizeof(rgdbpInit)); | ||
67 | memset(rgdbpsetInit, 0, sizeof(rgdbpsetInit)); | ||
68 | |||
69 | //obtain access to the SQLOLEDB provider | ||
70 | hr = ::CoCreateInstance(CLSID_SQLOLEDB, NULL, CLSCTX_INPROC_SERVER, | ||
71 | IID_IDBInitialize, (LPVOID*)&pidbInitialize); | ||
72 | SqlExitOnFailure(hr, "failed to create IID_IDBInitialize object"); | ||
73 | |||
74 | // if there is an instance | 85 | // if there is an instance |
75 | if (wzInstance && *wzInstance) | 86 | if (wzInstance && *wzInstance) |
76 | { | 87 | { |
@@ -137,17 +148,23 @@ extern "C" HRESULT DAPI SqlConnectDatabase( | |||
137 | rgdbpsetInit[0].rgProperties = rgdbpInit; | 148 | rgdbpsetInit[0].rgProperties = rgdbpInit; |
138 | rgdbpsetInit[0].cProperties = cProperties; | 149 | rgdbpsetInit[0].cProperties = cProperties; |
139 | 150 | ||
140 | // create and set the property set | 151 | // obtain access to the SQL Native Client provider |
141 | hr = pidbInitialize->QueryInterface(IID_IDBProperties, (LPVOID*)&pidbProperties); | 152 | hr = InitializeDatabaseConnection(SQLNCLI_CLSID, "SQL Native Client", rgdbpsetInit, countof(rgdbpsetInit), ppidbSession); |
142 | SqlExitOnFailure(hr, "failed to get IID_IDBProperties object"); | 153 | if (FAILED(hr)) |
143 | hr = pidbProperties->SetProperties(1, rgdbpsetInit); | 154 | { |
144 | SqlExitOnFailure(hr, "failed to set properties"); | 155 | SqlExitTrace(hr, "Could not initialize SQL Native Client, falling back to SQL OLE DB..."); |
145 | |||
146 | //initialize connection to datasource | ||
147 | hr = pidbInitialize->Initialize(); | ||
148 | SqlExitOnFailure(hr, "failed to initialize connection to database: %ls", wzDatabase); | ||
149 | 156 | ||
150 | hr = pidbInitialize->QueryInterface(IID_IDBCreateSession, (LPVOID*)ppidbSession); | 157 | // try OLE DB but if that fails return original error failure |
158 | HRESULT hr2 = InitializeDatabaseConnection(CLSID_SQLOLEDB, "SQL OLE DB", rgdbpsetInit, countof(rgdbpsetInit), ppidbSession); | ||
159 | if (FAILED(hr2)) | ||
160 | { | ||
161 | SqlExitTrace(hr2, "Could not initialize SQL OLE DB either, giving up."); | ||
162 | } | ||
163 | else | ||
164 | { | ||
165 | hr = S_OK; | ||
166 | } | ||
167 | } | ||
151 | 168 | ||
152 | LExit: | 169 | LExit: |
153 | for (; 0 < cProperties; cProperties--) | 170 | for (; 0 < cProperties; cProperties--) |
@@ -155,8 +172,6 @@ LExit: | |||
155 | ::VariantClear(&rgdbpInit[cProperties - 1].vValue); | 172 | ::VariantClear(&rgdbpInit[cProperties - 1].vValue); |
156 | } | 173 | } |
157 | 174 | ||
158 | ReleaseObject(pidbProperties); | ||
159 | ReleaseObject(pidbInitialize); | ||
160 | ReleaseStr(pwzServerInstance); | 175 | ReleaseStr(pwzServerInstance); |
161 | 176 | ||
162 | return hr; | 177 | return hr; |
@@ -787,6 +802,110 @@ LExit: | |||
787 | // private | 802 | // private |
788 | // | 803 | // |
789 | 804 | ||
805 | static HRESULT InitializeDatabaseConnection( | ||
806 | __in REFCLSID rclsid, | ||
807 | __in_z LPCSTR szFriendlyClsidName, | ||
808 | __in DBPROPSET rgdbpsetInit[], | ||
809 | __in_ecount(rgdbpsetInit) DWORD cdbpsetInit, | ||
810 | __out IDBCreateSession** ppidbSession | ||
811 | ) | ||
812 | { | ||
813 | Unused(szFriendlyClsidName); // only used in DEBUG builds | ||
814 | |||
815 | HRESULT hr = S_OK; | ||
816 | IDBInitialize* pidbInitialize = NULL; | ||
817 | IDBProperties* pidbProperties = NULL; | ||
818 | |||
819 | hr = ::CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, IID_IDBInitialize, (LPVOID*)&pidbInitialize); | ||
820 | SqlExitOnFailure(hr, "failed to initialize %s", szFriendlyClsidName); | ||
821 | |||
822 | // create and set the property set | ||
823 | hr = pidbInitialize->QueryInterface(IID_IDBProperties, (LPVOID*)&pidbProperties); | ||
824 | SqlExitOnFailure(hr, "failed to get IID_IDBProperties for %s", szFriendlyClsidName); | ||
825 | |||
826 | hr = pidbProperties->SetProperties(cdbpsetInit, rgdbpsetInit); | ||
827 | SqlExitOnFailure(hr, "failed to set properties for %s", szFriendlyClsidName); | ||
828 | |||
829 | // initialize connection to datasource | ||
830 | hr = pidbInitialize->Initialize(); | ||
831 | if (FAILED(hr)) | ||
832 | { | ||
833 | DumpErrorRecords(); | ||
834 | } | ||
835 | SqlExitOnFailure(hr, "failed to initialize connection for %s", szFriendlyClsidName); | ||
836 | |||
837 | hr = pidbInitialize->QueryInterface(IID_IDBCreateSession, (LPVOID*)ppidbSession); | ||
838 | SqlExitOnFailure(hr, "failed to query for connection session for %s", szFriendlyClsidName); | ||
839 | |||
840 | LExit: | ||
841 | ReleaseObject(pidbProperties); | ||
842 | ReleaseObject(pidbInitialize); | ||
843 | |||
844 | return hr; | ||
845 | } | ||
846 | |||
847 | HRESULT DumpErrorRecords() | ||
848 | { | ||
849 | HRESULT hr = S_OK; | ||
850 | IErrorInfo* pIErrorInfo = NULL; | ||
851 | IErrorRecords* pIErrorRecords = NULL; | ||
852 | IErrorInfo* pIErrorInfoRecord = NULL; | ||
853 | BSTR bstrDescription = NULL; | ||
854 | ULONG i = 0; | ||
855 | ULONG cRecords = 0; | ||
856 | ERRORINFO ErrorInfo = { }; | ||
857 | |||
858 | // Get IErrorInfo pointer from OLE. | ||
859 | hr = ::GetErrorInfo(0, &pIErrorInfo); | ||
860 | if (FAILED(hr)) | ||
861 | { | ||
862 | ExitFunction(); | ||
863 | } | ||
864 | |||
865 | // QI for IID_IErrorRecords. | ||
866 | hr = pIErrorInfo->QueryInterface(IID_IErrorRecords, (void**)&pIErrorRecords); | ||
867 | if (FAILED(hr)) | ||
868 | { | ||
869 | ExitFunction(); | ||
870 | } | ||
871 | |||
872 | // Get error record count. | ||
873 | hr = pIErrorRecords->GetRecordCount(&cRecords); | ||
874 | if (FAILED(hr)) | ||
875 | { | ||
876 | ExitFunction(); | ||
877 | } | ||
878 | |||
879 | // Loop through the error records. | ||
880 | for (i = 0; i < cRecords; i++) | ||
881 | { | ||
882 | // Get pIErrorInfo from pIErrorRecords. | ||
883 | hr = pIErrorRecords->GetErrorInfo(i, 1033, &pIErrorInfoRecord); | ||
884 | |||
885 | if (SUCCEEDED(hr)) | ||
886 | { | ||
887 | // Get error description and source. | ||
888 | hr = pIErrorInfoRecord->GetDescription(&bstrDescription); | ||
889 | |||
890 | // Retrieve the ErrorInfo structures. | ||
891 | hr = pIErrorRecords->GetBasicErrorInfo(i, &ErrorInfo); | ||
892 | |||
893 | SqlExitTrace(ErrorInfo.hrError, "SQL error %lu/%lu: %ls", i + 1, cRecords, bstrDescription); | ||
894 | |||
895 | ReleaseNullObject(pIErrorInfoRecord); | ||
896 | ReleaseNullBSTR(bstrDescription); | ||
897 | } | ||
898 | } | ||
899 | |||
900 | LExit: | ||
901 | ReleaseNullBSTR(bstrDescription); | ||
902 | ReleaseObject(pIErrorInfoRecord); | ||
903 | ReleaseObject(pIErrorRecords); | ||
904 | ReleaseObject(pIErrorInfo); | ||
905 | |||
906 | return hr; | ||
907 | } | ||
908 | |||
790 | /******************************************************************** | 909 | /******************************************************************** |
791 | FileSpecToString | 910 | FileSpecToString |
792 | 911 | ||