Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

894 lines
23 KiB

/********************************************************************/
/** Copyright(c) 1989 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: volume.c
//
// Description: This module contains support routines for the volume
// category API's for the AFP server service
//
// History:
// June 11,1992. NarenG Created original version.
//
#include "afpsvcp.h"
static HANDLE hmutexInvalidVolume;
// Invalid volume structure
//
typedef struct _AFP_BADVOLUME {
LPWSTR lpwsName;
LPWSTR lpwsPath;
DWORD cbVariableData; // Number of bytes of name+path.
struct _AFP_BADVOLUME * Next;
} AFP_BADVOLUME, * PAFP_BADVOLUME;
// Singly linked list of invalid volumes
//
typedef struct _AFP_INVALID_VOLUMES {
DWORD cbTotalData;
PAFP_BADVOLUME Head;
} AFP_INVALID_VOLUMES;
static AFP_INVALID_VOLUMES InvalidVolumeList;
//**
//
// Call: AfpAdminrVolumeEnum
//
// Returns: NO_ERROR
// ERROR_ACCESS_DENIED
// non-zero returns from AfpServerIOCtrlGetInfo
//
// Description: This routine communicates with the AFP FSD to implement
// the AfpAdminrVolumeEnum function.
//
DWORD
AfpAdminrVolumeEnum(
IN AFP_SERVER_HANDLE hServer,
IN OUT PVOLUME_INFO_CONTAINER pInfoStruct,
IN DWORD dwPreferedMaximumLength,
OUT LPDWORD lpdwTotalEntries,
IN OUT LPDWORD lpdwResumeHandle OPTIONAL
)
{
AFP_REQUEST_PACKET AfpSrp;
DWORD dwRetCode=0;
DWORD dwAccessStatus=0;
// Check if caller has access
//
if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
{
AFP_PRINT(( "SFMSVC: AfpAdminrVolumeEnum, 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: AfpAdminrVolumeEnum, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
return( ERROR_ACCESS_DENIED );
}
// Set up request packet and make IOCTL to the FSD
//
AfpSrp.dwRequestCode = OP_VOLUME_ENUM;
AfpSrp.dwApiType = AFP_API_TYPE_ENUM;
AfpSrp.Type.Enum.cbOutputBufSize = dwPreferedMaximumLength;
// If resume handle was not passed then we set it to zero, cause caller
// wants all information starting from the beginning.
//
if ( lpdwResumeHandle )
AfpSrp.Type.Enum.EnumRequestPkt.erqp_Index = *lpdwResumeHandle;
else
AfpSrp.Type.Enum.EnumRequestPkt.erqp_Index = 0;
dwRetCode = AfpServerIOCtrlGetInfo( &AfpSrp );
if ( dwRetCode != ERROR_MORE_DATA && dwRetCode != NO_ERROR )
return( dwRetCode );
*lpdwTotalEntries = AfpSrp.Type.Enum.dwTotalAvail;
pInfoStruct->pBuffer =(PAFP_VOLUME_INFO)(AfpSrp.Type.Enum.pOutputBuf);
pInfoStruct->dwEntriesRead = AfpSrp.Type.Enum.dwEntriesRead;
if ( lpdwResumeHandle )
*lpdwResumeHandle = AfpSrp.Type.Enum.EnumRequestPkt.erqp_Index;
// Convert all offsets to pointers
//
AfpBufOffsetToPointer( (LPBYTE)(pInfoStruct->pBuffer),
pInfoStruct->dwEntriesRead,
AFP_VOLUME_STRUCT );
return( dwRetCode );
}
//**
//
// Call: AfpAdminrVolumeSetInfo
//
// Returns: NO_ERROR
// ERROR_ACCESS_DENIED
// non-zero returns from AfpServerIOCtrl
//
// Description: This routine communicates with the AFP FSD to implement
// the AfpAdminVolumeSetInfo function.
//
DWORD
AfpAdminrVolumeSetInfo(
IN AFP_SERVER_HANDLE hServer,
IN PAFP_VOLUME_INFO pAfpVolumeInfo,
IN DWORD dwParmNum
)
{
AFP_REQUEST_PACKET AfpSrp;
DWORD dwRetCode=0;
LPBYTE pAfpVolumeInfoSR = NULL;
DWORD cbAfpVolumeInfoSRSize;
DWORD dwAccessStatus=0;
// Check if caller has access
//
if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
{
AFP_PRINT(( "SFMSVC: AfpAdminrVolumeSetInfo, 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: AfpAdminrVolumeSetInfo, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
return( ERROR_ACCESS_DENIED );
}
// MUTEX start
//
WaitForSingleObject( AfpGlobals.hmutexVolume, INFINITE );
// This loop is used to allow break's instead of goto's to be used
// on an error condition.
//
do {
dwRetCode = NO_ERROR;
// Make this buffer self-relative.
//
if ( dwRetCode = AfpBufMakeFSDRequest((LPBYTE)pAfpVolumeInfo,
sizeof(SETINFOREQPKT),
AFP_VOLUME_STRUCT,
&pAfpVolumeInfoSR,
&cbAfpVolumeInfoSRSize ))
break;
// Make IOCTL to set info
//
AfpSrp.dwRequestCode = OP_VOLUME_SET_INFO;
AfpSrp.dwApiType = AFP_API_TYPE_SETINFO;
AfpSrp.Type.SetInfo.pInputBuf = pAfpVolumeInfoSR;
AfpSrp.Type.SetInfo.cbInputBufSize = cbAfpVolumeInfoSRSize;
AfpSrp.Type.SetInfo.dwParmNum = dwParmNum;
if ( dwRetCode = AfpServerIOCtrl( &AfpSrp ) )
break;
// Now IOCTL the FSD to get information to set in the registry
// The input buffer for a GetInfo type call should point to a volume
// structure with the volume name filled in. Since we already have
// this from the previos SetInfo call, we use the same buffer with
// the pointer advances by sizeof(SETINFOREQPKT) bytes.
//
AfpSrp.dwRequestCode = OP_VOLUME_GET_INFO;
AfpSrp.dwApiType = AFP_API_TYPE_GETINFO;
AfpSrp.Type.GetInfo.pInputBuf = pAfpVolumeInfoSR +
sizeof(SETINFOREQPKT);
AfpSrp.Type.GetInfo.cbInputBufSize = cbAfpVolumeInfoSRSize -
sizeof(SETINFOREQPKT);
if ( dwRetCode = AfpServerIOCtrlGetInfo( &AfpSrp ) )
break;
// Update the registry if the IOCTL was successful
//
AfpBufOffsetToPointer( AfpSrp.Type.GetInfo.pOutputBuf,
1,
AFP_VOLUME_STRUCT
);
dwRetCode = AfpRegVolumeSetInfo( AfpSrp.Type.GetInfo.pOutputBuf );
LocalFree( AfpSrp.Type.GetInfo.pOutputBuf );
} while( FALSE );
// MUTEX end
//
ReleaseMutex( AfpGlobals.hmutexVolume );
if ( pAfpVolumeInfoSR )
LocalFree( pAfpVolumeInfoSR );
return( dwRetCode );
}
//**
//
// Call: AfpAdminrVolumeDelete
//
// Returns: NO_ERROR
// ERROR_ACCESS_DENIED
// non-zero returns from AfpServerIOCtrl
//
// Description: This routine communicates with the AFP FSD to implement
// the AfpAdminVolumeDelete function.
//
DWORD
AfpAdminrVolumeDelete(
IN AFP_SERVER_HANDLE hServer,
IN LPWSTR lpwsVolumeName
)
{
AFP_REQUEST_PACKET AfpSrp;
PAFP_VOLUME_INFO pAfpVolumeInfoSR;
AFP_VOLUME_INFO AfpVolumeInfo;
DWORD cbAfpVolumeInfoSRSize;
DWORD dwRetCode=0;
DWORD dwAccessStatus=0;
// Check if caller has access
//
if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
{
AFP_PRINT(( "SFMSVC: AfpAdminrVolumeDelete, 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: AfpAdminrVolumeDelete, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
return( ERROR_ACCESS_DENIED );
}
// Delete FSD request expects a AFP_VOLUME_INFO structure with only
// the volume name field filled in.
//
AfpVolumeInfo.afpvol_name = lpwsVolumeName;
AfpVolumeInfo.afpvol_password = NULL;
AfpVolumeInfo.afpvol_path = NULL;
// MUTEX start
//
WaitForSingleObject( AfpGlobals.hmutexVolume, INFINITE );
// This loop is used to allow break's instead of goto's to be used
// on an error condition.
//
do {
dwRetCode = NO_ERROR;
// Make this buffer self-relative.
//
if ( dwRetCode = AfpBufMakeFSDRequest((LPBYTE)&AfpVolumeInfo,
0,
AFP_VOLUME_STRUCT,
(LPBYTE*)&pAfpVolumeInfoSR,
&cbAfpVolumeInfoSRSize ) )
break;
// IOCTL the FSD to delete the volume
//
AfpSrp.dwRequestCode = OP_VOLUME_DELETE;
AfpSrp.dwApiType = AFP_API_TYPE_DELETE;
AfpSrp.Type.Delete.pInputBuf = pAfpVolumeInfoSR;
AfpSrp.Type.Delete.cbInputBufSize = cbAfpVolumeInfoSRSize;
dwRetCode = AfpServerIOCtrl( &AfpSrp );
LocalFree( pAfpVolumeInfoSR );
if ( dwRetCode )
break;
// Update the registry if the IOCTL was successful
//
dwRetCode = AfpRegVolumeDelete( lpwsVolumeName );
} while( FALSE );
// MUTEX end
//
ReleaseMutex( AfpGlobals.hmutexVolume );
return( dwRetCode );
}
//**
//
// Call: AfpAdminrVolumeAdd
//
// Returns: NO_ERROR
// ERROR_ACCESS_DENIED
// non-zero returns from AfpServerIOCtrl
//
// Description: This routine communicates with the AFP FSD to implement
// the AfpAdminVolumeAdd function.
//
DWORD
AfpAdminrVolumeAdd(
IN AFP_SERVER_HANDLE hServer,
IN PAFP_VOLUME_INFO pAfpVolumeInfo
)
{
AFP_REQUEST_PACKET AfpSrp;
DWORD dwRetCode=0, dwLastDstCharIndex = 0;
PAFP_VOLUME_INFO pAfpVolumeInfoSR = NULL;
DWORD cbAfpVolumeInfoSRSize;
DWORD dwAccessStatus=0;
BOOL fCopiedIcon = FALSE;
WCHAR wchSrcIconPath[MAX_PATH];
WCHAR wchDstIconPath[MAX_PATH + AFPSERVER_VOLUME_ICON_FILE_SIZE + 1 + (sizeof(AFPSERVER_RESOURCE_STREAM)/sizeof(WCHAR))];
WCHAR wchServerIconFile[AFPSERVER_VOLUME_ICON_FILE_SIZE] = AFPSERVER_VOLUME_ICON_FILE;
// Check if caller has access
//
if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
{
AFP_PRINT(( "SFMSVC: AfpAdminrVolumeAdd, 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: AfpAdminrVolumeAdd, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
return( ERROR_ACCESS_DENIED );
}
if ( pAfpVolumeInfo == NULL)
{
AFP_PRINT(( "SFMSVC: AfpAdminrVolumeAdd, pAfpVolumeInfo == NULL\n"));
return( ERROR_INVALID_DATA );
}
// MUTEX start
//
WaitForSingleObject( AfpGlobals.hmutexVolume, INFINITE );
// This loop is used to allow break's instead of goto's to be used
// on an error condition.
//
do {
// Copy the server icon to the volume root
//
// Construct a path to the NTSFM volume custom icon
//
if ( GetSystemDirectory( wchSrcIconPath, MAX_PATH ) )
{
wcscat( wchSrcIconPath, AFP_DEF_VOLICON_SRCNAME );
if ( pAfpVolumeInfo->afpvol_path == NULL )
{
AFP_PRINT(( "SFMSVC: AfpAdminrVolumeAdd, pAfpVolumeInfo->afpvol_path == NULL\n"));
dwRetCode = ERROR_INVALID_DATA;
break;
}
// Construct a path to the destination volume "Icon<0D>" file
//
wcscpy( wchDstIconPath, pAfpVolumeInfo->afpvol_path );
if ( wcslen(wchDstIconPath) == 0 )
{
AFP_PRINT(( "SFMSVC: AfpAdminrVolumeAdd, wcslen(wchDstIconPath) == 0\n"));
dwRetCode = ERROR_INVALID_DATA;
break;
}
if (wchDstIconPath[wcslen(wchDstIconPath) - 1] != TEXT('\\'))
{
wcscat( wchDstIconPath, TEXT("\\") );
}
wcscat( wchDstIconPath, wchServerIconFile );
// Keep track of end of name without the resource fork tacked on
//
dwLastDstCharIndex = wcslen(wchDstIconPath);
wcscat( wchDstIconPath, AFPSERVER_RESOURCE_STREAM );
// Copy the icon file to the root of the volume (do not overwrite)
//
if ((fCopiedIcon = CopyFile( wchSrcIconPath, wchDstIconPath, TRUE )) ||
(GetLastError() == ERROR_FILE_EXISTS))
{
pAfpVolumeInfo->afpvol_props_mask |= AFP_VOLUME_HAS_CUSTOM_ICON;
// Make sure the file is hidden
SetFileAttributes( wchDstIconPath,
FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_ARCHIVE );
}
}
else
{
dwRetCode = GetLastError ();
break;
}
// Make this buffer self-relative.
//
if ( dwRetCode = AfpBufMakeFSDRequest( (LPBYTE)pAfpVolumeInfo,
0,
AFP_VOLUME_STRUCT,
(LPBYTE*)&pAfpVolumeInfoSR,
&cbAfpVolumeInfoSRSize ) )
break;
// IOCTL the FSD to add the volume
//
AfpSrp.dwRequestCode = OP_VOLUME_ADD;
AfpSrp.dwApiType = AFP_API_TYPE_ADD;
AfpSrp.Type.Add.pInputBuf = pAfpVolumeInfoSR;
AfpSrp.Type.Add.cbInputBufSize = cbAfpVolumeInfoSRSize;
dwRetCode = AfpServerIOCtrl( &AfpSrp );
// Don't allow icon bit to be written to the registry if it was set
pAfpVolumeInfo->afpvol_props_mask &= ~AFP_VOLUME_HAS_CUSTOM_ICON;
if ( dwRetCode )
{
// 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
wchDstIconPath[dwLastDstCharIndex] = 0;
DeleteFile( wchDstIconPath );
}
break;
}
// Update the registry if the IOCTL was successful
//
dwRetCode = AfpRegVolumeAdd( pAfpVolumeInfo );
if ( dwRetCode )
break;
// Delete this volume if it exists in the invalid volume list
//
AfpDeleteInvalidVolume( pAfpVolumeInfo->afpvol_name );
} while( FALSE );
// MUTEX end
//
ReleaseMutex( AfpGlobals.hmutexVolume );
if ( pAfpVolumeInfoSR != NULL )
LocalFree( pAfpVolumeInfoSR );
return( dwRetCode );
}
//**
//
// Call: AfpAdminrVolumeGetInfo
//
// Returns: NO_ERROR
// ERROR_ACCESS_DENIED
// non-zero returns from AfpServerIOCtrlGetInfo
//
// Description: This routine communicates with the AFP FSD to implement
// the AfpAdminVolumeGetInfo function.
//
DWORD
AfpAdminrVolumeGetInfo(
IN AFP_SERVER_HANDLE hServer,
IN LPWSTR lpwsVolumeName,
OUT PAFP_VOLUME_INFO* ppAfpVolumeInfo
)
{
AFP_REQUEST_PACKET AfpSrp;
PAFP_VOLUME_INFO pAfpVolumeInfoSR;
AFP_VOLUME_INFO AfpVolumeInfo;
DWORD cbAfpVolumeInfoSRSize;
DWORD dwRetCode=0;
DWORD dwAccessStatus=0;
// Check if caller has access
//
if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
{
AFP_PRINT(( "SFMSVC: AfpAdminrVolumeGetInfo, 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: AfpAdminrVolumeGetInfo, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
return( ERROR_ACCESS_DENIED );
}
// MUTEX start
//
WaitForSingleObject( AfpGlobals.hmutexVolume, INFINITE );
// This loop is used to allow break's instead of goto's to be used
// on an error condition.
//
do {
dwRetCode = NO_ERROR;
// Get info FSD request expects a AFP_VOLUME_INFO structure with only
// the volume name field filled in.
//
AfpVolumeInfo.afpvol_name = lpwsVolumeName;
AfpVolumeInfo.afpvol_password = NULL;
AfpVolumeInfo.afpvol_path = NULL;
// Make this buffer self-relative.
//
if ( dwRetCode = AfpBufMakeFSDRequest((LPBYTE)&AfpVolumeInfo,
0,
AFP_VOLUME_STRUCT,
(LPBYTE*)&pAfpVolumeInfoSR,
&cbAfpVolumeInfoSRSize ) )
break;
AfpSrp.dwRequestCode = OP_VOLUME_GET_INFO;
AfpSrp.dwApiType = AFP_API_TYPE_GETINFO;
AfpSrp.Type.GetInfo.pInputBuf = pAfpVolumeInfoSR;
AfpSrp.Type.GetInfo.cbInputBufSize = cbAfpVolumeInfoSRSize;
dwRetCode = AfpServerIOCtrlGetInfo( &AfpSrp );
if ( dwRetCode != ERROR_MORE_DATA && dwRetCode != NO_ERROR )
break;
LocalFree( pAfpVolumeInfoSR );
*ppAfpVolumeInfo = AfpSrp.Type.GetInfo.pOutputBuf;
// Convert all offsets to pointers
//
AfpBufOffsetToPointer( (LPBYTE)*ppAfpVolumeInfo, 1, AFP_VOLUME_STRUCT);
} while( FALSE );
// MUTEX end
//
ReleaseMutex( AfpGlobals.hmutexVolume );
return( dwRetCode );
}
//**
//
// Call: AfpAdminrInvalidVolumeEnum
//
// Returns: NO_ERROR
// ERROR_ACCESS_DENIED
//
// Description: This routine will return a list of all invalid volumes. This
// List is stored in a cache that is local to this module.
//
DWORD
AfpAdminrInvalidVolumeEnum(
IN AFP_SERVER_HANDLE hServer,
IN OUT PVOLUME_INFO_CONTAINER pInfoStruct
)
{
DWORD dwRetCode=0;
DWORD dwAccessStatus=0;
PAFP_VOLUME_INFO pOutputBuf;
PAFP_VOLUME_INFO pOutputWalker;
WCHAR * pwchVariableData;
PAFP_BADVOLUME pAfpBadVolWalker;
// Check if caller has access
//
if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
{
AFP_PRINT(( "SFMSVC: AfpAdminrInvalidVolumeEnum, 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: AfpAdminrInvalidVolumeEnum, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
return( ERROR_ACCESS_DENIED );
}
// MUTEX start
//
WaitForSingleObject( hmutexInvalidVolume, INFINITE );
// Allocate enough space to hold all the information.
//
pOutputBuf = MIDL_user_allocate( InvalidVolumeList.cbTotalData );
if ( pOutputBuf == NULL ){
ReleaseMutex( hmutexInvalidVolume );
return( ERROR_NOT_ENOUGH_MEMORY );
}
ZeroMemory( pOutputBuf, InvalidVolumeList.cbTotalData );
// Variable data begins from the end of the buffer.
//
pwchVariableData=(WCHAR*)((ULONG_PTR)pOutputBuf+InvalidVolumeList.cbTotalData);
// Walk the list and create the array of volume structures
//
for( pAfpBadVolWalker = InvalidVolumeList.Head,
pInfoStruct->dwEntriesRead = 0,
pOutputWalker = pOutputBuf;
pAfpBadVolWalker != NULL;
pOutputWalker++,
(pInfoStruct->dwEntriesRead)++,
pAfpBadVolWalker = pAfpBadVolWalker->Next ) {
pwchVariableData -= (STRLEN(pAfpBadVolWalker->lpwsName) + 1);
STRCPY( (LPWSTR)pwchVariableData, pAfpBadVolWalker->lpwsName );
pOutputWalker->afpvol_name = (LPWSTR)pwchVariableData;
if ( pAfpBadVolWalker->lpwsPath != NULL ) {
pwchVariableData -=( STRLEN(pAfpBadVolWalker->lpwsPath)+1 );
STRCPY( (LPWSTR)pwchVariableData, pAfpBadVolWalker->lpwsPath );
pOutputWalker->afpvol_path = (LPWSTR)pwchVariableData;
}
}
// MUTEX end
//
ReleaseMutex( hmutexInvalidVolume );
pInfoStruct->pBuffer = pOutputBuf;
return( dwRetCode );
}
//**
//
// Call: AfpAdminrInvalidVolumeDelete
//
// Returns: NO_ERROR
// ERROR_ACCESS_DENIED
//
// Description: This routine will remove an invalid volume from the registry
// and the list of invalid volumes.
//
DWORD
AfpAdminrInvalidVolumeDelete(
IN AFP_SERVER_HANDLE hServer,
IN LPWSTR lpwsVolumeName
)
{
DWORD dwRetCode=0;
DWORD dwAccessStatus=0;
// Check if caller has access
//
if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
{
AFP_PRINT(( "SFMSVC: AfpAdminrInvalidVolumeDelete, 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: AfpAdminrInvalidVolumeDelete, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
return( ERROR_ACCESS_DENIED );
}
// Remove this volume from the registry
//
if ( dwRetCode = AfpRegVolumeDelete( lpwsVolumeName ) ) {
if ( dwRetCode == ERROR_FILE_NOT_FOUND )
dwRetCode = (DWORD)AFPERR_VolumeNonExist;
}
// MUTEX start
//
WaitForSingleObject( hmutexInvalidVolume, INFINITE );
AfpDeleteInvalidVolume( lpwsVolumeName );
// MUTEX end
//
ReleaseMutex( hmutexInvalidVolume );
return( dwRetCode );
}
//**
//
// Call: AfpAddInvalidVolume
//
// Returns: none
//
// Description: Will add a volume structure to a sigly linked list of volumes.
//
VOID
AfpAddInvalidVolume(
IN LPWSTR lpwsName,
IN LPWSTR lpwsPath
)
{
DWORD dwRetCode = NO_ERROR;
WCHAR* pwchVariableData = NULL;
PAFP_BADVOLUME pAfpVolumeInfo = NULL;
DWORD cbVariableData;
// MUTEX start
//
WaitForSingleObject( hmutexInvalidVolume, INFINITE );
do {
cbVariableData = (STRLEN(lpwsName)+1) * sizeof(WCHAR);
if ( lpwsPath != NULL )
cbVariableData += ( (STRLEN(lpwsPath)+1)*sizeof(WCHAR) );
pwchVariableData = (WCHAR*)LocalAlloc( LPTR, cbVariableData );
if ( pwchVariableData == NULL ) {
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
break;
}
pAfpVolumeInfo = (PAFP_BADVOLUME)LocalAlloc( LPTR,
sizeof(AFP_BADVOLUME));
if ( pAfpVolumeInfo == NULL ) {
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
break;
}
// Add the volume strucutre
//
pAfpVolumeInfo->Next = InvalidVolumeList.Head;
InvalidVolumeList.Head = pAfpVolumeInfo;
// Add the name and the path
//
STRCPY( (LPWSTR)pwchVariableData, lpwsName );
pAfpVolumeInfo->lpwsName = (LPWSTR)pwchVariableData;
if ( lpwsPath != NULL ) {
pwchVariableData += ( STRLEN( lpwsName ) + 1);
STRCPY( (LPWSTR)pwchVariableData, lpwsPath );
pAfpVolumeInfo->lpwsPath = (LPWSTR)pwchVariableData;
}
pAfpVolumeInfo->cbVariableData = cbVariableData;
InvalidVolumeList.cbTotalData += ( sizeof( AFP_VOLUME_INFO ) +
cbVariableData );
} while( FALSE );
if ( dwRetCode != NO_ERROR ) {
if ( pAfpVolumeInfo != NULL )
LocalFree( pAfpVolumeInfo );
if ( pwchVariableData != NULL ) {
LocalFree( pwchVariableData );
}
}
// MUTEX end
//
ReleaseMutex( hmutexInvalidVolume );
}
//**
//
// Call: AfpDeleteInvalidVolume
//
// Returns: none
//
// Description: Will delete a volume structure from the list of invalid
// volumes, if it is found.
//
VOID
AfpDeleteInvalidVolume(
IN LPWSTR lpwsVolumeName
)
{
PAFP_BADVOLUME pTmp;
PAFP_BADVOLUME pBadVolWalker;
// Walk the list and delete the volume structure
//
if ( InvalidVolumeList.Head != NULL ) {
if ( STRICMP( InvalidVolumeList.Head->lpwsName, lpwsVolumeName ) == 0 ){
pTmp = InvalidVolumeList.Head;
InvalidVolumeList.cbTotalData -= ( sizeof( AFP_VOLUME_INFO )
+ pTmp->cbVariableData );
InvalidVolumeList.Head = pTmp->Next;
LocalFree( pTmp->lpwsName );
LocalFree( pTmp );
}
else {
for( pBadVolWalker = InvalidVolumeList.Head;
pBadVolWalker->Next != NULL;
pBadVolWalker = pBadVolWalker->Next ) {
if ( STRICMP( pBadVolWalker->Next->lpwsName, lpwsVolumeName )
== 0 ) {
pTmp = pBadVolWalker->Next;
InvalidVolumeList.cbTotalData -= ( sizeof( AFP_VOLUME_INFO )
+ pTmp->cbVariableData );
pBadVolWalker->Next = pTmp->Next;
LocalFree( pTmp->lpwsName );
LocalFree( pTmp);
break;
}
}
}
}
}