Source code of Windows XP (NT5)
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.

1051 lines
31 KiB

  1. /*++
  2. Copyright (C) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. PROVCOMP.CPP
  5. Abstract:
  6. Purpose: Defines the acutal "Put" and "Get" functions for the
  7. Ole compound file provider.
  8. History:
  9. a-davj 10-10-95 v0.01
  10. --*/
  11. #include "precomp.h"
  12. #include "stdafx.h"
  13. #include <wbemidl.h>
  14. #include "impdyn.h"
  15. #define GET_FLAGS STGM_READ|STGM_SHARE_DENY_WRITE
  16. #define PUT_FLAGS STGM_READWRITE|STGM_SHARE_EXCLUSIVE
  17. enum {NORMAL, STRING, WSTRING, DBLOB, DCLSID, UNKNOWN};
  18. void CImpComp::AddBlankData(CBuff * pBuff,DWORD dwType)
  19. {
  20. VARIANTARG vTemp;
  21. DWORD dwDataSize;
  22. BOOL bStringType;
  23. // If we have an variant array, then add an empty entry and be done
  24. if(dwType == VT_VARIANT) {
  25. DWORD dwEmpty = VT_EMPTY; //TODO, is the right? maybe VT_NULL??
  26. pBuff->Add((void *)&dwEmpty,sizeof(DWORD));
  27. return;
  28. }
  29. // Create an empty variantarg, get its statistics
  30. VariantInit(&vTemp);
  31. vTemp.cyVal.int64 = 0;
  32. vTemp.vt = (VARTYPE)dwType;
  33. if(!bGetVariantStats(&vTemp, NULL, &dwDataSize, &bStringType))
  34. return;
  35. if(!bStringType) {
  36. pBuff->Add((void *)&vTemp.cyVal.int64,dwDataSize);
  37. }
  38. else if (dwType == VT_BLOB){
  39. DWORD dwSize = 0;
  40. pBuff->Add((void *)&dwSize,sizeof(DWORD));
  41. }
  42. else {
  43. DWORD dwSize = 1;
  44. pBuff->Add((void *)&dwSize,sizeof(DWORD));
  45. pBuff->Add((void *)&vTemp.cyVal.int64,2); // add a null,
  46. pBuff->RoundOff();
  47. }
  48. }
  49. //***************************************************************************
  50. //
  51. // CImpComp::AddVariantData
  52. //
  53. // Adds the property value to a buffer that is to be output. For normal
  54. // data, this acutally sets the buffer. However, for the case of array
  55. // data, it is probably adding to the buffer (unless its the first element)
  56. //
  57. //***************************************************************************
  58. void CImpComp::AddVariantData(VARIANTARG * pIn,CBuff * pBuff)
  59. {
  60. void * pCopy;
  61. BOOL bSizeNeeded;
  62. DWORD dwDataSize;
  63. bGetVariantStats(pIn, NULL, &dwDataSize, &bSizeNeeded);
  64. // If strings, blobs etc, copy size in first
  65. if(bSizeNeeded) {
  66. if(pIn->vt == VT_LPWSTR){
  67. DWORD dwTemp = dwDataSize /2 ;
  68. pBuff->Add((void*)&dwTemp,sizeof(DWORD));
  69. }
  70. else
  71. pBuff->Add((void*)&dwDataSize,sizeof(DWORD));
  72. pCopy = (void *)pIn->bstrVal;
  73. }
  74. else
  75. pCopy = (void *)&pIn->iVal;
  76. // copy the data
  77. pBuff->Add((void *)pCopy,dwDataSize);
  78. // round the data to a 4 byte boundry
  79. if(bSizeNeeded)
  80. pBuff->RoundOff();
  81. return;
  82. }
  83. //***************************************************************************
  84. //
  85. // CImpComp::bCreateWriteArray
  86. //
  87. // Create a buffer with an array of values. This is used when writting
  88. // out properties that are members of arrays. To do this, an array must
  89. // be constructed.
  90. //
  91. //***************************************************************************
  92. BOOL CImpComp::bCreateWriteArray(VARIANTARG * pIn, CBuff * pBuff,
  93. MODYNPROP *pMo, int iIndex, DWORD & dwType, BOOL bExisting, CProp * pProp)
  94. {
  95. DWORD * dwp;
  96. DWORD dwExisting; // number of existing entries
  97. DWORD dwNumElem; // number of elements to be written
  98. DWORD dwTempType;
  99. SCODE sc;
  100. // If the property alread exists, get the current type and number
  101. // of existing elements.
  102. if(bExisting) {
  103. dwType = pProp->GetType();
  104. dwType &= ~VT_VECTOR;
  105. dwp = (DWORD *)pProp->Get();
  106. dwExisting = *dwp;
  107. }
  108. else {
  109. if(!bGetVariantStats(pIn, &dwType, NULL, NULL)){
  110. pMo->dwResult = ERROR_UNKNOWN; // BAD INPUT DATA
  111. return FALSE;
  112. }
  113. dwExisting = 0;
  114. }
  115. // Determine the number of elements to write. It may be more that the
  116. // number of existing elements when writting a new vector or adding to
  117. // an existing one
  118. if((unsigned)iIndex >= dwExisting)
  119. dwNumElem = iIndex + 1; // iIndex has 0 as the first element
  120. else
  121. dwNumElem = dwExisting;
  122. // Copy in the number of elements
  123. pBuff->Add((void *)&dwNumElem,sizeof(DWORD));
  124. // Now build the output array one element at the time
  125. // todo, more error checking in here???
  126. DWORD dwCnt;
  127. for(dwCnt = 0; dwCnt < dwNumElem; dwCnt++) {
  128. if(dwCnt == (unsigned)iIndex) {
  129. // This element is being supplied by the caller
  130. if(!bExisting) {
  131. // no converstion necessary since this is a new array
  132. AddVariantData(pIn,pBuff);
  133. }
  134. else if(dwType == VT_VARIANT) {
  135. // write type first
  136. DWORD dwTemp = 0;
  137. dwTemp = pIn->vt;
  138. pBuff->Add((void *)&dwTemp,sizeof(DWORD));
  139. // write the data;
  140. AddVariantData(pIn,pBuff);
  141. }
  142. else {
  143. // existing array that isnt VARIANT type. Convert the input
  144. // data into the same format and then add
  145. VARIANTARG vTemp;
  146. VariantInit(&vTemp);
  147. vTemp.cyVal.int64 = 0;
  148. sc = OMSVariantChangeType(&vTemp,pIn,0,(VARTYPE)dwType);
  149. if(sc != S_OK) {
  150. pMo->dwResult = sc;
  151. return FALSE;
  152. }
  153. // write the data;
  154. AddVariantData(&vTemp,pBuff);
  155. OMSVariantClear(&vTemp); // all done, free it
  156. }
  157. }
  158. else if (dwCnt < dwExisting) {
  159. // Add from the read data
  160. int iIgnore;
  161. void * pTemp = ExtractData(pProp,dwTempType,dwCnt,TRUE);
  162. DWORD dwSkip = dwSkipSize((char *)pTemp,dwTempType,iIgnore);
  163. pBuff->Add(pTemp,dwSkip);
  164. }
  165. else
  166. // create a blank entry
  167. AddBlankData(pBuff,dwType);
  168. }
  169. dwType |= VT_VECTOR;
  170. return TRUE;
  171. }
  172. //***************************************************************************
  173. //
  174. // CImpComp::bGetVariantStats
  175. //
  176. // Determines various characteristics of a VARIANTARG.
  177. //
  178. // Returns TRUE if the variant type is valid.
  179. //
  180. //***************************************************************************
  181. BOOL CImpComp::bGetVariantStats(VARIANTARG * pIn, DWORD * pType, DWORD * pDataSize, BOOL * pSizeNeeded)
  182. {
  183. BOOL bSizeNeeded = FALSE; // set to true for strings and blobs etc.
  184. DWORD dwDataSize = 0, dwType;
  185. void * pData = (void *)pIn->bstrVal;
  186. // normall the type is whatever is in the VARIANTARG. However,
  187. // certain new types, such as VT_UI4 are not in the ole spec and
  188. // might cause problems to older programs. Therefore, the new
  189. // types have an equivalent older type returned.
  190. dwType = pIn->vt;
  191. // just in case we are running in a 16 bit environment
  192. if((sizeof(INT) == 2) && (pIn->vt == VT_INT || pIn->vt == VT_UINT))
  193. pIn->vt = VT_I2;
  194. // determine how big the data is, where to copy it from and determine
  195. // if the size needs to also be written.
  196. switch (pIn->vt) {
  197. case VT_I1:
  198. case VT_UI1:
  199. case VT_I2:
  200. case VT_BOOL:
  201. case VT_UI2: // all get handled as I2
  202. if(pIn->vt != VT_BOOL)
  203. dwType = VT_I2;
  204. dwDataSize = 2;
  205. break;
  206. case VT_R4:
  207. case VT_I4:
  208. case VT_INT:
  209. case VT_UINT:
  210. case VT_UI4:
  211. if(pIn->vt != VT_R4)
  212. dwType = VT_I4;
  213. dwDataSize = 4;
  214. break;
  215. case VT_I8:
  216. case VT_UI8:
  217. case VT_R8:
  218. case VT_CY:
  219. case VT_DATE:
  220. if(pIn->vt == VT_UI8)
  221. dwType = VT_I8;
  222. dwDataSize = 8;
  223. break;
  224. case VT_LPSTR:
  225. dwDataSize = lstrlenA((char *)pData)+1;
  226. bSizeNeeded = TRUE;
  227. break;
  228. case VT_LPWSTR:
  229. dwDataSize = 2*(lstrlenW((WCHAR *)pData)+1);
  230. bSizeNeeded = TRUE;
  231. break;
  232. case VT_BSTR:
  233. if(sizeof(OLECHAR) == 2)
  234. dwDataSize = 2*(lstrlenW((WCHAR *)pData)+1);
  235. else
  236. dwDataSize = lstrlenA((char *)pData)+1;
  237. bSizeNeeded = TRUE;
  238. break;
  239. default:
  240. return FALSE;
  241. }
  242. // Set the desired values
  243. if(pType)
  244. *pType = dwType;
  245. if(pDataSize)
  246. *pDataSize = dwDataSize;
  247. if(pSizeNeeded)
  248. *pSizeNeeded = bSizeNeeded;
  249. return TRUE;
  250. }
  251. //***************************************************************************
  252. //
  253. // CImpComp::CImpComp
  254. //
  255. // Constructor. Doesnt do much except call base class constructor.
  256. //
  257. //***************************************************************************
  258. CImpComp::CImpComp(LPUNKNOWN pUnkOuter) : CImpDyn(pUnkOuter)
  259. {
  260. return;
  261. }
  262. //***************************************************************************
  263. //
  264. // CImpComp::ConvertGetData
  265. //
  266. // Converts the data from the property set into the format desired by
  267. // the caller.
  268. //
  269. //***************************************************************************
  270. void CImpComp::ConvertGetData(MODYNPROP *pMo,char * pData,DWORD dwType)
  271. {
  272. HRESULT sc;
  273. OLECHAR * poTemp = NULL;
  274. GUID * piid;
  275. int iCat;
  276. DWORD dwLen = dwSkipSize(pData,dwType,iCat);
  277. // TODO, remove this temporary stuff!!!
  278. DWORD dwSave = pMo->dwType;
  279. if(pMo->dwType == M_TYPE_LPSTR)
  280. pMo->dwType = VT_LPSTR;
  281. else if(pMo->dwType == M_TYPE_DWORD)
  282. pMo->dwType = VT_UINT;
  283. else if(pMo->dwType == M_TYPE_INT64)
  284. pMo->dwType = VT_I8;
  285. else {
  286. pMo->dwResult = M_INVALID_TYPE;
  287. return;
  288. }
  289. // bail out if bad data
  290. if(iCat == UNKNOWN || pData == NULL) {
  291. pMo->dwResult = ERROR_UNKNOWN;
  292. return;
  293. }
  294. // convert the data into standard form
  295. VARIANTARG vTemp,* pvConvert;
  296. pvConvert = (VARIANTARG *)CoTaskMemAlloc(sizeof(VARIANTARG));
  297. if(pvConvert == NULL) {
  298. pMo->dwResult = WBEM_E_OUT_OF_MEMORY;
  299. return;
  300. }
  301. VariantInit(&vTemp);
  302. VariantInit(pvConvert);
  303. vTemp.cyVal.int64 = 0;
  304. pvConvert->cyVal.int64 = 0;
  305. switch(iCat) {
  306. case NORMAL:
  307. memcpy((void *)&vTemp.iVal,pData,dwLen);
  308. vTemp.vt = (VARTYPE)dwType;
  309. break;
  310. case STRING:
  311. vTemp.bstrVal = (BSTR)(pData + sizeof(DWORD));
  312. vTemp.vt = VT_LPSTR;
  313. break;
  314. case WSTRING:
  315. vTemp.bstrVal = (BSTR)(pData + sizeof(DWORD));
  316. vTemp.vt = VT_LPWSTR;
  317. break;
  318. case DBLOB:
  319. vTemp.bstrVal = (BSTR)pData; // TODO, check on this!
  320. vTemp.vt = VT_BLOB;
  321. break;
  322. case DCLSID:
  323. piid = (GUID * )pData;
  324. sc = StringFromIID(*piid,&poTemp); //todo, error checking!
  325. vTemp.bstrVal = (BSTR)poTemp;
  326. if(sizeof(OLECHAR) == 1)
  327. vTemp.vt = VT_LPSTR;
  328. else
  329. vTemp.vt = VT_LPWSTR;
  330. break;
  331. }
  332. sc = OMSVariantChangeType(pvConvert,&vTemp,0,(VARTYPE)pMo->dwType);
  333. if(poTemp)
  334. CoTaskMemFree(poTemp);
  335. // note, that the variant memory is not freeded here since it is
  336. // actually "owned" by the CProp object which will free it.
  337. if(sc != S_OK) {
  338. pMo->dwResult = sc;
  339. return;
  340. }
  341. //todo, in the future, the size should just be s
  342. // sizeof VARIANTARG! AND WE SHOULD RETURN THE VARIANT
  343. // POINTER AND NOT THE DATA!!!!!
  344. int iSize = sizeof(VARIANTARG);
  345. if(pMo->dwType == VT_LPSTR)
  346. iSize = lstrlen((LPTSTR)pvConvert->pbstrVal) + 1;
  347. if(pMo->dwType == VT_LPWSTR)
  348. iSize = 2*wcslen((WCHAR *)pvConvert->pbstrVal) + 2;
  349. if(pMo->dwType == VT_BSTR)
  350. iSize = 2*wcslen((WCHAR *)pvConvert->pbstrVal) + 6;
  351. pMo->pPropertyValue = CoTaskMemAlloc(iSize);
  352. // check for errors
  353. if(pMo->pPropertyValue == NULL){
  354. pMo->dwResult = WBEM_E_OUT_OF_MEMORY;
  355. }
  356. else {
  357. if(pMo->dwType != VT_LPSTR)
  358. memcpy(pMo->pPropertyValue,(void *)&pvConvert->iVal,iSize);
  359. else
  360. memcpy(pMo->pPropertyValue,(void *)pvConvert->pbstrVal,iSize);
  361. pMo->dwResult = ERROR_SUCCESS;
  362. }
  363. pMo->dwType = dwSave ;
  364. }
  365. //***************************************************************************
  366. //
  367. // CImpComp::DoSetData
  368. //
  369. // Conversts the property data into propset format and writes it out.
  370. //
  371. //***************************************************************************
  372. void CImpComp::DoSetData(MODYNPROP *pMo,int iIndex,CProp * pProp,
  373. CPropSet * pSet,GUID fmtid,int iPid,LPSTREAM pIStream)
  374. {
  375. BOOL bExisting = TRUE;
  376. CBuff OutBuff;
  377. DWORD dwType;
  378. // If the property doesnt exist, I.e, its new, then create it
  379. if(pProp == NULL) {
  380. bExisting = FALSE;
  381. pProp = new CProp;
  382. if(pProp == NULL) {
  383. pMo->dwResult = WBEM_E_OUT_OF_MEMORY;
  384. return;
  385. }
  386. pSet->AddProperty(fmtid,pProp);
  387. }
  388. // TODO REMOVE, TEMP CODE, create variant
  389. VARIANTARG vIn;
  390. VariantInit(&vIn);
  391. vIn.cyVal.int64 = 0;
  392. if(pMo->dwType == M_TYPE_DWORD){
  393. vIn.vt = VT_I4;
  394. vIn.lVal = *(DWORD *)pMo->pPropertyValue;
  395. }
  396. else if(pMo->dwType == M_TYPE_LPSTR){
  397. vIn.vt = VT_LPSTR;
  398. vIn.bstrVal = (BSTR)pMo->pPropertyValue;
  399. }
  400. else {
  401. pMo->dwResult = M_TYPE_NOT_SUPPORTED;
  402. return;
  403. }
  404. // TODO REMOVE, TEMP CODE,
  405. if(iIndex >= 0) {
  406. // Get the data for an array
  407. if(!bCreateWriteArray(&vIn,&OutBuff,pMo,iIndex,dwType,
  408. bExisting,pProp)) {
  409. return;
  410. }
  411. }
  412. else {
  413. if(!bGetVariantStats(&vIn, &dwType, NULL, NULL)) {
  414. pMo->dwResult = ERROR_UNKNOWN; // bad input data
  415. return;
  416. }
  417. AddVariantData(&vIn,&OutBuff);
  418. /* temp stuff to generate a sample vector
  419. dwType = VT_VARIANT | VT_VECTOR;
  420. DWORD dwCnt = 3;
  421. OutBuff.Add((void *)&dwCnt, 4);
  422. DWORD dwT = VT_I4;
  423. OutBuff.Add((void *)&dwT, 4);
  424. DWORD dwData = 0x1234;
  425. OutBuff.Add((void *)&dwData, 4);
  426. dwT = VT_I2;
  427. dwData = 1;
  428. OutBuff.Add((void *)&dwT, 4);
  429. OutBuff.Add((void *)&dwData, 2);
  430. dwData = 2;
  431. OutBuff.Add((void *)&dwT, 4);
  432. OutBuff.Add((void *)&dwData, 2);
  433. end of temp stuff */
  434. }
  435. if(!OutBuff.bOK())
  436. pMo->dwResult = WBEM_E_OUT_OF_MEMORY; // bad input data
  437. else {
  438. pProp->Set(iPid, OutBuff.Get(),dwType,OutBuff.GetSize());
  439. pSet->WriteToStream(pIStream);
  440. }
  441. //xxx pIStream->Commit(STGC_OVERWRITE);
  442. return;
  443. }
  444. //***************************************************************************
  445. //
  446. // CImpComp::dwSkip
  447. //
  448. // Returns the size of a data element. Also sets the iCat reference to
  449. // indicate the category of the data type.
  450. //
  451. //***************************************************************************
  452. DWORD CImpComp::dwSkipSize(char *pData,DWORD dwType, int & iCat)
  453. {
  454. DWORD cbItem, cbVariant = 0;
  455. DWORD * dwp;
  456. iCat = NORMAL;
  457. dwType &= ~VT_VECTOR;
  458. if(dwType == VT_VARIANT) {
  459. dwp = (DWORD *)pData;
  460. dwType = *dwp;
  461. pData += sizeof(DWORD);
  462. cbVariant = sizeof(DWORD);
  463. }
  464. switch (dwType)
  465. {
  466. case VT_EMPTY: // nothing
  467. cbItem = 0;
  468. break;
  469. case VT_I2: // 2 byte signed int
  470. case VT_BOOL: // True=-1, False=0
  471. cbItem = 2;
  472. break;
  473. case VT_I4: // 4 byte signed int
  474. case VT_R4: // 4 byte real
  475. cbItem = 4;
  476. break;
  477. case VT_R8: // 8 byte real
  478. case VT_CY: // currency
  479. case VT_DATE: // date
  480. case VT_I8: // signed 64-bit int
  481. case VT_FILETIME: // FILETIME
  482. cbItem = 8;
  483. break;
  484. case VT_LPSTR: // null terminated string
  485. case VT_BSTR: // binary string
  486. case VT_BLOB: // Length prefixed bytes
  487. case VT_BLOB_OBJECT: // Blob contains an object
  488. case VT_BLOB_PROPSET: // Blob contains a propset
  489. // Read the DWORD that gives us the size, making
  490. // sure we increment cbValue.
  491. dwp = (DWORD *)pData;
  492. cbItem = sizeof(DWORD)+ *dwp;
  493. if(dwType != VT_BLOB && dwType != VT_BLOB_OBJECT &&
  494. dwType != VT_BLOB_PROPSET)
  495. iCat = STRING;
  496. else
  497. iCat = DBLOB;
  498. for(;cbItem % 4; cbItem++); // round up to 4 byte boundry
  499. break;
  500. case VT_LPWSTR: // UNICODE string
  501. dwp = (DWORD *)pData;
  502. cbItem = sizeof(DWORD)+ (*dwp) * sizeof(WCHAR);
  503. iCat = WSTRING;
  504. for(;cbItem % 4; cbItem++); // round up to 4 byte boundry
  505. break;
  506. case VT_CLSID: // A Class ID
  507. cbItem = sizeof(CLSID);
  508. iCat = DCLSID;
  509. break;
  510. default:
  511. iCat = UNKNOWN;
  512. cbItem = 0;
  513. }
  514. return cbItem + cbVariant;
  515. }
  516. //***************************************************************************
  517. //
  518. // CImpComp::EndBatch
  519. //
  520. // Called at the end of a batch of Refrest/Update Property calls. Free up
  521. // any cached handles and then delete the handle cache.
  522. //
  523. //***************************************************************************
  524. void CImpComp::EndBatch(MODYNPROP * pMo,CObject *pObj,DWORD dwListSize,BOOL bGet)
  525. {
  526. if(pObj != NULL) {
  527. Free(0,(CHandleCache *)pObj);
  528. delete pObj;
  529. }
  530. }
  531. //***************************************************************************
  532. //
  533. // CImpComp::ExtractData
  534. //
  535. // Gets the property objects data and returns a pointer to it. This is
  536. // complicated since the data may be a vector (array) or the data might
  537. // be a variant, or even a vectory of variants.
  538. //
  539. // Returns a pointer to the data and also sets the dwType reference to
  540. // indicate the type. Note that the type refernce indicates the acutal
  541. // data and does not include the vector bit or the fact that the data
  542. // may be a variant.
  543. //
  544. //***************************************************************************
  545. void * CImpComp::ExtractData( CProp * pProp,DWORD & dwType,int iIndex, BOOL bRaw)
  546. {
  547. // Get the type and data
  548. char * pRet;
  549. int iIgnore;
  550. pRet = (char *)pProp->Get();
  551. dwType = pProp->GetType();
  552. // if the type is a vector, then step into the data. Ie if there are
  553. // 10 elements and we want the 5th, step over the first four
  554. if(dwType & VT_VECTOR) {
  555. DWORD dwCnt;
  556. DWORD * dwpNumVec = (DWORD *)pRet; // first dword is num elements
  557. pRet += sizeof(DWORD);
  558. if(iIndex == -1 || (unsigned)iIndex >= *dwpNumVec)
  559. return NULL;
  560. for(dwCnt = 0; dwCnt < (unsigned)iIndex; dwCnt++)
  561. pRet += dwSkipSize(pRet,dwType, iIgnore);
  562. }
  563. dwType &= ~VT_VECTOR;
  564. // If the data type is VARIANT, then get the actual type out of
  565. // the variant structure and increment the pointer past it.
  566. if(dwType == VT_VARIANT && !bRaw) {
  567. DWORD *dwp = (DWORD *)pRet;
  568. dwType = *dwp;
  569. pRet += sizeof(DWORD);
  570. }
  571. return pRet;
  572. }
  573. //***************************************************************************
  574. //
  575. // CImpComp::Free
  576. //
  577. // Frees up cached registry handles starting with position
  578. // iStart till the end. After freeing handles, the cache object
  579. // member function is used to delete the cache entries.
  580. //
  581. //***************************************************************************
  582. void CImpComp::Free(int iStart, CHandleCache * pCache)
  583. {
  584. int iCurr,iLast;
  585. iLast = pCache->lGetNumEntries()-1;
  586. for(iCurr = iLast; iCurr >= iStart; iCurr--) {
  587. LPSTORAGE pIStorage = (LPSTORAGE)pCache->hGetHandle(iCurr);
  588. // if(iCurr == 0)
  589. // pIStorage->Commit(STGC_OVERWRITE);
  590. if(pIStorage != NULL)
  591. pIStorage->Release();
  592. }
  593. pCache->Delete(iStart); // get cache to delete the entries
  594. }
  595. //***************************************************************************
  596. //
  597. // CImpComp::GetData
  598. //
  599. // Gets a pointer to a property object and then calls the conversion
  600. // routines to convert the properties data. Note that some properties
  601. // are stream or storage names and so this routine may be called
  602. // recursively to get the acutual data.
  603. //
  604. //***************************************************************************
  605. void CImpComp::GetData(MODYNPROP * pMo, CProvObj & ProvObj, int iToken,
  606. LPSTORAGE pIStore, LPSTREAM pIStream, BOOL bGet, BOOL bNewStream)
  607. {
  608. SCODE hr;
  609. COleString sTemp;
  610. DWORD dwType;
  611. void * pData;
  612. // create a property set object
  613. CPropSet Set;
  614. GUID fmtid;
  615. if(!bNewStream) {
  616. BOOL bRet = Set.ReadFromStream(pIStream);
  617. if(bRet == 0) {
  618. pMo->dwResult = ERROR_UNKNOWN; //bad stream, probably bad mapping
  619. return;
  620. }
  621. }
  622. // Get the property.
  623. sTemp = ProvObj.sGetToken(iToken++);
  624. hr = IIDFromString(sTemp,&fmtid);
  625. if(hr != S_OK) {
  626. pMo->dwResult = ERROR_UNKNOWN;
  627. return;
  628. }
  629. int iPid = ProvObj.iGetIntExp(iToken,0,pMo->dwOptArrayIndex);
  630. if(iPid == -1) {
  631. pMo->dwResult = ERROR_UNKNOWN; // bad mapping string!
  632. return;
  633. }
  634. CProp * pProp = Set.GetProperty(fmtid,iPid);
  635. int iIndex = ProvObj.iGetIntExp(iToken,1,pMo->dwOptArrayIndex);
  636. if(bGet) {
  637. // Get the data, it might be complicated if the property is an array
  638. // etc.
  639. if(pProp == NULL) {
  640. pMo->dwResult = ERROR_UNKNOWN; // bad mapping string!
  641. return;
  642. }
  643. pData = ExtractData(pProp, dwType,iIndex,FALSE);
  644. if(pData == NULL)
  645. pMo->dwResult = ERROR_UNKNOWN; // bad mapping string!
  646. else
  647. ConvertGetData(pMo, (char *)pData, dwType);
  648. }
  649. else
  650. DoSetData(pMo, iIndex, pProp, &Set,fmtid, iPid, pIStream);
  651. return;
  652. }
  653. //***************************************************************************
  654. //
  655. // CImpComp::GetProp
  656. //
  657. // Gets the value of a single property from an Ole Compound file
  658. //
  659. //***************************************************************************
  660. void CImpComp::GetProp(MODYNPROP * pMo, CProvObj & ProvObj,CObject * pPackage)
  661. {
  662. int iCnt;
  663. int iNumSkip; // number of handles already provided by cache.
  664. SCODE hr;
  665. int iLast;
  666. CHandleCache * pCache = (CHandleCache *)pPackage;
  667. CString sRoot,sRet;
  668. COleString soTemp;
  669. LPSTORAGE pCurr,pNew;
  670. LPSTREAM pIStream;
  671. // Do a second parse on the provider string. The initial parse
  672. // is done by the calling routine and it's first token is
  673. // the path. The path token is then parsed
  674. // into StorePath and it will have a token for each part of the
  675. // storage path.
  676. CProvObj StorePath(ProvObj.sGetFullToken(1),SUB_DELIM);
  677. pMo->dwResult = StorePath.dwGetStatus();
  678. if(pMo->dwResult != WBEM_NO_ERROR)
  679. return;
  680. // Get the root storage (ie, the file) and possibly other substorages
  681. // if available in the cache.
  682. pMo->dwResult = GetRoot(&pCurr,StorePath,ProvObj.sGetFullToken(0),
  683. pCache,iNumSkip,TRUE);
  684. if(pMo->dwResult != ERROR_SUCCESS)
  685. return;
  686. pIStream = (LPSTREAM)pCurr; // just in case cache matched all the way.
  687. // Go down the storage path till we get to the stream
  688. iLast = StorePath.iGetNumTokens() -1;
  689. for(iCnt = iNumSkip; iCnt <= iLast; iCnt ++) {
  690. soTemp = StorePath.sGetToken(iCnt);
  691. if(iCnt == iLast) {
  692. // the last entry in the path specifies the stream
  693. hr = pCurr->OpenStream(soTemp,NULL,
  694. STGM_READ|STGM_SHARE_EXCLUSIVE,
  695. 0,&pIStream);
  696. if(hr != S_OK) {
  697. pMo->dwResult = hr; // bad storage name!
  698. return;
  699. }
  700. pMo->dwResult = pCache->lAddToList(soTemp,pIStream);
  701. if(pMo->dwResult != WBEM_NO_ERROR)
  702. return;
  703. }
  704. else {
  705. hr = pCurr->OpenStorage(soTemp,NULL,
  706. STGM_READ|STGM_SHARE_EXCLUSIVE,
  707. NULL,0,&pNew);
  708. if(hr != S_OK) {
  709. pMo->dwResult = hr; // bad storage name!
  710. return;
  711. }
  712. pMo->dwResult = pCache->lAddToList(soTemp,pNew);
  713. if(pMo->dwResult != WBEM_NO_ERROR)
  714. return;
  715. pCurr = pNew;
  716. }
  717. }
  718. // Finish up getting the data.
  719. GetData(pMo,ProvObj,2, pNew, pIStream, TRUE);
  720. return;
  721. }
  722. //***************************************************************************
  723. //
  724. // CImpComp::GetRoot
  725. //
  726. // Sets the pointer to an open storage. Typically this is the root storage,
  727. // but it might be a substorage if the path matches the storages in the
  728. // cachee.
  729. // Returns 0 if OK, otherwise return is error code. Also the storage
  730. // pointer is set as well as the number of substorages to skip in
  731. // cases where the cache is being used.
  732. //
  733. //***************************************************************************
  734. int CImpComp::GetRoot(LPSTORAGE * pRet,CProvObj & Path,const TCHAR * pNewFilePath,CHandleCache * pCache,int & iNumSkip,BOOL bGet)
  735. {
  736. *pRet = NULL;
  737. int iRet;
  738. iNumSkip = 0;
  739. LPSTORAGE pIStorage;
  740. SCODE hr;
  741. if(pCache->lGetNumEntries() > 0){ //I.e. in use
  742. const TCHAR * pOldFilePath = pCache->sGetString(0);
  743. if(lstrcmpi(pOldFilePath,pNewFilePath)) //todo, handle nulls here!
  744. // If the file path has changed, free all
  745. // the cached handles and get a new root
  746. Free(0,pCache);
  747. else {
  748. // FilePath is in common.
  749. // determine how much else is in
  750. // common, free what isnt in common,
  751. // return handle of best match.
  752. iNumSkip = pCache->lGetNumMatch(1,0,Path);
  753. Free(1+iNumSkip,pCache);
  754. *pRet = (LPSTORAGE)pCache->hGetHandle(1+iNumSkip);
  755. return ERROR_SUCCESS;
  756. }
  757. }
  758. // If the is a Set, and the file doesnt exist, create it
  759. COleString sNew;
  760. sNew = pNewFilePath;
  761. if(!bGet)
  762. if(NOERROR != StgIsStorageFile(sNew)) {
  763. hr = StgCreateDocfile(sNew,
  764. STGM_READWRITE|STGM_SHARE_DENY_WRITE|STGM_CREATE,
  765. 0L, &pIStorage);
  766. if(hr == S_OK) {
  767. iRet = pCache->lAddToList(pNewFilePath,pIStorage);
  768. if(iRet)
  769. return iRet;
  770. *pRet = pIStorage;
  771. }
  772. return hr;
  773. }
  774. // open an existing file
  775. hr = StgOpenStorage(sNew,NULL,
  776. (bGet) ? GET_FLAGS : PUT_FLAGS,
  777. NULL,0L, &pIStorage);
  778. if(hr == S_OK){
  779. hr = pCache->lAddToList(pNewFilePath,pIStorage);
  780. *pRet = pIStorage;
  781. }
  782. return hr;
  783. }
  784. //***************************************************************************
  785. //
  786. // CImpComp::SetProp
  787. //
  788. // Writes the value of a single property into an Ole Compound file
  789. //
  790. //***************************************************************************
  791. void CImpComp::SetProp(MODYNPROP * pMo, CProvObj & ProvObj,CObject * pPackage)
  792. {
  793. int iCnt;
  794. int iNumSkip; // number of handles already provided by cache.
  795. SCODE hr;
  796. int iLast;
  797. CHandleCache * pCache = (CHandleCache *)pPackage;
  798. CString sRoot,sRet;
  799. COleString soTemp;
  800. LPSTORAGE pCurr,pNew;
  801. LPSTREAM pIStream;
  802. BOOL bStreamCreated = FALSE;
  803. // Do a second parse on the provider string. The initial parse
  804. // is done by the calling routine and it's first token is
  805. // the path. The path token is then parsed
  806. // into StorePath and it will have a token for each part of the
  807. // storage path.
  808. CProvObj StorePath(ProvObj.sGetFullToken(1),SUB_DELIM);
  809. pMo->dwResult = StorePath.dwGetStatus();
  810. if(pMo->dwResult != WBEM_NO_ERROR)
  811. return;
  812. // Get the root storage (ie, the file) and possibly other substorages
  813. // if available in the cache.
  814. pMo->dwResult = GetRoot(&pCurr,StorePath,ProvObj.sGetFullToken(0),
  815. pCache,iNumSkip,FALSE);
  816. if(pMo->dwResult != ERROR_SUCCESS)
  817. return;
  818. pIStream = (LPSTREAM)pCurr; // just in case cache matched all the way.
  819. // Go down the storage path till we get to the stream
  820. iLast = StorePath.iGetNumTokens() -1;
  821. for(iCnt = iNumSkip; iCnt <= iLast; iCnt ++) {
  822. soTemp = StorePath.sGetToken(iCnt);
  823. if(iCnt == iLast) {
  824. // the last entry in the path specifies the stream
  825. hr = pCurr->OpenStream(soTemp,NULL,
  826. STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
  827. 0,&pIStream);
  828. if(hr == STG_E_FILENOTFOUND) {
  829. bStreamCreated = TRUE;
  830. hr = pCurr->CreateStream(soTemp,
  831. STGM_READWRITE|STGM_SHARE_EXCLUSIVE|STGM_FAILIFTHERE,
  832. 0,0,&pIStream);
  833. }
  834. if(hr != S_OK) {
  835. pMo->dwResult = hr; // bad storage name!
  836. return;
  837. }
  838. pMo->dwResult = pCache->lAddToList(soTemp,pIStream);
  839. if(pMo->dwResult != WBEM_NO_ERROR)
  840. return;
  841. }
  842. else {
  843. hr = pCurr->OpenStorage(soTemp,NULL,
  844. STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
  845. NULL,0,&pNew);
  846. if(hr == STG_E_FILENOTFOUND)
  847. hr = pCurr->CreateStorage(soTemp,
  848. STGM_READWRITE|STGM_SHARE_EXCLUSIVE|STGM_FAILIFTHERE,
  849. 0,0,&pNew);
  850. if(hr != S_OK) {
  851. pMo->dwResult = hr; // bad storage name!
  852. return;
  853. }
  854. pMo->dwResult = pCache->lAddToList(soTemp,pNew);
  855. if(pMo->dwResult != WBEM_NO_ERROR)
  856. return;
  857. pCurr = pNew;
  858. }
  859. }
  860. // Finish up getting the data.
  861. GetData(pMo,ProvObj,2, pNew, pIStream, FALSE, bStreamCreated);
  862. return;
  863. }
  864. //***************************************************************************
  865. //
  866. // CImpComp::StartBatch
  867. //
  868. // Called at the start of a batch of Refrest/Update Property calls. Initialize
  869. // the handle cache.
  870. //
  871. //***************************************************************************
  872. void CImpComp::StartBatch(MODYNPROP * pMo,CObject **pObj,DWORD dwListSize,BOOL bGet)
  873. {
  874. *pObj = new CHandleCache;
  875. }