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.
339 lines
7.4 KiB
339 lines
7.4 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 2000
|
|
//
|
|
// File: listfile.cpp
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
|
|
#include "listfile.h"
|
|
|
|
const TCHAR g_szPin[] = TEXT("Pin");
|
|
const TCHAR g_szUnpin[] = TEXT("Unpin");
|
|
const TCHAR g_szDefault[] = TEXT("Default");
|
|
|
|
|
|
bool
|
|
CDblNulStrIter::Next(
|
|
LPCTSTR *ppsz
|
|
) const
|
|
{
|
|
ASSERT(NULL != ppsz);
|
|
|
|
if (m_pszCurrent && *m_pszCurrent)
|
|
{
|
|
*ppsz = m_pszCurrent;
|
|
while(*m_pszCurrent++)
|
|
NULL;
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
|
|
//
|
|
// Class used to represent a double-nul terminated list of strings.
|
|
// Simplifies counting and enumerating substrings.
|
|
//
|
|
class CDblNulStr
|
|
{
|
|
public:
|
|
CDblNulStr(LPCTSTR psz)
|
|
: m_pszStart(psz) { }
|
|
|
|
DWORD StringCount(void) const;
|
|
|
|
CDblNulStrIter GetIter(void) const
|
|
{ return CDblNulStrIter(m_pszStart); }
|
|
|
|
private:
|
|
LPCTSTR m_pszStart;
|
|
};
|
|
|
|
|
|
DWORD
|
|
CDblNulStr::StringCount(
|
|
void
|
|
) const
|
|
{
|
|
ASSERT(NULL != m_pszStart);
|
|
|
|
LPCWSTR psz = m_pszStart;
|
|
DWORD n = 0;
|
|
while(*psz++)
|
|
{
|
|
n++;
|
|
while(*psz++)
|
|
NULL;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
|
|
CListFile::CListFile(
|
|
LPCTSTR pszFile
|
|
) : m_pszFilesToPin(NULL),
|
|
m_pszFilesToUnpin(NULL),
|
|
m_pszFilesDefault(NULL)
|
|
{
|
|
lstrcpyn(m_szFile, pszFile, ARRAYSIZE(m_szFile));
|
|
}
|
|
|
|
|
|
CListFile::~CListFile(
|
|
void
|
|
)
|
|
{
|
|
if (NULL != m_pszFilesToPin)
|
|
{
|
|
LocalFree(m_pszFilesToPin);
|
|
}
|
|
if (NULL != m_pszFilesToUnpin)
|
|
{
|
|
LocalFree(m_pszFilesToUnpin);
|
|
}
|
|
if (NULL != m_pszFilesDefault)
|
|
{
|
|
LocalFree(m_pszFilesDefault);
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CListFile::GetFilesToPin(
|
|
CDblNulStrIter *pIter
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
if (NULL == m_pszFilesToPin)
|
|
{
|
|
DWORD dwResult = _ReadPathsToPin(&m_pszFilesToPin);
|
|
if (ERROR_SUCCESS != dwResult)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwResult);
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*pIter = CDblNulStrIter(m_pszFilesToPin);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CListFile::GetFilesToUnpin(
|
|
CDblNulStrIter *pIter
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
if (NULL == m_pszFilesToUnpin)
|
|
{
|
|
DWORD dwResult = _ReadPathsToUnpin(&m_pszFilesToUnpin);
|
|
if (ERROR_SUCCESS != dwResult)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwResult);
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*pIter = CDblNulStrIter(m_pszFilesToUnpin);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CListFile::GetFilesDefault(
|
|
CDblNulStrIter *pIter
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
if (NULL == m_pszFilesDefault)
|
|
{
|
|
DWORD dwResult = _ReadPathsDefault(&m_pszFilesDefault);
|
|
if (ERROR_SUCCESS != dwResult)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwResult);
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*pIter = CDblNulStrIter(m_pszFilesDefault);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// Load a value string from an INI file. Automatically
|
|
// grows buffer to necessary length. Returned string must be freed
|
|
// using LocalFree().
|
|
//
|
|
DWORD
|
|
CListFile::_ReadString(
|
|
LPCTSTR pszAppName, // May be NULL.
|
|
LPCTSTR pszKeyName, // May be NULL.
|
|
LPCTSTR pszDefault,
|
|
LPTSTR *ppszResult
|
|
)
|
|
{
|
|
ASSERT(NULL != pszDefault);
|
|
ASSERT(NULL != ppszResult);
|
|
|
|
|
|
LPTSTR pszValue = NULL;
|
|
const DWORD CCHGROW = MAX_PATH;
|
|
DWORD cchValue = CCHGROW;
|
|
DWORD dwResult = ERROR_SUCCESS;
|
|
|
|
do
|
|
{
|
|
pszValue = (LPTSTR)LocalAlloc(LPTR, cchValue * sizeof(*pszValue));
|
|
if (NULL == pszValue)
|
|
{
|
|
dwResult = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
DWORD cchCopied = GetPrivateProfileString(pszAppName,
|
|
pszKeyName,
|
|
pszDefault,
|
|
pszValue,
|
|
cchValue,
|
|
m_szFile);
|
|
|
|
if (((NULL == pszAppName || NULL == pszKeyName) && (cchValue - 2) == cchCopied) ||
|
|
((NULL != pszAppName && NULL != pszKeyName) && (cchValue - 1) == cchCopied))
|
|
{
|
|
//
|
|
// Buffer too small. Reallocate and try again.
|
|
//
|
|
cchValue += CCHGROW;
|
|
LocalFree(pszValue);
|
|
pszValue = NULL;
|
|
}
|
|
}
|
|
}
|
|
while(NULL == pszValue && ERROR_SUCCESS == dwResult);
|
|
|
|
if (ERROR_SUCCESS == dwResult)
|
|
{
|
|
//
|
|
// Don't forget, this data can be a double-nul terminated string.
|
|
// Don't try to copy it to an exact-sized buffer using strcpy.
|
|
//
|
|
ASSERT(NULL != pszValue);
|
|
*ppszResult = pszValue;
|
|
}
|
|
return dwResult;
|
|
}
|
|
|
|
|
|
//
|
|
// Read all of the item names in a given INI file section.
|
|
// The names are returned in a double-nul term string.
|
|
// Caller must free returned string using LocalFree.
|
|
// *pbEmpty is set to true if no items were found.
|
|
//
|
|
DWORD
|
|
CListFile::_ReadSectionItemNames(
|
|
LPCTSTR pszSection,
|
|
LPTSTR *ppszItemNames,
|
|
bool *pbEmpty // [optional] Default == NULL.
|
|
)
|
|
{
|
|
bool bEmpty = false;
|
|
LPTSTR pszItemNames;
|
|
DWORD dwResult = _ReadString(pszSection, NULL, TEXT(""), &pszItemNames);
|
|
if (ERROR_SUCCESS == dwResult && TEXT('\0') == *pszItemNames)
|
|
{
|
|
LocalFree(pszItemNames);
|
|
bEmpty = true;
|
|
}
|
|
else
|
|
{
|
|
*ppszItemNames = pszItemNames;
|
|
}
|
|
if (NULL != pbEmpty)
|
|
{
|
|
*pbEmpty = bEmpty;
|
|
}
|
|
return dwResult;
|
|
}
|
|
|
|
|
|
//
|
|
// Read a single item value from an INI file.
|
|
// Caller must free returned string using LocalFree.
|
|
//
|
|
DWORD
|
|
CListFile::_ReadItemValue(
|
|
LPCTSTR pszSection,
|
|
LPCTSTR pszItemName,
|
|
LPTSTR *ppszItemValue
|
|
)
|
|
{
|
|
LPTSTR pszValue;
|
|
DWORD dwResult = _ReadString(pszSection, pszItemName, TEXT(""), &pszValue);
|
|
if (ERROR_SUCCESS == dwResult && TEXT('\0') == *pszValue)
|
|
{
|
|
LocalFree(pszValue);
|
|
dwResult = ERROR_INVALID_DATA;
|
|
}
|
|
else
|
|
{
|
|
*ppszItemValue = pszValue;
|
|
}
|
|
return dwResult;
|
|
}
|
|
|
|
|
|
//
|
|
// Read the names of all paths in the [Pin] section.
|
|
// Caller must free returned string using LocalFree
|
|
//
|
|
DWORD
|
|
CListFile::_ReadPathsToPin(
|
|
LPTSTR *ppszNames,
|
|
bool *pbEmpty
|
|
)
|
|
{
|
|
return _ReadSectionItemNames(g_szPin, ppszNames, pbEmpty);
|
|
}
|
|
|
|
|
|
//
|
|
// Read the names of all paths in the [Unpin] section.
|
|
// Caller must free returned string using LocalFree
|
|
//
|
|
DWORD
|
|
CListFile::_ReadPathsToUnpin(
|
|
LPWSTR *ppszNames,
|
|
bool *pbEmpty
|
|
)
|
|
{
|
|
return _ReadSectionItemNames(g_szUnpin, ppszNames, pbEmpty);
|
|
}
|
|
|
|
|
|
//
|
|
// Read the names of all paths in the [Default] section.
|
|
// Caller must free returned string using LocalFree
|
|
//
|
|
DWORD
|
|
CListFile::_ReadPathsDefault(
|
|
LPWSTR *ppszNames,
|
|
bool *pbEmpty
|
|
)
|
|
{
|
|
return _ReadSectionItemNames(g_szDefault, ppszNames, pbEmpty);
|
|
}
|
|
|
|
|