Source code of Windows XP (NT5)
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.

766 lines
18 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. StartD.cpp : implementation file
  5. File History:
  6. JonY Jan-96 created
  7. --*/
  8. #include "stdafx.h"
  9. #include "Mustard.h"
  10. #include "wizlist.h"
  11. #include "StartD.h"
  12. #include "Listdata.h"
  13. #include <winreg.h>
  14. #ifdef _DEBUG
  15. #define new DEBUG_NEW
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. LPITEMIDLIST CreatePIDL(UINT cbSize);
  20. LPITEMIDLIST ConcatPIDLs(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
  21. LPITEMIDLIST Next(LPCITEMIDLIST pidl);
  22. UINT GetSize(LPCITEMIDLIST pidl);
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CStartD dialog
  25. CStartD::CStartD(CWnd* pParent /*=NULL*/)
  26. : CDialog(CStartD::IDD, pParent), m_bActive(TRUE),
  27. m_hAccelTable(NULL)
  28. {
  29. //{{AFX_DATA_INIT(CStartD)
  30. m_bStartup = TRUE;
  31. //}}AFX_DATA_INIT
  32. m_pFont1 = NULL;
  33. m_pFont2 = NULL;
  34. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  35. // Load the accelerator tables.
  36. m_hAccelTable = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1));
  37. }
  38. CStartD::~CStartD()
  39. {
  40. if (m_pFont1 != NULL) delete m_pFont1;
  41. // if (m_pFont2 != NULL) delete m_pFont2;
  42. }
  43. void CStartD::DoDataExchange(CDataExchange* pDX)
  44. {
  45. CDialog::DoDataExchange(pDX);
  46. //{{AFX_DATA_MAP(CStartD)
  47. DDX_Control(pDX, IDC_WIZ_LIST2, m_lbWizList2);
  48. DDX_Control(pDX, IDC_WIZ_LIST, m_lbWizList);
  49. DDX_Check(pDX, IDC_STARTUP, m_bStartup);
  50. //}}AFX_DATA_MAP
  51. }
  52. BEGIN_MESSAGE_MAP(CStartD, CDialog)
  53. //{{AFX_MSG_MAP(CStartD)
  54. ON_WM_PAINT()
  55. ON_BN_CLICKED(IDC_QUIT_BUTTON, OnQuitButton)
  56. ON_WM_ACTIVATEAPP()
  57. ON_WM_QUERYDRAGICON()
  58. ON_WM_MOUSEMOVE()
  59. //}}AFX_MSG_MAP
  60. ON_COMMAND(ID_ACCEL_GROUP, OnAccelGroup)
  61. ON_COMMAND(ID_ACCEL_MODEM, OnAccelModem)
  62. ON_COMMAND(ID_ACCEL_NETWORK, OnAccelNetwork)
  63. ON_COMMAND(ID_ACCEL_PRINT, OnAccelPrint)
  64. ON_COMMAND(ID_ACCEL_SHARE, OnAccelShare)
  65. ON_COMMAND(ID_ACCEL_USER, OnAccelUser)
  66. ON_COMMAND(ID_ACCEL_PROGRAMS, OnAccelPrograms)
  67. ON_COMMAND(ID_ACCEL_LICENSE, OnAccelLicense)
  68. END_MESSAGE_MAP()
  69. /////////////////////////////////////////////////////////////////////////////
  70. // CStartD message handlers
  71. BOOL CStartD::OnInitDialog()
  72. {
  73. CDialog::OnInitDialog();
  74. // tell the two sides about each other
  75. m_lbWizList2.m_pOtherGuy = &m_lbWizList;
  76. m_lbWizList.m_pOtherGuy = &m_lbWizList2;
  77. SetIcon(m_hIcon, TRUE); // Set big icon
  78. SetIcon(m_hIcon, FALSE); // Set small icon
  79. // font information for the headings
  80. m_pFont1 = new CFont;
  81. LOGFONT lf;
  82. memset(&lf, 0, sizeof(LOGFONT)); // Clear out structure.
  83. CString fontname;
  84. fontname.LoadString(IDS_FONT_NAME);
  85. _tcscpy(lf.lfFaceName, fontname);
  86. CString fontheight;
  87. fontheight.LoadString(IDS_BIGFONT_SIZE);
  88. lf.lfHeight = (LONG)_tcstoul(fontheight, NULL, 10);
  89. lf.lfWeight = 700;
  90. m_pFont1->CreateFontIndirect(&lf); // Create the font.
  91. CString cs;
  92. cs.LoadString(IDS_CAPTION);
  93. CWnd* pWnd = GetDlgItem(IDC_STATIC1);
  94. pWnd->SetWindowText(cs);
  95. pWnd->SetFont(m_pFont1);
  96. CMustardApp* pApp = (CMustardApp*)AfxGetApp();
  97. // get install dir
  98. TCHAR pSysDir[256];
  99. UINT nLen = GetWindowsDirectory(pSysDir, 256);
  100. if (*(pSysDir + nLen) != '\\') _tcscat(pSysDir, L"\\");
  101. _tcscat(pSysDir, L"SYSTEM32\\");
  102. // Add User
  103. CItemData* pData = new CItemData;
  104. pData->csName.LoadString(IDS_USER_NAME);// = L"Add User";
  105. pData->csDesc.LoadString(IDS_USER_DESC);// = L"Add User";
  106. pData->csAppStart1 = pSysDir + CString(L"addusrw.exe");
  107. pData->csAppStart2 = L"";
  108. GetIconIndices(pData->csAppStart1, &pData->hIcon, &pData->hSelIcon);
  109. m_lbWizList.InsertString(0, _T(""));
  110. m_lbWizList.SetItemData(0, (LONG_PTR)pData);
  111. // Group Creation
  112. pData = new CItemData;
  113. pData->csName.LoadString(IDS_GROUP_NAME);// = L"Group Creation";
  114. pData->csDesc.LoadString(IDS_GROUP_DESC);// = L"Group Creation";
  115. pData->csAppStart1 = pSysDir + CString(L"addgrpw.exe");
  116. pData->csAppStart2 = L"";
  117. GetIconIndices(pData->csAppStart1, &pData->hIcon, &pData->hSelIcon);
  118. m_lbWizList.InsertString(1, _T(""));
  119. m_lbWizList.SetItemData(1, (LONG_PTR)pData);
  120. // Share Publishing / folder security
  121. pData = new CItemData;
  122. pData->csName.LoadString(IDS_SHRPUB_NAME);// = L"Share Publishing";
  123. pData->csDesc.LoadString(IDS_SHRPUB_DESC);// = L"Share Publishing ";
  124. pData->csAppStart1 = pSysDir + CString(L"shrpubw.exe");
  125. pData->csAppStart2 = L"";
  126. GetIconIndices(pData->csAppStart1, &pData->hIcon, &pData->hSelIcon);
  127. m_lbWizList.InsertString(2, _T(""));
  128. m_lbWizList.SetItemData(2, (LONG_PTR)pData);
  129. // printer
  130. pData = new CItemData;
  131. pData->csName.LoadString(IDS_PRINT_NAME);// = L"Add Printer";
  132. pData->csDesc.LoadString(IDS_PRINT_DESC);// = L"Print manager";
  133. pData->csAppStart1 = L"";
  134. pData->csAppStart2 = L"";
  135. GetCPLIcon(IDS_ADD_PRINTER, &pData->hIcon, &pData->hSelIcon, TRUE);
  136. m_lbWizList.InsertString(3, _T(""));
  137. m_lbWizList.SetItemData(3, (LONG_PTR)pData);
  138. // Add/remove software
  139. pData = new CItemData;
  140. pData->csName.LoadString(IDS_ARS_NAME);// = L"Add/Remove software";
  141. pData->csDesc.LoadString(IDS_ARS_DESC);// = L"Add/Remove software";
  142. pData->csAppStart1 = L"control.exe";
  143. pData->csAppStart2 = L"appwiz.cpl";
  144. GetCPLIcon(IDS_APPWIZ, &pData->hIcon, &pData->hSelIcon);
  145. m_lbWizList2.InsertString(0, _T(""));
  146. m_lbWizList2.SetItemData(0, (LONG_PTR)pData);
  147. // modem
  148. pData = new CItemData;
  149. pData->csName.LoadString(IDS_MODEM_NAME);// = L"Add Modem";
  150. pData->csDesc.LoadString(IDS_MODEM_DESC);// = L"Modems, ports, etc";
  151. pData->csAppStart1 = L"control.exe";
  152. pData->csAppStart2 = L"modem.cpl";
  153. GetCPLIcon(IDS_MODEM, &pData->hIcon, &pData->hSelIcon);
  154. m_lbWizList2.InsertString(1, _T(""));
  155. m_lbWizList2.SetItemData(1, (LONG_PTR)pData);
  156. // Workstation installation
  157. pData = new CItemData;
  158. pData->csName.LoadString(IDS_WKSSETUP_NAME);// = L"Workstation Installation";
  159. pData->csDesc.LoadString(IDS_WKSSETUP_DESC);// = L"Workstation Installation";
  160. pData->csAppStart1 = pSysDir + CString(L"ncadmin.exe");
  161. pData->csAppStart2 = L"";
  162. GetIconIndices(pData->csAppStart1, &pData->hIcon, &pData->hSelIcon);
  163. m_lbWizList2.InsertString(2, _T(""));
  164. m_lbWizList2.SetItemData(2, (LONG_PTR)pData);
  165. // license compliancy
  166. pData = new CItemData;
  167. pData->csName.LoadString(IDS_FDS_NAME);
  168. pData->csDesc.LoadString(IDS_FDS_DESC);
  169. pData->csAppStart1 = pSysDir + CString(L"lcwiz.exe");
  170. pData->csAppStart2 = L"";
  171. GetIconIndices(pData->csAppStart1, &pData->hIcon, &pData->hSelIcon);
  172. m_lbWizList2.InsertString(3, _T(""));
  173. m_lbWizList2.SetItemData(3, (LONG_PTR)pData);
  174. // check the registry to see if we are loaded automatically at startup
  175. DWORD dwRet;
  176. HKEY hKey;
  177. DWORD cbProv = 0;
  178. TCHAR* lpProv = NULL;
  179. dwRet = RegOpenKey(HKEY_CURRENT_USER,
  180. TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"), &hKey );
  181. TCHAR* lpStartup = NULL;
  182. if ((dwRet = RegQueryValueEx( hKey, TEXT("run"), NULL, NULL, NULL, &cbProv )) == ERROR_SUCCESS)
  183. {
  184. lpStartup = (TCHAR*)malloc(cbProv);
  185. if (lpStartup == NULL)
  186. {
  187. AfxMessageBox(IDS_GENERIC_NO_HEAP, MB_ICONEXCLAMATION);
  188. ExitProcess(1);
  189. }
  190. dwRet = RegQueryValueEx( hKey, TEXT("run"), NULL, NULL, (LPBYTE) lpStartup, &cbProv );
  191. // see if we are included
  192. if (_tcsstr(lpStartup, L"wizmgr.exe") != NULL)
  193. m_bStartup = TRUE;
  194. else m_bStartup = FALSE;
  195. UpdateData(FALSE);
  196. }
  197. free(lpStartup);
  198. RegCloseKey(hKey);
  199. return TRUE; // return TRUE unless you set the focus to a control
  200. // EXCEPTION: OCX Property Pages should return FALSE
  201. }
  202. void CStartD::OnPaint()
  203. {
  204. CPaintDC dc(this); // device context for painting
  205. if (IsIconic())
  206. {
  207. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  208. // Center icon in client rectangle
  209. int cxIcon = GetSystemMetrics(SM_CXICON);
  210. int cyIcon = GetSystemMetrics(SM_CYICON);
  211. CRect rect;
  212. GetClientRect(&rect);
  213. int x = (rect.Width() - cxIcon + 1) / 2;
  214. int y = (rect.Height() - cyIcon + 1) / 2;
  215. // Draw the icon
  216. dc.DrawIcon(x, y, m_hIcon);
  217. }
  218. else
  219. {
  220. CPen pBlackPen(PS_SOLID, 1, RGB(0,0,0));
  221. CPen* pOriginalPen = (CPen*)dc.SelectObject(pBlackPen);
  222. dc.MoveTo(596, 77);
  223. dc.LineTo(2, 77);
  224. dc.LineTo(2, 362);
  225. CPen pLtGreyPen(PS_SOLID, 1, RGB(192, 192, 192));
  226. dc.SelectObject(pLtGreyPen);
  227. dc.LineTo(596, 362);
  228. dc.LineTo(596, 77);
  229. CPen pDkGreyPen(PS_SOLID, 1, RGB(128, 128, 128));
  230. dc.SelectObject(pDkGreyPen);
  231. dc.MoveTo(597, 76);
  232. dc.LineTo(1, 76);
  233. dc.LineTo(1, 363);
  234. CPen pWhitePen(PS_SOLID, 1, RGB(255, 255, 255));
  235. dc.SelectObject(pWhitePen);
  236. dc.MoveTo(2, 363);
  237. dc.LineTo(598, 363);
  238. dc.LineTo(598, 76);
  239. }
  240. // Do not call CDialog::OnPaint() for painting messages
  241. }
  242. HCURSOR CStartD::OnQueryDragIcon()
  243. {
  244. return (HCURSOR) m_hIcon;
  245. }
  246. void CStartD::OnQuitButton()
  247. {
  248. CItemData* pData;
  249. ULONG_PTR lData;
  250. USHORT us = 0;
  251. while((lData = m_lbWizList.GetItemData(us)) != LB_ERR)
  252. {
  253. pData = (CItemData*)lData;
  254. delete pData;
  255. m_lbWizList.DeleteString(us);
  256. }
  257. while((lData = m_lbWizList2.GetItemData(us)) != LB_ERR)
  258. {
  259. pData = (CItemData*)lData;
  260. delete pData;
  261. m_lbWizList2.DeleteString(us);
  262. }
  263. // set the reg value for startup
  264. UpdateData(TRUE);
  265. DWORD dwRet;
  266. HKEY hKey;
  267. DWORD cbProv = 0;
  268. TCHAR* lpProv = NULL;
  269. dwRet = RegOpenKey(HKEY_CURRENT_USER,
  270. TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"), &hKey );
  271. TCHAR* lpStartup = NULL;
  272. if ((dwRet = RegQueryValueEx( hKey, TEXT("run"), NULL, NULL, NULL, &cbProv )) == ERROR_SUCCESS)
  273. {
  274. lpStartup = (TCHAR*)malloc(cbProv);
  275. if (lpStartup == NULL)
  276. {
  277. AfxMessageBox(IDS_GENERIC_NO_HEAP, MB_ICONEXCLAMATION);
  278. ExitProcess(1);
  279. }
  280. dwRet = RegQueryValueEx( hKey, TEXT("run"), NULL, NULL, (LPBYTE) lpStartup, &cbProv );
  281. // see if we are included
  282. TCHAR* pPos;
  283. if ((pPos = _tcsstr(lpStartup, L"wizmgr.exe")) != NULL) // included
  284. {
  285. if (!m_bStartup) // don't want to be
  286. {
  287. UINT nPos = (UINT)(pPos - lpStartup);
  288. CString csCurrentValue = lpStartup;
  289. CString csNewVal = csCurrentValue.Left(nPos);
  290. csNewVal += csCurrentValue.Right(csCurrentValue.GetLength() - nPos - _tcslen(L"wizmgr.exe"));
  291. RegSetValueEx(hKey,
  292. TEXT("run"),
  293. 0,
  294. REG_SZ,
  295. (BYTE *)csNewVal.GetBuffer(csNewVal.GetLength()),
  296. csNewVal.GetLength() * sizeof(TCHAR));
  297. }
  298. }
  299. else // not included
  300. {
  301. if (m_bStartup) // want to be
  302. {
  303. CString csNewVal = lpStartup;
  304. csNewVal += L" wizmgr.exe";
  305. RegSetValueEx(hKey,
  306. TEXT("run"),
  307. 0,
  308. REG_SZ,
  309. (BYTE *)csNewVal.GetBuffer(csNewVal.GetLength()),
  310. csNewVal.GetLength() * sizeof(TCHAR));
  311. }
  312. }
  313. UpdateData(FALSE);
  314. }
  315. free(lpStartup);
  316. RegCloseKey(hKey);
  317. EndDialog(1);
  318. }
  319. void CStartD::OnActivateApp(BOOL bActive, HTASK hTask)
  320. {
  321. CDialog::OnActivateApp(bActive, hTask);
  322. m_bActive = bActive;
  323. // Remove the selections from the list boxes if
  324. // the application is being deactivated.
  325. if (!m_bActive)
  326. {
  327. m_lbWizList.SetCurSel(-1);
  328. m_lbWizList2.SetCurSel(-1);
  329. }
  330. }
  331. void CStartD::OnMouseMove(UINT nFlags, CPoint point)
  332. {
  333. if (m_bActive)
  334. {
  335. // Remove the selection from the list boxes if
  336. // the mouse has moved outside of them.
  337. m_lbWizList.SetCurSel(-1);
  338. m_lbWizList2.SetCurSel(-1);
  339. }
  340. CDialog::OnMouseMove(nFlags, point);
  341. }
  342. BOOL CStartD::PreTranslateMessage(MSG* pMsg)
  343. {
  344. if (m_hAccelTable != NULL)
  345. {
  346. if (!TranslateAccelerator(GetSafeHwnd(), m_hAccelTable, pMsg) )
  347. return CDialog::PreTranslateMessage(pMsg);
  348. else
  349. return TRUE;
  350. }
  351. return CDialog::PreTranslateMessage(pMsg);
  352. }
  353. void CStartD::HandleAccelerator1(USHORT nIndex)
  354. {
  355. // Change the selection in the listbox and
  356. // make it think it's been clicked.
  357. // Remove the selection from the other listbox, too.
  358. m_lbWizList.SetCurSel(nIndex);
  359. m_lbWizList2.SetCurSel(-1);
  360. m_lbWizList.PostMessage(WM_LBUTTONDOWN);
  361. }
  362. void CStartD::HandleAccelerator2(USHORT nIndex)
  363. {
  364. m_lbWizList2.SetCurSel(nIndex);
  365. m_lbWizList.SetCurSel(-1);
  366. m_lbWizList2.PostMessage(WM_LBUTTONDOWN);
  367. }
  368. void CStartD::OnAccelUser()
  369. {
  370. HandleAccelerator1(ACCEL_USER);
  371. }
  372. void CStartD::OnAccelGroup()
  373. {
  374. HandleAccelerator1(ACCEL_GROUP);
  375. }
  376. void CStartD::OnAccelShare()
  377. {
  378. HandleAccelerator1(ACCEL_SHARE);
  379. }
  380. void CStartD::OnAccelPrint()
  381. {
  382. HandleAccelerator1(ACCEL_PRINT);
  383. }
  384. void CStartD::OnAccelPrograms()
  385. {
  386. HandleAccelerator2(ACCEL_PROGRAMS);
  387. }
  388. void CStartD::OnAccelModem()
  389. {
  390. HandleAccelerator2(ACCEL_MODEM);
  391. }
  392. void CStartD::OnAccelNetwork()
  393. {
  394. HandleAccelerator2(ACCEL_NETWORK);
  395. }
  396. void CStartD::OnAccelLicense()
  397. {
  398. HandleAccelerator2(ACCEL_LICENSE);
  399. }
  400. void CStartD::GetIconIndices(LPCTSTR pszPathName, HICON* hiNormal, HICON* hiSelected)
  401. {
  402. SHFILEINFO sfi;
  403. // Get the index for the normal icon.
  404. SHGetFileInfo(pszPathName, 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_LARGEICON);
  405. *hiNormal = sfi.hIcon;
  406. // Get the index for the selected icon.
  407. SHGetFileInfo(pszPathName, 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_LARGEICON | SHGFI_SELECTED);
  408. *hiSelected = sfi.hIcon;
  409. }
  410. void CStartD::GetCPLIcon(UINT pszCplItem, HICON* hiNormal, HICON* hiSelected, BOOL bPrinters)
  411. {
  412. LPSHELLFOLDER pshf, pshfCPLItem;
  413. LPITEMIDLIST pidlCPLFolder, pidlCPLObj;
  414. LPMALLOC pMalloc;
  415. HRESULT hr;
  416. // Get a pointer to the shell's IMalloc interface.
  417. hr = SHGetMalloc(&pMalloc);
  418. if (SUCCEEDED(hr) && pMalloc) // JonN 01/26/00: PREFIX bug 445827
  419. {
  420. // Get a pointer to the shell's IShellFolder interface.
  421. hr = SHGetDesktopFolder(&pshf);
  422. if (SUCCEEDED(hr))
  423. {
  424. // Get a PIDL for the specified folder.
  425. if (!bPrinters)
  426. hr = SHGetSpecialFolderLocation(GetSafeHwnd(), CSIDL_CONTROLS, &pidlCPLFolder);
  427. else
  428. hr = SHGetSpecialFolderLocation(GetSafeHwnd(), CSIDL_PRINTERS, &pidlCPLFolder);
  429. if (SUCCEEDED(hr))
  430. {
  431. hr = pshf->BindToObject(pidlCPLFolder, NULL, IID_IShellFolder, (LPVOID*)&pshfCPLItem);
  432. if (SUCCEEDED(hr))
  433. GetCPLObject(pszCplItem, pshfCPLItem, &pidlCPLObj, hiNormal, hiSelected, pidlCPLFolder);
  434. }
  435. pMalloc->Free(pidlCPLFolder);
  436. }
  437. pMalloc->Release();
  438. }
  439. }
  440. HRESULT CStartD::GetCPLObject(UINT pszCplItem, LPSHELLFOLDER pshf, LPITEMIDLIST* ppidl, HICON* hiNormal, HICON* hiSelected, LPITEMIDLIST pParentPIDL)
  441. {
  442. HRESULT hr;
  443. LPENUMIDLIST pEnum;
  444. LPMALLOC pMalloc;
  445. // Get a pointer to the shell's IMalloc interface.
  446. hr = SHGetMalloc(&pMalloc);
  447. if (SUCCEEDED(hr))
  448. {
  449. // Get a pointer to the folder's IEnumIDList interface.
  450. hr = pshf->EnumObjects(GetSafeHwnd(), SHCONTF_NONFOLDERS, &pEnum);
  451. if (SUCCEEDED(hr))
  452. {
  453. STRRET str;
  454. CString strCPLObj, strEnumObj;
  455. // Load the display name for the control panel object.
  456. strCPLObj.LoadString(pszCplItem);
  457. // Enumerate the objects in the control panel folder.
  458. while (pEnum->Next(1, ppidl, NULL) == NOERROR)
  459. {
  460. // Get the display name for the object.
  461. hr = pshf->GetDisplayNameOf((LPCITEMIDLIST)*ppidl, SHGDN_INFOLDER, &str);
  462. if (SUCCEEDED(hr))
  463. {
  464. // Copy the display name to the strEnumObj string.
  465. switch (str.uType)
  466. {
  467. case STRRET_CSTR:
  468. strEnumObj = str.cStr;
  469. break;
  470. case STRRET_OFFSET:
  471. char pStr[255];
  472. strcpy(pStr, (LPCSTR)(((UINT_PTR)*ppidl) + str.uOffset));
  473. TCHAR wStr[255];
  474. mbstowcs(wStr, pStr, 255);
  475. strEnumObj = wStr;
  476. break;
  477. case STRRET_WSTR:
  478. strEnumObj = str.pOleStr;
  479. break;
  480. case 0x04:
  481. strEnumObj = (LPCTSTR)(((UINT_PTR)*ppidl) + str.uOffset);
  482. break;
  483. case 0x05:
  484. {
  485. TCHAR pStr[255];
  486. memcpy(pStr, str.cStr, 255);
  487. strEnumObj = pStr;
  488. break;
  489. }
  490. default:
  491. strEnumObj.Empty();
  492. }
  493. // If we found the correct object, exit the loop.
  494. if (strCPLObj == strEnumObj)
  495. {
  496. LPITEMIDLIST pBigPIDL = ConcatPIDLs(pParentPIDL, *ppidl);
  497. SHFILEINFO sfi;
  498. // Get the index for the normal icon.
  499. SHGetFileInfo((LPCTSTR)pBigPIDL, 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_LARGEICON | SHGFI_PIDL);
  500. *hiNormal = sfi.hIcon;
  501. // Get the index for the selected icon.
  502. SHGetFileInfo((LPCTSTR)pBigPIDL, 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_LARGEICON | SHGFI_SELECTED | SHGFI_PIDL);
  503. *hiSelected = sfi.hIcon;
  504. }
  505. // Free the PIDL returned by IEnumIDList::Next().
  506. pMalloc->Free(*ppidl);
  507. if (FAILED(hr))
  508. {
  509. TRACE(_T("IMalloc::Free failed.\n"));
  510. break;
  511. }
  512. }
  513. else
  514. {
  515. TRACE(_T("IShellFolder::GetDisplayNameOf failed.\n"));
  516. }
  517. }
  518. // Release the IEnumIDList pointer.
  519. pEnum->Release();
  520. }
  521. else
  522. {
  523. TRACE(_T("IShellFolder::EnumObjects failed.\n"));
  524. }
  525. // Release the IMalloc pointer.
  526. pMalloc->Release();
  527. }
  528. return hr;
  529. }
  530. /****************************************************************************
  531. *
  532. * FUNCTION: Create(UINT cbSize)
  533. *
  534. * PURPOSE: Allocates a PIDL
  535. *
  536. ****************************************************************************/
  537. LPITEMIDLIST CreatePIDL(UINT cbSize)
  538. {
  539. LPMALLOC lpMalloc;
  540. HRESULT hr;
  541. LPITEMIDLIST pidl=NULL;
  542. hr=SHGetMalloc(&lpMalloc);
  543. if (FAILED(hr))
  544. return 0;
  545. pidl=(LPITEMIDLIST)lpMalloc->Alloc(cbSize);
  546. if (pidl)
  547. memset(pidl, 0, cbSize); // zero-init for external task alloc
  548. if (lpMalloc) lpMalloc->Release();
  549. return pidl;
  550. }
  551. /****************************************************************************
  552. *
  553. * FUNCTION: ConcatPidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  554. *
  555. * PURPOSE: Concatenates two PIDLs
  556. *
  557. ****************************************************************************/
  558. LPITEMIDLIST ConcatPIDLs(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  559. {
  560. LPITEMIDLIST pidlNew;
  561. UINT cb1;
  562. UINT cb2;
  563. if (pidl1) //May be NULL
  564. cb1 = GetSize(pidl1) - sizeof(pidl1->mkid.cb);
  565. else
  566. cb1 = 0;
  567. cb2 = GetSize(pidl2);
  568. pidlNew = CreatePIDL(cb1 + cb2);
  569. if (pidlNew)
  570. {
  571. if (pidl1)
  572. memcpy(pidlNew, pidl1, cb1);
  573. memcpy(((LPSTR)pidlNew) + cb1, pidl2, cb2);
  574. }
  575. return pidlNew;
  576. }
  577. /****************************************************************************
  578. *
  579. * FUNCTION: Next(LPCITEMIDLIST pidl)
  580. *
  581. * PURPOSE: Gets the next PIDL in the list
  582. *
  583. ****************************************************************************/
  584. LPITEMIDLIST Next(LPCITEMIDLIST pidl)
  585. {
  586. LPSTR lpMem=(LPSTR)pidl;
  587. lpMem+=pidl->mkid.cb;
  588. return (LPITEMIDLIST)lpMem;
  589. }
  590. /****************************************************************************
  591. *
  592. * FUNCTION: GetSize(LPCITEMIDLIST pidl)
  593. *
  594. * PURPOSE: Gets the size of the PIDL
  595. *
  596. ****************************************************************************/
  597. UINT GetSize(LPCITEMIDLIST pidl)
  598. {
  599. UINT cbTotal = 0;
  600. if (pidl)
  601. {
  602. cbTotal += sizeof(pidl->mkid.cb); // Null terminator
  603. while (pidl->mkid.cb)
  604. {
  605. cbTotal += pidl->mkid.cb;
  606. pidl = Next(pidl);
  607. }
  608. }
  609. return cbTotal;
  610. }