1300 lines
33 KiB
C
1300 lines
33 KiB
C
/********************************************************************/
|
||
/** Copyright(c) 1989 Microsoft Corporation. **/
|
||
/********************************************************************/
|
||
|
||
//***
|
||
//
|
||
// Filename: init.c
|
||
//
|
||
// Description: This module contains code to intialize and de-initialize
|
||
// the AFP Server, RPC server, the security object and
|
||
// other global vriables.
|
||
//
|
||
// History:
|
||
// May 11,1992. NarenG Created original version.
|
||
//
|
||
//
|
||
#include "afpsvcp.h"
|
||
|
||
// Prototypes of functions used only within this module.
|
||
//
|
||
DWORD
|
||
AfpInitServerVolumes(
|
||
VOID
|
||
);
|
||
|
||
DWORD
|
||
AfpInitServerParameters(
|
||
VOID
|
||
);
|
||
|
||
DWORD
|
||
AfpInitServerIcons(
|
||
VOID
|
||
);
|
||
|
||
DWORD
|
||
AfpInitETCMaps(
|
||
VOID
|
||
);
|
||
|
||
DWORD
|
||
AfpInitRPC(
|
||
VOID
|
||
);
|
||
|
||
DWORD
|
||
AfpInitServerDomainOffsets(
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
AfpTerminateRPC(
|
||
VOID
|
||
);
|
||
|
||
|
||
VOID
|
||
AfpIniLsa(
|
||
VOID
|
||
);
|
||
|
||
|
||
BOOL
|
||
IsAfpGuestAccountEnabled(
|
||
VOID
|
||
);
|
||
|
||
//**
|
||
//
|
||
// Call: AfpInitialize
|
||
//
|
||
// Returns: NO_ERROR
|
||
//
|
||
// Description: Will do all server intialization.
|
||
// 1) Create the security object.
|
||
// 2) Set up the server for RPC.
|
||
// 3) Open all the registry keys that store AFP data.
|
||
// 4) Get the handle to the FSD.
|
||
// 5) Get default server parameters
|
||
// 6) It will initialize the AFP Server with volume, ETC, icon
|
||
// and server parameter information.
|
||
// 7) IOCTL the FSD to start the server.
|
||
//
|
||
DWORD
|
||
AfpInitialize(
|
||
VOID
|
||
)
|
||
{
|
||
AFP_REQUEST_PACKET AfpRequestPkt;
|
||
DWORD dwRetCode;
|
||
BOOL fFirstThread;
|
||
DWORD nThreads;
|
||
|
||
|
||
|
||
|
||
// Load strings from resource file
|
||
//
|
||
if (( !LoadString( GetModuleHandle( NULL ), 1, AfpGlobals.wchUnknown, 100 ))
|
||
||
|
||
( !LoadString( GetModuleHandle( NULL ), 2, AfpGlobals.wchInvalid, 100 ))
|
||
||
|
||
( !LoadString( GetModuleHandle( NULL ), 3, AfpGlobals.wchDeleted, 100 ))
|
||
||
|
||
( !LoadString( GetModuleHandle( NULL ), 4, AfpGlobals.wchDefTCComment,
|
||
AFP_ETC_COMMENT_LEN+1 )))
|
||
AfpLogEvent( AFPLOG_CANT_LOAD_RESOURCE, 0, NULL,
|
||
GetLastError(), EVENTLOG_WARNING_TYPE );
|
||
|
||
//
|
||
// Create the security object
|
||
//
|
||
if ( dwRetCode = AfpSecObjCreate() ) {
|
||
AfpLogEvent( AFPLOG_CANT_CREATE_SECOBJ, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE );
|
||
return( dwRetCode );
|
||
}
|
||
|
||
// Initialize the server to accept RPC calls
|
||
//
|
||
if ( dwRetCode = AfpInitRPC() ) {
|
||
AfpLogEvent( AFPLOG_CANT_INIT_RPC, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE );
|
||
return( dwRetCode );
|
||
}
|
||
|
||
AfpGlobals.dwServerState |= AFPSTATE_RPC_STARTED;
|
||
|
||
// Open the registry keys where AFP Server information is stored
|
||
//
|
||
if ( dwRetCode = AfpRegOpen() ) {
|
||
AfpLogEvent( AFPLOG_CANT_OPEN_REGKEY, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE );
|
||
return( dwRetCode );
|
||
}
|
||
|
||
AfpGlobals.ServiceStatus.dwCheckPoint++;
|
||
AfpAnnounceServiceStatus();
|
||
|
||
// Open and load the AFP Server FSD and obtain a handle to it
|
||
//
|
||
if ( dwRetCode = AfpFSDLoad() ) {
|
||
AfpLogEvent( AFPLOG_CANT_LOAD_FSD, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE );
|
||
return( dwRetCode );
|
||
}
|
||
|
||
AfpGlobals.dwServerState |= AFPSTATE_FSD_LOADED;
|
||
|
||
if ( dwRetCode = AfpFSDOpen( &(AfpGlobals.hFSD) ) ) {
|
||
AfpLogEvent( AFPLOG_CANT_OPEN_FSD, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE );
|
||
return( dwRetCode );
|
||
}
|
||
|
||
// Query the product type of server.
|
||
//
|
||
AfpGlobals.pSidNone = NULL;
|
||
RtlGetNtProductType ( &(AfpGlobals.NtProductType) );
|
||
|
||
// Create the event object for the server helper thread.
|
||
//
|
||
if ( (AfpGlobals.heventSrvrHlprThread =
|
||
CreateEvent( NULL, FALSE, FALSE, NULL ) ) == NULL){
|
||
AfpLogEvent( AFPLOG_CANT_START, 0, NULL, GetLastError(),
|
||
EVENTLOG_ERROR_TYPE );
|
||
return( GetLastError() );
|
||
}
|
||
|
||
// Create the event object for the server helper thread termination.
|
||
//
|
||
if ( (AfpGlobals.heventSrvrHlprThreadTerminate =
|
||
CreateEvent( NULL, FALSE, FALSE, NULL ) ) == NULL){
|
||
AfpLogEvent( AFPLOG_CANT_START, 0, NULL, GetLastError(),
|
||
EVENTLOG_ERROR_TYPE );
|
||
return( GetLastError() );
|
||
}
|
||
|
||
// Create the event object for the "special case" unblocking of server helper thread
|
||
//
|
||
if ( (AfpGlobals.heventSrvrHlprSpecial =
|
||
CreateEvent( NULL, FALSE, FALSE, NULL ) ) == NULL){
|
||
AfpLogEvent( AFPLOG_CANT_START, 0, NULL, GetLastError(),
|
||
EVENTLOG_ERROR_TYPE );
|
||
return( GetLastError() );
|
||
}
|
||
|
||
// Create server helper threads. The parameter indicates if this is the
|
||
// first thread that is being created.
|
||
//
|
||
fFirstThread = TRUE;
|
||
nThreads = 0;
|
||
|
||
do {
|
||
|
||
if ( ( dwRetCode = AfpCreateServerHelperThread( fFirstThread ) )
|
||
!= NO_ERROR ) {
|
||
AfpLogEvent( AFPLOG_CANT_CREATE_SRVRHLPR, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE );
|
||
|
||
if ( fFirstThread ) {
|
||
AfpLogEvent( AFPLOG_CANT_START, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE );
|
||
return( dwRetCode );
|
||
}
|
||
}
|
||
|
||
// Wait for the server helper thread to indicate if it successfully
|
||
// initialized itself.
|
||
//
|
||
WaitForSingleObject( AfpGlobals.heventSrvrHlprThread, INFINITE );
|
||
|
||
if ( AfpGlobals.dwSrvrHlprCode != NO_ERROR ) {
|
||
AfpLogEvent(AFPLOG_CANT_INIT_SRVRHLPR,
|
||
0,
|
||
NULL,
|
||
AfpGlobals.dwSrvrHlprCode,
|
||
EVENTLOG_ERROR_TYPE );
|
||
|
||
if ( fFirstThread )
|
||
{
|
||
AFP_PRINT( ( "SFMSVC: can't start macfile, first thread failed %ld\n",
|
||
AfpGlobals.dwSrvrHlprCode));
|
||
AfpLogEvent( AFPLOG_CANT_START, 0, NULL, dwRetCode,
|
||
EVENTLOG_ERROR_TYPE );
|
||
return( AfpGlobals.dwSrvrHlprCode );
|
||
}
|
||
}
|
||
|
||
fFirstThread = FALSE;
|
||
|
||
}while( ++nThreads < NUM_SECURITY_UTILITY_THREADS );
|
||
|
||
// Read in server parameters from the registry and intialize the
|
||
// server with them.
|
||
//
|
||
if ( dwRetCode = AfpInitServerParameters())
|
||
{
|
||
AFP_PRINT( ( "SFMSVC: AfpInitServerParameters failed %ld\n",dwRetCode));
|
||
AfpLogEvent( AFPLOG_CANT_INIT_SRVR_PARAMS, 0, NULL, dwRetCode,EVENTLOG_ERROR_TYPE );
|
||
return( dwRetCode );
|
||
}
|
||
|
||
|
||
AfpGlobals.ServiceStatus.dwCheckPoint++;
|
||
AfpAnnounceServiceStatus();
|
||
|
||
|
||
// Read in the ETC Mappings and initialize the AFP Server with them
|
||
// Also create a private cache of this information.
|
||
//
|
||
if ( dwRetCode = AfpInitETCMaps() )
|
||
{
|
||
AFP_PRINT( ( "SFMSVC: AfpInitETCMaps failed %ld\n",dwRetCode));
|
||
AfpLogEvent( AFPLOG_CANT_INIT_ETCINFO, 0, NULL, dwRetCode,EVENTLOG_ERROR_TYPE );
|
||
return( dwRetCode );
|
||
}
|
||
|
||
|
||
if ( dwRetCode = AfpInitServerIcons() )
|
||
{
|
||
AFP_PRINT( ( "SFMSVC: AfpInitServerIcons failed %ld\n",dwRetCode));
|
||
AfpLogEvent( AFPLOG_CANT_INIT_ICONS, 0, NULL, dwRetCode ,EVENTLOG_ERROR_TYPE );
|
||
return( dwRetCode );
|
||
}
|
||
|
||
|
||
AfpGlobals.ServiceStatus.dwCheckPoint++;
|
||
AfpAnnounceServiceStatus();
|
||
|
||
// Read in any volumes and initialize the server with them
|
||
//
|
||
if ( dwRetCode = AfpInitServerVolumes() )
|
||
{
|
||
AFP_PRINT( ( "SFMSVC: AfpInitServerVolumes failed %ld\n",dwRetCode));
|
||
AfpLogEvent( AFPLOG_CANT_INIT_VOLUMES, 0, NULL, dwRetCode,EVENTLOG_ERROR_TYPE );
|
||
return( dwRetCode );
|
||
}
|
||
|
||
|
||
// Create mutex objects around volume operations to avoid simultaneous
|
||
// writing in the registry.
|
||
//
|
||
if ( (AfpGlobals.hmutexVolume = CreateMutex( NULL, FALSE, NULL ) ) == NULL)
|
||
{
|
||
AFP_PRINT( ( "SFMSVC: CreateMutex failed in AfpInitialize\n"));
|
||
AfpLogEvent( AFPLOG_CANT_START, 0, NULL, dwRetCode,EVENTLOG_ERROR_TYPE );
|
||
return( GetLastError() );
|
||
}
|
||
|
||
// Create mutex objects around ETCMap operations.
|
||
//
|
||
if ( (AfpGlobals.hmutexETCMap = CreateMutex( NULL, FALSE, NULL ) ) == NULL)
|
||
{
|
||
AFP_PRINT( ( "SFMSVC: CreateMutex 2 failed in AfpInitialize\n"));
|
||
AfpLogEvent( AFPLOG_CANT_START, 0, NULL, GetLastError(),EVENTLOG_ERROR_TYPE );
|
||
return( GetLastError() );
|
||
}
|
||
|
||
// OK we are all set to go so lets tell the AFP Server to start
|
||
//
|
||
AfpRequestPkt.dwRequestCode = OP_SERVICE_START;
|
||
AfpRequestPkt.dwApiType = AFP_API_TYPE_COMMAND;
|
||
|
||
AFP_PRINT( ( "SFMSVC: ioctling sfmsrv to start\n"));
|
||
|
||
if ( dwRetCode = AfpServerIOCtrl( &AfpRequestPkt ) )
|
||
{
|
||
AFP_PRINT( ( "SFMSVC: AfpServerIOCtrl to start sfmsrv failed %ld\n",dwRetCode));
|
||
AfpLogEvent( AFPLOG_CANT_START,0,NULL,dwRetCode,EVENTLOG_ERROR_TYPE);
|
||
return( dwRetCode );
|
||
}
|
||
|
||
|
||
AfpIniLsa();
|
||
|
||
return( NO_ERROR );
|
||
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpTerminate
|
||
//
|
||
// Returns: none.
|
||
//
|
||
// Description: This procedure will shut down the server, and do any
|
||
// clean up if required.
|
||
//
|
||
VOID
|
||
AfpTerminate(
|
||
VOID
|
||
)
|
||
{
|
||
AFP_REQUEST_PACKET AfpRequestPkt;
|
||
DWORD dwRetCode;
|
||
|
||
|
||
// If the FSD was loaded
|
||
//
|
||
if ( AfpGlobals.dwServerState & AFPSTATE_FSD_LOADED ) {
|
||
|
||
// Tell the server to shut down
|
||
//
|
||
AfpRequestPkt.dwRequestCode = OP_SERVICE_STOP;
|
||
AfpRequestPkt.dwApiType = AFP_API_TYPE_COMMAND;
|
||
|
||
if ( dwRetCode = AfpServerIOCtrl( &AfpRequestPkt ) )
|
||
AfpLogEvent( AFPLOG_CANT_STOP, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE );
|
||
}
|
||
|
||
AfpGlobals.ServiceStatus.dwCheckPoint++;
|
||
AfpAnnounceServiceStatus();
|
||
|
||
// Try to close the FSD
|
||
//
|
||
if ( AfpGlobals.hFSD != NULL )
|
||
{
|
||
if ( dwRetCode = AfpFSDClose( AfpGlobals.hFSD ) )
|
||
{
|
||
AfpLogEvent( AFPLOG_CANT_STOP, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE );
|
||
}
|
||
|
||
// Try to unload the FSD
|
||
//
|
||
if ( dwRetCode = AfpFSDUnload() )
|
||
{
|
||
AfpLogEvent( AFPLOG_CANT_STOP, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE);
|
||
}
|
||
}
|
||
|
||
AfpGlobals.ServiceStatus.dwCheckPoint++;
|
||
AfpAnnounceServiceStatus();
|
||
|
||
// Delete the security object.
|
||
//
|
||
AfpSecObjDelete();
|
||
|
||
// De-initialize the RPC server
|
||
//
|
||
AfpTerminateRPC();
|
||
|
||
// Close the registry keys.
|
||
//
|
||
AfpRegClose();
|
||
|
||
// Free the pSidNone if we allocated it for standalone
|
||
//
|
||
if (AfpGlobals.pSidNone != NULL)
|
||
{
|
||
LocalFree(AfpGlobals.pSidNone);
|
||
AfpGlobals.pSidNone = NULL;
|
||
}
|
||
|
||
if (SfmLsaHandle != NULL)
|
||
{
|
||
LsaDeregisterLogonProcess( SfmLsaHandle );
|
||
SfmLsaHandle = NULL;
|
||
}
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpInitServerParameters
|
||
//
|
||
// Returns: NO_ERROR
|
||
// non-zero return codes from the IOCTL or other system calls.
|
||
//
|
||
// Description: This procedure will set default values for parameters. It
|
||
// will then call AfpRegServerGetInfo to override these defaults
|
||
// with any parameters that may be stored in the registry. It
|
||
// will then initialize the FSD with these parameters.
|
||
//
|
||
DWORD
|
||
AfpInitServerParameters(
|
||
VOID
|
||
)
|
||
{
|
||
AFP_SERVER_INFO AfpServerInfo;
|
||
DWORD cbServerNameSize;
|
||
DWORD dwRetCode;
|
||
AFP_REQUEST_PACKET AfpRequestPkt;
|
||
|
||
|
||
// Initialize all the server parameters with defaults
|
||
//
|
||
cbServerNameSize = sizeof( AfpGlobals.wchServerName );
|
||
if ( !GetComputerName( AfpGlobals.wchServerName, &cbServerNameSize ) )
|
||
return( GetLastError() );
|
||
|
||
AfpGlobals.dwMaxSessions = AFP_DEF_MAXSESSIONS;
|
||
AfpGlobals.dwServerOptions = AFP_DEF_SRVOPTIONS;
|
||
AfpGlobals.wchLoginMsg[0] = TEXT('\0');
|
||
AfpGlobals.dwMaxPagedMem = AFP_DEF_MAXPAGEDMEM;
|
||
AfpGlobals.dwMaxNonPagedMem = AFP_DEF_MAXNONPAGEDMEM;
|
||
|
||
// Read in any server parameters in the registry. Registry parameters
|
||
// will override the defaults set above.
|
||
//
|
||
if ( dwRetCode = AfpRegServerGetInfo() )
|
||
return( dwRetCode );
|
||
|
||
if (IsAfpGuestAccountEnabled())
|
||
{
|
||
AfpGlobals.dwServerOptions |= AFP_SRVROPT_GUESTLOGONALLOWED;
|
||
}
|
||
else
|
||
{
|
||
AfpGlobals.dwServerOptions &= ~AFP_SRVROPT_GUESTLOGONALLOWED;
|
||
}
|
||
|
||
// Get the path to the codepage
|
||
//
|
||
if ( dwRetCode = AfpRegServerGetCodePagePath() )
|
||
return( dwRetCode );
|
||
|
||
// Set up server info structure
|
||
//
|
||
AfpServerInfo.afpsrv_name = AfpGlobals.wchServerName;
|
||
AfpServerInfo.afpsrv_max_sessions = AfpGlobals.dwMaxSessions;
|
||
AfpServerInfo.afpsrv_options = AfpGlobals.dwServerOptions;
|
||
if (AfpGlobals.NtProductType != NtProductLanManNt)
|
||
{
|
||
AfpServerInfo.afpsrv_options |= AFP_SRVROPT_STANDALONE;
|
||
}
|
||
AfpServerInfo.afpsrv_login_msg = AfpGlobals.wchLoginMsg;
|
||
AfpServerInfo.afpsrv_max_paged_mem = AfpGlobals.dwMaxPagedMem;
|
||
AfpServerInfo.afpsrv_max_nonpaged_mem = AfpGlobals.dwMaxNonPagedMem;
|
||
AfpServerInfo.afpsrv_codepage = AfpGlobals.wchCodePagePath;
|
||
|
||
// Make this buffer self-relative.
|
||
//
|
||
if ( dwRetCode = AfpBufMakeFSDRequest(
|
||
(LPBYTE)&AfpServerInfo,
|
||
sizeof(SETINFOREQPKT),
|
||
AFP_SERVER_STRUCT,
|
||
(LPBYTE*)&(AfpRequestPkt.Type.SetInfo.pInputBuf),
|
||
&(AfpRequestPkt.Type.SetInfo.cbInputBufSize)))
|
||
{
|
||
return( dwRetCode );
|
||
}
|
||
|
||
// IOCTL the FSD to set the server parameters
|
||
//
|
||
AfpRequestPkt.dwRequestCode = OP_SERVER_SET_INFO;
|
||
AfpRequestPkt.dwApiType = AFP_API_TYPE_SETINFO;
|
||
AfpRequestPkt.Type.SetInfo.dwParmNum = AFP_SERVER_PARMNUM_ALL;
|
||
|
||
dwRetCode = AfpServerIOCtrl( &AfpRequestPkt );
|
||
|
||
LocalFree( AfpRequestPkt.Type.SetInfo.pInputBuf );
|
||
|
||
return( dwRetCode );
|
||
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpInitServerVolumes
|
||
//
|
||
// Returns: NO_ERROR - success
|
||
// ERROR_NOT_ENOUGH_MEMORY
|
||
// non-zero return codes from registry apis.
|
||
//
|
||
// Description: This procedure will read in a volume at a time from the
|
||
// registry, and then register this volume with the server.
|
||
// This procedure will only return fatal errors that will
|
||
// require that the service to fail initialization. All other
|
||
// error will be logged by this routine. All returns from the
|
||
// the FSD are treated as non-fatal.
|
||
//
|
||
DWORD
|
||
AfpInitServerVolumes(
|
||
VOID
|
||
)
|
||
{
|
||
DWORD dwRetCode;
|
||
LPWSTR lpwsValName, lpwsSrcIconPath, lpwsDstIconPath;
|
||
DWORD dwMaxValNameLen;
|
||
DWORD dwValNameBufSize;
|
||
DWORD dwNumValues;
|
||
DWORD dwMaxValueDataSize;
|
||
DWORD dwIndex;
|
||
DWORD dwType;
|
||
DWORD dwBufSize;
|
||
AFP_REQUEST_PACKET AfpRequestPkt;
|
||
AFP_VOLUME_INFO VolumeInfo;
|
||
LPBYTE lpbMultiSz;
|
||
LPBYTE lpbFSDBuf;
|
||
DWORD dwLength;
|
||
DWORD dwCount;
|
||
WCHAR wchServerIconFile[AFPSERVER_VOLUME_ICON_FILE_SIZE] = AFPSERVER_VOLUME_ICON_FILE;
|
||
BOOLEAN fCopiedIcon;
|
||
DWORD dwLastDstCharIndex;
|
||
|
||
// Find out the size of the largest data value and the largest
|
||
// value name.
|
||
//
|
||
if ( dwRetCode = AfpRegGetKeyInfo( AfpGlobals.hkeyVolumesList,
|
||
&dwMaxValNameLen,
|
||
&dwNumValues,
|
||
&dwMaxValueDataSize
|
||
))
|
||
return( dwRetCode );
|
||
|
||
// If there are no volumes to add then simply return
|
||
//
|
||
if ( dwNumValues == 0 )
|
||
return( NO_ERROR );
|
||
|
||
if (( lpwsValName = (LPWSTR)LocalAlloc( LPTR, dwMaxValNameLen ) ) == NULL )
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
|
||
if ((lpbMultiSz = (LPBYTE)LocalAlloc( LPTR, dwMaxValueDataSize )) == NULL ){
|
||
LocalFree( lpwsValName );
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
}
|
||
|
||
if (( lpwsSrcIconPath = (LPWSTR)LocalAlloc( LPTR, MAX_PATH * sizeof(WCHAR) ) ) == NULL )
|
||
{
|
||
LocalFree( lpwsValName );
|
||
LocalFree( lpbMultiSz );
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
}
|
||
|
||
if (( lpwsDstIconPath = (LPWSTR)LocalAlloc( LPTR, (MAX_PATH +
|
||
AFPSERVER_VOLUME_ICON_FILE_SIZE + 1 +
|
||
(sizeof(AFPSERVER_RESOURCE_STREAM)/sizeof(WCHAR))) *
|
||
sizeof(WCHAR)) ) == NULL )
|
||
{
|
||
LocalFree( lpwsValName );
|
||
LocalFree( lpbMultiSz );
|
||
LocalFree( lpwsSrcIconPath );
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
}
|
||
|
||
// Construct a path to the NTSFM volume custom icon
|
||
//
|
||
*lpwsSrcIconPath = 0;
|
||
if ( GetSystemDirectory( lpwsSrcIconPath, MAX_PATH * sizeof(WCHAR) ))
|
||
{
|
||
wcscat( lpwsSrcIconPath, AFP_DEF_VOLICON_SRCNAME );
|
||
}
|
||
|
||
|
||
for ( dwIndex = 0,
|
||
dwBufSize = dwMaxValueDataSize,
|
||
dwValNameBufSize = dwMaxValNameLen;
|
||
|
||
dwIndex < dwNumValues;
|
||
|
||
dwIndex++,
|
||
dwBufSize = dwMaxValueDataSize,
|
||
dwValNameBufSize = dwMaxValNameLen ) {
|
||
|
||
ZeroMemory( lpbMultiSz, dwBufSize );
|
||
|
||
// Get the volume info from the registry in multi-sz form.
|
||
//
|
||
if ( dwRetCode = RegEnumValue( AfpGlobals.hkeyVolumesList,
|
||
dwIndex,
|
||
lpwsValName,
|
||
&dwValNameBufSize,
|
||
NULL,
|
||
&dwType,
|
||
lpbMultiSz,
|
||
&dwBufSize
|
||
))
|
||
break;
|
||
|
||
// Parse the mult sz and extract info into volume info structure
|
||
//
|
||
if ( dwRetCode = AfpBufParseMultiSz(
|
||
AFP_VOLUME_STRUCT,
|
||
lpbMultiSz,
|
||
(LPBYTE)&VolumeInfo ) ) {
|
||
|
||
// If this volume contained invalid registry information then log
|
||
// it and store the volume name in the list of invalid volumes.
|
||
//
|
||
AfpAddInvalidVolume( lpwsValName, NULL );
|
||
|
||
AfpLogEvent( AFPLOG_INVALID_VOL_REG,1,&lpwsValName,
|
||
dwRetCode, EVENTLOG_WARNING_TYPE );
|
||
dwRetCode = NO_ERROR;
|
||
continue;
|
||
}
|
||
|
||
// Insert the volume name viz. the valuename
|
||
//
|
||
VolumeInfo.afpvol_name = lpwsValName;
|
||
|
||
// Validate the volume info structure
|
||
//
|
||
if ( !IsAfpVolumeInfoValid( AFP_VALIDATE_ALL_FIELDS, &VolumeInfo ) ) {
|
||
|
||
// If this volume contained invalid registry information then log
|
||
// it and store the volume name in the list of invalid volumes.
|
||
//
|
||
AfpAddInvalidVolume( lpwsValName, NULL );
|
||
|
||
AfpLogEvent( AFPLOG_INVALID_VOL_REG,1,&lpwsValName,
|
||
dwRetCode, EVENTLOG_WARNING_TYPE );
|
||
dwRetCode = NO_ERROR;
|
||
continue;
|
||
}
|
||
|
||
// If there is a password then decrypt it
|
||
//
|
||
if ( VolumeInfo.afpvol_password != (LPWSTR)NULL ){
|
||
|
||
dwLength = STRLEN( VolumeInfo.afpvol_password );
|
||
|
||
for ( dwCount = 0; dwCount < dwLength; dwCount++ )
|
||
VolumeInfo.afpvol_password[dwCount] ^= 0xF000;
|
||
}
|
||
|
||
//
|
||
// Construct a path to the destination volume "Icon<0D>" file
|
||
//
|
||
|
||
fCopiedIcon = FALSE;
|
||
|
||
wcscpy( lpwsDstIconPath, VolumeInfo.afpvol_path );
|
||
if (lpwsDstIconPath[wcslen(lpwsDstIconPath) - 1] != TEXT('\\'))
|
||
{
|
||
wcscat( lpwsDstIconPath, TEXT("\\") );
|
||
}
|
||
wcscat( lpwsDstIconPath, wchServerIconFile );
|
||
// Keep track of end of name without the resource fork tacked on
|
||
//
|
||
dwLastDstCharIndex = wcslen(lpwsDstIconPath);
|
||
wcscat( lpwsDstIconPath, AFPSERVER_RESOURCE_STREAM );
|
||
|
||
// Copy the icon file to the root of the volume (do not overwrite)
|
||
//
|
||
if ((fCopiedIcon = (BOOLEAN)CopyFile( lpwsSrcIconPath, lpwsDstIconPath, TRUE )) ||
|
||
(GetLastError() == ERROR_FILE_EXISTS))
|
||
{
|
||
VolumeInfo.afpvol_props_mask |= AFP_VOLUME_HAS_CUSTOM_ICON;
|
||
|
||
// Make sure the file is hidden
|
||
SetFileAttributes( lpwsDstIconPath,
|
||
FILE_ATTRIBUTE_HIDDEN |
|
||
FILE_ATTRIBUTE_ARCHIVE );
|
||
}
|
||
|
||
|
||
// Make this a self relative buffer
|
||
//
|
||
if ( dwRetCode = AfpBufMakeFSDRequest(
|
||
(LPBYTE)&VolumeInfo,
|
||
0,
|
||
AFP_VOLUME_STRUCT,
|
||
&lpbFSDBuf,
|
||
&dwBufSize
|
||
))
|
||
break;
|
||
|
||
// Initialize the FSD with this volume
|
||
//
|
||
AfpRequestPkt.dwRequestCode = OP_VOLUME_ADD;
|
||
AfpRequestPkt.dwApiType = AFP_API_TYPE_ADD;
|
||
AfpRequestPkt.Type.Add.pInputBuf = lpbFSDBuf;
|
||
AfpRequestPkt.Type.Add.cbInputBufSize = dwBufSize;
|
||
|
||
dwRetCode = AfpServerIOCtrl( &AfpRequestPkt );
|
||
|
||
if ( dwRetCode ) {
|
||
|
||
// If this volume could not be added by the FSD then we errorlog
|
||
// this and insert this volume into the list of invalid volumes.
|
||
//
|
||
AfpAddInvalidVolume( lpwsValName, VolumeInfo.afpvol_path );
|
||
|
||
AfpLogEvent( AFPLOG_CANT_ADD_VOL, 1, &lpwsValName,
|
||
dwRetCode, EVENTLOG_WARNING_TYPE );
|
||
dwRetCode = NO_ERROR;
|
||
|
||
// Delete the icon file we just copied if the volume add failed
|
||
//
|
||
if ( fCopiedIcon )
|
||
{
|
||
// Truncate the resource fork name so we delete the whole file
|
||
lpwsDstIconPath[dwLastDstCharIndex] = 0;
|
||
DeleteFile( lpwsDstIconPath );
|
||
}
|
||
|
||
}
|
||
|
||
LocalFree( lpbFSDBuf );
|
||
}
|
||
|
||
LocalFree( lpwsValName );
|
||
LocalFree( lpbMultiSz );
|
||
LocalFree( lpwsSrcIconPath );
|
||
LocalFree( lpwsDstIconPath );
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpInitETCMaps
|
||
//
|
||
// Returns: NO_ERROR success
|
||
// non-zero returns from the IOCTL
|
||
// non-zero returns from the AfpRegXXX apis.
|
||
//
|
||
//
|
||
// Description: This routine will read in all the type/creators and extensions
|
||
// from the registry and store them in a cache. It will then
|
||
// create a list of mappings from the cache and then IOCTL the
|
||
// the FSD to add them. If the default is not in the registry,
|
||
// a hardcoded one is used. All non-zero returns from this
|
||
// routine are fatal. All non-fatal errors will be logged.
|
||
//
|
||
//
|
||
DWORD
|
||
AfpInitETCMaps(
|
||
VOID
|
||
)
|
||
{
|
||
DWORD dwRetCode;
|
||
AFP_REQUEST_PACKET AfpSrp;
|
||
AFP_EXTENSION DefExtension;
|
||
AFP_TYPE_CREATOR DefTypeCreator;
|
||
BYTE bDefaultETC[sizeof(ETCMAPINFO2)+sizeof(SETINFOREQPKT)];
|
||
PAFP_TYPE_CREATOR pTypeCreator;
|
||
DWORD dwNumTypeCreators;
|
||
AFP_TYPE_CREATOR AfpTypeCreatorKey;
|
||
|
||
// Get all type-creators from the registry and store them in a global cache.
|
||
//
|
||
if ( dwRetCode = AfpRegTypeCreatorEnum() )
|
||
return( dwRetCode );
|
||
|
||
// Get all extensions from the registry and store them in a global cache.
|
||
//
|
||
if ( dwRetCode = AfpRegExtensionEnum() )
|
||
return( dwRetCode );
|
||
|
||
// If there are no mappings do not IOCTL.
|
||
//
|
||
if ( AfpGlobals.AfpETCMapInfo.afpetc_num_extensions > 0 ) {
|
||
|
||
// IOCTL the FSD to Add these mappings
|
||
//
|
||
AfpSrp.dwRequestCode = OP_SERVER_ADD_ETC;
|
||
AfpSrp.dwApiType = AFP_API_TYPE_ADD;
|
||
|
||
// Make a buffer with the type/creator mappings in the form as required
|
||
// by the FSD
|
||
//
|
||
if ( dwRetCode = AfpBufMakeFSDETCMappings(
|
||
(PSRVETCPKT*)&(AfpSrp.Type.Add.pInputBuf),
|
||
&(AfpSrp.Type.Add.cbInputBufSize) ) )
|
||
return( dwRetCode );
|
||
|
||
if ( AfpSrp.Type.Add.cbInputBufSize > 0 ) {
|
||
|
||
dwRetCode = AfpServerIOCtrl( &AfpSrp );
|
||
|
||
LocalFree( AfpSrp.Type.Add.pInputBuf );
|
||
|
||
if ( dwRetCode )
|
||
return( dwRetCode );
|
||
}
|
||
else
|
||
LocalFree( AfpSrp.Type.Add.pInputBuf );
|
||
}
|
||
|
||
// Check to see if the default type/creator is in the registry
|
||
//
|
||
AfpTypeCreatorKey.afptc_id = AFP_DEF_TCID;
|
||
|
||
dwNumTypeCreators = AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators;
|
||
|
||
pTypeCreator = _lfind( &AfpTypeCreatorKey,
|
||
AfpGlobals.AfpETCMapInfo.afpetc_type_creator,
|
||
(unsigned int *)&dwNumTypeCreators,
|
||
sizeof(AFP_TYPE_CREATOR),
|
||
AfpLCompareTypeCreator );
|
||
|
||
// If the default is not in the registry use the hard-coded defaults.
|
||
//
|
||
if ( pTypeCreator == NULL ) {
|
||
|
||
STRCPY( DefTypeCreator.afptc_type, AFP_DEF_TYPE );
|
||
STRCPY( DefTypeCreator.afptc_creator, AFP_DEF_CREATOR );
|
||
STRCPY( DefTypeCreator.afptc_comment, AfpGlobals.wchDefTCComment );
|
||
DefTypeCreator.afptc_id = AFP_DEF_TCID;
|
||
}
|
||
else
|
||
DefTypeCreator = *pTypeCreator;
|
||
|
||
ZeroMemory( (LPBYTE)(DefExtension.afpe_extension),
|
||
AFP_FIELD_SIZE( AFP_EXTENSION, afpe_extension) );
|
||
|
||
STRCPY( DefExtension.afpe_extension, AFP_DEF_EXTENSION_W );
|
||
|
||
AfpBufCopyFSDETCMapInfo( &DefTypeCreator,
|
||
&DefExtension,
|
||
(PETCMAPINFO2)(bDefaultETC+sizeof(SETINFOREQPKT)));
|
||
|
||
// IOCTL the FSD to set the default
|
||
//
|
||
AfpSrp.dwRequestCode = OP_SERVER_SET_ETC;
|
||
AfpSrp.dwApiType = AFP_API_TYPE_SETINFO;
|
||
AfpSrp.Type.SetInfo.pInputBuf = bDefaultETC;
|
||
AfpSrp.Type.SetInfo.cbInputBufSize = sizeof( bDefaultETC );
|
||
|
||
if ( dwRetCode = AfpServerIOCtrl( &AfpSrp ) )
|
||
return( dwRetCode );
|
||
|
||
// If the default was not in the cache, add it now.
|
||
//
|
||
if ( pTypeCreator == NULL ) {
|
||
|
||
// Grow the cache size by one entry.
|
||
//
|
||
pTypeCreator = AfpGlobals.AfpETCMapInfo.afpetc_type_creator;
|
||
dwNumTypeCreators = AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators;
|
||
|
||
pTypeCreator = (PAFP_TYPE_CREATOR)LocalReAlloc(
|
||
pTypeCreator,
|
||
(dwNumTypeCreators+1)*sizeof(AFP_TYPE_CREATOR),
|
||
LMEM_MOVEABLE );
|
||
|
||
if ( pTypeCreator == NULL )
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
|
||
pTypeCreator[dwNumTypeCreators++] = DefTypeCreator;
|
||
|
||
AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators = dwNumTypeCreators;
|
||
AfpGlobals.AfpETCMapInfo.afpetc_type_creator = pTypeCreator;
|
||
|
||
// Sort the table
|
||
//
|
||
qsort( pTypeCreator,
|
||
dwNumTypeCreators,
|
||
sizeof(AFP_TYPE_CREATOR),
|
||
AfpBCompareTypeCreator );
|
||
}
|
||
|
||
return( NO_ERROR );
|
||
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpInitServerIcons
|
||
//
|
||
// Returns: NO_ERROR - success
|
||
// ERROR_NOT_ENOUGH_MEMORY
|
||
// non-zero return codes from registry apis.
|
||
//
|
||
// Description: This procedure will read in an icon at a time from the
|
||
// registry, and then register this icon with the server.
|
||
// This procedure will only return fatal errors that will
|
||
// require that the service fail initialization. All other
|
||
// error will be logged by this routine. All returns from the
|
||
// the FSD are treated as non-fatal.
|
||
//
|
||
//
|
||
DWORD
|
||
AfpInitServerIcons(
|
||
VOID
|
||
)
|
||
{
|
||
DWORD dwRetCode;
|
||
LPWSTR lpwsValName;
|
||
DWORD dwMaxValNameLen;
|
||
DWORD dwNumValues;
|
||
DWORD dwMaxValueDataSize;
|
||
DWORD dwIndex;
|
||
DWORD dwType;
|
||
DWORD dwBufSize;
|
||
DWORD dwValNameBufSize;
|
||
AFP_REQUEST_PACKET AfpRequestPkt;
|
||
LPBYTE lpbMultiSz;
|
||
AFP_ICON_INFO IconInfo;
|
||
|
||
// Find out the size of the largest data value and the largest
|
||
// value name.
|
||
//
|
||
if ( dwRetCode = AfpRegGetKeyInfo( AfpGlobals.hkeyIcons,
|
||
&dwMaxValNameLen,
|
||
&dwNumValues,
|
||
&dwMaxValueDataSize
|
||
))
|
||
return( dwRetCode );
|
||
|
||
// If there are no icons in the registry then simply return
|
||
//
|
||
if ( dwNumValues == 0 )
|
||
return( NO_ERROR );
|
||
|
||
if (( lpwsValName = (LPWSTR)LocalAlloc( LPTR, dwMaxValNameLen )) == NULL )
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
|
||
if (( lpbMultiSz = (LPBYTE)LocalAlloc( LPTR, dwMaxValueDataSize))== NULL){
|
||
LocalFree( lpwsValName );
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
}
|
||
|
||
for ( dwIndex = 0,
|
||
dwBufSize = dwMaxValueDataSize,
|
||
dwValNameBufSize = dwMaxValNameLen;
|
||
|
||
dwIndex < dwNumValues;
|
||
|
||
dwIndex++,
|
||
dwBufSize = dwMaxValueDataSize,
|
||
dwValNameBufSize = dwMaxValNameLen ) {
|
||
|
||
ZeroMemory( lpbMultiSz, dwBufSize );
|
||
|
||
// Get the icon from the registry.
|
||
//
|
||
if ( dwRetCode = RegEnumValue( AfpGlobals.hkeyIcons,
|
||
dwIndex,
|
||
lpwsValName,
|
||
&dwValNameBufSize,
|
||
NULL,
|
||
&dwType,
|
||
lpbMultiSz,
|
||
&dwBufSize
|
||
))
|
||
break;
|
||
|
||
// Parse the mult sz and extract info into icon info structure
|
||
//
|
||
if ( dwRetCode = AfpBufParseMultiSz(
|
||
AFP_ICON_STRUCT,
|
||
lpbMultiSz,
|
||
(LPBYTE)&IconInfo
|
||
)) {
|
||
AfpLogEvent( AFPLOG_CANT_ADD_ICON, 1, &lpwsValName,
|
||
dwRetCode, EVENTLOG_WARNING_TYPE );
|
||
dwRetCode = NO_ERROR;
|
||
continue;
|
||
}
|
||
|
||
if ( dwRetCode = AfpBufUnicodeToNibble((LPWSTR)IconInfo.afpicon_data)){
|
||
AfpLogEvent( AFPLOG_CANT_ADD_ICON, 1, &lpwsValName,
|
||
dwRetCode, EVENTLOG_WARNING_TYPE );
|
||
dwRetCode = NO_ERROR;
|
||
continue;
|
||
}
|
||
|
||
// Validate the icon info structure
|
||
//
|
||
if ( !IsAfpIconValid( &IconInfo ) ) {
|
||
AfpLogEvent( AFPLOG_CANT_ADD_ICON, 1, &lpwsValName,
|
||
dwRetCode, EVENTLOG_WARNING_TYPE );
|
||
dwRetCode = NO_ERROR;
|
||
continue;
|
||
}
|
||
|
||
// Copy the icon info into an FSD icon structure.
|
||
// NOTE: Re-use lpbMultiSz to store the FSD Icon structure. We know
|
||
// it is big enough, because the FSD icon structure HAS to be
|
||
// smaller than the MultiSz that contains the same information.
|
||
//
|
||
AfpBufMakeFSDIcon( &IconInfo, lpbMultiSz, &dwBufSize );
|
||
|
||
// Initialize the FSD with this icon
|
||
//
|
||
AfpRequestPkt.dwRequestCode = OP_SERVER_ADD_ICON;
|
||
AfpRequestPkt.dwApiType = AFP_API_TYPE_ADD;
|
||
AfpRequestPkt.Type.Add.pInputBuf = lpbMultiSz;
|
||
AfpRequestPkt.Type.Add.cbInputBufSize = dwBufSize;
|
||
|
||
if ( dwRetCode = AfpServerIOCtrl( &AfpRequestPkt ) ) {
|
||
AfpLogEvent( AFPLOG_CANT_ADD_ICON, 1, &lpwsValName,
|
||
dwRetCode, EVENTLOG_WARNING_TYPE );
|
||
dwRetCode = NO_ERROR;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
LocalFree( lpwsValName );
|
||
LocalFree( lpbMultiSz );
|
||
|
||
return( dwRetCode );
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpInitRPC
|
||
//
|
||
// Returns: NO_ERROR - success
|
||
// ERROR_NOT_ENOUGH_MEMORY
|
||
// nonzero returns from RPC APIs
|
||
// RpcServerRegisterIf()
|
||
// RpcServerUseProtseqEp()
|
||
//
|
||
// Description: Starts an RPC Server, adds the address (or port/pipe),
|
||
// and adds the interface (dispatch table).
|
||
//
|
||
DWORD
|
||
AfpInitRPC( VOID )
|
||
{
|
||
RPC_STATUS RpcStatus;
|
||
LPWSTR lpwsEndpoint = NULL;
|
||
BOOL Bool;
|
||
|
||
|
||
// We need to concatenate \pipe\ to the front of the interface name.
|
||
//
|
||
lpwsEndpoint = (LPWSTR)LocalAlloc( LPTR, sizeof(NT_PIPE_PREFIX) +
|
||
((STRLEN(AFP_SERVICE_NAME)+1)*sizeof(WCHAR)));
|
||
if ( lpwsEndpoint == NULL)
|
||
return( ERROR_NOT_ENOUGH_MEMORY );
|
||
|
||
STRCPY( lpwsEndpoint, NT_PIPE_PREFIX );
|
||
STRCAT( lpwsEndpoint, AFP_SERVICE_NAME );
|
||
|
||
|
||
// Ignore the second argument for now.
|
||
//
|
||
RpcStatus = RpcServerUseProtseqEpW( TEXT("ncacn_np"),
|
||
10,
|
||
lpwsEndpoint,
|
||
NULL );
|
||
|
||
if ( RpcStatus != RPC_S_OK )
|
||
{
|
||
LocalFree( lpwsEndpoint );
|
||
return( I_RpcMapWin32Status( RpcStatus ) );
|
||
}
|
||
|
||
RpcStatus = RpcServerRegisterIf( afpsvc_v0_0_s_ifspec, 0, 0);
|
||
|
||
LocalFree( lpwsEndpoint );
|
||
|
||
if ( RpcStatus == RPC_S_OK )
|
||
return( NO_ERROR );
|
||
else
|
||
return( I_RpcMapWin32Status( RpcStatus ) );
|
||
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpTerminateRPC
|
||
//
|
||
// Returns: none
|
||
//
|
||
// Description: Deletes the interface.
|
||
//
|
||
VOID
|
||
AfpTerminateRPC(
|
||
VOID
|
||
)
|
||
{
|
||
RPC_STATUS RpcStatus;
|
||
|
||
if ( AfpGlobals.dwServerState & AFPSTATE_RPC_STARTED )
|
||
{
|
||
RpcStatus = RpcServerUnregisterIf( afpsvc_v0_0_s_ifspec, 0, 0 );
|
||
|
||
if (RpcStatus != RPC_S_OK)
|
||
{
|
||
AFP_PRINT(("RpcServerUnregisterIf failed %ld\n", I_RpcMapWin32Status( RpcStatus )));
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpIniLsa
|
||
//
|
||
// Returns: none.
|
||
//
|
||
// Description: This procedure will register our process with LSA, needed for
|
||
// change-password
|
||
//
|
||
VOID
|
||
AfpIniLsa(
|
||
VOID
|
||
)
|
||
{
|
||
NTSTATUS ntstatus;
|
||
STRING LsaName;
|
||
LSA_OPERATIONAL_MODE SecurityMode;
|
||
|
||
|
||
//
|
||
// register with Lsa as a logon process
|
||
//
|
||
|
||
RtlInitString(&LsaName, LOGON_PROCESS_NAME);
|
||
|
||
ntstatus = LsaRegisterLogonProcess(&LsaName, &SfmLsaHandle, &SecurityMode);
|
||
if (ntstatus != STATUS_SUCCESS)
|
||
{
|
||
SfmLsaHandle = NULL;
|
||
return;
|
||
}
|
||
|
||
//
|
||
// call Lsa to get the MSV1_0's pkg id, which we need during logon
|
||
//
|
||
|
||
RtlInitString(&LsaName, MSV1_0_PACKAGE_NAME);
|
||
|
||
ntstatus = LsaLookupAuthenticationPackage(SfmLsaHandle, &LsaName, &SfmAuthPkgId);
|
||
if (ntstatus != STATUS_SUCCESS)
|
||
{
|
||
LsaDeregisterLogonProcess( SfmLsaHandle );
|
||
SfmLsaHandle = NULL;
|
||
return;
|
||
}
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
BOOL
|
||
IsAfpGuestAccountEnabled(
|
||
VOID
|
||
)
|
||
{
|
||
|
||
NTSTATUS rc;
|
||
LSA_HANDLE hLsa;
|
||
PPOLICY_ACCOUNT_DOMAIN_INFO pAcctDomainInfo;
|
||
SECURITY_QUALITY_OF_SERVICE QOS;
|
||
OBJECT_ATTRIBUTES ObjAttribs;
|
||
NTSTATUS status;
|
||
SAM_HANDLE SamHandle;
|
||
SAM_HANDLE DomainHandle;
|
||
PUSER_ACCOUNT_INFORMATION UserAccount = NULL;
|
||
BOOLEAN fGuestEnabled;
|
||
SAMPR_HANDLE GuestAcctHandle;
|
||
|
||
|
||
|
||
// for now
|
||
fGuestEnabled = FALSE;
|
||
|
||
//
|
||
// Open the LSA and obtain a handle to it.
|
||
//
|
||
QOS.Length = sizeof(QOS);
|
||
QOS.ImpersonationLevel = SecurityImpersonation;
|
||
QOS.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
||
QOS.EffectiveOnly = FALSE;
|
||
|
||
InitializeObjectAttributes(&ObjAttribs, NULL, 0L, NULL, NULL);
|
||
|
||
ObjAttribs.SecurityQualityOfService = &QOS;
|
||
|
||
status = LsaOpenPolicy(NULL,
|
||
&ObjAttribs,
|
||
POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES,
|
||
&hLsa);
|
||
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
AFP_PRINT(("LsaOpenPolicy failed %lx\n",status));
|
||
return(fGuestEnabled);
|
||
}
|
||
|
||
//
|
||
// get the Domain Sid for the local domain: we'll need it very shortly
|
||
//
|
||
rc = LsaQueryInformationPolicy(hLsa,
|
||
PolicyAccountDomainInformation,
|
||
(PVOID) &pAcctDomainInfo);
|
||
if (!NT_SUCCESS(rc))
|
||
{
|
||
AFP_PRINT(("InitLSA: LsaQueryInfo... failed (%lx)\n",rc));
|
||
LsaClose(hLsa);
|
||
return(fGuestEnabled);
|
||
}
|
||
|
||
InitializeObjectAttributes(&ObjAttribs, NULL, 0L, NULL, NULL);
|
||
|
||
status = SamConnect(NULL, &SamHandle, MAXIMUM_ALLOWED, &ObjAttribs);
|
||
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
AFP_PRINT(("SamConnect failed %lx\n",status));
|
||
LsaFreeMemory(pAcctDomainInfo);
|
||
LsaClose(hLsa);
|
||
return(fGuestEnabled);
|
||
}
|
||
|
||
status = SamOpenDomain(
|
||
SamHandle,
|
||
MAXIMUM_ALLOWED,
|
||
pAcctDomainInfo->DomainSid,
|
||
&DomainHandle);
|
||
|
||
LsaFreeMemory(pAcctDomainInfo);
|
||
|
||
LsaClose(hLsa);
|
||
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
AFP_PRINT(("SamOpenDomain failed %lx\n",status));
|
||
SamCloseHandle(SamHandle);
|
||
return(fGuestEnabled);
|
||
}
|
||
|
||
status = SamOpenUser(
|
||
DomainHandle,
|
||
MAXIMUM_ALLOWED,
|
||
DOMAIN_USER_RID_GUEST,
|
||
&GuestAcctHandle);
|
||
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
AFP_PRINT(("SamOpenUser failed %lx\n",status));
|
||
SamCloseHandle(SamHandle);
|
||
return(fGuestEnabled);
|
||
}
|
||
|
||
status = SamQueryInformationUser(
|
||
GuestAcctHandle,
|
||
UserAccountInformation,
|
||
(PVOID *) &UserAccount );
|
||
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
AFP_PRINT(("SamQueryInformationUser failed %lx\n",status));
|
||
SamCloseHandle(SamHandle);
|
||
return(fGuestEnabled);
|
||
}
|
||
|
||
//
|
||
// now, see if the guest account is enabled.
|
||
//
|
||
if (!(UserAccount->UserAccountControl & USER_ACCOUNT_DISABLED))
|
||
{
|
||
fGuestEnabled = TRUE;
|
||
}
|
||
|
||
SamFreeMemory(UserAccount);
|
||
|
||
SamCloseHandle(GuestAcctHandle);
|
||
|
||
SamCloseHandle(SamHandle);
|
||
|
||
return(fGuestEnabled);
|
||
}
|
||
|