Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

255 lines
6.3 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // DataSource.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // This file implements the class CIasDataSource.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 11/05/1997 Original version.
  16. // 12/19/1997 Added ExecuteCommand method.
  17. // 01/15/1998 Implemented IIasComponent method.
  18. // 02/09/1998 Added AllowUpdate property.
  19. // 03/17/1999 Create TMP dir before calling IDBInitialize::Initialize.
  20. // 04/22/1999 Clean-up session and connection in destructor.
  21. //
  22. ///////////////////////////////////////////////////////////////////////////////
  23. #include <iascore.h>
  24. #include <iasutil.h>
  25. #include <guard.h>
  26. #include <DataSource.h>
  27. #include <PropSet.h>
  28. CIasDataSource::CIasDataSource() throw ()
  29. : initStatus(E_FAIL),
  30. provider(NULL),
  31. name(NULL),
  32. userID(NULL),
  33. password(NULL),
  34. allowUpdate(false),
  35. connection(NULL),
  36. session(NULL)
  37. {
  38. }
  39. CIasDataSource::~CIasDataSource() throw ()
  40. {
  41. if (session) { session->Release(); }
  42. if (connection) { connection->Release(); }
  43. delete[] password;
  44. delete[] userID;
  45. delete[] name;
  46. delete[] provider;
  47. }
  48. //////////
  49. // Macros to handle getting and putting a string property.
  50. //////////
  51. #define WSTRING_PROPERTY(class, prop, member) \
  52. STDMETHODIMP class ## ::put_ ## prop (LPCWSTR newVal) \
  53. { \
  54. _com_serialize \
  55. delete[] member; \
  56. member = ias_wcsdup(newVal); \
  57. return S_OK; \
  58. } \
  59. \
  60. STDMETHODIMP class ## ::get_ ## prop (LPWSTR* pVal) \
  61. { \
  62. if (pVal == NULL) return E_POINTER; \
  63. _com_serialize \
  64. *pVal = com_wcsdup(member); \
  65. return S_OK; \
  66. }
  67. WSTRING_PROPERTY(CIasDataSource, Provider, provider)
  68. WSTRING_PROPERTY(CIasDataSource, Name, name)
  69. WSTRING_PROPERTY(CIasDataSource, UserID, userID)
  70. WSTRING_PROPERTY(CIasDataSource, Password, password)
  71. STDMETHODIMP CIasDataSource::put_AllowUpdate(boolean newVal)
  72. {
  73. allowUpdate = (newVal != 0);
  74. return S_OK;
  75. }
  76. STDMETHODIMP CIasDataSource::get_AllowUpdate(boolean* pVal)
  77. {
  78. return pVal ? (*pVal = (boolean)allowUpdate), S_OK : E_POINTER;
  79. }
  80. //////////
  81. // Macro to set the InitStatus and bail on an error.
  82. //////////
  83. #define CHECK_INIT(expr) \
  84. if (FAILED(initStatus = expr)) return initStatus;
  85. STDMETHODIMP CIasDataSource::Initialize()
  86. {
  87. _com_serialize
  88. // Clean up an existing connection.
  89. Shutdown();
  90. // Convert the ProgID to a ClsID.
  91. CLSID clsid;
  92. CHECK_INIT(CLSIDFromProgID(provider, &clsid));
  93. // Create the OLE DB provider.
  94. CHECK_INIT(CoCreateInstance(clsid,
  95. NULL,
  96. CLSCTX_INPROC_SERVER,
  97. IID_IDBInitialize,
  98. (PVOID*)&connection));
  99. //////////
  100. // Set the properties for the data source.
  101. //////////
  102. CComPtr<IDBProperties> properties;
  103. CHECK_INIT(connection->QueryInterface(IID_IDBProperties,
  104. (PVOID*)&properties));
  105. DBPropertySet<4> propSet(DBPROPSET_DBINIT);
  106. propSet.AddProperty(DBPROP_INIT_MODE, allowUpdate ? DB_MODE_READWRITE
  107. : DB_MODE_READ);
  108. if (name) propSet.AddProperty(DBPROP_INIT_DATASOURCE, name);
  109. if (userID) propSet.AddProperty(DBPROP_AUTH_USERID, userID);
  110. if (password) propSet.AddProperty(DBPROP_AUTH_PASSWORD, password);
  111. CHECK_INIT(properties->SetProperties(1, &propSet));
  112. //////////
  113. // JetInit fails if the TMP directory doesn't exist, so we'll try to
  114. // create it just in case.
  115. //////////
  116. DWORD needed = GetEnvironmentVariableW(L"TMP", NULL, 0);
  117. if (needed)
  118. {
  119. PWCHAR buf = (PWCHAR)_alloca(needed * sizeof(WCHAR));
  120. DWORD actual = GetEnvironmentVariableW(L"TMP", buf, needed);
  121. if (actual > 0 && actual < needed)
  122. {
  123. CreateDirectoryW(buf, NULL);
  124. }
  125. }
  126. //////////
  127. // Initialize the connection.
  128. //////////
  129. CHECK_INIT(connection->Initialize());
  130. //////////
  131. // Create a session.
  132. //////////
  133. CComPtr<IDBCreateSession> creator;
  134. CHECK_INIT(connection->QueryInterface(IID_IDBCreateSession,
  135. (PVOID*)&creator));
  136. CHECK_INIT(creator->CreateSession(NULL,
  137. IID_IOpenRowset,
  138. (IUnknown**)&session));
  139. return S_OK;
  140. }
  141. STDMETHODIMP CIasDataSource::Shutdown()
  142. {
  143. _com_serialize
  144. IAS_DEREF(session);
  145. IAS_DEREF(connection);
  146. initStatus = E_FAIL;
  147. return S_OK;
  148. }
  149. STDMETHODIMP CIasDataSource::OpenTable(LPCWSTR szTableName, IUnknown** ppTable)
  150. {
  151. if (!ppTable)
  152. {
  153. return E_POINTER;
  154. }
  155. // Make sure the data source has been successfully initialized.
  156. _com_serialize
  157. if (FAILED(initStatus))
  158. {
  159. return initStatus;
  160. }
  161. *ppTable = NULL;
  162. DBID idTable;
  163. idTable.eKind = DBKIND_NAME;
  164. idTable.uName.pwszName = const_cast<LPWSTR>(szTableName);
  165. return session->OpenRowset(NULL,
  166. &idTable,
  167. NULL,
  168. IID_IUnknown,
  169. 0,
  170. NULL,
  171. ppTable);
  172. }
  173. STDMETHODIMP CIasDataSource::ExecuteCommand(REFGUID rguidDialect,
  174. LPCWSTR szCommandText,
  175. IUnknown** ppRowset)
  176. {
  177. if (!ppRowset)
  178. {
  179. return E_POINTER;
  180. }
  181. _com_serialize
  182. // Make sure the data source has been successfully initialized.
  183. if (FAILED(initStatus))
  184. {
  185. return initStatus;
  186. }
  187. *ppRowset = NULL;
  188. CComPtr<IDBCreateCommand> creator;
  189. RETURN_ERROR(session->QueryInterface(IID_IDBCreateCommand,
  190. (PVOID*)&creator));
  191. CComPtr<ICommandText> command;
  192. RETURN_ERROR(creator->CreateCommand(NULL,
  193. IID_ICommandText,
  194. (IUnknown**)&command));
  195. RETURN_ERROR(command->SetCommandText(rguidDialect,
  196. szCommandText));
  197. return command->Execute(NULL,
  198. IID_IUnknown,
  199. NULL,
  200. NULL,
  201. ppRowset);
  202. }