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.

405 lines
9.2 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Abstract:
  4. @doc
  5. @module sqlwriter.cpp | Implementation of Writer
  6. @end
  7. Author:
  8. Brian Berkowitz [brianb] 04/17/2000
  9. TBD:
  10. Revision History:
  11. Name Date Comments
  12. brianb 04/17/2000 created
  13. brianb 04/20/2000 integrated with coordinator
  14. brainb 05/05/2000 add OnIdentify support
  15. mikejohn 06/01/2000 fix minor but confusing typos in trace messages
  16. mikejohn 09/19/2000 176860: Add the missing calling convention specifiers
  17. --*/
  18. #include <stdafx.hxx>
  19. #include "vs_idl.hxx"
  20. #include "vswriter.h"
  21. #include "sqlsnap.h"
  22. #include "sqlwriter.h"
  23. #include "vs_seh.hxx"
  24. #include "vs_trace.hxx"
  25. #include "vs_debug.hxx"
  26. #include "allerror.h"
  27. ////////////////////////////////////////////////////////////////////////
  28. // Standard foo for file name aliasing. This code block must be after
  29. // all includes of VSS header files.
  30. //
  31. #ifdef VSS_FILE_ALIAS
  32. #undef VSS_FILE_ALIAS
  33. #endif
  34. #define VSS_FILE_ALIAS "SQWWRTRC"
  35. //
  36. ////////////////////////////////////////////////////////////////////////
  37. static LPCWSTR x_wszSqlServerWriter = L"SqlServerWriter";
  38. static GUID s_writerId =
  39. {
  40. 0xf8544ac1, 0x0611, 0x4fa5, 0xb0, 0x4b, 0xf7, 0xee, 0x00, 0xb0, 0x32, 0x77
  41. };
  42. static LPCWSTR s_wszWriterName = L"MSDEWriter";
  43. HRESULT STDMETHODCALLTYPE CSqlWriter::Initialize()
  44. {
  45. CVssFunctionTracer ft(VSSDBG_GEN, L"CSqlWriter::Initialize");
  46. try
  47. {
  48. InitSQLEnvironment();
  49. m_pSqlSnapshot = CreateSqlSnapshot();
  50. if (m_pSqlSnapshot == NULL)
  51. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Failed to allocate CSqlSnapshot object.");
  52. ft.hr = CVssWriter::Initialize
  53. (
  54. s_writerId,
  55. s_wszWriterName,
  56. VSS_UT_SYSTEMSERVICE,
  57. VSS_ST_TRANSACTEDDB,
  58. VSS_APP_BACK_END,
  59. 60000
  60. );
  61. if (ft.HrFailed())
  62. ft.Throw
  63. (
  64. VSSDBG_GEN,
  65. E_UNEXPECTED,
  66. L"Failed to initialize the Sql writer. hr = 0x%08lx",
  67. ft.hr
  68. );
  69. ft.hr = Subscribe();
  70. if (ft.HrFailed())
  71. ft.Throw
  72. (
  73. VSSDBG_GEN,
  74. E_UNEXPECTED,
  75. L"Subscribing the Sql server writer failed. hr = %0x08lx",
  76. ft.hr
  77. );
  78. }
  79. VSS_STANDARD_CATCH(ft)
  80. if (ft.HrFailed() && m_pSqlSnapshot)
  81. {
  82. delete m_pSqlSnapshot;
  83. m_pSqlSnapshot = NULL;
  84. }
  85. return ft.hr;
  86. }
  87. HRESULT STDMETHODCALLTYPE CSqlWriter::Uninitialize()
  88. {
  89. CVssFunctionTracer ft(VSSDBG_GEN, L"CSqlWriter::Uninitialize");
  90. return Unsubscribe();
  91. }
  92. bool STDMETHODCALLTYPE CSqlWriter::OnPrepareSnapshot()
  93. {
  94. CVssFunctionTracer ft(VSSDBG_GEN, L"CSqlWriter::OnPrepareSnapshot");
  95. try
  96. {
  97. BS_ASSERT(!m_fFrozen);
  98. ft.hr = m_pSqlSnapshot->Prepare(this);
  99. }
  100. VSS_STANDARD_CATCH(ft)
  101. TranslateWriterError(ft.hr);
  102. return !ft.HrFailed();
  103. }
  104. bool STDMETHODCALLTYPE CSqlWriter::OnFreeze()
  105. {
  106. CVssFunctionTracer ft(VSSDBG_GEN, L"CSqlWriter::OnFreeze");
  107. try
  108. {
  109. BS_ASSERT(!m_fFrozen);
  110. ft.hr = m_pSqlSnapshot->Freeze();
  111. if (!ft.HrFailed())
  112. m_fFrozen = true;
  113. }
  114. VSS_STANDARD_CATCH(ft)
  115. TranslateWriterError(ft.hr);
  116. return !ft.HrFailed();
  117. }
  118. bool STDMETHODCALLTYPE CSqlWriter::OnThaw()
  119. {
  120. CVssFunctionTracer ft(VSSDBG_GEN, L"CSqlWriter::OnThaw");
  121. try
  122. {
  123. if (m_fFrozen)
  124. {
  125. m_fFrozen = false;
  126. ft.hr = m_pSqlSnapshot->Thaw();
  127. }
  128. }
  129. VSS_STANDARD_CATCH(ft)
  130. TranslateWriterError(ft.hr);
  131. return !ft.HrFailed();
  132. }
  133. bool STDMETHODCALLTYPE CSqlWriter::OnAbort()
  134. {
  135. CVssFunctionTracer ft(VSSDBG_GEN, L"CSqlWriter::OnAbort");
  136. try
  137. {
  138. if (m_fFrozen)
  139. {
  140. m_fFrozen = false;
  141. ft.hr = m_pSqlSnapshot->Thaw();
  142. }
  143. }
  144. VSS_STANDARD_CATCH(ft)
  145. return !ft.HrFailed();
  146. }
  147. bool CSqlWriter::IsPathInSnapshot(const WCHAR *wszPath) throw()
  148. {
  149. return IsPathAffected(wszPath);
  150. }
  151. // handle request for WRITER_METADATA
  152. // implements CVssWriter::OnIdentify
  153. bool STDMETHODCALLTYPE CSqlWriter::OnIdentify(IVssCreateWriterMetadata *pMetadata)
  154. {
  155. CVssFunctionTracer ft(VSSDBG_GEN, L"CSqlWriter::OnIdentify");
  156. ServerInfo server;
  157. DatabaseInfo database;
  158. DatabaseFileInfo file;
  159. // create enumerator
  160. CSqlEnumerator *pEnumServers = CreateSqlEnumerator();
  161. CSqlEnumerator *pEnumDatabases = NULL;
  162. CSqlEnumerator *pEnumFiles = NULL;
  163. try
  164. {
  165. if (pEnumServers == NULL)
  166. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Failed to create CSqlEnumerator");
  167. // find first server
  168. ft.hr = pEnumServers->FirstServer(&server);
  169. while(ft.hr != DB_S_ENDOFROWSET)
  170. {
  171. // check for error code
  172. if (ft.HrFailed())
  173. ft.Throw
  174. (
  175. VSSDBG_GEN,
  176. E_UNEXPECTED,
  177. L"Enumerating database servers failed. hr = 0x%08lx",
  178. ft.hr
  179. );
  180. // only look at server if it is online
  181. if (server.isOnline)
  182. {
  183. // recreate enumerator for databases
  184. BS_ASSERT(pEnumDatabases == NULL);
  185. pEnumDatabases = CreateSqlEnumerator();
  186. if (pEnumDatabases == NULL)
  187. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Failed to create CSqlEnumerator");
  188. // find first database
  189. ft.hr = pEnumDatabases->FirstDatabase(server.name, &database);
  190. while(ft.hr != DB_S_ENDOFROWSET)
  191. {
  192. // check for error
  193. if (ft.HrFailed())
  194. ft.Throw
  195. (
  196. VSSDBG_GEN,
  197. E_UNEXPECTED,
  198. L"Enumerating databases failed. hr = 0x%08lx",
  199. ft.hr
  200. );
  201. // only include database if it supports Freeze
  202. if (database.supportsFreeze &&
  203. wcscmp(database.name, L"tempdb") != 0)
  204. {
  205. // add database component
  206. ft.hr = pMetadata->AddComponent
  207. (
  208. VSS_CT_DATABASE, // component type
  209. server.name, // logical path
  210. database.name, // component name
  211. NULL, // caption
  212. NULL, // pbIcon
  213. 0, // cbIcon
  214. false, // bRestoreMetadata
  215. false, // bNotifyOnBackupComplete
  216. false // bSelectable
  217. );
  218. if (ft.HrFailed())
  219. ft.Throw
  220. (
  221. VSSDBG_GEN,
  222. E_UNEXPECTED,
  223. L"IVssCreateWriterMetadata::AddComponent failed. hr = 0x%08lx",
  224. ft.hr
  225. );
  226. // recreate enumerator for files
  227. BS_ASSERT(pEnumFiles == NULL);
  228. pEnumFiles = CreateSqlEnumerator();
  229. if (pEnumFiles == NULL)
  230. ft.Throw(VSSDBG_GEN, E_OUTOFMEMORY, L"Failed to create CSqlEnumerator");
  231. // findfirst database file
  232. ft.hr = pEnumFiles->FirstFile(server.name, database.name, &file);
  233. while(ft.hr != DB_S_ENDOFROWSET)
  234. {
  235. // check for error
  236. if (ft.HrFailed())
  237. ft.Throw
  238. (
  239. VSSDBG_GEN,
  240. E_UNEXPECTED,
  241. L"Enumerating database files failed. hr = 0x%08lx",
  242. ft.hr
  243. );
  244. // split file name into separate path
  245. // and filename components. Path is everything
  246. // before the last backslash.
  247. WCHAR logicalPath[MAX_PATH];
  248. WCHAR *pFileName = file.name + wcslen(file.name);
  249. while(--pFileName > file.name)
  250. {
  251. if (*pFileName == '\\')
  252. break;
  253. }
  254. // if no backslash, then there is no path
  255. if (pFileName == file.name)
  256. logicalPath[0] = '\0';
  257. else
  258. {
  259. // extract path
  260. size_t cwc = wcslen(file.name) - wcslen(pFileName);
  261. memcpy(logicalPath, file.name, cwc*sizeof(WCHAR));
  262. logicalPath[cwc] = L'\0';
  263. pFileName++;
  264. }
  265. if (file.isLogFile)
  266. // log file
  267. ft.hr = pMetadata->AddDatabaseLogFiles
  268. (
  269. server.name,
  270. database.name,
  271. logicalPath,
  272. pFileName
  273. );
  274. else
  275. // physical database file
  276. ft.hr = pMetadata->AddDatabaseLogFiles
  277. (
  278. server.name,
  279. database.name,
  280. logicalPath,
  281. pFileName
  282. );
  283. // continue at next file
  284. ft.hr = pEnumFiles->NextFile(&file);
  285. }
  286. delete pEnumFiles;
  287. pEnumFiles = NULL;
  288. }
  289. // continue at next database
  290. ft.hr = pEnumDatabases->NextDatabase(&database);
  291. }
  292. delete pEnumDatabases;
  293. pEnumDatabases = NULL;
  294. }
  295. // continue at next server
  296. ft.hr = pEnumServers->NextServer(&server);
  297. }
  298. }
  299. VSS_STANDARD_CATCH(ft)
  300. TranslateWriterError(ft.hr);
  301. delete pEnumServers;
  302. delete pEnumDatabases;
  303. delete pEnumFiles;
  304. return ft.HrFailed() ? false : true;
  305. }
  306. // translate a sql writer error code into a writer error
  307. void CSqlWriter::TranslateWriterError(HRESULT hr)
  308. {
  309. switch(hr)
  310. {
  311. default:
  312. SetWriterFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  313. break;
  314. case S_OK:
  315. break;
  316. case E_OUTOFMEMORY:
  317. case HRESULT_FROM_WIN32(ERROR_DISK_FULL):
  318. case HRESULT_FROM_WIN32(ERROR_TOO_MANY_OPEN_FILES):
  319. case HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY):
  320. case HRESULT_FROM_WIN32(ERROR_NO_MORE_USER_HANDLES):
  321. SetWriterFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  322. break;
  323. case HRESULT_FROM_WIN32(E_SQLLIB_TORN_DB):
  324. SetWriterFailure(VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT);
  325. break;
  326. }
  327. }