Leaked source code of windows server 2003
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.

510 lines
12 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // SYNOPSIS
  6. //
  7. // Defines the class DatabasePage.
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "Precompiled.h"
  11. #include "dbpage.h"
  12. #include "changenotification.h"
  13. #include "dbconfig.h"
  14. #include "dbnode.h"
  15. #include "loggingmethodsnode.h"
  16. #include "iasutil.h"
  17. DatabasePage::DatabasePage(
  18. LONG_PTR notifyHandle,
  19. wchar_t* title,
  20. DatabaseNode* newSrc
  21. )
  22. : CIASPropertyPage<DatabasePage>(notifyHandle, title, TRUE),
  23. src(newSrc),
  24. initString(0),
  25. dbConfigDirty(false),
  26. sdoConfigDirty(false)
  27. {
  28. }
  29. DatabasePage::~DatabasePage() throw ()
  30. {
  31. CoTaskMemFree(initString);
  32. }
  33. HRESULT DatabasePage::Initialize(
  34. ISdo* config,
  35. ISdoServiceControl* control
  36. ) throw ()
  37. {
  38. HRESULT hr = CoMarshalInterThreadInterfaceInStream(
  39. __uuidof(ISdo),
  40. config,
  41. &configStream
  42. );
  43. if (FAILED(hr))
  44. {
  45. return hr;
  46. }
  47. hr = CoMarshalInterThreadInterfaceInStream(
  48. __uuidof(ISdoServiceControl),
  49. control,
  50. &controlStream
  51. );
  52. if (FAILED(hr))
  53. {
  54. return hr;
  55. }
  56. if (src->GetInitString() != 0)
  57. {
  58. initString = com_wcsdup(src->GetInitString());
  59. dataSourceName = src->GetDataSourceName();
  60. if ((initString == 0) || !dataSourceName)
  61. {
  62. return E_OUTOFMEMORY;
  63. }
  64. }
  65. return S_OK;
  66. }
  67. BOOL DatabasePage::OnApply() throw ()
  68. {
  69. HRESULT hr;
  70. // Validate the max sessions.
  71. UINT maxSessions = GetDlgItemInt(IDC_DB_EDIT_MAX_SESSIONS, 0, FALSE);
  72. if ((maxSessions < 1) || (maxSessions > 100))
  73. {
  74. ShowErrorDialog(
  75. m_hWnd,
  76. IDS_DB_E_INVALID_SESSIONS,
  77. 0,
  78. 0,
  79. IDS_DB_E_TITLE
  80. );
  81. ::SetFocus(GetDlgItem(IDC_DB_EDIT_MAX_SESSIONS));
  82. return FALSE;
  83. }
  84. if (dbConfigDirty)
  85. {
  86. hr = IASStoreDatabaseConfig(
  87. src->GetServerName(),
  88. initString,
  89. dataSourceName
  90. );
  91. if (SUCCEEDED(hr))
  92. {
  93. // We only need to send a change notification for the database config
  94. // since the SDO config is never cached.
  95. CChangeNotification* chg = new (std::nothrow) CChangeNotification();
  96. if (chg != 0)
  97. {
  98. chg->m_dwFlags = CHANGE_UPDATE_RESULT_NODE;
  99. chg->m_pNode = src;
  100. chg->m_pParentNode = src->Parent();
  101. PropertyChangeNotify(reinterpret_cast<LPARAM>(chg));
  102. }
  103. dbConfigDirty = false;
  104. }
  105. else
  106. {
  107. ShowErrorDialog(
  108. m_hWnd,
  109. IDS_DB_E_CANT_WRITE_DB_CONFIG,
  110. 0,
  111. hr,
  112. IDS_DB_E_TITLE
  113. );
  114. }
  115. }
  116. if (sdoConfigDirty)
  117. {
  118. SaveBool(
  119. IDC_DB_CHECK_ACCT,
  120. PROPERTY_ACCOUNTING_LOG_ACCOUNTING
  121. );
  122. SaveBool(
  123. IDC_DB_CHECK_AUTH,
  124. PROPERTY_ACCOUNTING_LOG_AUTHENTICATION
  125. );
  126. SaveBool(
  127. IDC_DB_CHECK_INTERIM,
  128. PROPERTY_ACCOUNTING_LOG_ACCOUNTING_INTERIM
  129. );
  130. VARIANT v;
  131. V_VT(&v) = VT_I4;
  132. V_I4(&v) = maxSessions;
  133. configSdo->PutProperty(PROPERTY_ACCOUNTING_SQL_MAX_SESSIONS, &v);
  134. hr = configSdo->Apply();
  135. if (SUCCEEDED(hr))
  136. {
  137. sdoConfigDirty = false;
  138. }
  139. else
  140. {
  141. ShowErrorDialog(
  142. m_hWnd,
  143. IDS_DB_E_CANT_WRITE_SDO_CONFIG,
  144. 0,
  145. hr,
  146. IDS_DB_E_TITLE
  147. );
  148. }
  149. }
  150. controlSdo->ResetService();
  151. return TRUE;
  152. }
  153. HRESULT DatabasePage::ConfigureConnection() throw ()
  154. {
  155. HRESULT hr;
  156. // Create the MSDAINITIALIZE object if necessary.
  157. if (dataInitialize == 0)
  158. {
  159. hr = CoCreateInstance(
  160. CLSID_MSDAINITIALIZE,
  161. 0,
  162. CLSCTX_INPROC_SERVER,
  163. __uuidof(IDataInitialize),
  164. reinterpret_cast<void**>(&dataInitialize)
  165. );
  166. if (FAILED(hr))
  167. {
  168. return hr;
  169. }
  170. }
  171. // Create the current data source if necessary.
  172. if ((initString != 0) && !dataSource)
  173. {
  174. dataInitialize->GetDataSource(
  175. 0,
  176. CLSCTX_INPROC_SERVER,
  177. initString,
  178. __uuidof(IDBProperties),
  179. reinterpret_cast<IUnknown**>(&dataSource)
  180. );
  181. // Ignore errors. If the init string is invalid, we'll just let the
  182. // user create a new one from scratch.
  183. }
  184. // Create the DataLinks object if necessary.
  185. if (dataLinks == 0)
  186. {
  187. hr = CoCreateInstance(
  188. CLSID_DataLinks,
  189. 0,
  190. CLSCTX_INPROC_SERVER,
  191. __uuidof(IDBPromptInitialize),
  192. reinterpret_cast<void**>(&dataLinks)
  193. );
  194. if (FAILED(hr))
  195. {
  196. return hr;
  197. }
  198. }
  199. // Since we don't want to let the admin choose the provider, we have to
  200. // supply a data source object to the DataLinks UI. If one is currently
  201. // configured we use that; otherwise, we create an empty SQL Server
  202. // provider.
  203. CComPtr<IDBProperties> newDataSource;
  204. if (dataSource)
  205. {
  206. newDataSource = dataSource;
  207. }
  208. else
  209. {
  210. CLSID clsid;
  211. hr = CLSIDFromProgID(L"SQLOLEDB", &clsid);
  212. if (FAILED(hr))
  213. {
  214. return hr;
  215. }
  216. hr = CoCreateInstance(
  217. clsid,
  218. 0,
  219. CLSCTX_INPROC_SERVER,
  220. __uuidof(IDBProperties),
  221. reinterpret_cast<void**>(&newDataSource)
  222. );
  223. if (FAILED(hr))
  224. {
  225. return hr;
  226. }
  227. }
  228. // Bring up the UI to let the user configure the data source.
  229. hr = dataLinks->PromptDataSource(
  230. 0,
  231. m_hWnd,
  232. (DBPROMPTOPTIONS_PROPERTYSHEET |
  233. DBPROMPTOPTIONS_DISABLE_PROVIDER_SELECTION),
  234. 0,
  235. 0,
  236. 0,
  237. __uuidof(IDBProperties),
  238. reinterpret_cast<IUnknown**>(&(newDataSource.p))
  239. );
  240. if (FAILED(hr))
  241. {
  242. return hr;
  243. }
  244. // Get the data source name.
  245. DBPROPID propId = DBPROP_INIT_DATASOURCE;
  246. DBPROPIDSET propIdSet;
  247. propIdSet.rgPropertyIDs = &propId;
  248. propIdSet.cPropertyIDs = 1;
  249. propIdSet.guidPropertySet = DBPROPSET_DBINIT;
  250. ULONG numPropSets;
  251. DBPROPSET* propSets = 0;
  252. hr = newDataSource->GetProperties(
  253. 1,
  254. &propIdSet,
  255. &numPropSets,
  256. &propSets
  257. );
  258. CComBSTR newDataSourceName;
  259. if (SUCCEEDED(hr))
  260. {
  261. newDataSourceName.Attach(V_BSTR(&(propSets[0].rgProperties[0].vValue)));
  262. }
  263. // Have to clean up even in some failure cases.
  264. if (propSets != 0)
  265. {
  266. CoTaskMemFree(propSets[0].rgProperties);
  267. CoTaskMemFree(propSets);
  268. }
  269. if (FAILED(hr))
  270. {
  271. return hr;
  272. }
  273. // Get the initialization string.
  274. LPOLESTR newInitString;
  275. hr = dataInitialize->GetInitializationString(
  276. newDataSource,
  277. 1,
  278. &newInitString
  279. );
  280. if (FAILED(hr))
  281. {
  282. return hr;
  283. }
  284. // All went well, so store the result.
  285. CoTaskMemFree(initString);
  286. initString = newInitString;
  287. dataSourceName.Empty();
  288. dataSourceName.Attach(newDataSourceName.Detach());
  289. dataSource = newDataSource;
  290. return S_OK;
  291. }
  292. void DatabasePage::LoadBool(UINT control, LONG propId) throw ()
  293. {
  294. VARIANT v;
  295. VariantInit(&v);
  296. HRESULT hr = configSdo->GetProperty(propId, &v);
  297. if (SUCCEEDED(hr))
  298. {
  299. if ((V_VT(&v) == VT_BOOL) && V_BOOL(&v))
  300. {
  301. ::SendMessage(GetDlgItem(control), BM_SETCHECK, 1, 0);
  302. }
  303. VariantClear(&v);
  304. }
  305. }
  306. void DatabasePage::SaveBool(UINT control, LONG propId) throw ()
  307. {
  308. BOOL newVal = SendDlgItemMessage(control, BM_GETCHECK, 0, 0);
  309. VARIANT v;
  310. V_VT(&v) = VT_BOOL;
  311. V_BOOL(&v) = newVal ? VARIANT_TRUE : VARIANT_FALSE;
  312. configSdo->PutProperty(propId, &v);
  313. }
  314. LRESULT DatabasePage::OnInitDialog(
  315. UINT uMsg,
  316. WPARAM wParam,
  317. LPARAM lParam,
  318. BOOL& bHandled
  319. )
  320. {
  321. HRESULT hr = CoUnmarshalInterface(
  322. configStream,
  323. __uuidof(ISdo),
  324. reinterpret_cast<void**>(&configSdo)
  325. );
  326. if (SUCCEEDED(hr))
  327. {
  328. hr = CoUnmarshalInterface(
  329. controlStream,
  330. __uuidof(ISdoServiceControl),
  331. reinterpret_cast<void**>(&controlSdo)
  332. );
  333. }
  334. configStream.Release();
  335. controlStream.Release();
  336. if (FAILED(hr))
  337. {
  338. ShowErrorDialog(
  339. m_hWnd,
  340. IDS_DB_E_CANT_INIT_DIALOG,
  341. 0,
  342. hr,
  343. IDS_DB_E_TITLE
  344. );
  345. EnableWindow(FALSE);
  346. }
  347. LoadBool(
  348. IDC_DB_CHECK_ACCT,
  349. PROPERTY_ACCOUNTING_LOG_ACCOUNTING
  350. );
  351. LoadBool(
  352. IDC_DB_CHECK_AUTH,
  353. PROPERTY_ACCOUNTING_LOG_AUTHENTICATION
  354. );
  355. LoadBool(
  356. IDC_DB_CHECK_INTERIM,
  357. PROPERTY_ACCOUNTING_LOG_ACCOUNTING_INTERIM
  358. );
  359. VARIANT maxSessions;
  360. VariantInit(&maxSessions);
  361. hr = configSdo->GetProperty(
  362. PROPERTY_ACCOUNTING_SQL_MAX_SESSIONS,
  363. &maxSessions
  364. );
  365. if (SUCCEEDED(hr))
  366. {
  367. if (V_VT(&maxSessions) == VT_I4)
  368. {
  369. SetDlgItemInt(IDC_DB_EDIT_MAX_SESSIONS, V_I4(&maxSessions), FALSE);
  370. }
  371. VariantClear(&maxSessions);
  372. }
  373. // Max sessions is 100, so don't let the user enter more than 3 digits.
  374. ::SendMessage(GetDlgItem(IDC_DB_EDIT_MAX_SESSIONS), EM_LIMITTEXT, 3, 0);
  375. if (dataSourceName != 0)
  376. {
  377. SetDlgItemText(IDC_DB_EDIT_DATA_SOURCE, dataSourceName);
  378. }
  379. return TRUE;
  380. }
  381. LRESULT DatabasePage::OnChange(
  382. WORD wNotifyCode,
  383. WORD wID,
  384. HWND hWndCtl,
  385. BOOL& bHandled
  386. )
  387. {
  388. sdoConfigDirty = true;
  389. SetModified(TRUE);
  390. return 0;
  391. }
  392. LRESULT DatabasePage::OnClear(
  393. WORD wNotifyCode,
  394. WORD wID,
  395. HWND hWndCtl,
  396. BOOL& bHandled
  397. )
  398. {
  399. if (initString != 0)
  400. {
  401. // Clear out the config.
  402. CoTaskMemFree(initString);
  403. initString = 0;
  404. dataSourceName.Empty();
  405. dataSource.Release();
  406. // Clear out the UI.
  407. SetDlgItemText(IDC_DB_EDIT_DATA_SOURCE, L"");
  408. // Mark ourselves as modified.
  409. dbConfigDirty = true;
  410. SetModified(TRUE);
  411. }
  412. return 0;
  413. }
  414. LRESULT DatabasePage::OnConfigure(
  415. WORD wNotifyCode,
  416. WORD wID,
  417. HWND hWndCtl,
  418. BOOL& bHandled
  419. )
  420. {
  421. HRESULT hr = ConfigureConnection();
  422. if (SUCCEEDED(hr))
  423. {
  424. // Update the UI.
  425. if (dataSourceName)
  426. {
  427. SetDlgItemText(IDC_DB_EDIT_DATA_SOURCE, dataSourceName);
  428. }
  429. else
  430. {
  431. SetDlgItemText(IDC_DB_EDIT_DATA_SOURCE, L"");
  432. }
  433. // Mark ourselves as modified.
  434. dbConfigDirty = true;
  435. SetModified(TRUE);
  436. }
  437. return 0;
  438. }