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.

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