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.

807 lines
24 KiB

  1. // MSInfo4Category.cpp: implementation of the CMSInfo4Category class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "resource.h"
  6. #include "category.h"
  7. #include "msictrl.h"
  8. #include "datasource.h"
  9. #include "MSInfo4Category.h"
  10. #include "MSInfo5Category.h"
  11. #include "filestuff.h"
  12. #include <afxole.h>
  13. #include "FileIO.h"
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[]=__FILE__;
  17. #define new DEBUG_NEW
  18. #endif
  19. //////////////////////////////////////////////////////////////////////
  20. // Construction/Destruction
  21. //////////////////////////////////////////////////////////////////////
  22. CNFO4DataSource* CMSInfo4Category::s_pNfo4DataSource = NULL;
  23. //a-kjaw
  24. BOOL CMSInfo4Category::m_bIsControlInstalled = TRUE;
  25. //a-kjaw
  26. CMSInfo4Category::CMSInfo4Category() : m_pUnknown(NULL)
  27. {
  28. }
  29. CMSInfo4Category::~CMSInfo4Category()
  30. {
  31. }
  32. HRESULT CMSInfo4Category::ReadMSI4NFO(CString strFileName/*HANDLE hFile*/,CMSInfo4Category** ppRootCat)
  33. {
  34. DWORD grfMode = STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE;
  35. CComPtr<IStream> pStream;
  36. CComBSTR bstrFileName(strFileName);
  37. CComPtr<IStorage> pStorage;
  38. HRESULT hr = StgOpenStorage(bstrFileName, NULL, grfMode, NULL, 0, &pStorage);
  39. if (!SUCCEEDED(hr))
  40. {
  41. return hr;
  42. }
  43. CComBSTR bstrMSIStream(_T("MSInfo"));
  44. hr = pStorage->OpenStream(bstrMSIStream, NULL, grfMode, 0, &pStream);
  45. if (!SUCCEEDED(hr))
  46. {
  47. return hr;
  48. }
  49. COleStreamFile* pOStream;
  50. pOStream = new COleStreamFile(pStream);
  51. const DWORD MSI_FILE_VER = 0x03000000;
  52. DWORD dwVersion, dwCount;
  53. ULONG ulCount;
  54. // First, read and check the version number in the stream.
  55. ulCount = pOStream->Read((void *) &dwVersion, sizeof(DWORD));
  56. if (FAILED(hr) || ulCount != sizeof(DWORD))
  57. {
  58. return E_FAIL;
  59. }
  60. if (dwVersion != MSI_FILE_VER)
  61. return E_FAIL;
  62. // The next thing in the stream is a set of three strings, each terminated by
  63. // a newline character. These three strings are the time/date, machine name and
  64. // user name from the saving system. The length of the total string precedes
  65. // the string.
  66. DWORD dwSize;
  67. ulCount = pOStream->Read(&dwSize,sizeof(DWORD));
  68. if ( ulCount != sizeof(DWORD))
  69. return E_FAIL;
  70. char * szBuffer = new char[dwSize];
  71. if (szBuffer == NULL)
  72. return E_FAIL;
  73. ulCount = pOStream->Read((void *) szBuffer,dwSize);
  74. if (ulCount != dwSize)
  75. {
  76. delete szBuffer;
  77. return E_FAIL;
  78. }
  79. // We don't actually care about these values (now at least).
  80. /*
  81. CString strData(szBuffer, dwSize);
  82. m_strTimeDateStamp = strData.SpanExcluding("\n");
  83. strData = strData.Right(strData.GetLength() - m_strTimeDateStamp.GetLength() - 1);
  84. m_strMachineName = strData.SpanExcluding("\n");
  85. strData = strData.Right(strData.GetLength() - m_strMachineName.GetLength() - 1);
  86. m_strUserName = strData.SpanExcluding("\n");
  87. */
  88. delete szBuffer;
  89. // Next, read the map from CLSIDs to stream names. This also includes some
  90. // other information about the controls. First we should find a DWORD with
  91. // the count of controls.
  92. DWORD dwControlCount;
  93. ulCount = pOStream->Read(&dwControlCount,sizeof(DWORD));
  94. delete pOStream;
  95. if (ulCount != sizeof(int))
  96. return E_FAIL;
  97. SAVED_CONTROL_INFO controlInfo;
  98. CString strCLSID, strStreamName;
  99. //a-stephl
  100. CMapStringToString mapStreams;
  101. for (DWORD i = 0; i < dwControlCount; i++)
  102. {
  103. if (FAILED(pStream->Read((void *) &controlInfo, sizeof(SAVED_CONTROL_INFO), &dwCount)) || dwCount != sizeof(SAVED_CONTROL_INFO))
  104. return E_FAIL;
  105. strCLSID = controlInfo.szCLSID;
  106. strStreamName = controlInfo.szStreamName;
  107. // We don't currently care about this information...
  108. /*
  109. strSize.Format("%ld", controlInfo.dwSize);
  110. strInfo.FormatMessage(IDS_OCX_INFO, controlInfo.szName, controlInfo.szVersion, strSize);
  111. m_mapCLSIDToInfo.SetAt(strCLSID, strInfo);
  112. */
  113. mapStreams.SetAt(strCLSID, strStreamName);
  114. }
  115. // Read and build the category tree. Read the first level, which must be 0.
  116. int iLevel;
  117. if (FAILED(pStream->Read((void *) &iLevel, sizeof(int), &dwCount)) || dwCount != sizeof(int))
  118. return E_FAIL;
  119. if (iLevel == 0)
  120. {
  121. LARGE_INTEGER li; li.HighPart = -1; li.LowPart = (ULONG)(0 - sizeof(int));
  122. if (FAILED(pStream->Seek(li, STREAM_SEEK_CUR, NULL)))
  123. return E_FAIL;
  124. if (!SUCCEEDED(RecurseLoad410Tree(ppRootCat,pStream,pStorage,mapStreams)))
  125. {
  126. return E_FAIL;
  127. }
  128. // After RecurseLoadTree is through, we should be able to read a -1
  129. // for the next level.
  130. if (FAILED(pStream->Read((void *) &iLevel, sizeof(int), &dwCount)) || dwCount != sizeof(int) || iLevel != -1)
  131. {
  132. return E_FAIL;
  133. }
  134. ASSERT(iLevel == -1 && "unexpected value read after RecurseLoadTree");
  135. }
  136. else
  137. return E_FAIL;
  138. CString strAppend;
  139. strAppend.Format(_T(" (%s)"), strFileName);
  140. (*ppRootCat)->m_strCaption += strAppend;
  141. return S_OK;
  142. }
  143. //-----------------------------------------------------------------------------
  144. // This function (which doesn't really use recursion - the name is left over
  145. // from 4.10 MSInfo) read the category tree from the MSInfo stream and creates
  146. // the necessary COCXFolder objects to represent it.
  147. //-----------------------------------------------------------------------------
  148. HRESULT CMSInfo4Category::RecurseLoad410Tree(CMSInfo4Category** ppRoot, CComPtr<IStream> pStream,CComPtr<IStorage> pStorage,CMapStringToString& mapStreams)
  149. {
  150. // This array of folders is used to keep track of the last folder read
  151. // on each level. This is useful for getting the parent and previous
  152. // sibling when reading a new folder.
  153. CMSInfo4Category* pRoot = NULL;
  154. // The iLevel variable keeps track of the current tree level we are
  155. // reading a folder for. A -1 indicates the end of the tree.
  156. DWORD dwCount;
  157. int iLevel = 1;
  158. if (FAILED(pStream->Read((void *) &iLevel, sizeof(int), &dwCount)) || dwCount != sizeof(int))
  159. return E_FAIL;
  160. int iLastLevel = iLevel;
  161. HRESULT hr;
  162. CMSInfo4Category* pLastCat = NULL;
  163. for(;iLevel != -1;)
  164. {
  165. CMSInfo4Category* pCat = new CMSInfo4Category();
  166. hr = pCat->LoadFromStream(pStream,pStorage);
  167. if (FAILED(hr))
  168. {
  169. delete pCat;
  170. return hr;
  171. }
  172. if (!pRoot)
  173. {
  174. pRoot = pCat;
  175. }
  176. //CString strCLSID(pCat->m_bstrCLSID);
  177. if (!mapStreams.Lookup(pCat->m_strCLSID,pCat->m_strStream))
  178. {
  179. ASSERT(1);
  180. }
  181. if (iLevel == iLastLevel)
  182. {
  183. pCat->m_pPrevSibling = pLastCat;
  184. if (pLastCat)
  185. {
  186. pCat->m_pParent = pLastCat->m_pParent;
  187. pLastCat->m_pNextSibling = pCat;
  188. }
  189. }
  190. else if (iLevel - 1 == iLastLevel)
  191. {
  192. //we've just stepped from parent to child
  193. pCat->m_pPrevSibling = NULL;
  194. if (pLastCat)
  195. {
  196. pCat->m_pParent = pLastCat;
  197. pLastCat->m_pFirstChild = pCat;
  198. }
  199. }
  200. else if (iLevel < iLastLevel)
  201. {
  202. //we need to trace back up chain to find common parent
  203. DWORD iLevelDiff = iLastLevel - iLevel;
  204. for(DWORD i = 0; i < iLevelDiff; i++)
  205. {
  206. if (!pLastCat)
  207. {
  208. break;
  209. }
  210. pLastCat = (CMSInfo4Category*) pLastCat->m_pParent;
  211. }
  212. pCat->m_pPrevSibling = pLastCat;
  213. if (pLastCat)
  214. {
  215. pCat->m_pParent = pLastCat->m_pParent;
  216. pLastCat->m_pNextSibling = pCat;
  217. }
  218. }
  219. pLastCat = pCat;
  220. iLastLevel = iLevel;
  221. if (FAILED(pStream->Read((void *) &iLevel, sizeof(int), &dwCount)) || dwCount != sizeof(int))
  222. return E_FAIL;
  223. }
  224. //a-kjaw
  225. if( CMSInfo4Category::m_bIsControlInstalled == FALSE)
  226. {
  227. CString strCaption, strMessage;
  228. ::AfxSetResourceHandle(_Module.GetResourceInstance());
  229. strCaption.LoadString(IDS_SYSTEMINFO);
  230. strMessage.LoadString(IDS_NOWI2KRESKIT);
  231. ::MessageBox(NULL, strMessage, strCaption, MB_OK | MB_ICONEXCLAMATION);
  232. CMSInfo4Category::m_bIsControlInstalled = TRUE;
  233. }
  234. //a-kjaw
  235. *ppRoot = pRoot;
  236. // We read a -1 to exit the loop, then we are through with the
  237. // category tree. Backup (so any other recursion trees will read
  238. // the -1 as well) and return TRUE.
  239. if (iLevel == -1)
  240. {
  241. LARGE_INTEGER li; li.HighPart = -1; li.LowPart = (ULONG)(0 - sizeof(int));
  242. if (FAILED(pStream->Seek(li, STREAM_SEEK_CUR, NULL)))
  243. return E_FAIL;
  244. }
  245. return S_OK;
  246. }
  247. //-----------------------------------------------------------------------------
  248. // This function creates a CMSInfo4Category object based on the information read
  249. // from the stream.
  250. //-----------------------------------------------------------------------------
  251. HRESULT CMSInfo4Category::LoadFromStream(CComPtr<IStream> pStream,CComPtr<IStorage> pStorage)
  252. {
  253. // Read in the values from the stream. Make sure they're all there before
  254. // we create the COCXFolder.
  255. BOOL fUsesView = FALSE;
  256. BOOL fControl = FALSE;
  257. DWORD dwView = 0;
  258. CLSID clsidCategory;
  259. char szName[100];
  260. if (FAILED(pStream->Read((void *) &fUsesView, sizeof(BOOL), NULL))) return E_FAIL;
  261. if (FAILED(pStream->Read((void *) &fControl, sizeof(BOOL), NULL))) return E_FAIL;
  262. if (FAILED(pStream->Read((void *) &dwView, sizeof(DWORD), NULL))) return E_FAIL;
  263. if (FAILED(pStream->Read((void *) &clsidCategory, sizeof(CLSID), NULL))) return E_FAIL;
  264. if (FAILED(pStream->Read((void *) &szName, sizeof(char) * 100, NULL))) return E_FAIL;
  265. // USES_CONVERSION;
  266. // LPOLESTR lpName = A2W(szName);
  267. this->m_clsid = clsidCategory;
  268. ///////a-kjaw
  269. CComPtr<IUnknown> pUnk;
  270. HRESULT hr = S_OK;
  271. if( !IsEqualGUID(m_clsid , GUID_NULL) )
  272. hr = CoCreateInstance( m_clsid , NULL, CLSCTX_ALL , IID_IUnknown ,
  273. (LPVOID*)&pUnk);
  274. if (FAILED(hr))
  275. {
  276. m_bIsControlInstalled = FALSE;
  277. }
  278. ///////a-kjaw
  279. //StringFromCLSID(this->m_clsid,&m_bstrCLSID);
  280. LPOLESTR lpstrCLSID;
  281. StringFromCLSID(this->m_clsid,&lpstrCLSID);
  282. m_strCLSID = lpstrCLSID;
  283. CoTaskMemFree(lpstrCLSID);
  284. this->m_pStorage = pStorage;
  285. this->m_dwView = dwView;
  286. this->m_strName = szName;
  287. m_strCaption = szName;
  288. return S_OK;
  289. }
  290. HRESULT CMSInfo4Category::Refresh()
  291. {
  292. return S_OK;
  293. }
  294. HRESULT CMSInfo4Category::CreateControl(HWND hWnd,CRect& rct)
  295. {
  296. try
  297. {
  298. /*LPOLESTR lpCLSID;
  299. if (FAILED(StringFromCLSID(m_clsid, &lpCLSID)))
  300. return E_FAIL;*/
  301. HRESULT hr = E_FAIL;
  302. if (m_pUnknown == NULL)
  303. {
  304. hr = CoCreateInstance(m_clsid,NULL,CLSCTX_INPROC_SERVER,IID_IUnknown,(void**) &m_pUnknown);
  305. }
  306. // Get the stream for this control, and load it.
  307. if (!SUCCEEDED(hr))
  308. {
  309. return hr;
  310. }
  311. DWORD grfMode = STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE;
  312. CComPtr<IStream> pStream;
  313. USES_CONVERSION;
  314. CComBSTR bstrStream = m_strStream;//A2W(m_strStream);
  315. hr = m_pStorage->OpenStream(bstrStream, NULL, grfMode, 0, &pStream);
  316. if (!SUCCEEDED(hr))
  317. {
  318. return hr;
  319. }
  320. else
  321. {
  322. COleStreamFile olefile(pStream.Detach());
  323. CMSIControl* p4Ctrl = new CMSIControl(m_clsid);
  324. CWnd* pWnd = CWnd::FromHandle(hWnd);
  325. AfxEnableControlContainer();
  326. //if (!p4Ctrl->Create(NULL, WS_VISIBLE | WS_CHILD, rct, pWnd, 0, &olefile, FALSE, NULL))
  327. if (!p4Ctrl->Create(NULL, /*WS_VISIBLE |*/ WS_CHILD, rct, pWnd, 0, &olefile, FALSE, NULL))
  328. {
  329. return E_FAIL;
  330. }
  331. olefile.Close();
  332. p4Ctrl->MSInfoUpdateView();
  333. p4Ctrl->MSInfoRefresh();
  334. //Add Control and CLSID to map of CLSID's
  335. CMSInfo4Category::s_pNfo4DataSource->AddControlMapping(m_strCLSID,p4Ctrl);
  336. }
  337. }
  338. catch (COleException* pException)
  339. {
  340. ASSERT(0);
  341. pException->Delete();
  342. }
  343. catch (CException* pException)
  344. {
  345. ASSERT(0);
  346. pException->Delete();
  347. }
  348. catch (...)
  349. {
  350. ASSERT(0);
  351. }
  352. return S_OK;
  353. }
  354. //---------------------------------------------------------------------------
  355. // GetDISPID returns the DISPID for a given string, by looking it up using
  356. // IDispatch->GetIDsOfNames. This avoids hardcoding DISPIDs in this class.
  357. //---------------------------------------------------------------------------
  358. BOOL CMSInfo4Category::GetDISPID(IDispatch * pDispatch, LPOLESTR szMember, DISPID *pID)
  359. {
  360. BOOL result = FALSE;
  361. DISPID dispid;
  362. if (SUCCEEDED(pDispatch->GetIDsOfNames(IID_NULL, &szMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid)))
  363. {
  364. *pID = dispid;
  365. result = TRUE;
  366. }
  367. return result;
  368. }
  369. HRESULT CMSInfo4Category::ShowControl(HWND hWnd, CRect rctList, BOOL fShow)
  370. {
  371. try
  372. {
  373. //CString strCLSID(m_bstrCLSID);
  374. CMSIControl* p4Ctrl = NULL;
  375. if (!CMSInfo4Category::s_pNfo4DataSource->GetControlFromCLSID(m_strCLSID,p4Ctrl))
  376. {
  377. if (!SUCCEEDED(CreateControl(hWnd,rctList)))
  378. {
  379. //could not serialize control
  380. return E_FAIL;
  381. }
  382. if(!CMSInfo4Category::s_pNfo4DataSource->GetControlFromCLSID(m_strCLSID,p4Ctrl))
  383. {
  384. if (!IsDisplayableCategory())
  385. {
  386. //this is one of the parent nodes, which does not display info
  387. CMSInfo4Category::s_pNfo4DataSource->UpdateCurrentControl(NULL);
  388. return S_OK;
  389. }
  390. return E_FAIL;
  391. }
  392. }
  393. else
  394. {
  395. ResizeControl(rctList);
  396. }
  397. ASSERT(p4Ctrl && "Invalid OCX pointer");
  398. if (fShow)
  399. {
  400. CMSInfo4Category::s_pNfo4DataSource->UpdateCurrentControl(p4Ctrl);
  401. p4Ctrl->ShowWindow(SW_SHOW);
  402. p4Ctrl->SetMSInfoView(this->m_dwView);
  403. p4Ctrl->MSInfoUpdateView();
  404. p4Ctrl->MSInfoRefresh();
  405. }
  406. else
  407. p4Ctrl->ShowWindow(SW_HIDE);
  408. }
  409. catch (CException* pException)
  410. {
  411. ASSERT(0);
  412. pException->Delete();
  413. }
  414. catch (...)
  415. {
  416. ASSERT(0);
  417. }
  418. return S_OK;
  419. }
  420. //TD: Move into nfodata.cpp?
  421. CNFO4DataSource::CNFO4DataSource()
  422. {
  423. m_pCurrentControl = NULL;
  424. }
  425. CNFO4DataSource::~CNFO4DataSource()
  426. {
  427. CString strKey;
  428. CMSIControl* pCtrl;
  429. // m_pCurrentControl->DestroyWindow();
  430. for(POSITION mapPos = m_mapCLSIDToControl.GetStartPosition( );;)
  431. {
  432. if (!mapPos)
  433. {
  434. break;
  435. }
  436. m_mapCLSIDToControl.GetNextAssoc(mapPos, strKey, (void*&)pCtrl);
  437. pCtrl->DestroyWindow();
  438. delete pCtrl;
  439. }
  440. }
  441. void CNFO4DataSource::UpdateCurrentControl(CMSIControl* pControl)
  442. {
  443. if (m_pCurrentControl && pControl != m_pCurrentControl)
  444. {
  445. m_pCurrentControl->ShowWindow(SW_HIDE);
  446. }
  447. m_pCurrentControl = pControl;
  448. }
  449. //---------------------------------------------------------------------------
  450. // Creates the datasource, and the root CMSInfo4Category
  451. //---------------------------------------------------------------------------
  452. HRESULT CNFO4DataSource::Create(CString strFileName)
  453. {
  454. CMSInfo4Category * pNewRoot = NULL;
  455. CMSInfo4Category::SetDataSource(this);
  456. HRESULT hr = CMSInfo4Category::ReadMSI4NFO(strFileName, &pNewRoot);
  457. if (SUCCEEDED(hr) && pNewRoot)
  458. m_pRoot = pNewRoot;
  459. return hr;
  460. }
  461. void CMSInfo4Category::Print(CMSInfoPrintHelper* pPrintHelper, BOOL bRecursive)
  462. {
  463. #ifdef A_STEPHL
  464. // ASSERT(0);
  465. #endif
  466. CString strOut;
  467. CString strBracket;
  468. VERIFY(strBracket.LoadString(IDS_LEFTBRACKET) && "Failed to find resource IDS_LEFTBRACKET");
  469. strOut = strBracket;
  470. CString strName, strCaption;
  471. GetNames(&strCaption,&strName);
  472. strOut += strCaption;
  473. VERIFY(strBracket.LoadString(IDS_RIGHTBRACKET) && "Failed to find resource IDS_RIGHTBRACKET");
  474. strOut += strBracket;
  475. pPrintHelper->PrintLine("");
  476. pPrintHelper->PrintLine(strOut);
  477. int iRowCount,iColCount;
  478. this->GetCategoryDimensions(&iColCount,&iRowCount);
  479. CString strColHeader;
  480. //TD: put in resources
  481. CString strColSpacing = " ";
  482. pPrintHelper->PrintLine("");
  483. /*if (1 == iColCount && 0 == iRowCount)
  484. {
  485. //this is a parent node, with no data of its own
  486. CString strCatHeading;
  487. strCatHeading.LoadString(IDS_CATEGORYHEADING);
  488. pPrintHelper->PrintLine(strCatHeading);
  489. }*/
  490. // When allocating the
  491. // buffer for the information, allocate 5 extra bytes (1 for the null, and
  492. // 4 to hold "\r\n\r\n").
  493. CString strLine;
  494. CMSIControl* pControl = NULL;
  495. if (!CMSInfo4Category::s_pNfo4DataSource->GetControlFromCLSID(m_strCLSID,pControl))
  496. {
  497. //need to make sure it's not "empty parent" category, like HARDWARE RESOURCES
  498. if ("{00000000-0000-0000-0000-000000000000}" == m_strCLSID)
  499. {
  500. //this is a parent node, with no data of its own
  501. CString strCatHeading;
  502. strCatHeading.LoadString(IDS_CATEGORYHEADING);
  503. pPrintHelper->PrintLine(strCatHeading);
  504. }
  505. else
  506. {
  507. pPrintHelper->PrintLine("");
  508. strLine.LoadString(IDS_NOOCX);
  509. pPrintHelper->PrintLine(strLine);
  510. CString strDetail;
  511. strDetail.LoadString(IDS_NOOCXDETAIL);
  512. pPrintHelper->PrintLine(strDetail);
  513. }
  514. }
  515. else
  516. {
  517. //pControl->SetMSInfoView(this->m_dwView);
  518. //pControl->MSInfoUpdateView();
  519. //pControl->MSInfoRefresh();
  520. long lBufferLength = pControl->MSInfoGetData(m_dwView, NULL, 0);
  521. if (lBufferLength < 0)
  522. {
  523. ASSERT(1);
  524. }
  525. else
  526. {
  527. char * pBuffer = new char[lBufferLength + 5];
  528. if (pBuffer)
  529. {
  530. strcpy(pBuffer, "\r\n\r\n");
  531. if (!pControl->MSInfoGetData(m_dwView, (long *) (&pBuffer[4]), lBufferLength + 1) == lBufferLength)
  532. {
  533. ASSERT(1);
  534. }
  535. else
  536. {
  537. //process pBuffer for strings to print
  538. CString strBuff(pBuffer);
  539. CString strCharSet = _T("\r\n");
  540. strCharSet += _T("\r"); //strCharSet += 10;
  541. strCharSet += _T("\n"); //strCharSet += 13;
  542. /*for(int i = 0; ;)
  543. {
  544. i = strBuff.FindOneOf(strCharSet);
  545. strLine = strBuff.Left(i);
  546. pPrintHelper->PrintLine(strLine);
  547. i+=2;
  548. strBuff = strBuff.Right(strBuff.GetLength() - i);
  549. //a-stephl: to fix OSR4.1 bug#135918
  550. if (i > strBuff.GetLength())
  551. {
  552. pPrintHelper->PrintLine(strBuff);
  553. break;
  554. }
  555. }*/
  556. //a-stephl: to fix OSR4.1 bug#135918
  557. //for(int i = 0; ;)
  558. int i = 0;
  559. while( i > 0)
  560. {
  561. i = strBuff.FindOneOf(strCharSet);
  562. if (-1 == i)
  563. {
  564. pPrintHelper->PrintLine(strBuff);
  565. }
  566. strLine = strBuff.Left(i);
  567. pPrintHelper->PrintLine(strLine);
  568. i+=2;
  569. strBuff = strBuff.Right(strBuff.GetLength() - i);
  570. }
  571. //end a-stephl: to fix OSR4.1 bug#135918
  572. delete pBuffer;
  573. }
  574. }
  575. }
  576. }
  577. if (bRecursive && this->m_pFirstChild != NULL)
  578. {
  579. for(CMSInfo4Category* pChild = (CMSInfo4Category*) this->GetFirstChild();pChild != NULL;pChild = (CMSInfo4Category*) pChild->GetNextSibling())
  580. {
  581. pChild->Print(pPrintHelper,TRUE);
  582. }
  583. }
  584. }
  585. void CMSInfo4Category::Print(HDC hDC, BOOL bRecursive,int nStartPage, int nEndPage)
  586. {
  587. //nStartPage and nEndPage mark a page range to print;
  588. //if both are 0, then print everything
  589. CMSInfoPrintHelper* pPrintHelper = new CMSInfoPrintHelper(hDC,nStartPage,nEndPage);
  590. //header info..do we need this?
  591. // WCHAR wHeader = 0xFEFF;
  592. //pTxtFile->Write( &wHeader, 2);
  593. CTime tNow = CTime::GetCurrentTime();
  594. CString strTimeFormat;
  595. strTimeFormat.LoadString(IDS_TIME_FORMAT);
  596. CString strHeaderText = tNow.Format(strTimeFormat);
  597. pPrintHelper->PrintLine(strHeaderText);
  598. pPrintHelper->PrintLine("");
  599. Print(pPrintHelper,bRecursive);
  600. delete pPrintHelper;
  601. }
  602. HRESULT CMSInfo4Category::RefreshAllForPrint(HWND hWnd, CRect rctList)
  603. {
  604. if (this->m_pFirstChild != NULL)
  605. {
  606. for(CMSInfo4Category* pChild = (CMSInfo4Category*) this->GetFirstChild();pChild != NULL;pChild = (CMSInfo4Category*) pChild->GetNextSibling())
  607. {
  608. CMSIControl* p4Ctrl;
  609. //if (pChild->GetClsid() !=
  610. if (!CMSInfo4Category::s_pNfo4DataSource->GetControlFromCLSID(pChild->m_strCLSID,p4Ctrl))
  611. {
  612. if (FAILED(pChild->CreateControl(hWnd,rctList)))
  613. {
  614. return E_FAIL;
  615. }
  616. if (CMSInfo4Category::s_pNfo4DataSource->GetControlFromCLSID(pChild->m_strCLSID,p4Ctrl))
  617. {
  618. p4Ctrl->ShowWindow(SW_HIDE);
  619. }
  620. else //if (!CMSInfo4Category::s_pNfo4DataSource->GetControlFromCLSID(pChild->m_strCLSID,p4Ctrl))
  621. {
  622. //ASSERT(!pChild->IsDisplayableCategory() && "Invalid Class ID");
  623. //OCX is not installed on this system
  624. }
  625. }
  626. pChild->RefreshAllForPrint(hWnd,rctList);
  627. }
  628. }
  629. return S_OK;
  630. }
  631. BOOL CMSInfo4Category::IsDisplayableCategory()
  632. {
  633. if ("{00000000-0000-0000-0000-000000000000}" == this->m_strCLSID)
  634. {
  635. return FALSE;
  636. }
  637. return TRUE;
  638. }
  639. //-----------------------------------------------------------------------------
  640. //Saves category information as text, recursing children in bRecursive is true
  641. //-----------------------------------------------------------------------------
  642. BOOL CMSInfo4Category::SaveAsText(CMSInfoTextFile* pTxtFile, BOOL bRecursive)
  643. {
  644. CString strOut;
  645. CString strBracket;
  646. VERIFY(strBracket.LoadString(IDS_LEFTBRACKET) && "Failed to find resource IDS_LEFTBRACKET");
  647. strOut = strBracket;
  648. CString strName, strCaption;
  649. GetNames(&strCaption,&strName);
  650. strOut += strCaption;
  651. VERIFY(strBracket.LoadString(IDS_RIGHTBRACKET) && "Failed to find resource IDS_RIGHTBRACKET");
  652. strOut += strBracket;
  653. pTxtFile->WriteString("\r\n\r\n");
  654. pTxtFile->WriteString(strOut);
  655. CMSIControl* pControl = NULL;
  656. if (!CMSInfo4Category::s_pNfo4DataSource->GetControlFromCLSID(m_strCLSID,pControl))
  657. {
  658. ASSERT(1);
  659. }
  660. else
  661. {
  662. pControl->MSInfoUpdateView();
  663. pControl->MSInfoRefresh();
  664. long lBufferLength = pControl->MSInfoGetData(m_dwView, NULL, 0);
  665. if (lBufferLength < 0)
  666. {
  667. ASSERT(1);
  668. }
  669. else
  670. {
  671. char * pBuffer = new char[lBufferLength + 5];
  672. if (pBuffer)
  673. {
  674. strcpy(pBuffer, "\r\n\r\n");
  675. if (!pControl->MSInfoGetData(m_dwView, (long *) (&pBuffer[4]), lBufferLength + 1) == lBufferLength)
  676. {
  677. ASSERT(0 && "could not get data from control");
  678. }
  679. else
  680. {
  681. //process pBuffer for strings to print
  682. CString strBuff(pBuffer);
  683. pTxtFile->WriteString(pBuffer);
  684. delete pBuffer;
  685. }
  686. }
  687. }
  688. }
  689. if (bRecursive && this->m_pFirstChild != NULL)
  690. {
  691. for(CMSInfo4Category* pChild = (CMSInfo4Category*) this->GetFirstChild();pChild != NULL;pChild = (CMSInfo4Category*) pChild->GetNextSibling())
  692. {
  693. pChild->SaveAsText(pTxtFile,TRUE);
  694. }
  695. }
  696. return TRUE;
  697. }