NT4/private/ole32/com/objact/distname.cxx
2020-09-30 17:12:29 +02:00

423 lines
10 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: cobjact.cxx
//
// Contents: Functions that activate objects residing in persistent storage.
//
// Functions: ConvertToOrgBasedDfsPath
// ProcessPath
// PathFromNormal
//
// History: 05-Oct-93 Ricksa Created
// 31-Dec-93 ErikGav Chicago port
//
//--------------------------------------------------------------------------
#include <ole2int.h>
#ifdef _CAIRO_
#include <compname.hxx>
#include "objact.hxx"
// Name of current computer
CComputerName cnMachine;
#ifdef CAIROLE_DECDEMO
//+-------------------------------------------------------------------------
//
// Function: ProcessDCEPath
//
// Synopsis: Processes the path of a DCE filename
//
// Arguments: [pwszPathIn] - Input path
// [ppwszPathOut] - Output UNC path
//
// Returns: S_OK - Path processed correctly
//
// Algorithm:
//
// History:
//
// Notes: There is a trick in this routine. The output buffer
// is expected to be pointing to a MAX_PATH sized buffer.
// But if we don't need to build the path we just assign
// the old path to it. In other words, the out path
// should be allocated on the stack so it is automatically
// freed.
//
//--------------------------------------------------------------------------
HRESULT ProcessDCEPath(
WCHAR *pwszPathIn,
WCHAR **ppwszPathOut,
WCHAR **ppwszServer)
{
HRESULT hr = CO_E_BAD_PATH;
WCHAR * pch;
WCHAR chHld;
RPC_NS_HANDLE hRpc;
RPC_STATUS rpcStatus;
WCHAR * pwszBinding;
RPC_BINDING_VECTOR * pBindVec;
RPC_BINDING_HANDLE hBindIpTcp = NULL;
RPC_BINDING_HANDLE hBindNp = NULL;
RPC_BINDING_HANDLE hBind = NULL;
WCHAR * pProtSeq;
WCHAR * pNetworkAddr;
BOOL fContinue;
// split off the DCE Name
pch = pwszPathIn;
while(*pch != '!' && *pch != '\0')
pch++;
// The remain part should point to the path of the file
if(*pch == '!')
*ppwszPathOut = pch+1;
// if no server to find, we are done
if(ppwszServer == NULL)
return(hr);
// otherwise find the server name
chHld = *pch;
*pch = '\0';
rpcStatus = RpcNsBindingLookupBegin(RPC_C_NS_SYNTAX_DCE,
pwszPathIn,
NULL,
NULL,
0,
&hRpc);
*pch = chHld;
if(rpcStatus)
return(hr);
fContinue = TRUE;
while( fContinue && !RpcNsBindingLookupNext(hRpc, &pBindVec) ) {
while( fContinue && !RpcNsBindingSelect(pBindVec, &hBind) ) {
if( !RpcBindingToStringBinding(hBind, &pwszBinding) ) {
RpcStringBindingParse(pwszBinding,
NULL,
&pProtSeq,
NULL,
NULL,
NULL);
// tcp or lpc protocall
if(!hBindIpTcp && (
!lstrcmpW(pProtSeq, LOCAL_PROTSEQ) ||
!lstrcmpW(pProtSeq, L"ncacn_ip_tcp") ||
!lstrcmpW(pProtSeq, L"ncacn_nb_tcp") )
) {
hBindIpTcp = hBind;
fContinue = FALSE;
}
// named pipes
else if(!hBindNp && !lstrcmpW(pProtSeq, L"ncacn_np"))
hBindNp = hBind;
else
RpcBindingFree(&hBind);
RpcStringFree(&pwszBinding);
RpcStringFree(&pProtSeq);
}
}
RpcBindingVectorFree(&pBindVec);
}
RpcNsBindingLookupDone(&hRpc);
// select the binding of choice
if(hBindIpTcp)
hBind = hBindIpTcp;
else
hBind = hBindNp;
// get the network address
if( hBind && !RpcBindingToStringBinding(hBind, &pwszBinding) ) {
RpcStringBindingParse(pwszBinding,
NULL,
NULL,
&pNetworkAddr,
NULL,
NULL);
**ppwszServer = '\0';
if(pNetworkAddr[0] != '\\' || pNetworkAddr[1] != '\\')
lstrcpyW(*ppwszServer, L"\\\\");
lstrcatW(*ppwszServer, pNetworkAddr);
RpcStringFree(&pwszBinding);
RpcStringFree(&pNetworkAddr);
hr = S_OK;
}
// free up the binding handle
if(hBindIpTcp)
RpcBindingFree(&hBindIpTcp);
if(hBindNp)
RpcBindingFree(&hBindNp);
return(hr);
}
#endif
//+-------------------------------------------------------------------------
//
// Function: ProcessPath
//
// Synopsis: Converts an old style redirection to UNC path
//
// Arguments: [pwszPathIn] - Input path
// [ppwszPathOut] - Output UNC path
//
// Returns: S_OK - Path processed correctly
//
// Algorithm: Determine if drive is remote. If drive is remote
// try to get the connection which should fail for
// a DFS drive. If drive is an old style remote drive
// then build a UNC path to the object. For DFS paths
// and local paths just return the paths that were input.
// For paths whose root is invalid return and invalid
// path invalid path indication.
//
// History: 25-Jun-93 Ricksa Created
//
// Notes: There is a trick in this routine. The output buffer
// is expected to be pointing to a MAX_PATH sized buffer.
// But if we don't need to build the path we just assign
// the old path to it. In other words, the out path
// should be allocated on the stack so it is automatically
// freed.
//
// BUGBUG [mikese] The ppwszServer parameter is redundant
// since the server address is now computed inside SCM.
//
//--------------------------------------------------------------------------
HRESULT ProcessPath(
WCHAR *pwszPathIn,
WCHAR **ppwszPathOut,
WCHAR **ppwszServer)
{
// build a root directory for the API
WCHAR awcRootDir[3] = L"A:";
awcRootDir[0] = *pwszPathIn;
HRESULT hr = S_OK;
#ifdef CAIROLE_DECDEMO
if( (lstrlenW(pwszPathIn) >= 3 && memcmp(pwszPathIn, L"/.:", 3*sizeof(WCHAR))) ||
(lstrlenW(pwszPathIn) >= 4 && memcmp(pwszPathIn, L"/...", 4*sizeof(WCHAR))) ) {
{
hr = ProcessDCEPath(pwszPathIn, ppwszPathOut, ppwszServer);
return(hr);
}
#endif
// The server address is now computed inside SCM.
**ppwszServer = NULL;
// For UNC paths we don't need to do anything much
if ((pwszPathIn[0] == '\\') && (pwszPathIn[1] == '\\'))
{
// UNC path
*ppwszPathOut = pwszPathIn;
}
else
{
// Conventional drive based path. Attempt to resolve to universal form
CHAR achInfoBuffer[sizeof(UNIVERSAL_NAME_INFOW)
+ MAX_PATH * sizeof(WCHAR)];
DWORD dwInfoSize = sizeof(achInfoBuffer);
DWORD dwStatus = OleWNetGetUniversalName ( pwszPathIn,
UNIVERSAL_NAME_INFO_LEVEL,
achInfoBuffer, &dwInfoSize );
if ( dwStatus == ERROR_SUCCESS )
{
// We successfully resolved to a UNC name
lstrcpyW ( *ppwszPathOut,
((UNIVERSAL_NAME_INFOW*)achInfoBuffer)->lpUniversalName );
}
else
{
// Could not resolve to universal form, so probably local
*ppwszPathOut = pwszPathIn;
}
}
return hr;
}
#else // !_CAIRO_
#ifdef CAIROLE_NT1X_DIST
#include <compname.hxx>
// Name of current computer
CComputerName cnMachine;
//+-------------------------------------------------------------------------
//
// Function: ProcessPath
//
// Synopsis: Converts an old style redirection to UNC path
//
// Arguments: [pwszPathIn] - Input path
// [ppwszPathOut] - Output UNC path
//
// Returns: S_OK - Path processed correctly
//
// Algorithm: Determine if drive is remote. If drive is remote
// try to get the connection which should fail for
// a DFS drive. If drive is an old style remote drive
// then build a UNC path to the object. For DFS paths
// and local paths just return the paths that were input.
// For paths whose root is invalid return and invalid
// path invalid path indication.
//
// History: 25-Jun-93 Ricksa Created
//
// Notes: There is a trick in this routine. The output buffer
// is expected to be pointing to a MAX_PATH sized buffer.
// But if we don't need to build the path we just assign
// the old path to it. In other words, the out path
// should be allocated on the stack so it is automatically
// freed.
//
//--------------------------------------------------------------------------
HRESULT ProcessPath(
WCHAR *pwszPathIn,
WCHAR **ppwszPathOut,
WCHAR **ppwszServer)
{
// build a root directory for the API
WCHAR awcRootDir[4] = L"A:\\";
awcRootDir[0] = *pwszPathIn;
HRESULT hr = S_OK;
if ((pwszPathIn[0] == '\\') && (pwszPathIn[1] == '\\'))
{
// UNC path
*ppwszPathOut = pwszPathIn;
// Do we need to find what server to contact?
if (ppwszServer != NULL)
{
// Find the end of the server name
WCHAR *pwszSlash = wcschr(pwszPathIn + 2, '\\');
// Store the length
int cServer = pwszSlash - pwszPathIn;
if (cServer >= MAX_PATH)
{
// This path is invalid
return CO_E_BAD_PATH;
}
// Is the endpoint us?
if ((lstrlenW(pwszPathIn) == cServer) &&
(lstrlenW((cnMachine.GetUNCCompuerName()) == cServer) &&
(memcmp(pwszPathIn, cnMachine.GetUNCComputerName(), cServer) == 0)))
{
// This path is local
*ppwszServer = NULL;
}
else
{
// Non local path -- Copy in server address & nul terminate.
memcpy(*ppwszServer, pwszPathIn, cServer * sizeof(WCHAR));
(*ppwszServer)[cServer] = 0;
}
}
}
else if (pwszPathIn[1] == ':')
{
if (GetDriveType(awcRootDir) == DRIVE_REMOTE)
{
// Conventional drive based path
DWORD cUNCPath = MAX_PATH;
awcRootDir[2] = 0;
DWORD dwErr;
// Connection based path
if ((dwErr
= OleWNetGetConnection(awcRootDir, *ppwszPathOut, &cUNCPath))
== NO_ERROR)
{
// Find the end of the server name
WCHAR *pwszSlash = wcschr(*ppwszPathOut + 2, '\\');
WCHAR wcSave = *pwszSlash;
*pwszSlash = 0;
// Is this a local path?
if (ppwszServer
&& (lstrcmpiW(*ppwszPathOut, cnMachine.GetUNCComputerName())
!= 0))
{
lstrcpyW(*ppwszServer, *ppwszPathOut);
}
else if (ppwszServer)
{
*ppwszServer = NULL;
}
*pwszSlash = wcSave;
// Concatenate path relative to the root to the
// connection name
lstrcat(*ppwszPathOut, pwszPathIn + 2);
}
else
{
// Convert error to HRESULT
hr = HRESULT_FROM_WIN32(dwErr);
}
}
else
{
*ppwszPathOut = pwszPathIn;
if (ppwszServer)
{
*ppwszServer = NULL;
}
}
}
else
{
hr = CO_E_BAD_PATH;
}
return hr;
}
#endif // CAIROLE_NT1X_DIST
#endif // _CAIRO_