208 lines
4.7 KiB
C++
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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|