home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / shell / regview / pidlmgr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-27  |  22.5 KB  |  953 lines

  1. /**************************************************************************
  2.    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3.    ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4.    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5.    PARTICULAR PURPOSE.
  6.  
  7.    Copyright 1997 Microsoft Corporation.  All Rights Reserved.
  8. **************************************************************************/
  9.  
  10. /**************************************************************************
  11.  
  12.    File:          PidlMgr.cpp
  13.    
  14.    Description:   Implements CPidlMgr.
  15.  
  16. **************************************************************************/
  17.  
  18. /**************************************************************************
  19.    #include statements
  20. **************************************************************************/
  21.  
  22. #include "PidlMgr.h"
  23. #include "ShlFldr.h"
  24. #include "resource.h"
  25.  
  26. /**************************************************************************
  27.  
  28.    CPidlMgr::CPidlMgr
  29.  
  30. **************************************************************************/
  31.  
  32. CPidlMgr::CPidlMgr()
  33. {
  34. //get the shell's IMalloc pointer
  35. //we'll keep this until we get destroyed
  36. if(FAILED(SHGetMalloc(&m_pMalloc)))
  37.    {
  38.    delete this;
  39.    }
  40.  
  41. g_DllRefCount++;
  42. }
  43.  
  44. /**************************************************************************
  45.  
  46.    CPidlMgr::~CPidlMgr
  47.  
  48. **************************************************************************/
  49.  
  50. CPidlMgr::~CPidlMgr()
  51. {
  52. if(m_pMalloc)
  53.    m_pMalloc->Release();
  54.  
  55. g_DllRefCount--;
  56. }
  57.  
  58. /**************************************************************************
  59.  
  60.    CPidlMgr::Create(DWORD, LPVOID, DWORD)
  61.  
  62.    Creates a new PIDL
  63.    
  64. **************************************************************************/
  65.  
  66. LPITEMIDLIST CPidlMgr::Create(PIDLTYPE type, LPVOID pIn, USHORT uInSize)
  67. {
  68. LPITEMIDLIST   pidlOut;
  69. USHORT         uSize;
  70.  
  71. pidlOut = NULL;
  72.  
  73. /*
  74. Calculate the size. This consists of the ITEMIDLIST, the PIDL structure plus 
  75. the size of the data. We subtract the size of an HKEY because that is included 
  76. in uInSize.
  77. */
  78. uSize = sizeof(ITEMIDLIST) + (sizeof(PIDLDATA) - sizeof(HKEY)) + uInSize;
  79.  
  80. /*
  81. Allocate the memory, adding an additional ITEMIDLIST for the NULL terminating 
  82. ID List.
  83. */
  84. pidlOut = (LPITEMIDLIST)m_pMalloc->Alloc(uSize + sizeof(ITEMIDLIST));
  85.  
  86. if(pidlOut)
  87.    {
  88.    LPITEMIDLIST   pidlTemp = pidlOut;
  89.    LPPIDLDATA     pData;
  90.  
  91.    //set the size of this item
  92.    pidlTemp->mkid.cb = uSize;
  93.  
  94.    //set the data for this item
  95.    pData = GetDataPointer(pidlTemp);
  96.    pData->type = type;
  97.    switch(type)
  98.       {
  99.       case PT_ROOTKEY:
  100.          pData->hRootKey = *(HKEY*)pIn;
  101.          break;
  102.  
  103.       case PT_SUBKEY:
  104.       case PT_VALUE:
  105.          CopyMemory(pData->szText, pIn, uInSize);
  106.          break;
  107.       }
  108.    
  109.    //set the NULL terminator to 0
  110.    pidlTemp = GetNextItem(pidlTemp);
  111.    pidlTemp->mkid.cb = 0;
  112.    pidlTemp->mkid.abID[0] = 0;
  113.    }
  114.  
  115. return pidlOut;
  116. }
  117.  
  118. /**************************************************************************
  119.  
  120.    CPidlMgr::Delete(HKEY)
  121.  
  122.    Deletes a PIDL
  123.    
  124. **************************************************************************/
  125.  
  126. void CPidlMgr::Delete(LPITEMIDLIST pidl)
  127. {
  128. m_pMalloc->Free(pidl);
  129. }
  130.  
  131. /**************************************************************************
  132.  
  133.    CPidlMgr::CreateRootKey()
  134.  
  135.    Creates a root key PIDL
  136.    
  137. **************************************************************************/
  138.  
  139. LPITEMIDLIST CPidlMgr::CreateRootKey(HKEY hKeyRoot)
  140. {
  141. return Create(PT_ROOTKEY, (LPVOID)&hKeyRoot, sizeof(hKeyRoot));
  142. }
  143.  
  144. /**************************************************************************
  145.  
  146.    CPidlMgr::CreateSubKey()
  147.  
  148.    Creates a sub key PIDL
  149.    
  150. **************************************************************************/
  151.  
  152. LPITEMIDLIST CPidlMgr::CreateSubKey(LPCTSTR lpszNew)
  153. {
  154. return Create(PT_SUBKEY, (LPVOID)lpszNew, (lstrlen(lpszNew) + 1) * sizeof(TCHAR));
  155. }
  156.  
  157. /**************************************************************************
  158.  
  159.    CPidlMgr::CreateValue()
  160.  
  161.    Creates a value PIDL
  162.    
  163. **************************************************************************/
  164.  
  165. LPITEMIDLIST CPidlMgr::CreateValue(LPCTSTR lpszNew)
  166. {
  167. return Create(PT_VALUE, (LPVOID)lpszNew, (lstrlen(lpszNew) + 1) * sizeof(TCHAR));
  168. }
  169.  
  170. /**************************************************************************
  171.  
  172.    CPidlMgr::GetNextItem()
  173.    
  174. **************************************************************************/
  175.  
  176. LPITEMIDLIST CPidlMgr::GetNextItem(LPCITEMIDLIST pidl)
  177. {
  178. if(pidl)
  179.    return (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
  180. else
  181.    return (NULL);
  182. }
  183.  
  184. /**************************************************************************
  185.  
  186.    CPidlMgr::GetSize()
  187.    
  188. **************************************************************************/
  189.  
  190. UINT CPidlMgr::GetSize(LPCITEMIDLIST pidl)
  191. {
  192. UINT cbTotal = 0;
  193. LPITEMIDLIST pidlTemp = (LPITEMIDLIST) pidl;
  194.  
  195. if(pidlTemp)
  196.    {
  197.    while(pidlTemp->mkid.cb)
  198.       {
  199.       cbTotal += pidlTemp->mkid.cb;
  200.       pidlTemp = GetNextItem(pidlTemp);
  201.       }  
  202.  
  203.    //add the size of the NULL terminating ITEMIDLIST
  204.    cbTotal += sizeof(ITEMIDLIST);
  205.    }
  206.  
  207. return (cbTotal);
  208. }
  209.  
  210. /**************************************************************************
  211.  
  212.    CPidlMgr::GetData(PIDLTYPE, LPCITEMIDLIST, LPVOID, USHORT)
  213.    
  214. **************************************************************************/
  215.  
  216. DWORD CPidlMgr::GetData(PIDLTYPE type, LPCITEMIDLIST pidl, LPVOID pOut, USHORT uOutSize)
  217. {
  218. if(!pidl)
  219.    return 0;
  220.  
  221. LPPIDLDATA  pData = GetDataPointer(pidl);
  222. DWORD       dwReturn = 0;
  223.  
  224. //copy the data
  225. switch(type)
  226.    {
  227.    case PT_ROOTKEY:
  228.       if(uOutSize < sizeof(HKEY))
  229.          return 0;
  230.       
  231.       if(PT_ROOTKEY != pData->type)
  232.          return 0;
  233.       
  234.       *(HKEY*)pOut = pData->hRootKey;
  235.       dwReturn = sizeof(pData->hRootKey);
  236.       break;
  237.  
  238.    case PT_SUBKEY:
  239.    case PT_VALUE:
  240.    case PT_TEXT:
  241.       *(LPTSTR)pOut = 0;
  242.       lstrcpyn((LPTSTR)pOut, pData->szText, uOutSize);
  243.       dwReturn = lstrlen((LPTSTR)pOut);
  244.       break;
  245.    }
  246.  
  247. return dwReturn;
  248. }
  249.  
  250. /**************************************************************************
  251.  
  252.    CPidlMgr::GetRootKey()
  253.    
  254. **************************************************************************/
  255.  
  256. BOOL CPidlMgr::GetRootKey(LPCITEMIDLIST pidl, HKEY *phKeyRoot)
  257. {
  258. return (BOOL)GetData(PT_ROOTKEY, pidl, (LPVOID)phKeyRoot, sizeof(HKEY));
  259. }
  260.  
  261. /**************************************************************************
  262.  
  263.    CPidlMgr::GetLastItem()
  264.  
  265.    Gets the last item in the list
  266.    
  267. **************************************************************************/
  268.  
  269. LPITEMIDLIST CPidlMgr::GetLastItem(LPCITEMIDLIST pidl)
  270. {
  271. LPITEMIDLIST   pidlLast = NULL;
  272.  
  273. //get the PIDL of the last item in the list
  274. if(pidl)
  275.    {
  276.    while(pidl->mkid.cb)
  277.       {
  278.       pidlLast = (LPITEMIDLIST)pidl;
  279.       pidl = GetNextItem(pidl);
  280.       }  
  281.    }
  282.  
  283. return pidlLast;
  284. }
  285.  
  286. /**************************************************************************
  287.  
  288.    CPidlMgr::GetItemText()
  289.  
  290.    Gets the text for only this item
  291.    
  292. **************************************************************************/
  293.  
  294. DWORD CPidlMgr::GetItemText(LPCITEMIDLIST pidl, LPTSTR lpszText, USHORT uSize)
  295. {
  296. //if this is a root key, it needs to be handled specially
  297. if(IsRootKey(pidl))
  298.    {
  299.    HKEY  hKey;
  300.  
  301.    if(!GetRootKey(pidl, &hKey))
  302.       return 0;
  303.  
  304.    return GetRootKeyText(hKey, lpszText, uSize);
  305.    }
  306.  
  307. return GetData(PT_TEXT, pidl, (LPVOID)lpszText, uSize);
  308. }
  309.  
  310. /**************************************************************************
  311.  
  312.    CPidlMgr::GetSubKeyText()
  313.  
  314.    Creates a sub key string from a PIDL, filtering out the root key and 
  315.    value, if either is present.
  316.    
  317. **************************************************************************/
  318.  
  319. DWORD CPidlMgr::GetSubKeyText(LPCITEMIDLIST pidl, LPTSTR lpszSubKey, DWORD dwSize)
  320. {
  321. if(!pidl)
  322.    return 0;
  323.  
  324. LPITEMIDLIST   pidlTemp;
  325. DWORD          dwCopied = 0;
  326.  
  327. /*
  328. This may be a list of items, so if the first item is a key rather than a 
  329. string, skip the first item because it contains the root key.
  330. */
  331. if(IsRootKey(pidl))
  332.    pidlTemp = GetNextItem(pidl);
  333. else
  334.    pidlTemp = (LPITEMIDLIST)pidl;
  335.  
  336. //if this is NULL, return the required size of the buffer
  337. if(!lpszSubKey)
  338.    {
  339.    while(pidlTemp->mkid.cb)
  340.       {
  341.       LPPIDLDATA  pData = GetDataPointer(pidlTemp);
  342.       
  343.       //add the length of this item plus one for the backslash
  344.       dwCopied += lstrlen(pData->szText) + 1;
  345.  
  346.       pidlTemp = GetNextItem(pidlTemp);
  347.       }
  348.  
  349.    //add one for the NULL terminator
  350.    return dwCopied + 1;
  351.    }
  352.  
  353. *lpszSubKey = 0;
  354.  
  355. while(pidlTemp->mkid.cb && (dwCopied < dwSize))
  356.    {
  357.    LPPIDLDATA  pData = GetDataPointer(pidlTemp);
  358.  
  359.    //if this item is a value, then skip it and finish
  360.    if(PT_VALUE == pData->type)
  361.       break;
  362.    
  363.    lstrcat(lpszSubKey, pData->szText);
  364.    lstrcat(lpszSubKey, TEXT("\\"));
  365.  
  366.    dwCopied += lstrlen(pData->szText) + 1;
  367.  
  368.    pidlTemp = GetNextItem(pidlTemp);
  369.    }
  370.  
  371. //remove the last backslash if necessary
  372. if(dwCopied)
  373.    {
  374.    if(*(lpszSubKey + lstrlen(lpszSubKey) - 1) == '\\')
  375.       {
  376.       *(lpszSubKey + lstrlen(lpszSubKey) - 1) = 0;
  377.       dwCopied--;
  378.       }
  379.    }
  380.  
  381. return dwCopied;
  382. }
  383.  
  384. /**************************************************************************
  385.  
  386.    CPidlMgr::GetValueText()
  387.  
  388.    Gets the text for the last item in the list
  389.    
  390. **************************************************************************/
  391.  
  392. DWORD CPidlMgr::GetValueText(LPCITEMIDLIST pidl, LPTSTR lpszValue, DWORD dwSize)
  393. {
  394. if(!pidl)
  395.    return 0;
  396.  
  397. LPCITEMIDLIST  pidlTemp = pidl;
  398. TCHAR          szText[MAX_PATH];
  399.  
  400. /*
  401. This may be a list of items, so search through the list looking for an item 
  402. that is a value. There should be only one, and it should be the last one, but 
  403. we will assume it can be anywhere and only copy the first one.
  404. */
  405. while(pidlTemp->mkid.cb && !IsValue(pidlTemp))
  406.    {
  407.    pidlTemp = GetNextItem(pidlTemp);
  408.    }
  409.  
  410. //we didn't find a value pidl
  411. if(!pidlTemp->mkid.cb)
  412.    return 0;
  413.  
  414. //get the item's text
  415. GetItemText(pidlTemp, szText, sizeof(szText));
  416.  
  417. //if this is NULL, return the required size of the buffer
  418. if(!lpszValue)
  419.    {
  420.    return lstrlen(szText) + 1;
  421.    }
  422.  
  423. lstrcpy(lpszValue, szText);
  424.  
  425. return lstrlen(lpszValue);
  426. }
  427.  
  428. /**************************************************************************
  429.  
  430.    CPidlMgr::Copy()
  431.    
  432. **************************************************************************/
  433.  
  434. LPITEMIDLIST CPidlMgr::Copy(LPCITEMIDLIST pidlSource)
  435. {
  436. LPITEMIDLIST pidlTarget = NULL;
  437. UINT cbSource = 0;
  438.  
  439. if(NULL == pidlSource)
  440.    return (NULL);
  441.  
  442. // Allocate the new pidl
  443. cbSource = GetSize(pidlSource);
  444. pidlTarget = (LPITEMIDLIST)m_pMalloc->Alloc(cbSource);
  445. if(!pidlTarget)
  446.    return (NULL);
  447.  
  448. // Copy the source to the target
  449. CopyMemory(pidlTarget, pidlSource, cbSource);
  450.  
  451. return pidlTarget;
  452. }
  453.  
  454. /**************************************************************************
  455.  
  456.    CPidlMgr::IsRootKey()
  457.    
  458. **************************************************************************/
  459.  
  460. BOOL CPidlMgr::IsRootKey(LPCITEMIDLIST pidl)
  461. {
  462. LPPIDLDATA  pData = GetDataPointer(pidl);
  463.  
  464. return (PT_ROOTKEY == pData->type);
  465. }
  466.  
  467. /**************************************************************************
  468.  
  469.    CPidlMgr::IsSubKey()
  470.    
  471. **************************************************************************/
  472.  
  473. BOOL CPidlMgr::IsSubKey(LPCITEMIDLIST pidl)
  474. {
  475. LPPIDLDATA  pData = GetDataPointer(pidl);
  476.  
  477. return (PT_SUBKEY == pData->type);
  478. }
  479.  
  480. /**************************************************************************
  481.  
  482.    CPidlMgr::IsValue()
  483.    
  484. **************************************************************************/
  485.  
  486. BOOL CPidlMgr::IsValue(LPCITEMIDLIST pidl)
  487. {
  488. LPPIDLDATA  pData = GetDataPointer(pidl);
  489.  
  490. return (PT_VALUE == pData->type);
  491. }
  492.  
  493. /**************************************************************************
  494.  
  495.    CPidlMgr::HasSubKeys()
  496.    
  497. **************************************************************************/
  498.  
  499. BOOL CPidlMgr::HasSubKeys(HKEY hKeyRoot, LPCTSTR pszSubKey, LPCITEMIDLIST pidl)
  500. {
  501. HKEY     hKey;
  502. LONG     lResult = !ERROR_SUCCESS;
  503. FILETIME ft;
  504. LPTSTR   lpszTemp;
  505.  
  506. if(!pszSubKey)
  507.    pszSubKey = TEXT("");
  508.  
  509. if(!hKeyRoot)
  510.    GetRootKey(pidl, &hKeyRoot);
  511.  
  512. DWORD dwSize = GetSubKeyText(pidl, NULL, 0) + lstrlen(pszSubKey) + 2;
  513.  
  514. lpszTemp = new TCHAR[dwSize];
  515. if(!lpszTemp)
  516.    return FALSE;
  517.  
  518. lstrcpy(lpszTemp, pszSubKey);
  519. if(*lpszTemp)
  520.    lstrcat(lpszTemp, TEXT("\\"));
  521. GetSubKeyText(pidl, lpszTemp + lstrlen(lpszTemp), dwSize - lstrlen(lpszTemp));
  522.  
  523. //open the specified key
  524. lResult = RegOpenKeyEx( hKeyRoot,
  525.                         lpszTemp,
  526.                         0,
  527.                         KEY_ENUMERATE_SUB_KEYS,
  528.                         &hKey);
  529.  
  530. if(ERROR_SUCCESS == lResult)
  531.    {
  532.    TCHAR szTemp[MAX_PATH];
  533.    DWORD dwSize = sizeof(szTemp);
  534.  
  535.    //try to get the specified subkey
  536.    lResult = RegEnumKeyEx( hKey,
  537.                            0,
  538.                            szTemp,
  539.                            &dwSize,
  540.                            NULL,
  541.                            NULL,
  542.                            NULL,
  543.                            &ft);
  544.  
  545.    RegCloseKey(hKey);
  546.    }
  547.  
  548. delete lpszTemp;
  549.  
  550. return (BOOL)(ERROR_SUCCESS == lResult);
  551. }
  552.  
  553. /**************************************************************************
  554.  
  555.    CPidlMgr::GetDataPointer()
  556.    
  557. **************************************************************************/
  558.  
  559. LPPIDLDATA CPidlMgr::GetDataPointer(LPCITEMIDLIST pidl)
  560. {
  561. if(!pidl)
  562.    return NULL;
  563.  
  564. return (LPPIDLDATA)(pidl->mkid.abID);
  565. }
  566.  
  567. /**************************************************************************
  568.  
  569.    CPidlMgr::GetValueType()
  570.    
  571. **************************************************************************/
  572.  
  573. BOOL CPidlMgr::GetValueType(  LPCITEMIDLIST pidlFQ, 
  574.                               LPDWORD pdwType)
  575. {
  576. BOOL  bReturn;
  577. LPITEMIDLIST   pidlKey;
  578. LPITEMIDLIST   pidlValue;
  579.  
  580. if(!SeparateKeyAndValue(pidlFQ, &pidlKey, &pidlValue))
  581.    return 0;
  582.  
  583. bReturn = GetValueType(pidlKey, pidlValue, pdwType);
  584.  
  585. Delete(pidlKey);
  586. Delete(pidlValue);
  587.  
  588. return bReturn;
  589. }
  590.  
  591. /**************************************************************************
  592.  
  593.    CPidlMgr::GetValueType()
  594.    
  595. **************************************************************************/
  596.  
  597. BOOL CPidlMgr::GetValueType(  LPCITEMIDLIST pidlKey, 
  598.                               LPCITEMIDLIST pidlValue, 
  599.                               LPDWORD pdwType)
  600. {
  601. if(!pidlKey)
  602.    return FALSE;
  603.  
  604. if(!pidlValue)
  605.    return FALSE;
  606.  
  607. if(!pdwType)
  608.    return FALSE;
  609.  
  610. HKEY     hKey,
  611.          hRootKey;
  612. LPTSTR   lpszSubKey,
  613.          lpszValueName;
  614. DWORD    dwNameSize;
  615. LONG     lResult;
  616.  
  617. //get the root key
  618. GetRootKey(pidlKey, &hRootKey);
  619.  
  620. //assemble the key string
  621. dwNameSize = GetSubKeyText(pidlKey, NULL, 0);
  622. lpszSubKey = new TCHAR[dwNameSize];
  623. if(!lpszSubKey)
  624.    return FALSE;
  625. GetSubKeyText(pidlKey, lpszSubKey, dwNameSize);
  626.  
  627. //assemble the value name
  628. dwNameSize = GetValueText(pidlValue, NULL, 0);
  629. lpszValueName = new TCHAR[dwNameSize];
  630. if(!lpszValueName)
  631.    {
  632.    delete lpszSubKey;
  633.    return FALSE;
  634.    }
  635. GetValueText(pidlValue, lpszValueName, dwNameSize);
  636.  
  637. //open the key
  638. lResult = RegOpenKeyEx( hRootKey,
  639.                         lpszSubKey,
  640.                         0,
  641.                         KEY_QUERY_VALUE,
  642.                         &hKey);
  643.  
  644. if(ERROR_SUCCESS != lResult)
  645.    return FALSE;
  646.  
  647. //get the value type
  648. lResult = RegQueryValueEx( hKey,
  649.                            lpszValueName,
  650.                            NULL,
  651.                            pdwType,
  652.                            NULL,
  653.                            NULL);
  654.  
  655. RegCloseKey(hKey);
  656.  
  657. delete lpszSubKey;
  658.  
  659. delete lpszValueName;
  660.  
  661. return TRUE;
  662. }
  663.  
  664. /**************************************************************************
  665.  
  666.    CPidlMgr::GetDataText()
  667.    
  668. **************************************************************************/
  669.  
  670. DWORD CPidlMgr::GetDataText(  LPCITEMIDLIST pidlFQ, 
  671.                               LPTSTR lpszOut, 
  672.                               DWORD dwOutSize)
  673. {
  674. DWORD dwReturn;
  675. LPITEMIDLIST   pidlKey;
  676. LPITEMIDLIST   pidlValue;
  677.  
  678. if(!SeparateKeyAndValue(pidlFQ, &pidlKey, &pidlValue))
  679.    return 0;
  680.  
  681. dwReturn = GetDataText(pidlKey, pidlValue, lpszOut, dwOutSize);
  682.  
  683. Delete(pidlKey);
  684. Delete(pidlValue);
  685.  
  686. return dwReturn;
  687. }
  688.  
  689. /**************************************************************************
  690.  
  691.    CPidlMgr::GetDataText()
  692.    
  693. **************************************************************************/
  694.  
  695. DWORD CPidlMgr::GetDataText(  LPCITEMIDLIST pidlKey, 
  696.                               LPCITEMIDLIST pidlValue, 
  697.                               LPTSTR lpszOut, 
  698.                               DWORD dwOutSize)
  699. {
  700. HKEY     hKey,
  701.          hRootKey;
  702. LPTSTR   lpszSubKey,
  703.          lpszValueName;
  704. DWORD    dwNameSize,
  705.          dwType,
  706.          dwSize,
  707.          dwReturn = 0;
  708. LONG     lResult;
  709. TCHAR    szData[MAX_PATH];
  710.  
  711. if(!lpszOut)
  712.    return dwReturn;
  713.  
  714. if(!pidlKey)
  715.    return dwReturn;
  716.  
  717. if(!pidlValue)
  718.    return dwReturn;
  719.  
  720. //get the root key
  721. GetRootKey(pidlKey, &hRootKey);
  722.  
  723. //assemble the key string
  724. dwNameSize = GetSubKeyText(pidlKey, NULL, 0);
  725. lpszSubKey = new TCHAR[dwNameSize];
  726. if(!lpszSubKey)
  727.    return dwReturn;
  728. GetSubKeyText(pidlKey, lpszSubKey, dwNameSize);
  729.  
  730. //assemble the value name
  731. dwNameSize = GetValueText(pidlValue, NULL, 0);
  732. lpszValueName = new TCHAR[dwNameSize];
  733. if(!lpszValueName)
  734.    {
  735.    delete lpszSubKey;
  736.    return dwReturn;
  737.    }
  738. GetValueText(pidlValue, lpszValueName, dwNameSize);
  739.  
  740. //open the key
  741. lResult = RegOpenKeyEx( hRootKey,
  742.                         lpszSubKey,
  743.                         0,
  744.                         KEY_QUERY_VALUE,
  745.                         &hKey);
  746.  
  747. if(ERROR_SUCCESS != lResult)
  748.    return 0;
  749.  
  750. //get the value
  751. dwSize = sizeof(szData);
  752. lResult = RegQueryValueEx( hKey,
  753.                            lpszValueName,
  754.                            NULL,
  755.                            &dwType,
  756.                            (LPBYTE)szData,
  757.                            &dwSize);
  758.  
  759. /*
  760. If this fails, then there is no default value set, so go ahead and add the 
  761. empty default value.
  762. */
  763. if(ERROR_SUCCESS == lResult)
  764.    {
  765.    //format the data
  766.    switch(dwType)
  767.       {
  768.       case REG_BINARY:
  769.       case REG_DWORD:
  770.       case REG_DWORD_BIG_ENDIAN:
  771.          {
  772.          LPTSTR   lpszBuffer,
  773.                   lpszTemp;
  774.          LPBYTE   pData = (LPBYTE)szData;
  775.                   
  776.          lpszBuffer = lpszTemp = new TCHAR[dwSize * sizeof(TCHAR) * 3 + sizeof(TCHAR)];
  777.  
  778.          if(lpszTemp)
  779.             {
  780.             DWORD dwTemp;
  781.  
  782.             for(dwTemp = 0; dwTemp < dwSize; dwTemp++)
  783.                {
  784.                wsprintf(lpszTemp, TEXT("%02x"), *(pData + dwTemp));
  785.                lstrcat(lpszTemp, TEXT(" "));
  786.                lpszTemp = lpszBuffer + lstrlen(lpszBuffer);
  787.                }
  788.  
  789.             lstrcpyn(lpszOut, lpszBuffer, dwOutSize);
  790.             
  791.             delete lpszBuffer;
  792.             }
  793.          }
  794.          break;
  795.  
  796.       default:
  797.          lstrcpyn(lpszOut, szData, dwOutSize);
  798.          break;
  799.       }
  800.    dwReturn = lstrlen(lpszOut);
  801.    }
  802.  
  803. RegCloseKey(hKey);
  804.  
  805. delete lpszSubKey;
  806.  
  807. delete lpszValueName;
  808.  
  809. return dwReturn;
  810. }
  811.  
  812. /**************************************************************************
  813.  
  814.    CPidlMgr::GetPidlPath()
  815.  
  816.    Create a string that includes the root key name, the sub key text and 
  817.    the value text.
  818.    
  819. **************************************************************************/
  820.  
  821. DWORD CPidlMgr::GetPidlPath(LPCITEMIDLIST pidl, LPTSTR lpszOut, DWORD dwOutSize)
  822. {
  823. LPTSTR   lpszTemp;
  824.  
  825. if(!lpszOut)
  826.    return 0;
  827.  
  828. *lpszOut = 0;
  829. lpszTemp = lpszOut;
  830.  
  831. //add the root key text if necessary
  832. if(IsRootKey(pidl))
  833.    {
  834.    HKEY  hKey;
  835.  
  836.    GetRootKey(pidl, &hKey);
  837.    dwOutSize -= GetRootKeyText(hKey, lpszOut, dwOutSize);
  838.  
  839.    lpszTemp = lpszOut + lstrlen(lpszOut);
  840.    }
  841.  
  842. //add a backslash if necessary
  843. if(*lpszOut && (*(lpszOut + lstrlen(lpszOut) - 1) != '\\'))
  844.    lstrcat(lpszOut, TEXT("\\"));
  845.  
  846. //add the subkey string
  847. dwOutSize -= GetSubKeyText(pidl, lpszTemp, dwOutSize);
  848.  
  849. //add a backslash if necessary
  850. if(*lpszOut && (*(lpszOut + lstrlen(lpszOut) - 1) != '\\'))
  851.    lstrcat(lpszOut, TEXT("\\"));
  852.  
  853. lpszTemp = lpszOut + lstrlen(lpszOut);
  854.  
  855. //add the value string
  856. GetValueText(pidl, lpszTemp, dwOutSize);
  857.  
  858. //remove the last backslash if necessary
  859. if(*(lpszOut + lstrlen(lpszOut) - 1) == '\\')
  860.    {
  861.    *(lpszOut + lstrlen(lpszOut) - 1) = 0;
  862.    }
  863.  
  864. return lstrlen(lpszOut);
  865. }
  866.  
  867. /**************************************************************************
  868.  
  869.    CPidlMgr::Concatenate()
  870.  
  871.    Create a new PIDL by combining two existing PIDLs.
  872.    
  873. **************************************************************************/
  874.  
  875. LPITEMIDLIST CPidlMgr::Concatenate(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  876. {
  877. LPITEMIDLIST   pidlNew;
  878. UINT           cb1 = 0, 
  879.                cb2 = 0;
  880.  
  881. //are both of these NULL?
  882. if(!pidl1 && !pidl2)
  883.    return NULL;
  884.  
  885. //if pidl1 is NULL, just return a copy of pidl2
  886. if(!pidl1)
  887.    {
  888.    pidlNew = Copy(pidl2);
  889.  
  890.    return pidlNew;
  891.    }
  892.  
  893. //if pidl2 is NULL, just return a copy of pidl1
  894. if(!pidl2)
  895.    {
  896.    pidlNew = Copy(pidl1);
  897.  
  898.    return pidlNew;
  899.    }
  900.  
  901. cb1 = GetSize(pidl1) - sizeof(ITEMIDLIST);
  902.  
  903. cb2 = GetSize(pidl2);
  904.  
  905. //create the new PIDL
  906. pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(cb1 + cb2);
  907.  
  908. if(pidlNew)
  909.    {
  910.    //copy the first PIDL
  911.    CopyMemory(pidlNew, pidl1, cb1);
  912.    
  913.   //copy the second PIDL
  914.    CopyMemory(((LPBYTE)pidlNew) + cb1, pidl2, cb2);
  915.    }
  916.  
  917. return pidlNew;
  918. }
  919.  
  920. /**************************************************************************
  921.  
  922.    CPidlMgr::SeparateKeyAndValue()
  923.  
  924.    Creates a separate key and value PIDL from a fully qualified PIDL.
  925.    
  926. **************************************************************************/
  927.  
  928. BOOL CPidlMgr::SeparateKeyAndValue( LPCITEMIDLIST pidlFQ, 
  929.                                     LPITEMIDLIST *ppidlKey, 
  930.                                     LPITEMIDLIST*ppidlValue)
  931. {
  932. if(!pidlFQ)
  933.    return FALSE;
  934.  
  935. *ppidlValue = GetLastItem(pidlFQ);
  936. if(!IsValue(*ppidlValue))
  937.    return FALSE;
  938.  
  939. //make a copy of the value pidl
  940. *ppidlValue = Copy(*ppidlValue);
  941.  
  942. //make a copy of the fully qualified PIDL
  943. *ppidlKey = Copy(pidlFQ);
  944.  
  945. //truncate the last item of the key PIDL
  946. LPITEMIDLIST   pidlTemp = GetLastItem(*ppidlKey);
  947. pidlTemp->mkid.cb = 0;
  948. pidlTemp->mkid.abID[0] = 0;
  949.  
  950. return TRUE;
  951. }
  952.  
  953.