windows-nt/Source/XPSP1/NT/net/sfm/afp/service/server/init.c
2020-09-26 16:20:57 +08:00

1300 lines
33 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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