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.

647 lines
13 KiB

  1. // ***************************************************************************
  2. // Copyright (C) 2000- Microsoft Corporation.
  3. // @File: sqlsnapi.h
  4. //
  5. // PURPOSE:
  6. //
  7. // The internal include file for the sql snapshot module
  8. //
  9. // NOTES:
  10. //
  11. // HISTORY:
  12. //
  13. // @Version: Whistler/Shiloh
  14. // 85581 SRS 08/15/01 Event security
  15. // 76910 SRS 08/08/01 Rollforward from VSS snapshot
  16. // 68228 12/05/00 ntsnap work
  17. // 66601 srs 10/05/00 NTSNAP improvements
  18. //
  19. //
  20. // @EndHeader@
  21. // ***************************************************************************
  22. #include <string>
  23. #include <vector>
  24. #include <list>
  25. #include <oledb.h>
  26. #include <oledberr.h>
  27. #include <sqloledb.h>
  28. #include "vdi.h" // interface declaration from SQLVDI kit
  29. ////////////////////////////////////////////////////////////////////////
  30. // Standard foo for file name aliasing. This code block must be after
  31. // all includes of VSS header files.
  32. //
  33. #ifdef VSS_FILE_ALIAS
  34. #undef VSS_FILE_ALIAS
  35. #endif
  36. #define VSS_FILE_ALIAS "SQLSNPIH"
  37. //
  38. ////////////////////////////////////////////////////////////////////////
  39. typedef unsigned long ULONG;
  40. typedef wchar_t WCHAR;
  41. #define TRUE 1
  42. #define FALSE 0
  43. class CLogMsg;
  44. // Converting from int to bool "naturally" gives a 4800 warning....
  45. //
  46. inline bool IntToBool (int v)
  47. {
  48. return v ? true : false;
  49. }
  50. // Unexpected, "internal" errors can be logged with some
  51. // generic international text, like "Internal error: <English servicibility text>"
  52. //
  53. // Situations we expect, for which the user needs to know should
  54. // occur with proper internationalization
  55. //
  56. // Process wide globals used by the sql modules
  57. //
  58. extern IMalloc * g_pIMalloc;
  59. //-------------------------------------------------------------------------
  60. //
  61. typedef std::wstring WString;
  62. typedef std::vector<WString> StringVector;
  63. typedef StringVector::const_iterator StringVectorIter;
  64. typedef std::list<WString> StringList;
  65. typedef StringList::const_iterator StringListIter;
  66. StringVector* EnumerateServers ();
  67. //--------------------------------------------------------------------------------
  68. // database names need special syntactical handling
  69. //
  70. const MaxSysNameLen = 128;
  71. const SysNameBufferLen = MaxSysNameLen * 2; // easily accomodate doubled quotes and delimiters
  72. void
  73. FormStringForName (WCHAR* pString, const WCHAR* pName);
  74. void
  75. FormDelimitedIdentifier (WCHAR* pString, const WCHAR* pName);
  76. //-------------------------------------------------------------------------
  77. // Handle our simple needs for DB services.
  78. //
  79. // Useage:
  80. // - Connect : establish a connection to a given server
  81. // - SetCommand: setup the SQL text to send
  82. // - ExecCommand: execute some SQL, returns TRUE if a result set
  83. // is open and ready for retrieval
  84. // - Get*: retrieve info from the result set
  85. //
  86. // The destructor will automatically disconnect from the server.
  87. //
  88. class SqlConnection
  89. {
  90. public:
  91. SqlConnection () :
  92. m_pCommandFactory (NULL),
  93. m_pCommand (NULL),
  94. m_pRowset (NULL),
  95. m_pBuffer (NULL),
  96. m_BufferSize (0),
  97. m_hAcc (NULL),
  98. m_pAccessor (NULL),
  99. m_pBindings (NULL),
  100. m_cBindings (0)
  101. {}
  102. ~SqlConnection ();
  103. void
  104. Connect (const std::wstring& serverName);
  105. void
  106. Disconnect ();
  107. void
  108. ReleaseRowset ();
  109. void
  110. SetCommand (const std::wstring& command);
  111. BOOL
  112. ExecCommand ();
  113. StringVector*
  114. GetStringColumn ();
  115. ULONG
  116. GetServerVersion () {return m_ServerVersion;}
  117. BOOL
  118. FetchFirst ();
  119. BOOL
  120. FetchNext ();
  121. void*
  122. AccessColumn (int id);
  123. private:
  124. void LogOledbError
  125. (
  126. CVssFunctionTracer &ft,
  127. CVssDebugInfo &dbgInfo,
  128. LPCWSTR wszRoutine,
  129. CLogMsg &msg
  130. );
  131. WString m_ServerName;
  132. IDBCreateCommand* m_pCommandFactory;
  133. ICommandText* m_pCommand;
  134. IRowset* m_pRowset;
  135. ULONG m_ServerVersion;
  136. // used for the generic findfirst/findnext
  137. DBBINDING* m_pBindings;
  138. ULONG m_cBindings;
  139. BYTE* m_pBuffer;
  140. ULONG m_BufferSize;
  141. HACCESSOR m_hAcc;
  142. IAccessor* m_pAccessor;
  143. };
  144. BOOL
  145. IsServerOnline (const WCHAR* serverName);
  146. //-------------------------------------------------------------------------
  147. // Provide a simple container for BACKUP metadata.
  148. //
  149. class MetaData
  150. {
  151. public:
  152. MetaData ();
  153. ~MetaData ();
  154. // Data is appended until complete
  155. //
  156. void
  157. Append (const BYTE* pData, UINT length);
  158. // At completion, a checksum is appended
  159. //
  160. void
  161. Finalize ();
  162. // The buffer and its length are made available.
  163. //
  164. const BYTE*
  165. GetImage (UINT* pLength);
  166. // Verify the checksum
  167. //
  168. static
  169. BOOL
  170. IsValidImage (const BYTE* pData, UINT length);
  171. private:
  172. static
  173. UINT
  174. Checksum (const BYTE* pData, UINT length);
  175. BYTE* m_pData;
  176. UINT m_AllocatedLength;
  177. UINT m_UsedLength;
  178. };
  179. class Freeze2000;
  180. class FrozenServer;
  181. //-------------------------------------------------------------------------
  182. // Handle a single frozen database (>=SQL2000 only).
  183. //
  184. class FrozenDatabase
  185. {
  186. friend Freeze2000;
  187. friend FrozenServer;
  188. //protected:
  189. enum VDState
  190. {
  191. Unknown=0,
  192. Created,
  193. Open,
  194. PreparedToFreeze,
  195. Frozen
  196. };
  197. FrozenDatabase () :
  198. m_pContext (NULL),
  199. m_hThread (NULL),
  200. m_pIVDSet (NULL),
  201. m_pIVD (NULL),
  202. m_pSnapshotCmd (NULL),
  203. m_VDState (Unknown),
  204. m_SuccessDetected (FALSE)
  205. {}
  206. Freeze2000* m_pContext;
  207. HANDLE m_hThread;
  208. IClientVirtualDeviceSet2* m_pIVDSet;
  209. IClientVirtualDevice* m_pIVD;
  210. WString m_DbName;
  211. VDC_Command* m_pSnapshotCmd;
  212. VDState m_VDState;
  213. WCHAR m_SetName [80];
  214. bool m_SuccessDetected;
  215. MetaData m_MetaData;
  216. // bool m_IsSimpleModel; // true if recovery model is simple
  217. bool m_IsMaster; // true if this is the "master" database
  218. };
  219. //-------------------------------------------------------------------------
  220. //
  221. // Handle a SQL2000 server.
  222. //
  223. // In SQL2000 we'll use VDI snapshots to avoid bug 58266: thaw fails.
  224. //
  225. // We'll prepare each database by starting a BACKUP WITH SNAPSHOT.
  226. // This will require one thread per database.
  227. // The backups will stall waiting for the VDI client to pull metadata.
  228. // When the "freeze" message comes along, the controlling thread will
  229. // pull all the BACKUPs to the frozen state.
  230. // Later the "thaw" message results in gathering the "success" report
  231. // from each thread.
  232. //
  233. //
  234. class Snapshot;
  235. class Freeze2000
  236. {
  237. friend Snapshot;
  238. friend FrozenServer;
  239. public:
  240. Freeze2000 (
  241. const WString& serverName,
  242. ULONG maxDatabases);
  243. ~Freeze2000 ();
  244. void
  245. PrepareDatabase (
  246. const WString& dbName);
  247. const BYTE*
  248. GetMetaData (
  249. const WString& dbName,
  250. UINT* pDataLength);
  251. void
  252. WaitForPrepare ();
  253. void
  254. Freeze ();
  255. BOOL
  256. Thaw () throw ();
  257. static DWORD
  258. DatabaseThreadStart (LPVOID pContext);
  259. private:
  260. enum State {
  261. Unprepared,
  262. Preparing,
  263. Prepared,
  264. Frozen,
  265. Complete,
  266. Aborted
  267. };
  268. DWORD
  269. DatabaseThread (
  270. FrozenDatabase* pDbContext);
  271. void
  272. WaitForThreads ();
  273. void
  274. AdvanceVDState (
  275. FrozenDatabase::VDState targetState);
  276. void // race-free method to persist an abort condition
  277. SetAbort ()
  278. {
  279. InterlockedIncrement (&m_AbortCount);
  280. }
  281. bool // return true if the freeze is aborting
  282. CheckAbort ()
  283. {
  284. return 0 != InterlockedCompareExchange (
  285. #ifdef DOWNLEVEL_WINBASE
  286. (void**)
  287. #endif
  288. &m_AbortCount, 0, 0);
  289. }
  290. void
  291. Abort () throw ();
  292. void
  293. Lock ()
  294. {
  295. EnterCriticalSection (&m_Latch);
  296. }
  297. void
  298. Unlock ()
  299. {
  300. LeaveCriticalSection (&m_Latch);
  301. }
  302. BOOL // return TRUE if we got the lock
  303. TryLock ()
  304. {
  305. return TryEnterCriticalSection (&m_Latch);
  306. }
  307. LONG m_AbortCount;
  308. CRITICAL_SECTION m_Latch;
  309. State m_State;
  310. WString m_ServerName;
  311. GUID m_BackupId;
  312. UINT m_NumDatabases;
  313. UINT m_MaxDatabases;
  314. FrozenDatabase* m_pDBContext;
  315. };
  316. //-------------------------------------------------------------------------
  317. // Represent a server which can be frozen.
  318. //
  319. class FrozenServer
  320. {
  321. friend Snapshot;
  322. public:
  323. FrozenServer (const std::wstring& serverName) :
  324. m_Name (serverName),
  325. m_pFreeze2000 (NULL)
  326. {}
  327. ~FrozenServer ()
  328. {
  329. if (m_pFreeze2000)
  330. {
  331. delete m_pFreeze2000;
  332. m_pFreeze2000 = NULL;
  333. }
  334. }
  335. const std::wstring& GetName () const
  336. { return m_Name; }
  337. BOOL
  338. FindDatabasesToFreeze (
  339. CCheckPath* checker);
  340. BOOL
  341. Prepare ();
  342. BOOL
  343. Freeze ();
  344. BOOL
  345. Thaw () throw ();
  346. #if 0
  347. void
  348. GetServerInfo (ServerInfo* pSrv);
  349. UINT
  350. GetDatabaseCount ();
  351. #endif
  352. void
  353. GetDatabaseInfo (UINT dbIndex, FrozenDatabaseInfo* pInfo);
  354. private:
  355. BOOL
  356. FindDatabases2000 (
  357. CCheckPath* checker);
  358. void
  359. GetDatabaseProperties70 (const WString& dbName,
  360. BOOL* pSimple,
  361. BOOL* pOnline);
  362. private:
  363. std::wstring m_Name;
  364. SqlConnection m_Connection;
  365. StringList m_FrozenDatabases;
  366. Freeze2000* m_pFreeze2000;
  367. };
  368. //-------------------------------------------------------------------------
  369. //
  370. class Snapshot : public CSqlSnapshot
  371. {
  372. enum Status {
  373. NotInitialized,
  374. Enumerated,
  375. Prepared,
  376. Frozen };
  377. public:
  378. HRESULT Prepare (
  379. CCheckPath* checker) throw ();
  380. HRESULT Freeze () throw ();
  381. HRESULT Thaw () throw ();
  382. Snapshot () {m_Status = NotInitialized;}
  383. ~Snapshot () throw ();
  384. #if 0
  385. CSqlEnumerator* GetEnumerator () throw ()
  386. {return (CSqlEnumerator*)this;}
  387. // Call this at "Post-snapshot" time, after all databases are frozen and MD is complete.
  388. //
  389. HRESULT GetBackupMetadata (
  390. const WCHAR* pInstance,
  391. const WCHAR* pDatabase,
  392. BYTE** ppData, // returns a pointer to the string of metadata
  393. unsigned int* pDataLen) // length of the metadata (in bytes)
  394. throw ();
  395. // The enumeration interface
  396. //
  397. HRESULT FirstServer (
  398. ServerInfo* pServer) throw ();
  399. HRESULT NextServer (
  400. ServerInfo* pServer) throw ();
  401. HRESULT FirstDatabase (
  402. const WCHAR* pServerName,
  403. DatabaseInfo* pDbInfo) throw ()
  404. {return E_NOTIMPL;}
  405. HRESULT FirstDatabase (
  406. DatabaseInfo* pDbInfo) throw ();
  407. HRESULT NextDatabase (
  408. DatabaseInfo* pDbInfo) throw ();
  409. HRESULT FirstFile (
  410. const WCHAR* pServerName,
  411. const WCHAR* pDbName,
  412. DatabaseFileInfo* pDbInfo) throw ()
  413. {return E_NOTIMPL;}
  414. HRESULT NextFile (
  415. DatabaseFileInfo* pDbInfo) throw ()
  416. {return E_NOTIMPL;}
  417. #endif
  418. HRESULT GetFirstDatabase (
  419. FrozenDatabaseInfo* pInfo) throw ();
  420. HRESULT GetNextDatabase (
  421. FrozenDatabaseInfo* pInfo) throw ();
  422. private:
  423. void
  424. Deinitialize ();
  425. Status m_Status;
  426. std::list<FrozenServer*> m_FrozenServers;
  427. typedef std::list<FrozenServer*>::iterator ServerIter;
  428. ServerIter m_ServerIter; // iterate over the frozen servers
  429. UINT m_DbIndex; // iterate over databases within a server
  430. };
  431. //-------------------------------------------------------------------------
  432. //
  433. class RestoreHandler : public CSqlRestore
  434. {
  435. public:
  436. RestoreHandler ();
  437. // Inform SQLServer that data laydown is desired on the full database.
  438. // Performs a DETACH, preventing SQLServer from touching the files.
  439. //
  440. virtual HRESULT PrepareToRestore (
  441. const WCHAR* pInstance,
  442. const WCHAR* pDatabase)
  443. throw ();
  444. // After data is laid down, this performs RESTORE WITH SNAPSHOT[,NORECOVERY]
  445. //
  446. virtual HRESULT FinalizeRestore (
  447. const WCHAR* pInstance,
  448. const WCHAR* pDatabase,
  449. bool compositeRestore, // true if WITH NORECOVERY desired
  450. const BYTE* pMetadata, // metadata obtained from BACKUP
  451. unsigned int dataLen) // size of metadata (in bytes)
  452. throw ();
  453. // Internal use only. Called from the thread proc wrapper.
  454. //
  455. void
  456. RestoreVD ();
  457. private:
  458. SqlConnection m_Connection;
  459. HANDLE m_hThread;
  460. IClientVirtualDeviceSet2* m_pIVDSet;
  461. IClientVirtualDevice* m_pIVD;
  462. WCHAR m_SetName [80];
  463. GUID m_VDSId;
  464. const BYTE* m_pMetaData;
  465. UINT m_MetaDataSize;
  466. };
  467. // We'll use very simple exception handling.
  468. //
  469. #define THROW_GENERIC throw exception ();
  470. //----------------------------------------------------------
  471. // Implement our simple enumeration service
  472. //
  473. class SqlEnumerator : public CSqlEnumerator
  474. {
  475. enum Status {
  476. Unknown = 0,
  477. DatabaseQueryActive,
  478. FileQueryActive
  479. };
  480. public:
  481. ~SqlEnumerator () throw ();
  482. SqlEnumerator () :
  483. m_State (Unknown),
  484. m_pServers (NULL)
  485. {}
  486. HRESULT FirstServer (
  487. ServerInfo* pServer) throw ();
  488. HRESULT NextServer (
  489. ServerInfo* pServer) throw ();
  490. HRESULT FirstDatabase (
  491. const WCHAR* pServerName,
  492. DatabaseInfo* pDbInfo) throw ();
  493. HRESULT NextDatabase (
  494. DatabaseInfo* pDbInfo) throw ();
  495. HRESULT FirstFile (
  496. const WCHAR* pServerName,
  497. const WCHAR* pDbName,
  498. DatabaseFileInfo* pDbInfo) throw ();
  499. HRESULT NextFile (
  500. DatabaseFileInfo* pDbInfo) throw ();
  501. private:
  502. void
  503. SetupDatabaseInfo (
  504. DatabaseInfo* pDbInfo);
  505. Status m_State;
  506. SqlConnection m_Connection;
  507. StringVector* m_pServers;
  508. UINT m_CurrServer;
  509. };
  510. #if defined (DEBUG)
  511. // Type of assertion passed through to utassert_fail function.
  512. //
  513. #define DBG_ASSERT(exp) BS_ASSERT(exp)
  514. // Allow for noop 64 bit asserts on win32 for things like
  515. // overflowing 32 bit long, etc.
  516. //
  517. #ifdef _WIN64
  518. #define DBG64_ASSERT(exp) BS_ASSERT(exp)
  519. #else
  520. #define DBG64_ASSERT(exp)
  521. #endif
  522. #else
  523. #define DBG_ASSERT(exp)
  524. #define DBG64_ASSERT(exp)
  525. #define DBG_ASSERTSZ(exp, txt)
  526. #endif