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