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.

2839 lines
70 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved
  3. Module Name:
  4. wsbpstbl.cpp
  5. Abstract:
  6. Abstract classes that provides persistence methods.
  7. Author:
  8. Chuck Bardeen [cbardeen] 29-Oct-1996
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "resource.h"
  13. #include "wsbport.h"
  14. #include "wsbpstbl.h"
  15. #include "wsbtrak.h"
  16. #define BYTE_SIZE 64 // Larger than largest BYTE_SIZE_*
  17. #define PERSIST_CHECK_VALUE 0x456D5377 // ASCII: "EmSw" (Eastman Software)
  18. // Local functions
  19. static BOOL WsbFileExists(OLECHAR* pFileName);
  20. // ******** CWsbPersistStream ************
  21. #pragma optimize("g", off)
  22. HRESULT
  23. CWsbPersistStream::FinalConstruct(
  24. void
  25. )
  26. /*++
  27. Implements:
  28. CComObjectRoot::FinalConstruct().
  29. --*/
  30. {
  31. HRESULT hr = S_OK;
  32. try {
  33. WsbAffirmHr(CComObjectRoot::FinalConstruct());
  34. // Initialize some member data.
  35. m_isDirty = TRUE;
  36. // Add class to object table
  37. GUID guid;
  38. if (S_OK != GetClassID(&guid)) {
  39. guid = GUID_NULL;
  40. }
  41. WSB_OBJECT_ADD(guid, this);
  42. } WsbCatch(hr);
  43. return(hr);
  44. }
  45. #pragma optimize("", on)
  46. void
  47. CWsbPersistStream::FinalRelease(
  48. void
  49. )
  50. /*++
  51. Implements:
  52. CComObjectRoot::FinalRelease().
  53. --*/
  54. {
  55. // Subtract class from object table
  56. GUID guid;
  57. if (S_OK != GetClassID(&guid)) {
  58. guid = GUID_NULL;
  59. }
  60. WSB_OBJECT_SUB(guid, this);
  61. CComObjectRoot::FinalRelease();
  62. }
  63. #if defined(WSB_TRACK_MEMORY)
  64. ULONG
  65. CWsbPersistStream::InternalAddRef(
  66. )
  67. {
  68. WsbTraceIn( L"CWsbPersistStream::InternalAddRef", L"this = %p",
  69. static_cast<void *>(this) );
  70. ULONG retval = CComObjectRoot::InternalAddRef( );
  71. WsbTraceOut( L"CWsbPersistStream::InternalAddRef", L"retval = %lu", retval);
  72. return( retval );
  73. }
  74. ULONG
  75. CWsbPersistStream::InternalRelease(
  76. )
  77. {
  78. WsbTraceIn( L"CWsbPersistStream::InternalRelease", L"this = %p",
  79. static_cast<void *>(this) );
  80. ULONG retval = CComObjectRoot::InternalRelease( );
  81. WsbTraceOut( L"CWsbPersistStream::InternalRelease", L"retval = %lu", retval);
  82. return( retval );
  83. }
  84. #endif
  85. HRESULT
  86. CWsbPersistStream::IsDirty(
  87. void
  88. )
  89. /*++
  90. Implements:
  91. IPersistStream::IsDirty().
  92. --*/
  93. {
  94. HRESULT hr = S_FALSE;
  95. WsbTraceIn(OLESTR("CWsbPersistStream::IsDirty"), OLESTR(""));
  96. if (m_isDirty) {
  97. hr = S_OK;
  98. }
  99. WsbTraceOut(OLESTR("CWsbPersistStream::IsDirty"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  100. return(hr);
  101. }
  102. HRESULT
  103. CWsbPersistStream::SetIsDirty(
  104. IN BOOL isDirty
  105. )
  106. /*++
  107. Implements:
  108. IWsbPersistable::SetIsDirty().
  109. --*/
  110. {
  111. WsbTraceIn(OLESTR("CWsbPersistable::SetIsDirty"), OLESTR("isDirty = <%ls>"), WsbBoolAsString(isDirty));
  112. m_isDirty = isDirty;
  113. WsbTraceOut(OLESTR("CWsbPersistable::SetIsDirty"), OLESTR(""));
  114. return(S_OK);
  115. }
  116. // ******** CWsbPersistable ************
  117. HRESULT
  118. CWsbPersistable::FinalConstruct(
  119. void
  120. )
  121. /*++
  122. Implements:
  123. CComObjectRoot::FinalConstruct().
  124. --*/
  125. {
  126. HRESULT hr = S_OK;
  127. try {
  128. WsbAffirmHr(CWsbPersistStream::FinalConstruct());
  129. // Initialize some member data.
  130. m_persistState = WSB_PERSIST_STATE_UNINIT;
  131. } WsbCatch(hr);
  132. return(hr);
  133. }
  134. void
  135. CWsbPersistable::FinalRelease(
  136. void
  137. )
  138. /*++
  139. Implements:
  140. CComObjectRoot::FinalRelease().
  141. --*/
  142. {
  143. HRESULT hr = S_OK;
  144. CWsbPersistStream::FinalRelease();
  145. }
  146. HRESULT
  147. CWsbPersistable::GetCurFile(
  148. OUT OLECHAR** pFileName
  149. )
  150. /*++
  151. Implements:
  152. IPersistFile::GetCurFile().
  153. --*/
  154. {
  155. HRESULT hr = S_OK;
  156. // Make sure that the string is returned into newly allocated
  157. // memory (or not at all).
  158. *pFileName = NULL;
  159. try {
  160. ULONG Size;
  161. WsbAffirm(m_persistState != WSB_PERSIST_STATE_UNINIT, E_UNEXPECTED);
  162. // Retrieve the actual name if one is specifed or the default name
  163. // if one has not been specified.
  164. WsbAffirmHr(m_persistFileName.GetSize(&Size));
  165. if (Size > 0) {
  166. WsbAffirmHr(WsbAllocAndCopyComString(pFileName, m_persistFileName, 0));
  167. } else {
  168. WsbAffirmHr(GetDefaultFileName(pFileName, 0));
  169. hr = S_FALSE;
  170. }
  171. } WsbCatch(hr);
  172. return(hr);
  173. }
  174. HRESULT
  175. CWsbPersistable::GetDefaultFileName(
  176. OUT OLECHAR** pFileName,
  177. IN ULONG bufferSize
  178. )
  179. /*++
  180. Implements:
  181. IWsbPersistable::GetDefaultFileName().
  182. --*/
  183. {
  184. HRESULT hr = S_OK;
  185. WsbTraceIn(OLESTR("CWsbPersistable::GetDefaultFileName"), OLESTR("bufferSize = <%lu>"), bufferSize);
  186. try {
  187. ULONG Size;
  188. // If we haven't read the default in from the resource file, then
  189. // do so now.
  190. WsbAffirmHr(m_persistDefaultName.GetSize(&Size));
  191. if (Size == 0) {
  192. WsbAffirmHr(m_persistDefaultName.LoadFromRsc(_Module.m_hInst, IDS_WSBPERSISTABLE_DEF_FILE));
  193. }
  194. WsbAffirmHr(WsbAllocAndCopyComString(pFileName, m_persistDefaultName, bufferSize));
  195. } WsbCatch(hr);
  196. WsbTraceOut(OLESTR("CWsbPersistable::GetDefaultFileName"), OLESTR("hr = <%ls>, FileName = <%ls>"), WsbHrAsString(hr), pFileName);
  197. return(hr);
  198. }
  199. HRESULT
  200. CWsbPersistable::Load(
  201. IN LPCOLESTR fileName,
  202. IN DWORD mode
  203. )
  204. /*++
  205. Implements:
  206. IPersistFile::Load().
  207. --*/
  208. {
  209. HRESULT hr = S_OK;
  210. CComPtr<IStream> pStream;
  211. CLSID clsid;
  212. CLSID clsidFile;
  213. CComPtr<IRunningObjectTable> pROT;
  214. CComPtr<IMoniker> pMoniker;
  215. WsbTraceIn(OLESTR("CWsbPersistable::Load"), OLESTR("fileName = <%ls>, mode = <%lx>> m_persistState = <%d>"),
  216. fileName, mode, m_persistState);
  217. try {
  218. CComPtr<IPersistStream> pIPersistStream;
  219. WsbAffirm(m_persistState == WSB_PERSIST_STATE_UNINIT, E_UNEXPECTED);
  220. WsbAffirm(fileName, E_UNEXPECTED);
  221. // Open a storage on the file where the data is stored.
  222. if (0 == mode) {
  223. WsbAffirmHr(StgOpenStorageEx(fileName, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  224. STGFMT_STORAGE, 0, NULL, NULL, IID_IStorage, (void**)&m_persistStorage));
  225. }
  226. else {
  227. WsbAffirmHr(StgOpenStorageEx(fileName, mode,
  228. STGFMT_STORAGE, 0, NULL, NULL, IID_IStorage, (void**)&m_persistStorage));
  229. }
  230. // Get the IPersistStream interface.
  231. WsbAffirmHr(((IUnknown*)(IWsbPersistable*) this)->QueryInterface(IID_IPersistStream, (void**) &pIPersistStream));
  232. // Open a stream.
  233. WsbAffirmHr(m_persistStorage->OpenStream(WSB_PERSIST_DEFAULT_STREAM_NAME, NULL, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  234. 0, &pStream));
  235. // Load the object using the IPersistStream::Load() method, checking
  236. // to make sure the CLSID is correct.
  237. WsbAffirmHr(pIPersistStream->GetClassID(&clsid));
  238. WsbAffirmHr(ReadClassStm(pStream, &clsidFile));
  239. WsbAffirm(clsid == clsidFile, WSB_E_STREAM_ERROR);
  240. WsbAffirmHr(pIPersistStream->Load(pStream));
  241. // Check that we got everything by reading a special ULONG
  242. // that should be at the end
  243. ULONG check_value;
  244. WsbAffirmHr(WsbLoadFromStream(pStream, &check_value));
  245. WsbAffirm(check_value == PERSIST_CHECK_VALUE, WSB_E_PERSISTENCE_FILE_CORRUPT);
  246. // We are now in the normal state.
  247. m_persistFileName = fileName;
  248. m_persistState = WSB_PERSIST_STATE_NORMAL;
  249. m_persistStream = pStream;
  250. } WsbCatchAndDo(hr,
  251. //
  252. // Set the storage pointer to null on an error to make sure the file is closed.
  253. //
  254. m_persistStorage = NULL;
  255. );
  256. WsbTraceOut(OLESTR("CWsbPersistable::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  257. return(hr);
  258. }
  259. HRESULT
  260. CWsbPersistable::ReleaseFile(
  261. void
  262. )
  263. /*++
  264. Implements:
  265. IWsbPersistable::ReleaseFile().
  266. --*/
  267. {
  268. HRESULT hr = S_OK;
  269. WsbTraceIn(OLESTR("CWsbPersistable::ReleaseFile"), OLESTR(""));
  270. try {
  271. WsbAffirm(m_persistState != WSB_PERSIST_STATE_UNINIT, E_UNEXPECTED);
  272. // Try to make sure changes are committed
  273. if (m_persistStream) {
  274. m_persistStream->Commit(STGC_DEFAULT);
  275. }
  276. if (m_persistStorage) {
  277. m_persistStorage->Commit(STGC_DEFAULT);
  278. }
  279. // Release the resources that we have been holding open.
  280. m_persistStream = NULL;
  281. m_persistStorage = NULL;
  282. m_persistFileName.Free();
  283. m_persistState = WSB_PERSIST_STATE_RELEASED;
  284. } WsbCatch(hr);
  285. WsbTraceOut(OLESTR("CWsbPersistable::ReleaseFile"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  286. return(hr);
  287. }
  288. HRESULT CWsbPersistable::Save(
  289. IN LPCOLESTR fileName,
  290. IN BOOL remember
  291. )
  292. /*++
  293. Implements:
  294. IPersistFile::Save().
  295. --*/
  296. {
  297. HRESULT hr = S_OK;
  298. OLECHAR* name;
  299. BOOL create = FALSE;
  300. CComPtr<IStream> pStream;
  301. CLSID clsid;
  302. WsbTraceIn(OLESTR("CWsbPersistable::Save"), OLESTR("fileName = <%ls>, remember = <%ls>"), WsbPtrToStringAsString((OLECHAR**) &fileName), WsbBoolAsString(remember));
  303. try {
  304. CComPtr<IPersistStream> pIPersistStream;
  305. // Make sure that we are in the right state.
  306. WsbAffirm(((m_persistState == WSB_PERSIST_STATE_UNINIT) ||
  307. (m_persistState == WSB_PERSIST_STATE_NORMAL) ||
  308. (m_persistState == WSB_PERSIST_STATE_RELEASED)),
  309. E_UNEXPECTED);
  310. WsbAssert((m_persistState == WSB_PERSIST_STATE_NORMAL) || (0 != fileName), E_POINTER);
  311. // If they supplied a name use it,
  312. if ((m_persistState == WSB_PERSIST_STATE_UNINIT) ||
  313. (m_persistState == WSB_PERSIST_STATE_RELEASED)) {
  314. // We need to create a new file based on the name
  315. // that they gave us.
  316. name = (OLECHAR*) fileName;
  317. create = TRUE;
  318. } else {
  319. // If they gave a name and it is different than what we have
  320. // stored, then we need to create a new file.
  321. if ((0 != fileName) && (_wcsicmp(m_persistFileName, fileName) != 0)) {
  322. name = (OLECHAR*) fileName;
  323. create = TRUE;
  324. }
  325. // Otherwise, use the stored name.
  326. else {
  327. name = m_persistFileName;
  328. }
  329. }
  330. // We should now have a file name and know whether to open or
  331. // create a file.
  332. if (create) {
  333. WsbAffirmHr(StgCreateStorageEx(name, STGM_DIRECT | STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
  334. STGFMT_STORAGE, 0, NULL, NULL, IID_IStorage, (void**)&m_persistStorage));
  335. WsbAffirmHr(m_persistStorage->CreateStream(WSB_PERSIST_DEFAULT_STREAM_NAME, STGM_DIRECT | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
  336. 0, 0, &pStream));
  337. } else {
  338. LARGE_INTEGER llOffset;
  339. pStream = m_persistStream;
  340. llOffset.QuadPart = 0;
  341. WsbAffirmHr(pStream->Seek(llOffset, STREAM_SEEK_SET, NULL));
  342. }
  343. // Get the IPersistStream interface.
  344. WsbAffirmHr(((IUnknown*)(IWsbPersistable*) this)->QueryInterface(IID_IPersistStream, (void**) &pIPersistStream));
  345. // Write out the class id, and then Save the data using IPersistStream method.
  346. WsbAffirmHr(pIPersistStream->GetClassID(&clsid));
  347. WsbAffirmHr(WriteClassStm(pStream, clsid));
  348. WsbAffirmHr(pIPersistStream->Save(pStream, remember));
  349. // Put a special ULONG value at the end as a check during load
  350. ULONG check_value = PERSIST_CHECK_VALUE;
  351. WsbAffirmHr(WsbSaveToStream(pStream, check_value));
  352. //
  353. // Commit the stream right now, as ReleaseFile will not commit it
  354. // if we close the stream
  355. //
  356. WsbAffirmHr(pStream->Commit(STGC_DEFAULT));
  357. // Should we remember the file that was specified as the new
  358. // current file?
  359. if (remember) {
  360. m_persistState = WSB_PERSIST_STATE_NOSCRIBBLE;
  361. // If we created a new file, then remember it's name.
  362. if (create) {
  363. m_persistFileName = fileName;
  364. }
  365. // We need to make sure that we don't have anything open on this
  366. // file.
  367. m_persistStream = NULL;
  368. }
  369. } WsbCatch(hr);
  370. WsbTraceOut(OLESTR("CWsbPersistable::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  371. return(hr);
  372. }
  373. HRESULT
  374. CWsbPersistable::SaveCompleted(
  375. IN LPCOLESTR fileName
  376. )
  377. /*++
  378. Implements:
  379. IPersistFile::SaveCompleted().
  380. --*/
  381. {
  382. HRESULT hr = S_OK;
  383. CComPtr<IStream> pStream;
  384. WsbTraceIn(OLESTR("CWsbPersistable::SaveCompleted"), OLESTR("fileName = <%ls>"), fileName);
  385. try {
  386. // Are we doing any other kind of persistance, are we doing storage
  387. // persistence, but are in the wrong state, or are the parameters
  388. // wrong.
  389. WsbAffirm(m_persistState == WSB_PERSIST_STATE_NOSCRIBBLE, E_UNEXPECTED);
  390. // Save off the name that was given to us, and only another save to
  391. // begin.
  392. if (fileName != NULL) {
  393. m_persistFileName = fileName;
  394. }
  395. // Open a storage to the file where the data is stored.
  396. WsbAffirmHr(StgOpenStorageEx(m_persistFileName, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  397. STGFMT_STORAGE, 0, NULL, NULL, IID_IStorage, (void**)&m_persistStorage));
  398. // Open a stream.
  399. WsbAffirmHr(m_persistStorage->OpenStream(WSB_PERSIST_DEFAULT_STREAM_NAME, NULL, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStream));
  400. // Save it all off.
  401. m_persistState = WSB_PERSIST_STATE_NORMAL;
  402. m_persistStream = pStream;
  403. } WsbCatch(hr);
  404. WsbTraceOut(OLESTR("CWsbPersistable::SaveCompleted"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  405. return(hr);
  406. }
  407. HRESULT
  408. CWsbPersistable::SetDefaultFileName(
  409. IN OLECHAR* fileName
  410. )
  411. /*++
  412. Implements:
  413. IWsbPersistable::SetDefaultFileName().
  414. --*/
  415. {
  416. HRESULT hr = S_OK;
  417. WsbTraceIn(OLESTR("CWsbPersistable::SetDefaultFileName"), OLESTR("fileName = <%ls>"), fileName);
  418. m_persistDefaultName = fileName;
  419. WsbTraceOut(OLESTR("CWsbPersistable::SetDefaultFileName"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  420. return(hr);
  421. }
  422. // Standard Type Helper Functions
  423. HRESULT
  424. WsbLoadFromStream(
  425. IN IStream* pStream,
  426. OUT BOOL* pValue
  427. )
  428. /*++
  429. Routine Description:
  430. Loads a BOOL value from the specified stream and sets
  431. pValue to value of the BOOL.
  432. Arguments:
  433. pStream - The stream from which the value will be read.
  434. pValue - A pointer to a BOOL that will be set to the value.
  435. Return Value:
  436. S_OK - Success
  437. E_POINTER - Either pStream or pValue were NULL.
  438. E_... - Anything returned by IStream::Read.
  439. --*/
  440. {
  441. HRESULT hr = S_OK;
  442. ULONG size;
  443. ULONG ulBytes;
  444. WsbTraceIn(OLESTR("WsbLoadFromStream(BOOL)"), OLESTR(""));
  445. try {
  446. UCHAR bytes[BYTE_SIZE];
  447. WsbAssert(0 != pStream, E_POINTER);
  448. WsbAssert(0 != pValue, E_POINTER);
  449. size = WsbByteSize(*pValue);
  450. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  451. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  452. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  453. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  454. } WsbCatch(hr);
  455. WsbTraceOut(OLESTR("WsbLoadFromStream(BOOL)"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr), WsbPtrToBoolAsString(pValue));
  456. return(hr);
  457. }
  458. HRESULT
  459. WsbLoadFromStream(
  460. IN IStream* pStream,
  461. OUT LONG* pValue
  462. )
  463. /*++
  464. Routine Description:
  465. Loads a LONG value from the specified stream and sets
  466. pValue to the value.
  467. Arguments:
  468. pStream - The stream from which the value will be read.
  469. pValue - A pointer to a LONG that will be set to the value.
  470. Return Value:
  471. S_OK - Success
  472. E_POINTER - Either pStream or pValue were NULL.
  473. E_... - Anything returned by IStream::Read.
  474. --*/
  475. {
  476. HRESULT hr = S_OK;
  477. ULONG size;
  478. ULONG ulBytes;
  479. WsbTraceIn(OLESTR("WsbLoadFromStream(LONG)"), OLESTR(""));
  480. try {
  481. UCHAR bytes[BYTE_SIZE];
  482. WsbAssert(0 != pStream, E_POINTER);
  483. WsbAssert(0 != pValue, E_POINTER);
  484. size = WsbByteSize(*pValue);
  485. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  486. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  487. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  488. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  489. } WsbCatch(hr);
  490. WsbTraceOut(OLESTR("WsbLoadFromStream(LONG)"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr), WsbPtrToLongAsString(pValue));
  491. return(hr);
  492. }
  493. HRESULT
  494. WsbLoadFromStream(
  495. IN IStream* pStream,
  496. OUT GUID* pValue
  497. )
  498. /*++
  499. Routine Description:
  500. Loads a GUID value from the specified stream and sets
  501. pValue to the value.
  502. Arguments:
  503. pStream - The stream from which the value will be read.
  504. pValue - A pointer to a GUID that will be set to the value.
  505. Return Value:
  506. S_OK - Success
  507. E_POINTER - Either pStream or pValue were NULL.
  508. E_... - Anything returned by IStream::Read.
  509. --*/
  510. {
  511. HRESULT hr = S_OK;
  512. ULONG size;
  513. ULONG ulBytes;
  514. WsbTraceIn(OLESTR("WsbLoadFromStream(GUID)"), OLESTR(""));
  515. try {
  516. UCHAR bytes[BYTE_SIZE];
  517. WsbAssert(0 != pStream, E_POINTER);
  518. WsbAssert(0 != pValue, E_POINTER);
  519. size = WsbByteSize(*pValue);
  520. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  521. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  522. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  523. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  524. } WsbCatch(hr);
  525. WsbTraceOut(OLESTR("WsbLoadFromStream(GUID)"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr), WsbPtrToGuidAsString(pValue));
  526. return(hr);
  527. }
  528. HRESULT
  529. WsbLoadFromStream(
  530. IN IStream* pStream,
  531. OUT SHORT* pValue
  532. )
  533. /*++
  534. Routine Description:
  535. Loads a SHORT value from the specified stream and sets
  536. pValue to the value.
  537. Arguments:
  538. pStream - The stream from which the value will be read.
  539. pValue - A pointer to a SHORT that will be set to the value.
  540. Return Value:
  541. S_OK - Success
  542. E_POINTER - Either pStream or pValue were NULL.
  543. E_... - Anything returned by IStream::Read.
  544. --*/
  545. {
  546. HRESULT hr = S_OK;
  547. ULONG size;
  548. ULONG ulBytes;
  549. WsbTraceIn(OLESTR("WsbLoadFromStream(SHORT)"), OLESTR(""));
  550. try {
  551. UCHAR bytes[BYTE_SIZE];
  552. WsbAssert(0 != pStream, E_POINTER);
  553. WsbAssert(0 != pValue, E_POINTER);
  554. size = WsbByteSize(*pValue);
  555. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  556. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  557. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  558. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  559. } WsbCatch(hr);
  560. WsbTraceOut(OLESTR("WsbLoadFromStream(SHORT)"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pValue));
  561. return(hr);
  562. }
  563. HRESULT
  564. WsbLoadFromStream(
  565. IN IStream* pStream,
  566. OUT BYTE* pValue
  567. )
  568. /*++
  569. Routine Description:
  570. Loads a BYTE value from the specified stream and sets
  571. pValue to the value.
  572. Arguments:
  573. pStream - The stream from which the value will be read.
  574. pValue - A pointer to a BYTE that will be set to the value.
  575. Return Value:
  576. S_OK - Success
  577. E_POINTER - Either pStream or pValue were NULL.
  578. E_... - Anything returned by IStream::Read.
  579. --*/
  580. {
  581. HRESULT hr = S_OK;
  582. ULONG size;
  583. ULONG ulBytes;
  584. WsbTraceIn(OLESTR("WsbLoadFromStream(BYTE)"), OLESTR(""));
  585. try {
  586. WsbAssert(0 != pStream, E_POINTER);
  587. WsbAssert(0 != pValue, E_POINTER);
  588. size = WsbByteSize(*pValue);
  589. WsbAffirmHr(pStream->Read((void*) pValue, size, &ulBytes));
  590. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  591. } WsbCatch(hr);
  592. WsbTraceOut(OLESTR("WsbLoadFromStream(BYTE)"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr), WsbPtrToByteAsString(pValue));
  593. return(hr);
  594. }
  595. HRESULT
  596. WsbLoadFromStream(
  597. IN IStream* pStream,
  598. OUT UCHAR* pValue,
  599. IN ULONG bufferSize
  600. )
  601. /*++
  602. Routine Description:
  603. Loads a UCHAR array value from the specified stream and sets
  604. pValue to the value.
  605. Arguments:
  606. pStream - The stream from which the value will be read.
  607. pValue - A pointer to a BYTE that will be set to the value.
  608. bufferSize - number of bytes to load
  609. Return Value:
  610. S_OK - Success
  611. E_POINTER - Either pStream or pValue were NULL.
  612. E_... - Anything returned by IStream::Read.
  613. --*/
  614. {
  615. HRESULT hr = S_OK;
  616. ULONG size;
  617. ULONG ulBytes;
  618. WsbTraceIn(OLESTR("WsbLoadFromStream(UCHAR)"), OLESTR(""));
  619. try {
  620. WsbAssert(0 != pStream, E_POINTER);
  621. WsbAssert(0 != pValue, E_POINTER);
  622. size = bufferSize;
  623. WsbAffirmHr(pStream->Read((void*) pValue, size, &ulBytes));
  624. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  625. } WsbCatch(hr);
  626. WsbTraceOut(OLESTR("WsbLoadFromStream(UCHAR)"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr));
  627. return(hr);
  628. }
  629. HRESULT
  630. WsbLoadFromStream(
  631. IN IStream* pStream,
  632. OUT OLECHAR** pValue,
  633. IN ULONG ulBufferSize
  634. )
  635. /*++
  636. Routine Description:
  637. Loads a STRING value from the specified stream and sets
  638. pValue to the string.
  639. Arguments:
  640. pStream - The stream from which the string will be read.
  641. pValue - A pointer to a STRING that will be set to the string
  642. read in..
  643. ulBufferSize - Size of buffer pValue points to or zero allow
  644. alloc/realloc of the buffer.
  645. Return Value:
  646. S_OK - Success
  647. E_POINTER - Either pStream or pValue were NULL.
  648. E_... - Anything returned by IStream::Read.
  649. --*/
  650. {
  651. HRESULT hr = S_OK;
  652. WsbTraceIn(OLESTR("WsbLoadFromStream(STRING)"), OLESTR(""));
  653. try {
  654. ULONG nchar;
  655. OLECHAR *pc;
  656. ULONG size;
  657. USHORT wc;
  658. WsbAssert(0 != pStream, E_POINTER);
  659. WsbAssert(0 != pValue, E_POINTER);
  660. WsbAssert(sizeof(OLECHAR) == sizeof(USHORT), E_UNEXPECTED);
  661. // Get the length of the string (in bytes).
  662. WsbAffirmHr(WsbLoadFromStream(pStream, &size));
  663. if (size != 0) {
  664. // Allocate a buffer to hold the string.
  665. WsbAffirmHr(WsbGetComBuffer(pValue, ulBufferSize, size, NULL));
  666. pc = *pValue;
  667. // Now read in the proper number of wide chars.
  668. nchar = size / sizeof(USHORT);
  669. for (ULONG i = 0; i < nchar; i++) {
  670. WsbAffirmHr(WsbLoadFromStream(pStream, &wc));
  671. *pc++ = wc;
  672. }
  673. } else {
  674. // Allocate a buffer to hold the string.
  675. WsbAffirmHr(WsbGetComBuffer(pValue, ulBufferSize, sizeof(OLECHAR), NULL));
  676. *(*pValue) = 0;
  677. }
  678. } WsbCatch(hr);
  679. WsbTraceOut(OLESTR("WsbLoadFromStream(STRING)"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr), WsbPtrToStringAsString(pValue));
  680. return(hr);
  681. }
  682. HRESULT
  683. WsbLoadFromStream(
  684. IN IStream* pStream,
  685. OUT ULONG* pValue
  686. )
  687. /*++
  688. Routine Description:
  689. Loads a ULONG value from the specified stream and sets
  690. pValue to the value.
  691. Arguments:
  692. pStream - The stream from which the value will be read.
  693. pValue - A pointer to a ULONG that will be set to the value.
  694. Return Value:
  695. S_OK - Success
  696. E_POINTER - Either pStream or pValue were NULL.
  697. E_... - Anything returned by IStream::Read.
  698. --*/
  699. {
  700. HRESULT hr = S_OK;
  701. ULONG size;
  702. ULONG ulBytes;
  703. WsbTraceIn(OLESTR("WsbLoadFromStream(ULONG)"), OLESTR(""));
  704. try {
  705. UCHAR bytes[BYTE_SIZE];
  706. WsbAssert(0 != pStream, E_POINTER);
  707. WsbAssert(0 != pValue, E_POINTER);
  708. size = WsbByteSize(*pValue);
  709. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  710. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  711. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  712. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  713. } WsbCatch(hr);
  714. WsbTraceOut(OLESTR("WsbLoadFromStream(ULONG)"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr), WsbPtrToUlongAsString(pValue));
  715. return(hr);
  716. }
  717. HRESULT
  718. WsbLoadFromStream(
  719. IN IStream* pStream,
  720. OUT USHORT* pValue
  721. )
  722. /*++
  723. Routine Description:
  724. Loads a USHORT value from the specified stream and sets
  725. pValue to the value.
  726. Arguments:
  727. pStream - The stream from which the value will be read.
  728. pValue - A pointer to a USHORT that will be set to the value.
  729. Return Value:
  730. S_OK - Success
  731. E_POINTER - Either pStream or pValue were NULL.
  732. E_... - Anything returned by IStream::Read.
  733. --*/
  734. {
  735. HRESULT hr = S_OK;
  736. ULONG size;
  737. ULONG ulBytes;
  738. WsbTraceIn(OLESTR("WsbLoadFromStream(USHORT)"), OLESTR(""));
  739. try {
  740. UCHAR bytes[BYTE_SIZE];
  741. WsbAssert(0 != pStream, E_POINTER);
  742. WsbAssert(0 != pValue, E_POINTER);
  743. size = WsbByteSize(*pValue);
  744. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  745. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  746. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  747. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  748. } WsbCatch(hr);
  749. WsbTraceOut(OLESTR("WsbLoadFromStream(USHORT)"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr), WsbPtrToUshortAsString(pValue));
  750. return(hr);
  751. }
  752. HRESULT
  753. WsbLoadFromStream(
  754. IN IStream* pStream,
  755. OUT LONGLONG* pValue
  756. )
  757. /*++
  758. Routine Description:
  759. Loads a LONGLONG value from the specified stream and sets
  760. pValue to the value.
  761. Arguments:
  762. pStream - The stream from which the value will be read.
  763. pValue - A pointer to a LONGLONG that will be set to the value.
  764. Return Value:
  765. S_OK - Success
  766. E_POINTER - Either pStream or pValue were NULL.
  767. E_... - Anything returned by IStream::Read.
  768. --*/
  769. {
  770. HRESULT hr = S_OK;
  771. ULONG size;
  772. ULONG ulBytes;
  773. WsbTraceIn(OLESTR("WsbLoadFromStream(LONGLONG)"), OLESTR(""));
  774. try {
  775. UCHAR bytes[BYTE_SIZE];
  776. WsbAssert(0 != pStream, E_POINTER);
  777. WsbAssert(0 != pValue, E_POINTER);
  778. size = WsbByteSize(*pValue);
  779. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  780. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  781. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  782. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  783. } WsbCatch(hr);
  784. WsbTraceOut(OLESTR("WsbLoadFromStream(LONGLONG)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  785. return(hr);
  786. }
  787. HRESULT
  788. WsbLoadFromStream(
  789. IN IStream* pStream,
  790. OUT ULONGLONG* pValue
  791. )
  792. /*++
  793. Routine Description:
  794. Loads a ULONGLONG value from the specified stream and sets
  795. pValue to the value.
  796. Arguments:
  797. pStream - The stream from which the value will be read.
  798. pValue - A pointer to a ULONGLONG that will be set to the value.
  799. Return Value:
  800. S_OK - Success
  801. E_POINTER - Either pStream or pValue were NULL.
  802. E_... - Anything returned by IStream::Read.
  803. --*/
  804. {
  805. HRESULT hr = S_OK;
  806. ULONG size;
  807. ULONG ulBytes;
  808. WsbTraceIn(OLESTR("WsbLoadFromStream(ULONGLONG)"), OLESTR(""));
  809. try {
  810. UCHAR bytes[BYTE_SIZE];
  811. WsbAssert(0 != pStream, E_POINTER);
  812. WsbAssert(0 != pValue, E_POINTER);
  813. size = WsbByteSize(*pValue);
  814. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  815. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  816. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  817. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  818. } WsbCatch(hr);
  819. WsbTraceOut(OLESTR("WsbLoadFromStream(ULONGLONG)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  820. return(hr);
  821. }
  822. HRESULT
  823. WsbLoadFromStream(
  824. IN IStream* pStream,
  825. OUT DATE* pValue
  826. )
  827. /*++
  828. Routine Description:
  829. Loads a DATE value from the specified stream and sets
  830. pValue to the value.
  831. Arguments:
  832. pStream - The stream from which the value will be read.
  833. pValue - A pointer to a DATE that will be set to the value.
  834. Return Value:
  835. S_OK - Success
  836. E_POINTER - Either pStream or pValue were NULL.
  837. E_... - Anything returned by IStream::Read.
  838. --*/
  839. {
  840. HRESULT hr = S_OK;
  841. ULONG size;
  842. ULONG ulBytes;
  843. WsbTraceIn(OLESTR("WsbLoadFromStream(DATE)"), OLESTR(""));
  844. try {
  845. UCHAR bytes[BYTE_SIZE];
  846. WsbAssert(0 != pStream, E_POINTER);
  847. WsbAssert(0 != pValue, E_POINTER);
  848. size = WsbByteSize(*pValue);
  849. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  850. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  851. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  852. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  853. } WsbCatch(hr);
  854. // WsbTraceOut(OLESTR("WsbLoadFromStream(DATE)"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr), WsbPtrToLongAsString(pValue));
  855. // Modify next statement after WsbDate functions written to be like the one above.
  856. WsbTraceOut(OLESTR("WsbLoadFromStream(DATE)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  857. return(hr);
  858. }
  859. HRESULT
  860. WsbLoadFromStream(
  861. IN IStream* pStream,
  862. OUT FILETIME* pValue
  863. )
  864. /*++
  865. Routine Description:
  866. Loads a FILETIME value from the specified stream and sets
  867. pValue to the value.
  868. Arguments:
  869. pStream - The stream from which the value will be read.
  870. pValue - A pointer to a FILETIME that will be set to the value.
  871. Return Value:
  872. S_OK - Success
  873. E_POINTER - Either pStream or pValue were NULL.
  874. E_... - Anything returned by IStream::Read.
  875. --*/
  876. {
  877. HRESULT hr = S_OK;
  878. ULONG size;
  879. ULONG ulBytes;
  880. WsbTraceIn(OLESTR("WsbLoadFromStream(FILETIME)"), OLESTR(""));
  881. try {
  882. UCHAR bytes[BYTE_SIZE];
  883. WsbAssert(0 != pStream, E_POINTER);
  884. WsbAssert(0 != pValue, E_POINTER);
  885. size = WsbByteSize(*pValue);
  886. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  887. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  888. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  889. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  890. } WsbCatch(hr);
  891. WsbTraceOut(OLESTR("WsbLoadFromStream(FILETIME)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  892. return(hr);
  893. }
  894. HRESULT
  895. WsbLoadFromStream(
  896. IN IStream* pStream,
  897. OUT ULARGE_INTEGER* pValue
  898. )
  899. /*++
  900. Routine Description:
  901. Loads a ULARGE_INTEGER value from the specified stream and sets
  902. pValue to the value.
  903. Arguments:
  904. pStream - The stream from which the value will be read.
  905. pValue - A pointer to a ULARGE_INTEGER that will be set to the value.
  906. Return Value:
  907. S_OK - Success
  908. E_POINTER - Either pStream or pValue were NULL.
  909. E_... - Anything returned by IStream::Read.
  910. --*/
  911. {
  912. HRESULT hr = S_OK;
  913. ULONG size;
  914. ULONG ulBytes;
  915. WsbTraceIn(OLESTR("WsbLoadFromStream(ULARGE_INTEGER)"), OLESTR(""));
  916. try {
  917. UCHAR bytes[BYTE_SIZE];
  918. WsbAssert(0 != pStream, E_POINTER);
  919. WsbAssert(0 != pValue, E_POINTER);
  920. size = WsbByteSize(*pValue);
  921. WsbAffirmHr(pStream->Read((void*) bytes, size, &ulBytes));
  922. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  923. WsbAffirmHr(WsbConvertFromBytes(bytes, pValue, &size));
  924. WsbAffirm(size == ulBytes, WSB_E_STREAM_ERROR);
  925. } WsbCatch(hr);
  926. WsbTraceOut(OLESTR("WsbLoadFromStream(ULARGE_INTEGER)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  927. return(hr);
  928. }
  929. HRESULT
  930. WsbSaveToStream(
  931. IN IStream* pStream,
  932. IN BOOL value
  933. )
  934. /*++
  935. Routine Description:
  936. Saves a BOOL value to the specified stream.
  937. Arguments:
  938. pStream - The stream to which the value will be written.
  939. value - The value of the BOOL to be written.
  940. Return Value:
  941. S_OK - Success
  942. E_POINTER - Either pStream was NULL.
  943. E_... - Anything returned by IStream::Write.
  944. --*/
  945. {
  946. HRESULT hr = S_OK;
  947. ULONG size;
  948. ULONG ulBytes;
  949. WsbTraceIn(OLESTR("WsbSaveToStream(BOOL)"), OLESTR("value = <%ls>"), WsbBoolAsString(value));
  950. try {
  951. UCHAR bytes[BYTE_SIZE];
  952. WsbAssert(0 != pStream, E_POINTER);
  953. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  954. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  955. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  956. } WsbCatch(hr);
  957. WsbTraceOut(OLESTR("WsbSaveToStream(BOOL)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  958. return(hr);
  959. }
  960. HRESULT
  961. WsbSaveToStream(
  962. IN IStream* pStream,
  963. IN GUID value
  964. )
  965. /*++
  966. Routine Description:
  967. Saves a GUID value to the specified stream.
  968. Arguments:
  969. pStream - The stream to which the value will be written.
  970. value - The value of the GUID to be written.
  971. Return Value:
  972. S_OK - Success
  973. E_POINTER - Either pStream was NULL.
  974. E_... - Anything returned by IStream::Write.
  975. --*/
  976. {
  977. HRESULT hr = S_OK;
  978. ULONG size;
  979. ULONG ulBytes;
  980. WsbTraceIn(OLESTR("WsbSaveToStream(GUID)"), OLESTR("value = <%ls>"), WsbGuidAsString(value));
  981. try {
  982. UCHAR bytes[BYTE_SIZE];
  983. WsbAssert(0 != pStream, E_POINTER);
  984. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  985. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  986. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  987. } WsbCatch(hr);
  988. WsbTraceOut(OLESTR("WsbSaveToStream(GUID)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  989. return(hr);
  990. }
  991. HRESULT
  992. WsbSaveToStream(
  993. IStream* pStream,
  994. LONG value
  995. )
  996. /*++
  997. Routine Description:
  998. Saves a LONG value to the specified stream.
  999. Arguments:
  1000. pStream - The stream to which the value will be written.
  1001. value - The value of the LONG to be written.
  1002. Return Value:
  1003. S_OK - Success
  1004. E_POINTER - Either pStream was NULL.
  1005. E_... - Anything returned by IStream::Write.
  1006. --*/
  1007. {
  1008. HRESULT hr = S_OK;
  1009. ULONG size;
  1010. ULONG ulBytes;
  1011. WsbTraceIn(OLESTR("WsbSaveToStream(LONG)"), OLESTR("value = <%ld>"), value);
  1012. try {
  1013. UCHAR bytes[BYTE_SIZE];
  1014. WsbAssert(0 != pStream, E_POINTER);
  1015. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  1016. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  1017. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1018. } WsbCatch(hr);
  1019. WsbTraceOut(OLESTR("WsbSaveToStream(LONG)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1020. return(hr);
  1021. }
  1022. HRESULT
  1023. WsbSaveToStream(
  1024. IStream* pStream,
  1025. SHORT value
  1026. )
  1027. /*++
  1028. Routine Description:
  1029. Saves a SHORT value to the specified stream.
  1030. Arguments:
  1031. pStream - The stream to which the value will be written.
  1032. value - The value of the SHORT to be written.
  1033. Return Value:
  1034. S_OK - Success
  1035. E_POINTER - Either pStream was NULL.
  1036. E_... - Anything returned by IStream::Write.
  1037. --*/
  1038. {
  1039. HRESULT hr = S_OK;
  1040. ULONG size;
  1041. ULONG ulBytes;
  1042. WsbTraceIn(OLESTR("WsbSaveToStream(SHORT)"), OLESTR("value = <%ld>"), value);
  1043. try {
  1044. UCHAR bytes[BYTE_SIZE];
  1045. WsbAssert(0 != pStream, E_POINTER);
  1046. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  1047. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  1048. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1049. } WsbCatch(hr);
  1050. WsbTraceOut(OLESTR("WsbSaveToStream(SHORT)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1051. return(hr);
  1052. }
  1053. HRESULT
  1054. WsbSaveToStream(
  1055. IStream* pStream,
  1056. BYTE value
  1057. )
  1058. /*++
  1059. Routine Description:
  1060. Saves a BYTE value to the specified stream.
  1061. Arguments:
  1062. pStream - The stream to which the value will be written.
  1063. value - The value of the BYTE to be written.
  1064. Return Value:
  1065. S_OK - Success
  1066. E_POINTER - Either pStream was NULL.
  1067. E_... - Anything returned by IStream::Write.
  1068. --*/
  1069. {
  1070. HRESULT hr = S_OK;
  1071. ULONG size;
  1072. ULONG ulBytes;
  1073. WsbTraceIn(OLESTR("WsbSaveToStream(BYTE)"), OLESTR("value = <%ld>"), value);
  1074. try {
  1075. WsbAssert(0 != pStream, E_POINTER);
  1076. size = WsbByteSize(value);
  1077. WsbAffirmHr(pStream->Write((void*) &value, size, &ulBytes));
  1078. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1079. } WsbCatch(hr);
  1080. WsbTraceOut(OLESTR("WsbSaveToStream(BYTE)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1081. return(hr);
  1082. }
  1083. HRESULT
  1084. WsbSaveToStream(
  1085. IStream* pStream,
  1086. UCHAR* value,
  1087. ULONG bufferSize
  1088. )
  1089. /*++
  1090. Routine Description:
  1091. Saves a UCHAR array to the specified stream.
  1092. Arguments:
  1093. pStream - The stream to which the value will be written.
  1094. value - The pointer to value of the UCHAR array to be written.
  1095. bufferSize - Size of array to save (in bytes).
  1096. Return Value:
  1097. S_OK - Success
  1098. E_POINTER - Either pStream was NULL.
  1099. E_... - Anything returned by IStream::Write.
  1100. --*/
  1101. {
  1102. HRESULT hr = S_OK;
  1103. ULONG size;
  1104. ULONG ulBytes;
  1105. WsbTraceIn(OLESTR("WsbSaveToStream(UCHAR)"), OLESTR("value = <%ld>"), value);
  1106. try {
  1107. WsbAssert(0 != pStream, E_POINTER);
  1108. // WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  1109. size = bufferSize;
  1110. WsbAffirmHr(pStream->Write((void*) value, size, &ulBytes));
  1111. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1112. } WsbCatch(hr);
  1113. WsbTraceOut(OLESTR("WsbSaveToStream(UCHAR)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1114. return(hr);
  1115. }
  1116. HRESULT
  1117. WsbSaveToStream(
  1118. IN IStream* pStream,
  1119. IN OLECHAR* value
  1120. )
  1121. /*++
  1122. Routine Description:
  1123. Saves a OLECHAR string to the specified stream.
  1124. Arguments:
  1125. pStream - The stream to which the string will be written.
  1126. value - The string to be written.
  1127. Return Value:
  1128. S_OK - Success
  1129. E_POINTER - Either pStream or value was NULL.
  1130. E_... - Anything returned by IStream::Write.
  1131. --*/
  1132. {
  1133. HRESULT hr = S_OK;
  1134. WsbTraceIn(OLESTR("WsbSaveToStream(STRING)"), OLESTR("value = <%ls>"), WsbPtrToStringAsString(&value));
  1135. try {
  1136. ULONG nchar;
  1137. OLECHAR *pc;
  1138. ULONG size;
  1139. USHORT wc;
  1140. WsbAssert(0 != pStream, E_POINTER);
  1141. // WsbAssert(0 != value, E_POINTER);
  1142. WsbAssert(sizeof(OLECHAR) == sizeof(USHORT), E_UNEXPECTED);
  1143. // Save the length of the string (in bytes).
  1144. if (value) {
  1145. nchar = wcslen(value) + 1;
  1146. } else {
  1147. nchar = 0;
  1148. }
  1149. size = nchar * sizeof(USHORT);
  1150. WsbAffirmHr(WsbSaveToStream(pStream, size));
  1151. // Now write out the proper number of wide chars
  1152. pc = value;
  1153. for (ULONG i = 0; i < nchar; i++) {
  1154. wc = *pc++;
  1155. WsbAffirmHr(WsbSaveToStream(pStream, wc));
  1156. }
  1157. } WsbCatch(hr);
  1158. WsbTraceOut(OLESTR("WsbSaveToStream(STRING)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1159. return(hr);
  1160. }
  1161. HRESULT
  1162. WsbSaveToStream(
  1163. IStream* pStream,
  1164. ULONG value
  1165. )
  1166. /*++
  1167. Routine Description:
  1168. Saves a ULONG value to the specified stream.
  1169. Arguments:
  1170. pStream - The stream to which the value will be written.
  1171. value - The value of the ULONG to be written.
  1172. Return Value:
  1173. S_OK - Success
  1174. E_POINTER - Either pStream was NULL.
  1175. E_... - Anything returned by IStream::Write.
  1176. --*/
  1177. {
  1178. HRESULT hr = S_OK;
  1179. ULONG size;
  1180. ULONG ulBytes;
  1181. WsbTraceIn(OLESTR("WsbSaveToStream(ULONG)"), OLESTR("value = <%ld>"), value);
  1182. try {
  1183. UCHAR bytes[BYTE_SIZE];
  1184. WsbAssert(0 != pStream, E_POINTER);
  1185. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  1186. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  1187. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1188. } WsbCatch(hr);
  1189. WsbTraceOut(OLESTR("WsbSaveToStream(ULONG)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1190. return(hr);
  1191. }
  1192. HRESULT
  1193. WsbSaveToStream(
  1194. IStream* pStream,
  1195. USHORT value
  1196. )
  1197. /*++
  1198. Routine Description:
  1199. Saves a USHORT value to the specified stream.
  1200. Arguments:
  1201. pStream - The stream to which the value will be written.
  1202. value - The value of the USHORT to be written.
  1203. Return Value:
  1204. S_OK - Success
  1205. E_POINTER - Either pStream was NULL.
  1206. E_... - Anything returned by IStream::Write.
  1207. --*/
  1208. {
  1209. HRESULT hr = S_OK;
  1210. ULONG size;
  1211. ULONG ulBytes;
  1212. WsbTraceIn(OLESTR("WsbSaveToStream(USHORT)"), OLESTR("value = <%ld>"), value);
  1213. try {
  1214. UCHAR bytes[BYTE_SIZE];
  1215. WsbAssert(0 != pStream, E_POINTER);
  1216. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  1217. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  1218. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1219. } WsbCatch(hr);
  1220. WsbTraceOut(OLESTR("WsbSaveToStream(USHORT)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1221. return(hr);
  1222. }
  1223. HRESULT
  1224. WsbSaveToStream(
  1225. IStream* pStream,
  1226. LONGLONG value
  1227. )
  1228. /*++
  1229. Routine Description:
  1230. Saves a LONGLONG value to the specified stream.
  1231. Arguments:
  1232. pStream - The stream to which the value will be written.
  1233. value - The value of the LONGLONG to be written.
  1234. Return Value:
  1235. S_OK - Success
  1236. E_POINTER - pStream was NULL.
  1237. E_... - Anything returned by IStream::Write.
  1238. --*/
  1239. {
  1240. HRESULT hr = S_OK;
  1241. ULONG size;
  1242. ULONG ulBytes;
  1243. WsbTraceIn(OLESTR("WsbSaveToStream(LONGLONG)"), OLESTR("value = <%l64x>"), value);
  1244. try {
  1245. UCHAR bytes[BYTE_SIZE];
  1246. WsbAssert(0 != pStream, E_POINTER);
  1247. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  1248. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  1249. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1250. } WsbCatch(hr);
  1251. WsbTraceOut(OLESTR("WsbSaveToStream(LONGLONG)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1252. return(hr);
  1253. }
  1254. HRESULT
  1255. WsbSaveToStream(
  1256. IStream* pStream,
  1257. ULONGLONG value
  1258. )
  1259. /*++
  1260. Routine Description:
  1261. Saves a ULONGLONG value to the specified stream.
  1262. Arguments:
  1263. pStream - The stream to which the value will be written.
  1264. value - The value of the ULONGLONG to be written.
  1265. Return Value:
  1266. S_OK - Success
  1267. E_POINTER - pStream was NULL.
  1268. E_... - Anything returned by IStream::Write.
  1269. --*/
  1270. {
  1271. HRESULT hr = S_OK;
  1272. ULONG size;
  1273. ULONG ulBytes;
  1274. WsbTraceIn(OLESTR("WsbSaveToStream(ULONGLONG)"), OLESTR("value = <%l64x>"), value);
  1275. try {
  1276. UCHAR bytes[BYTE_SIZE];
  1277. WsbAssert(0 != pStream, E_POINTER);
  1278. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  1279. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  1280. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1281. } WsbCatch(hr);
  1282. WsbTraceOut(OLESTR("WsbSaveToStream(ULONGLONG)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1283. return(hr);
  1284. }
  1285. HRESULT
  1286. WsbSaveToStream(
  1287. IStream* pStream,
  1288. DATE value
  1289. )
  1290. /*++
  1291. Routine Description:
  1292. Saves a DATE value to the specified stream.
  1293. Arguments:
  1294. pStream - The stream to which the value will be written.
  1295. value - The value of the DATE to be written.
  1296. Return Value:
  1297. S_OK - Success
  1298. E_POINTER - Either pStream was NULL.
  1299. E_... - Anything returned by IStream::Write.
  1300. --*/
  1301. {
  1302. HRESULT hr = S_OK;
  1303. ULONG size;
  1304. ULONG ulBytes;
  1305. // Modify next statement to return date after WsbDate functions written.
  1306. WsbTraceIn(OLESTR("WsbSaveToStream(DATE)"), OLESTR("value = <%f>"), value);
  1307. try {
  1308. UCHAR bytes[BYTE_SIZE];
  1309. WsbAssert(0 != pStream, E_POINTER);
  1310. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  1311. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  1312. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1313. } WsbCatch(hr);
  1314. WsbTraceOut(OLESTR("WsbSaveToStream(DATE)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1315. return(hr);
  1316. }
  1317. HRESULT
  1318. WsbSaveToStream(
  1319. IStream* pStream,
  1320. FILETIME value
  1321. )
  1322. /*++
  1323. Routine Description:
  1324. Saves a FILETIME value to the specified stream.
  1325. Arguments:
  1326. pStream - The stream to which the value will be written.
  1327. value - The value of the FILETIME to be written.
  1328. Return Value:
  1329. S_OK - Success
  1330. E_POINTER - pStream was NULL.
  1331. E_... - Anything returned by IStream::Write.
  1332. --*/
  1333. {
  1334. HRESULT hr = S_OK;
  1335. ULONG size;
  1336. ULONG ulBytes;
  1337. WsbTraceIn(OLESTR("WsbSaveToStream(FILETIME)"), OLESTR(""));
  1338. try {
  1339. UCHAR bytes[BYTE_SIZE];
  1340. WsbAssert(0 != pStream, E_POINTER);
  1341. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  1342. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  1343. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1344. } WsbCatch(hr);
  1345. WsbTraceOut(OLESTR("WsbSaveToStream(FILETIME)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1346. return(hr);
  1347. }
  1348. HRESULT
  1349. WsbBstrFromStream(
  1350. IN IStream* pStream,
  1351. OUT BSTR* pValue
  1352. )
  1353. /*++
  1354. Routine Description:
  1355. Loads a BSTR value from the specified stream.
  1356. Arguments:
  1357. pStream - The stream from which the BSTR will be read.
  1358. pValue - A pointer to a BSTR. If *pValue is NULL, this
  1359. function will allocate the BSTR; if it already
  1360. points to a BSTR that is too short, the BSTR
  1361. will be reallocated.
  1362. Return Value:
  1363. S_OK - Success
  1364. E_POINTER - Either pStream or pValue were NULL.
  1365. E_... - Anything returned by IStream::Read.
  1366. --*/
  1367. {
  1368. HRESULT hr = S_OK;
  1369. WsbTraceIn(OLESTR("WsbBstrFromStream"), OLESTR(""));
  1370. try {
  1371. ULONG bchar;
  1372. ULONG nchar;
  1373. OLECHAR *pc;
  1374. ULONG size;
  1375. USHORT wc;
  1376. WsbAssert(0 != pStream, E_POINTER);
  1377. WsbAssert(0 != pValue, E_POINTER);
  1378. WsbAssert(sizeof(OLECHAR) == sizeof(USHORT), E_UNEXPECTED);
  1379. // Get the length of the string (in bytes).
  1380. WsbAffirmHr(WsbLoadFromStream(pStream, &size));
  1381. // (Re)allocate a buffer to hold the string.
  1382. nchar = size / sizeof(USHORT);
  1383. bchar = nchar - 1;
  1384. if (*pValue) {
  1385. if (bchar != SysStringLen(*pValue)) {
  1386. WsbAffirm(WsbReallocStringLen(pValue, NULL, bchar),
  1387. WSB_E_RESOURCE_UNAVAILABLE);
  1388. }
  1389. } else {
  1390. *pValue = WsbAllocStringLen(NULL, bchar);
  1391. WsbAffirm(*pValue, WSB_E_RESOURCE_UNAVAILABLE);
  1392. }
  1393. // Now read in the proper number of wide chars.
  1394. pc = *pValue;
  1395. for (ULONG i = 0; i < nchar; i++) {
  1396. WsbAffirmHr(WsbLoadFromStream(pStream, &wc));
  1397. *pc++ = wc;
  1398. }
  1399. } WsbCatch(hr);
  1400. WsbTraceOut(OLESTR("WsbBstrFromStream"), OLESTR("hr = <%ls>, value = <%ls>"), WsbHrAsString(hr), WsbPtrToStringAsString(pValue));
  1401. return(hr);
  1402. }
  1403. HRESULT
  1404. WsbBstrToStream(
  1405. IN IStream* pStream,
  1406. IN BSTR value
  1407. )
  1408. /*++
  1409. Routine Description:
  1410. Saves a BSTR to the specified stream.
  1411. Arguments:
  1412. pStream - The stream to which the BSTR will be written.
  1413. value - The BSTR to be written.
  1414. Return Value:
  1415. S_OK - Success
  1416. E_POINTER - pStream was NULL.
  1417. E_... - Anything returned by IStream::Write.
  1418. --*/
  1419. {
  1420. HRESULT hr = S_OK;
  1421. WsbTraceIn(OLESTR("WsbBstrToStream"), OLESTR("value = <%ls>"), WsbPtrToStringAsString(&value));
  1422. try {
  1423. ULONG nchar;
  1424. OLECHAR *pc;
  1425. ULONG size;
  1426. USHORT wc;
  1427. WsbAssert(0 != pStream, E_POINTER);
  1428. WsbAssert(0 != value, E_POINTER);
  1429. WsbAssert(sizeof(OLECHAR) == sizeof(USHORT), E_UNEXPECTED);
  1430. // Save the length of the string (in bytes).
  1431. nchar = SysStringLen(value) + 1;
  1432. size = nchar * sizeof(USHORT);
  1433. WsbAffirmHr(WsbSaveToStream(pStream, size));
  1434. // Now write out the proper number of wide chars
  1435. pc = value;
  1436. for (ULONG i = 0; i < nchar; i++) {
  1437. wc = *pc++;
  1438. WsbAffirmHr(WsbSaveToStream(pStream, wc));
  1439. }
  1440. } WsbCatch(hr);
  1441. WsbTraceOut(OLESTR("WsbBstrToStream"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1442. return(hr);
  1443. }
  1444. HRESULT
  1445. WsbSaveToStream(
  1446. IStream* pStream,
  1447. ULARGE_INTEGER value
  1448. )
  1449. /*++
  1450. Routine Description:
  1451. Saves a ULARGE_INTEGER value to the specified stream.
  1452. Arguments:
  1453. pStream - The stream to which the value will be written.
  1454. value - The value of the ULARGE_INTEER to be written.
  1455. Return Value:
  1456. S_OK - Success
  1457. E_POINTER - pStream was NULL.
  1458. E_... - Anything returned by IStream::Write.
  1459. --*/
  1460. {
  1461. HRESULT hr = S_OK;
  1462. ULONG size;
  1463. ULONG ulBytes;
  1464. WsbTraceIn(OLESTR("WsbSaveToStream(ULARGE_INTEGER)"), OLESTR("value = <%l64x>"), value);
  1465. try {
  1466. UCHAR bytes[BYTE_SIZE];
  1467. WsbAssert(0 != pStream, E_POINTER);
  1468. WsbAffirmHr(WsbConvertToBytes(bytes, value, &size));
  1469. WsbAffirmHr(pStream->Write((void*) bytes, size, &ulBytes));
  1470. WsbAffirm(ulBytes == size, WSB_E_STREAM_ERROR);
  1471. } WsbCatch(hr);
  1472. WsbTraceOut(OLESTR("WsbSaveToStream(ULARGE_INTEGER)"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1473. return(hr);
  1474. }
  1475. static HRESULT
  1476. WsbMakeBackupName(
  1477. OLECHAR* pSaveName,
  1478. OLECHAR* pExtension,
  1479. OLECHAR** ppBackupName
  1480. )
  1481. /*++
  1482. Routine Description:
  1483. Converts a Save file name to a backup file name.
  1484. Arguments:
  1485. pSaveName - Orginal file name.
  1486. pExtension - The file extension to substitute.
  1487. ppBackupName - Pointer to pointer to new backup file name.
  1488. Return Value:
  1489. S_OK - Success
  1490. E_... - Some error.
  1491. --*/
  1492. {
  1493. HRESULT hr = S_OK;
  1494. try {
  1495. size_t len;
  1496. CWsbStringPtr NewName;
  1497. OLECHAR* pC;
  1498. // It sure would be nice to have a general function for parsing
  1499. // file names!
  1500. // Find the file extension (if any)
  1501. NewName = pSaveName;
  1502. if (NewName == NULL) {
  1503. WsbThrow(E_OUTOFMEMORY);
  1504. }
  1505. len = wcslen(NewName);
  1506. pC = wcsrchr(NewName, OLECHAR('.'));
  1507. if (pC && (size_t)((pC - (OLECHAR*)NewName) + 4) >= len) {
  1508. *pC = 0;
  1509. }
  1510. // Put on new file extension
  1511. NewName.Append(pExtension);
  1512. // Give the buffer to the output parameter
  1513. NewName.GiveTo(ppBackupName);
  1514. } WsbCatch(hr);
  1515. return(hr);
  1516. }
  1517. HRESULT
  1518. WsbPrintfToStream(
  1519. IStream* pStream,
  1520. OLECHAR* fmtString,
  1521. ...
  1522. )
  1523. /*++
  1524. Routine Description:
  1525. Print printf-style format string and arguments to a stream.
  1526. Arguments:
  1527. pStream - The stream to which the value will be written.
  1528. fmtString - A printf style string indicating the number of
  1529. arguments and how they should be formatted.
  1530. Return Value:
  1531. S_OK - Success.
  1532. --*/
  1533. {
  1534. HRESULT hr = S_OK;
  1535. try {
  1536. ULONG bytesWritten;
  1537. ULONG nBytes;
  1538. ULONG nChars=0;
  1539. CWsbStringPtr tmpString;
  1540. va_list vaList;
  1541. va_start(vaList, fmtString);
  1542. WsbAffirmHr(tmpString.VPrintf(fmtString, vaList));
  1543. va_end(vaList);
  1544. WsbAffirmHr(tmpString.GetLen(&nChars));
  1545. nBytes = nChars * sizeof(WCHAR);
  1546. if (0 < nBytes) {
  1547. WsbAffirmHr(pStream->Write(static_cast<WCHAR *>(tmpString),
  1548. nBytes, &bytesWritten));
  1549. WsbAffirm(bytesWritten == nBytes, E_FAIL);
  1550. }
  1551. } WsbCatch(hr);
  1552. return(hr);
  1553. }
  1554. HRESULT
  1555. WsbSafeCreate(
  1556. OLECHAR* pFileName,
  1557. IPersistFile* pIPFile
  1558. )
  1559. /*++
  1560. Routine Description:
  1561. Makes sure there are no database files found and then creates the database files.
  1562. Arguments:
  1563. pFileName - Name of the file containing the persisted data
  1564. pIPFile - Pointer to the objects IPersistFile interface.
  1565. Return Value:
  1566. S_OK - Success
  1567. WSB_E_DATABASE_ALREADY_EXISTS - The databases already exist and cannot be created.
  1568. E_... - Some other error.
  1569. --*/
  1570. {
  1571. HRESULT hr = S_OK;
  1572. OLECHAR* pBackupName = NULL;
  1573. OLECHAR* pNewName = NULL;
  1574. WsbTraceIn(OLESTR("WsbSafeCreate"), OLESTR("<%ls>"), pFileName);
  1575. try {
  1576. CComPtr<IWsbPersistable> pIWsbPersist;
  1577. BOOL fileThere = FALSE;
  1578. // Save the file name passed as the default file name
  1579. WsbAffirmHr(pIPFile->QueryInterface(IID_IWsbPersistable,
  1580. (void**)&pIWsbPersist));
  1581. WsbAffirmHr(pIWsbPersist->SetDefaultFileName(pFileName));
  1582. //
  1583. // Check to see if the file exists. If so, life is BAD.
  1584. // If not, then see if the new or backup files exist
  1585. // and use them
  1586. //
  1587. // Make sure the Save file exists
  1588. if (!WsbFileExists(pFileName)) {
  1589. //
  1590. // The file doesn't exist. See if the new copy is there
  1591. //
  1592. // Create name for new (temporary) file
  1593. //
  1594. WsbAffirmHr(WsbMakeBackupName(pFileName, OLESTR(".new"), &pNewName));
  1595. // See if the new file exists
  1596. if (!WsbFileExists(pNewName)) {
  1597. //
  1598. // Don't have the new file, look for the backup file
  1599. //
  1600. WsbAffirmHr(WsbMakeBackupName(pFileName, OLESTR(".bak"), &pBackupName));
  1601. if (WsbFileExists(pBackupName)) {
  1602. //
  1603. // Backup is there - complain
  1604. //
  1605. hr = WSB_E_DATABASE_ALREADY_EXISTS;
  1606. }
  1607. } else {
  1608. //
  1609. // New is there - complain
  1610. //
  1611. hr = WSB_E_DATABASE_ALREADY_EXISTS;
  1612. }
  1613. } else {
  1614. //
  1615. // The file exists so complain
  1616. //
  1617. hr = WSB_E_DATABASE_ALREADY_EXISTS;
  1618. WsbThrow( hr );
  1619. }
  1620. //
  1621. // If we haven't thrown then it is OK to create the files
  1622. //
  1623. hr = pIPFile->Save( pFileName, TRUE);
  1624. if (!SUCCEEDED(hr)) {
  1625. WsbLogEvent(WSB_MESSAGE_SAFECREATE_SAVE_FAILED, 0, NULL, pFileName, NULL);
  1626. WsbThrow(hr);
  1627. }
  1628. // Release the file
  1629. WsbAffirmHr(pIWsbPersist->ReleaseFile());
  1630. } WsbCatch(hr);
  1631. if (pBackupName) {
  1632. WsbFree(pBackupName);
  1633. }
  1634. if (pNewName) {
  1635. WsbFree(pNewName);
  1636. }
  1637. WsbTraceOut(OLESTR("WsbSafeCreate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1638. return(hr);
  1639. }
  1640. HRESULT
  1641. WsbSafeLoad(
  1642. OLECHAR* pFileName,
  1643. IPersistFile* pIPFile,
  1644. BOOL UseBackup
  1645. )
  1646. /*++
  1647. Routine Description:
  1648. Loads data from the specified file name. Works in conjunction with WsbSafeSave
  1649. to best recover from disaster situations.
  1650. Arguments:
  1651. pFileName - Name of the file containing the persisted data
  1652. pIPFile - Pointer to the objects IPersistFile interface.
  1653. UseBackup - Load data from backup file instead of normal file
  1654. NOTE: (this is not used anymore)
  1655. Return Value:
  1656. S_OK - Success
  1657. WSB_E_NOTFOUND - The databases could not be found
  1658. E_... - Some other error.
  1659. --*/
  1660. {
  1661. HRESULT hr = S_OK;
  1662. OLECHAR* pBackupName = NULL;
  1663. OLECHAR* pLoadName = NULL;
  1664. BOOL usingBackup = FALSE;
  1665. BOOL TracePersistence = FALSE;
  1666. UNREFERENCED_PARAMETER(UseBackup);
  1667. // Turn tracing off during save if it's not wanted
  1668. if (g_pWsbTrace) {
  1669. g_pWsbTrace->GetTraceSetting(WSB_TRACE_BIT_PERSISTENCE, &TracePersistence);
  1670. }
  1671. if (!TracePersistence) {
  1672. WsbTraceThreadOff();
  1673. }
  1674. WsbTraceIn(OLESTR("WsbSafeLoad"), OLESTR("File = <%ls>, UseBackup = %ls"),
  1675. pFileName, WsbBoolAsString(UseBackup));
  1676. try {
  1677. HRESULT hrLoad;
  1678. BOOL fileThere = FALSE;
  1679. CComPtr<IWsbPersistable> pIWsbPersist;
  1680. // Save the file name passed as the default file name
  1681. WsbAffirmHr(pIPFile->QueryInterface(IID_IWsbPersistable,
  1682. (void**)&pIWsbPersist));
  1683. WsbAffirmHr(pIWsbPersist->SetDefaultFileName(pFileName));
  1684. //
  1685. // Create the backup file name
  1686. //
  1687. WsbAffirmHr(WsbMakeBackupName(pFileName, OLESTR(".bak"), &pBackupName));
  1688. //
  1689. // Check if the .col exists
  1690. //
  1691. if (WsbFileExists(pFileName)) {
  1692. //
  1693. // The file exists. Use it
  1694. //
  1695. fileThere = TRUE;
  1696. pLoadName = pFileName;
  1697. } else {
  1698. //
  1699. // Look for the backup file
  1700. //
  1701. WsbTrace(OLESTR("WsbSafeLoad: trying .bak\n"));
  1702. if (WsbFileExists(pBackupName)) {
  1703. //
  1704. // Use the backup file
  1705. //
  1706. // WsbLogEvent(WSB_MESSAGE_SAFELOAD_USING_BACKUP, 0, NULL, pFileName, NULL);
  1707. pLoadName = pBackupName;
  1708. fileThere = TRUE;
  1709. usingBackup= TRUE;
  1710. }
  1711. }
  1712. WsbAffirm(fileThere, WSB_E_NOTFOUND);
  1713. //
  1714. // The file exists so try to load from it
  1715. //
  1716. hr = pIPFile->Load(pLoadName, 0);
  1717. if (SUCCEEDED(hr)) {
  1718. //
  1719. // Load succeeded, release the file
  1720. //
  1721. WsbAffirmHr(pIWsbPersist->ReleaseFile());
  1722. //
  1723. // TO BE DONE: check if .bak file is out of date
  1724. // and update it if so..
  1725. //
  1726. } else if (!usingBackup) {
  1727. WsbTrace(OLESTR("WsbSafeLoad: trying .bak\n"));
  1728. if (WsbFileExists(pBackupName)) {
  1729. WsbLogEvent(WSB_MESSAGE_SAFELOAD_USING_BACKUP, 0, NULL, pLoadName, WsbHrAsString(hr));
  1730. //
  1731. // Use the backup file
  1732. //
  1733. hrLoad = pIPFile->Load(pBackupName, 0);
  1734. if (SUCCEEDED(hrLoad)) {
  1735. // Load succeeded, release the file
  1736. WsbAffirmHr(pIWsbPersist->ReleaseFile());
  1737. //
  1738. // Now save the changes to the .col file to keep it in sync
  1739. //
  1740. hr = pIPFile->Save(pFileName, FALSE);
  1741. if (!SUCCEEDED(hr)) {
  1742. WsbLogEvent(WSB_MESSAGE_SAFESAVE_RECOVERY_CANT_SAVE, 0, NULL, pFileName, WsbHrAsString(hr), NULL);
  1743. WsbThrow(hr);
  1744. }
  1745. //
  1746. // Commit and release .col file
  1747. //
  1748. WsbAffirmHr(pIWsbPersist->ReleaseFile());
  1749. } else {
  1750. WsbLogEvent(WSB_MESSAGE_SAFELOAD_RECOVERY_FAILED, 0, NULL, pFileName, WsbHrAsString(hrLoad), NULL);
  1751. WsbThrow(hrLoad);
  1752. }
  1753. } else {
  1754. WsbLogEvent(WSB_MESSAGE_SAFELOAD_RECOVERY_FAILED, 0, NULL, pFileName, NULL);
  1755. }
  1756. } else {
  1757. WsbLogEvent(WSB_MESSAGE_SAFELOAD_RECOVERY_FAILED, 0, NULL, pFileName, WsbHrAsString(hr));
  1758. }
  1759. } WsbCatch(hr);
  1760. if (pBackupName) {
  1761. WsbFree(pBackupName);
  1762. }
  1763. WsbTraceOut(OLESTR("WsbSafeLoad"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1764. // Restore tracing if we turned it off
  1765. if (!TracePersistence) {
  1766. WsbTraceThreadOn();
  1767. }
  1768. return(hr);
  1769. }
  1770. HRESULT
  1771. WsbSafeSave(
  1772. IPersistFile* pIPFile
  1773. )
  1774. /*++
  1775. Routine Description:
  1776. Saves the object to a backup file and then replaces the objects Save file
  1777. with the backup file. Use with WsbSafeLoad
  1778. Arguments:
  1779. pIPFile - Pointer to the objects IPersistFile interface.
  1780. Return Value:
  1781. S_OK - Success
  1782. E_... - Some error.
  1783. --*/
  1784. {
  1785. HRESULT hr = S_OK;
  1786. OLECHAR* pBackupName = NULL;
  1787. OLECHAR* pFileName = NULL;
  1788. BOOL TracePersistence = FALSE;
  1789. DWORD file_attrs;
  1790. // Turn tracing off during save if it's not wanted
  1791. if (g_pWsbTrace) {
  1792. g_pWsbTrace->GetTraceSetting(WSB_TRACE_BIT_PERSISTENCE, &TracePersistence);
  1793. }
  1794. if (!TracePersistence) {
  1795. WsbTraceThreadOff();
  1796. }
  1797. WsbTraceIn(OLESTR("WsbSafeSave"), OLESTR(""));
  1798. try {
  1799. CComPtr<IWsbPersistable> pIWsbPersist;
  1800. // Get the current Save file name
  1801. WsbAffirmHr(pIPFile->GetCurFile(&pFileName));
  1802. WsbTrace(OLESTR("WsbSafeSave: filename = <%ls>\n"), pFileName);
  1803. // Create name for backup file
  1804. WsbAffirmHr(WsbMakeBackupName(pFileName, OLESTR(".bak"), &pBackupName));
  1805. // Make sure we have write access to the save file if it exists!
  1806. if (WsbFileExists(pFileName)) {
  1807. file_attrs = GetFileAttributes(pFileName);
  1808. if (file_attrs & FILE_ATTRIBUTE_READONLY) {
  1809. WsbLogEvent(WSB_MESSAGE_SAFESAVE_RECOVERY_CANT_ACCESS, 0, NULL, pFileName, NULL);
  1810. WsbThrow(E_FAIL);
  1811. }
  1812. }
  1813. // Save data to save file
  1814. hr = pIPFile->Save(pFileName, FALSE);
  1815. if (!SUCCEEDED(hr)) {
  1816. WsbLogEvent(WSB_MESSAGE_SAFESAVE_RECOVERY_CANT_SAVE, 0, NULL, pFileName, WsbHrAsString(hr), NULL);
  1817. WsbThrow(hr);
  1818. }
  1819. // Commit and release the save file
  1820. WsbAffirmHr(pIPFile->QueryInterface(IID_IWsbPersistable,
  1821. (void**)&pIWsbPersist));
  1822. WsbAffirmHr(pIWsbPersist->ReleaseFile());
  1823. // Save data to .bak file
  1824. // Make sure we have write access to the save file if it exists!
  1825. if (WsbFileExists(pBackupName)) {
  1826. file_attrs = GetFileAttributes(pBackupName);
  1827. if (file_attrs & FILE_ATTRIBUTE_READONLY) {
  1828. WsbLogEvent(WSB_MESSAGE_SAFESAVE_RECOVERY_CANT_ACCESS, 0, NULL, pBackupName, NULL);
  1829. WsbThrow(E_FAIL);
  1830. }
  1831. }
  1832. hr = pIPFile->Save(pBackupName, FALSE);
  1833. if (!SUCCEEDED(hr)) {
  1834. WsbLogEvent(WSB_MESSAGE_SAFESAVE_RECOVERY_CANT_SAVE, 0, NULL, pBackupName, WsbHrAsString(hr), NULL);
  1835. WsbThrow(hr);
  1836. }
  1837. // Commit and release the .bak file
  1838. WsbAffirmHr(pIWsbPersist->ReleaseFile());
  1839. } WsbCatch(hr);
  1840. if (pFileName) {
  1841. WsbFree(pFileName);
  1842. }
  1843. if (pBackupName) {
  1844. WsbFree(pBackupName);
  1845. }
  1846. WsbTraceOut(OLESTR("WsbSafeSave"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1847. // Restore tracing if we turned it off
  1848. if (!TracePersistence) {
  1849. WsbTraceThreadOn();
  1850. }
  1851. return(hr);
  1852. }
  1853. HRESULT WsbStreamToFile(
  1854. HANDLE hFile,
  1855. IStream* pStream,
  1856. BOOL AddCR
  1857. )
  1858. /*++
  1859. Routine Description:
  1860. Copies text from a stream (which must have been created with CreateStreamOnHGlobal)
  1861. to an open file (opened via CreateFile). The text is assumed to be wide characters
  1862. with no embedded wide-character nulls. The text is converted to multibyte characters
  1863. for output to the file.
  1864. After the text is copied, the stream position is reset to the beggining.
  1865. Arguments:
  1866. hFile - Handle of output file.
  1867. pStream - Pointer to an IStream interface.
  1868. AddCR - Convert LF to CR-LF if TRUE.
  1869. Return Value:
  1870. S_OK - Success
  1871. --*/
  1872. {
  1873. HRESULT hr = S_OK;
  1874. const int safe_size = 1024;
  1875. static char buf[safe_size + 16];
  1876. static char CRLF[3] = "\r\n";
  1877. HGLOBAL hMem = 0; // Mem block for stream
  1878. WCHAR* addr = NULL;
  1879. try {
  1880. WCHAR big_eof = 0;
  1881. BOOL doCRLF = FALSE;
  1882. DWORD err;
  1883. DWORD nbytes;
  1884. int nchars_todo;
  1885. int nchars_remaining;
  1886. LARGE_INTEGER seek_pos_zero;
  1887. // Make sure the text ends with a null
  1888. WsbAffirmHr(pStream->Write(&big_eof, sizeof(WCHAR), NULL));
  1889. // Get the address of the memory block for the stream
  1890. WsbAffirmHr(GetHGlobalFromStream(pStream, &hMem));
  1891. addr = static_cast<WCHAR *>(GlobalLock(hMem));
  1892. WsbAffirm(addr, E_HANDLE);
  1893. // Get the total number of chars. in the string
  1894. nchars_remaining = wcslen(addr);
  1895. // Loop until all chars. are written
  1896. while (nchars_remaining) {
  1897. DWORD bytesWritten;
  1898. if (nchars_remaining * sizeof(WCHAR) > safe_size) {
  1899. nchars_todo = safe_size / sizeof(WCHAR);
  1900. } else {
  1901. nchars_todo = nchars_remaining;
  1902. }
  1903. // Stop at LineFeed if we need to convert to CR-LF
  1904. if (AddCR) {
  1905. int lf_todo;
  1906. WCHAR* pLF;
  1907. pLF = wcschr(addr, WCHAR('\n'));
  1908. if (pLF) {
  1909. lf_todo = (int)(pLF - addr);
  1910. if (lf_todo < nchars_todo) {
  1911. nchars_todo = lf_todo;
  1912. doCRLF = TRUE;
  1913. }
  1914. }
  1915. }
  1916. // Output everything up to LF
  1917. if (0 < nchars_todo) {
  1918. nbytes = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, addr, nchars_todo, buf,
  1919. safe_size, NULL, NULL);
  1920. if (0 == nbytes) {
  1921. DWORD dwErr = GetLastError();
  1922. hr = HRESULT_FROM_WIN32(dwErr);
  1923. WsbAffirmHr(hr);
  1924. }
  1925. if (!WriteFile(hFile, buf, nbytes, &bytesWritten, NULL)) {
  1926. err = GetLastError();
  1927. WsbThrow(HRESULT_FROM_WIN32(err));
  1928. }
  1929. WsbAffirm(bytesWritten == nbytes, E_FAIL);
  1930. }
  1931. // Output CR-LF in place of LF if needed
  1932. if (doCRLF) {
  1933. if (!WriteFile(hFile, CRLF, 2, &bytesWritten, NULL)) {
  1934. err = GetLastError();
  1935. WsbThrow(HRESULT_FROM_WIN32(err));
  1936. }
  1937. WsbAffirm(bytesWritten == 2, E_FAIL);
  1938. nchars_todo++;
  1939. doCRLF = FALSE;
  1940. }
  1941. nchars_remaining -= nchars_todo;
  1942. addr += nchars_todo;
  1943. }
  1944. seek_pos_zero.QuadPart = 0;
  1945. WsbAffirmHr(pStream->Seek(seek_pos_zero, STREAM_SEEK_SET, NULL));
  1946. } WsbCatch(hr);
  1947. if (addr != NULL) {
  1948. GlobalUnlock(hMem);
  1949. addr = NULL;
  1950. }
  1951. return(hr);
  1952. }
  1953. // WsbFileExists - determine if a file exists or not
  1954. static BOOL WsbFileExists(OLECHAR* pFileName)
  1955. {
  1956. BOOL doesExist = FALSE;
  1957. DWORD file_attrs;
  1958. WsbTraceIn(OLESTR("WsbFileExists"), OLESTR("%ls"), pFileName);
  1959. file_attrs = GetFileAttributes(pFileName);
  1960. if (0xffffffff != file_attrs) {
  1961. doesExist = TRUE;
  1962. }
  1963. WsbTraceOut(OLESTR("WsbFileExists"), OLESTR("%ls"),
  1964. WsbBoolAsString(doesExist));
  1965. return(doesExist);
  1966. }