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

351 lines
7.8 KiB
C

/********************************************************************/
/** Copyright(c) 1989 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: finder.c
//
// Description: This module contains support routines for the finder
// category API's for the AFP server service
//
// History:
// Sept 30,1993. NarenG Created original version.
//
#include "afpsvcp.h"
BOOL
IsTargetNTFS(
IN LPWSTR lpwsPath
);
DWORD
CopyStream(
IN HANDLE hSrc,
IN HANDLE hDst
);
#define AFP_RESC_STREAM TEXT(":AFP_Resource")
//**
//
// Call: AfpAdminrFinderSetInfo
//
// Returns: NO_ERROR
// ERROR_ACCESS_DENIED
// non-zero returns from AfpServerIOCtrl
//
// Description: This routine communicates with the AFP FSD to implement
// the AfpAdminFinderSetInfo function.
//
DWORD
AfpAdminrFinderSetInfo(
IN AFP_SERVER_HANDLE hServer,
IN LPWSTR pType,
IN LPWSTR pCreator,
IN LPWSTR pData,
IN LPWSTR pResource,
IN LPWSTR pTarget,
IN DWORD dwParmNum
)
{
AFP_REQUEST_PACKET AfpSrp;
DWORD dwRetCode = NO_ERROR, dwRetryCount = 0;
AFP_FINDER_INFO AfpFinderInfo;
LPBYTE pAfpFinderInfoSR = NULL;
DWORD cbAfpFinderInfoSRSize;
DWORD dwAccessStatus=0;
HANDLE hTarget = INVALID_HANDLE_VALUE;
HANDLE hDataSrc = INVALID_HANDLE_VALUE;
HANDLE hResourceSrc = INVALID_HANDLE_VALUE;
LPWSTR lpwsResourceFork;
BOOLEAN fCreatedFile = FALSE;
// Check if caller has access
//
if ( dwRetCode = AfpSecObjAccessCheck( AFPSVC_ALL_ACCESS, &dwAccessStatus))
{
AFP_PRINT(( "SFMSVC: AfpAdminrFinderSetInfo, 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: AfpAdminrFinderSetInfo, AfpSecObjAccessCheck returned %ld\n",dwAccessStatus));
return( ERROR_ACCESS_DENIED );
}
if ( wcsstr( pTarget, (LPWSTR)TEXT(":\\") ) == NULL )
return( ERROR_INVALID_NAME );
if ( !IsTargetNTFS( pTarget ) )
return( (DWORD)AFPERR_UnsupportedFS );
//
// Impersonate the client while we read/write the fork data
//
dwRetCode = RpcImpersonateClient( NULL );
if ( dwRetCode != RPC_S_OK )
{
return(I_RpcMapWin32Status( dwRetCode ));
}
// open the data source file if one was specified
//
if ( STRLEN( pData ) > 0 ){
hDataSrc = CreateFile(pData, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDataSrc == INVALID_HANDLE_VALUE) {
RpcRevertToSelf();
return( GetLastError() );
}
// open the target file's data stream if the file exists,
// otherwise create the file
//
hTarget = CreateFile(pTarget, GENERIC_WRITE, FILE_SHARE_READ, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hTarget == INVALID_HANDLE_VALUE) {
dwRetCode = GetLastError();
CloseHandle(hDataSrc);
RpcRevertToSelf();
return( dwRetCode );
}
// Figure out if we just created a new file
if (GetLastError() == 0)
{
fCreatedFile = TRUE;
}
SetFilePointer(hTarget,0,NULL,FILE_BEGIN);
SetEndOfFile(hTarget);
// Read the source data and write it to target data stream
//
SetLastError(NO_ERROR);
dwRetCode = CopyStream(hDataSrc, hTarget);
CloseHandle(hDataSrc);
CloseHandle(hTarget);
if (dwRetCode != NO_ERROR) {
RpcRevertToSelf();
return( dwRetCode );
}
}
// open the resource source file if one was specified
//
if ( STRLEN( pResource ) > 0 ) {
hResourceSrc = CreateFile( pResource, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);
if (hResourceSrc == INVALID_HANDLE_VALUE) {
RpcRevertToSelf();
return( GetLastError() );
}
lpwsResourceFork = LocalAlloc( LPTR,
(STRLEN(pTarget)+
STRLEN(AFP_RESC_STREAM)+1)
* sizeof( WCHAR ) );
if ( lpwsResourceFork == NULL ) {
CloseHandle(hResourceSrc);
RpcRevertToSelf();
return( ERROR_NOT_ENOUGH_MEMORY );
}
// Open the target resource fork
//
STRCPY(lpwsResourceFork, pTarget );
STRCAT(lpwsResourceFork, AFP_RESC_STREAM);
hTarget = CreateFile(lpwsResourceFork, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hTarget == INVALID_HANDLE_VALUE) {
dwRetCode = GetLastError();
LocalFree( lpwsResourceFork );
CloseHandle(hResourceSrc);
RpcRevertToSelf();
return( dwRetCode );
}
LocalFree( lpwsResourceFork );
// Assume we created a new file (datafork) in the process, there is
// no way to tell for sure since creating a new resource fork will
// not tell us whether or not the datafork already existed or not
fCreatedFile = TRUE;
// Read the source resource and write it to target resource stream
//
SetLastError(NO_ERROR);
dwRetCode = CopyStream(hResourceSrc, hTarget);
CloseHandle(hResourceSrc);
CloseHandle(hTarget);
if (dwRetCode != NO_ERROR) {
RpcRevertToSelf();
return( dwRetCode );
}
}
//
// Revert back to LocalSystem context
//
RpcRevertToSelf();
if ( dwParmNum & ( AFP_FD_PARMNUM_TYPE | AFP_FD_PARMNUM_CREATOR ) ){
dwRetCode = NO_ERROR;
AfpFinderInfo.afpfd_path = pTarget;
if ( dwParmNum & AFP_FD_PARMNUM_TYPE )
STRCPY( AfpFinderInfo.afpfd_type, pType );
else
AfpFinderInfo.afpfd_type[0] = TEXT( '\0' );
if ( dwParmNum & AFP_FD_PARMNUM_CREATOR )
STRCPY( AfpFinderInfo.afpfd_creator, pCreator );
else
AfpFinderInfo.afpfd_creator[0] = TEXT( '\0' );
// Make this buffer self-relative.
//
if ( dwRetCode = AfpBufMakeFSDRequest((LPBYTE)&AfpFinderInfo,
sizeof(SETINFOREQPKT),
AFP_FINDER_STRUCT,
&pAfpFinderInfoSR,
&cbAfpFinderInfoSRSize ))
return( dwRetCode );
// Make IOCTL to set info
//
AfpSrp.dwRequestCode = OP_FINDER_SET;
AfpSrp.dwApiType = AFP_API_TYPE_SETINFO;
AfpSrp.Type.SetInfo.pInputBuf = pAfpFinderInfoSR;
AfpSrp.Type.SetInfo.cbInputBufSize = cbAfpFinderInfoSRSize;
AfpSrp.Type.SetInfo.dwParmNum = dwParmNum;
// Since there will be a delay between the time the change
// notify comes into the server for the new file, and the
// time it is actually processed by the server, we need to
// put in a delay and retry to give the server a chance to
// cache the new file
if (fCreatedFile)
{
Sleep( 2000 );
}
do
{
dwRetCode = AfpServerIOCtrl( &AfpSrp );
if (dwRetCode != ERROR_PATH_NOT_FOUND)
{
break;
}
Sleep( 2000);
} while ( ++dwRetryCount < 4 );
LocalFree( pAfpFinderInfoSR );
}
return( dwRetCode );
}
DWORD
CopyStream(
IN HANDLE hSrc,
IN HANDLE hDst
)
{
DWORD bytesread, byteswritten, Status = NO_ERROR;
BYTE Buffer[1024 * 16];
do
{
bytesread = byteswritten = 0;
// read from src, write to dst
//
if (ReadFile(hSrc, Buffer, sizeof(Buffer), &bytesread, NULL))
{
if (bytesread == 0)
{
break;
}
}
else
{
Status = GetLastError();
break;
}
if (!WriteFile(hDst, Buffer, bytesread, &byteswritten, NULL))
{
Status = GetLastError();
break;
}
} while (TRUE);
return(Status);
}
BOOL
IsTargetNTFS(
IN LPWSTR lpwsPath
)
{
WCHAR wchDrive[5];
DWORD dwMaxCompSize;
DWORD dwFlags;
WCHAR wchFileSystem[10];
// Get the drive letter, : and backslash
//
ZeroMemory( wchDrive, sizeof( wchDrive ) );
STRNCPY( wchDrive, lpwsPath, 3 );
if ( !( GetVolumeInformation( (LPWSTR)wchDrive,
NULL,
0,
NULL,
&dwMaxCompSize,
&dwFlags,
(LPWSTR)wchFileSystem,
sizeof( wchFileSystem ) ) ) ){
return( FALSE );
}
if ( STRICMP( wchFileSystem, TEXT("NTFS") ) == 0 )
return( TRUE );
else
return( FALSE );
}