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.

624 lines
18 KiB

  1. #include "stdafx.hxx"
  2. #include "vs_idl.hxx"
  3. #include "vswriter.h"
  4. #include "vsbackup.h"
  5. #include "compont.h"
  6. #include <debug.h>
  7. #include <cwriter.h>
  8. #include <lmshare.h>
  9. #include <lmaccess.h>
  10. #include <time.h>
  11. //
  12. // CWriterComponentsSelection class
  13. //
  14. CWriterComponentsSelection::CWriterComponentsSelection()
  15. {
  16. m_WriterId = GUID_NULL;
  17. m_uNumComponents = 0;
  18. m_uNumSubcomponents = 0;
  19. m_ppwszComponentLogicalPaths = NULL;
  20. m_ppwszSubcomponentLogicalPaths = NULL;
  21. }
  22. CWriterComponentsSelection::~CWriterComponentsSelection()
  23. {
  24. if ((m_uNumComponents > 0) && (m_ppwszComponentLogicalPaths != NULL))
  25. {
  26. for (UINT i=0; i<m_uNumComponents; i++)
  27. {
  28. if (m_ppwszComponentLogicalPaths[i] != NULL)
  29. {
  30. free(m_ppwszComponentLogicalPaths[i]);
  31. m_ppwszComponentLogicalPaths[i] = NULL;
  32. }
  33. }
  34. free(m_ppwszComponentLogicalPaths);
  35. m_ppwszComponentLogicalPaths = NULL;
  36. m_uNumComponents = 0;
  37. }
  38. if ((m_uNumSubcomponents > 0) && (m_ppwszSubcomponentLogicalPaths != NULL))
  39. {
  40. for (UINT i=0; i<m_uNumSubcomponents; i++)
  41. {
  42. if (m_ppwszSubcomponentLogicalPaths[i] != NULL)
  43. {
  44. free(m_ppwszSubcomponentLogicalPaths[i]);
  45. m_ppwszSubcomponentLogicalPaths[i] = NULL;
  46. }
  47. }
  48. free(m_ppwszSubcomponentLogicalPaths);
  49. m_ppwszSubcomponentLogicalPaths = NULL;
  50. m_uNumSubcomponents = 0;
  51. }
  52. }
  53. void CWriterComponentsSelection::SetWriter
  54. (
  55. IN VSS_ID WriterId
  56. )
  57. {
  58. m_WriterId = WriterId;
  59. }
  60. HRESULT CWriterComponentsSelection::AddSelectedComponent
  61. (
  62. IN WCHAR* pwszComponentLogicalPath
  63. )
  64. {
  65. return AddSelected(pwszComponentLogicalPath, m_ppwszComponentLogicalPaths, m_uNumComponents);
  66. }
  67. HRESULT CWriterComponentsSelection::AddSelectedSubcomponent
  68. (
  69. IN WCHAR* pwszSubcomponentLogicalPath
  70. )
  71. {
  72. return AddSelected(pwszSubcomponentLogicalPath, m_ppwszSubcomponentLogicalPaths, m_uNumSubcomponents);
  73. }
  74. HRESULT CWriterComponentsSelection::AddSelected
  75. (
  76. IN WCHAR* pwszLogicalPath,
  77. WCHAR**& pwszLogicalPaths,
  78. UINT& uSize
  79. )
  80. {
  81. if (m_WriterId == GUID_NULL)
  82. {
  83. // Don't allow adding components to NULL writer...
  84. return E_UNEXPECTED;
  85. }
  86. if (pwszLogicalPath == NULL)
  87. {
  88. return E_INVALIDARG;
  89. }
  90. // A more clever implementation would allocate memory in chuncks, but this is just a test program...
  91. PWCHAR *ppwzTemp = (PWCHAR *) realloc(pwszLogicalPaths, (uSize+1) * sizeof (PWCHAR));
  92. if (ppwzTemp != NULL)
  93. {
  94. pwszLogicalPaths = ppwzTemp;
  95. pwszLogicalPaths[uSize] = NULL;
  96. }
  97. else
  98. {
  99. return E_OUTOFMEMORY;
  100. }
  101. pwszLogicalPaths[uSize] = (PWCHAR) malloc((wcslen(pwszLogicalPath) + 1) * sizeof (WCHAR));
  102. if (pwszLogicalPaths[uSize] != NULL)
  103. {
  104. wcscpy(pwszLogicalPaths[uSize], pwszLogicalPath);
  105. uSize++;
  106. }
  107. else
  108. {
  109. return E_OUTOFMEMORY;
  110. }
  111. return S_OK;
  112. }
  113. BOOL CWriterComponentsSelection::IsComponentSelected
  114. (
  115. IN WCHAR* pwszComponentLogicalPath,
  116. IN WCHAR* pwszComponentName
  117. )
  118. {
  119. return IsSelected(pwszComponentLogicalPath, pwszComponentName,
  120. m_ppwszComponentLogicalPaths, m_uNumComponents);
  121. }
  122. BOOL CWriterComponentsSelection::IsSubcomponentSelected
  123. (
  124. IN WCHAR* pwszSubcomponentLogicalPath,
  125. IN WCHAR* pwszSubcomponentName
  126. )
  127. {
  128. return IsSelected(pwszSubcomponentLogicalPath, pwszSubcomponentName,
  129. m_ppwszSubcomponentLogicalPaths, m_uNumSubcomponents);
  130. }
  131. BOOL CWriterComponentsSelection::IsSelected(IN WCHAR* pwszLogicalPath, IN WCHAR* pwszName,
  132. IN WCHAR** pwszLogicalPaths, IN UINT uSize)
  133. {
  134. if (m_WriterId == GUID_NULL)
  135. {
  136. // Don't allow query for NULL writer...
  137. return FALSE;
  138. }
  139. if (uSize <= 0)
  140. {
  141. return FALSE;
  142. }
  143. // A component matches if:
  144. // 1. The selection criteria is on the logical-path of the leaf component OR
  145. // 2. The selection criteria is <full-logical-path>\<component-name>
  146. // 3. The selction criteria is component-name (only if logical-path is NULL)
  147. for (UINT i=0; i<uSize; i++)
  148. {
  149. DWORD dwLen;
  150. if (pwszLogicalPaths[i] == NULL)
  151. {
  152. continue;
  153. }
  154. dwLen = (DWORD)wcslen(pwszLogicalPaths[i]);
  155. if (pwszLogicalPath != NULL)
  156. {
  157. // Case 1.
  158. if (_wcsnicmp(pwszLogicalPaths[i], pwszLogicalPath, dwLen) == 0 &&
  159. pwszName == NULL)
  160. {
  161. return TRUE;
  162. }
  163. // Case 2.
  164. if (pwszName == NULL)
  165. {
  166. continue;
  167. }
  168. WCHAR* pwszTemp = wcsrchr(pwszLogicalPaths[i], L'\\');
  169. if (pwszTemp == NULL)
  170. {
  171. continue;
  172. }
  173. if ((pwszTemp != pwszLogicalPaths[i]) && (*(pwszTemp+1) != '\0'))
  174. {
  175. dwLen = (DWORD)(pwszTemp - pwszLogicalPaths[i]);
  176. if ( (dwLen == wcslen(pwszLogicalPath)) &&
  177. (_wcsnicmp(pwszLogicalPaths[i], pwszLogicalPath, dwLen) == 0) &&
  178. (wcscmp(pwszTemp+1, pwszName) == 0) )
  179. {
  180. return TRUE;
  181. }
  182. }
  183. }
  184. else
  185. {
  186. // Case 3.
  187. if (pwszName == NULL)
  188. {
  189. continue;
  190. }
  191. if (_wcsnicmp(pwszLogicalPaths[i], pwszName, dwLen) == 0)
  192. {
  193. return TRUE;
  194. }
  195. }
  196. }
  197. return FALSE;
  198. }
  199. //
  200. // CWritersSelection class
  201. //
  202. CWritersSelection::CWritersSelection()
  203. {
  204. m_lRef = 0;
  205. }
  206. CWritersSelection::~CWritersSelection()
  207. {
  208. // Cleanup the Map
  209. for(int nIndex = 0; nIndex < m_WritersMap.GetSize(); nIndex++)
  210. {
  211. CWriterComponentsSelection* pComponentsSelection = m_WritersMap.GetValueAt(nIndex);
  212. if (pComponentsSelection)
  213. {
  214. delete pComponentsSelection;
  215. }
  216. }
  217. m_WritersMap.RemoveAll();
  218. }
  219. CWritersSelection* CWritersSelection::CreateInstance()
  220. {
  221. CWritersSelection* pObj = new CWritersSelection;
  222. return pObj;
  223. }
  224. STDMETHODIMP CWritersSelection::QueryInterface(
  225. IN REFIID iid,
  226. OUT void** pp
  227. )
  228. {
  229. if (pp == NULL)
  230. return E_INVALIDARG;
  231. if (iid != IID_IUnknown)
  232. return E_NOINTERFACE;
  233. AddRef();
  234. IUnknown** pUnk = reinterpret_cast<IUnknown**>(pp);
  235. (*pUnk) = static_cast<IUnknown*>(this);
  236. return S_OK;
  237. }
  238. ULONG CWritersSelection::AddRef()
  239. {
  240. return ::InterlockedIncrement(&m_lRef);
  241. }
  242. ULONG CWritersSelection::Release()
  243. {
  244. LONG l = ::InterlockedDecrement(&m_lRef);
  245. if (l == 0)
  246. delete this; // We assume that we always allocate this object on the heap!
  247. return l;
  248. }
  249. STDMETHODIMP CWritersSelection::BuildChosenComponents
  250. (
  251. WCHAR *pwszComponentsFileName
  252. )
  253. {
  254. HRESULT hr = S_OK;
  255. HANDLE hFile = INVALID_HANDLE_VALUE;
  256. DWORD dwBytesToRead = 0;
  257. DWORD dwBytesRead;
  258. // Create the file
  259. hFile = CreateFile(pwszComponentsFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  260. if (hFile == INVALID_HANDLE_VALUE)
  261. {
  262. DWORD dwLastError = GetLastError();
  263. wprintf(L"Invalid components file, CreateFile returned = %lu\n", dwLastError);
  264. return HRESULT_FROM_WIN32(dwLastError);
  265. }
  266. if ((dwBytesToRead = GetFileSize(hFile, NULL)) <= 0)
  267. {
  268. CloseHandle(hFile);
  269. DWORD dwLastError = GetLastError();
  270. wprintf(L"Invalid components file, GetFileSize returned = %lu\n", dwLastError);
  271. return HRESULT_FROM_WIN32(dwLastError);
  272. }
  273. if (dwBytesToRead > 0x100000)
  274. {
  275. CloseHandle(hFile);
  276. wprintf(L"Invalid components file, Provide a file with a size of less than 1 MB\n");
  277. return E_FAIL;
  278. }
  279. char * pcBuffer = (PCHAR) malloc (dwBytesToRead);
  280. if (! pcBuffer)
  281. {
  282. CloseHandle(hFile);
  283. return E_OUTOFMEMORY;
  284. }
  285. // Read the components info
  286. if (! ReadFile(hFile, (LPVOID)pcBuffer, dwBytesToRead, &dwBytesRead, NULL))
  287. {
  288. DWORD dwLastError = GetLastError();
  289. CloseHandle(hFile);
  290. free (pcBuffer);
  291. wprintf(L"Invalid components file, ReadFile returned = %lu\n", dwLastError);
  292. return HRESULT_FROM_WIN32(dwLastError);
  293. }
  294. CloseHandle(hFile);
  295. if (dwBytesToRead != dwBytesRead)
  296. {
  297. free (pcBuffer);
  298. wprintf(L"Components selection file is supposed to have %lu bytes but only %lu bytes are read\n", dwBytesToRead, dwBytesRead);
  299. return E_FAIL;
  300. }
  301. // Allocate a buffer to work with
  302. WCHAR * pwcBuffer = (PWCHAR) malloc ((dwBytesToRead+1) * sizeof(WCHAR));
  303. if (! pwcBuffer)
  304. {
  305. free (pcBuffer);
  306. return E_OUTOFMEMORY;
  307. }
  308. // Simple pasring, assume ANSI, Format:
  309. // "writer1-id": "component1.1-name", "component1.2-name",... ; "writer2-id": "component2.1-name", ...
  310. CWriterComponentsSelection* pWriterComponents = NULL;
  311. try
  312. {
  313. VSS_ID WriterId = GUID_NULL;
  314. BOOL bBeforeWriter = TRUE;
  315. BOOL bBeforeComponents = TRUE;
  316. BOOL bInString = FALSE;
  317. char* pcStart = NULL;
  318. for (char* pcCurrent = pcBuffer; pcCurrent < (pcBuffer+dwBytesToRead); pcCurrent++)
  319. {
  320. switch (*pcCurrent)
  321. {
  322. case ':':
  323. if (bBeforeWriter && !bInString)
  324. {
  325. bBeforeWriter = FALSE;
  326. }
  327. else if (bBeforeComponents && !bInString)
  328. {
  329. bBeforeComponents = FALSE;
  330. }
  331. else if (!bInString)
  332. {
  333. throw(E_FAIL);
  334. }
  335. break;
  336. case ';':
  337. if (bBeforeWriter || bInString)
  338. {
  339. throw(E_FAIL);
  340. }
  341. else
  342. {
  343. // If we have a valid writer - add it to the map
  344. if ((pWriterComponents != NULL) && (WriterId != GUID_NULL))
  345. {
  346. if (!m_WritersMap.Add(WriterId, pWriterComponents))
  347. {
  348. delete pWriterComponents;
  349. throw E_OUTOFMEMORY;
  350. }
  351. pWriterComponents = NULL;
  352. WriterId = GUID_NULL;
  353. }
  354. bBeforeWriter = TRUE;
  355. }
  356. break;
  357. case ',':
  358. if (bBeforeWriter || bInString)
  359. {
  360. throw(E_FAIL);
  361. }
  362. break;
  363. case '"':
  364. if (! bInString)
  365. {
  366. // Mark string-start for later
  367. pcStart = pcCurrent + 1;
  368. }
  369. else if (pcStart == pcCurrent)
  370. {
  371. // empty string - skip it
  372. }
  373. else
  374. {
  375. // String ends - convert to WCHAR and process
  376. DWORD dwSize = (DWORD)mbstowcs(pwcBuffer, pcStart, pcCurrent - pcStart);
  377. pwcBuffer[dwSize] = NULL;
  378. if (dwSize <= 0)
  379. {
  380. throw(E_FAIL);
  381. }
  382. if (bBeforeWriter)
  383. {
  384. // If before-writer - must be a writer GUID
  385. HRESULT hrConvert = CLSIDFromString(pwcBuffer, &WriterId);
  386. if ((! SUCCEEDED(hrConvert)) && (hrConvert != REGDB_E_WRITEREGDB))
  387. {
  388. wprintf(L"A writer id in the components selection file is in invalid GUID format\n");
  389. throw(E_FAIL);
  390. }
  391. if (pWriterComponents != NULL)
  392. {
  393. // Previous writer info was not ended correctly
  394. throw(E_FAIL);
  395. }
  396. pWriterComponents = new CWriterComponentsSelection;
  397. if (pWriterComponents == NULL)
  398. {
  399. throw(E_OUTOFMEMORY);
  400. }
  401. pWriterComponents->SetWriter(WriterId);
  402. }
  403. else if (bBeforeComponents)
  404. {
  405. // Must be a component logical-path , name or logical-path\name
  406. if (pWriterComponents != NULL)
  407. {
  408. pWriterComponents->AddSelectedComponent(pwcBuffer);
  409. }
  410. }
  411. else
  412. {
  413. // Must be a component logical-path , name or logical-path\name
  414. if (pWriterComponents != NULL)
  415. {
  416. pWriterComponents->AddSelectedSubcomponent(pwcBuffer);
  417. }
  418. }
  419. }
  420. // Flip in-string flag
  421. bInString = (! bInString);
  422. break;
  423. case ' ':
  424. break;
  425. case '\n':
  426. case '\t':
  427. case '\r':
  428. if (bInString)
  429. {
  430. throw(E_FAIL);
  431. }
  432. break;
  433. default:
  434. if (! bInString)
  435. {
  436. throw(E_FAIL);
  437. }
  438. break;
  439. }
  440. }
  441. }
  442. catch (HRESULT hrParse)
  443. {
  444. hr = hrParse;
  445. if (hr == E_FAIL)
  446. {
  447. wprintf(L"Invalid format of components selection file\n");
  448. }
  449. if (pWriterComponents != NULL)
  450. {
  451. // Error int he middle of writer-components creation (not added to the map yet...)
  452. delete pWriterComponents;
  453. }
  454. }
  455. free (pcBuffer);
  456. free (pwcBuffer);
  457. return hr;
  458. }
  459. BOOL CWritersSelection::IsComponentSelected
  460. (
  461. IN VSS_ID WriterId,
  462. IN WCHAR* pwszComponentLogicalPath,
  463. IN WCHAR* pwszComponentName
  464. )
  465. {
  466. CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId);
  467. if (pWriterComponents == NULL)
  468. {
  469. // No component is selected for this writer
  470. return FALSE;
  471. }
  472. // There are components selected for this writer, check if this specific one is selected
  473. return pWriterComponents->IsComponentSelected(pwszComponentLogicalPath, pwszComponentName);
  474. }
  475. BOOL CWritersSelection::IsSubcomponentSelected
  476. (
  477. IN VSS_ID WriterId,
  478. IN WCHAR* pwszComponentLogicalPath,
  479. IN WCHAR* pwszComponentName
  480. )
  481. {
  482. CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId);
  483. if (pWriterComponents == NULL)
  484. {
  485. // No component is selected for this writer
  486. return FALSE;
  487. }
  488. // There are subccomponents selected for this writer, check if this specific one is selected
  489. return pWriterComponents->IsSubcomponentSelected(pwszComponentLogicalPath, pwszComponentName);
  490. }
  491. const WCHAR* const * CWritersSelection::GetComponents
  492. (
  493. IN VSS_ID WriterId
  494. )
  495. {
  496. CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId);
  497. if (pWriterComponents == NULL)
  498. {
  499. return NULL;
  500. }
  501. return pWriterComponents->GetComponents();
  502. }
  503. const WCHAR* const * CWritersSelection::GetSubcomponents
  504. (
  505. IN VSS_ID WriterId
  506. )
  507. {
  508. CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId);
  509. if (pWriterComponents == NULL)
  510. {
  511. return NULL;
  512. }
  513. return pWriterComponents->GetSubcomponents();
  514. }
  515. const UINT CWritersSelection::GetComponentsCount
  516. (
  517. IN VSS_ID WriterId
  518. )
  519. {
  520. CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId);
  521. if (pWriterComponents == NULL)
  522. {
  523. return NULL;
  524. }
  525. return pWriterComponents->GetComponentsCount();
  526. }
  527. const UINT CWritersSelection::GetSubcomponentsCount
  528. (
  529. IN VSS_ID WriterId
  530. )
  531. {
  532. CWriterComponentsSelection* pWriterComponents = m_WritersMap.Lookup(WriterId);
  533. if (pWriterComponents == NULL)
  534. {
  535. return NULL;
  536. }
  537. return pWriterComponents->GetSubcomponentsCount();
  538. }