////////////////////////////////////////////////////////
// File Name: FileHelperFunctions.cpp
//
//  Abstract: Helper functions for dealing with paths
//
////////////////////////////////////////////////////////

#include "stdafx.h"
#include "FileHelperFunctions.h"
#include "Sddl.h"

const TCHAR DirectorySeparatorChar = '\\';
const TCHAR AltDirectorySeparatorChar = '/';
const TCHAR VolumeSeparatorChar = ':';

/////////////////////////////////////////////////////////////////////////////
// Function       : GetDirectoryName
// Description    : Obtains the directory name from a file path.
// Return type    : CATLString - The directory name.
// Argument [In]  : const CATLString& PathWithFileName - The file path.
/////////////////////////////////////////////////////////////////////////////
CATLString GetDirectoryName(const CATLString& PathWithFileName)
{
	CATLString RetVal;
	int BackSlashIndex = -1;
	int ForwardSlashIndex = -1;

	BackSlashIndex = PathWithFileName.ReverseFind(_T('\\'));
	ForwardSlashIndex = PathWithFileName.ReverseFind(_T('/'));

	if(BackSlashIndex > -1 || ForwardSlashIndex > -1)
	{
		if(BackSlashIndex > ForwardSlashIndex)
		{
			RetVal = PathWithFileName.Left(BackSlashIndex + 1);
		}
		else
		{
			RetVal = PathWithFileName.Left(ForwardSlashIndex + 1);
		}
	}

	return RetVal;
}

/////////////////////////////////////////////////////////////////////////////
// Function       : IsPathRooted
// Description    : Checks if the path is rooted.
// Return type    : bool
// Argument [In]  : const CATLString& Path - The path.
/////////////////////////////////////////////////////////////////////////////
bool IsPathRooted(const CATLString& Path)
{
    int length = Path.GetLength();

    if (((length >= 1) && ((Path[0] == DirectorySeparatorChar) || (Path[0] == AltDirectorySeparatorChar))) || ((length >= 2) && (Path[1] == VolumeSeparatorChar)))
    {
        return true;
    }

    return false;
}

/////////////////////////////////////////////////////////////////////////////
// Function       : CombinePaths
// Description    : Combines two paths.
// Return type    : CATLString - The two paths combined.
// Argument [In]  : const CATLString& Path1 - The first path.
// Argument [In]  : const CATLString& Path2 - The second path.
/////////////////////////////////////////////////////////////////////////////
CATLString CombinePaths(const CATLString& Path1, const CATLString& Path2)
{
    if (Path2.GetLength() == 0)
    {
        return Path1;
    }

    if (Path1.GetLength() == 0)
    {
        return Path2;
    }

    if (IsPathRooted(Path2))
    {
        return Path2;
    }

    TCHAR ch = Path1[Path1.GetLength() - 1];

    if (((ch != DirectorySeparatorChar) && (ch != AltDirectorySeparatorChar)) && (ch != VolumeSeparatorChar))
    {
        return (Path1 + DirectorySeparatorChar + Path2);
    }

    return (Path1 + Path2);
}

/////////////////////////////////////////////////////////////////////////////
// Function       : CreateDirectoryFromFilePath
// Description    : Parses through a full file path for the directory and creates it.
// Return type    : void
// Argument [In]  : LPCTSTR szDir - The file path.
/////////////////////////////////////////////////////////////////////////////
void CreateDirectoryFromFilePath(LPCTSTR szDir)
{  
	TCHAR* pCurrentChar = NULL;
    CATLString TempPath(szDir);
    BOOL   MoreToProcess = TRUE;
    DWORD  LastError = ERROR_SUCCESS;

    pCurrentChar = (LPTSTR)(LPCTSTR)TempPath;

	//*******************************************************************
	//Setting security attributes for everyone and for admins
	LPCTSTR NewDirectorySDStr = TEXT("D:")
	TEXT("(A;OICI;GA;;;AU)")   // Everyone
	TEXT("(A;OICI;GA;;;BA)");  // Admins

	SECURITY_ATTRIBUTES NewDirectorySA;
	NewDirectorySA.nLength = sizeof(SECURITY_ATTRIBUTES);
	NewDirectorySA.bInheritHandle = FALSE;  
	::ConvertStringSecurityDescriptorToSecurityDescriptor(NewDirectorySDStr, SDDL_REVISION_1, &(NewDirectorySA.lpSecurityDescriptor), NULL);
	//*******************************************************************

    
	// Skip over any leading backslashes\forwardslashes.  A UNC pathname would contain two leading backslashes.
    while ( *pCurrentChar == _T('\\') || *pCurrentChar == _T('/') )
    {
        pCurrentChar = CharNext(pCurrentChar) ;
    }

    // Find the next backslash\forwardslash, change it to a null, create the directory path up to
    // that point and then continue.
    while ( *pCurrentChar != NULL ) 
    {
        if ( *pCurrentChar == _T('\\') || *pCurrentChar == _T('/') )
        {
            MoreToProcess = FALSE ;
            *pCurrentChar = NULL ;
            if ( CreateDirectory( TempPath, &NewDirectorySA ) == FALSE )
            {
                LastError = GetLastError() ;
            }
            else
            {
                LastError = ERROR_SUCCESS ;
            }
            *pCurrentChar = _T('\\') ;
        }
        else
        {
            MoreToProcess = TRUE ;
        }
        
        pCurrentChar = CharNext(pCurrentChar) ;
    }

    // If there was remaining directory path after the last backslash\forwardslash then create that
    // remaining directory.
    if ( MoreToProcess )
    {
		if(TempPath.ReverseFind(_T('.')) == -1)	//Don't create more if it is a filename.
		{
			if (CreateDirectory(TempPath, &NewDirectorySA) == FALSE )
			{
				LastError = GetLastError() ;
			}
			else
			{
				LastError = ERROR_SUCCESS ;
			}
		}
    }

	// Free the memory allocated for the SECURITY_DESCRIPTOR.
	LocalFree(NewDirectorySA.lpSecurityDescriptor);
}