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.

546 lines
17 KiB

  1. /*
  2. #include <stdio.h>
  3. #include "PStgServ.h"
  4. #include "PropMshl.hxx"
  5. #include "CPropVar.hxx"
  6. #include "CHResult.hxx"
  7. #include "proptest.hxx"
  8. */
  9. #include "pch.cxx"
  10. #include <shellapi.h>
  11. const IID IID_IPropertyStorageServer = {0xaf4ae0d0,0xa37f,0x11cf,{0x8d,0x73,0x00,0xaa,0x00,0x4c,0xd0,0x1a}};
  12. const IID IID_IPropertyStorageServerApp = {0xaf4ae0d1,0xa37f,0x11cf,{0x8d,0x73,0x00,0xaa,0x00,0x4c,0xd0,0x1a}};
  13. CPropSpec g_rgcpropspecVariant[] = { OLESTR("SafeArray") };
  14. CPropStgMarshalTest::CPropStgMarshalTest( )
  15. {
  16. m_cAllProperties = 0;
  17. m_cSimpleProperties = 0;
  18. m_rgpropspec = NULL;
  19. m_rgpropvar = NULL;
  20. m_pwszDocFileName = NULL;
  21. m_fInitialized = FALSE;
  22. }
  23. CPropStgMarshalTest::~CPropStgMarshalTest()
  24. {
  25. if( m_pwszDocFileName != NULL )
  26. delete m_pwszDocFileName;
  27. }
  28. HRESULT
  29. CPropStgMarshalTest::Init( OLECHAR *pwszDocFileName,
  30. PROPVARIANT rgpropvar[],
  31. PROPSPEC rgpropspec[],
  32. ULONG cAllProperties,
  33. ULONG cSimpleProperties )
  34. {
  35. HRESULT hr = E_FAIL;
  36. // Validate the input.
  37. if( pwszDocFileName == NULL )
  38. {
  39. hr = STG_E_INVALIDPARAMETER;
  40. goto Exit;
  41. }
  42. m_cAllProperties = cAllProperties;
  43. m_cSimpleProperties = cSimpleProperties;
  44. m_rgpropvar = rgpropvar;
  45. m_rgpropspec = rgpropspec;
  46. // Copy the docfile name.
  47. m_pwszDocFileName = new WCHAR[ wcslen(pwszDocFileName) + 1 ];
  48. if( m_pwszDocFileName != NULL )
  49. {
  50. wcscpy( m_pwszDocFileName, pwszDocFileName );
  51. }
  52. else
  53. {
  54. hr = E_OUTOFMEMORY;
  55. goto Exit;
  56. }
  57. // Register the local server. We assume that it's either in
  58. // the local directory or in the path.
  59. if( g_fRegisterLocalServer )
  60. {
  61. HINSTANCE hinst = 0;
  62. DWORD dwWait;
  63. PROCESS_INFORMATION ProcessInformation;
  64. STARTUPINFO StartupInfo;
  65. memset( &StartupInfo, 0, sizeof(StartupInfo) );
  66. StartupInfo.cb = sizeof(StartupInfo);
  67. TCHAR tszCommand[] = TEXT("PStgServ.exe /RegServer");
  68. if( !CreateProcess( NULL,
  69. tszCommand,
  70. NULL, NULL,
  71. FALSE,
  72. 0,
  73. NULL,
  74. NULL,
  75. &StartupInfo,
  76. &ProcessInformation ))
  77. {
  78. hr = HRESULT_FROM_WIN32( GetLastError() );
  79. goto Exit;
  80. }
  81. if( WAIT_OBJECT_0 != WaitForSingleObject( ProcessInformation.hProcess, INFINITE ))
  82. {
  83. hr = HRESULT_FROM_WIN32( GetLastError() );
  84. goto Exit;
  85. }
  86. }
  87. hr = S_OK;
  88. Exit:
  89. return( hr );
  90. }
  91. HRESULT
  92. CPropStgMarshalTest::Run()
  93. {
  94. HRESULT hr = S_OK;
  95. IPropertyStorageServer *pserver = NULL;
  96. IStorage *pstg = NULL;
  97. IPropertySetStorage *ppsstg = NULL;
  98. IPropertyStorage *ppstg = NULL;
  99. DWORD grfFlags=0;
  100. // ------------------------
  101. // Create a PropSet locally
  102. // ------------------------
  103. // Create a local IPropertySetStorage
  104. hr = g_pfnStgCreateStorageEx (
  105. m_pwszDocFileName,
  106. STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  107. DetermineStgFmt( g_enumImplementation ),
  108. 0,
  109. NULL,
  110. NULL,
  111. PROPIMP_NTFS == g_enumImplementation ? IID_IFlatStorage : IID_IStorage,
  112. (void**) &pstg );
  113. if(FAILED(hr)) ERROR_EXIT( TEXT("Failed open of local Storage") );
  114. hr = StgToPropSetStg( pstg, &ppsstg );
  115. if( FAILED(hr) ) ERROR_EXIT( TEXT("Couldn't create local IPropertySetStorage") );
  116. // Create an IPropertyStorage
  117. grfFlags = PROPSETFLAG_ANSI | PROPSETFLAG_NONSIMPLE;
  118. hr = ppsstg->Create( IID_IPropertyStorageServer, NULL,
  119. grfFlags,
  120. STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  121. &ppstg );
  122. if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't create a local IPropertyStorage") );
  123. RELEASE_INTERFACE( ppsstg );
  124. // Write properties to it and close it.
  125. hr = WriteProperties( ppstg, FALSE /* Not Marshaled */ );
  126. if(FAILED(hr)) ERROR_EXIT( TEXT("Failed to write properties to local PropStg") );
  127. RELEASE_INTERFACE( ppstg );
  128. RELEASE_INTERFACE( pstg );
  129. // -----------------------------------------
  130. // Verify the properties through a marshaled
  131. // IPropertySetStorage
  132. // -----------------------------------------
  133. // Get a remote IPropertySetStorage
  134. Status( TEXT("Starting Server") );
  135. hr = CoCreateInstance( IID_IPropertyStorageServerApp,
  136. NULL,
  137. CLSCTX_LOCAL_SERVER,
  138. IID_IPropertyStorageServer,
  139. (void **)&pserver );
  140. if(FAILED(hr)) ERROR_EXIT( TEXT("Failed CoCreateInstance") );
  141. hr = pserver->Initialize( g_enumImplementation, g_Restrictions );
  142. if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't initialize property set storage server") );
  143. Status( TEXT("Requesting remote IPropertySetStorage") );
  144. hr = pserver->StgOpenPropSetStg( m_pwszDocFileName,
  145. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  146. &ppsstg );
  147. if(FAILED(hr)) ERROR_EXIT( TEXT("Failed to open remote PropSetStg") );
  148. // Get an IPropertyStorage
  149. hr = ppsstg->Open( IID_IPropertyStorageServer,
  150. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  151. &ppstg );
  152. if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't create a local IPropertyStorage") );
  153. RELEASE_INTERFACE( ppsstg );
  154. // Read from the marshalled Storage and compare the properties against
  155. // the local copy we kept.
  156. Status( TEXT("Reading/verifying properties from marshalled IPropertySetStorage") );
  157. hr = ReadAndCompareProperties( ppstg, TRUE /* Marshaled */ );
  158. if(FAILED(hr)) ERROR_EXIT( TEXT("Failed marshalled read and compare") );
  159. // Remove the existing properties via the marhsalled interface, and
  160. // re-write them.
  161. hr = DeleteProperties( ppstg, TRUE /* Marshaled */ );
  162. if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't delete properties from remote IPropertySetStorage") );
  163. // Write the properties back to the remote storage.
  164. Status( TEXT("Writing properties through marshalled IPropertySetStorage") );
  165. hr = WriteProperties( ppstg, TRUE /* Marshaled */ );
  166. if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't write properties to remote Storage") );
  167. RELEASE_INTERFACE( ppstg );
  168. // -----------------------------------------
  169. // Verify the properties through a marshaled
  170. // IPropertyStorage
  171. // -----------------------------------------
  172. // Get a remote IPropertyStorage
  173. Status( TEXT("Requesting remote IPropertyStorage") );
  174. hr = pserver->StgOpenPropStg( m_pwszDocFileName,
  175. IID_IPropertyStorageServer,
  176. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  177. &ppstg );
  178. if(FAILED(hr)) ERROR_EXIT( TEXT("Failed to open remote PropStg") );
  179. // Read from the marshalled Storage and compare the properties against
  180. // the local copy we kept.
  181. Status( TEXT("Reading/verifying properties from marshalled IPropertyStorage") );
  182. hr = ReadAndCompareProperties( ppstg, TRUE /* Marshaled */ );
  183. if(FAILED(hr)) ERROR_EXIT( TEXT("Failed marshalled read and compare") );
  184. // Remove the existing properties via the marhsalled interface, and
  185. // re-write them.
  186. hr = DeleteProperties( ppstg, TRUE /* Marshaled */ );
  187. if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't delete properties from remote Storage") );
  188. // Write the properties back to the remote storage.
  189. Status( TEXT("Writing properties through marshalled IPropertyStorage") );
  190. hr = WriteProperties( ppstg, TRUE /* Marshaled */ );
  191. if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't write properties to remote Storage") );
  192. RELEASE_INTERFACE( ppstg );
  193. RELEASE_INTERFACE( pserver );
  194. // --------------------------------
  195. // Re-verify the properties locally
  196. // --------------------------------
  197. // Re-open the DocFile locally.
  198. hr = g_pfnStgOpenStorageEx( m_pwszDocFileName,
  199. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  200. STGFMT_ANY, //DetermineStgFmt( g_enumImplementation )
  201. 0L,
  202. NULL,
  203. NULL,
  204. PROPIMP_NTFS == g_enumImplementation ? IID_IFlatStorage : IID_IStorage,
  205. (PVOID*)&pstg );
  206. if (SUCCEEDED(hr))
  207. {
  208. hr = StgToPropSetStg( pstg, &ppsstg );
  209. if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't create IPropertySetStorage on local DocFile") );
  210. }
  211. else
  212. {
  213. hr = g_pfnStgOpenStorageEx( m_pwszDocFileName,
  214. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  215. STGFMT_ANY, //DetermineStgFmt( g_enumImplementation )
  216. 0L,
  217. NULL,
  218. NULL,
  219. IID_IPropertySetStorage,
  220. (PVOID*)&ppsstg );
  221. }
  222. if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't re-open the File locally") );
  223. hr = ppsstg->Open( IID_IPropertyStorageServer,
  224. STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  225. &ppstg );
  226. if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't open load IPropertyStorage") );
  227. RELEASE_INTERFACE( ppsstg );
  228. // Compare the properties in the property set, which we wrote through
  229. // the marshalled interface, against what they should be.
  230. Status( TEXT("Reading/verifying properties from local IPropertyStorage") );
  231. hr = ReadAndCompareProperties( ppstg, FALSE /* Not Marshaled */ );
  232. if(FAILED(hr)) ERROR_EXIT( TEXT("Properties written through marshalled interface do not appear correct") );
  233. RELEASE_INTERFACE( ppstg );
  234. RELEASE_INTERFACE( pstg );
  235. Exit:
  236. RELEASE_INTERFACE( pstg );
  237. RELEASE_INTERFACE( ppsstg );
  238. RELEASE_INTERFACE( ppstg );
  239. RELEASE_INTERFACE( pserver );
  240. return( hr );
  241. }
  242. HRESULT CPropStgMarshalTest::WriteProperties( IPropertyStorage *ppstg, BOOL fMarshaled )
  243. {
  244. HRESULT hr = E_FAIL;
  245. // Are we restricted to simple properties?
  246. if( RESTRICT_SIMPLE_ONLY & g_Restrictions )
  247. {
  248. // Write the simple properties
  249. hr = ppstg->WriteMultiple( m_cSimpleProperties, m_rgpropspec, m_rgpropvar, PID_FIRST_USABLE );
  250. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed WriteMultiple") );
  251. }
  252. // Or, are we marshaling with IProp (where non-simple properties don't work)?
  253. else if( fMarshaled && g_SystemInfo.fIPropMarshaling )
  254. {
  255. // Verify that we can't write the non-simple properties
  256. hr = ppstg->WriteMultiple( m_cAllProperties, m_rgpropspec, m_rgpropvar, PID_FIRST_USABLE );
  257. if( RPC_E_CLIENT_CANTMARSHAL_DATA != hr )
  258. {
  259. hr = E_FAIL;
  260. ERROR_EXIT( TEXT("Failed WriteMultiple") );
  261. }
  262. // Write the simple properties
  263. hr = ppstg->WriteMultiple( m_cSimpleProperties, m_rgpropspec, m_rgpropvar, PID_FIRST_USABLE );
  264. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed WriteMultiple") );
  265. }
  266. // Otherwise, write all the properties
  267. else
  268. {
  269. hr = ppstg->WriteMultiple( m_cAllProperties, m_rgpropspec, m_rgpropvar, PID_FIRST_USABLE );
  270. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed WriteMultiple") );
  271. Check( S_OK, ResetRGPropVar( (CPropVariant*)m_rgpropvar ));
  272. // Test with a SafeArray too.
  273. PROPVARIANT propvar;
  274. SAFEARRAY *psa = NULL;
  275. SAFEARRAYBOUND rgsaBound[] = { {2, 0} };
  276. psa = SafeArrayCreateEx( VT_I4, 1, rgsaBound, NULL );
  277. LONG rgIndices[] = {0};
  278. LONG lVal = 0;
  279. Check( S_OK, SafeArrayPutElement( psa, rgIndices, &lVal ));
  280. rgIndices[0] = lVal = 1;
  281. Check( S_OK, SafeArrayPutElement( psa, rgIndices, &lVal ));
  282. PropVariantInit( &propvar );
  283. propvar.vt = VT_ARRAY | VT_I4;
  284. propvar.parray = psa;
  285. psa = NULL;
  286. hr = ppstg->WriteMultiple( 1, g_rgcpropspecVariant, &propvar, PID_FIRST_USABLE );
  287. PropVariantClear( &propvar );
  288. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed WriteMultiple") );
  289. }
  290. // ----
  291. // Exit
  292. // ----
  293. hr = S_OK;
  294. Exit:
  295. return( hr );
  296. }
  297. HRESULT CPropStgMarshalTest::ReadAndCompareProperties( IPropertyStorage *ppstg, BOOL fMarshaled )
  298. {
  299. HRESULT hr = E_FAIL;
  300. ULONG i;
  301. ULONG cProperties = 0;
  302. // Allocate a PROPVARIANT[] into which we can read the
  303. // properties
  304. PROPVARIANT *rgpropvar = new PROPVARIANT[ m_cAllProperties ];
  305. if( NULL == rgpropvar )
  306. {
  307. hr = E_OUTOFMEMORY;
  308. goto Exit;
  309. }
  310. // Are we restricted to only simple properties?
  311. if( RESTRICT_SIMPLE_ONLY & g_Restrictions )
  312. {
  313. cProperties = m_cSimpleProperties;
  314. // Read just the simple properties
  315. hr = ppstg->ReadMultiple( cProperties, m_rgpropspec, rgpropvar );
  316. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed ReadMultiple") );
  317. }
  318. // Or, are we marshaling with IProp (where non-simple properties don't work)?
  319. else if( fMarshaled && g_SystemInfo.fIPropMarshaling )
  320. {
  321. cProperties = m_cSimpleProperties;
  322. // Try to read all the properties, including the non-simples.
  323. hr = ppstg->ReadMultiple( m_cAllProperties, m_rgpropspec, rgpropvar );
  324. if( RPC_E_SERVER_CANTMARSHAL_DATA != hr )
  325. {
  326. hr = E_FAIL;
  327. ERROR_EXIT( TEXT("Failed ReadMultiple") );
  328. }
  329. // Now read just the simple properties
  330. hr = ppstg->ReadMultiple( cProperties, m_rgpropspec, rgpropvar );
  331. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed ReadMultiple") );
  332. }
  333. // Otherwise, read all the properties
  334. else
  335. {
  336. cProperties = m_cAllProperties;
  337. // Read the properties
  338. hr = ppstg->ReadMultiple( cProperties, m_rgpropspec, rgpropvar );
  339. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed ReadMultiple") );
  340. // Read and compare the safearray property
  341. PROPVARIANT propvar;
  342. PropVariantInit( &propvar );
  343. hr = ppstg->ReadMultiple( 1, g_rgcpropspecVariant, &propvar );
  344. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed ReadMultiple") );
  345. if( (VT_ARRAY | VT_I4) != propvar.vt
  346. ||
  347. NULL == propvar.parray
  348. ||
  349. 1 != SafeArrayGetDim(propvar.parray) )
  350. {
  351. ERROR_EXIT( TEXT("Invalid type returned in ReadMultiple") );
  352. }
  353. LONG rgIndices[] = { 0 };
  354. LONG rglVal[] = { -1, -1 };
  355. hr = SafeArrayGetElement( propvar.parray, rgIndices, &rglVal[0] );
  356. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed SafeArrayGetElement") );
  357. rgIndices[0] = 1;
  358. hr = SafeArrayGetElement( propvar.parray, rgIndices, &rglVal[1] );
  359. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed SafeArrayGetElement") );
  360. if( 0 != rglVal[0] || 1 != rglVal[1] )
  361. ERROR_EXIT( TEXT("SafeArray types don't match") );
  362. PropVariantClear( &propvar );
  363. }
  364. // Compare the properties with what we expect.
  365. for( i = 0; i < cProperties; i++ )
  366. {
  367. hr = CPropVariant::Compare( &rgpropvar[i], &m_rgpropvar[i] );
  368. if( S_OK != hr )
  369. {
  370. hr = E_FAIL;
  371. ERROR_EXIT( TEXT("Property mismatch") );
  372. }
  373. }
  374. // ----
  375. // Exit
  376. // ----
  377. hr = S_OK;
  378. Exit:
  379. if( NULL != rgpropvar )
  380. {
  381. g_pfnFreePropVariantArray( m_cAllProperties, rgpropvar );
  382. delete[]( rgpropvar );
  383. }
  384. return( hr );
  385. }
  386. HRESULT CPropStgMarshalTest::DeleteProperties( IPropertyStorage *ppstg, BOOL fMarshaled )
  387. {
  388. HRESULT hr = E_FAIL;
  389. ULONG cProperties;
  390. // Determine the correct number of properties to delete.
  391. if( (RESTRICT_SIMPLE_ONLY & g_Restrictions)
  392. ||
  393. (fMarshaled && g_SystemInfo.fIPropMarshaling) )
  394. {
  395. cProperties = m_cSimpleProperties;
  396. }
  397. else
  398. cProperties = m_cAllProperties;
  399. // Delete the properties
  400. hr = ppstg->DeleteMultiple( cProperties, m_rgpropspec );
  401. if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed DeleteMultiple") );
  402. hr = S_OK;
  403. Exit:
  404. return( hr );
  405. }