aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/sqlutil.cpp
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-04-08 14:06:21 -0700
committerRob Mensching <rob@firegiant.com>2021-04-12 12:29:11 -0700
commitb2c4600453f926fbfdc63219126930ad39601f25 (patch)
treeb7c8429ffcfe4f1f8b98f9e43b00d671b2d3a1d6 /src/dutil/sqlutil.cpp
parent0c2b4cf3a439eda3e19d20fadfc65ddc7d0394c0 (diff)
downloadwix-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.cpp171
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_)
24extern 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
43static 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 );
50HRESULT DumpErrorRecords();
28static HRESULT FileSpecToString( 51static 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
33static HRESULT EscapeSqlIdentifier( 55static 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
152LExit: 169LExit:
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
805static 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
840LExit:
841 ReleaseObject(pidbProperties);
842 ReleaseObject(pidbInitialize);
843
844 return hr;
845}
846
847HRESULT 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
900LExit:
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