312 lines
9.1 KiB
C++
312 lines
9.1 KiB
C++
/*****************************************************************/
|
|
/** Microsoft LAN Manager **/
|
|
/** Copyright(c) Microsoft Corp., 1990 **/
|
|
/*****************************************************************/
|
|
|
|
|
|
/*
|
|
MiscAPIs.cxx
|
|
Miscallaneous APIs
|
|
|
|
|
|
FILE HISTORY:
|
|
|
|
jonn 14-Jan-1991 Split from winprof.cxx
|
|
jonn 17-Jan-1991 Split off lm21util.cxx, lm30spfc.cxx
|
|
jonn 02-Feb-1991 Removed unused routines
|
|
rustanl 12-Apr-1991 Added UI_UNCPathCompare and
|
|
UI_UNCPathValidate
|
|
beng 17-May-1991 Correct lmui.hxx usage
|
|
jonn 22-May-1991 Added MyNetUseAdd (was in winprof.cxx)
|
|
rustanl 24-May-1991 Added AUTO_CURSOR to MyNetUseAdd
|
|
terryk 31-Oct-1991 add mnet.h and change I_NetXXX to
|
|
I_MNetXXX
|
|
Yi-HsinS 31-Dec-1991 Unicode work
|
|
terryk 10-Oct-1993 deleted MyNetUseAdd
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define INCL_WINDOWS
|
|
#define INCL_WINDOWS_GDI
|
|
#define INCL_DOSERRORS
|
|
#define INCL_NETERRORS
|
|
#define INCL_NETCONS
|
|
#define INCL_NETACCESS
|
|
#define INCL_NETSERVER
|
|
#define INCL_NETWKSTA
|
|
#define INCL_NETSERVICE
|
|
#define INCL_NETLIB
|
|
#define INCL_ICANON
|
|
#define INCL_NETUSE // for NetUseAdd
|
|
#define _WINNETWK_
|
|
#include <lmui.hxx>
|
|
#undef _WINNETWK_
|
|
|
|
extern "C"
|
|
{
|
|
#include <mnet.h>
|
|
#include <winnetwk.h>
|
|
#include <npapi.h>
|
|
#include <lmsname.h>
|
|
}
|
|
|
|
#include <uiassert.hxx>
|
|
#include <uitrace.hxx>
|
|
#include <string.hxx>
|
|
#include <lmowks.hxx>
|
|
#include <lmodom.hxx>
|
|
#include <lmodev.hxx> // for DEVICE object
|
|
#include <uibuffer.hxx>
|
|
#include <strchlit.hxx> // for string and character literals
|
|
#include <lmsvc.hxx>
|
|
#include <miscapis.hxx>
|
|
|
|
|
|
|
|
/* Local prototypes */
|
|
|
|
|
|
/* functions */
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: CheckLMService
|
|
|
|
SYNOPSIS: Checks to make sure the LM Wksta service is willing to
|
|
accept requests.
|
|
|
|
RETURNS: NERR_Success if the service is happy happy
|
|
WN_NO_NETWORK if the service is stopped or stopping
|
|
WN_FUNCTION_BUSY if the service is starting
|
|
Other error if an error occurred getting the status
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
Johnl 09-Sep-1992 Created
|
|
|
|
********************************************************************/
|
|
|
|
APIERR CheckLMService( void )
|
|
{
|
|
|
|
APIERR err = NERR_Success ;
|
|
|
|
//
|
|
// we almost always hit the wksta soon after this call & the wksta
|
|
// is usually started. so this check will avoid paging in the service
|
|
// controller. it just ends up paging in the wksta a bit earlier.
|
|
// only if the call fails do we hit the service controller for the
|
|
// actual status.
|
|
//
|
|
WKSTA_10 wksta_10 ;
|
|
|
|
if ( (wksta_10.QueryError() == NERR_Success) &&
|
|
(wksta_10.GetInfo() == NERR_Success) )
|
|
{
|
|
return NERR_Success ;
|
|
}
|
|
|
|
LM_SERVICE service( NULL, (const TCHAR *)SERVICE_WORKSTATION );
|
|
if ( err = service.QueryError() )
|
|
{
|
|
return err ;
|
|
}
|
|
|
|
switch ( service.QueryStatus( &err ) )
|
|
{
|
|
case LM_SVC_STOPPED:
|
|
case LM_SVC_STOPPING:
|
|
if ( !err )
|
|
err = WN_NO_NETWORK ;
|
|
TRACEEOL("::CheckLMService - Returning WN_NO_NETWORK") ;
|
|
break ;
|
|
|
|
case LM_SVC_STARTING:
|
|
if ( !err )
|
|
err = WN_FUNCTION_BUSY ;
|
|
TRACEEOL("::CheckLMService - Returning WN_FUNCTION_BUSY") ;
|
|
break ;
|
|
|
|
case LM_SVC_STATUS_UNKNOWN:
|
|
case LM_SVC_STARTED:
|
|
case LM_SVC_PAUSED:
|
|
case LM_SVC_PAUSING:
|
|
case LM_SVC_CONTINUING:
|
|
default:
|
|
/* Return unadultered error code
|
|
*/
|
|
break ;
|
|
}
|
|
|
|
return err ;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: ParseRemoteName
|
|
|
|
SYNOPSIS: Canonicalizes a remote resource name and determines
|
|
its type
|
|
|
|
ARGUMENTS:
|
|
RemoteName - Remote resource name to be parsed
|
|
CanonName - Buffer for canonicalized name, assumed to be
|
|
MAX_PATH characters long
|
|
CanonNameSize - Size, in bytes, of output buffer
|
|
PathStart - Set to the offset, in characters, of the start
|
|
of the "\share" portion (in the REMOTENAMETYPE_SHARE case)
|
|
or the "\path" portion (in the REMOTENAMETYPE_PATH case)
|
|
of the name within CanonName. Not set in other cases.
|
|
|
|
RETURNS:
|
|
If nlsRemote is like Then returns
|
|
-------------------- ------------
|
|
workgroup REMOTENAMETYPE_WORKGROUP
|
|
\\server REMOTENAMETYPE_SERVER
|
|
\\server\share REMOTENAMETYPE_SHARE
|
|
\\server\share\path REMOTENAMETYPE_PATH
|
|
(other) REMOTENAMETYPE_INVALID
|
|
|
|
NOTES:
|
|
|
|
HISTORY:
|
|
AnirudhS 21-Apr-1995 Ported from Win95 sources - used netlib
|
|
functions rather than ad hoc parsing, introduced comments
|
|
|
|
********************************************************************/
|
|
|
|
REMOTENAMETYPE ParseRemoteName(
|
|
IN LPWSTR RemoteName,
|
|
OUT LPWSTR CanonName,
|
|
IN DWORD CanonNameSize,
|
|
OUT PULONG PathStart
|
|
)
|
|
{
|
|
//
|
|
// Determine the path type
|
|
//
|
|
DWORD PathType = 0;
|
|
NET_API_STATUS Status = I_NetPathType(NULL, RemoteName, &PathType, 0);
|
|
|
|
if (Status != NERR_Success)
|
|
{
|
|
return REMOTENAMETYPE_INVALID;
|
|
}
|
|
|
|
//
|
|
// I_NetPathType doesn't give us quite as fine a classification of
|
|
// path types as we need, so we still need to do a little more parsing
|
|
//
|
|
switch (PathType)
|
|
{
|
|
case ITYPE_PATH_RELND:
|
|
//
|
|
// A driveless relative path
|
|
// A valid workgroup or domain name would be classified as
|
|
// such, but it still needs to be validated as a workgroup name
|
|
//
|
|
Status = I_NetNameCanonicalize(
|
|
NULL, // ServerName
|
|
RemoteName, // Name
|
|
CanonName, // Outbuf
|
|
CanonNameSize, // OutbufLen
|
|
NAMETYPE_WORKGROUP, // NameType
|
|
0 // Flags
|
|
);
|
|
|
|
if (Status == NERR_Success)
|
|
{
|
|
return REMOTENAMETYPE_WORKGROUP;
|
|
}
|
|
else
|
|
{
|
|
return REMOTENAMETYPE_INVALID;
|
|
}
|
|
|
|
case ITYPE_UNC_COMPNAME:
|
|
//
|
|
// A UNC computername, "\\server"
|
|
//
|
|
{
|
|
//
|
|
// HACK: I_NetPathCanonicalize likes "\\server\share" but not
|
|
// "\\server", so append a dummy share name to canonicalize.
|
|
// We assume that the CanonName buffer will still be big
|
|
// enough (which it will, in the calls made from this file).
|
|
//
|
|
if (wcslen(RemoteName) + 3 > NNLEN)
|
|
{
|
|
return REMOTENAMETYPE_INVALID;
|
|
}
|
|
WCHAR wszDummy[NNLEN];
|
|
wcscpy(wszDummy, RemoteName);
|
|
wcscat(wszDummy, L"\\a");
|
|
|
|
UIASSERT(CanonNameSize >= sizeof(wszDummy));
|
|
PathType = ITYPE_UNC;
|
|
Status = I_NetPathCanonicalize(
|
|
NULL, // ServerName
|
|
wszDummy, // PathName
|
|
CanonName, // Outbuf
|
|
CanonNameSize, // OutbufLen
|
|
NULL, // Prefix
|
|
&PathType, // PathType
|
|
0 // Flags
|
|
);
|
|
}
|
|
|
|
if (Status != NERR_Success)
|
|
{
|
|
return REMOTENAMETYPE_INVALID;
|
|
}
|
|
|
|
CanonName[ wcslen(CanonName) - 2 ] = 0;
|
|
|
|
return REMOTENAMETYPE_SERVER;
|
|
|
|
case ITYPE_UNC:
|
|
//
|
|
// A UNC path, either "\\server\share" or "\\server\share\path" -
|
|
// canonicalize and determine which one
|
|
//
|
|
Status = I_NetPathCanonicalize(
|
|
NULL, // ServerName
|
|
RemoteName, // PathName
|
|
CanonName, // Outbuf
|
|
CanonNameSize, // OutbufLen
|
|
NULL, // Prefix
|
|
&PathType, // PathType
|
|
0 // Flags
|
|
);
|
|
if (Status != NERR_Success)
|
|
{
|
|
return REMOTENAMETYPE_INVALID;
|
|
}
|
|
|
|
{
|
|
WCHAR * pSlash = wcschr(CanonName+2, PATH_SEPARATOR);
|
|
UIASSERT(pSlash);
|
|
*PathStart = (ULONG)(pSlash - CanonName);
|
|
|
|
// Look for a fourth slash
|
|
pSlash = wcschr(pSlash+1, PATH_SEPARATOR);
|
|
if (pSlash)
|
|
{
|
|
*PathStart = (ULONG)(pSlash - CanonName);
|
|
return REMOTENAMETYPE_PATH;
|
|
}
|
|
else
|
|
{
|
|
return REMOTENAMETYPE_SHARE;
|
|
}
|
|
}
|
|
|
|
default:
|
|
return REMOTENAMETYPE_INVALID;
|
|
}
|
|
}
|