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.

737 lines
21 KiB

  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft WMIOLE DB Provider
  4. //
  5. // (C) Copyright 2000-1999 Microsoft Corporation. All Rights Reserved.
  6. //
  7. // IBindResource.CPP CImplIBindResource interface implementation
  8. //
  9. ///////////////////////////////////////////////////////////////////////////
  10. #include "headers.h"
  11. ////////////////////////////////////////////////////////////////////////////////
  12. // Method of the IBindResource which binds the requested URL
  13. // Returns one of the following values:
  14. // S_OK Bind succeeded
  15. // DB_S_ERRORSOCCURRED Bind succeeded, but some bind flags
  16. // or properties were not satisfied
  17. // DB_E_NOAGGREGATION Aggregation not supported by the
  18. // object requested
  19. // DB_E_NOTFOUND Object requested as from URL not found
  20. // DB_E_OBJECTMISMATCH The object requested and the URL passed
  21. // does not match
  22. // DB_SEC_E_PERMISSIONDENIED User does not have permission for the
  23. // object requested
  24. // E_FAIL Other error ( WMI specifice errors)
  25. // E_INVALIDARG one or more arguments are not valid
  26. // E_NOINTERFACE The interface requested is not supported
  27. // E_UNEXPECTED unexpected error
  28. // NOTE: This should be allowed for only Scopes as the path of the objects in
  29. // scope have the path of the scope in which they are and make sense only for
  30. // that. In case of objects in container, these objects can be in as many
  31. // container as it wants and its path need not be dependent on the containee
  32. ////////////////////////////////////////////////////////////////////////////////
  33. STDMETHODIMP CImpIScopedOperations::Bind(IUnknown * pUnkOuter,
  34. LPCOLESTR pwszURL,
  35. DBBINDURLFLAG dwBindURLFlags,
  36. REFGUID rguid,
  37. REFIID riid,
  38. IAuthenticate * pAuthenticate,
  39. DBIMPLICITSESSION * pImplSession,
  40. DBBINDURLSTATUS * pdwBindStatus,
  41. IUnknown ** ppUnk)
  42. {
  43. HRESULT hr = DB_E_NOTSUPPORTED;
  44. WCHAR * pstrUrl = NULL;
  45. CSetStructuredExceptionHandler seh;
  46. // Bind is allowed only for Scopes
  47. if(!m_pObj->IsContainer())
  48. {
  49. TRY_BLOCK;
  50. // Serialize the object
  51. CAutoBlock cab(m_pObj->GetCriticalSection());
  52. g_pCError->ClearErrorInfo();
  53. // If URL is NULL return Invalid Argument
  54. if(pwszURL == NULL)
  55. {
  56. hr = E_INVALIDARG;
  57. }
  58. else
  59. {
  60. try
  61. {
  62. // Allocate the string
  63. pstrUrl = new WCHAR[wcslen(pwszURL) + 1];
  64. hr = S_OK;
  65. }
  66. catch(...)
  67. {
  68. SAFE_DELETE_PTR(pstrUrl);
  69. }
  70. wcscpy(pstrUrl,pwszURL);
  71. if(SUCCEEDED(hr = CheckIfProperURL(pstrUrl,rguid)))
  72. {
  73. if( pUnkOuter != NULL && riid != IID_IUnknown)
  74. {
  75. hr = DB_E_NOAGGREGATION;
  76. }
  77. else
  78. {
  79. //========================================================================
  80. // Calling this to bind the URL to the appropriate object
  81. //========================================================================
  82. hr = BindURL(pUnkOuter,pstrUrl,dwBindURLFlags,rguid,riid,pImplSession,pdwBindStatus,ppUnk);
  83. }
  84. }
  85. SAFE_DELETE_ARRAY(pstrUrl);
  86. }
  87. CATCH_BLOCK_HRESULT(hr,L"IScopedOperations::Bind");
  88. }
  89. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IBindResource);
  90. return hr;
  91. }
  92. ////////////////////////////////////////////////////////////////////////////////
  93. // Copy link from one container to another container
  94. // Returns one of the following values:
  95. ////////////////////////////////////////////////////////////////////////////////
  96. STDMETHODIMP CImpIScopedOperations::Copy(DBCOUNTITEM cRows,
  97. LPCOLESTR __RPC_FAR rgpwszSourceURLs[ ],
  98. LPCOLESTR __RPC_FAR rgpwszDestURLs[ ],
  99. DWORD dwCopyFlags,
  100. IAuthenticate __RPC_FAR *pAuthenticate,
  101. DBSTATUS __RPC_FAR rgdwStatus[ ],
  102. LPOLESTR __RPC_FAR rgpwszNewURLs[ ],
  103. OLECHAR __RPC_FAR *__RPC_FAR *ppStringsBuffer)
  104. {
  105. HRESULT hr = S_OK;
  106. CSetStructuredExceptionHandler seh;
  107. TRY_BLOCK;
  108. // Seriliaze the object
  109. CAutoBlock cab(m_pObj->GetCriticalSection());
  110. // Clear Error information
  111. g_pCError->ClearErrorInfo();
  112. if(!m_pObj->IsContainer() && !(dwCopyFlags & DBCOPY_NON_RECURSIVE))
  113. {
  114. hr = DB_E_NOTSUPPORTED;
  115. LogMessage("Copy of the entire sub tree is not supported for Scopes");
  116. }
  117. else
  118. if(cRows)
  119. {
  120. //======================================================================================================
  121. // The last parameter specifies ManipulateObjects to Copy objects from one scope/contianer to another
  122. //======================================================================================================
  123. ManipulateObjects(cRows,rgpwszSourceURLs,rgpwszDestURLs,rgdwStatus,rgpwszNewURLs,ppStringsBuffer,FALSE);
  124. }
  125. CATCH_BLOCK_HRESULT(hr,L"IScopedOperations::Copy");
  126. return hr;
  127. }
  128. ////////////////////////////////////////////////////////////////////////////////
  129. // Moving item from one container to another container
  130. // Returns one of the following values:
  131. ////////////////////////////////////////////////////////////////////////////////
  132. STDMETHODIMP CImpIScopedOperations::Move(DBCOUNTITEM cRows,
  133. LPCOLESTR __RPC_FAR rgpwszSourceURLs[ ],
  134. LPCOLESTR __RPC_FAR rgpwszDestURLs[ ],
  135. DWORD dwMoveFlags,
  136. IAuthenticate __RPC_FAR *pAuthenticate,
  137. DBSTATUS __RPC_FAR rgdwStatus[ ],
  138. LPOLESTR __RPC_FAR rgpwszNewURLs[ ],
  139. OLECHAR __RPC_FAR *__RPC_FAR *ppStringsBuffer)
  140. {
  141. HRESULT hr = S_OK;
  142. CSetStructuredExceptionHandler seh;
  143. // Seriliaze the object
  144. CAutoBlock cab(m_pObj->GetCriticalSection());
  145. // Clear Error information
  146. g_pCError->ClearErrorInfo();
  147. ppStringsBuffer = NULL;
  148. TRY_BLOCK
  149. if(!m_pObj->IsContainer())
  150. {
  151. hr = DB_E_NOTSUPPORTED;
  152. LogMessage("Move not supported on a scope object");
  153. }
  154. else
  155. if(cRows)
  156. {
  157. //======================================================================================================
  158. // The last parameter specifies ManipulateObjects to Move objects from one contianer to another
  159. //======================================================================================================
  160. hr = ManipulateObjects(cRows,rgpwszSourceURLs,rgpwszDestURLs,rgdwStatus,rgpwszNewURLs,ppStringsBuffer,TRUE);
  161. }
  162. CATCH_BLOCK_HRESULT(hr,L"IScopedOperations::Move");
  163. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IBindResource);
  164. return hr;
  165. }
  166. ////////////////////////////////////////////////////////////////////////////////
  167. // Deleting objects from container. This can also be used to delete
  168. // items from scope
  169. // Returns one of the following values:
  170. ////////////////////////////////////////////////////////////////////////////////
  171. STDMETHODIMP CImpIScopedOperations::Delete(DBCOUNTITEM cRows,
  172. LPCOLESTR __RPC_FAR rgpwszURLs[ ],
  173. DWORD dwDeleteFlags,
  174. DBSTATUS __RPC_FAR rgdwStatus[ ])
  175. {
  176. HRESULT hr = S_OK;
  177. BOOL bContainer = FALSE;
  178. DBSTATUS dbStatus;
  179. DBCOUNTITEM cError = 0;
  180. WCHAR * pstrUrl = NULL;
  181. CSetStructuredExceptionHandler seh;
  182. // Seriliaze the object
  183. CAutoBlock cab(m_pObj->GetCriticalSection());
  184. // Clear Error information
  185. g_pCError->ClearErrorInfo();
  186. if(cRows > 0)
  187. {
  188. TRY_BLOCK
  189. for ( DBCOUNTITEM item = 0 ; item < cRows ; item++)
  190. {
  191. dbStatus = DBSTATUS_S_OK;
  192. try
  193. {
  194. // Allocate the string
  195. pstrUrl = new WCHAR[wcslen(rgpwszURLs[item]) + 1];
  196. }
  197. catch(...)
  198. {
  199. SAFE_DELETE_PTR(pstrUrl);
  200. }
  201. if(pstrUrl)
  202. {
  203. memset(pstrUrl,0,(wcslen(rgpwszURLs[item]) + 1) * sizeof(WCHAR));
  204. hr = S_OK;
  205. wcscpy(pstrUrl,rgpwszURLs[item]);
  206. }
  207. else
  208. {
  209. hr = E_OUTOFMEMORY;
  210. break;
  211. }
  212. //=============================================
  213. // check if the URL passed is valid
  214. //=============================================
  215. if(SUCCEEDED(hr = CheckIfProperURL(pstrUrl,DBGUID_ROW)))
  216. {
  217. //======================================================
  218. // call this function to delete the object passed
  219. // refered in the URL
  220. //======================================================
  221. if(FAILED(m_pObj->Delete(pstrUrl,dwDeleteFlags,dbStatus)))
  222. {
  223. cError++;
  224. }
  225. if(rgdwStatus)
  226. {
  227. rgdwStatus[item] = dbStatus;
  228. }
  229. }
  230. else
  231. {
  232. if(rgdwStatus)
  233. {
  234. rgdwStatus[item] = DBSTATUS_E_INVALIDURL;
  235. }
  236. cError++;
  237. hr = S_OK;
  238. }
  239. SAFE_DELETE_PTR(pstrUrl);
  240. } // for loop
  241. if(SUCCEEDED(hr))
  242. {
  243. hr = cError > 0 ? DB_S_ERRORSOCCURRED: S_OK;
  244. } hr = cError >= cRows ? DB_E_ERRORSOCCURRED: hr;
  245. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IBindResource);
  246. CATCH_BLOCK_HRESULT(hr,L"IScopedOperations::Delete");
  247. }
  248. return hr;
  249. }
  250. ////////////////////////////////////////////////////////////////////////////////
  251. // Opening a rowset contiang objects in scope/container
  252. // Returns one of the following values:
  253. ////////////////////////////////////////////////////////////////////////////////
  254. STDMETHODIMP CImpIScopedOperations::OpenRowset(IUnknown __RPC_FAR *pUnkOuter,
  255. DBID __RPC_FAR *pTableID,
  256. DBID __RPC_FAR *pIndexID,
  257. REFIID riid,
  258. ULONG cPropertySets,
  259. DBPROPSET __RPC_FAR rgPropertySets[ ],
  260. IUnknown __RPC_FAR *__RPC_FAR *ppRowset)
  261. {
  262. HRESULT hr = S_OK;
  263. WCHAR * pTempStr = NULL;
  264. WCHAR * pStrURL = NULL;
  265. CSetStructuredExceptionHandler seh;
  266. if( ppRowset )
  267. {
  268. *ppRowset = NULL;
  269. }
  270. TRY_BLOCK;
  271. // Seriliaze the object
  272. CAutoBlock cab(m_pObj->GetCriticalSection());
  273. // Clear Error information
  274. g_pCError->ClearErrorInfo();
  275. //=====================================================================
  276. // Check Arguments
  277. //=====================================================================
  278. if ( riid == IID_NULL)
  279. {
  280. hr = E_NOINTERFACE;
  281. // return g_pCError->PostHResult(E_NOINTERFACE,&IID_IOpenRowset) ;
  282. }
  283. else
  284. //==========================================================
  285. // We only accept NULL for pIndexID at this present time
  286. //==========================================================
  287. if( pIndexID )
  288. {
  289. hr = DB_E_NOINDEX;
  290. // return g_pCError->PostHResult(DB_E_NOINDEX,&IID_IOpenRowset) ;
  291. }
  292. else
  293. //===================================================================================
  294. // We do not allow the riid to be anything other than IID_IUnknown for aggregation
  295. //===================================================================================
  296. if ( (pUnkOuter) && (riid != IID_IUnknown) )
  297. {
  298. hr = DB_E_NOAGGREGATION;
  299. // return g_pCError->PostHResult(DB_E_NOAGGREGATION,&IID_IOpenRowset) ;
  300. }
  301. if (pTableID == NULL ||
  302. (pTableID != NULL && pTableID->eKind == DBKIND_NAME && pTableID->uName.pwszName == NULL) ||
  303. (pTableID != NULL && pTableID->eKind == DBKIND_NAME && !wcscmp(pTableID->uName.pwszName,L"") ))
  304. {
  305. pTempStr = NULL;
  306. }
  307. else
  308. {
  309. pTempStr = pTableID->uName.pwszName;
  310. }
  311. if(SUCCEEDED(hr))
  312. {
  313. if(pTempStr)
  314. {
  315. pStrURL = new WCHAR [ wcslen(pTempStr) + 1];
  316. if(pStrURL)
  317. {
  318. wcscpy(pStrURL,pTempStr);
  319. }
  320. else
  321. {
  322. hr = E_OUTOFMEMORY;
  323. }
  324. }
  325. //====================================================
  326. // Check if the URL passed is in the require format
  327. //====================================================
  328. if(SUCCEEDED(hr) && SUCCEEDED(hr =CheckIfProperURL(pStrURL,DBGUID_ROWSET)))
  329. {
  330. //==============================
  331. // Open the rowset
  332. //==============================
  333. hr = m_pObj->OpenRowset(pStrURL,pUnkOuter,riid,TRUE,ppRowset,cPropertySets,rgPropertySets);
  334. }
  335. SAFE_DELETE_ARRAY(pStrURL);
  336. }
  337. hr = hr == S_OK ? hr :g_pCError->PostHResult(hr,&IID_IScopedOperations);
  338. CATCH_BLOCK_HRESULT(hr,L"IScopedOperations::OpenRowset");
  339. return hr;
  340. }
  341. ////////////////////////////////////////////////////////////////////////////////////////////
  342. // Function which checks if the URL flags matches the requested object
  343. // This is as per the OLEDB specs
  344. ///////////////////////////////////////////////////////////////////////////////////////////
  345. BOOL CImpIScopedOperations::CheckBindURLFlags(DBBINDURLFLAG dwBindURLFlags , REFGUID rguid)
  346. {
  347. BOOL bFlag = FALSE;
  348. if( DBGUID_ROW == rguid)
  349. {
  350. bFlag = TRUE;
  351. }
  352. if( DBGUID_ROWSET == rguid)
  353. {
  354. if(!((dwBindURLFlags & DBBINDURLFLAG_DELAYFETCHCOLUMNS) || // Flags cannot have any of these two values
  355. (dwBindURLFlags & DBBINDURLFLAG_DELAYFETCHSTREAM)))
  356. bFlag = TRUE;
  357. }
  358. return bFlag;
  359. }
  360. ////////////////////////////////////////////////////////////////////////////////////////////
  361. // Function which checks if the URL is valid for the requested object
  362. ///////////////////////////////////////////////////////////////////////////////////////////
  363. HRESULT CImpIScopedOperations::CheckIfProperURL(LPOLESTR & lpszURL,REFGUID rguid)
  364. {
  365. HRESULT hr = S_OK;
  366. LONG lUrlType = -1;
  367. CURLParser urlParser;
  368. BOOL bEmptyURL = FALSE;
  369. // IScopedOperations::Bind supports binding of only
  370. // to rowset and row objects
  371. if(!(rguid == DBGUID_ROW || rguid == DBGUID_ROWSET))
  372. {
  373. hr = DB_E_NOTSUPPORTED;
  374. }
  375. else
  376. // Empty URL can be passed only for OpenRowset call
  377. if(!lpszURL && rguid != DBGUID_ROWSET)
  378. {
  379. hr = E_INVALIDARG;
  380. }
  381. else
  382. if(urlParser.IsValidURL(lpszURL) != RELATIVEURL)
  383. {
  384. bEmptyURL = (lpszURL == NULL || (lpszURL != NULL && wcslen(lpszURL) == 0));
  385. // if URL is null or empty string then the requested object has to be rowset or
  386. // if URL of the current row object and the object requested is same and if the row object is
  387. // requested then there is no meaning as the current row is reffering to the object
  388. if( (bEmptyURL && rguid != DBGUID_ROWSET)
  389. ||( wbem_wcsicmp(lpszURL,m_pObj->m_strURL) == 0 && rguid == DBGUID_ROW))
  390. {
  391. hr = E_INVALIDARG;
  392. }
  393. else
  394. {
  395. // If URL is passed then the URL should be in the scope of the current object
  396. // otherwise there error should be returned
  397. if(!bEmptyURL && SUCCEEDED(hr = urlParser.SetURL(lpszURL)))
  398. {
  399. if(wbem_wcsincmp(m_pObj->m_strURL,lpszURL,wcslen(m_pObj->m_strURL)))
  400. {
  401. hr = DB_E_RESOURCEOUTOFSCOPE;
  402. }
  403. }
  404. }
  405. }
  406. return hr;
  407. }
  408. ///////////////////////////////////////////////////////////////////////////
  409. // Function to bind the requested URL
  410. ///////////////////////////////////////////////////////////////////////////
  411. HRESULT CImpIScopedOperations::BindURL(IUnknown * pUnkOuter,
  412. LPCOLESTR pwszURL,
  413. DBBINDURLFLAG dwBindURLFlags,
  414. REFGUID rguid,
  415. REFIID riid,
  416. DBIMPLICITSESSION * pImplSession,
  417. DBBINDURLSTATUS * pdwBindStatus,
  418. IUnknown ** ppUnk)
  419. {
  420. HRESULT hr = E_FAIL;
  421. IUnknown *pTempUnk = NULL;
  422. LONG lInitFlags = 0;
  423. LONG lBindFlags = 0;
  424. REFGUID guidTemp = GUID_NULL;
  425. IUnknown* pReqestedPtr = NULL;
  426. WCHAR * pStrTemp = NULL;
  427. GetInitAndBindFlagsFromBindFlags(dwBindURLFlags,lInitFlags,lBindFlags);
  428. //=========================================================================================
  429. // If requested object is row then call function to
  430. // to create a row
  431. //=========================================================================================
  432. if( rguid == DBGUID_ROW)
  433. {
  434. pReqestedPtr = NULL;
  435. hr = m_pObj->OpenRow(pwszURL,pUnkOuter,riid,&pReqestedPtr);
  436. }
  437. //=========================================================================================
  438. // If requested object is rowset then call function to
  439. // to create a rowset
  440. //=========================================================================================
  441. if( rguid == DBGUID_ROWSET)
  442. {
  443. pReqestedPtr = NULL;
  444. // This has to be changed to path . URL should not be sent
  445. // if DBBINDURLFLAG_COLLECTION flag of bindflags is set then , it means that the rowset is to
  446. // be opened as container
  447. hr = m_pObj->OpenRowset(pStrTemp,pUnkOuter,riid,(dwBindURLFlags & DBBINDURLFLAG_COLLECTION),&pReqestedPtr);
  448. }
  449. if( SUCCEEDED(hr))
  450. {
  451. *ppUnk = pReqestedPtr;
  452. }
  453. return hr ;
  454. }
  455. //////////////////////////////////////////////////////////////////////////////////////////////
  456. // Function to Move/Copy objects from one container to another
  457. //////////////////////////////////////////////////////////////////////////////////////////////
  458. HRESULT CImpIScopedOperations::ManipulateObjects(DBCOUNTITEM cRows,
  459. LPCOLESTR __RPC_FAR rgpwszSourceURLs[ ],
  460. LPCOLESTR __RPC_FAR rgpwszDestURLs[ ],
  461. DBSTATUS __RPC_FAR rgdwStatus[ ],
  462. LPOLESTR __RPC_FAR rgpwszNewURLs[ ],
  463. OLECHAR __RPC_FAR *__RPC_FAR *ppStringsBuffer,
  464. BOOL bMoveObjects)
  465. {
  466. HRESULT hr = S_OK;
  467. WCHAR * pstrSrcURL = NULL;
  468. WCHAR * pStrDstURL = NULL;
  469. WCHAR * pstrNewURL = NULL;
  470. DBCOUNTITEM item = 0;
  471. DBCOUNTITEM cError = 0;
  472. DBSTATUS dbStatus = DBSTATUS_S_OK;
  473. // NTRaid:111804
  474. // 06/07/00
  475. WCHAR ** prgURL = NULL;
  476. if(cRows)
  477. {
  478. prgURL = new WCHAR*[cRows];
  479. // NTRaid:111803
  480. // 06/07/00
  481. if(prgURL)
  482. {
  483. for(item = 0 ; item < cRows ; item++)
  484. {
  485. prgURL[item] = NULL;
  486. }
  487. try
  488. {
  489. for ( item = 0 ; item < cRows ; item++)
  490. {
  491. dbStatus = DBSTATUS_S_OK;
  492. // Allocate the string
  493. pstrSrcURL = new WCHAR[wcslen(rgpwszSourceURLs[item]) + 1];
  494. pStrDstURL = new WCHAR[wcslen(rgpwszDestURLs[item]) + 1];
  495. // NTRaid:111805 & 111806
  496. // 06/07/00
  497. if(!pstrSrcURL || !pStrDstURL)
  498. {
  499. SAFE_DELETE_ARRAY(pstrSrcURL);
  500. SAFE_DELETE_ARRAY(pStrDstURL);
  501. SAFE_DELETE_ARRAY(prgURL);
  502. hr = E_OUTOFMEMORY;
  503. break;
  504. }
  505. else
  506. {
  507. memset(pstrSrcURL,0,(wcslen(rgpwszSourceURLs[item]) + 1) * sizeof(WCHAR));
  508. memset(pStrDstURL,0,(wcslen(rgpwszDestURLs[item]) + 1) * sizeof(WCHAR));
  509. hr = S_OK;
  510. wcscpy(pstrSrcURL,rgpwszSourceURLs[item]);
  511. wcscpy(pStrDstURL,rgpwszDestURLs[item]);
  512. if((SUCCEEDED(hr = CheckIfProperURL(pstrSrcURL,DBGUID_ROW))) &&
  513. (SUCCEEDED(hr = CheckIfProperURL(pStrDstURL,DBGUID_ROW))))
  514. {
  515. if(bMoveObjects)
  516. {
  517. hr = m_pObj->MoveObjects(pStrDstURL,pstrSrcURL,prgURL[item],dbStatus);
  518. }
  519. else
  520. {
  521. hr = m_pObj->CopyObjects(pStrDstURL,pstrSrcURL,prgURL[item],dbStatus);
  522. }
  523. if(FAILED(hr))
  524. {
  525. hr = S_OK;
  526. cError++;
  527. }
  528. else
  529. if(rgdwStatus)
  530. {
  531. rgdwStatus[item] = dbStatus;
  532. }
  533. }
  534. else
  535. {
  536. if(rgdwStatus)
  537. {
  538. rgdwStatus[item] = DBSTATUS_E_INVALIDURL;
  539. }
  540. cError++;
  541. hr = S_OK;
  542. }
  543. }
  544. SAFE_DELETE_ARRAY(pstrSrcURL);
  545. SAFE_DELETE_ARRAY(pStrDstURL);
  546. SAFE_DELETE_ARRAY(prgURL);
  547. } // for loop
  548. if(SUCCEEDED(hr))
  549. {
  550. DBCOUNTITEM lNumberOfCharacters;
  551. for(item = 0 ; item < cRows ; item++)
  552. {
  553. if(rgpwszNewURLs)
  554. {
  555. rgpwszNewURLs[item] = prgURL[item];
  556. }
  557. lNumberOfCharacters += wcslen(prgURL[item]);
  558. lNumberOfCharacters++;
  559. }
  560. //==================================================================
  561. // if the pointer is not NULL then allocate buffer for the
  562. // URL strings and fill the data
  563. //==================================================================
  564. if(ppStringsBuffer)
  565. {
  566. WCHAR *pTemp;
  567. *ppStringsBuffer = (OLECHAR *)g_pIMalloc->Alloc(lNumberOfCharacters * sizeof(WCHAR));
  568. pTemp = *ppStringsBuffer;
  569. DBLENGTH lBytesToCopy = 0;
  570. for(item = 0 ; item < cRows ; item++)
  571. {
  572. lBytesToCopy = (wcslen(prgURL[item]) + 1) * sizeof(WCHAR);
  573. memcpy(pTemp,prgURL[item],lBytesToCopy);
  574. pTemp = (WCHAR *)(((BYTE *)pTemp) + lBytesToCopy);
  575. }
  576. }
  577. //==================================================================
  578. // if the output parameter is NULL then delete all the memory
  579. // allocated
  580. //==================================================================
  581. if(!rgpwszNewURLs)
  582. {
  583. for(item = 0 ; item < cRows ; item++)
  584. {
  585. SAFE_DELETE_ARRAY(prgURL[item]);
  586. }
  587. }
  588. }
  589. }
  590. catch(...)
  591. {
  592. //=====================================
  593. // Release the memory allocated
  594. //=====================================
  595. for(item = 0 ; item < cRows ; item++)
  596. {
  597. SAFE_DELETE_ARRAY(prgURL[item]);
  598. }
  599. SAFE_DELETE_ARRAY(pstrSrcURL);
  600. SAFE_DELETE_ARRAY(pStrDstURL);
  601. SAFE_DELETE_ARRAY(prgURL);
  602. if(*ppStringsBuffer)
  603. {
  604. g_pIMalloc->Free(*ppStringsBuffer);
  605. }
  606. throw;
  607. }
  608. if(SUCCEEDED(hr))
  609. {
  610. hr = cError > 0 ? DB_S_ERRORSOCCURRED: S_OK;
  611. hr = (cError >= cRows) ? DB_E_ERRORSOCCURRED: hr;
  612. }
  613. else
  614. {
  615. if(ppStringsBuffer)
  616. {
  617. *ppStringsBuffer = NULL;
  618. }
  619. for(item = 0 ; item < cRows ; item++)
  620. {
  621. SAFE_DELETE_ARRAY(prgURL[item]);
  622. }
  623. SAFE_DELETE_ARRAY(pstrSrcURL);
  624. SAFE_DELETE_ARRAY(pStrDstURL);
  625. }
  626. SAFE_DELETE_ARRAY(prgURL);
  627. }
  628. else
  629. {
  630. hr = E_OUTOFMEMORY;
  631. }
  632. }
  633. return hr;
  634. }