PIDLMGR.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:22k
源码类别:

Windows编程

开发平台:

Visual C++

  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.    Copyright 1997 Microsoft Corporation.  All Rights Reserved.
  7. **************************************************************************/
  8. /**************************************************************************
  9.    File:          PidlMgr.cpp
  10.    
  11.    Description:   Implements CPidlMgr.
  12. **************************************************************************/
  13. /**************************************************************************
  14.    #include statements
  15. **************************************************************************/
  16. #include "PidlMgr.h"
  17. #include "ShlFldr.h"
  18. #include "resource.h"
  19. /**************************************************************************
  20.    CPidlMgr::CPidlMgr
  21. **************************************************************************/
  22. CPidlMgr::CPidlMgr()
  23. {
  24. //get the shell's IMalloc pointer
  25. //we'll keep this until we get destroyed
  26. if(FAILED(SHGetMalloc(&m_pMalloc)))
  27.    {
  28.    delete this;
  29.    }
  30. g_DllRefCount++;
  31. }
  32. /**************************************************************************
  33.    CPidlMgr::~CPidlMgr
  34. **************************************************************************/
  35. CPidlMgr::~CPidlMgr()
  36. {
  37. if(m_pMalloc)
  38.    m_pMalloc->Release();
  39. g_DllRefCount--;
  40. }
  41. /**************************************************************************
  42.    CPidlMgr::Create(DWORD, LPVOID, DWORD)
  43.    Creates a new PIDL
  44.    
  45. **************************************************************************/
  46. LPITEMIDLIST CPidlMgr::Create(PIDLTYPE type, LPVOID pIn, USHORT uInSize)
  47. {
  48. LPITEMIDLIST   pidlOut;
  49. USHORT         uSize;
  50. pidlOut = NULL;
  51. /*
  52. Calculate the size. This consists of the ITEMIDLIST, the PIDL structure plus 
  53. the size of the data. We subtract the size of an HKEY because that is included 
  54. in uInSize.
  55. */
  56. uSize = sizeof(ITEMIDLIST) + (sizeof(PIDLDATA) - sizeof(HKEY)) + uInSize;
  57. /*
  58. Allocate the memory, adding an additional ITEMIDLIST for the NULL terminating 
  59. ID List.
  60. */
  61. pidlOut = (LPITEMIDLIST)m_pMalloc->Alloc(uSize + sizeof(ITEMIDLIST));
  62. if(pidlOut)
  63.    {
  64.    LPITEMIDLIST   pidlTemp = pidlOut;
  65.    LPPIDLDATA     pData;
  66.    //set the size of this item
  67.    pidlTemp->mkid.cb = uSize;
  68.    //set the data for this item
  69.    pData = GetDataPointer(pidlTemp);
  70.    pData->type = type;
  71.    switch(type)
  72.       {
  73.       case PT_ROOTKEY:
  74.          pData->hRootKey = *(HKEY*)pIn;
  75.          break;
  76.       case PT_SUBKEY:
  77.       case PT_VALUE:
  78.          CopyMemory(pData->szText, pIn, uInSize);
  79.          break;
  80.       }
  81.    
  82.    //set the NULL terminator to 0
  83.    pidlTemp = GetNextItem(pidlTemp);
  84.    pidlTemp->mkid.cb = 0;
  85.    pidlTemp->mkid.abID[0] = 0;
  86.    }
  87. return pidlOut;
  88. }
  89. /**************************************************************************
  90.    CPidlMgr::Delete(HKEY)
  91.    Deletes a PIDL
  92.    
  93. **************************************************************************/
  94. void CPidlMgr::Delete(LPITEMIDLIST pidl)
  95. {
  96. m_pMalloc->Free(pidl);
  97. }
  98. /**************************************************************************
  99.    CPidlMgr::CreateRootKey()
  100.    Creates a root key PIDL
  101.    
  102. **************************************************************************/
  103. LPITEMIDLIST CPidlMgr::CreateRootKey(HKEY hKeyRoot)
  104. {
  105. return Create(PT_ROOTKEY, (LPVOID)&hKeyRoot, sizeof(hKeyRoot));
  106. }
  107. /**************************************************************************
  108.    CPidlMgr::CreateSubKey()
  109.    Creates a sub key PIDL
  110.    
  111. **************************************************************************/
  112. LPITEMIDLIST CPidlMgr::CreateSubKey(LPCTSTR lpszNew)
  113. {
  114. return Create(PT_SUBKEY, (LPVOID)lpszNew, (lstrlen(lpszNew) + 1) * sizeof(TCHAR));
  115. }
  116. /**************************************************************************
  117.    CPidlMgr::CreateValue()
  118.    Creates a value PIDL
  119.    
  120. **************************************************************************/
  121. LPITEMIDLIST CPidlMgr::CreateValue(LPCTSTR lpszNew)
  122. {
  123. return Create(PT_VALUE, (LPVOID)lpszNew, (lstrlen(lpszNew) + 1) * sizeof(TCHAR));
  124. }
  125. /**************************************************************************
  126.    CPidlMgr::GetNextItem()
  127.    
  128. **************************************************************************/
  129. LPITEMIDLIST CPidlMgr::GetNextItem(LPCITEMIDLIST pidl)
  130. {
  131. if(pidl)
  132.    return (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
  133. else
  134.    return (NULL);
  135. }
  136. /**************************************************************************
  137.    CPidlMgr::GetSize()
  138.    
  139. **************************************************************************/
  140. UINT CPidlMgr::GetSize(LPCITEMIDLIST pidl)
  141. {
  142. UINT cbTotal = 0;
  143. LPITEMIDLIST pidlTemp = (LPITEMIDLIST) pidl;
  144. if(pidlTemp)
  145.    {
  146.    while(pidlTemp->mkid.cb)
  147.       {
  148.       cbTotal += pidlTemp->mkid.cb;
  149.       pidlTemp = GetNextItem(pidlTemp);
  150.       }  
  151.    //add the size of the NULL terminating ITEMIDLIST
  152.    cbTotal += sizeof(ITEMIDLIST);
  153.    }
  154. return (cbTotal);
  155. }
  156. /**************************************************************************
  157.    CPidlMgr::GetData(PIDLTYPE, LPCITEMIDLIST, LPVOID, USHORT)
  158.    
  159. **************************************************************************/
  160. DWORD CPidlMgr::GetData(PIDLTYPE type, LPCITEMIDLIST pidl, LPVOID pOut, USHORT uOutSize)
  161. {
  162. if(!pidl)
  163.    return 0;
  164. LPPIDLDATA  pData = GetDataPointer(pidl);
  165. DWORD       dwReturn = 0;
  166. //copy the data
  167. switch(type)
  168.    {
  169.    case PT_ROOTKEY:
  170.       if(uOutSize < sizeof(HKEY))
  171.          return 0;
  172.       
  173.       if(PT_ROOTKEY != pData->type)
  174.          return 0;
  175.       
  176.       *(HKEY*)pOut = pData->hRootKey;
  177.       dwReturn = sizeof(pData->hRootKey);
  178.       break;
  179.    case PT_SUBKEY:
  180.    case PT_VALUE:
  181.    case PT_TEXT:
  182.       *(LPTSTR)pOut = 0;
  183.       lstrcpyn((LPTSTR)pOut, pData->szText, uOutSize);
  184.       dwReturn = lstrlen((LPTSTR)pOut);
  185.       break;
  186.    }
  187. return dwReturn;
  188. }
  189. /**************************************************************************
  190.    CPidlMgr::GetRootKey()
  191.    
  192. **************************************************************************/
  193. BOOL CPidlMgr::GetRootKey(LPCITEMIDLIST pidl, HKEY *phKeyRoot)
  194. {
  195. return (BOOL)GetData(PT_ROOTKEY, pidl, (LPVOID)phKeyRoot, sizeof(HKEY));
  196. }
  197. /**************************************************************************
  198.    CPidlMgr::GetLastItem()
  199.    Gets the last item in the list
  200.    
  201. **************************************************************************/
  202. LPITEMIDLIST CPidlMgr::GetLastItem(LPCITEMIDLIST pidl)
  203. {
  204. LPITEMIDLIST   pidlLast = NULL;
  205. //get the PIDL of the last item in the list
  206. if(pidl)
  207.    {
  208.    while(pidl->mkid.cb)
  209.       {
  210.       pidlLast = (LPITEMIDLIST)pidl;
  211.       pidl = GetNextItem(pidl);
  212.       }  
  213.    }
  214. return pidlLast;
  215. }
  216. /**************************************************************************
  217.    CPidlMgr::GetItemText()
  218.    Gets the text for only this item
  219.    
  220. **************************************************************************/
  221. DWORD CPidlMgr::GetItemText(LPCITEMIDLIST pidl, LPTSTR lpszText, USHORT uSize)
  222. {
  223. //if this is a root key, it needs to be handled specially
  224. if(IsRootKey(pidl))
  225.    {
  226.    HKEY  hKey;
  227.    if(!GetRootKey(pidl, &hKey))
  228.       return 0;
  229.    return GetRootKeyText(hKey, lpszText, uSize);
  230.    }
  231. return GetData(PT_TEXT, pidl, (LPVOID)lpszText, uSize);
  232. }
  233. /**************************************************************************
  234.    CPidlMgr::GetSubKeyText()
  235.    Creates a sub key string from a PIDL, filtering out the root key and 
  236.    value, if either is present.
  237.    
  238. **************************************************************************/
  239. DWORD CPidlMgr::GetSubKeyText(LPCITEMIDLIST pidl, LPTSTR lpszSubKey, DWORD dwSize)
  240. {
  241. if(!pidl)
  242.    return 0;
  243. LPITEMIDLIST   pidlTemp;
  244. DWORD          dwCopied = 0;
  245. /*
  246. This may be a list of items, so if the first item is a key rather than a 
  247. string, skip the first item because it contains the root key.
  248. */
  249. if(IsRootKey(pidl))
  250.    pidlTemp = GetNextItem(pidl);
  251. else
  252.    pidlTemp = (LPITEMIDLIST)pidl;
  253. //if this is NULL, return the required size of the buffer
  254. if(!lpszSubKey)
  255.    {
  256.    while(pidlTemp->mkid.cb)
  257.       {
  258.       LPPIDLDATA  pData = GetDataPointer(pidlTemp);
  259.       
  260.       //add the length of this item plus one for the backslash
  261.       dwCopied += lstrlen(pData->szText) + 1;
  262.       pidlTemp = GetNextItem(pidlTemp);
  263.       }
  264.    //add one for the NULL terminator
  265.    return dwCopied + 1;
  266.    }
  267. *lpszSubKey = 0;
  268. while(pidlTemp->mkid.cb && (dwCopied < dwSize))
  269.    {
  270.    LPPIDLDATA  pData = GetDataPointer(pidlTemp);
  271.    //if this item is a value, then skip it and finish
  272.    if(PT_VALUE == pData->type)
  273.       break;
  274.    
  275.    lstrcat(lpszSubKey, pData->szText);
  276.    lstrcat(lpszSubKey, TEXT("\"));
  277.    dwCopied += lstrlen(pData->szText) + 1;
  278.    pidlTemp = GetNextItem(pidlTemp);
  279.    }
  280. //remove the last backslash if necessary
  281. if(dwCopied)
  282.    {
  283.    if(*(lpszSubKey + lstrlen(lpszSubKey) - 1) == '\')
  284.       {
  285.       *(lpszSubKey + lstrlen(lpszSubKey) - 1) = 0;
  286.       dwCopied--;
  287.       }
  288.    }
  289. return dwCopied;
  290. }
  291. /**************************************************************************
  292.    CPidlMgr::GetValueText()
  293.    Gets the text for the last item in the list
  294.    
  295. **************************************************************************/
  296. DWORD CPidlMgr::GetValueText(LPCITEMIDLIST pidl, LPTSTR lpszValue, DWORD dwSize)
  297. {
  298. if(!pidl)
  299.    return 0;
  300. LPCITEMIDLIST  pidlTemp = pidl;
  301. TCHAR          szText[MAX_PATH];
  302. /*
  303. This may be a list of items, so search through the list looking for an item 
  304. that is a value. There should be only one, and it should be the last one, but 
  305. we will assume it can be anywhere and only copy the first one.
  306. */
  307. while(pidlTemp->mkid.cb && !IsValue(pidlTemp))
  308.    {
  309.    pidlTemp = GetNextItem(pidlTemp);
  310.    }
  311. //we didn't find a value pidl
  312. if(!pidlTemp->mkid.cb)
  313.    return 0;
  314. //get the item's text
  315. GetItemText(pidlTemp, szText, sizeof(szText));
  316. //if this is NULL, return the required size of the buffer
  317. if(!lpszValue)
  318.    {
  319.    return lstrlen(szText) + 1;
  320.    }
  321. lstrcpy(lpszValue, szText);
  322. return lstrlen(lpszValue);
  323. }
  324. /**************************************************************************
  325.    CPidlMgr::Copy()
  326.    
  327. **************************************************************************/
  328. LPITEMIDLIST CPidlMgr::Copy(LPCITEMIDLIST pidlSource)
  329. {
  330. LPITEMIDLIST pidlTarget = NULL;
  331. UINT cbSource = 0;
  332. if(NULL == pidlSource)
  333.    return (NULL);
  334. // Allocate the new pidl
  335. cbSource = GetSize(pidlSource);
  336. pidlTarget = (LPITEMIDLIST)m_pMalloc->Alloc(cbSource);
  337. if(!pidlTarget)
  338.    return (NULL);
  339. // Copy the source to the target
  340. CopyMemory(pidlTarget, pidlSource, cbSource);
  341. return pidlTarget;
  342. }
  343. /**************************************************************************
  344.    CPidlMgr::IsRootKey()
  345.    
  346. **************************************************************************/
  347. BOOL CPidlMgr::IsRootKey(LPCITEMIDLIST pidl)
  348. {
  349. LPPIDLDATA  pData = GetDataPointer(pidl);
  350. return (PT_ROOTKEY == pData->type);
  351. }
  352. /**************************************************************************
  353.    CPidlMgr::IsSubKey()
  354.    
  355. **************************************************************************/
  356. BOOL CPidlMgr::IsSubKey(LPCITEMIDLIST pidl)
  357. {
  358. LPPIDLDATA  pData = GetDataPointer(pidl);
  359. return (PT_SUBKEY == pData->type);
  360. }
  361. /**************************************************************************
  362.    CPidlMgr::IsValue()
  363.    
  364. **************************************************************************/
  365. BOOL CPidlMgr::IsValue(LPCITEMIDLIST pidl)
  366. {
  367. LPPIDLDATA  pData = GetDataPointer(pidl);
  368. return (PT_VALUE == pData->type);
  369. }
  370. /**************************************************************************
  371.    CPidlMgr::HasSubKeys()
  372.    
  373. **************************************************************************/
  374. BOOL CPidlMgr::HasSubKeys(HKEY hKeyRoot, LPCTSTR pszSubKey, LPCITEMIDLIST pidl)
  375. {
  376. HKEY     hKey;
  377. LONG     lResult = !ERROR_SUCCESS;
  378. FILETIME ft;
  379. LPTSTR   lpszTemp;
  380. if(!pszSubKey)
  381.    pszSubKey = TEXT("");
  382. if(!hKeyRoot)
  383.    GetRootKey(pidl, &hKeyRoot);
  384. DWORD dwSize = GetSubKeyText(pidl, NULL, 0) + lstrlen(pszSubKey) + 2;
  385. lpszTemp = new TCHAR[dwSize];
  386. if(!lpszTemp)
  387.    return FALSE;
  388. lstrcpy(lpszTemp, pszSubKey);
  389. if(*lpszTemp)
  390.    lstrcat(lpszTemp, TEXT("\"));
  391. GetSubKeyText(pidl, lpszTemp + lstrlen(lpszTemp), dwSize - lstrlen(lpszTemp));
  392. //open the specified key
  393. lResult = RegOpenKeyEx( hKeyRoot,
  394.                         lpszTemp,
  395.                         0,
  396.                         KEY_ENUMERATE_SUB_KEYS,
  397.                         &hKey);
  398. if(ERROR_SUCCESS == lResult)
  399.    {
  400.    TCHAR szTemp[MAX_PATH];
  401.    DWORD dwSize = sizeof(szTemp);
  402.    //try to get the specified subkey
  403.    lResult = RegEnumKeyEx( hKey,
  404.                            0,
  405.                            szTemp,
  406.                            &dwSize,
  407.                            NULL,
  408.                            NULL,
  409.                            NULL,
  410.                            &ft);
  411.    RegCloseKey(hKey);
  412.    }
  413. delete lpszTemp;
  414. return (BOOL)(ERROR_SUCCESS == lResult);
  415. }
  416. /**************************************************************************
  417.    CPidlMgr::GetDataPointer()
  418.    
  419. **************************************************************************/
  420. LPPIDLDATA CPidlMgr::GetDataPointer(LPCITEMIDLIST pidl)
  421. {
  422. if(!pidl)
  423.    return NULL;
  424. return (LPPIDLDATA)(pidl->mkid.abID);
  425. }
  426. /**************************************************************************
  427.    CPidlMgr::GetValueType()
  428.    
  429. **************************************************************************/
  430. BOOL CPidlMgr::GetValueType(  LPCITEMIDLIST pidlFQ, 
  431.                               LPDWORD pdwType)
  432. {
  433. BOOL  bReturn;
  434. LPITEMIDLIST   pidlKey;
  435. LPITEMIDLIST   pidlValue;
  436. if(!SeparateKeyAndValue(pidlFQ, &pidlKey, &pidlValue))
  437.    return 0;
  438. bReturn = GetValueType(pidlKey, pidlValue, pdwType);
  439. Delete(pidlKey);
  440. Delete(pidlValue);
  441. return bReturn;
  442. }
  443. /**************************************************************************
  444.    CPidlMgr::GetValueType()
  445.    
  446. **************************************************************************/
  447. BOOL CPidlMgr::GetValueType(  LPCITEMIDLIST pidlKey, 
  448.                               LPCITEMIDLIST pidlValue, 
  449.                               LPDWORD pdwType)
  450. {
  451. if(!pidlKey)
  452.    return FALSE;
  453. if(!pidlValue)
  454.    return FALSE;
  455. if(!pdwType)
  456.    return FALSE;
  457. HKEY     hKey,
  458.          hRootKey;
  459. LPTSTR   lpszSubKey,
  460.          lpszValueName;
  461. DWORD    dwNameSize;
  462. LONG     lResult;
  463. //get the root key
  464. GetRootKey(pidlKey, &hRootKey);
  465. //assemble the key string
  466. dwNameSize = GetSubKeyText(pidlKey, NULL, 0);
  467. lpszSubKey = new TCHAR[dwNameSize];
  468. if(!lpszSubKey)
  469.    return FALSE;
  470. GetSubKeyText(pidlKey, lpszSubKey, dwNameSize);
  471. //assemble the value name
  472. dwNameSize = GetValueText(pidlValue, NULL, 0);
  473. lpszValueName = new TCHAR[dwNameSize];
  474. if(!lpszValueName)
  475.    {
  476.    delete lpszSubKey;
  477.    return FALSE;
  478.    }
  479. GetValueText(pidlValue, lpszValueName, dwNameSize);
  480. //open the key
  481. lResult = RegOpenKeyEx( hRootKey,
  482.                         lpszSubKey,
  483.                         0,
  484.                         KEY_QUERY_VALUE,
  485.                         &hKey);
  486. if(ERROR_SUCCESS != lResult)
  487.    return FALSE;
  488. //get the value type
  489. lResult = RegQueryValueEx( hKey,
  490.                            lpszValueName,
  491.                            NULL,
  492.                            pdwType,
  493.                            NULL,
  494.                            NULL);
  495. RegCloseKey(hKey);
  496. delete lpszSubKey;
  497. delete lpszValueName;
  498. return TRUE;
  499. }
  500. /**************************************************************************
  501.    CPidlMgr::GetDataText()
  502.    
  503. **************************************************************************/
  504. DWORD CPidlMgr::GetDataText(  LPCITEMIDLIST pidlFQ, 
  505.                               LPTSTR lpszOut, 
  506.                               DWORD dwOutSize)
  507. {
  508. DWORD dwReturn;
  509. LPITEMIDLIST   pidlKey;
  510. LPITEMIDLIST   pidlValue;
  511. if(!SeparateKeyAndValue(pidlFQ, &pidlKey, &pidlValue))
  512.    return 0;
  513. dwReturn = GetDataText(pidlKey, pidlValue, lpszOut, dwOutSize);
  514. Delete(pidlKey);
  515. Delete(pidlValue);
  516. return dwReturn;
  517. }
  518. /**************************************************************************
  519.    CPidlMgr::GetDataText()
  520.    
  521. **************************************************************************/
  522. DWORD CPidlMgr::GetDataText(  LPCITEMIDLIST pidlKey, 
  523.                               LPCITEMIDLIST pidlValue, 
  524.                               LPTSTR lpszOut, 
  525.                               DWORD dwOutSize)
  526. {
  527. HKEY     hKey,
  528.          hRootKey;
  529. LPTSTR   lpszSubKey,
  530.          lpszValueName;
  531. DWORD    dwNameSize,
  532.          dwType,
  533.          dwSize,
  534.          dwReturn = 0;
  535. LONG     lResult;
  536. TCHAR    szData[MAX_PATH];
  537. if(!lpszOut)
  538.    return dwReturn;
  539. if(!pidlKey)
  540.    return dwReturn;
  541. if(!pidlValue)
  542.    return dwReturn;
  543. //get the root key
  544. GetRootKey(pidlKey, &hRootKey);
  545. //assemble the key string
  546. dwNameSize = GetSubKeyText(pidlKey, NULL, 0);
  547. lpszSubKey = new TCHAR[dwNameSize];
  548. if(!lpszSubKey)
  549.    return dwReturn;
  550. GetSubKeyText(pidlKey, lpszSubKey, dwNameSize);
  551. //assemble the value name
  552. dwNameSize = GetValueText(pidlValue, NULL, 0);
  553. lpszValueName = new TCHAR[dwNameSize];
  554. if(!lpszValueName)
  555.    {
  556.    delete lpszSubKey;
  557.    return dwReturn;
  558.    }
  559. GetValueText(pidlValue, lpszValueName, dwNameSize);
  560. //open the key
  561. lResult = RegOpenKeyEx( hRootKey,
  562.                         lpszSubKey,
  563.                         0,
  564.                         KEY_QUERY_VALUE,
  565.                         &hKey);
  566. if(ERROR_SUCCESS != lResult)
  567.    return 0;
  568. //get the value
  569. dwSize = sizeof(szData);
  570. lResult = RegQueryValueEx( hKey,
  571.                            lpszValueName,
  572.                            NULL,
  573.                            &dwType,
  574.                            (LPBYTE)szData,
  575.                            &dwSize);
  576. /*
  577. If this fails, then there is no default value set, so go ahead and add the 
  578. empty default value.
  579. */
  580. if(ERROR_SUCCESS == lResult)
  581.    {
  582.    //format the data
  583.    switch(dwType)
  584.       {
  585.       case REG_BINARY:
  586.       case REG_DWORD:
  587.       case REG_DWORD_BIG_ENDIAN:
  588.          {
  589.          LPTSTR   lpszBuffer,
  590.                   lpszTemp;
  591.          LPBYTE   pData = (LPBYTE)szData;
  592.                   
  593.          lpszBuffer = lpszTemp = new TCHAR[dwSize * sizeof(TCHAR) * 3 + sizeof(TCHAR)];
  594.          if(lpszTemp)
  595.             {
  596.             DWORD dwTemp;
  597.             for(dwTemp = 0; dwTemp < dwSize; dwTemp++)
  598.                {
  599.                wsprintf(lpszTemp, TEXT("%02x"), *(pData + dwTemp));
  600.                lstrcat(lpszTemp, TEXT(" "));
  601.                lpszTemp = lpszBuffer + lstrlen(lpszBuffer);
  602.                }
  603.             lstrcpyn(lpszOut, lpszBuffer, dwOutSize);
  604.             
  605.             delete lpszBuffer;
  606.             }
  607.          }
  608.          break;
  609.       default:
  610.          lstrcpyn(lpszOut, szData, dwOutSize);
  611.          break;
  612.       }
  613.    dwReturn = lstrlen(lpszOut);
  614.    }
  615. RegCloseKey(hKey);
  616. delete lpszSubKey;
  617. delete lpszValueName;
  618. return dwReturn;
  619. }
  620. /**************************************************************************
  621.    CPidlMgr::GetPidlPath()
  622.    Create a string that includes the root key name, the sub key text and 
  623.    the value text.
  624.    
  625. **************************************************************************/
  626. DWORD CPidlMgr::GetPidlPath(LPCITEMIDLIST pidl, LPTSTR lpszOut, DWORD dwOutSize)
  627. {
  628. LPTSTR   lpszTemp;
  629. if(!lpszOut)
  630.    return 0;
  631. *lpszOut = 0;
  632. lpszTemp = lpszOut;
  633. //add the root key text if necessary
  634. if(IsRootKey(pidl))
  635.    {
  636.    HKEY  hKey;
  637.    GetRootKey(pidl, &hKey);
  638.    dwOutSize -= GetRootKeyText(hKey, lpszOut, dwOutSize);
  639.    lpszTemp = lpszOut + lstrlen(lpszOut);
  640.    }
  641. //add a backslash if necessary
  642. if(*lpszOut && (*(lpszOut + lstrlen(lpszOut) - 1) != '\'))
  643.    lstrcat(lpszOut, TEXT("\"));
  644. //add the subkey string
  645. dwOutSize -= GetSubKeyText(pidl, lpszTemp, dwOutSize);
  646. //add a backslash if necessary
  647. if(*lpszOut && (*(lpszOut + lstrlen(lpszOut) - 1) != '\'))
  648.    lstrcat(lpszOut, TEXT("\"));
  649. lpszTemp = lpszOut + lstrlen(lpszOut);
  650. //add the value string
  651. GetValueText(pidl, lpszTemp, dwOutSize);
  652. //remove the last backslash if necessary
  653. if(*(lpszOut + lstrlen(lpszOut) - 1) == '\')
  654.    {
  655.    *(lpszOut + lstrlen(lpszOut) - 1) = 0;
  656.    }
  657. return lstrlen(lpszOut);
  658. }
  659. /**************************************************************************
  660.    CPidlMgr::Concatenate()
  661.    Create a new PIDL by combining two existing PIDLs.
  662.    
  663. **************************************************************************/
  664. LPITEMIDLIST CPidlMgr::Concatenate(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  665. {
  666. LPITEMIDLIST   pidlNew;
  667. UINT           cb1 = 0, 
  668.                cb2 = 0;
  669. //are both of these NULL?
  670. if(!pidl1 && !pidl2)
  671.    return NULL;
  672. //if pidl1 is NULL, just return a copy of pidl2
  673. if(!pidl1)
  674.    {
  675.    pidlNew = Copy(pidl2);
  676.    return pidlNew;
  677.    }
  678. //if pidl2 is NULL, just return a copy of pidl1
  679. if(!pidl2)
  680.    {
  681.    pidlNew = Copy(pidl1);
  682.    return pidlNew;
  683.    }
  684. cb1 = GetSize(pidl1) - sizeof(ITEMIDLIST);
  685. cb2 = GetSize(pidl2);
  686. //create the new PIDL
  687. pidlNew = (LPITEMIDLIST)m_pMalloc->Alloc(cb1 + cb2);
  688. if(pidlNew)
  689.    {
  690.    //copy the first PIDL
  691.    CopyMemory(pidlNew, pidl1, cb1);
  692.    
  693.   //copy the second PIDL
  694.    CopyMemory(((LPBYTE)pidlNew) + cb1, pidl2, cb2);
  695.    }
  696. return pidlNew;
  697. }
  698. /**************************************************************************
  699.    CPidlMgr::SeparateKeyAndValue()
  700.    Creates a separate key and value PIDL from a fully qualified PIDL.
  701.    
  702. **************************************************************************/
  703. BOOL CPidlMgr::SeparateKeyAndValue( LPCITEMIDLIST pidlFQ, 
  704.                                     LPITEMIDLIST *ppidlKey, 
  705.                                     LPITEMIDLIST*ppidlValue)
  706. {
  707. if(!pidlFQ)
  708.    return FALSE;
  709. *ppidlValue = GetLastItem(pidlFQ);
  710. if(!IsValue(*ppidlValue))
  711.    return FALSE;
  712. //make a copy of the value pidl
  713. *ppidlValue = Copy(*ppidlValue);
  714. //make a copy of the fully qualified PIDL
  715. *ppidlKey = Copy(pidlFQ);
  716. //truncate the last item of the key PIDL
  717. LPITEMIDLIST   pidlTemp = GetLastItem(*ppidlKey);
  718. pidlTemp->mkid.cb = 0;
  719. pidlTemp->mkid.abID[0] = 0;
  720. return TRUE;
  721. }