mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1346 lines
25 KiB
1346 lines
25 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
prtshare.cxx
|
|
|
|
Abstract:
|
|
|
|
Printer Share class
|
|
|
|
Author:
|
|
|
|
Steve Kiraly (SteveKi) 17-Mar-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "prtshare.hxx"
|
|
#include "persist.hxx"
|
|
|
|
/********************************************************************
|
|
|
|
Class statics.
|
|
|
|
********************************************************************/
|
|
LPCTSTR TPrtShare::_gszIllegalDosChars = TEXT( " *?/\\|,;:+=<>[]\"" );
|
|
LPCTSTR TPrtShare::_gszIllegalNtChars = TEXT( ",\\/" );
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
PrtShare constructor
|
|
|
|
Routine Description:
|
|
|
|
Initializes the printer share object.
|
|
|
|
Arguments:
|
|
|
|
Pointer to the print server name to build a
|
|
share enumeration for.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
|
|
TPrtShare::
|
|
TPrtShare(
|
|
IN LPCTSTR pszServerName
|
|
) : _PrtPrinter( pszServerName ),
|
|
_pNetResBuf( NULL ),
|
|
_dwNetResCount( 0 ),
|
|
_strServerName( pszServerName ),
|
|
_bValid( FALSE ),
|
|
_pfNetShareEnum( NULL ),
|
|
_pfNetApiBufferFree( NULL ),
|
|
_pLibrary( NULL )
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::ctor.\n" ) );
|
|
|
|
//
|
|
// Check if members were constructed successfuly.
|
|
//
|
|
if( _strServerName.bValid() &&
|
|
_PrtPrinter.bValid() &&
|
|
bLoad() &&
|
|
bGetEnumData() ){
|
|
|
|
_bValid = TRUE;
|
|
}
|
|
|
|
//
|
|
// Dump debug information.
|
|
//
|
|
#if DBG
|
|
if( _bValid ){
|
|
vPrint();
|
|
}
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
PrtShare destructor.
|
|
|
|
Routine Description:
|
|
|
|
Releases resources owned by this class.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
TPrtShare::
|
|
~TPrtShare(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::dtor.\n" ) );
|
|
vDestroy();
|
|
vUnload();
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bValid
|
|
|
|
Routine Description:
|
|
|
|
Indicates if the object is in a valid state.
|
|
|
|
Arguments:
|
|
|
|
Nothing.
|
|
|
|
Return Value:
|
|
|
|
TRUE object is valid, FALSE object is not valid.
|
|
|
|
--*/
|
|
TPrtShare::
|
|
bValid(
|
|
VOID
|
|
) const
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::bValid.\n" ) );
|
|
return _bValid;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bIsValidShareNameForThisPrinter
|
|
|
|
Routine Description:
|
|
|
|
Indicates if the specified share name is valid for the specified
|
|
share name provided as the first argument. If the printer name is
|
|
not provided then this routine returns an indication if the name is
|
|
unique.
|
|
|
|
Arguments:
|
|
|
|
pszShareName - Pointer to new share name.
|
|
pszPrinterName - Printer name to check against.
|
|
|
|
Return Value:
|
|
|
|
TRUE if name is a usable sharen name for this printer.
|
|
FALSE if error occurred.
|
|
|
|
--*/
|
|
BOOL
|
|
TPrtShare::
|
|
bIsValidShareNameForThisPrinter(
|
|
IN LPCTSTR pszShareName,
|
|
IN LPCTSTR pszPrinterName
|
|
) const
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::bIsValidShareNameForThisPrinter.\n" ) );
|
|
|
|
//
|
|
// Ensure we are in a valid state.
|
|
//
|
|
SPLASSERT( bValid() );
|
|
SPLASSERT( pszShareName );
|
|
SPLASSERT( pszPrinterName );
|
|
|
|
BOOL bStatus;
|
|
|
|
//
|
|
// Check if the share name is currently in use.
|
|
//
|
|
#ifdef _UNICODE
|
|
bStatus = !bIsShareNameUsedW( pszShareName );
|
|
#else
|
|
bStatus = !bIsShareNameUsedA( pszShareName );
|
|
#endif
|
|
|
|
//
|
|
// If we failed to find a match from the network shares.
|
|
// Check for printer name matches, since they are exist in
|
|
// the same namespace.
|
|
//
|
|
if( bStatus ){
|
|
bStatus = _PrtPrinter.bIsValidShareNameForThisPrinter( pszShareName,
|
|
pszPrinterName );
|
|
}
|
|
|
|
return bStatus;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bRefresh
|
|
|
|
Routine Description:
|
|
|
|
Will refresh the share enumeration structure.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE if enumeration was refreshed and object is still valid,
|
|
FALSE if error occurred.
|
|
|
|
--*/
|
|
BOOL
|
|
TPrtShare::
|
|
bRefresh(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::bRefresh\n" ) );
|
|
|
|
//
|
|
// Ensure we are in a valid state.
|
|
//
|
|
SPLASSERT( bValid() );
|
|
|
|
//
|
|
// Release the current resources.
|
|
//
|
|
vDestroy();
|
|
|
|
//
|
|
// Refresh the share names and the printer names.
|
|
//
|
|
_bValid = bGetEnumData() && _PrtPrinter.bRefresh();
|
|
|
|
return _bValid;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bNewShareName
|
|
|
|
Routine Description:
|
|
|
|
Creates a new share name from the given name.
|
|
|
|
Arguments:
|
|
|
|
Place where to return the new share name.
|
|
Base share name to create new name from.
|
|
|
|
Return Value:
|
|
|
|
TRUE new unique share name returned, FALSE error occurred.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
TPrtShare::
|
|
bNewShareName(
|
|
IN TString &strShareName,
|
|
IN const TString &strBaseShareName
|
|
) const
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::bNewShareName\n" ) );
|
|
|
|
//
|
|
// Ensure we are in a valid state.
|
|
//
|
|
SPLASSERT( bValid() );
|
|
|
|
UINT i;
|
|
BOOL bStatus = FALSE;
|
|
TCHAR szTempShareName[kPrinterShareNameBufMax];
|
|
TCHAR szShareName[kPrinterShareNameBufMax];
|
|
|
|
PTSTR pDst = szTempShareName;
|
|
PTSTR pSrc = (LPTSTR)(LPCTSTR)strBaseShareName;
|
|
|
|
//
|
|
// Truncate the base name and filter illegal characters.
|
|
//
|
|
for( i = 0; i < 8 && *pSrc; i++, pSrc++ ){
|
|
|
|
//
|
|
// Replace illegal characters with underscore.
|
|
//
|
|
if( _tcschr( _gszIllegalDosChars, *pSrc ) ){
|
|
i--; // Collapse spaces.
|
|
} else {
|
|
*pDst++ = *pSrc;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Null terminate.
|
|
//
|
|
*pDst = 0;
|
|
|
|
//
|
|
// If the share name does not have length then
|
|
// get the default printer share name.
|
|
//
|
|
if( !_tcslen( szTempShareName ) ){
|
|
bStatus = LoadString( ghInst,
|
|
IDS_DEFAULT_SHARE,
|
|
szTempShareName,
|
|
COUNTOF( szTempShareName ) - 1 );
|
|
if( !bStatus ){
|
|
DBGMSG( DBG_WARN, ( "Unable loaded default share name resource.\n" ) );
|
|
szTempShareName[0] = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Copy share name from temp buffer.
|
|
//
|
|
_tcscpy( szShareName, szTempShareName );
|
|
|
|
//
|
|
// Generate a share name until it is unique.
|
|
//
|
|
for( i = 2; i < 1000; i++ ){
|
|
|
|
//
|
|
// If unique name has been found.
|
|
//
|
|
if( bIsValidShareNameForThisPrinter( szShareName,
|
|
strBaseShareName ) ){
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Build formated share name.
|
|
//
|
|
wsprintf( szShareName, TEXT( "%s.%d" ), szTempShareName, i );
|
|
|
|
}
|
|
|
|
//
|
|
// Copy back the share name.
|
|
//
|
|
bStatus = strShareName.bUpdate( szShareName );
|
|
|
|
return bStatus;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
iIsValidDosShare(
|
|
|
|
Routine Description:
|
|
|
|
Indicates the spcified share name is valid.
|
|
|
|
Arguments:
|
|
|
|
Point to share name to check.
|
|
|
|
Return Value:
|
|
|
|
Status indicates the validity of the share name.
|
|
kSuccess - share name is valid.
|
|
kInvalidLength - share name is too long,
|
|
kInvalidChar - share name has invalid characters.
|
|
kInvalidDosFormat - share name does not conform to dos file name.
|
|
|
|
--*/
|
|
INT
|
|
TPrtShare::
|
|
iIsValidDosShare(
|
|
IN LPCTSTR pszShareName
|
|
) const
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::iIsValidDosShare\n" ) );
|
|
|
|
//
|
|
// Ensure we are in a valid state.
|
|
//
|
|
SPLASSERT( bValid() );
|
|
|
|
INT iStatus = kInvalidLength;
|
|
INT iExtLen = 0;
|
|
INT iExtInc = 0;
|
|
BOOL bDotFound = FALSE;
|
|
|
|
//
|
|
// Check the share name pointer.
|
|
//
|
|
if( pszShareName ){
|
|
|
|
//
|
|
// Scan for any illegal characters.
|
|
//
|
|
iStatus = kSuccess;
|
|
for( UINT i = 0; *pszShareName; pszShareName++, i++, iExtLen += iExtInc ){
|
|
|
|
//
|
|
// If an illegal character found.
|
|
//
|
|
if( _tcschr( _gszIllegalDosChars, *pszShareName ) ){
|
|
|
|
iStatus = kInvalidChar;
|
|
break;
|
|
|
|
//
|
|
// Check for the dot.
|
|
//
|
|
} else if( *pszShareName == TEXT( '.' ) ){
|
|
|
|
//
|
|
// We exclude leading dots
|
|
//
|
|
if( i == 0 ){
|
|
iStatus = kInvalidDosFormat;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If a second dot found, indicate failure.
|
|
//
|
|
if( bDotFound ){
|
|
iStatus = kInvalidDosFormat;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Indicate dot found.
|
|
// Set extension count.
|
|
//
|
|
bDotFound = TRUE;
|
|
iExtInc = 1;
|
|
|
|
//
|
|
// Check if the extenstion length is greater than three.
|
|
//
|
|
} else if( iExtLen > 3 ) {
|
|
|
|
iStatus = kInvalidDosFormat;
|
|
break;
|
|
|
|
//
|
|
// Check the share name length
|
|
//
|
|
} else if( i >= kPrinterDosShareNameMax ){
|
|
|
|
iStatus = kInvalidLength;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return iStatus;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
iIsValidNtShare(
|
|
|
|
Routine Description:
|
|
|
|
Indicates the spcified share name is valid.
|
|
|
|
Arguments:
|
|
|
|
Point to share name to check.
|
|
|
|
Return Value:
|
|
|
|
Status indicates the validity of the share name.
|
|
kSuccess - share name is valid.
|
|
kInvalidLength - share name is too long,
|
|
kInvalidChar - share name has invalid characters.
|
|
|
|
--*/
|
|
INT
|
|
TPrtShare::
|
|
iIsValidNtShare(
|
|
IN LPCTSTR pszShareName
|
|
) const
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::iIsValidNtShare\n" ) );
|
|
|
|
//
|
|
// Ensure we are in a valid state.
|
|
//
|
|
SPLASSERT( bValid() );
|
|
|
|
INT iStatus = kInvalidLength;
|
|
|
|
//
|
|
// Check the share name pointer.
|
|
//
|
|
if( pszShareName ){
|
|
|
|
//
|
|
// Scan for any illegal characters.
|
|
//
|
|
iStatus = kSuccess;
|
|
for( UINT i = 0 ; *pszShareName; pszShareName++, i++ ){
|
|
|
|
//
|
|
// If an illegal character found.
|
|
//
|
|
if( _tcschr( _gszIllegalNtChars, *pszShareName ) ){
|
|
|
|
iStatus = kInvalidChar;
|
|
break;
|
|
|
|
//
|
|
// If the share name is too long.
|
|
//
|
|
} else if( i >= kPrinterShareNameBufMax ){
|
|
|
|
iStatus = kInvalidLength;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return iStatus;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bNetworkInstalled.
|
|
|
|
Routine Description:
|
|
|
|
Checks if the network has been installed and functional.
|
|
|
|
Arguments:
|
|
|
|
Nothing.
|
|
|
|
Return Value:
|
|
|
|
TRUE network is installed, FALSE if network is not installed.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
TPrtShare::
|
|
bNetworkInstalled(
|
|
VOID
|
|
)
|
|
{
|
|
BOOL bNetwork = FALSE;
|
|
|
|
TPersist Persist( gszNetworkProvider, TPersist::kOpen|TPersist::kRead, HKEY_LOCAL_MACHINE );
|
|
|
|
if( VALID_OBJ( Persist ) )
|
|
{
|
|
TStatusB bStatus;
|
|
TString strProvider;
|
|
bStatus DBGCHK = Persist.bRead( gszProviderOrder, strProvider );
|
|
|
|
DBGMSG( DBG_TRACE, ("Network Provider order " TSTR "\n", (LPCTSTR)strProvider ) );
|
|
|
|
if( bStatus && strProvider.uLen() > 1 )
|
|
{
|
|
bNetwork = TRUE;
|
|
}
|
|
}
|
|
return bNetwork;
|
|
}
|
|
|
|
#if DBG
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
vPrint
|
|
|
|
Routine Description:
|
|
|
|
Displays the net resource structure.
|
|
|
|
Arguments:
|
|
|
|
Nothing.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
VOID
|
|
TPrtShare::
|
|
vPrint(
|
|
VOID
|
|
) const
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::vPrint\n" ) );
|
|
|
|
PSHARE_INFO_0 pShare = (PSHARE_INFO_0)_pNetResBuf;
|
|
|
|
for( UINT i = 0; i < _dwNetResCount; i++ ){
|
|
|
|
DBGMSG( DBG_TRACE, ( "Share name %ws\n", pShare[i].shi0_netname ) );
|
|
|
|
}
|
|
|
|
_PrtPrinter.vPrint();
|
|
}
|
|
|
|
#endif
|
|
|
|
/********************************************************************
|
|
|
|
Private member functions.
|
|
|
|
********************************************************************/
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bIsShareNameUsed
|
|
|
|
Routine Description:
|
|
|
|
Checks if the specified share name is in use.
|
|
|
|
Arguments:
|
|
|
|
pszShareName - share name to check.
|
|
|
|
Return Value:
|
|
|
|
TRUE the specified share name is used.
|
|
FALSE share name is not currently used.
|
|
|
|
--*/
|
|
BOOL
|
|
TPrtShare::
|
|
bIsShareNameUsedW(
|
|
IN PCWSTR pszShareName
|
|
) const
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::bIsShareNameUsedW\n" ) );
|
|
|
|
PSHARE_INFO_0 pShare = (PSHARE_INFO_0)_pNetResBuf;
|
|
|
|
for( UINT i = 0; i < _dwNetResCount; i++ ){
|
|
|
|
#if 0
|
|
DBGMSG( DBG_TRACE, ( "Comparing share %ws with share %ws\n", pszShareName, pShare[i].shi0_netname ) );
|
|
#endif
|
|
//
|
|
// Compare the share names case is ignored.
|
|
//
|
|
if(!_wcsicmp( pszShareName, (PCWSTR)pShare[i].shi0_netname ) ){
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bIsShareNameUsed
|
|
|
|
Routine Description:
|
|
|
|
Checks if the specified share name is in use.
|
|
|
|
Arguments:
|
|
|
|
pszShareName - share name to check.
|
|
|
|
Return Value:
|
|
|
|
TRUE the specified share name is used.
|
|
FALSE share name is not currently used.
|
|
|
|
--*/
|
|
BOOL
|
|
TPrtShare::
|
|
bIsShareNameUsedA(
|
|
IN PCSTR pszShareName
|
|
) const
|
|
{
|
|
INT iLen;
|
|
BOOL bStatus = FALSE;
|
|
WCHAR szwShareName[kPrinterShareNameBufMax];
|
|
|
|
iLen = lstrlenA( pszShareName );
|
|
|
|
if( iLen ){
|
|
|
|
if( iLen == MultiByteToWideChar( CP_THREAD_ACP,
|
|
0,
|
|
(LPCSTR)pszShareName,
|
|
-1,
|
|
szwShareName,
|
|
COUNTOF( szwShareName ) ) ){
|
|
|
|
bStatus = bIsShareNameUsedW( szwShareName );
|
|
}
|
|
}
|
|
|
|
if( bStatus ){
|
|
DBGMSG( DBG_WARN, ( "Conversion ANSI sharename failed with %d\n", GetLastError() ) );
|
|
}
|
|
|
|
return bStatus;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bGetEnumData
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the shared resources.
|
|
|
|
Arguments:
|
|
|
|
Nothing.
|
|
|
|
Return Value:
|
|
|
|
TRUE the share name resources fetched successfuly.
|
|
FALSE error occured and data is not available.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
TPrtShare::
|
|
bGetEnumData(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::bGetEnumData.\n" ) );
|
|
|
|
BOOL bStatus = TRUE;
|
|
LPCTSTR pszServerName = NULL;
|
|
TString strMachineName;
|
|
|
|
//
|
|
// If the server name is empty then use the local machine name.
|
|
//
|
|
if( _strServerName.bEmpty() && bGetMachineName( strMachineName ) ){
|
|
pszServerName = (LPTSTR)(LPCTSTR)strMachineName;
|
|
} else {
|
|
pszServerName = (LPTSTR)(LPCTSTR)_strServerName;
|
|
}
|
|
|
|
DBGMSG( DBG_TRACE, ( "Enumerating shares for " TSTR "\n", DBGSTR( pszServerName ) ) );
|
|
|
|
//
|
|
// We sould never get here with a null function pointer.
|
|
//
|
|
SPLASSERT( _pfNetShareEnum );
|
|
|
|
//
|
|
// Enumerate all the shares.
|
|
//
|
|
DWORD dwEntriesRead = 0;
|
|
DWORD dwTotalEntries = 0;
|
|
|
|
DWORD dwError = _pfNetShareEnum(
|
|
(LPTSTR)pszServerName, // Server Name
|
|
0,
|
|
&_pNetResBuf,
|
|
0xffffffff, // no buffer limit; get them all!
|
|
&dwEntriesRead,
|
|
&dwTotalEntries,
|
|
NULL); // no resume handle 'cause we're getting all
|
|
|
|
if( dwError != NERR_Success){
|
|
|
|
//
|
|
// Just in case NetShareEnum munged it
|
|
//
|
|
_pNetResBuf = NULL;
|
|
_dwNetResCount = 0;
|
|
|
|
DBGMSG( DBG_WARN, ( "Error enumerating shares: %x with %d\n", dwError, GetLastError() ) );
|
|
|
|
} else {
|
|
|
|
//
|
|
// Check if we read partial data.
|
|
//
|
|
SPLASSERT( dwEntriesRead == dwTotalEntries );
|
|
|
|
//
|
|
// Set network share resource count.
|
|
//
|
|
_dwNetResCount = dwEntriesRead;
|
|
}
|
|
|
|
return bStatus;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
vDestroy
|
|
|
|
Routine Description:
|
|
|
|
Destroys this class and any allocated resources.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
VOID
|
|
TPrtShare::
|
|
vDestroy(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::vDestroy.\n" ) );
|
|
|
|
if( _pfNetApiBufferFree ){
|
|
_pfNetApiBufferFree( _pNetResBuf );
|
|
}
|
|
_pNetResBuf = NULL;
|
|
_dwNetResCount = 0;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
bLoad
|
|
|
|
Routine Description:
|
|
|
|
Loads the library initializes all procedure addresses
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE library loaded and usable, FALSE if error occurred.
|
|
|
|
--*/
|
|
BOOL
|
|
TPrtShare::
|
|
bLoad(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::bLoad.\n" ) );
|
|
|
|
BOOL bStatus = FALSE;
|
|
|
|
//
|
|
// If the library is not loaded then load it.
|
|
//
|
|
if( !_pLibrary ){
|
|
|
|
//
|
|
// Load the library.
|
|
//
|
|
_pLibrary = new TLibrary( TEXT( NETAPI32_LIB ) );
|
|
|
|
//
|
|
// If library is load is in a constant state.
|
|
//
|
|
if( VALID_PTR( _pLibrary ) ){
|
|
|
|
_pfNetShareEnum = (PF_NETSHAREENUM) _pLibrary->pfnGetProc( NETSHAREENUM );
|
|
_pfNetApiBufferFree = (PF_NETAPIBUFFERFREE) _pLibrary->pfnGetProc( NETAPIBUFFERFREE );
|
|
|
|
//
|
|
// Ensure all the procedure address were initialized.
|
|
//
|
|
if( _pfNetShareEnum &&
|
|
_pfNetApiBufferFree ){
|
|
|
|
bStatus = TRUE;
|
|
} else {
|
|
DBGMSG( DBG_WARN, ( "TPrtShare::Failed fetching proc address.\n" ) );
|
|
}
|
|
}
|
|
|
|
//
|
|
// If something failed return to a consistent state.
|
|
//
|
|
if( !bStatus ){
|
|
vUnload();
|
|
}
|
|
|
|
//
|
|
// Return true the library is already loaded.
|
|
//
|
|
} else {
|
|
bStatus = TRUE;
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
/*++
|
|
|
|
vUnload
|
|
|
|
Routine Description:
|
|
|
|
Unloads the library and release any procedure address
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
VOID
|
|
TPrtShare::
|
|
vUnload(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtShare::vUnload.\n" ) );
|
|
|
|
delete _pLibrary;
|
|
_pLibrary = NULL;
|
|
_pfNetShareEnum = NULL;
|
|
_pfNetApiBufferFree = NULL;
|
|
}
|
|
|
|
/********************************************************************
|
|
|
|
Printer and Shares exist in the same name space. To check for
|
|
a valid printer share name we must look at all the existing
|
|
printers.
|
|
|
|
********************************************************************/
|
|
|
|
/*++
|
|
|
|
TPrtPrinter
|
|
|
|
Routine Description:
|
|
|
|
Shared Printer constructor.
|
|
|
|
Arguments:
|
|
|
|
Pointer to server name to check.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
TPrtPrinter::
|
|
TPrtPrinter(
|
|
IN LPCTSTR pszServerName
|
|
) : _bValid( FALSE ),
|
|
_pPrinterInfo2( NULL ),
|
|
_cPrinterInfo2( 0 )
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtPrinter::ctor.\n" ) );
|
|
TStatusB bStatus;
|
|
|
|
//
|
|
// Update the server name and gather the
|
|
// printer enumeration data.
|
|
//
|
|
bStatus DBGCHK = _strServerName.bUpdate( pszServerName ) &&
|
|
bGetEnumData();
|
|
//
|
|
// Set valid class indication.
|
|
//
|
|
_bValid = bStatus;
|
|
}
|
|
|
|
/*++
|
|
|
|
TPrtPrinter
|
|
|
|
Routine Description:
|
|
|
|
Shared Printer destructor.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
TPrtPrinter::
|
|
~TPrtPrinter(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtPrinter::dtor.\n" ) );
|
|
FreeMem( _pPrinterInfo2 );
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bValid
|
|
|
|
Routine Description:
|
|
|
|
Indicates if the object is in a valid state.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE object is valid, FALSE object is not valid.
|
|
|
|
--*/
|
|
BOOL
|
|
TPrtPrinter::
|
|
bValid(
|
|
VOID
|
|
) const
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtPrinter::bValid.\n" ) );
|
|
return _bValid;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bRefresh
|
|
|
|
Routine Description:
|
|
|
|
Updates the printer enumeration with the system.
|
|
|
|
Arguments:
|
|
|
|
Nothing.
|
|
|
|
Return Value:
|
|
|
|
TRUE updated was successful, FALSE if error occurred.
|
|
|
|
--*/
|
|
BOOL
|
|
TPrtPrinter::
|
|
bRefresh(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtPrinter::bRefresh.\n" ) );
|
|
|
|
//
|
|
// Ensure we are in a valid state.
|
|
//
|
|
SPLASSERT( bValid() );
|
|
|
|
//
|
|
// Refresh the printer enumeration data.
|
|
//
|
|
_bValid = bGetEnumData();
|
|
return _bValid;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bIsValidShareNameForThisPrinter
|
|
|
|
Routine Description:
|
|
|
|
Indicates if the specified share name is valid for the specified
|
|
share name provided as the first argument. If the printer name is
|
|
not provided then this routine returns an indication if the name is
|
|
unique.
|
|
|
|
Arguments:
|
|
|
|
pszShareName - Printer share name to check.
|
|
pszPrinterName - Printer name to check against.
|
|
|
|
Return Value:
|
|
|
|
TRUE if name is a usable sharen name for this printer.
|
|
FALSE if error occurred.
|
|
|
|
--*/
|
|
BOOL
|
|
TPrtPrinter::
|
|
bIsValidShareNameForThisPrinter(
|
|
IN LPCTSTR pszShareName,
|
|
IN LPCTSTR pszPrinterName
|
|
) const
|
|
{
|
|
|
|
DBGMSG( DBG_TRACE, ( "TPrtPrinter::bIsValidShareNameForThisPrinter.\n" ) );
|
|
|
|
BOOL bStatus = TRUE;
|
|
|
|
//
|
|
// Ensure we are in a valid state.
|
|
//
|
|
SPLASSERT( bValid() );
|
|
SPLASSERT( pszShareName );
|
|
|
|
//
|
|
// Traverse all the enumerated shares.
|
|
//
|
|
for( UINT i = 0; i < _cPrinterInfo2; i++ ){
|
|
|
|
//
|
|
// If nobody has access to this printer then spooler doesn't really share
|
|
// the printer out even if it has the shared bit up and eating up a name in
|
|
// the namespace, so we need to do an additionbal check here to make sure
|
|
// the proposed share name doesn't collide with an existing printer share name.
|
|
//
|
|
if( _pPrinterInfo2[i].pShareName && !_tcsicmp( pszShareName, _pPrinterInfo2[i].pShareName ) ){
|
|
bStatus = FALSE;
|
|
break;
|
|
}
|
|
|
|
LPCTSTR pszServer;
|
|
LPCTSTR pszPrinter;
|
|
TCHAR szScratch[kPrinterBufMax];
|
|
|
|
//
|
|
// Split the printer name into its components.
|
|
//
|
|
vPrinterSplitFullName( szScratch,
|
|
_pPrinterInfo2[i].pPrinterName,
|
|
&pszServer,
|
|
&pszPrinter );
|
|
//
|
|
// If the share name is a fully qualified name then use the fully
|
|
// qualified printer name.
|
|
//
|
|
if( pszShareName[0] == TEXT( '\\' ) &&
|
|
pszShareName[1] == TEXT( '\\' ) ){
|
|
|
|
pszPrinter = _pPrinterInfo2[i].pPrinterName;
|
|
}
|
|
#if 0
|
|
DBGMSG( DBG_TRACE, ( "Comparing share " TSTR " with printer " TSTR "\n", pszShareName, pszPrinter ) );
|
|
#endif
|
|
//
|
|
// Compare the share name to the printer name.
|
|
//
|
|
if( !_tcsicmp( pszShareName, pszPrinter ) ){
|
|
bStatus = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the share name is not unique check if happens to be the
|
|
// same as the printer name. It's ok for the printer name
|
|
// and the share name to be the same. The spooler allows this.
|
|
//
|
|
if( !bStatus && pszPrinterName ){
|
|
|
|
LPCTSTR pszServer;
|
|
LPCTSTR pszPrinter;
|
|
TCHAR szScratch[kPrinterBufMax];
|
|
|
|
//
|
|
// Split the printer name into its components.
|
|
//
|
|
vPrinterSplitFullName( szScratch,
|
|
pszPrinterName,
|
|
&pszServer,
|
|
&pszPrinter );
|
|
//
|
|
// If the share name is a fully qualified name then use the fully
|
|
// qualified printer name.
|
|
//
|
|
if( pszShareName[0] == TEXT( '\\' ) &&
|
|
pszShareName[1] == TEXT( '\\' ) ){
|
|
|
|
pszPrinter = pszPrinterName;
|
|
}
|
|
|
|
DBGMSG( DBG_TRACE, ( "Comparing like share " TSTR " with printer " TSTR "\n",
|
|
pszShareName, DBGSTR( pszPrinter ) ) );
|
|
|
|
//
|
|
// Check if the printer name matches the share name
|
|
//
|
|
if( !_tcsicmp( pszShareName, pszPrinter ) ){
|
|
DBGMSG( DBG_TRACE, ("The printer name matches the share name.\n") );
|
|
bStatus = TRUE;
|
|
}
|
|
}
|
|
|
|
return bStatus;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
bGetEnumData
|
|
|
|
Routine Description:
|
|
|
|
Fetches the printer enumeration data.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE enumeration data fetched, FALSE if error occurred.
|
|
|
|
--*/
|
|
BOOL
|
|
TPrtPrinter::
|
|
bGetEnumData(
|
|
VOID
|
|
)
|
|
{
|
|
|
|
DBGMSG( DBG_TRACE, ( "TPrtPrinter::bGetEnumData.\n" ) );
|
|
|
|
//
|
|
// Release any previously allocated structure.
|
|
//
|
|
FreeMem( _pPrinterInfo2 );
|
|
|
|
//
|
|
// Reset the variables.
|
|
//
|
|
_pPrinterInfo2 = NULL;
|
|
_cPrinterInfo2 = 0;
|
|
DWORD cbPrinterInfo2 = 0;
|
|
|
|
//
|
|
// Enumerate the current printers.
|
|
//
|
|
TStatusB bEnumStatus;
|
|
bEnumStatus DBGCHK = VDataRefresh::bEnumPrinters(
|
|
PRINTER_ENUM_NAME,
|
|
(LPTSTR)(LPCTSTR)_strServerName,
|
|
2,
|
|
(PVOID *)&_pPrinterInfo2,
|
|
&cbPrinterInfo2,
|
|
&_cPrinterInfo2 );
|
|
|
|
return bEnumStatus;
|
|
|
|
}
|
|
|
|
|
|
#if DBG
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
vPrint
|
|
|
|
Routine Description:
|
|
|
|
Prints the printer enumeration data.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
VOID
|
|
TPrtPrinter::
|
|
vPrint(
|
|
VOID
|
|
) const
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TPrtPrinter::vPrint.\n" ) );
|
|
|
|
SPLASSERT( bValid() );
|
|
|
|
DBGMSG( DBG_TRACE, ( "_pPrinterInfo2 %x.\n", _pPrinterInfo2 ) );
|
|
DBGMSG( DBG_TRACE, ( "_cPrinterInfo2 %d\n", _cPrinterInfo2 ) );
|
|
|
|
for( UINT i = 0; i < _cPrinterInfo2; i++ ){
|
|
DBGMSG( DBG_TRACE, ( "PrinterInfo2.pPrinterName " TSTR "\n", _pPrinterInfo2[i].pPrinterName ) );
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|