/********************************************************************/ /** Copyright(c) 1989 Microsoft Corporation. **/ /********************************************************************/ //*** // // Filename: etcmap.c // // Description: This module contains support routines for the extension/ // type/creator mappings category API's for the AFP server // service. These routines are called directly by the RPC // runtime. // // History: // June 11,1992. NarenG Created original version. // #include "afpsvcp.h" //** // // Call: AfpAdminrETCMapGetInfo // // Returns: NO_ERROR // ERROR_ACCESS_DENIED // ERROR_NOT_ENOUGH_MEMORY // // Description: Will alllocate enough memory to contain all mappings, copy // the information and return. // DWORD AfpAdminrETCMapGetInfo( IN AFP_SERVER_HANDLE hServer, OUT PAFP_ETCMAP_INFO *ppAfpETCMapInfo ) { DWORD dwRetCode=0; DWORD dwAccessStatus=0; // Check if caller has access // if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus)) { AFP_PRINT(( "SFMSVC: AfpAdminrETCMapGetInfo, AfpSecObjAccessCheck failed %ld\n",dwRetCode)); AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL, dwRetCode, EVENTLOG_ERROR_TYPE ); return( ERROR_ACCESS_DENIED ); } if ( dwAccessStatus ) { AFP_PRINT(( "SFMSVC: AfpAdminrETCMapGetInfo, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus)); return( ERROR_ACCESS_DENIED ); } // MUTEX start // WaitForSingleObject( AfpGlobals.hmutexETCMap, INFINITE ); // This loop is used to allow break's instead of goto's to be used // on an error condition. // do { dwRetCode = NO_ERROR; // Allocate memory and copy ETC mappings information // *ppAfpETCMapInfo = MIDL_user_allocate( sizeof(AFP_ETCMAP_INFO) ); if ( *ppAfpETCMapInfo == NULL ) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } (*ppAfpETCMapInfo)->afpetc_num_type_creators = AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators; (*ppAfpETCMapInfo)->afpetc_type_creator = MIDL_user_allocate( sizeof(AFP_TYPE_CREATOR) *AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators); if ( (*ppAfpETCMapInfo)->afpetc_type_creator == NULL ) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } (*ppAfpETCMapInfo)->afpetc_num_extensions = AfpGlobals.AfpETCMapInfo.afpetc_num_extensions; (*ppAfpETCMapInfo)->afpetc_extension = MIDL_user_allocate( sizeof(AFP_EXTENSION) *AfpGlobals.AfpETCMapInfo.afpetc_num_extensions); if ( (*ppAfpETCMapInfo)->afpetc_extension == NULL ) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } CopyMemory( (LPBYTE)(*ppAfpETCMapInfo)->afpetc_type_creator, (LPBYTE)(AfpGlobals.AfpETCMapInfo.afpetc_type_creator), sizeof(AFP_TYPE_CREATOR) * AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators); CopyMemory( (LPBYTE)(*ppAfpETCMapInfo)->afpetc_extension, (LPBYTE)(AfpGlobals.AfpETCMapInfo.afpetc_extension), sizeof(AFP_EXTENSION) * AfpGlobals.AfpETCMapInfo.afpetc_num_extensions); } while( FALSE ); // MUTEX end // ReleaseMutex( AfpGlobals.hmutexETCMap ); if ( dwRetCode ) { if ( *ppAfpETCMapInfo != NULL ) { if ( (*ppAfpETCMapInfo)->afpetc_type_creator != NULL ) MIDL_user_free( (*ppAfpETCMapInfo)->afpetc_type_creator ); MIDL_user_free( *ppAfpETCMapInfo ); } } return( dwRetCode ); } //** // // Call: AfpAdminrETCMapAdd // // Returns: NO_ERROR // ERROR_ACCESS_DENIED // AFPERR_DuplicateTypeCreator; // non-zero returns from the registry API's // // Description: This routine will add a type/creator/comment tupple to the // registry and the cache. // DWORD AfpAdminrETCMapAdd( IN AFP_SERVER_HANDLE hServer, IN PAFP_TYPE_CREATOR pAfpTypeCreator ) { DWORD dwRetCode=0; DWORD dwAccessStatus=0; PAFP_TYPE_CREATOR pTypeCreator; PAFP_TYPE_CREATOR pTmpTypeCreator=NULL; DWORD dwNumTypeCreators; // Check if caller has access // if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus)) { AFP_PRINT(( "SFMSVC: AfpAdminrETCMapAdd, AfpSecObjAccessCheck failed %ld\n",dwRetCode)); AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL, dwRetCode, EVENTLOG_ERROR_TYPE ); return( ERROR_ACCESS_DENIED ); } if ( dwAccessStatus ) { AFP_PRINT(( "SFMSVC: AfpAdminrETCMapAdd, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus)); return( ERROR_ACCESS_DENIED ); } // MUTEX start // WaitForSingleObject( AfpGlobals.hmutexETCMap, INFINITE ); // This loop is used to allow break's instead of goto's to be used // on an error condition. // do { dwRetCode = NO_ERROR; // First check to see if the type already exists. // pTypeCreator = AfpBinarySearch( pAfpTypeCreator, AfpGlobals.AfpETCMapInfo.afpetc_type_creator, AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators, sizeof(AFP_TYPE_CREATOR), AfpBCompareTypeCreator ); // It exists so return error // if ( pTypeCreator != NULL ) { dwRetCode = (DWORD)AFPERR_DuplicateTypeCreator; break; } // Set the ID for this type/creator // pAfpTypeCreator->afptc_id = ++AfpGlobals.dwCurrentTCId; // It does not exist so add it to the registry and the cache. // if ( dwRetCode = AfpRegTypeCreatorAdd( pAfpTypeCreator ) ) break; // Grow the cache size by one entry. // pTypeCreator = AfpGlobals.AfpETCMapInfo.afpetc_type_creator; dwNumTypeCreators = AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators; pTmpTypeCreator = (PAFP_TYPE_CREATOR)LocalReAlloc( pTypeCreator, (dwNumTypeCreators+1)*sizeof(AFP_TYPE_CREATOR), LMEM_MOVEABLE ); if ( pTmpTypeCreator == NULL ) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } pTypeCreator = pTmpTypeCreator; pTypeCreator[dwNumTypeCreators++] = *pAfpTypeCreator; AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators = dwNumTypeCreators; AfpGlobals.AfpETCMapInfo.afpetc_type_creator = pTypeCreator; // Sort the table // qsort( pTypeCreator, dwNumTypeCreators, sizeof(AFP_TYPE_CREATOR), AfpBCompareTypeCreator ); } while( FALSE ); // MUTEX end // ReleaseMutex( AfpGlobals.hmutexETCMap ); return( dwRetCode ); } //** // // Call: AfpAdminrETCMapDelete // // Returns: NO_ERROR // ERROR_ACCESS_DENIED // AFPERR_TypeCreatorNotExistant // non-zero returns from registry api's. // non-zero returns from the FSD. // // // Description: This routine will delete a type/creator tupple from the // registry and the cache. If there are any extensions that map // to this tupple, they are deleted. // Shrinking by reallocating is not done. This will be done the // next time an extension is added or if the server is restarted. // DWORD AfpAdminrETCMapDelete( IN AFP_SERVER_HANDLE hServer, IN PAFP_TYPE_CREATOR pAfpTypeCreator ) { AFP_REQUEST_PACKET AfpSrp; DWORD dwRetCode=0; DWORD dwAccessStatus=0; PAFP_TYPE_CREATOR pTypeCreator; AFP_EXTENSION AfpExtensionKey; PAFP_EXTENSION pExtension; PAFP_EXTENSION pExtensionWalker; DWORD cbSize; DWORD dwIndex; ETCMAPINFO2 ETCMapFSDBuf; DWORD dwCount; // Check if caller has access // if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus)) { AFP_PRINT(( "SFMSVC: AfpAdminrETCMapDelete, AfpSecObjAccessCheck failed %ld\n",dwRetCode)); AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL, dwRetCode, EVENTLOG_ERROR_TYPE ); return( ERROR_ACCESS_DENIED ); } if ( dwAccessStatus ) { AFP_PRINT(( "SFMSVC: AfpAdminrETCMapDelete, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus)); return( ERROR_ACCESS_DENIED ); } // MUTEX start // WaitForSingleObject( AfpGlobals.hmutexETCMap, INFINITE ); // This loop is used to allow break's instead of goto's to be used // on an error condition. // do { dwRetCode = NO_ERROR; // First check to see if the type/creator exists. // pTypeCreator = AfpBinarySearch( pAfpTypeCreator, AfpGlobals.AfpETCMapInfo.afpetc_type_creator, AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators, sizeof(AFP_TYPE_CREATOR), AfpBCompareTypeCreator ); // It does not exist so return error // if ( pTypeCreator == NULL ) { dwRetCode = (DWORD)AFPERR_TypeCreatorNotExistant; break; } // If this is the default type/creator // if ( pTypeCreator->afptc_id == AFP_DEF_TCID ) { dwRetCode = (DWORD)AFPERR_CannotDeleteDefaultTC; break; } // Store the id of this type/creator. All extensions with this // id will have to be deleted. // AfpExtensionKey.afpe_tcid = pTypeCreator->afptc_id; // Walk the list of extensions and delete all entries with // the corresponding type/creator ID // pExtension = AfpBinarySearch( &AfpExtensionKey, AfpGlobals.AfpETCMapInfo.afpetc_extension, AfpGlobals.AfpETCMapInfo.afpetc_num_extensions, sizeof(AFP_EXTENSION), AfpBCompareExtension ); if ( pExtension != NULL ) { for ( dwIndex = (DWORD)(((ULONG_PTR)pExtension - (ULONG_PTR)(AfpGlobals.AfpETCMapInfo.afpetc_extension)) / sizeof(AFP_EXTENSION)), pExtensionWalker = pExtension, dwCount = 0; ( dwIndex < AfpGlobals.AfpETCMapInfo.afpetc_num_extensions ) && ( pExtensionWalker->afpe_tcid == AfpExtensionKey.afpe_tcid ); dwIndex++, dwCount++, pExtensionWalker++ ) { // IOCTL the FSD to delete this tupple // AfpBufCopyFSDETCMapInfo( pAfpTypeCreator, pExtensionWalker, &ETCMapFSDBuf ); AfpSrp.dwRequestCode = OP_SERVER_DELETE_ETC; AfpSrp.dwApiType = AFP_API_TYPE_DELETE; AfpSrp.Type.Delete.pInputBuf = &ETCMapFSDBuf; AfpSrp.Type.Delete.cbInputBufSize = sizeof(ETCMAPINFO2); if ( dwRetCode = AfpServerIOCtrl( &AfpSrp ) ) { break; } // Delete this extension from the registry // if ( dwRetCode = AfpRegExtensionDelete( pExtensionWalker )) { break; } } if ( dwRetCode ) break; // Remove the extensions from the cache // AfpGlobals.AfpETCMapInfo.afpetc_num_extensions -= dwCount; // Remove these extensions from the cache too // cbSize = AfpGlobals.AfpETCMapInfo.afpetc_num_extensions * sizeof(AFP_EXTENSION); cbSize -= (DWORD)((ULONG_PTR)pExtension - (ULONG_PTR)(AfpGlobals.AfpETCMapInfo.afpetc_extension)); CopyMemory( (LPBYTE)pExtension, (LPBYTE)pExtensionWalker, cbSize ); } // Delete the type/creator from the registry // if ( dwRetCode = AfpRegTypeCreatorDelete( pTypeCreator ) ) break; // Delete the type/creator from the cache // AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators--; cbSize = AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators * sizeof(AFP_TYPE_CREATOR); cbSize -= (DWORD)((ULONG_PTR)pTypeCreator - (ULONG_PTR)AfpGlobals.AfpETCMapInfo.afpetc_type_creator); CopyMemory( (LPBYTE)pTypeCreator, (LPBYTE)((ULONG_PTR)pTypeCreator+sizeof(AFP_TYPE_CREATOR)), cbSize ); } while( FALSE ); // MUTEX end // ReleaseMutex( AfpGlobals.hmutexETCMap ); return( dwRetCode ); } //** // // Call: AfpAdminrETCMapSetInfo // // Returns: NO_ERROR // ERROR_ACCESS_DENIED // AFPERR_TypeCreatorNotExistant // AFPERR_CannotEditDefaultTC; // non-zero returns from registry api's. // // Description: This routine will simply change the comment for a type/creator // tupple. // DWORD AfpAdminrETCMapSetInfo( IN AFP_SERVER_HANDLE hServer, IN PAFP_TYPE_CREATOR pAfpTypeCreator ) { DWORD dwRetCode=0; DWORD dwAccessStatus=0; PAFP_TYPE_CREATOR pTypeCreator; // Check if caller has access // if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus)) { AFP_PRINT(( "SFMSVC: AfpAdminrETCMapSetInfo, AfpSecObjAccessCheck failed %ld\n",dwRetCode)); AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL, dwRetCode, EVENTLOG_ERROR_TYPE ); return( ERROR_ACCESS_DENIED ); } if ( dwAccessStatus ) { AFP_PRINT(( "SFMSVC: AfpAdminrETCMapSetInfo, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus)); return( ERROR_ACCESS_DENIED ); } // MUTEX start // WaitForSingleObject( AfpGlobals.hmutexETCMap, INFINITE ); // This loop is used to allow break's instead of goto's to be used // on an error condition. // do { dwRetCode = NO_ERROR; // First check to see if the type/creator exists. // pTypeCreator = AfpBinarySearch( pAfpTypeCreator, AfpGlobals.AfpETCMapInfo.afpetc_type_creator, AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators, sizeof(AFP_TYPE_CREATOR), AfpBCompareTypeCreator ); // It does not exist so return error // if ( pTypeCreator == NULL ) { dwRetCode = (DWORD)AFPERR_TypeCreatorNotExistant; break; } // If this is the default type/creator // if ( pTypeCreator->afptc_id == AFP_DEF_TCID ) { dwRetCode = (DWORD)AFPERR_CannotEditDefaultTC; break; } // Copy the id. // pAfpTypeCreator->afptc_id = pTypeCreator->afptc_id; // Set the comment in the registry // if ( dwRetCode = AfpRegTypeCreatorSetInfo( pAfpTypeCreator ) ) { break; } // Set the comment in the cache. // STRCPY( pTypeCreator->afptc_comment, pAfpTypeCreator->afptc_comment ); } while( FALSE ); // MUTEX end // ReleaseMutex( AfpGlobals.hmutexETCMap ); return( dwRetCode ); } //** // // Call: AfpAdminrETCMapAssociate // // Returns: NO_ERROR // ERROR_ACCESS_DENIED // AFPERR_TypeCreatorNotExistant // non-zero returns from registry api's. // non-zero returns from the FSD // // // Description: This routine will associate the given extension with the // specified type/creator if it exists. If the extension is // being mapped to the default type/creator, it will be // deleted. // DWORD AfpAdminrETCMapAssociate( IN AFP_SERVER_HANDLE hServer, IN PAFP_TYPE_CREATOR pAfpTypeCreator, IN PAFP_EXTENSION pAfpExtension ) { AFP_REQUEST_PACKET AfpSrp; DWORD dwRetCode=0; DWORD dwAccessStatus=0; PAFP_TYPE_CREATOR pTypeCreator; PAFP_EXTENSION pExtension; PAFP_EXTENSION pTmpExtension=NULL; SRVETCPKT SrvETCPkt; DWORD dwNumExtensions; DWORD cbSize; BYTE bETCMapFSDBuf[sizeof(ETCMAPINFO2)+sizeof(SETINFOREQPKT)]; // Check if caller has access // if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus)) { AFP_PRINT(( "SFMSVC: AfpAdminrETCMapAssociate, AfpSecObjAccessCheck failed %ld\n",dwRetCode)); AfpLogEvent( AFPLOG_CANT_CHECK_ACCESS, 0, NULL, dwRetCode, EVENTLOG_ERROR_TYPE ); return( ERROR_ACCESS_DENIED ); } if ( dwAccessStatus ) { AFP_PRINT(( "SFMSVC: AfpAdminrETCMapAssociate, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus)); return( ERROR_ACCESS_DENIED ); } // MUTEX start // WaitForSingleObject( AfpGlobals.hmutexETCMap, INFINITE ); // This loop is used to allow break's instead of goto's to be used // on an error condition. // do { dwRetCode = NO_ERROR; // First check to see if the type/creator pair that the // new extension is to be associated with, exists. // pTypeCreator = AfpBinarySearch( pAfpTypeCreator, AfpGlobals.AfpETCMapInfo.afpetc_type_creator, AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators, sizeof(AFP_TYPE_CREATOR), AfpBCompareTypeCreator ); // It does not exist so return error // if ( pTypeCreator == NULL ) { dwRetCode = (DWORD)AFPERR_TypeCreatorNotExistant; break; } // Now check to see if the extension is already associated with // a type/creator pair. // dwNumExtensions = AfpGlobals.AfpETCMapInfo.afpetc_num_extensions; pExtension = _lfind( pAfpExtension, AfpGlobals.AfpETCMapInfo.afpetc_extension, (unsigned int *)&dwNumExtensions, sizeof(AFP_EXTENSION), AfpLCompareExtension ); // Not currently associated so we need to add an entry // if ( pExtension == NULL ) { // If this extension is being associated with the default // then simply return. // if ( pTypeCreator->afptc_id == AFP_DEF_TCID ) { dwRetCode = NO_ERROR; break; } // Add mapping to FSD // AfpBufCopyFSDETCMapInfo( pAfpTypeCreator, pAfpExtension, &(SrvETCPkt.retc_EtcMaps[0]) ); SrvETCPkt.retc_NumEtcMaps = 1; AfpSrp.dwRequestCode = OP_SERVER_ADD_ETC; AfpSrp.dwApiType = AFP_API_TYPE_ADD; AfpSrp.Type.Add.pInputBuf = &SrvETCPkt; AfpSrp.Type.Add.cbInputBufSize = sizeof(SRVETCPKT); if ( dwRetCode = AfpServerIOCtrl( &AfpSrp ) ) break; // Add extension to registry. // pAfpExtension->afpe_tcid = pTypeCreator->afptc_id; if ( dwRetCode = AfpRegExtensionSetInfo( pAfpExtension ) ) { break; } // Add extension to cache. // pExtension = AfpGlobals.AfpETCMapInfo.afpetc_extension; dwNumExtensions = AfpGlobals.AfpETCMapInfo.afpetc_num_extensions; pTmpExtension = (PAFP_EXTENSION)LocalReAlloc( pExtension, (dwNumExtensions+1)*sizeof(AFP_EXTENSION), LMEM_MOVEABLE ); if ( pTmpExtension == NULL ) { dwRetCode = ERROR_NOT_ENOUGH_MEMORY; break; } pExtension = pTmpExtension; pExtension[dwNumExtensions++] = *pAfpExtension; AfpGlobals.AfpETCMapInfo.afpetc_num_extensions = dwNumExtensions; AfpGlobals.AfpETCMapInfo.afpetc_extension = pExtension; } // Extension is already mapped. // else { // If this extension is being associated with the default // then delete this extension from the registry and cache and // delete the mapping from the FSD // if ( pTypeCreator->afptc_id == AFP_DEF_TCID ) { // IOCTL the FSD to delete this tupple // AfpBufCopyFSDETCMapInfo( pAfpTypeCreator, pAfpExtension, (PETCMAPINFO2)bETCMapFSDBuf ); AfpSrp.dwRequestCode = OP_SERVER_DELETE_ETC; AfpSrp.dwApiType = AFP_API_TYPE_DELETE; AfpSrp.Type.Delete.pInputBuf = bETCMapFSDBuf; AfpSrp.Type.Delete.cbInputBufSize = sizeof(ETCMAPINFO2); if ( dwRetCode = AfpServerIOCtrl( &AfpSrp ) ) break; // Delete this extension from the registry // if ( dwRetCode = AfpRegExtensionDelete( pAfpExtension ) ) { break; } // Remove this extensions from the cache too // AfpGlobals.AfpETCMapInfo.afpetc_num_extensions--; cbSize = AfpGlobals.AfpETCMapInfo.afpetc_num_extensions * sizeof(AFP_EXTENSION); cbSize -= (DWORD)((ULONG_PTR)pExtension - (ULONG_PTR)(AfpGlobals.AfpETCMapInfo.afpetc_extension)); CopyMemory( (LPBYTE)pExtension, (LPBYTE)((ULONG_PTR)pExtension+sizeof(AFP_EXTENSION)), cbSize ); } else { // Otherwise simply change the mapping in the FSD // pExtension->afpe_tcid = pTypeCreator->afptc_id; AfpBufCopyFSDETCMapInfo(pTypeCreator, pExtension, (PETCMAPINFO2)(bETCMapFSDBuf+sizeof(SETINFOREQPKT))); AfpSrp.dwRequestCode = OP_SERVER_SET_ETC; AfpSrp.dwApiType = AFP_API_TYPE_SETINFO; AfpSrp.Type.SetInfo.pInputBuf = bETCMapFSDBuf; AfpSrp.Type.SetInfo.cbInputBufSize = sizeof(bETCMapFSDBuf); if ( dwRetCode = AfpServerIOCtrl( &AfpSrp ) ) break; // Change the registry // if ( dwRetCode = AfpRegExtensionSetInfo( pExtension ) ) { break; } } } // Sort the table // qsort( AfpGlobals.AfpETCMapInfo.afpetc_extension, AfpGlobals.AfpETCMapInfo.afpetc_num_extensions, sizeof(AFP_EXTENSION), AfpBCompareExtension ); } while( FALSE ); // MUTEX end // ReleaseMutex( AfpGlobals.hmutexETCMap ); return( dwRetCode ); }