/**@@@+++@@@@******************************************************************
**
** Microsoft Windows Media
** Copyright (C) Microsoft Corporation. All rights reserved.
**
***@@@---@@@@******************************************************************
*/

#undef __STRICT_ANSI__
#include <drmcommon.h>
#include <drmutilities.h>
#include <drmcrt.h>
#include <stdio.h>
#include <stdarg.h>
#include <oemimpl.h>
#include <DX_VOS_File.h>



static void PackedCharsToNative( DRM_CHAR *f_pPackedString, DRM_DWORD cch )
{
	DRM_DWORD ich;

	if( f_pPackedString == NULL
			|| cch == 0 )
	{
		return;
	}
    for( ich = cch; ich > 0; ich-- )
    {
        f_pPackedString[ich] = GET_CHAR( f_pPackedString, ich );
    }
    f_pPackedString[0]   = GET_CHAR( f_pPackedString, 0 ) ;
    f_pPackedString[cch] = '\0';
}

static DRM_BOOL FileExists (const DRM_CHAR *pszFileName)
{
    DxVosFile    pfile   = NULL;
    DRM_BOOL  bExists = FALSE;

	DX_VOS_FOpen(&pfile,pszFileName, "r");
    if (pfile != NULL)
    {
        bExists = TRUE;
        
        DX_VOS_FClose (pfile);
    }
    
    return bExists;
}

/*
** return 0xFFFFFFFF if failed
*/
OEM_FILEHDL DRM_API OEM_OpenFile(
    const DRM_WCHAR *pwszFileName,
    DRM_DWORD        fModeAccess,
    DRM_DWORD        fModeShare,
    DRM_DWORD        fModeCreateOpen,
    DRM_DWORD        fAttributes)
{
    DxVosFile      pfile    = OEM_INVALID_HANDLE_VALUE;
    DRM_CHAR  *pszMode = NULL;
    DRM_DWORD  fShare   = 0;
    DRM_BOOL   bOK      = FALSE;

    DRM_DWORD cch = 0;
    DRM_CHAR rgchFileName[DRM_MAX_PATH];    
    DRM_CHAR *pszFName = rgchFileName;

	int res;

    
    cch = DRM_wcslen( pwszFileName );
    DRM_UTL_DemoteUNICODEtoANSI( pwszFileName, rgchFileName, cch );
    PackedCharsToNative( rgchFileName, cch );

    if  (fModeCreateOpen == OEM_CREATE_NEW) 
    {
        DRMASSERT ((fModeAccess & OEM_GENERIC_WRITE) != 0);

        bOK = (FileExists (pszFName) == FALSE);

        pszMode = "w+b";
    }
    else if (fModeCreateOpen == OEM_TRUNCATE_EXISTING)
    {
        DRMASSERT ((fModeAccess & OEM_GENERIC_WRITE) != 0);

        bOK = FileExists (pszFName);

        pszMode = "w+b";
    }
    else if (fModeCreateOpen == OEM_CREATE_ALWAYS)
    {
        DRMASSERT ((fModeAccess & OEM_GENERIC_WRITE) != 0);

        bOK      = TRUE;
        pszMode = "w+b";
    }
    else if (fModeCreateOpen == OEM_OPEN_EXISTING)
    {
        if ((res = FileExists (pszFName)))
        {
            if (fModeAccess & OEM_GENERIC_WRITE)
            {
                pszMode = "r+b";
                bOK      = TRUE;
            }
            else if (fModeAccess & OEM_GENERIC_READ)
            {
                pszMode = "rb";
                bOK      = TRUE;
            }
            else
            {
                DRMASSERT (0);
            }
        }
    }
    else if (fModeCreateOpen == OEM_OPEN_ALWAYS)
    {
        pszMode = "a+b";
        bOK      = TRUE;
    }

	/* translate our I/O share flags to standard C's */
#if DRM_SUPPORT_LOCKING	
    if ((fModeShare & OEM_FILE_SHARE_WRITE)
    &&  (fModeShare & OEM_FILE_SHARE_READ))
    {
        fShare = _SH_DENYNO;
    }
    else if (fModeShare & OEM_FILE_SHARE_WRITE)
    {
        fShare = _SH_DENYRD;
    }
    else if (fModeShare & OEM_FILE_SHARE_READ)
    {
        fShare = _SH_DENYWR;
    }
    else
    {
        fShare = _SH_DENYRW;
    }

#endif
    if (bOK)
    {
		res = DX_VOS_FOpen(&pfile,pszFName, pszMode) ;
        if (pfile == NULL)
        {
            pfile = (DxVosFile) OEM_INVALID_HANDLE_VALUE;
        }
    }

    return (OEM_FILEHDL) pfile;
}

/*
**
*/
DRM_BOOL DRM_API OEM_CloseFile(
    OEM_FILEHDL hFile)
{
    return DX_VOS_FClose((DxVosFile)hFile)==0;
}


/*
**
*/
DRM_BOOL DRM_API OEM_ReadFile(
    OEM_FILEHDL hFile,
    DRM_VOID   *pBuffer,
    DRM_DWORD   cbRead,
    DRM_DWORD  *pcbRead)
{
	DxStatus rc;
    rc = DX_VOS_FReadEx((DxVosFile)hFile, pBuffer, 1*(DxUint32)cbRead, (pcbRead));
    if(rc != DX_SUCCESS)
    {
    	return FALSE;
    }
    return TRUE;
}

/*
**
*/
DRM_BOOL DRM_API OEM_WriteFile(
    OEM_FILEHDL hFile,
    DRM_VOID   *pBuffer,
    DRM_DWORD   cbWrite,
    DRM_DWORD  *pcbWritten)
{

	DxStatus rc;
    rc = DX_VOS_FWrite((DxVosFile)hFile,pBuffer, 1*(DxUint32)cbWrite);
    if(rc != DX_SUCCESS)
    {
	    *pcbWritten = 0x0;
    	return FALSE;
    }
	*pcbWritten = cbWrite;

    return TRUE;
}


/*
**
*/
DRM_BOOL DRM_API OEM_SetFilePointer(
    OEM_FILEHDL hFile,
    DRM_LONG    lDistanceToMove,
    DRM_DWORD   dwMoveMethod,
    DRM_DWORD  *pdwNewFilePointer)
{
    DRM_BOOL fResult = FALSE;
	DxStatus rc;
#if DRM_PROFILE_DRIVESEEK
    DRM_PROFILING_ENTER_SCOPE(L"OEM_SetFilePointer", g_pwszEnteringFunction, DRM_PROFILING_DONT_START);
#endif

#if DRM_SUPPORT_PROFILING
    g_contextPRO.dwNumSeeks++;
#endif

    rc = DX_VOS_FSeekEx((DxVosFile)hFile,lDistanceToMove,(DRM_INT)dwMoveMethod);
    if (rc != 0)
    {
    	return fResult;
    }
    else
    {
        if (pdwNewFilePointer!=NULL)
        {
            rc = DX_VOS_FTell((DxVosFile)hFile,pdwNewFilePointer);
		    if (rc != 0)
		    {
		    	return fResult;
		    }
        }
        fResult = TRUE;
    }

#if DRM_PROFILE_DRIVESEEK
    DRM_PROFILING_LEAVE_SCOPE(L"OEM_SetFilePointer", g_pwszLeavingFunction);
#endif
    return fResult;
}

/*
**
*/
DRM_BOOL DRM_API OEM_LockFile(
    OEM_FILEHDL hFile,
    DRM_BOOL    fExclusive,
    DRM_DWORD   dwFileOffset,
    DRM_DWORD   nNumberOfBytesToLock,
    DRM_BOOL    fWait)
{
#if DRM_SUPPORT_LOCKING
    DRM_INT flag = 0;

    flag = fWait? _LK_LOCK : _LK_NBLCK;

    if (fseek((FILE *)hFile, dwFileOffset, SEEK_SET) == 0 )
    {
        /* _locking does not support non-exclusive mode, we ignore fExclusive */
        if (_locking(_fileno((FILE *)hFile), flag, (DRM_LONG)nNumberOfBytesToLock)==0)
        {
            return TRUE;
        }
    }
    return FALSE;
#else
    return TRUE;
#endif
}

/*
**
*/
DRM_BOOL DRM_API OEM_UnlockFile(
    OEM_FILEHDL hFile,
    DRM_DWORD   dwFileOffset,
    DRM_DWORD   nNumberOfBytesToUnlock)
{
#if DRM_SUPPORT_LOCKING
    if (fseek((FILE *)hFile, dwFileOffset, SEEK_SET) == 0)
    {
        if (_locking(_fileno((FILE *)hFile), _LK_UNLCK, (DRM_LONG)nNumberOfBytesToUnlock)==0)
        {
            return TRUE;
        }
    }
    return FALSE;
#else
    return TRUE;
#endif
}


/*
**
*/
DRM_BOOL DRM_API OEM_SetEndOfFile(
    OEM_FILEHDL hFile)
{
    /* no CRT support */
    return FALSE;
}

/*
**
*/
DRM_BOOL DRM_API OEM_GetFileSize(
    OEM_FILEHDL hfile,
    DRM_DWORD  *pcbFile)
{
    DRM_DWORD oFileCurr = 0;
    DxVosFile pfile     = (DxVosFile) hfile;
    DxStatus  rc;
    DRMASSERT (pcbFile != NULL);
    DRMASSERT (hfile   != OEM_INVALID_HANDLE_VALUE);

    rc = DX_VOS_FTell (pfile,&oFileCurr);
	if(rc != 0x0)
	{
		return FALSE;
	}
	rc = DX_VOS_FSeekEx (pfile, 0, DX_SEEK_END);
    if (rc != 0)
    {
    	return FALSE;
    }
    
    rc = DX_VOS_FTell(pfile,pcbFile);
    if (rc != 0)
    {
    	return FALSE;
    }
	rc = DX_VOS_FSeekEx(pfile, oFileCurr, DX_SEEK_SET);
    if (rc != 0)
    {
    	return FALSE;
    }
    return TRUE;
}

/*
**
*/
DRM_BOOL DRM_API OEM_FlushFileBuffers(
    OEM_FILEHDL hFile)
{
    return DX_VOS_FFlush((DxVosFile)hFile)==0;
}


