windows-nt/Source/XPSP1/NT/com/ole32/dcomss/olescm/actmisc.cxx
2020-09-26 16:20:57 +08:00

533 lines
13 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996.
//
// File: actmisc.cxx
//
// Contents: Miscellaneous functions.
//
// Functions:
//
// History:
//
//--------------------------------------------------------------------------
#include "act.hxx"
//-------------------------------------------------------------------------
//
// GetSystemDir
//
// Returns the system directory path.
//
// ppwszSystemDir is allocated by this routine and should be freed by the
// caller.
//
//-------------------------------------------------------------------------
HRESULT
GetSystemDir(
OUT WCHAR ** ppwszSystemDir
)
{
DWORD PathChars;
WCHAR * pszSystemDir;
*ppwszSystemDir = 0;
PathChars = GetSystemDirectory( NULL, 0 );
if ( ! PathChars )
return HRESULT_FROM_WIN32( GetLastError() );
// I don't trust these APIs to include the null.
PathChars++;
pszSystemDir = (WCHAR *) PrivMemAlloc( PathChars * sizeof(WCHAR) );
if ( ! pszSystemDir )
return E_OUTOFMEMORY;
PathChars = GetSystemDirectoryW( pszSystemDir, PathChars );
if ( ! PathChars )
{
PrivMemFree( pszSystemDir );
return HRESULT_FROM_WIN32( GetLastError() );
}
#if 1 // #ifndef _CHICAGO_
*ppwszSystemDir = pszSystemDir;
return S_OK;
#else
*ppwszSystemDir = (WCHAR *) PrivMemAlloc( PathChars * sizeof(WCHAR) );
PathChars = MultiByteToWideChar(
CP_ACP,
0,
pszSystemDir,
-1,
*ppwszSystemDir,
PathChars );
PrivMemFree( pszSystemDir );
if ( ! PathChars )
{
PrivMemFree( *ppwszSystemDir );
return HRESULT_FROM_WIN32( GetLastError() );
}
else
{
return S_OK;
}
#endif
}
HRESULT GetMachineName(
WCHAR * pwszPath,
WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1]
#ifdef DFSACTIVATION
,BOOL bDoDfsConversion
#endif
)
{
WCHAR * pwszServerName;
BYTE Buffer[sizeof(REMOTE_NAME_INFO)+MAX_PATH*sizeof(WCHAR)];
DWORD BufferSize = sizeof(Buffer);
WCHAR Drive[4];
DWORD Status;
//
// Extract the server name from the file's path name.
//
if ( pwszPath[0] != L'\\' || pwszPath[1] != L'\\' )
{
lstrcpynW(Drive, pwszPath, 3);
Drive[2] = L'\\';
Drive[3] = NULL;
// We must impersonate around the call to GetDriveType as well,
// so that we have the same access to the mapped drive as the
// calling client.
if ( RpcImpersonateClient((RPC_BINDING_HANDLE)0) != ERROR_SUCCESS )
return CO_E_SCM_RPC_FAILURE;
if (GetDriveType(Drive) != DRIVE_REMOTE )
{
RpcRevertToSelf();
return S_FALSE;
}
Status = ScmWNetGetUniversalName( pwszPath,
UNIVERSAL_NAME_INFO_LEVEL,
Buffer,
&BufferSize );
RpcRevertToSelf();
if ( Status != NO_ERROR )
{
return CO_E_BAD_PATH;
}
pwszPath = ((UNIVERSAL_NAME_INFO *)Buffer)->lpUniversalName;
if ( ! pwszPath || pwszPath[0] != L'\\' || pwszPath[1] != L'\\' )
{
// Must be a local path.
return S_FALSE;
}
}
#ifdef DFSACTIVATION
WCHAR wszDfsPath[MAX_PATH];
WCHAR * pwszDfsPath = wszDfsPath;
if ( bDoDfsConversion && ghDfs )
{
DWORD DfsPathLen;
DfsPathLen = sizeof(wszDfsPath);
for (;;)
{
Status = DfsFsctl(
ghDfs,
FSCTL_DFS_GET_SERVER_NAME,
(PVOID) &pwszPath[1],
lstrlenW(&pwszPath[1]) * sizeof(WCHAR),
(PVOID) pwszDfsPath,
&DfsPathLen );
if ( Status == STATUS_BUFFER_OVERFLOW )
{
Win4Assert( pwszDfsPath == wszDfsPath );
pwszDfsPath = (WCHAR *) PrivMemAlloc( DfsPathLen );
if ( ! pwszDfsPath )
return E_OUTOFMEMORY;
continue;
}
break;
}
if ( Status == STATUS_SUCCESS )
pwszPath = pwszDfsPath;
}
#endif
// Skip the "\\".
LPWSTR pwszTemp = pwszPath + 2;
pwszServerName = wszMachineName;
while ( *pwszTemp != L'\\' )
*pwszServerName++ = *pwszTemp++;
*pwszServerName = 0;
#ifdef DFSACTIVATION
if ( pwszDfsPath != wszDfsPath )
PrivMemFree( pwszDfsPath );
#endif
return S_OK;
}
HRESULT GetPathForServer(
WCHAR * pwszPath,
WCHAR wszPathForServer[MAX_PATH+1],
WCHAR ** ppwszPathForServer )
{
BYTE Buffer[sizeof(REMOTE_NAME_INFO)+MAX_PATH*sizeof(WCHAR)];
WCHAR Drive[4];
DWORD BufferSize = sizeof(Buffer);
DWORD PathLength;
DWORD Status;
UINT uiDriveType;
*ppwszPathForServer = 0;
if ( pwszPath &&
(lstrlenW(pwszPath) >= 3) &&
(pwszPath[1] == L':') && (pwszPath[2] == L'\\') )
{
lstrcpynW(Drive, pwszPath, 3);
Drive[2] = L'\\';
Drive[3] = NULL;
// We must impersonate around the call to GetDriveType as well,
// so that we have the same access to the mapped drive as the
// calling client.
if ( RpcImpersonateClient((RPC_BINDING_HANDLE)0) != ERROR_SUCCESS )
return CO_E_SCM_RPC_FAILURE;
uiDriveType = GetDriveType( Drive );
RpcRevertToSelf();
switch ( uiDriveType )
{
case 0 : // Drive type can not be determined
case 1 : // The root directory does not exist
case DRIVE_CDROM :
case DRIVE_RAMDISK :
case DRIVE_REMOVABLE :
//
// We can't convert these to file names that the server will be
// able to access.
//
return CO_E_BAD_PATH;
case DRIVE_FIXED :
if ( 0 == gpMachineName )
{
return E_OUTOFMEMORY;
}
wszPathForServer[0] = wszPathForServer[1] = L'\\';
lstrcpyW( &wszPathForServer[2], gpMachineName->Name() );
PathLength = lstrlenW( wszPathForServer );
wszPathForServer[PathLength] = L'\\';
wszPathForServer[PathLength+1] = pwszPath[0];
wszPathForServer[PathLength+2] = L'$';
wszPathForServer[PathLength+3] = L'\\';
lstrcpyW( &wszPathForServer[PathLength+4], &pwszPath[3] );
*ppwszPathForServer = wszPathForServer;
break;
case DRIVE_REMOTE :
if ( RpcImpersonateClient((RPC_BINDING_HANDLE)0) != ERROR_SUCCESS )
return CO_E_SCM_RPC_FAILURE;
Status = ScmWNetGetUniversalName( pwszPath,
UNIVERSAL_NAME_INFO_LEVEL,
Buffer,
&BufferSize );
RpcRevertToSelf();
if ( Status != NO_ERROR )
{
return CO_E_BAD_PATH;
}
Win4Assert( ((UNIVERSAL_NAME_INFO *)Buffer)->lpUniversalName );
lstrcpyW( wszPathForServer, ((UNIVERSAL_NAME_INFO *)Buffer)->lpUniversalName );
*ppwszPathForServer = wszPathForServer;
Win4Assert( wszPathForServer[0] == L'\\' &&
wszPathForServer[1] == L'\\' );
break;
}
}
else
{
*ppwszPathForServer = pwszPath;
}
return S_OK;
}
//
// Finds an exe name by looking for the first .exe sub string which
// is followed by any of the given delimiter chars or a null.
//
BOOL
FindExeComponent(
IN WCHAR * pwszString,
IN WCHAR * pwszDelimiters,
OUT WCHAR ** ppwszStart,
OUT WCHAR ** ppwszEnd
)
{
WCHAR * pwszLast;
WCHAR * pwszSearch;
WCHAR wszStr[4];
DWORD Delimiters;
Delimiters = lstrlenW( pwszDelimiters ) + 1;
pwszSearch = pwszString;
pwszLast = pwszSearch + lstrlenW( pwszSearch );
for ( ; pwszSearch <= (pwszLast - 4); pwszSearch++ )
{
if ( pwszSearch[0] != L'.' )
continue;
for ( DWORD n = 0; n < Delimiters; n++ )
{
if ( pwszDelimiters[n] == pwszSearch[4] )
{
// Note that there is no lstrnicmpW, so we use memcpy/lstrcmpiW.
memcpy( wszStr, &pwszSearch[1], 3 * sizeof(WCHAR) );
wszStr[3] = 0;
if ( lstrcmpiW( wszStr, L"exe" ) == 0 )
goto FoundExe;
}
}
}
FoundExe:
if ( pwszSearch > (pwszLast - 4) )
return FALSE;
*ppwszEnd = &pwszSearch[4];
for ( ; pwszSearch != pwszString && pwszSearch[-1] != L'\\'; pwszSearch-- )
;
*ppwszStart = pwszSearch;
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Function: HexStringToDword
//
// Synopsis: Convert a character string hex digits to a DWORD
//
// Arguments: [lpsz] - string to convert
// [Value] - where to put the value
// [cDigits] - number of digits expected
// [chDelim] - delimiter for end of string
//
// Returns: TRUE - string converted to a DWORD
// FALSE - string could not be converted
//
// Algorithm: For each digit in the string, shift the value and
// add the value of the digit to the output value. When
// all the digits are processed, if a delimiter is
// provided, make sure the last character is the delimiter.
//
// History: 22-Apr-93 Ricksa Created
//
// Notes: Lifted from CairOLE sources so that SCM will have no
// dependency on compobj.dll.
//
//--------------------------------------------------------------------------
#if 1 // #ifndef _CHICAGO_
BOOL HexStringToDword(
LPCWSTR FAR& lpsz,
DWORD FAR& Value,
int cDigits,
WCHAR chDelim)
{
int Count;
Value = 0;
for (Count = 0; Count < cDigits; Count++, lpsz++)
{
if (*lpsz >= '0' && *lpsz <= '9')
{
Value = (Value << 4) + *lpsz - '0';
}
else if (*lpsz >= 'A' && *lpsz <= 'F')
{
Value = (Value << 4) + *lpsz - 'A' + 10;
}
else if (*lpsz >= 'a' && *lpsz <= 'f')
{
Value = (Value << 4) + *lpsz - 'a' + 10;
}
else
{
return FALSE;
}
}
if (chDelim != 0)
{
return *lpsz++ == chDelim;
}
return TRUE;
}
#endif
//+-------------------------------------------------------------------------
//
// Function: GUIDFromString
//
// Synopsis: Convert a string in Registry to a GUID.
//
// Arguments: [lpsz] - string from registry
// [pguid] - where to put the guid.
//
// Returns: TRUE - GUID conversion successful
// FALSE - GUID conversion failed.
//
// Algorithm: Convert each part of the GUID string to the
// appropriate structure member in the guid using
// HexStringToDword. If all conversions work return
// TRUE.
//
// History: 22-Apr-93 Ricksa Created
//
// Notes: Lifted from CairOLE sources so that SCM will have no
// dependency on compobj.dll.
//
//--------------------------------------------------------------------------
#if 1 // #ifndef _CHICAGO_
BOOL GUIDFromString(LPCWSTR lpsz, LPGUID pguid)
{
DWORD dw;
if (*lpsz++ != '{')
{
return FALSE;
}
if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
{
return FALSE;
}
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
{
return FALSE;
}
pguid->Data2 = (WORD)dw;
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
{
return FALSE;
}
pguid->Data3 = (WORD)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
{
return FALSE;
}
pguid->Data4[0] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
{
return FALSE;
}
pguid->Data4[1] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
{
return FALSE;
}
pguid->Data4[2] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
{
return FALSE;
}
pguid->Data4[3] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
{
return FALSE;
}
pguid->Data4[4] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
{
return FALSE;
}
pguid->Data4[5] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
{
return FALSE;
}
pguid->Data4[6] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, /*(*/ '}'))
{
return FALSE;
}
pguid->Data4[7] = (BYTE)dw;
return TRUE;
}
#endif