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.

756 lines
23 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Abstract:
  4. @doc
  5. @module stssites.cxx | Implementation of CSTSSites
  6. @end
  7. Author:
  8. Brian Berkowitz [brianb] 10/15/2001
  9. Revision History:
  10. Name Date Comments
  11. brianb 10/15/2001 Created
  12. --*/
  13. #include "stdafx.hxx"
  14. #include "vs_inc.hxx"
  15. #include "vs_reg.hxx"
  16. #include "iadmw.h"
  17. #include "iiscnfg.h"
  18. #include "mdmsg.h"
  19. #include "stssites.hxx"
  20. #include "vswriter.h"
  21. ////////////////////////////////////////////////////////////////////////
  22. // Standard foo for file name aliasing. This code block must be after
  23. // all includes of VSS header files.
  24. //
  25. #ifdef VSS_FILE_ALIAS
  26. #undef VSS_FILE_ALIAS
  27. #endif
  28. #define VSS_FILE_ALIAS "STSSITEC"
  29. //
  30. ////////////////////////////////////////////////////////////////////////
  31. // toplevel key for enumeration of sites and their DSNs
  32. static LPCWSTR x_STSSECUREKEY = L"Software\\Microsoft\\Shared Tools\\Web Server Extensions\\Secure";
  33. // bottom level keys for sharepoint sites
  34. static LPCWSTR x_STSRegistryKey = L"/LM/W3SVC/";
  35. static LPCWSTR x_STSRegistryKeyFormat = L"/LM/W3SVC/%d:";
  36. static LPCWSTR x_STSMetabaseKey = L"/LM/W3SVC";
  37. static LPCWSTR x_STSMetabaseKeyFormat= L"/LM/W3SVC/%d";
  38. // DSN value
  39. static LPCWSTR x_ValueDSN = L"DSN";
  40. // version key for Sharepoint Team Services 5.0"
  41. static LPCWSTR x_STSVERSIONKEY = L"Software\\Microsoft\\Shared Tools\\Web Server Extensions\\5.0";
  42. // key to Shell Folders properties. Used to get Applications Data directory"
  43. static LPCWSTR x_ShellFoldersKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
  44. // value of applications data directory under Shell folders key
  45. static LPCWSTR x_AppDataValue = L"Common AppData";
  46. // subfolder under Applications data directory for STS data"
  47. static LPCWSTR x_STSSubfolder = L"\\Microsoft\\Web Server Extensions\\50";
  48. // constructor
  49. CSTSSites::CSTSSites() :
  50. m_cSites(0),
  51. m_rgSiteIds(NULL),
  52. m_rootKey(KEY_READ|KEY_ENUMERATE_SUB_KEYS),
  53. m_hQuotaLock(INVALID_HANDLE_VALUE),
  54. m_wszAppDataFolder(NULL)
  55. {
  56. }
  57. // destructor
  58. CSTSSites::~CSTSSites()
  59. {
  60. delete m_rgSiteIds;
  61. UnlockSites();
  62. UnlockQuotaDatabase();
  63. CoTaskMemFree(m_wszAppDataFolder);
  64. }
  65. // initialize the array of site ids. Returns FALSE if there are no sites
  66. bool CSTSSites::Initialize()
  67. {
  68. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::Initialize");
  69. if (!m_rootKey.Open(HKEY_LOCAL_MACHINE, x_STSSECUREKEY))
  70. return false;
  71. CVssRegistryKeyIterator iter;
  72. iter.Attach(m_rootKey);
  73. try
  74. {
  75. m_cSites = iter.GetSubkeysCount();
  76. m_rgSiteIds = new DWORD[m_cSites];
  77. if (m_rgSiteIds == NULL)
  78. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"can't allocate site id array");
  79. for(UINT iSite = 0; iSite < m_cSites; iSite++)
  80. {
  81. DWORD siteId;
  82. BS_ASSERT(!iter.IsEOF());
  83. LPCWSTR wszSiteName = iter.GetCurrentKeyName();
  84. BS_ASSERT(wcslen(wszSiteName) > wcslen(x_STSRegistryKey));
  85. BS_ASSERT(wcsncmp(wszSiteName, x_STSRegistryKey, wcslen(x_STSRegistryKey)) == 0);
  86. #ifdef DEBUG
  87. DWORD cFields =
  88. #endif
  89. swscanf(wszSiteName, x_STSRegistryKeyFormat, &siteId);
  90. BS_ASSERT(cFields == 1);
  91. m_rgSiteIds[iSite] = siteId;
  92. iter.MoveNext();
  93. }
  94. }
  95. catch(...)
  96. {
  97. iter.Detach();
  98. throw;
  99. }
  100. iter.Detach();
  101. return true;
  102. }
  103. // return the id of a specific site
  104. VSS_PWSZ CSTSSites::GetSiteDSN(DWORD iSite)
  105. {
  106. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::GetSiteDSN");
  107. CVssRegistryKey key(KEY_READ);
  108. BS_ASSERT(iSite < m_cSites);
  109. DWORD siteId = m_rgSiteIds[iSite];
  110. WCHAR buf[MAX_PATH];
  111. swprintf(buf, x_STSRegistryKeyFormat, siteId);
  112. if (!key.Open(m_rootKey.GetHandle(), buf))
  113. ft.Throw(VSSDBG_STSWRITER, E_UNEXPECTED, L"missing registry key");
  114. VSS_PWSZ pwszDSN = NULL;
  115. key.GetValue(x_ValueDSN, pwszDSN);
  116. BS_ASSERT(pwszDSN);
  117. return pwszDSN;
  118. }
  119. // determine if this is the correct sharepoint version
  120. bool CSTSSites::ValidateSharepointVersion()
  121. {
  122. CVssRegistryKey key;
  123. return key.Open(HKEY_LOCAL_MACHINE, x_STSVERSIONKEY);
  124. }
  125. void CSTSSites::SetupMetabaseInterface()
  126. {
  127. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::SetupMetabaseInterface");
  128. if (!m_pMetabase)
  129. {
  130. ft.hr = CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, (void **) &m_pMetabase);
  131. ft.CheckForError(VSSDBG_STSWRITER, L"CoCreateInstance MSAdminBase");
  132. }
  133. }
  134. // return pointer to site content root. The return value should be
  135. // freed using CoTaskMemFree by the caller
  136. VSS_PWSZ CSTSSites::GetSiteRoot(DWORD iSite)
  137. {
  138. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::GetSiteRoles");
  139. METADATA_HANDLE h;
  140. static const DWORD x_MDTimeout = 2000;
  141. BS_ASSERT(iSite < m_cSites);
  142. DWORD siteId = m_rgSiteIds[iSite];
  143. WCHAR buf[METADATA_MAX_NAME_LEN];
  144. SetupMetabaseInterface();
  145. swprintf(buf, x_STSMetabaseKeyFormat, siteId);
  146. ft.hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, buf, METADATA_PERMISSION_READ, x_MDTimeout, &h);
  147. ft.CheckForError(VSSDBG_STSWRITER, L"IMSAdminBase::OpenKey");
  148. CVssAutoMetabaseHandle MetaHandle(m_pMetabase, h);
  149. METADATA_RECORD rec;
  150. DWORD dwBufLen = METADATA_MAX_NAME_LEN;
  151. PBYTE pbBuffer = (BYTE *) CoTaskMemAlloc(dwBufLen);
  152. if (pbBuffer == NULL)
  153. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  154. rec.dwMDAttributes = METADATA_INHERIT;
  155. rec.dwMDUserType = IIS_MD_UT_SERVER,
  156. rec.dwMDDataType = ALL_METADATA;
  157. rec.dwMDDataLen = dwBufLen;
  158. rec.pbMDData = pbBuffer;
  159. rec.dwMDIdentifier = MD_VR_PATH;
  160. DWORD dwReqSize;
  161. ft.hr = m_pMetabase->GetData(h, L"/root", &rec, &dwReqSize);
  162. if (ft.hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
  163. {
  164. CoTaskMemFree(pbBuffer);
  165. pbBuffer = (BYTE *) CoTaskMemAlloc(dwReqSize);
  166. if (pbBuffer == NULL)
  167. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  168. rec.dwMDDataLen = dwReqSize;
  169. rec.pbMDData = pbBuffer;
  170. ft.hr = m_pMetabase->GetData(h, L"/root", &rec, &dwReqSize);
  171. }
  172. ft.CheckForError(VSSDBG_STSWRITER, L"IMSAdminBase::GetData");
  173. return (WCHAR *) pbBuffer;
  174. }
  175. void CSTSSites::LockSiteContents(DWORD iSite)
  176. {
  177. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::LockSiteContents");
  178. VSS_PWSZ wszContentRoot = GetSiteRoot(iSite);
  179. WCHAR *wszCurrentFile = NULL;
  180. char *szFile = NULL;
  181. WCHAR *wszFile = NULL;
  182. WCHAR *wszNewRoot = NULL;
  183. CSimpleArray<VSS_PWSZ> rgwszRoots;
  184. try
  185. {
  186. wszCurrentFile = new WCHAR[wcslen(wszContentRoot) + 1];
  187. if (wszCurrentFile == NULL)
  188. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  189. wcscpy(wszCurrentFile, wszContentRoot);
  190. rgwszRoots.Add(wszCurrentFile);
  191. wszCurrentFile = NULL;
  192. DWORD iCurrentPos = 0;
  193. DWORD iEndLevel = 1;
  194. CoTaskMemFree(wszContentRoot);
  195. wszContentRoot = NULL;
  196. while(iCurrentPos < iEndLevel)
  197. {
  198. for(; iCurrentPos < iEndLevel; iCurrentPos++)
  199. {
  200. LPCWSTR wszCurrentRoot = rgwszRoots[iCurrentPos];
  201. wszCurrentFile = new WCHAR[wcslen(wszCurrentRoot) + MAX_PATH + 2];
  202. if (wszCurrentFile == NULL)
  203. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  204. // get front page lock
  205. wcscpy(wszCurrentFile, wszCurrentRoot);
  206. wcscat(wszCurrentFile, L"\\_vti_pvt\\frontpg.lck");
  207. TryLock(wszCurrentFile, false);
  208. // get service lock
  209. wcscpy(wszCurrentFile, wszCurrentRoot);
  210. wcscat(wszCurrentFile, L"\\_vti_pvt\\service.lck");
  211. TryLock(wszCurrentFile, false);
  212. // find child sub webs
  213. wcscpy(wszCurrentFile, wszCurrentRoot);
  214. wcscat(wszCurrentFile, L"\\_vti_pvt\\services.cnf");
  215. CVssAutoWin32Handle h = CreateFile
  216. (
  217. wszCurrentFile,
  218. GENERIC_READ,
  219. FILE_SHARE_READ,
  220. NULL,
  221. OPEN_EXISTING,
  222. 0,
  223. NULL
  224. );
  225. if (h == INVALID_HANDLE_VALUE)
  226. {
  227. DWORD dwErr = GetLastError();
  228. if (dwErr == ERROR_PATH_NOT_FOUND ||
  229. dwErr == ERROR_FILE_NOT_FOUND)
  230. continue;
  231. ft.TranslateGenericError
  232. (
  233. VSSDBG_STSWRITER,
  234. HRESULT_FROM_WIN32(GetLastError()),
  235. L"CreateFile(%s)",
  236. wszCurrentFile
  237. );
  238. }
  239. DWORD dwSize = GetFileSize(h, NULL);
  240. if (dwSize == 0)
  241. ft.TranslateGenericError
  242. (
  243. VSSDBG_STSWRITER,
  244. HRESULT_FROM_WIN32(GetLastError()),
  245. L"GetFileSize(%s)",
  246. wszCurrentFile
  247. );
  248. szFile = new char[dwSize + 1];
  249. wszFile = new WCHAR[dwSize + 1];
  250. if (szFile == NULL || wszFile == NULL)
  251. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  252. DWORD dwRead;
  253. if (!ReadFile(h, szFile, dwSize, &dwRead, NULL))
  254. ft.TranslateGenericError
  255. (
  256. VSSDBG_STSWRITER,
  257. HRESULT_FROM_WIN32(GetLastError()),
  258. L"ReadFile(%s)",
  259. wszCurrentFile
  260. );
  261. szFile[dwSize] = '\0';
  262. if (!MultiByteToWideChar
  263. (
  264. CP_ACP,
  265. MB_ERR_INVALID_CHARS,
  266. szFile,
  267. dwSize,
  268. wszFile,
  269. dwSize))
  270. {
  271. ft.hr = HRESULT_FROM_WIN32(GetLastError());
  272. ft.CheckForError(VSSDBG_STSWRITER, L"MultiByteToWideChar");
  273. }
  274. WCHAR *pwcCur = wszFile;
  275. WCHAR *pwcMax = wszFile + dwSize;
  276. while(pwcCur < pwcMax)
  277. {
  278. WCHAR *pwcEnd = wcschr(pwcCur, L'\n');
  279. if (pwcEnd == NULL)
  280. pwcEnd = pwcMax;
  281. *pwcEnd = L'\0';
  282. stripWhiteChars(pwcCur);
  283. if (*pwcCur == L'\0' || *pwcCur != L'/' || pwcCur[1] == L'\0')
  284. {
  285. pwcCur = pwcEnd + 1;
  286. continue;
  287. }
  288. wszNewRoot = new WCHAR[wcslen(pwcCur) + wcslen(wszCurrentRoot) + 1];
  289. if (wszNewRoot == NULL)
  290. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  291. wcscpy(wszNewRoot, wszCurrentRoot);
  292. // use backslash instead of forward slash
  293. wcscat(wszNewRoot, L"\\");
  294. // root of subweb
  295. wcscat(wszNewRoot, pwcCur+1);
  296. rgwszRoots.Add(wszNewRoot);
  297. wszNewRoot = NULL;
  298. pwcCur = pwcEnd + 1;
  299. }
  300. delete [] wszFile;
  301. wszFile = NULL;
  302. delete [] szFile;
  303. szFile = NULL;
  304. }
  305. iCurrentPos = iEndLevel;
  306. iEndLevel = rgwszRoots.GetSize();
  307. }
  308. }
  309. catch(...)
  310. {
  311. UnlockSites();
  312. delete [] wszNewRoot;
  313. delete [] wszFile;
  314. delete [] szFile;
  315. delete wszCurrentFile;
  316. CoTaskMemFree(wszContentRoot);
  317. for (int x = 0; x < rgwszRoots.GetSize(); x++)
  318. delete [] rgwszRoots[x];
  319. throw;
  320. }
  321. for (int x = 0; x < rgwszRoots.GetSize(); x++)
  322. delete [] rgwszRoots[x];
  323. }
  324. // remove white characters from beginning and ending of the string
  325. void CSTSSites::stripWhiteChars(LPWSTR &wsz)
  326. {
  327. static LPCWSTR x_wszWhiteChars = L"^[ \t]+";
  328. while(*wsz != L'\0')
  329. {
  330. if (wcschr(x_wszWhiteChars, *wsz) == NULL)
  331. break;
  332. wsz++;
  333. }
  334. if (*wsz == L'\0')
  335. return;
  336. LPWSTR wszEnd = wsz + wcslen(wsz) - 1;
  337. while(wszEnd > wsz)
  338. {
  339. if (wcschr(x_wszWhiteChars, *wszEnd) == NULL && *wszEnd != L'\r')
  340. break;
  341. *wszEnd = L'\0';
  342. wszEnd--;
  343. }
  344. }
  345. void CSTSSites::TryLock(LPCWSTR wszFile, bool bQuotaFile)
  346. {
  347. static const DWORD x_MAX_RETRIES = 60;
  348. static const DWORD x_SLEEP_INTERVAL = 1000;
  349. HANDLE h = INVALID_HANDLE_VALUE;
  350. for(DWORD i = 0; i < x_MAX_RETRIES; i++)
  351. {
  352. h = CreateFile
  353. (
  354. wszFile,
  355. GENERIC_READ|GENERIC_WRITE,
  356. 0,
  357. NULL,
  358. OPEN_EXISTING,
  359. 0,
  360. NULL
  361. );
  362. if (h != INVALID_HANDLE_VALUE)
  363. break;
  364. DWORD dwErr = GetLastError();
  365. if (dwErr == ERROR_SHARING_VIOLATION)
  366. {
  367. Sleep(x_SLEEP_INTERVAL);
  368. continue;
  369. }
  370. // assume file doesn't exist
  371. return;
  372. }
  373. if (i >= x_MAX_RETRIES)
  374. throw VSS_E_WRITERERROR_TIMEOUT;
  375. BS_ASSERT(h != INVALID_HANDLE_VALUE);
  376. try
  377. {
  378. if (bQuotaFile)
  379. {
  380. BS_ASSERT(m_hQuotaLock == INVALID_HANDLE_VALUE);
  381. m_hQuotaLock = h;
  382. }
  383. else
  384. m_rgContentLocks.Add(h);
  385. }
  386. catch(...)
  387. {
  388. // add failed, close handle and rethrow error
  389. CloseHandle(h);
  390. throw;
  391. }
  392. }
  393. void CSTSSites::UnlockSites()
  394. {
  395. DWORD dwSize = m_rgContentLocks.GetSize();
  396. for(DWORD i = 0; i < dwSize; i++)
  397. CloseHandle(m_rgContentLocks[i]);
  398. m_rgContentLocks.RemoveAll();
  399. }
  400. // lock the quota database
  401. void CSTSSites::LockQuotaDatabase()
  402. {
  403. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::LockQuotaDatabase");
  404. // do nothing if quota database is already locked
  405. if (m_hQuotaLock != INVALID_HANDLE_VALUE)
  406. return;
  407. static LPCWSTR x_wszLockFile = L"\\owsuser.lck";
  408. VSS_PWSZ wszDbRoot = GetQuotaDatabase();
  409. LPWSTR wsz = NULL;
  410. try
  411. {
  412. wsz = new WCHAR[wcslen(wszDbRoot) + 1 + wcslen(x_wszLockFile)];
  413. if (wsz == NULL)
  414. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  415. wcscpy(wsz, wszDbRoot);
  416. wcscat(wsz, x_wszLockFile);
  417. TryLock(wsz, true);
  418. delete wsz;
  419. CoTaskMemFree(wszDbRoot);
  420. }
  421. catch(...)
  422. {
  423. delete wsz;
  424. CoTaskMemFree(wszDbRoot);
  425. throw;
  426. }
  427. }
  428. // unlock the quota database
  429. void CSTSSites::UnlockQuotaDatabase()
  430. {
  431. if (m_hQuotaLock != INVALID_HANDLE_VALUE)
  432. {
  433. CloseHandle(m_hQuotaLock);
  434. m_hQuotaLock = INVALID_HANDLE_VALUE;
  435. }
  436. }
  437. // get location of Documents And Settings/All Users folder
  438. LPCWSTR CSTSSites::GetAppDataFolder()
  439. {
  440. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::GetAppDataFolder");
  441. if (m_wszAppDataFolder)
  442. return m_wszAppDataFolder;
  443. CVssRegistryKey key;
  444. if (!key.Open(HKEY_LOCAL_MACHINE, x_ShellFoldersKey))
  445. ft.Throw(VSSDBG_STSWRITER, E_UNEXPECTED, L"shell folders key is missing");
  446. key.GetValue(x_AppDataValue, m_wszAppDataFolder);
  447. return m_wszAppDataFolder;
  448. }
  449. // get location of directory containing the quota database for
  450. // sharepoint. Caller should call CoTaskMemFree on the returned value
  451. VSS_PWSZ CSTSSites::GetQuotaDatabase()
  452. {
  453. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::GetQuotaDatabase");
  454. LPCWSTR wszAppData = GetAppDataFolder();
  455. DWORD cwc = (DWORD) (wcslen(wszAppData) + wcslen(x_STSSubfolder) + 1);
  456. VSS_PWSZ wsz = (VSS_PWSZ) CoTaskMemAlloc(cwc * sizeof(WCHAR));
  457. if (wsz == NULL)
  458. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  459. wcscpy(wsz, wszAppData);
  460. wcscat(wsz, x_STSSubfolder);
  461. return wsz;
  462. }
  463. // return of the root directory for the sites roles database under
  464. // the app data folder
  465. VSS_PWSZ CSTSSites::GetSiteRoles(DWORD iSite)
  466. {
  467. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::GetSiteRoles");
  468. DWORD siteId = GetSiteId(iSite);
  469. WCHAR buf[32];
  470. swprintf(buf, L"\\W3SVC%d", siteId);
  471. LPCWSTR wszAppData = GetAppDataFolder();
  472. DWORD cwc = (DWORD) (wcslen(wszAppData) + wcslen(x_STSSubfolder) + wcslen(buf) + 1);
  473. VSS_PWSZ wsz = (VSS_PWSZ) CoTaskMemAlloc(cwc * sizeof(WCHAR));
  474. if (wsz == NULL)
  475. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  476. wcscpy(wsz, wszAppData);
  477. wcscat(wsz, x_STSSubfolder);
  478. wcscat(wsz, buf);
  479. return wsz;
  480. }
  481. VSS_PWSZ CSTSSites::GetSiteBasicInfo(DWORD iSite, DWORD propId)
  482. {
  483. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::GetSiteBasicInfo");
  484. METADATA_HANDLE h;
  485. static const DWORD x_MDTimeout = 2000;
  486. BS_ASSERT(iSite < m_cSites);
  487. DWORD siteId = m_rgSiteIds[iSite];
  488. SetupMetabaseInterface();
  489. ft.hr = m_pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, x_STSMetabaseKey, METADATA_PERMISSION_READ, x_MDTimeout, &h);
  490. ft.CheckForError(VSSDBG_STSWRITER, L"IMSAdminBase::OpenKey");
  491. CVssAutoMetabaseHandle MetaHandle(m_pMetabase, h);
  492. METADATA_RECORD rec;
  493. DWORD dwBufLen = METADATA_MAX_NAME_LEN;
  494. PBYTE pbBuffer = (BYTE *) CoTaskMemAlloc(dwBufLen);
  495. if (pbBuffer == NULL)
  496. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  497. rec.dwMDAttributes = METADATA_INHERIT;
  498. rec.dwMDUserType = IIS_MD_UT_SERVER,
  499. rec.dwMDDataType = ALL_METADATA;
  500. rec.dwMDDataLen = dwBufLen;
  501. rec.pbMDData = pbBuffer;
  502. rec.dwMDIdentifier = propId;
  503. WCHAR buf[16];
  504. swprintf(buf, L"/%d", siteId);
  505. DWORD dwReqSize;
  506. ft.hr = m_pMetabase->GetData(h, buf, &rec, &dwReqSize);
  507. if (ft.hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
  508. {
  509. CoTaskMemFree(pbBuffer);
  510. pbBuffer = (BYTE *) CoTaskMemAlloc(dwReqSize);
  511. if (pbBuffer == NULL)
  512. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  513. rec.dwMDDataLen = dwReqSize;
  514. rec.pbMDData = pbBuffer;
  515. ft.hr = m_pMetabase->GetData(h, buf, &rec, &dwReqSize);
  516. }
  517. if (ft.hr == MD_ERROR_DATA_NOT_FOUND)
  518. return NULL;
  519. ft.CheckForError(VSSDBG_STSWRITER, L"IMSAdminBase::GetData");
  520. return (WCHAR *) pbBuffer;
  521. }
  522. // return comments for site (site description). Caller is responsible
  523. // for freeing up the memory using CoTaskMemFree
  524. VSS_PWSZ CSTSSites::GetSiteComment(DWORD iSite)
  525. {
  526. return GetSiteBasicInfo(iSite, MD_SERVER_COMMENT);
  527. }
  528. // return ip address of the site if it exists. Caller is responsible for
  529. // freeing up the memory using CoTaskMemFree
  530. VSS_PWSZ CSTSSites::GetSiteIpAddress(DWORD iSite)
  531. {
  532. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::GetSiteIpAddress");
  533. VSS_PWSZ wszBindings = GetSiteBasicInfo(iSite, MD_SERVER_BINDINGS);
  534. if (wszBindings == NULL)
  535. return NULL;
  536. LPWSTR wszHost = wcsrchr(wszBindings, L':');
  537. if (wszHost == NULL)
  538. {
  539. CoTaskMemFree(wszBindings);
  540. return NULL;
  541. }
  542. *wszHost = '\0';
  543. LPCWSTR wszPort = wcsrchr(wszBindings, L':');
  544. if (wszPort == NULL || wszPort == wszBindings)
  545. {
  546. CoTaskMemFree(wszBindings);
  547. return NULL;
  548. }
  549. DWORD cwc = (DWORD) (wszPort - wszBindings);
  550. VSS_PWSZ pwszRet = (VSS_PWSZ) CoTaskMemAlloc(cwc * sizeof(WCHAR));
  551. if (pwszRet == NULL)
  552. {
  553. CoTaskMemFree(wszBindings);
  554. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  555. }
  556. wcsncpy(pwszRet, wszBindings, cwc - 1);
  557. pwszRet[cwc - 1] = L'\0';
  558. return pwszRet;
  559. }
  560. // return port address of the site if it exists. Caller is responsible for
  561. // freeing up the memory using CoTaskMemFree
  562. DWORD CSTSSites::GetSitePort(DWORD iSite)
  563. {
  564. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::GetSiteIpAddress");
  565. VSS_PWSZ wszBindings = GetSiteBasicInfo(iSite, MD_SERVER_BINDINGS);
  566. if (wszBindings == NULL)
  567. return NULL;
  568. LPWSTR wszHost = wcsrchr(wszBindings, L':');
  569. if (wszHost == NULL)
  570. {
  571. CoTaskMemFree(wszBindings);
  572. return NULL;
  573. }
  574. *wszHost = L'\0';
  575. LPWSTR wszPort = wcsrchr(wszBindings, L':');
  576. if (wszPort == NULL || wszPort + 1 == wszHost)
  577. {
  578. CoTaskMemFree(wszBindings);
  579. return 0;
  580. }
  581. DWORD dwPort = _wtoi(wszPort + 1);
  582. CoTaskMemFree(wszBindings);
  583. return dwPort;
  584. }
  585. // return port address of the site if it exists. Caller is responsible for
  586. // freeing up the memory using CoTaskMemFree
  587. VSS_PWSZ CSTSSites::GetSiteHost(DWORD iSite)
  588. {
  589. CVssFunctionTracer ft(VSSDBG_STSWRITER, L"CSTSSites::GetSiteIpAddress");
  590. VSS_PWSZ wszBindings = GetSiteBasicInfo(iSite, MD_SERVER_BINDINGS);
  591. if (wszBindings == NULL)
  592. return NULL;
  593. LPCWSTR wszHost = wcsrchr(wszBindings, L':');
  594. if (wszHost == NULL || wcslen(wszHost) == 1)
  595. {
  596. CoTaskMemFree(wszBindings);
  597. return NULL;
  598. }
  599. VSS_PWSZ pwszRet = (VSS_PWSZ) CoTaskMemAlloc(wcslen(wszHost));
  600. if (pwszRet == NULL)
  601. {
  602. CoTaskMemFree(wszBindings);
  603. ft.Throw(VSSDBG_STSWRITER, E_OUTOFMEMORY, L"out of memory");
  604. }
  605. wcscpy(pwszRet, wszHost + 1);
  606. CoTaskMemFree(wszBindings);
  607. return pwszRet;
  608. }