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.

426 lines
13 KiB

  1. // cimpexp.cxx
  2. #include "precomp.hxx"
  3. #include <atlbase.h>
  4. #include <iadm.h>
  5. #include "coiadm.hxx"
  6. #define DEFAULT_TIMEOUT_VALUE 30000
  7. // Implementation of CImpExpHelp
  8. CADMCOMW::CImpExpHelp::CImpExpHelp()
  9. {
  10. return;
  11. }
  12. CADMCOMW::CImpExpHelp::~CImpExpHelp(void)
  13. {
  14. return;
  15. }
  16. VOID CADMCOMW::CImpExpHelp::Init(CADMCOMW *pBackObj)
  17. {
  18. // Init the Back Object Pointer to point to the parent object.
  19. m_pUnkOuter = (IUnknown*)pBackObj;
  20. return;
  21. }
  22. STDMETHODIMP CADMCOMW::CImpExpHelp::QueryInterface(
  23. REFIID riid,
  24. PPVOID ppv)
  25. {
  26. // Delegate this call to the outer object's QueryInterface.
  27. return m_pUnkOuter->QueryInterface(riid, ppv);
  28. }
  29. STDMETHODIMP_(ULONG) CADMCOMW::CImpExpHelp::AddRef(void)
  30. {
  31. // Delegate this call to the outer object's AddRef.
  32. return m_pUnkOuter->AddRef();
  33. }
  34. STDMETHODIMP_(ULONG) CADMCOMW::CImpExpHelp::Release(void)
  35. {
  36. // Delegate this call to the outer object's Release.
  37. return m_pUnkOuter->Release();
  38. }
  39. STDMETHODIMP CADMCOMW::CImpExpHelp::EnumeratePathsInFile (
  40. /* [unique, in, string] */ LPCWSTR pszFileName,
  41. /* [unique, in, string] */ LPCWSTR pszKeyType,
  42. /* [in] */ DWORD dwMDBufferSize,
  43. /* [out, size_is(dwMDBufferSize)] */ WCHAR *pszBuffer,
  44. /* [out] */ DWORD *pdwMDRequiredBufferSize)
  45. {
  46. HRESULT hr = S_OK;
  47. CComPtr<ISimpleTableDispenser2> spISTDisp;
  48. CComPtr<ISimpleTableRead2> spISTProperty;
  49. CComPtr<IErrorInfo> spErrorInfo;
  50. CComPtr<ISimpleTableRead2> spISTError;
  51. CComPtr<ICatalogErrorLogger2> spILogger;
  52. CComPtr<IAdvancedTableDispenser> spISTDispAdvanced;
  53. ULONG iRowDuplicateLocation = 0;
  54. STRAU strFileName;
  55. if ((!pszFileName)||(!*pszFileName)||(!pszKeyType))
  56. {
  57. hr = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
  58. goto done;
  59. }
  60. if (!pszBuffer)
  61. {
  62. dwMDBufferSize = 0;
  63. }
  64. hr = CoImpersonateClient();
  65. if (FAILED(hr))
  66. {
  67. goto done;
  68. }
  69. METADATA_HANDLE hActualHandle;
  70. CADMCOMW* pOuter = NULL;
  71. pOuter = (CADMCOMW*)m_pUnkOuter;
  72. hr = pOuter->LookupAndAccessCheck( METADATA_MASTER_ROOT_HANDLE,
  73. &hActualHandle,
  74. L"",
  75. MD_ADMIN_ACL,
  76. METADATA_PERMISSION_WRITE);
  77. if (FAILED(hr))
  78. {
  79. goto done;
  80. }
  81. // IVANPASH 598894 (SCR)
  82. // Prepend the file name with \\?\ (or \\?\UNC\) to prevent canonicalization
  83. hr = MakePathCanonicalizationProof( pszFileName, TRUE, &strFileName );
  84. if ( FAILED( hr ) )
  85. {
  86. goto done;
  87. }
  88. // Don't use i_wszFileName any more
  89. pszFileName = NULL;
  90. STQueryCell QueryCell[1];
  91. //
  92. // Get the property table.
  93. //
  94. QueryCell[0].pData = (LPVOID)strFileName.QueryStrW();
  95. QueryCell[0].eOperator = eST_OP_EQUAL;
  96. QueryCell[0].iCell = iST_CELL_FILE;
  97. QueryCell[0].dbType = DBTYPE_WSTR;
  98. QueryCell[0].cbSize = (lstrlenW(strFileName.QueryStrW())+1)*sizeof(WCHAR);
  99. ULONG cCell = sizeof(QueryCell)/sizeof(STQueryCell);
  100. //
  101. // No need to initilize dispenser (InitializeSimpleTableDispenser()),
  102. // because we now specify USE_CRT=1 in sources, which means that
  103. // globals will be initialized.
  104. //
  105. hr = DllGetSimpleObjectByIDEx( eSERVERWIRINGMETA_TableDispenser, IID_ISimpleTableDispenser2, (VOID**)&spISTDisp, WSZ_PRODUCT_IIS );
  106. if(FAILED(hr))
  107. {
  108. DBGERROR((
  109. DBG_CONTEXT,
  110. "[%s] DllGetSimpleObjectByIDEx failed with hr = 0x%x.\n",__FUNCTION__,hr));
  111. goto done;
  112. }
  113. hr = spISTDisp->GetTable(
  114. wszDATABASE_METABASE,
  115. wszTABLE_MBProperty,
  116. (LPVOID)QueryCell,
  117. (LPVOID)&cCell,
  118. eST_QUERYFORMAT_CELLS,
  119. fST_LOS_DETAILED_ERROR_TABLE | fST_LOS_NO_LOGGING,
  120. (LPVOID *)&spISTProperty);
  121. //
  122. // Log warnings/errors in getting the mb property table
  123. // Do this BEFORE checking the return code of GetTable.
  124. //
  125. HRESULT hrErrorTable = GetErrorInfo(0, &spErrorInfo);
  126. if(hrErrorTable == S_OK) // GetErrorInfo returns S_FALSE when there is no error object
  127. {
  128. //
  129. // Get the ICatalogErrorLogger interface to log the errors.
  130. //
  131. hrErrorTable = spISTDisp->QueryInterface(
  132. IID_IAdvancedTableDispenser,
  133. (LPVOID*)&spISTDispAdvanced);
  134. if(FAILED(hrErrorTable))
  135. {
  136. DBGWARN((
  137. DBG_CONTEXT,
  138. "[%s] Could not QI for Adv Dispenser, hr=0x%x\n", __FUNCTION__, hrErrorTable));
  139. goto done;
  140. }
  141. hrErrorTable = spISTDispAdvanced->GetCatalogErrorLogger(&spILogger);
  142. if(FAILED(hrErrorTable))
  143. {
  144. DBGWARN((
  145. DBG_CONTEXT,
  146. "[%s] Could not get ICatalogErrorLogger2, hr=0x%x\n", __FUNCTION__, hrErrorTable));
  147. goto done;
  148. }
  149. //
  150. // Get the ISimpleTableRead2 interface to read the errors.
  151. //
  152. hrErrorTable =
  153. spErrorInfo->QueryInterface(IID_ISimpleTableRead2, (LPVOID*)&spISTError);
  154. if(FAILED(hrErrorTable))
  155. {
  156. DBGWARN((DBG_CONTEXT, "[%s] Could not get ISTRead2 from IErrorInfo\n, __FUNCTION__"));
  157. goto done;
  158. }
  159. for(ULONG iRow=0; ; iRow++)
  160. {
  161. tDETAILEDERRORSRow ErrorInfo;
  162. hrErrorTable = spISTError->GetColumnValues(
  163. iRow,
  164. cDETAILEDERRORS_NumberOfColumns,
  165. 0,
  166. 0,
  167. (LPVOID*)&ErrorInfo);
  168. if(hrErrorTable == E_ST_NOMOREROWS)
  169. {
  170. break;
  171. }
  172. if(FAILED(hrErrorTable))
  173. {
  174. DBGWARN((DBG_CONTEXT, "[%s] Could not read an error row.\n", __FUNCTION__));
  175. goto done;
  176. }
  177. DBG_ASSERT(ErrorInfo.pEvent);
  178. switch(*ErrorInfo.pEvent)
  179. {
  180. case IDS_METABASE_DUPLICATE_LOCATION:
  181. iRowDuplicateLocation = iRow;
  182. break;
  183. default:
  184. hrErrorTable =
  185. spILogger->ReportError(
  186. BaseVersion_DETAILEDERRORS,
  187. ExtendedVersion_DETAILEDERRORS,
  188. cDETAILEDERRORS_NumberOfColumns,
  189. 0,
  190. (LPVOID*)&ErrorInfo);
  191. if(FAILED(hrErrorTable))
  192. {
  193. DBGWARN((DBG_CONTEXT, "[%s] Could not log error.\n", __FUNCTION__));
  194. goto done;
  195. }
  196. hr = MD_ERROR_READ_METABASE_FILE;
  197. }
  198. } // for(ULONG iRow=0; ; iRow++)
  199. } // if(hrErrorTable == S_OK)
  200. if(FAILED(hr))
  201. {
  202. DBGERROR((DBG_CONTEXT, "[%s] GetTable failed with hr = 0x%x.\n",__FUNCTION__,hr));
  203. goto done;
  204. }
  205. //
  206. // All of the stuff is read into pISTProperty.
  207. // Now loop through and populate in-memory cache.
  208. // Properties are sorted by location.
  209. //
  210. ULONG acbMBPropertyRow[cMBProperty_NumberOfColumns];
  211. tMBPropertyRow MBPropertyRow;
  212. DWORD dwPreviousLocationID = (DWORD)-1;
  213. DWORD bufLoc = 0;
  214. DWORD dSize = 0;
  215. const WCHAR cSpace[2] = L" ";
  216. const WCHAR cNoName[2] = L"/";
  217. const WCHAR cWebDirType[17] = L"IIsWebVirtualDir";
  218. const WCHAR cFtpDirType[17] = L"IIsFtpVirtualDir";
  219. const WCHAR cRoot[6] = L"ROOT/";
  220. DWORD dwWSLoc = (DWORD)-1;
  221. bool bServCommAdded = true;
  222. ULONG topIndex = 0;
  223. bool bSameLocation = true;
  224. long spot = 0;
  225. long avail = dwMDBufferSize - 1;
  226. for(ULONG i=0; ;i++)
  227. {
  228. hr = spISTProperty->GetColumnValues(
  229. i,
  230. cMBProperty_NumberOfColumns,
  231. 0,
  232. acbMBPropertyRow,
  233. (LPVOID*)&MBPropertyRow);
  234. if(E_ST_NOMOREROWS == hr)
  235. {
  236. hr = S_OK;
  237. break;
  238. }
  239. else if(FAILED(hr))
  240. {
  241. DBGINFO((DBG_CONTEXT,
  242. "[ReadSomeDataFromXML] GetColumnValues failed with hr = 0x%x. Table:%ws. Read row index:%d.\n", \
  243. hr, wszTABLE_MBProperty, i));
  244. goto done;
  245. }
  246. if(dwPreviousLocationID != *MBPropertyRow.pLocationID)
  247. {
  248. dwPreviousLocationID = *MBPropertyRow.pLocationID;
  249. topIndex = i;
  250. }
  251. if(*MBPropertyRow.pID == MD_KEY_TYPE)
  252. {
  253. if (!wcscmp((LPCWSTR)MBPropertyRow.pValue, pszKeyType))
  254. {
  255. // MBPropertyRow.pLocation
  256. dSize = (DWORD)wcslen(MBPropertyRow.pLocation);
  257. spot = bufLoc + dSize;
  258. if (spot < avail)
  259. {
  260. wcscpy(&(pszBuffer[bufLoc]), MBPropertyRow.pLocation);
  261. pszBuffer[bufLoc + dSize] = 0;
  262. }
  263. bufLoc += dSize+1;
  264. dwWSLoc = *MBPropertyRow.pLocationID;
  265. bServCommAdded = false;
  266. // now check from topIndex down for a ServerComment
  267. hr = S_OK;
  268. bSameLocation = true;
  269. while (SUCCEEDED(hr) && !bServCommAdded && bSameLocation)
  270. {
  271. // special case for "IIsWebVirtualDir"
  272. if (!wcscmp(pszKeyType, cWebDirType) || !wcscmp(pszKeyType, cFtpDirType))
  273. {
  274. WCHAR* pCopy = NULL;
  275. WCHAR* pPos = NULL;
  276. pCopy = _wcsdup(MBPropertyRow.pLocation);
  277. if (!pCopy)
  278. {
  279. hr = E_OUTOFMEMORY;
  280. goto done;
  281. }
  282. if (!_wcsupr(pCopy))
  283. {
  284. hr = E_FAIL;
  285. goto done;
  286. }
  287. pPos = wcsstr(pCopy, cRoot);
  288. if (pPos)
  289. {
  290. LONG_PTR lPos = pPos - pCopy;
  291. pPos = MBPropertyRow.pLocation + lPos + wcslen(cRoot);
  292. }
  293. else
  294. {
  295. pPos = (WCHAR*)cNoName;
  296. }
  297. // now copy pPos if applicable
  298. dSize = (DWORD)wcslen(pPos);
  299. spot = bufLoc + dSize;
  300. if (spot < avail)
  301. {
  302. wcscpy(&(pszBuffer[bufLoc]), pPos);
  303. pszBuffer[bufLoc + dSize] = 0;
  304. }
  305. bufLoc += dSize+1;
  306. free(pCopy);
  307. bServCommAdded = true;
  308. break;
  309. }
  310. hr = spISTProperty->GetColumnValues(
  311. topIndex,
  312. cMBProperty_NumberOfColumns,
  313. 0,
  314. acbMBPropertyRow,
  315. (LPVOID*)&MBPropertyRow);
  316. if (*MBPropertyRow.pLocationID != dwWSLoc)
  317. {
  318. bSameLocation = false;
  319. break;
  320. }
  321. if (*MBPropertyRow.pID == MD_SERVER_COMMENT)
  322. {
  323. dSize = (DWORD)wcslen((WCHAR*)MBPropertyRow.pValue);
  324. spot = bufLoc + dSize;
  325. if (spot < avail)
  326. {
  327. wcscpy(&(pszBuffer[bufLoc]), (WCHAR*)MBPropertyRow.pValue);
  328. pszBuffer[bufLoc + dSize] = 0;
  329. }
  330. bufLoc += dSize+1;
  331. bServCommAdded = true;
  332. }
  333. topIndex++;
  334. }
  335. if (!bServCommAdded)
  336. {
  337. // need to add in " "
  338. dSize = (DWORD)wcslen(cSpace);
  339. spot = bufLoc + dSize;
  340. if (spot < avail)
  341. {
  342. wcscpy(&(pszBuffer[bufLoc]), cSpace);
  343. pszBuffer[bufLoc + dSize] = 0;
  344. }
  345. bufLoc += dSize+1;
  346. }
  347. }
  348. }
  349. }
  350. if (bufLoc < dwMDBufferSize)
  351. {
  352. pszBuffer[bufLoc] = 0;
  353. }
  354. else if (pszBuffer)
  355. {
  356. pszBuffer[dwMDBufferSize-1] = 0;
  357. pszBuffer[dwMDBufferSize-2] = 0;
  358. hr = RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER);
  359. }
  360. *pdwMDRequiredBufferSize = bufLoc + 1;
  361. done:
  362. return hr;
  363. }