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.
786 lines
22 KiB
786 lines
22 KiB
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1997.
|
|
//
|
|
// File: path.cxx
|
|
//
|
|
// Contents: Common routines for processing file and pathnames.
|
|
//
|
|
// History: 11-22-1996 DavidMun Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "..\pch\headers.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include <regstr.h> // for app path reg key constant
|
|
#include "..\inc\common.hxx"
|
|
#include "..\inc\misc.hxx"
|
|
#include "..\inc\debug.hxx"
|
|
|
|
|
|
|
|
//
|
|
// Forward references
|
|
//
|
|
|
|
LPCTSTR
|
|
FindFirstTrailingSpace(LPCTSTR ptsz);
|
|
|
|
BOOL
|
|
FileExistsInPath(
|
|
LPTSTR ptszFilename,
|
|
LPCTSTR ptszPath,
|
|
LPTSTR ptszFoundFile,
|
|
ULONG cchFoundBuf);
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: ProcessApplicationName
|
|
//
|
|
// Synopsis: Canonicalize and search for [ptszFilename].
|
|
//
|
|
// Arguments: [ptszFilename] - must be at least MAX_PATH chars long
|
|
// [tszWorkingDir] - "" or a directory not ending in slash
|
|
//
|
|
// Returns: TRUE - a filename was found
|
|
// FALSE - no filename found
|
|
//
|
|
// Modifies: *[ptszFilename]
|
|
//
|
|
// History: 11-21-1996 DavidMun Created
|
|
// 06-03-1997 DavidMun Expand environment vars
|
|
//
|
|
// Notes: This function should only be called to process filenames
|
|
// on the local machine.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
ProcessApplicationName(LPTSTR ptszFilename, size_t cchBuff, LPCTSTR tszWorkingDir)
|
|
{
|
|
BOOL fFound = FALSE;
|
|
TCHAR tszFilenameWithExe[MAX_PATH + 1];
|
|
|
|
//
|
|
// Use tszFilenameWithExe as a temporary buffer for preparing the string
|
|
// in ptszFilename. Get rid of lead/trail spaces and double quotes, then
|
|
// expand environment strings.
|
|
//
|
|
|
|
StringCchCopy(tszFilenameWithExe, MAX_PATH + 1, ptszFilename);
|
|
StripLeadTrailSpace(tszFilenameWithExe);
|
|
DeleteQuotes(tszFilenameWithExe);
|
|
ExpandEnvironmentStrings(tszFilenameWithExe, ptszFilename, MAX_PATH + 1);
|
|
tszFilenameWithExe[0] = TEXT('\0');
|
|
|
|
ULONG cchFilename = lstrlen(ptszFilename) + 1;
|
|
|
|
//
|
|
// If the filename doesn't end with .exe, and the resulting string
|
|
// wouldn't be greater than MAX_PATH + 1 (including NULL),
|
|
// create a version of the filename with .exe appended.
|
|
//
|
|
// Note this will prevent us from finding foo.exe.exe when we're given
|
|
// foo.exe, but the performance gained by excluding this case outweighs
|
|
// the value of completeness, since it's unlikely anyone would create
|
|
// such a filename.
|
|
//
|
|
|
|
if (cchFilename < MAX_PATH + 1 - 4)
|
|
{
|
|
LPTSTR ptszLastDot = _tcsrchr(ptszFilename, TEXT('.'));
|
|
|
|
if (!ptszLastDot || lstrcmpi(ptszLastDot, DOTEXE))
|
|
{
|
|
StringCchCopy(tszFilenameWithExe, MAX_PATH + 1, ptszFilename);
|
|
StringCchCopy(&tszFilenameWithExe[cchFilename], MAX_PATH + 1 - cchFilename, DOTEXE);
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
//
|
|
// If the user specified path information (if there is a colon or
|
|
// backslash anywhere in the string), look for the file as
|
|
// specified or with .exe appended, but look nowhere else.
|
|
//
|
|
|
|
if (_tcspbrk(ptszFilename, TEXT(":\\")))
|
|
{
|
|
if (*tszFilenameWithExe)
|
|
{
|
|
fFound = FileExists(tszFilenameWithExe, MAX_PATH + 1);
|
|
|
|
if (fFound)
|
|
{
|
|
StringCchCopy(ptszFilename, cchBuff, tszFilenameWithExe);
|
|
}
|
|
}
|
|
|
|
if (!fFound)
|
|
{
|
|
fFound = FileExists(ptszFilename, cchBuff);
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// First try the working directory
|
|
//
|
|
|
|
TCHAR tszFoundFile[MAX_PATH + 1] = TEXT("");
|
|
|
|
if (*tszWorkingDir)
|
|
{
|
|
if (*tszFilenameWithExe)
|
|
{
|
|
fFound = FileExistsInPath(tszFilenameWithExe,
|
|
tszWorkingDir,
|
|
tszFoundFile,
|
|
MAX_PATH + 1);
|
|
}
|
|
|
|
if (!fFound)
|
|
{
|
|
fFound = FileExistsInPath(ptszFilename,
|
|
tszWorkingDir,
|
|
tszFoundFile,
|
|
MAX_PATH + 1);
|
|
}
|
|
|
|
if (fFound)
|
|
{
|
|
StringCchCopy(ptszFilename, cchBuff, tszFoundFile);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Next try using the app paths key
|
|
//
|
|
|
|
TCHAR tszAppPathVar[MAX_PATH_VALUE] = TEXT("");
|
|
TCHAR tszAppPathDefault[MAX_PATH + 1] = TEXT("");
|
|
|
|
if (*tszFilenameWithExe)
|
|
{
|
|
GetAppPathInfo(tszFilenameWithExe,
|
|
tszAppPathDefault,
|
|
MAX_PATH + 1,
|
|
tszAppPathVar,
|
|
MAX_PATH_VALUE);
|
|
}
|
|
|
|
if (!*tszAppPathDefault && !*tszAppPathVar)
|
|
{
|
|
GetAppPathInfo(ptszFilename,
|
|
tszAppPathDefault,
|
|
MAX_PATH + 1,
|
|
tszAppPathVar,
|
|
MAX_PATH_VALUE);
|
|
}
|
|
|
|
//
|
|
// If there was a default value, try that
|
|
//
|
|
|
|
if (*tszAppPathDefault)
|
|
{
|
|
fFound = FileExists(tszAppPathDefault, MAX_PATH + 1);
|
|
|
|
if (fFound)
|
|
{
|
|
StringCchCopy(ptszFilename, cchBuff, tszAppPathDefault);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If there's room, concat .exe to the default and look for
|
|
// that
|
|
//
|
|
|
|
ULONG cchDefault = lstrlen(tszAppPathDefault) + 1;
|
|
if (cchDefault < MAX_PATH + 1 - 4)
|
|
{
|
|
StringCchCat(tszAppPathDefault, MAX_PATH + 1, DOTEXE);
|
|
fFound = FileExists(tszAppPathDefault, MAX_PATH + 1);
|
|
if (fFound)
|
|
{
|
|
StringCchCopy(ptszFilename, cchBuff, tszAppPathDefault);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the app path key specified a value for the PATH variable,
|
|
// try looking in all the directories it specifies
|
|
//
|
|
|
|
if (*tszAppPathVar)
|
|
{
|
|
if (*tszFilenameWithExe)
|
|
{
|
|
fFound = FileExistsInPath(tszFilenameWithExe,
|
|
tszAppPathVar,
|
|
tszFoundFile,
|
|
MAX_PATH + 1);
|
|
}
|
|
|
|
if (!fFound)
|
|
{
|
|
fFound = FileExistsInPath(ptszFilename,
|
|
tszAppPathVar,
|
|
tszFoundFile,
|
|
MAX_PATH + 1);
|
|
}
|
|
|
|
if (fFound)
|
|
{
|
|
StringCchCopy(ptszFilename, cchBuff, tszFoundFile);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Try looking along the system PATH variable
|
|
//
|
|
|
|
ULONG cchPath;
|
|
TCHAR tszSystemPath[MAX_PATH_VALUE] = TEXT("");
|
|
|
|
cchPath = GetEnvironmentVariable(TEXT("Path"),
|
|
tszSystemPath,
|
|
MAX_PATH_VALUE);
|
|
|
|
if (!cchPath || cchPath > MAX_PATH_VALUE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (*tszFilenameWithExe)
|
|
{
|
|
fFound = FileExistsInPath(tszFilenameWithExe,
|
|
tszSystemPath,
|
|
tszFoundFile,
|
|
MAX_PATH + 1);
|
|
}
|
|
|
|
if (!fFound)
|
|
{
|
|
fFound = FileExistsInPath(ptszFilename,
|
|
tszSystemPath,
|
|
tszFoundFile,
|
|
MAX_PATH + 1);
|
|
}
|
|
|
|
if (fFound)
|
|
{
|
|
StringCchCopy(ptszFilename, cchBuff, tszFoundFile);
|
|
}
|
|
} while (0);
|
|
|
|
return fFound;
|
|
}
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: IsLocalFilename
|
|
//
|
|
// Synopsis: Return TRUE if [tszFilename] represents a file on the local
|
|
// machine, FALSE otherwise.
|
|
//
|
|
// History: 1-31-1997 DavidMun Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
IsLocalFilename(LPCTSTR tszFilename)
|
|
{
|
|
if (!tszFilename || !*tszFilename)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (tszFilename[0] == TEXT('\\') && tszFilename[1] == TEXT('\\'))
|
|
{
|
|
//
|
|
// Find the length of the portion of the name belonging to the machine name
|
|
//
|
|
LPCTSTR ptszNextSlash = _tcschr(tszFilename + 2, TEXT('\\'));
|
|
if (!ptszNextSlash)
|
|
{
|
|
return FALSE;
|
|
}
|
|
DWORD cchMachineName = (DWORD)(ptszNextSlash - tszFilename - 2);
|
|
|
|
//
|
|
// Get the local machine name (both NetBIOS and FQDN) to compare with that passed in.
|
|
//
|
|
TCHAR tszLocalName[SA_MAX_COMPUTERNAME_LENGTH + 1];
|
|
DWORD cchLocalName = SA_MAX_COMPUTERNAME_LENGTH + 1;
|
|
if (!GetComputerName(tszLocalName, &cchLocalName))
|
|
{
|
|
ERR_OUT("IsLocalFilename: GetComputerName", HRESULT_FROM_WIN32(GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
TCHAR tszFQDN[SA_MAX_COMPUTERNAME_LENGTH + 1];
|
|
DWORD cchFQDN = SA_MAX_COMPUTERNAME_LENGTH + 1;
|
|
if (!GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified, tszFQDN, &cchFQDN))
|
|
{
|
|
ERR_OUT("IsLocalFilename: GetComputerNameEx", HRESULT_FROM_WIN32(GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Return whether we have a match on the machine name portion.
|
|
// I'm assuming that we won't have a case where the NetBIOS name
|
|
// and the FQDN are the same length but different.
|
|
//
|
|
if (cchMachineName == cchLocalName)
|
|
{
|
|
return lstrcmpi(tszFilename + 2, tszLocalName) == 0;
|
|
}
|
|
else if (cchMachineName == cchFQDN)
|
|
{
|
|
return lstrcmpi(tszFilename + 2, tszFQDN) == 0;
|
|
}
|
|
else
|
|
{
|
|
// if the lengths didn't match, there's no need
|
|
// to even bother with a string comparison
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (s_isDriveLetter(tszFilename[0]) && tszFilename[1] == TEXT(':'))
|
|
{
|
|
TCHAR tszRoot[] = TEXT("x:\\");
|
|
tszRoot[0] = tszFilename[0];
|
|
UINT uiType = GetDriveType(tszRoot);
|
|
if (uiType == DRIVE_REMOTE || uiType == 0 || uiType == 1)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: StripLeadTrailSpace
|
|
//
|
|
// Synopsis: Delete leading and trailing spaces from [ptsz].
|
|
//
|
|
// History: 11-22-1996 DavidMun Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
VOID
|
|
StripLeadTrailSpace(LPTSTR ptsz)
|
|
{
|
|
ULONG cchLeadingSpace = _tcsspn(ptsz, TEXT(" \t"));
|
|
ULONG cch = lstrlen(ptsz);
|
|
|
|
//
|
|
// If there are any leading spaces or tabs, move the string
|
|
// (including its nul terminator) left to delete them.
|
|
//
|
|
|
|
if (cchLeadingSpace)
|
|
{
|
|
MoveMemory(ptsz,
|
|
ptsz + cchLeadingSpace,
|
|
(cch - cchLeadingSpace + 1) * sizeof(TCHAR));
|
|
cch -= cchLeadingSpace;
|
|
}
|
|
|
|
//
|
|
// Concatenate at the first trailing space
|
|
//
|
|
|
|
LPTSTR ptszTrailingSpace = (LPTSTR) FindFirstTrailingSpace(ptsz);
|
|
|
|
if (ptszTrailingSpace)
|
|
{
|
|
*ptszTrailingSpace = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: FindFirstTrailingSpace
|
|
//
|
|
// Synopsis: Return a pointer to the first trailing space in [ptsz].
|
|
//
|
|
// History: 11-22-1996 DavidMun Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
LPCTSTR
|
|
FindFirstTrailingSpace(LPCTSTR ptsz)
|
|
{
|
|
LPCTSTR ptszFirstTrailingSpace = NULL;
|
|
LPCTSTR ptszCur;
|
|
|
|
for (ptszCur = ptsz; *ptszCur; ptszCur= NextChar(ptszCur))
|
|
{
|
|
if (*ptszCur == ' ' || *ptszCur == '\t')
|
|
{
|
|
if (!ptszFirstTrailingSpace)
|
|
{
|
|
ptszFirstTrailingSpace = ptszCur;
|
|
}
|
|
}
|
|
else if (ptszFirstTrailingSpace)
|
|
{
|
|
ptszFirstTrailingSpace = NULL;
|
|
}
|
|
}
|
|
return ptszFirstTrailingSpace;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteQuotes
|
|
//
|
|
// Synopsis: Delete all instances of the double quote character from
|
|
// [ptsz].
|
|
//
|
|
// Arguments: [ptsz] - nul terminated string
|
|
//
|
|
// Modifies: *[ptsz]
|
|
//
|
|
// History: 11-21-1996 DavidMun Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
VOID
|
|
DeleteQuotes(LPTSTR ptsz)
|
|
{
|
|
TCHAR *ptszLead;
|
|
TCHAR *ptszTrail;
|
|
|
|
//
|
|
// Move a lead and trail pointer through the buffer, copying from the lead
|
|
// to the trail whenever the character isn't one we're deleting (a double
|
|
// quote).
|
|
//
|
|
// Note: the "Lead" and "Trail" in ptszLead and ptszTrail do not refer
|
|
// to DBCS lead/trail bytes, rather that the ptszLead pointer can move
|
|
// ahead of ptszTrail when it is advanced past a double quote.
|
|
//
|
|
|
|
for (ptszTrail = ptszLead = ptsz;
|
|
*ptszLead;
|
|
ptszLead = NextChar(ptszLead))
|
|
{
|
|
//
|
|
// If the current char is a double quote, we want it deleted, so don't
|
|
// copy it and go on to the next char.
|
|
//
|
|
|
|
if (*ptszLead == TEXT('"'))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// ptszLead is pointing to a 'normal' character, i.e. not a double
|
|
// quote.
|
|
//
|
|
*ptszTrail++ = ptszLead[0];
|
|
}
|
|
*ptszTrail = TEXT('\0');
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: AddQuotes
|
|
//
|
|
// Synopsis: If there's room in the buffer, insert a quote as the first
|
|
// character and concat a quote as the last character.
|
|
//
|
|
// Arguments: [ptsz] - string to modify
|
|
// [cchBuf] - size of string's buffer, in chars
|
|
//
|
|
// History: 11-22-1996 DavidMun Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
VOID
|
|
AddQuotes(LPTSTR ptsz, ULONG cchBuf)
|
|
{
|
|
ULONG cch = lstrlen(ptsz);
|
|
|
|
if (cch < cchBuf - 2)
|
|
{
|
|
MoveMemory(ptsz + 1, ptsz, cch * sizeof(TCHAR));
|
|
*ptsz = ptsz[cch + 1] = TEXT('"');
|
|
ptsz[cch + 2] = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FileExists
|
|
//
|
|
// Synopsis: Return TRUE if the specified file exists and is not a
|
|
// directory.
|
|
//
|
|
// Arguments: [ptszFileName] - filename to search for & modify
|
|
// [cchBuff] - size of buffer
|
|
//
|
|
// Modifies: Filename portion of [ptszFileName].
|
|
//
|
|
// Returns: TRUE - file found
|
|
// FALSE - file not found or error
|
|
//
|
|
// History: 11-21-96 DavidMun Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
FileExists(LPTSTR ptszFileName, size_t cchBuff)
|
|
{
|
|
TCHAR tszFullPath[MAX_PATH + 1];
|
|
LPTSTR ptszFilePart;
|
|
|
|
ULONG cchFullPath = GetFullPathName(ptszFileName,
|
|
MAX_PATH + 1,
|
|
tszFullPath,
|
|
&ptszFilePart) + 1;
|
|
|
|
if (cchFullPath && cchFullPath <= MAX_PATH + 1)
|
|
{
|
|
if (FAILED(StringCchCopy(ptszFileName, cchBuff, tszFullPath)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ULONG flAttributes;
|
|
|
|
flAttributes = GetFileAttributes(ptszFileName);
|
|
|
|
// If we couldn't determine file's attributes, don't consider it found
|
|
|
|
if (flAttributes == 0xFFFFFFFF)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// if file is actually a directory, it's unsuitable as a task, so fail
|
|
|
|
if (flAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Get the filename sans trailing spaces
|
|
|
|
WIN32_FIND_DATA FindFileData;
|
|
HANDLE hFile = FindFirstFile(ptszFileName, &FindFileData);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
FindClose(hFile);
|
|
|
|
LPTSTR ptszLastSlash = _tcsrchr((LPTSTR)ptszFileName, TEXT('\\'));
|
|
if (ptszLastSlash)
|
|
{
|
|
StringCchCopy(ptszLastSlash + 1, cchBuff - (ptszLastSlash + 1 - ptszFileName), FindFileData.cFileName);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: FileExistsInPath
|
|
//
|
|
// Synopsis: Return TRUE if [ptszFilename] exists in path [ptszPath].
|
|
//
|
|
// Arguments: [ptszFilename] - file to look for
|
|
// [ptszPath] - semicolon delimited list of dirs
|
|
// [ptszFoundFile] - if found, [ptszDir]\[ptszFilename]
|
|
// [cchFoundBuf] - size in chars of [ptszFoundFile] buffer
|
|
//
|
|
// Returns: TRUE if file found in dir, FALSE otherwise
|
|
//
|
|
// Modifies: *[ptszFoundFile]
|
|
//
|
|
// History: 11-22-1996 DavidMun Created
|
|
//
|
|
// Notes: Note that by calling FileExists we ensure the found file
|
|
// is a file, not a directory.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
FileExistsInPath(
|
|
LPTSTR ptszFilename,
|
|
LPCTSTR ptszPath,
|
|
LPTSTR ptszFoundFile,
|
|
ULONG cchFoundBuf)
|
|
{
|
|
ULONG cchCopied;
|
|
LPTSTR ptszFilePart;
|
|
|
|
cchCopied = SearchPath(ptszPath,
|
|
ptszFilename,
|
|
NULL,
|
|
cchFoundBuf,
|
|
ptszFoundFile,
|
|
&ptszFilePart);
|
|
|
|
if (cchCopied && cchCopied <= cchFoundBuf)
|
|
{
|
|
return FileExists(ptszFoundFile, cchFoundBuf);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
#define MAX_KEY_LEN (ARRAY_LEN(REGSTR_PATH_APPPATHS) + MAX_PATH)
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetAppPathInfo
|
|
//
|
|
// Synopsis: Fill [ptszAppPathDefault] with the default value and
|
|
// [ptszAppPathVar] with the Path value in the
|
|
// [ptszFilename] application's key under the APPPATHS regkey.
|
|
//
|
|
// Arguments: [ptszFilename] - application name
|
|
// [ptszAppPathDefault] - if not NULL, filled with default value
|
|
// [cchDefaultBuf] - size of [ptszAppPathDefault] buffer
|
|
// [ptszAppPathVar] - if not NULL, filled with Path value
|
|
// [cchPathVarBuf] - size of [cchPathVarBuf] buffer
|
|
//
|
|
// Modifies: *[ptszAppPathDefault], *[ptszAppPathVar]
|
|
//
|
|
// History: 11-22-1996 DavidMun Created
|
|
//
|
|
// Notes: Both values are optional on the registry key, so if a
|
|
// requested value isn't found, it is set to "".
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
VOID
|
|
GetAppPathInfo(
|
|
LPCTSTR ptszFilename,
|
|
LPTSTR ptszAppPathDefault,
|
|
ULONG cchDefaultBuf,
|
|
LPTSTR ptszAppPathVar,
|
|
ULONG cchPathVarBuf)
|
|
{
|
|
HKEY hkey = NULL;
|
|
TCHAR tszAppPathKey[MAX_KEY_LEN];
|
|
|
|
//
|
|
// Initialize out vars
|
|
//
|
|
|
|
if (ptszAppPathDefault)
|
|
{
|
|
ptszAppPathDefault[0] = TEXT('\0');
|
|
}
|
|
|
|
if (ptszAppPathVar)
|
|
{
|
|
ptszAppPathVar[0] = TEXT('\0');
|
|
}
|
|
|
|
//
|
|
// Build registry key name for this app
|
|
//
|
|
|
|
StringCchCopy(tszAppPathKey, MAX_KEY_LEN, REGSTR_PATH_APPPATHS);
|
|
StringCchCat(tszAppPathKey, MAX_KEY_LEN, TEXT("\\"));
|
|
StringCchCat(tszAppPathKey, MAX_KEY_LEN, ptszFilename);
|
|
|
|
do
|
|
{
|
|
LRESULT lr;
|
|
lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
tszAppPathKey,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hkey);
|
|
|
|
if (lr != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If the key could be opened, attempt to read requested values.
|
|
// Both are optional, so ignore errors.
|
|
//
|
|
|
|
DWORD cb;
|
|
DWORD dwType;
|
|
|
|
|
|
if (ptszAppPathDefault)
|
|
{
|
|
cb = cchDefaultBuf * sizeof(TCHAR);
|
|
lr = RegQueryValueEx(hkey,
|
|
NULL, // value name
|
|
NULL, // reserved
|
|
&dwType,
|
|
(LPBYTE) ptszAppPathDefault,
|
|
&cb);
|
|
|
|
if (lr == ERROR_SUCCESS)
|
|
{
|
|
schAssert(dwType == REG_SZ);
|
|
}
|
|
}
|
|
|
|
if (ptszAppPathVar)
|
|
{
|
|
cb = cchPathVarBuf * sizeof(TCHAR);
|
|
|
|
lr = RegQueryValueEx(hkey,
|
|
TEXT("Path"), // value name
|
|
NULL, // reserved
|
|
&dwType,
|
|
(LPBYTE) ptszAppPathVar,
|
|
&cb);
|
|
|
|
if (lr == ERROR_SUCCESS)
|
|
{
|
|
schAssert(dwType == REG_SZ);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
if (hkey)
|
|
{
|
|
RegCloseKey(hkey);
|
|
}
|
|
}
|
|
|
|
|