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