|
|
/********************************************************************/ /** 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); }
|