/*
 =======================================================================================
  Name        :MajData.cpp
 
  Author      :vincent lhullie              Date :21/07/97
 
  Description : High level functions to update Vss data base
 =======================================================================================
  Modification -> Author :                  Date :
  Description :
 =======================================================================================
 */

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#include "stdafx.h"
#include "majdata.h"
#include "error.h"
#include "inidata.h"
#include "DlgConfl.h"
#include "DlgUpdOp.h"
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/*
 =======================================================================================
	Globals
 =======================================================================================
 */

char			g_szVssFileName[ MAX_PATH ];	// info on checked out file
tdstFileInfo	g_stTarget;						// info on target (vss) section
tdstFileInfo	g_stSource;						// info on source (local) section
char			g_cDeleteSectionModif;			
char			g_cAddModifiedFile;


/*
 =======================================================================================
	Functions to create semaphore file 
 =======================================================================================
 */

/*
 ---------------------------------------------------------------------------------------
  Description : function that create the InUpdate semaphore file
 ---------------------------------------------------------------------------------------
 */
void fn_vCreateInUpdateSemFile( char *szName )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	FILE *hpFile;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	hpFile = fopen( szName, "wt" );
	fprintf( hpFile, "*******************************************\n");
	fprintf( hpFile, "* >>>>>>>>>>>>>  WARNING  <<<<<<<<<<<<<<< *\n");
	fprintf( hpFile, "*******************************************\n");
	fprintf( hpFile, "* This file is used to know if someone is *\n");
	fprintf( hpFile, "* updating the data base. If this file is *\n");
	fprintf( hpFile, "* extract it's the case and nobody else   *\n");
	fprintf( hpFile, "* can update or obtain data               *\n");
	fprintf( hpFile, "*******************************************\n");
	fclose( hpFile );
}

/*
 ---------------------------------------------------------------------------------------
  Description : function that create the InObtain semaphore file
 ---------------------------------------------------------------------------------------
 */
void fn_vCreateInObtainFile( char *szName )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	FILE *hpFile;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	hpFile = fopen( szName, "wt" );
	fprintf( hpFile, "*******************************************\n");
	fprintf( hpFile, "* >>>>>>>>>>>>>  WARNING  <<<<<<<<<<<<<<< *\n");
	fprintf( hpFile, "*******************************************\n");
	fprintf( hpFile, "* This file is used to know if someone is *\n");
	fprintf( hpFile, "* obtaining the data base. If this file is*\n");
	fprintf( hpFile, "* extract it's the case and no one can    *\n");
	fprintf( hpFile, "* update. Because there can be more than  *\n");
	fprintf( hpFile, "* one obtaning at the same time, this file*\n");
	fprintf( hpFile, "* can be in multiple extraction           *\n");
	fprintf( hpFile, "*******************************************\n");
	fclose( hpFile );
}

/*
 =======================================================================================
	function to manage section : read, build, save
 =======================================================================================
 */

/*
 ---------------------------------------------------------------------------------------
  Description : read desired section and section des
 ---------------------------------------------------------------------------------------
 */
BOOL fn_bGetSection( tdstFileInfo *p_stFI, char *p_szSectionName )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char		szFullSectionName[MAX_PATH];
	char		*p_cCur, *szEndLine;
	BOOL		bDate;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/* 
	 * get section desc for file info and section name
	 */
	sprintf( szFullSectionName, "%s^%s", p_stFI->szFullName, p_szSectionName );
	p_stFI->p_stSection = fnp_st_Anl_SearchSectionDes( p_stFI->p_stFile, szFullSectionName, 0);
    p_stFI->oTime.SetDate( 100, 1, 1 );
	if (p_stFI->p_stSection == NULL)
		return FALSE;
	
	/* 
	 * get entire source section 
	 */
	p_stFI->lSize = p_stFI->p_stSection->stEndPosition.lAfterSeekInFile - p_stFI->p_stSection->stBeginPosition.lAfterSeekInFile;
	p_stFI->p_cBuffer = (char *) malloc (p_stFI->lSize + 1);
	SCR_M_File_Seek( &p_stFI->p_stFile->stFile, p_stFI->p_stSection->stBeginPosition.lAfterSeekInFile, SEEK_SET );
	p_stFI->lSize = SCR_M_fread( p_stFI->p_cBuffer, 1, p_stFI->lSize, &p_stFI->p_stFile->stFile);
	p_stFI->p_cBuffer[p_stFI->lSize] = 0;

	/* 
	 * retrieve section date 
	 */
	bDate = FALSE;
	p_cCur = strchr(p_stFI->p_cBuffer, ';');
	if (p_cCur != NULL)
	{
		p_cCur++;
		if ( (szEndLine = strchr( p_cCur, 0x0D)) != NULL )
			*szEndLine = 0;
		
		if ( strlen( p_cCur ) >= 16 )
		{
			if (p_cCur[ 16 ] == 0)
			{
				bDate = p_stFI->oTime.ParseDateTime( p_cCur );
				strcpy( p_stFI->szLastUserName, "Unknow" );
			}
			else if (p_cCur[ 16 ] == ' ')
			{
				p_cCur[16] = 0;
				bDate = p_stFI->oTime.ParseDateTime( p_cCur );
				strcpy( p_stFI->szLastUserName, p_cCur + 17 );
				p_cCur[16] = ' ';
			}
		}
		
		if (szEndLine !=NULL)
			*szEndLine = 0x0D;
	}
	if ( !bDate )
	{
		p_stFI->oTime.SetDate( 100, 1, 1 );
		strcpy( p_stFI->szLastUserName, "Unknow" );
	}

	return TRUE;
}

/*
 ---------------------------------------------------------------------------------------
  Description : Check if parent section of a section exist
 ---------------------------------------------------------------------------------------
 */
BOOL fn_bCheckParentSection( tdstFileInfo *p_stFI, char *p_szSectionName )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char					szParentSectionName[MAX_PATH];
	char					*p_cCur;
	SCR_tdst_Anl_SectionDes	*p_stParentSection;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/* 
	 * get section desc for file info and section name
	 */
	if ( (p_cCur = strrchr( p_szSectionName, '^' )) == NULL )
		return TRUE;
	*p_cCur = 0;
	sprintf( szParentSectionName, "%s^%s", p_stFI->szFullName, p_szSectionName );
	*p_cCur = '^';
	p_stParentSection = fnp_st_Anl_SearchSectionDes( p_stFI->p_stFile, szParentSectionName, 0);
    
	return (p_stParentSection != NULL);
}


/*
 ---------------------------------------------------------------------------------------
  Description : read a comment line in script file
 ---------------------------------------------------------------------------------------
 */
BOOL fn_bGetCommentLine( SCR_tdst_File_Description *p_stFile, char *szLine )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	int iRead;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	SCR_M_Pars_GetNextNonSpaceChar(p_stFile, iRead);
	if ((iRead == SCR_CC_c_Cfg_CommentMark) || (iRead == SCR_CC_c_Cfg_CommentMark1))
	{
        while((iRead != '\n') && (iRead != EOF))
        {
			if (szLine != NULL)
				*szLine++ = (char) iRead;
            SCR_M_Pars_ReadChar(p_stFile, iRead);
        }
		return TRUE;
	}
	return FALSE;
}

			
/*
 ---------------------------------------------------------------------------------------
  Description : save a section
 ---------------------------------------------------------------------------------------
 */
void fn_vSaveSection(SCR_tdst_File_Description *p_stFile, char *szSectionName, void *p_vData, SCR_tde_Ntfy_Action eAction)
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char						*p_cSection = (char *)p_vData;
	char						*p_cCur = p_cSection;
	SCR_tdst_Anl_SectionDes		*p_stSection;
	SCR_tdst_File_Open			*p_stOpenFile;
	char						szCommentLine[SCR_CV_ui_Cfg_MaxLenLine];
	char						szIndent[100];
	BOOL						bAlreadyADate;
	struct tm					stTime;
	char						*p_cSectionSeparation;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/*
	 * If it's a new section or subsection file pointer is on father section beginning
	 * we deplace file pointer to the end of section
	 * if father section isn't the file we must go one line back to set file pointer
	 * before the end of section (before the '}' character )
	 */
	if (eAction == SCR_EA_Ntfy_AddSection)
	{
		SCR_fn_v_SvL1_ToEndSection( p_stFile );
		p_cSectionSeparation = strchr( szSectionName, '^' );
		if (p_cSectionSeparation != NULL)
		{
			p_cSectionSeparation = strchr( p_cSectionSeparation + 1, '^' );
			if (p_cSectionSeparation != NULL)
			{
				SCR_fn_v_SvL1_ToPrevLine( p_stFile );
			}
		}
	}

	/*
	 * write section (or sub-section)
	 */
	while (*p_cCur != 0)
	{
		if (*p_cCur != '\r')
			fn_v_SvL0_fputc( p_stFile, *p_cCur );
		p_cCur ++;
	}
	fn_v_SvL0_fputc( p_stFile, '\n' );
	free( p_cSection );

	/*
	 * if parent section exist save updating time for parent section too
	 */
	memset ( szIndent, '\t', 100 );
	p_stOpenFile = SCR_fnp_st_RdL0_GetOpenFile( p_stFile->a_szFileName );
	*strrchr( szSectionName, '^' ) = 0;
	p_stSection = fnp_st_Anl_SearchSectionDes( p_stOpenFile, szSectionName, 0);
	while( p_stSection != NULL)
	{
		szIndent[p_stSection->stBeginPosition.uiLevel - 1] = 0;
		SCR_M_File_Seek( p_stFile, p_stSection->stBeginPosition.lAfterSeekInFile, SEEK_SET );
		/*
		 * look if there's already a date in section beginning, if so delete line
		 */
		bAlreadyADate = FALSE;
		if (fn_bGetCommentLine( p_stFile, szCommentLine ) )
			bAlreadyADate = fn_bReadDate( szCommentLine + 1, &stTime );
		SCR_M_File_Seek( p_stFile, p_stSection->stBeginPosition.lAfterSeekInFile, SEEK_SET );
		if (bAlreadyADate)
			SCR_fn_v_SvL1_DeleteLine( p_stFile );
		
		/*
		 * save date for parent section
		 */
		SCR_fn_v_SvL0_SaveWord( p_stFile, SCR_CC_C_Cfg_NoChar, szIndent ,SCR_CC_C_Cfg_NoChar );
		//SCR_fn_v_SvL0_SaveWord( p_stFile, SCR_CC_c_Cfg_CommentMark, g_szUpdateTimeString ,SCR_CC_C_Cfg_EOL );
		SCR_fn_v_SvL0_SaveWord( p_stFile, SCR_CC_c_Cfg_CommentMark, g_szUpdateTimeString ,' ' );
		SCR_fn_v_SvL0_SaveWord( p_stFile, SCR_CC_C_Cfg_NoChar, g_stIniData.szVssUserName ,SCR_CC_C_Cfg_EOL );
		p_stSection = p_stSection->p_stParentSection;
	}

}

/*
 ---------------------------------------------------------------------------------------
  Description build a section from a SectionDes
 ---------------------------------------------------------------------------------------
 */
char *fn_p_cBuildSection( tdstFileInfo  *p_stFI, BOOL _bCurrentTime )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	long lSize;
	char *p_cBuf;
	char *p_cCur;
	char *p_szParam;
	SCR_tdst_Cxt_DynBuffers	*p_stBuf = &p_stFI->p_stSection->stBuffers;
	SCR_tdst_Anl_SectionDes *p_stParentSection  = p_stFI->p_stSection->p_stParentSection;
	char szIndent[SCR_CV_ui_Cfg_MaxLenLine];
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/*
	 * compute indent string
	 */
	*szIndent = 0;
	while ( p_stParentSection != NULL)
	{
		strcat( szIndent, "\t" );
		p_stParentSection = p_stParentSection->p_stParentSection;
	}

	/*
	 *allocate memory for section content
	 */
	lSize = p_stFI->lSize + 2 * SCR_CV_ui_Cfg_MaxLenLine;
	p_cCur = p_cBuf = (char *) malloc (lSize);

	/*
	 * write begin section line
	 */
	p_cCur += sprintf( p_cCur, "\r\n%s{%s:%s", szIndent, p_stBuf->p_szBufferName, p_stBuf->p_szBufferNameExt );
	if (*p_stBuf->a_szBufferFormat)
		p_cCur += sprintf( p_cCur, "[%s]", p_stBuf->a_szBufferFormat );
	if (*p_stBuf->a_szBufferParams)
	{
		p_cCur += sprintf( p_cCur, "(" );
		p_szParam = p_stBuf->a_szBufferParams;
		while ( *p_szParam )
		{
			p_cCur += sprintf( p_cCur, "%s,", p_szParam );
			p_szParam += strlen( p_szParam ) + 1;
		}
		p_cCur--;
		p_cCur += sprintf( p_cCur, ")" );
	}

	p_cCur += sprintf( p_cCur, "\r\n" );
	p_szParam = p_stFI->p_cBuffer;
	
	if ( _bCurrentTime )
	{
		/*
		 * write time
		 */
		p_cCur += sprintf( p_cCur, "%s;%s %s\r\n", szIndent, g_szUpdateTimeString, g_stIniData.szVssUserName );
		/*
		 * swap old date line
		 */
		if ( (p_stFI->oTime.GetYear() != 1899) && (p_stFI->oTime.GetYear() != 100) )
		{
			p_szParam = strchr( p_stFI->p_cBuffer, ';' );
			while (*p_szParam++ != '\n');
		}
	}

	/*
	 * write other's line of section in buffer
	 */
	strcpy(p_cCur, p_szParam );

	return p_cBuf;
}


/*
 =======================================================================================
	Algorithm functions
 =======================================================================================
 */

/*
 ---------------------------------------------------------------------------------------
  function that watch if semaphore file is extract or not
 ---------------------------------------------------------------------------------------
 */
BOOL fn_bSomeoneUpdate( BOOL bCreateFile, BOOL _bMessage )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char cStatus;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/*
	 * get status of InUpdate.Sem file
	 */
	cStatus = OLE_fn_cGetVssFileStatus( g_stIniData.szVssInUpdate );
 
	/*
	 * if file is extract by current user, display problem
	 */
	if (cStatus == VSSFILE_CHECKEDOUT_ME)
	{
		if (
				(!_bMessage)
				||
				(
					AfxMessageBox
					( 
						"There's a problem, base status indicate\r\nthat you currently update base\r\nWould you correct problem ?", 
						MB_ICONEXCLAMATION | MB_YESNO
					) == IDYES
				)
			)
		{
			/*
			 * try to correct problem by undoing checkout
			 */
			OLE_fn_bUndoCheckoutFile( g_stIniData.szVssInUpdate, g_stIniData.szLocalInUpdate, 0 );
			cStatus = OLE_fn_cGetVssFileStatus( g_stIniData.szVssInUpdate );
			/*
			 * if still extract by current user, display error
			 */
			if (cStatus == VSSFILE_CHECKEDOUT_ME)
			{
				if (_bMessage)
					AfxMessageBox( "Can't correct problem, contact administraton", MB_ICONSTOP );
				return TRUE;
			}
		}
		else
		{
			return TRUE;
		}
	}

	/*
	 * if file is extract, someone update, stop 
	 */
	if (cStatus == VSSFILE_CHECKEDOUT)
		return TRUE;

	/* 
	 * if file does'nt exist, create it and add it in VSS 
	 */
	if ((cStatus == VSSFILE_NOTFOUND) && bCreateFile)
	{
		fn_vCreateInUpdateSemFile(g_stIniData.szLocalInUpdate);
		OLE_fn_bAddFile( g_stIniData.szVssPath, g_stIniData.szLocalInUpdate );
	}

	return FALSE;
}

/*
 ----------------------------------------------------------------------------------------
  Description   : return update status of base (TRUE) if someone update and write in
					_p_szMsg variable a status string
  Returns (BOOL ) TRUE if someone update, otherwise FALSE
 ----------------------------------------------------------------------------------------
 */
BOOL fn_bGetUpdateStatus( char *_p_szMsg )
{
	BOOL bResult;

	bResult = fn_bSomeoneUpdate(FALSE, TRUE);

	if (_p_szMsg != NULL )
	{
		if (bResult)
			sprintf( _p_szMsg, "%s is updating", g_a_szUserName[0] );
		else
			sprintf( _p_szMsg, "Nobody is being updating");
	}

	return bResult;
}


/*
 ---------------------------------------------------------------------------------------
  begin updating
 ---------------------------------------------------------------------------------------
 */
BOOL fn_bBeginUpdating( void )
{
	//return OLE_fn_bCheckoutFile( g_stIniData.szVssInUpdate, g_stIniData.szLocalInUpdate, VSSFLAG_GETNO );
	return OLE_fn_bCheckoutFile( g_stIniData.szVssInUpdate, g_stIniData.szLocalInUpdate, VSSFLAG_GETYES | VSSFLAG_REPREPLACE );
}

/*
 ---------------------------------------------------------------------------------------
  end obtaining data
 ---------------------------------------------------------------------------------------
 */
BOOL fn_bEndUpdating( void )
{
	FILE *hpFile;
	
	if ( (hpFile = fopen( g_stIniData.szLocalInUpdate, "at")) != NULL)
	{
		fprintf( hpFile, "%s %s\n", g_szUpdateTimeString, g_stIniData.szVssUserName );
		fclose (hpFile );
	}
	return OLE_fn_bCheckinFile( g_stIniData.szVssInUpdate, g_stIniData.szLocalInUpdate, VSSFLAG_DELYES );
	//return OLE_fn_bUndoCheckoutFile( g_stIniData.szVssInUpdate, g_stIniData.szLocalInUpdate, VSSFLAG_DELYES );
}

/*
 ---------------------------------------------------------------------------------------
  doing a modification
 ---------------------------------------------------------------------------------------
 */
BOOL fn_bDoModif( tdstModif *p_stModif )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char					*p_szSectionName = strchr( p_stModif->szName, '^' );
	char					szNotifiedSection[MAX_PATH];
	SCR_tde_Ntfy_Action		eNotifyAction;
	BOOL					bSource;
	BOOL					bTarget;
	BOOL					bError = FALSE;
	BOOL					bContinue = TRUE;

	char					*szVssSection;
	char					*szLocalSection = NULL;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/*
	 * check section
	 */
	if (p_szSectionName == NULL)
		return FALSE;
	sprintf( szNotifiedSection, "%s%s", g_stTarget.szFullName, p_szSectionName );
	p_szSectionName++;
	
	/*
	 * get target and source section
	 */
	bTarget = fn_bGetSection( &g_stTarget, p_szSectionName );
	bSource = fn_bGetSection( &g_stSource, p_szSectionName );

	if (!bSource && !bTarget)
	{
		/*
		 * none of source or target section exist
		 */
		Error_fn_vSet( Error_eSectionNotFound, "Section Not Found neither in Vss nor in local disk" );
		return FALSE;
	}
	else
	{
		/*
		 * compute notify action 
		 */
		if (!bSource)
			eNotifyAction = SCR_EA_Ntfy_DeleteSection;
		else
		{
			if (!bTarget)
				eNotifyAction = SCR_EA_Ntfy_AddSection;
			else
			{
				if (p_stModif->cType == C_ModifType_cAdd)
				{
					int cChoice;
					if (g_cDeleteSectionModif == 0)
					{
						CYesNoAllDlg oQuestion;
						char szMessage[1024], *p_szMessage = szMessage;
						p_szMessage += sprintf( p_szMessage, "Warning : %s section\n", p_stModif->szName );
						p_szMessage += sprintf( p_szMessage, "was created in your local directory but already exist in vss data\n");
						p_szMessage += sprintf( p_szMessage, "-------------------------------------\n" );
						p_szMessage += sprintf( p_szMessage, "Do you want I delete this section modification and \n");
						p_szMessage += sprintf( p_szMessage, "take care of sub section modification ?");
						oQuestion.fn_vSetMessage( szMessage );
						oQuestion.DoModal();
						cChoice = oQuestion.fn_cGetChoice();
						switch( cChoice )
						{
							case C_CHOICE_cYesAll:
								g_cDeleteSectionModif = cChoice;
								cChoice = C_CHOICE_cYes;
								break;
							case C_CHOICE_cNoAll:
								g_cDeleteSectionModif = cChoice;
								cChoice = C_CHOICE_cNo;
								break;
						}
					}
					else 
					{
						cChoice = (g_cDeleteSectionModif == C_CHOICE_cYesAll) ? C_CHOICE_cYes : C_CHOICE_cNo;
					}
					if (cChoice == C_CHOICE_cNo)
					{
						Error_fn_vSet( Error_eVssSectionAlreadyCreated, "Created local section already exist" );
						bError = TRUE;
					}
					else
					{
						fn_vRestoreSubModif( p_stModif );
					}
					bContinue = FALSE;

				}
				eNotifyAction = SCR_EA_Ntfy_RebuildSection;
			}
		}
	}

	/*
	 * watch if time are ok
	 */
	if (bContinue)
	{
		if ( g_stTarget.oTime > *g_stIniData.p_oObtainingTime)
		{
			if (stricmp( g_stIniData.szVssUserName, g_stTarget.szLastUserName) != 0)
			{
				BOOL bForce = FALSE;

				if ( g_stWinPref.lUpdateFlags & C_UpdateOption_lForce )
				{
					bForce = TRUE;
					if (g_stWinPref.lUpdateFlags & C_UpdateOption_lConfirmForce )
					{
						CConflictDlg	oConflictDlg;

						szVssSection = fn_p_cBuildSection( &g_stTarget, FALSE );
						if ( bSource )
							szLocalSection = fn_p_cBuildSection( &g_stSource, TRUE );
				
						oConflictDlg.m_fn_vSetSectionName( p_stModif->szName );
						//oConflictDlg.m_fn_vSetUserName( g_a_szUserName[0] );
						oConflictDlg.m_fn_vSetUserName( g_stTarget.szLastUserName );
						oConflictDlg.m_fn_vSetVssSection( szVssSection );
						oConflictDlg.m_fn_vSetLocalSection( szLocalSection );

						bForce = oConflictDlg.DoModal() == IDOK;

						free( szVssSection );
					}
				}
				if ( !bForce )
				{
					if (szLocalSection != NULL)
						free( szLocalSection );

					Error_fn_vSetFmt( Error_eVssSectionNewer, "Vss Section is newer (last update was done by %s)", g_stTarget.szLastUserName );
					bError = TRUE;
					bContinue = FALSE;
				}
			}
		}
	}

	/*
	 * check parent section in target file if we add a section
	 */
	if (eNotifyAction == SCR_EA_Ntfy_AddSection)
	{
		if (!fn_bCheckParentSection( &g_stTarget, p_szSectionName ) )
		{
			Error_fn_vSet( Error_eVssParentSectionInexistent, "Parent Section doesn't exist" );
			bError = TRUE;
			bContinue = FALSE;
		}
	}

	/*
	 * notify section
	 */
	if (bContinue)
	{
		if (eNotifyAction != SCR_EA_Ntfy_DeleteSection)
		{	
			if (szLocalSection == NULL)
				szLocalSection = fn_p_cBuildSection( &g_stSource, TRUE );
			SCR_fn_v_SvL1_RegisterNotify(szNotifiedSection, fn_vSaveSection, szLocalSection, eNotifyAction );
		}
		else
			SCR_fn_v_SvL1_RegisterNotify(szNotifiedSection, NULL, NULL, eNotifyAction );
	}

	/*
	 * free memory
	 */
	if (bTarget)
		free( g_stTarget.p_cBuffer );
	if (bSource)
		free( g_stSource.p_cBuffer );
	
	return (!bError);
}

/*
 ----------------------------------------------------------------------------------------
  Description   : watch if someone is obtaining base
  Returns (BOOL ) TRUE if someone obtain
 ----------------------------------------------------------------------------------------
 */
BOOL fn_bSomeoneObtain( BOOL _bMessage )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char cStatus;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/*
	 * get In obtain sem file status
	 */
	cStatus = OLE_fn_cGetVssFileStatus( g_stIniData.szVssInObtain );

	/*
	 * if file is extract by current user, display problem
	 */
	if (cStatus == VSSFILE_CHECKEDOUT_ME)
	{
		if (	
				(!_bMessage)
				||
				(
					AfxMessageBox
					( 
						"There's a problem, base status indicate\r\nthat you currently obtain base\r\nWould you correct problem ?", 
						MB_ICONEXCLAMATION | MB_YESNO
					) == IDYES
				)
			)
		{
			/*
			 * try to correct problem by undoing checkout
			 */
			OLE_fn_bUndoCheckoutFile( g_stIniData.szVssInObtain, g_stIniData.szLocalInObtain, 0 );
			cStatus = OLE_fn_cGetVssFileStatus( g_stIniData.szVssInObtain );
			/* 
			 * if still extract by current user, display error
			 */
			if (cStatus == VSSFILE_CHECKEDOUT_ME)
			{
				if (_bMessage)
					AfxMessageBox( "Can't correct problem, contact administraton", MB_ICONSTOP );
				return TRUE;
			}
		}
		else
		{
			return TRUE;
		}
	}

	return (cStatus == VSSFILE_CHECKEDOUT);
}


/*
 ----------------------------------------------------------------------------------------
  Description   : return obtain statusx of base (TRUE if someone obtain. And write in
					_p_szMsg variable a status string
  Returns (BOOL )TRUE if someone obtain, otherwise FALSE
 ----------------------------------------------------------------------------------------
 */
BOOL fn_bGetObtainStatus( char *_p_szMsg  )
{
	BOOL bResult;

	bResult = fn_bSomeoneObtain( TRUE );

	if (_p_szMsg != NULL)
	{
		if (bResult)
		{
			if (g_cNbUsers == 1)
				sprintf( _p_szMsg , "%s is obtaining", g_a_szUserName[0] );
			else
			{
				char cUser;

				_p_szMsg += sprintf(_p_szMsg , "%d persons are obtaining ( ", g_cNbUsers );
				for (cUser = 0; cUser < g_cNbUsers; cUser ++)
					_p_szMsg  += sprintf( _p_szMsg , "%s, ", g_a_szUserName[ cUser ] );
				strcpy (_p_szMsg - 2, " )");
			}
		}
		else
			sprintf( _p_szMsg , "Nobody is being obtaining" );
	}

	return bResult;
}


/*
 ----------------------------------------------------------------------------------------
  begin obtaining (extract InObtain semaphore file )
  Returns (BOOL ) TRUE if operation is successfull
 ----------------------------------------------------------------------------------------
 */
BOOL fn_bBeginObtaining( void )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char cStatus;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/*
	 * get file status for creating it if it's necessary
	 */
	cStatus = OLE_fn_cGetVssFileStatus( g_stIniData.szVssInObtain );

	/*
	 * if already checked by user, return TRUE
	 */
	if (cStatus == VSSFILE_CHECKEDOUT_ME)
		return TRUE;

	/*
	 * if file not found, add it
	 */
	if (cStatus == VSSFILE_NOTFOUND)
	{
		fn_vCreateInObtainFile( g_stIniData.szLocalInObtain );
		OLE_fn_bAddFile( g_stIniData.szVssPath, g_stIniData.szLocalInObtain );
	}

	return OLE_fn_bCheckoutFile( g_stIniData.szVssInObtain, g_stIniData.szLocalInObtain, VSSFLAG_GETNO);
}

/*
 ----------------------------------------------------------------------------------------
  end obtaining data
 ----------------------------------------------------------------------------------------
 */
BOOL fn_bEndObtaining( void )
{
	return OLE_fn_bUndoCheckoutFile( g_stIniData.szVssInObtain, g_stIniData.szLocalInObtain, VSSFLAG_DELYES );
}


/*
 ----------------------------------------------------------------------------------------
  obtaining data (a unique folder or recursive)
 ----------------------------------------------------------------------------------------
 */
BOOL fn_bObtainFile( char *szFileName, BOOL *_bObtain )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char	szLocalPath[MAX_PATH];
	char	*szVssName;
	int		iFlags;
	char	*p_cSeparation;
	BOOL	bFile;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/*
	 * Init
	 */
	szVssName = szFileName;
	iFlags = 0;
	bFile = FALSE;

	/*
	 * type of file to obtain
	 */
	if (*szFileName == '-')
	{
		switch ( *(szFileName + 1) )
		{
			case 'R':
				iFlags |= VSSFLAG_RECURSYES;
				break;
			case 'F':
				bFile = TRUE;
				break;
		}
		szVssName += 3;
	}

	/*
	 * Get Local path
	 */
	sprintf( szLocalPath, "%s%s", g_stIniData.szLocalPath, szVssName + strlen( g_stIniData.szVssPath) );
	if ( bFile )
	{
		p_cSeparation = strrchr( szLocalPath, '\\');
		if (p_cSeparation == NULL)
			return FALSE;
		*p_cSeparation = 0;
	}
	
	/*
	 * Create local directory if it does'nt exist
	 */
	if ( (!CreateDirectory( szLocalPath, NULL )) && (GetLastError() != ERROR_ALREADY_EXISTS) )
	{
		char *p_szCur = szLocalPath;

		/* 
		 * swap first \ character 
		 */
		while ( *p_szCur == '\\' )
			p_szCur ++;

		/*
		 * search first \ or second if this is a drive letter before the \\ character 
		 */
		p_szCur = strchr( p_szCur, '\\');
		if (*(p_szCur - 1) == ':')
			p_szCur = strchr( p_szCur + 1, '\\');


		/*
		 * create recursively each sub directory
		 */
		while (p_szCur != NULL)
		{
			*p_szCur = 0;
			if ((!CreateDirectory (szLocalPath, NULL)) && (GetLastError() != ERROR_ALREADY_EXISTS) )
			{
				Error_fn_vSetFmt( Error_eCantCreateLocalPath, "Can't create local path %s", szLocalPath );
				Error_fn_vDisplay( TRUE );
				return FALSE;
			}

			*p_szCur++ = '\\';
			p_szCur = strchr( p_szCur, '\\');
		};

		if ((!CreateDirectory (szLocalPath, NULL)) && (GetLastError() != ERROR_ALREADY_EXISTS) )
		{
			Error_fn_vSetFmt( Error_eCantCreateLocalPath, "Can't create local path %s", szLocalPath );
			Error_fn_vDisplay( TRUE );
			return FALSE;
		}
	}

	if (bFile)
		*p_cSeparation = '\\';

	return OLE_fn_bGetFile( szVssName, szLocalPath, iFlags, bFile, _bObtain );
}

/*
 ----------------------------------------------------------------------------------------
  update a file
 ----------------------------------------------------------------------------------------
 */
char fn_cUpdateFile( char *_szLocalFileName )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	char		szVssPath[MAX_PATH];
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	sprintf( szVssPath, "%s%s", g_stIniData.szVssPath, _szLocalFileName+ strlen( g_stIniData.szLocalPath ) );
	return OLE_fn_cUpdateFile( szVssPath, _szLocalFileName );
}
