windows-nt/Source/XPSP1/NT/com/ole32/cs/backend/cspath.cxx
2020-09-26 16:20:57 +08:00

208 lines
4.7 KiB
C++

#include "cstore.hxx"
HRESULT
GetAppmgmtIniFilePath(
PSID pSid,
LPWSTR* ppwszPath
)
{
UNICODE_STRING SidString;
PTOKEN_USER pTokenUser;
WCHAR wszPath[MAX_PATH];
WCHAR * pwszSystemDir;
DWORD AllocLength;
DWORD Length;
DWORD Size;
DWORD Status;
BOOL bStatus;
Status = ERROR_SUCCESS;
*ppwszPath = 0;
pwszSystemDir = wszPath;
AllocLength = sizeof(wszPath) / sizeof(WCHAR);
for (;;)
{
Length = GetSystemDirectory(
pwszSystemDir,
AllocLength );
if ( 0 == Length )
return HRESULT_FROM_WIN32(GetLastError());
if ( Length >= AllocLength )
{
AllocLength = Length + 1;
//
// No check for failure of alloca since it throws an
// exception on failure
//
pwszSystemDir = (WCHAR *) alloca( AllocLength * sizeof(WCHAR) );
continue;
}
break;
}
if ( pSid )
{
if ( ERROR_SUCCESS == Status )
{
Status = RtlConvertSidToUnicodeString(
&SidString,
pSid,
TRUE );
}
if ( Status != ERROR_SUCCESS )
return HRESULT_FROM_WIN32(Status);
}
else
{
RtlInitUnicodeString( &SidString, L"MACHINE" );
}
// System dir + \appmgmt\ + Sid \ + inifilename \ + null
*ppwszPath = new WCHAR[Length + 11 + (SidString.Length / 2) +
(sizeof(APPMGMT_INI_FILENAME) / sizeof(WCHAR))];
if ( *ppwszPath )
{
lstrcpy( *ppwszPath, pwszSystemDir );
if ( pwszSystemDir[lstrlen(pwszSystemDir)-1] != L'\\' )
lstrcat( *ppwszPath, L"\\" );
lstrcat( *ppwszPath, L"appmgmt\\" );
lstrcat( *ppwszPath, SidString.Buffer );
lstrcat( *ppwszPath, APPMGMT_INI_FILENAME );
}
else
{
Status = ERROR_OUTOFMEMORY;
}
if ( pSid )
RtlFreeUnicodeString( &SidString );
return HRESULT_FROM_WIN32(Status);
}
HRESULT ReadClassStorePath(PSID pSid, LPWSTR* ppwszClassStorePath)
{
HRESULT hr;
LPWSTR wszIniFilePath;
hr = GetAppmgmtIniFilePath(
pSid,
&wszIniFilePath);
if (FAILED(hr))
{
return hr;
}
DWORD nBufferSize;
DWORD nCharsReceived;
LPWSTR wszResult;
nBufferSize = DEFAULT_CSPATH_LENGTH;
wszResult = NULL;
//
// The GetPrivateProfileString function is so horribly designed
// that we have to write this disgusting code below to deal with it
//
for (DWORD dwRetry = 0; dwRetry < 7; dwRetry++)
{
WCHAR DefaultBuffer = L'\0';
wszResult = new WCHAR [nBufferSize];
if (!wszResult)
{
hr = E_OUTOFMEMORY;
break;
}
//
// It turns out that this api has other issues as well -- if the file
// doesn't exist it doesn't even return an error that would
// make sense (like 0) -- instead, I've seen it return 8!
// To get around this interesting behavior, I'll set the first
// character of the string to L'\0' before calling the api -- this means that
// subsequent code will treat the failure as if we read a
// zero length class store path from the file, which is the
// desired behavior.
//
*wszResult = L'\0';
nCharsReceived = GetPrivateProfileString(
APPMGMT_INI_CSTORE_SECTIONNAME,
APPMGMT_INI_CSPATH_KEYNAME,
&DefaultBuffer,
wszResult,
nBufferSize,
wszIniFilePath);
//
// If nothing is written, then there's no point in going forward
// since this api returns the number of characters we need to write
//
if (!nCharsReceived)
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
break;
}
if (nCharsReceived != (nBufferSize - 1))
{
break;
}
//
// Double the size of the allocation
//
nBufferSize *= 2;
//
// Free the previous allocation
//
delete [] wszResult;
wszResult = NULL;
}
if (wszResult && nCharsReceived)
{
LPWSTR wszAllocatedCSPathForCaller;
*ppwszClassStorePath = new WCHAR[nCharsReceived + 1];
if (*ppwszClassStorePath)
{
wcscpy(*ppwszClassStorePath, wszResult);
}
else
{
hr = E_OUTOFMEMORY;
}
}
delete [] wszResult;
delete [] wszIniFilePath;
return hr;
}