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.

791 lines
23 KiB

  1. #include <stdafx.h>
  2. #include <vss.h>
  3. #include <vswriter.h>
  4. #include <jetwriter.h>
  5. #include <esent98.h>
  6. #define DATABASE_ROOT L"%SystemDrive%\\JetTestDatabases"
  7. #define DATABASE_ROOT_A "%SystemDrive%\\JetTestDatabases"
  8. #define INCLUDED_DATABASES L"\\IncludedDatabases"
  9. #define INCLUDED_DATABASES_A "\\IncludedDatabases"
  10. #define EXCLUDED_DATABASES L"\\ExcludedDatabases"
  11. #define EXCLUDED_DATABASES_A "\\ExcludedDatabases"
  12. #if 1
  13. #define FilesToInclude L"X:\\Element-00\\/s;" \
  14. L"x:\\Element-01\\/s;" \
  15. L"x:\\Element-02\\* /S ;" \
  16. L" x:\\Element-03\\a very long path\\with a long dir\\a.bat"
  17. #define FilesToExclude DATABASE_ROOT EXCLUDED_DATABASES L"\\" L" /s"
  18. #else
  19. /*
  20. ** These are the paths used by RSS at one point.
  21. */
  22. #define FilesToExclude L"%SystemRoot%\\System32\\RemoteStorage\\FsaDb\\*;" \
  23. L"%SystemRoot%\\System32\\RemoteStorage\\Trace\\*"
  24. #define FilesToInclude L""
  25. #endif
  26. #define GET_STATUS_FROM_BOOL(_bSucceeded) ((_bSucceeded) ? NOERROR : HRESULT_FROM_WIN32 (GetLastError()))
  27. #define GET_STATUS_FROM_HANDLE(_handle) ((NULL != (_handle)) ? NOERROR : HRESULT_FROM_WIN32 (GetLastError()))
  28. #define GET_STATUS_FROM_POINTER(_ptr) ((NULL != (_ptr)) ? NOERROR : E_OUTOFMEMORY)
  29. static const PCHAR achDatabaseNames [] =
  30. {
  31. DATABASE_ROOT_A INCLUDED_DATABASES_A "\\jettest_db0.jdb",
  32. DATABASE_ROOT_A EXCLUDED_DATABASES_A "\\jettest_db1.jdb",
  33. DATABASE_ROOT_A INCLUDED_DATABASES_A "\\jettest_db2.jdb",
  34. DATABASE_ROOT_A EXCLUDED_DATABASES_A "\\jettest_db3.jdb",
  35. DATABASE_ROOT_A INCLUDED_DATABASES_A "\\jettest_db4.jdb",
  36. DATABASE_ROOT_A EXCLUDED_DATABASES_A "\\jettest_db5.jdb",
  37. DATABASE_ROOT_A INCLUDED_DATABASES_A "\\jettest_db6.jdb",
  38. DATABASE_ROOT_A EXCLUDED_DATABASES_A "\\jettest_db7.jdb"
  39. };
  40. #define MAX_DATABASE_COUNT (sizeof (achDatabaseNames) / sizeof (PWCHAR))
  41. static CHAR achExpandedDatabaseNames [MAX_DATABASE_COUNT] [MAX_PATH + 1];
  42. static const char szUser [] = "admin";
  43. static const char szPassword [] = "\0";
  44. static const char szTable1 [] = "table1";
  45. static const char szTable2 [] = "table2";
  46. static const char szF1Name [] = "F1PAD";
  47. static const char szF2Name [] = "F2";
  48. static const char szF3Name [] = "F3";
  49. static const char szV1Name [] = "V1";
  50. static const char szT1Name [] = "T1";
  51. static const char szT2Name [] = "T2";
  52. static const char szXF1Name [] = "XF1";
  53. static const char szXF3F2Name [] = "XF3F2";
  54. static const char szXV1Name [] = "XV1";
  55. static const char szXT1Name [] = "XT1";
  56. static const char szXT2Name [] = "XT2";
  57. HANDLE *g_phEventHandles = NULL;
  58. typedef enum
  59. {
  60. eHandleControlC = 0,
  61. eHandleStepToNextConfig,
  62. eHandleMaxHandleCount
  63. } EHANDLEOFFSETS;
  64. typedef struct
  65. {
  66. PCHAR pszDatabaseName;
  67. JET_DBID idDatabase;
  68. } CONTEXTDB, *PCONTEXTDB, **PPCONTEXTDB;
  69. typedef struct
  70. {
  71. JET_INSTANCE idInstance;
  72. JET_SESID idSession;
  73. CONTEXTDB aDatabase [MAX_DATABASE_COUNT];
  74. } CONTEXTJET, *PCONTEXTJET, **PPCONTEXTJET;
  75. class CVssJetWriterLocal : public CVssJetWriter
  76. {
  77. public:
  78. virtual bool STDMETHODCALLTYPE OnThawEnd (bool fJetThawSucceeded);
  79. virtual void STDMETHODCALLTYPE OnAbortEnd ();
  80. virtual bool STDMETHODCALLTYPE OnPostRestoreEnd(IVssWriterComponents *pComponents, bool bSucceeded);
  81. };
  82. bool STDMETHODCALLTYPE CVssJetWriterLocal::OnThawEnd (bool fJetThawSucceeded)
  83. {
  84. UNREFERENCED_PARAMETER(fJetThawSucceeded);
  85. wprintf(L"OnThawEnd\n");
  86. SetEvent (g_phEventHandles [eHandleStepToNextConfig]);
  87. return (true);
  88. }
  89. void STDMETHODCALLTYPE CVssJetWriterLocal::OnAbortEnd ()
  90. {
  91. wprintf(L"OnAbortEnd\n");
  92. SetEvent (g_phEventHandles [eHandleStepToNextConfig]);
  93. }
  94. // This function displays the formatted message at the console and throws
  95. void Error(
  96. IN INT nReturnCode,
  97. IN const WCHAR* pwszMsgFormat,
  98. IN ...
  99. )
  100. {
  101. va_list marker;
  102. va_start( marker, pwszMsgFormat );
  103. vwprintf( pwszMsgFormat, marker );
  104. va_end( marker );
  105. BS_ASSERT(FALSE);
  106. // throw that return code.
  107. throw(nReturnCode);
  108. }
  109. // Convert a component type into a string
  110. LPCWSTR GetStringFromComponentType (VSS_COMPONENT_TYPE eComponentType)
  111. {
  112. LPCWSTR pwszRetString = L"UNDEFINED";
  113. switch (eComponentType)
  114. {
  115. case VSS_CT_DATABASE: pwszRetString = L"Database"; break;
  116. case VSS_CT_FILEGROUP: pwszRetString = L"FileGroup"; break;
  117. default:
  118. break;
  119. }
  120. return (pwszRetString);
  121. }
  122. // Convert a failure type into a string
  123. LPCWSTR GetStringFromFailureType(HRESULT hrStatus)
  124. {
  125. LPCWSTR pwszFailureType = L"";
  126. switch (hrStatus)
  127. {
  128. case VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT: pwszFailureType = L"VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT"; break;
  129. case VSS_E_WRITERERROR_OUTOFRESOURCES: pwszFailureType = L"VSS_E_WRITERERROR_OUTOFRESOURCES"; break;
  130. case VSS_E_WRITERERROR_TIMEOUT: pwszFailureType = L"VSS_E_WRITERERROR_TIMEOUT"; break;
  131. case VSS_E_WRITERERROR_NONRETRYABLE: pwszFailureType = L"VSS_E_WRITERERROR_NONRETRYABLE"; break;
  132. case VSS_E_WRITERERROR_RETRYABLE: pwszFailureType = L"VSS_E_WRITERERROR_RETRYABLE"; break;
  133. case VSS_E_BAD_STATE: pwszFailureType = L"VSS_E_BAD_STATE"; break;
  134. case VSS_E_PROVIDER_ALREADY_REGISTERED: pwszFailureType = L"VSS_E_PROVIDER_ALREADY_REGISTERED"; break;
  135. case VSS_E_PROVIDER_NOT_REGISTERED: pwszFailureType = L"VSS_E_PROVIDER_NOT_REGISTERED"; break;
  136. case VSS_E_PROVIDER_VETO: pwszFailureType = L"VSS_E_PROVIDER_VETO"; break;
  137. case VSS_E_PROVIDER_IN_USE: pwszFailureType = L"VSS_E_PROVIDER_IN_USE"; break;
  138. case VSS_E_OBJECT_NOT_FOUND: pwszFailureType = L"VSS_E_OBJECT_NOT_FOUND"; break;
  139. case VSS_S_ASYNC_PENDING: pwszFailureType = L"VSS_S_ASYNC_PENDING"; break;
  140. case VSS_S_ASYNC_FINISHED: pwszFailureType = L"VSS_S_ASYNC_FINISHED"; break;
  141. case VSS_S_ASYNC_CANCELLED: pwszFailureType = L"VSS_S_ASYNC_CANCELLED"; break;
  142. case VSS_E_VOLUME_NOT_SUPPORTED: pwszFailureType = L"VSS_E_VOLUME_NOT_SUPPORTED"; break;
  143. case VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER: pwszFailureType = L"VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER"; break;
  144. case VSS_E_OBJECT_ALREADY_EXISTS: pwszFailureType = L"VSS_E_OBJECT_ALREADY_EXISTS"; break;
  145. case VSS_E_UNEXPECTED_PROVIDER_ERROR: pwszFailureType = L"VSS_E_UNEXPECTED_PROVIDER_ERROR"; break;
  146. case VSS_E_CORRUPT_XML_DOCUMENT: pwszFailureType = L"VSS_E_CORRUPT_XML_DOCUMENT"; break;
  147. case VSS_E_INVALID_XML_DOCUMENT: pwszFailureType = L"VSS_E_INVALID_XML_DOCUMENT"; break;
  148. case VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED: pwszFailureType = L"VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED"; break;
  149. case VSS_E_FLUSH_WRITES_TIMEOUT: pwszFailureType = L"VSS_E_FLUSH_WRITES_TIMEOUT"; break;
  150. case VSS_E_HOLD_WRITES_TIMEOUT: pwszFailureType = L"VSS_E_HOLD_WRITES_TIMEOUT"; break;
  151. case VSS_E_UNEXPECTED_WRITER_ERROR: pwszFailureType = L"VSS_E_UNEXPECTED_WRITER_ERROR"; break;
  152. case VSS_E_SNAPSHOT_SET_IN_PROGRESS: pwszFailureType = L"VSS_E_SNAPSHOT_SET_IN_PROGRESS"; break;
  153. case VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED: pwszFailureType = L"VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED"; break;
  154. case VSS_E_WRITER_INFRASTRUCTURE: pwszFailureType = L"VSS_E_WRITER_INFRASTRUCTURE"; break;
  155. case VSS_E_WRITER_NOT_RESPONDING: pwszFailureType = L"VSS_E_WRITER_NOT_RESPONDING"; break;
  156. case VSS_E_WRITER_ALREADY_SUBSCRIBED: pwszFailureType = L"VSS_E_WRITER_ALREADY_SUBSCRIBED"; break;
  157. case NOERROR:
  158. default:
  159. break;
  160. }
  161. return (pwszFailureType);
  162. }
  163. // Execute the given call and check that the return code must be S_OK
  164. #define CHECK_SUCCESS( Call ) \
  165. { \
  166. hr = Call; \
  167. if (hr != S_OK) \
  168. Error(1, L"\nError in %S(%d): \n\t- Call %S not succeeded. \n" \
  169. L"\t Error code = 0x%08lx. Error description = %s\n", \
  170. __FILE__, __LINE__, #Call, hr, GetStringFromFailureType(hr)); \
  171. }
  172. #define CHECK_NOFAIL( Call ) \
  173. { \
  174. hr = Call; \
  175. if (FAILED(hr)) \
  176. Error(1, L"\nError in %S(%d): \n\t- Call %S not succeeded. \n" \
  177. L"\t Error code = 0x%08lx. Error description = %s\n", \
  178. __FILE__, __LINE__, #Call, hr, GetStringFromFailureType(hr)); \
  179. }
  180. bool STDMETHODCALLTYPE CVssJetWriterLocal::OnPostRestoreEnd(IVssWriterComponents *pWriter, bool bRestoreSucceeded)
  181. {
  182. wprintf(L"Restore invoked.\n");
  183. if (bRestoreSucceeded)
  184. wprintf(L"Restore succeeded.\n");
  185. else
  186. wprintf(L"Restore failed.");
  187. try
  188. {
  189. HRESULT hr;
  190. unsigned cComponents;
  191. CHECK_SUCCESS(pWriter->GetComponentCount(&cComponents));
  192. VSS_ID idWriter, idInstance;
  193. CHECK_SUCCESS(pWriter->GetWriterInfo(&idInstance, &idWriter));
  194. for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
  195. {
  196. CComPtr<IVssComponent> pComponent;
  197. CHECK_SUCCESS(pWriter->GetComponent(iComponent, &pComponent));
  198. VSS_COMPONENT_TYPE ct;
  199. CComBSTR bstrLogicalPath;
  200. CComBSTR bstrComponentName;
  201. CHECK_NOFAIL(pComponent->GetLogicalPath(&bstrLogicalPath));
  202. CHECK_SUCCESS(pComponent->GetComponentType(&ct));
  203. CHECK_SUCCESS(pComponent->GetComponentName(&bstrComponentName));
  204. wprintf(L"COMPONENT path = %s, type=%s, name=%s\n", bstrLogicalPath, GetStringFromComponentType(ct), bstrComponentName);
  205. }
  206. }
  207. catch(...)
  208. {
  209. wprintf(L"***Unexpected exception thrown.***\n");
  210. }
  211. return true;
  212. }
  213. #define DO_CALL(xCall) \
  214. { \
  215. JET_ERR jetStatus = xCall; \
  216. if (jetStatus < JET_errSuccess) \
  217. Error(1, L"\nError in %S(%d): \n\t- Call %S not succeeded. \n" \
  218. L"\t Error code = 0x%08lx.\n", \
  219. __FILE__, __LINE__, #xCall, jetStatus); \
  220. }
  221. BOOL WINAPI Ctrl_C_Handler_Routine(IN DWORD type)
  222. {
  223. UNREFERENCED_PARAMETER(type);
  224. if (g_phEventHandles [eHandleControlC])
  225. {
  226. SetEvent (g_phEventHandles [eHandleControlC]);
  227. }
  228. return TRUE;
  229. }
  230. JET_ERR CreateAndPopulateDatabase (JET_SESID idSession,
  231. const char *szDatabase,
  232. JET_DBID *pidDatabase)
  233. {
  234. JET_DBID idDatabase;
  235. JET_TABLEID idTable;
  236. JET_COLUMNDEF columndef;
  237. JET_COLUMNID idColumnF1;
  238. JET_COLUMNID idColumnF2;
  239. JET_COLUMNID idColumnF3;
  240. JET_COLUMNID idColumnV1;
  241. JET_COLUMNID idColumnT1;
  242. JET_COLUMNID idColumnT2;
  243. const unsigned short usCodePage = 1252;
  244. const unsigned short usLanguage = 0x409;
  245. const long lOne = 1;
  246. DO_CALL (JetCreateDatabase (idSession, szDatabase, NULL, &idDatabase, 0));
  247. DO_CALL (JetCloseDatabase (idSession, idDatabase, 0));
  248. /*
  249. ** check multiple opens of same database
  250. */
  251. DO_CALL (JetOpenDatabase (idSession, szDatabase, NULL, &idDatabase, 0));
  252. DO_CALL (JetBeginTransaction (idSession));
  253. DO_CALL (JetCreateTable (idSession, idDatabase, szTable1, 0, 100, &idTable));
  254. DO_CALL (JetCloseTable (idSession, idTable));
  255. DO_CALL (JetOpenTable (idSession, idDatabase, szTable1, NULL, 0, JET_bitTableDenyRead, &idTable));
  256. columndef.cbStruct = sizeof (columndef);
  257. columndef.cp = usCodePage;
  258. columndef.langid = usLanguage;
  259. columndef.wCountry = 1;
  260. columndef.columnid = 0;
  261. columndef.coltyp = JET_coltypLong;
  262. columndef.cbMax = 0;
  263. columndef.grbit = 0;
  264. DO_CALL (JetAddColumn (idSession, idTable, szF1Name, &columndef, &lOne, sizeof(lOne), &idColumnF1));
  265. columndef.cbStruct = sizeof (columndef);
  266. columndef.cp = usCodePage;
  267. columndef.langid = usLanguage;
  268. columndef.wCountry = 1;
  269. columndef.columnid = 0;
  270. columndef.coltyp = JET_coltypUnsignedByte;
  271. columndef.cbMax = 0;
  272. columndef.grbit = 0;
  273. DO_CALL (JetAddColumn (idSession, idTable, szF2Name, &columndef, NULL, 0, &idColumnF2));
  274. columndef.cbStruct = sizeof (columndef);
  275. columndef.cp = usCodePage;
  276. columndef.langid = usLanguage;
  277. columndef.wCountry = 1;
  278. columndef.columnid = 0;
  279. columndef.coltyp = JET_coltypLong;
  280. columndef.cbMax = 0;
  281. columndef.grbit = 0;
  282. DO_CALL (JetAddColumn (idSession, idTable, szF3Name, &columndef, NULL, 0, &idColumnF3));
  283. columndef.cbStruct = sizeof (columndef);
  284. columndef.cp = usCodePage;
  285. columndef.langid = usLanguage;
  286. columndef.wCountry = 1;
  287. columndef.columnid = 0;
  288. columndef.coltyp = JET_coltypText;
  289. columndef.cbMax = 0;
  290. columndef.grbit = 0;
  291. DO_CALL (JetAddColumn (idSession, idTable, szV1Name, &columndef, NULL, 0, &idColumnV1));
  292. columndef.cbStruct = sizeof (columndef);
  293. columndef.cp = usCodePage;
  294. columndef.langid = usLanguage;
  295. columndef.wCountry = 1;
  296. columndef.columnid = 0;
  297. columndef.coltyp = JET_coltypLongText;
  298. columndef.cbMax = 0;
  299. columndef.grbit = JET_bitColumnTagged | JET_bitColumnMultiValued;
  300. DO_CALL (JetAddColumn (idSession, idTable, szT1Name, &columndef, NULL, 0, &idColumnT1));
  301. columndef.cbStruct = sizeof (columndef);
  302. columndef.cp = usCodePage;
  303. columndef.langid = usLanguage;
  304. columndef.wCountry = 1;
  305. columndef.columnid = 0;
  306. columndef.coltyp = JET_coltypBinary;
  307. columndef.cbMax = 0;
  308. columndef.grbit = JET_bitColumnTagged | JET_bitColumnMultiValued;
  309. DO_CALL (JetAddColumn (idSession, idTable, szT2Name, &columndef, NULL, 0, &idColumnT2));
  310. {
  311. char rgbCols[50];
  312. sprintf( rgbCols, "+%s", szF1Name);
  313. rgbCols[ 1 + strlen(szF1Name) + 1] = '\0';
  314. *(unsigned short *)(&rgbCols[ 1 + strlen(szF1Name) + 1 + 1]) = usLanguage;
  315. rgbCols[ 1 + strlen(szF1Name) + 1 + 1 + sizeof(usLanguage) ] = '\0';
  316. rgbCols[ 1 + strlen(szF1Name) + 1 + 1 + sizeof(usLanguage) + 1] = '\0';
  317. DO_CALL (JetCreateIndex (idSession,
  318. idTable,
  319. szXF1Name,
  320. JET_bitIndexPrimary | JET_bitIndexUnique,
  321. rgbCols,
  322. 1 + strlen( szF1Name) + 1 + 1 + sizeof(usLanguage) + 1 + 1,
  323. 100));
  324. }
  325. DO_CALL (JetCloseTable (idSession, idTable));
  326. DO_CALL (JetCommitTransaction (idSession, 0));
  327. *pidDatabase = idDatabase;
  328. return (JET_errSuccess);
  329. }
  330. void DatabaseSetup (PCONTEXTJET pctxJet, ULONG ulDatabaseCount)
  331. {
  332. JET_ERR jetStatus;
  333. DO_CALL (JetBeginSession (pctxJet->idInstance, &pctxJet->idSession, szUser, szPassword));
  334. while (ulDatabaseCount-- > 0)
  335. {
  336. jetStatus = JetAttachDatabase (pctxJet->idSession,
  337. pctxJet->aDatabase [ulDatabaseCount].pszDatabaseName,
  338. 0);
  339. if (jetStatus >= JET_errSuccess)
  340. {
  341. DO_CALL (JetOpenDatabase (pctxJet->idSession,
  342. pctxJet->aDatabase [ulDatabaseCount].pszDatabaseName,
  343. NULL,
  344. &pctxJet->aDatabase [ulDatabaseCount].idDatabase,
  345. 0));
  346. }
  347. else
  348. {
  349. DO_CALL (CreateAndPopulateDatabase (pctxJet->idSession,
  350. pctxJet->aDatabase [ulDatabaseCount].pszDatabaseName,
  351. &pctxJet->aDatabase [ulDatabaseCount].idDatabase));
  352. }
  353. }
  354. }
  355. void DatabaseCleanup (PCONTEXTJET pctxJet, ULONG ulDatabaseCount)
  356. {
  357. while (ulDatabaseCount-- > 0)
  358. {
  359. DO_CALL (JetCloseDatabase (pctxJet->idSession,
  360. pctxJet->aDatabase [ulDatabaseCount].idDatabase,
  361. 0));
  362. DO_CALL (JetDetachDatabase (pctxJet->idSession,
  363. pctxJet->aDatabase [ulDatabaseCount].pszDatabaseName));
  364. }
  365. DO_CALL (JetEndSession (pctxJet->idSession, 0));
  366. }
  367. extern "C" int _cdecl wmain(int argc, WCHAR **argv)
  368. {
  369. UNREFERENCED_PARAMETER(argc);
  370. UNREFERENCED_PARAMETER(argv);
  371. HRESULT hrStatus = NOERROR;
  372. DWORD dwStatus = 0;
  373. GUID idWriter = GUID_NULL;
  374. CVssJetWriter *pWriter = NULL;
  375. bool bContinue = true;
  376. BOOL bSucceeded = FALSE;
  377. ULONG ulDatabaseCount = 3;
  378. ULONG ulIndex;
  379. HANDLE hEventHandles [eHandleMaxHandleCount];
  380. CONTEXTJET ctxJet;
  381. WCHAR wszBufferName [MAX_PATH + 1];
  382. DWORD dwCharCount;
  383. dwCharCount = ExpandEnvironmentStringsW (DATABASE_ROOT, wszBufferName, sizeof (wszBufferName));
  384. hrStatus = GET_STATUS_FROM_BOOL (0 != dwCharCount);
  385. if (FAILED (hrStatus))
  386. {
  387. wprintf (L"ExpandEnvironmentStringsW (%s) FAILED with error code %08x\n",
  388. DATABASE_ROOT,
  389. hrStatus);
  390. }
  391. bSucceeded = CreateDirectoryW (wszBufferName, NULL);
  392. hrStatus = GET_STATUS_FROM_BOOL (bSucceeded);
  393. if (FAILED (hrStatus) && (HRESULT_FROM_WIN32 (ERROR_ALREADY_EXISTS) != hrStatus))
  394. {
  395. wprintf (L"CreateDirectoryW (%s) FAILED with error code %08x\n",
  396. wszBufferName,
  397. hrStatus);
  398. }
  399. dwCharCount = ExpandEnvironmentStringsW (DATABASE_ROOT INCLUDED_DATABASES, wszBufferName, sizeof (wszBufferName));
  400. hrStatus = GET_STATUS_FROM_BOOL (0 != dwCharCount);
  401. if (FAILED (hrStatus))
  402. {
  403. wprintf (L"ExpandEnvironmentStringsW (%s) FAILED with error code %08x\n",
  404. DATABASE_ROOT INCLUDED_DATABASES,
  405. hrStatus);
  406. }
  407. bSucceeded = CreateDirectoryW (wszBufferName, NULL);
  408. hrStatus = GET_STATUS_FROM_BOOL (bSucceeded);
  409. if (FAILED (hrStatus) && (HRESULT_FROM_WIN32 (ERROR_ALREADY_EXISTS) != hrStatus))
  410. {
  411. wprintf (L"CreateDirectoryW (%s) FAILED with error code %08x\n",
  412. wszBufferName,
  413. hrStatus);
  414. }
  415. dwCharCount = ExpandEnvironmentStringsW (DATABASE_ROOT EXCLUDED_DATABASES, wszBufferName, sizeof (wszBufferName));
  416. hrStatus = GET_STATUS_FROM_BOOL (0 != dwCharCount);
  417. if (FAILED (hrStatus))
  418. {
  419. wprintf (L"ExpandEnvironmentStringsW (%s) FAILED with error code %08x\n",
  420. DATABASE_ROOT EXCLUDED_DATABASES,
  421. hrStatus);
  422. }
  423. bSucceeded = CreateDirectoryW (wszBufferName, NULL);
  424. hrStatus = GET_STATUS_FROM_BOOL (bSucceeded);
  425. if (FAILED (hrStatus) && (HRESULT_FROM_WIN32 (ERROR_ALREADY_EXISTS) != hrStatus))
  426. {
  427. wprintf (L"CreateDirectoryW (%s) FAILED with error code %08x\n",
  428. wszBufferName,
  429. hrStatus);
  430. }
  431. hrStatus = NOERROR;
  432. /*
  433. ** Initialise the database contexts
  434. */
  435. ctxJet.idInstance = 0;
  436. ctxJet.idSession = 0;
  437. for (ulIndex = 0; ulIndex < MAX_DATABASE_COUNT; ulIndex++)
  438. {
  439. dwCharCount = ExpandEnvironmentStringsA (achDatabaseNames [ulIndex],
  440. achExpandedDatabaseNames [ulIndex],
  441. sizeof (achExpandedDatabaseNames [ulIndex]));
  442. ctxJet.aDatabase [ulIndex].idDatabase = 0;
  443. ctxJet.aDatabase [ulIndex].pszDatabaseName = achExpandedDatabaseNames [ulIndex];
  444. }
  445. /*
  446. ** Initialise the event handles array
  447. */
  448. for (ulIndex = 0; ulIndex < eHandleMaxHandleCount; ulIndex++)
  449. {
  450. if (SUCCEEDED (hrStatus))
  451. {
  452. hEventHandles [ulIndex] = CreateEvent (NULL, FALSE, FALSE, NULL);
  453. hrStatus = GET_STATUS_FROM_HANDLE (hEventHandles [ulIndex] );
  454. if (NULL == hEventHandles [ulIndex])
  455. {
  456. wprintf (L"CreateEvent %u failed with error code %08X\n", ulIndex, hrStatus);
  457. }
  458. }
  459. }
  460. /*
  461. ** Hook up the console GetOutOfJail device
  462. */
  463. if (SUCCEEDED (hrStatus))
  464. {
  465. g_phEventHandles = hEventHandles;
  466. ::SetConsoleCtrlHandler (Ctrl_C_Handler_Routine, TRUE);
  467. }
  468. /*
  469. ** Tally-ho chaps!
  470. */
  471. try
  472. {
  473. DO_CALL (JetInit(&ctxJet.idInstance));
  474. hrStatus = CoInitializeEx (NULL, COINIT_MULTITHREADED);
  475. if (FAILED (hrStatus))
  476. {
  477. wprintf (L"CoInitializeEx failed with error code %08x\n", hrStatus);
  478. }
  479. hrStatus = CoInitializeSecurity
  480. (
  481. NULL, // IN PSECURITY_DESCRIPTOR pSecDesc,
  482. -1, // IN LONG cAuthSvc,
  483. NULL, // IN SOLE_AUTHENTICATION_SERVICE *asAuthSvc,
  484. NULL, // IN void *pReserved1,
  485. RPC_C_AUTHN_LEVEL_CONNECT, // IN DWORD dwAuthnLevel,
  486. RPC_C_IMP_LEVEL_IMPERSONATE, // IN DWORD dwImpLevel,
  487. NULL, // IN void *pAuthList,
  488. EOAC_NONE, // IN DWORD dwCapabilities,
  489. NULL // IN void *pReserved3
  490. );
  491. if (FAILED (hrStatus))
  492. {
  493. wprintf (L"CoInitializeSecurity failed with error code %08x\n", hrStatus);
  494. }
  495. if (SUCCEEDED (hrStatus))
  496. {
  497. pWriter = new CVssJetWriterLocal;
  498. if (NULL == pWriter)
  499. {
  500. wprintf (L"new CVssJetWriter failed");
  501. hrStatus = HRESULT_FROM_WIN32 (ERROR_NOT_ENOUGH_MEMORY);
  502. }
  503. }
  504. if (SUCCEEDED (hrStatus))
  505. {
  506. hrStatus = pWriter->Initialize (idWriter, // id of writer
  507. L"JetTest Writer", // name of writer
  508. true, // system service
  509. false, // bootable state
  510. FilesToInclude, // files to include
  511. FilesToExclude); // files to exclude
  512. if (FAILED (hrStatus))
  513. {
  514. wprintf (L"CVssJetWriter::Initialize failed with error code %08x\n", hrStatus);
  515. }
  516. }
  517. while (SUCCEEDED (hrStatus) && bContinue)
  518. {
  519. DatabaseSetup (&ctxJet, ulDatabaseCount);
  520. dwStatus = WaitForMultipleObjects (eHandleMaxHandleCount, hEventHandles, FALSE, INFINITE);
  521. DatabaseCleanup (&ctxJet, ulDatabaseCount);
  522. switch (dwStatus - WAIT_OBJECT_0)
  523. {
  524. case (eHandleControlC):
  525. bContinue = FALSE;
  526. break;
  527. case (eHandleStepToNextConfig):
  528. ulDatabaseCount = (ulDatabaseCount + 1) % (MAX_DATABASE_COUNT + 1);
  529. break;
  530. default:
  531. BS_ASSERT (0);
  532. break;
  533. }
  534. }
  535. }
  536. catch(...)
  537. {
  538. wprintf(L"unexpected exception\n");
  539. exit(-1);
  540. }
  541. for (ulIndex = 0; ulIndex < eHandleMaxHandleCount; ulIndex++)
  542. {
  543. if (NULL != hEventHandles [ulIndex])
  544. {
  545. CloseHandle (hEventHandles [ulIndex]);
  546. hEventHandles [ulIndex] = NULL;
  547. }
  548. }
  549. if (NULL != pWriter)
  550. {
  551. pWriter->Uninitialize();
  552. delete pWriter;
  553. pWriter = NULL;
  554. }
  555. DO_CALL (JetTerm (ctxJet.idInstance));
  556. return (hrStatus);
  557. }