long
C_File::FileSize()
{
	C_FileCritSect	cCS0( this, CRITSECT0 );
	int iFlag = FALSE;
	if( (_bIs32s && iFile == -1) || (!_bIs32s && hFile == INVALID_HANDLE_VALUE) ){
		if( ReOpen() != OK ){		   
			if( !_xFile ){
				return( -1 );
			}
			_xFile->PseudoClose();
			ReOpen();
			iFlag = TRUE;
		}
	}

	if( _bIs32s ){
		long lCurPosAux = CurPos();
		Seek( 0, SEEK_END );
		long lSize = CurPos();
		Seek( lCurPosAux, SEEK_SET );
		if( iFlag ){
			PseudoClose();
			_xFile->ReOpen();
		}
		return( lSize );
	}
	// guarda a posicao corrente
//	long	lCurPosAux = CurPos();

	DWORD	dwResult = GetFileSize( hFile, NULL );

/*	// vai para o fim do arquivo e pega o numero do ultimo byte
	dwResult = SetFilePointer( hFile, 0, NULL, FILE_END );
/*
	if( dwResult == 0XFFFFFFFF ){
		DWORD	dw = GetLastError();
		char	szErr[ 500 ];

		sprintf( szErr, "Erro no GetFileSize: %d", (int) dw );
		MessageBox( NULL, szErr, "DEBUG - LIFILE", MB_OK );
	}

	// volta para a posicao que estava
	Seek( lCurPosAux, SEEK_SET );
*/
	if( iFlag ){
		PseudoClose();
		_xFile->ReOpen();
	}
	return( (long) dwResult );
}
/***
	Metodo Release
	Libera um registro previamente travado

	Parameters:
		- pcfControlFile

	Return:
		LBS_OK se conseguir liberar ou erro.

	Comments:

***/
int
C_File::Release( long lSize )
{
	C_FileCritSect	cCS0( this, CRITSECT0 );
	if( (_bIs32s && iFile == -1) || (!_bIs32s && hFile == INVALID_HANDLE_VALUE) ){
		if( ReOpen() != OK ){		   
			return( E_NOTOPEN );
		}
	}
	LockStruct ls( this, CurPos(), lSize );
	return( DelLock( &ls ) );
}
/***
	PRIVATE
	RealLock

	Realiza um lock em uma regiao do arquivo, utilizando rotinas
	do Sistema Operacional
***/
int
C_File::RealLock( LockStruct *ls, BOOL bWait )
{
	C_FileCritSect	cCS0( this, CRITSECT0 );
	if( !bRealLock ){
		return( OK );
	}
	int	iRet = !OK;
	int	iFlag = FALSE;
	if( (_bIs32s && iFile == -1) || (!_bIs32s && hFile == INVALID_HANDLE_VALUE) ){
		if( ReOpen() != OK ){
			if( !_xFile ){
				return( !OK );
			}
			_xFile->PseudoClose();
			ReOpen();
			iFlag = TRUE;
		}
	}

	if( ls ){
		if( _bIs32s ){
			long lPos = CurPos();
			if( Seek( ls->iPos, SEEK_SET ) == OK ){
				iRet = locking( iFile, _LK_LOCK, ls->iSize );
			}
			Seek( lPos, SEEK_SET );
		} else {
			if( Seek( ls->iPos, SEEK_SET ) == OK ){
				DWORD	dwErr;

				SetLastError( 0 );
				iRet = LockFile( hFile, ls->iPos, 0, ls->iSize, 0 ) ? OK : !OK;
				dwErr = GetLastError();
				while( bWait && ((dwErr == ERROR_LOCK_FAILED) || (dwErr == ERROR_LOCK_VIOLATION)) ){
					// esperar e tentar novamente.
					cCS0.LeaveCriticalSection();
					Sleep( 1000 );	// 1 segundo
					cCS0.EnterCriticalSection();
					SetLastError( 0 );
					iRet = LockFile( hFile, ls->iPos, 0, ls->iSize, 0 ) ? OK : !OK;
					dwErr = GetLastError();
				}
			}
		}
	}
	if( iFlag ){
		PseudoClose();
		_xFile->ReOpen();
	}
	return( iRet );
}
/***
	PRIVATE
	GrowFile

	Aumenta o tamanho do arquivo para lNewSize bytes.
	E' possivel que os buffers MMF sejam resetados (pWinView e pHeadView).
	E' interessante que o chamador deste metodo reavalie a necessidade de fazer
	um novo mapeamento do arquivo em MMF (refazer pWinView e pHeadView).
***/
int
C_File::GrowFile( long lNewSize )
{
	// guarda posicao atual
	long	lCPos = CurPos();

	// o seek abaixo ja' faz o arquivo crescer
	int		iRet = Seek( lNewSize, SEEK_SET );

	// volta para a posicao que estava
	Seek( lCPos, SEEK_SET );

	return( iRet );
}
/***
	Retorna TRUE se houve tentativa de lock em uma regiao depois que a mesma
	ja' estava travada.
***/
BOOL
C_File::TryUse()
{
	LockStruct	ls( this, CurPos(), 0L );

	C_FileCritSect	cCS0( this, CRITSECT0 );
	LockList &l = *(_LockTable[ iLine ]);
	for( int i = 0; i < l.NumElem(); i++ ){
		LockStruct *lsAux = l [ i ];
		if( lsAux->pcfFile == ls.pcfFile && lsAux->iPos == ls.iPos && lsAux->bTryUse == TRUE ){
			return( TRUE );
		}
	}
	return( FALSE );
}
int
C_File::PseudoClose( void )
{
	C_FileCritSect	cCS0( this, CRITSECT0 );
	if( (_bIs32s && iFile == -1) || (!_bIs32s && hFile == INVALID_HANDLE_VALUE) ){
		return( OK );
	}
#ifdef _USE_PRINTF_
	if( this == _xFile ){
		Printf( "C_File: Estou (pseudo) fechando o _xFile****************************" );
	}
#endif
	lCurPos = CurPos();
	Close();
	bReOpen = TRUE;
	return( OK );
}
/***
	Metodo Lock
	Trava o registro

	Parameters:
		- pcfControlFile

	Return:
		LBS_OK se conseguir travar ou erro.

	Comments:

***/
int
C_File::Lock( long lSize, BOOL bWait )
{
//	C_FileCritSect	cCS0( this, CRITSECT0 );
	if( (_bIs32s && iFile == -1) || (!_bIs32s && hFile == INVALID_HANDLE_VALUE) ){
		if( ReOpen() != OK ){		   
			return( E_NOTOPEN );
		}
	}

	LockStruct *ls = new LockStruct( this, CurPos(), lSize );
	if( ls ){
		if( AddLock( ls, bWait ) == OK ){
			return( OK );
		}
		delete ls;
	}
	return( !OK );
}
bool DirectShowVideoWrapper::seek(Real64 SeekPos)
{
    if(isInitialized())
    {
		HRESULT hr;
        TCHAR szErr[MAX_ERROR_TEXT_LEN];

        Real64 CurPos(getPosition());
        if((SeekPos < CurPos) &&
            (!canSeekBackward()))
        {
            SWARNING << "Unable to seek backwards on this type of media." << std::endl;
			return false;
        }
        if((SeekPos > CurPos) &&
            (!canSeekForward()))
        {
            SWARNING << "Unable to seek forwards on this type of media." << std::endl;
			return false;
        }

		CComPtr<IMediaPosition> mediaPosition;
		hr = _pGraphBuilder->QueryInterface(&mediaPosition);
		if (FAILED(hr))
        {
            AMGetErrorText(hr, szErr, MAX_ERROR_TEXT_LEN);
            SWARNING << "Unable to get IMediaPosition, error: " << szErr << std::endl;
			return false;
		}

		hr = mediaPosition->put_CurrentPosition(SeekPos);
		if (FAILED(hr))
        {
            AMGetErrorText(hr, szErr, MAX_ERROR_TEXT_LEN);
            SWARNING << "Unable to set position to value: " << SeekPos << ", error: " << szErr << std::endl;
			return false;
		}

		return true;
	}
	return false;
}
/***
	PRIVATE
	RealRelease

	Realiza um unlock em uma regiao do arquivo, utilizando rotinas
	do Sistema Operacional
***/
int
C_File::RealRelease( LockStruct *ls )
{
	C_FileCritSect	cCS0( this, CRITSECT0 );
	if( !bRealLock ){
		return( OK );
	}
	int	iRet = !OK;
	int	iFlag = FALSE;
	if( (_bIs32s && iFile == -1) || (!_bIs32s && hFile == INVALID_HANDLE_VALUE) ){
		if( ReOpen() != OK ){
			if( !_xFile ){
				return( !OK );
			}
			_xFile->PseudoClose();
			ReOpen();
			iFlag = TRUE;
		}
	}

	if( ls ){
		if( _bIs32s ){
			long lPos = CurPos();
			if( Seek( ls->iPos, SEEK_SET ) == OK ){
				iRet = locking( iFile, _LK_UNLCK, ls->iSize );
			}
			Seek( lPos, SEEK_SET );
		} else {
			if( Seek( ls->iPos, SEEK_SET ) == OK ){
				iRet = UnlockFile( hFile, ls->iPos, 0, ls->iSize, 0 ) ? OK : !OK;
			}
		}
	}
	if( iFlag ){
		PseudoClose();
		_xFile->ReOpen();
	}
	return( iRet );
}
/***
	Write bytes in a file from a given buffer.
	Parameters:
		- pvBuf: User buffer with data to write in file
		- tsSize: Size of iten to write
		- tsNumItens: Number of itens to write
	Return:
		Number of writtem itens in succes or E_NOTOPEN,
		E_BUFFNULL or E_WRITE.
***/
size_t
C_File::Write( void FAR *pvBuf, size_t tsSize, size_t tsNumItens )
{
	C_FileCritSect	cCS0( this, CRITSECT0 );

	size_t	i = 0;
	BOOL	bContinue = TRUE;


#ifdef _USE_PRINTF_
	Printf( "C_File: Estou em Write. (arq %s)", szFileName );
#endif
	int iFlag = FALSE;
	if( !pvBuf ){
		return( (size_t) E_BUFFNULL );
	}
	if( (_bIs32s && iFile == -1) || (!_bIs32s && hFile == INVALID_HANDLE_VALUE) ){
		if( ReOpen() != OK ){		   
			if( !_xFile ){
				return( 0 );
			}
			_xFile->PseudoClose();
			ReOpen();		   
			iFlag = TRUE;
		}
	}
	LockStruct ls( this, CurPos(), (tsSize * tsNumItens) );
	if( IsLocked( &ls ) ){
		if( iFlag ){
			PseudoClose();
			_xFile->ReOpen();
		}
#ifdef _USE_PRINTF_
		Printf( "C_File: Write: IsLocked." );
#endif
		return( (size_t) E_WRITE );
	}

	if( cCriptoOn ){
		Encrypt( pvBuf, szKey, tsSize );
	}

	// MMF
	BOOL	bWriteHeader = FALSE;
	if( !_bIs32s && hMMF ){
		// preparar gravacao a partir do MMF

		long	lFSize = FileSize();
		long	lCPos = CurPos();
		if( ( lCPos + (int) (tsNumItens * tsSize) ) > lFSize ){
			// este write vai exceder os limites do arquivo. vamos aumentar-lo.
			if( GrowFile( lCPos + (tsNumItens * tsSize) ) != OK ){
				// nao foi possivel aumentar o arquivo.
				bContinue = FALSE;
			}
		}
		if( bContinue ){
			if( (lCPos == iHeadInit)  && (((int) tsSize) == iHeadSize) ){
				bWriteHeader = TRUE;
				// vamos fazer write no header do arquivo.
				if( !pHeadView ){
					// o header ainda nao esta' mapeado. vamos fazer isso.
					CreateViewOfHead();
				}
			} else {
				if( !pWinView ){
					// o arquivo ainda nao esta' mapeado. vamos fazer isso.
					CreateViewOfFile();
				}
			}
		}
	}

	if( bContinue ){
		for( i = 0; i < tsNumItens; i++ ){
			if( _bIs32s ){
				if( write( iFile, pvBuf, (unsigned) tsSize ) < (int) tsSize ){
					break;
				}
			} else {
				if( bWriteHeader ){
					// gravar header no MMF.
					memcpy( pHeadView, pvBuf, tsSize );
				} else {
					if( pWinView ){
						// gravar no MMF.
						int	iNumBytes = ((iMMFWinSize * iPageSize) - iSeekWin) - (iHeadSize + 1);
						memcpy( (void*) ((char*) PWINVIEW + iSeekWin), pvBuf, min( iNumBytes, ((int) tsSize) ) );
						if( iNumBytes < ((int) tsSize) ){
							// precisamos mapear outra janela e continuar a gravacao
							++iWinNum;	// proxima janela
							CreateViewOfFile();
							if( !pWinView ){
								// mapeamento nao foi feito. fudeu.
								break;
							}
							// gravacao do restante
							memcpy( (void*) ((char*) PWINVIEW + iSeekWin), (void*) ((char*) pvBuf + iNumBytes), (tsSize - iNumBytes) );
							iSeekWin += (tsSize - iNumBytes);
						} else {
							iSeekWin += tsSize;
						}
					} else {
						DWORD	dwWrittenBytes;
						BOOL	bResult = WriteFile( hFile, pvBuf, (unsigned) tsSize, &dwWrittenBytes, NULL );
						if( !bResult || ( dwWrittenBytes < tsSize ) ){
							DWORD	dwErr = GetLastError();
							break;
						}
					}
				}
			}
		}
	}
//	if( ::GetTypeInt() == PE_REDE ){
//		Flush();
//	}
	dwLastUse = GetTickCount();
	if( cCriptoOn ){
		Decrypt( pvBuf, szKey, tsSize );
	}
	if( i < tsNumItens ){
#ifdef _USE_PRINTF_
		Printf( "C_File: Write: E_WRITE." );
#endif
		i = (size_t) E_WRITE;
	}
	if( iFlag ){
		PseudoClose();
		_xFile->ReOpen();
	}
#ifdef _USE_PRINTF_
	Printf( "C_File: Write: Vou retornar %d.", i );
#endif
	return( i );
}
/***
	Read bytes from a file to a buffer.
	Parameters:
		- pvBuf: User buffer. Contains the result of a read.
		- tsSize: Size of iten to read
		- tsNumItens: Number of itens to read
	Return:
		- O numero de itens lidos (nao o numero de bytes). Em caso
		de erro: E_NOTOPEN or E_BUFFNULL or EOF.
***/
size_t
C_File::Read( void FAR *pvBuf, size_t tsSize, size_t tsNumItens )
{
	C_FileCritSect	cCS0( this, CRITSECT0 );
	int iFlag = FALSE;
	if( !pvBuf ){
		return( (size_t) E_BUFFNULL );
	}
	if( (_bIs32s && iFile == -1) || (!_bIs32s && hFile == INVALID_HANDLE_VALUE) ){
		if( ReOpen() != OK ){
			if( !_xFile ){
				return( 0 );
			}
			_xFile->PseudoClose();
			ReOpen();
			iFlag = TRUE;
		}
	}
	// MMF
	BOOL	bReadHeader = FALSE;
	if( !_bIs32s && hMMF ){
		// preparar leitura a partir do MMF
		if( (CurPos() == iHeadInit)  && ((int) tsSize == iHeadSize) ){
			bReadHeader = TRUE;
			// vamos fazer read no header do arquivo.
			if( !pHeadView ){
				// o header ainda nao esta' mapeado. vamos fazer isso.
				CreateViewOfHead();
			}
		} else {
			if( !pWinView ){
				// o arquivo ainda nao esta' mapeado. vamos fazer isso.
				CreateViewOfFile();
			}
		}
	}

	for( size_t i = 0; i < tsNumItens; i++ ){
		if( _bIs32s ){
			if( read( iFile, ( char *) pvBuf + tsSize * i, tsSize ) < (int) tsSize ){
				break;
			}
		} else {
			if( bReadHeader ){
				// ler header a partir do MMF.
				memcpy( pvBuf, pHeadView, tsSize );
			} else {
				if( pWinView ){
					// ler a partir do MMF.
					int	iNumBytes = ((iMMFWinSize * iPageSize) - iSeekWin) - (iHeadSize + 1);
					memcpy( (void*) (( char *) pvBuf + tsSize * i), (void*) ((char*) PWINVIEW + iSeekWin), 
							min( iNumBytes, ((int) tsSize) ) );
					if( iNumBytes < ((int) tsSize) ){
						// precisamos mapear outra janela e continuar a leitura
						++iWinNum;	// proxima janela
						CreateViewOfFile();
						if( !pWinView ){
							// mapeamento nao foi feito. vamos assumir fim-de-arquivo.
							break;
						}
						// ler o restante
						memcpy( (void*) ((( char *) pvBuf + tsSize * i) + iNumBytes), (void*) ((char*) PWINVIEW + iSeekWin), 
								(tsSize - iNumBytes) );

						iSeekWin += (tsSize - iNumBytes);
					} else {
						iSeekWin += tsSize;
					}
				} else {
					// ler direto do arquivo
					DWORD	dwReadBytes;
					BOOL	bResult = ReadFile( hFile, ( char *) pvBuf + tsSize * i, tsSize, &dwReadBytes, NULL );
					if( !bResult || ( dwReadBytes  < tsSize ) ){
						break;
					}
				}
			}
		}
	}
	dwLastUse = GetTickCount();
	if( cCriptoOn && i >= tsNumItens ){
		Decrypt( pvBuf, szKey, tsSize * tsNumItens );
	}
	if( i < tsNumItens ){
		i = (size_t) EOF;
	}
	if( iFlag ){
		PseudoClose();
		_xFile->ReOpen();
	}
	return( i );
}