/**********************************************/
/*                                            */    
/* iFilesOperations.cpp                       */
/*                                            */
/* files operations (copy, move)              */
/*                                            */
/* scol v 4                                   */
/*                                            */
/**********************************************/


#include <windows.h>
#include <stdio.h>
#include "ireboot.h"
#include "iwinversion.h"
#include "ifilesoperations.h"






/***********************************************************************************/
/*                                                                                 */
/*     C O N T E N T                                                               */
/*                                                                                 */
/*                                                                                 */
/*                                                                                 */
/*     I N T E R N A L    B O D Y                                                  */
/*     G E N E R I C      F U N C T I O N S                                        */
/*                                                                                 */
/* LPTSTR ifopGetShortPath   (LPCTSTR path)                                        */
/*                                                                                 */
/* void   ifopCutFilename    (LPCTSTR filename, LPTSTR dir, LPTSTR name)           */
/*                                                                                 */
/*                                                                                 */
/*                                                                                 */
/*     I N T E R N A L    B O D Y                                                  */
/*     WIN NT4 / 2000 / WHISTLE      F U N C T I O N S                             */
/*                                                                                 */
/* BOOL ifopInitNT  ()                                                             */
/*                                                                                 */
/* BOOL ifopCloseNT ()                                                             */
/*                                                                                 */
/* BOOL ifopCopyFNT (LPCTSTR srcDir, LPCTSTR src, LPCTSTR fullDst)                 */
/*                                                                                 */
/*                                                                                 */
/*                                                                                 */
/*     I N T E R N A L    B O D Y                                                  */
/*     WIN 95 / 98 / ME   F U N C T I O N S                                        */
/*                                                                                 */
/* HANDLE ifopCloseFWindows   (HANDLE winInitFile)                                 */
/*                                                                                 */
/* HANDLE ifopInitFWindows    ()                                                   */
/*                                                                                 */
/* BOOL   ifopAddWinInitEntry (HANDLE file, LPCTSTR src, LPCTSTR tmp, LPCTSTR dst) */
/*                                                                                 */
/* BOOL   ifopCopyFWindows    (LPCTSTR srcDir, LPCTSTR src, LPCTSTR fullDst)       */
/*                                                                                 */
/*                                                                                 */
/*                                                                                 */
/*     E X T E R N A L    B O D Y                                                  */
/*                                                                                 */
/* DWORD ifopCopyF (LPCTSTR src, LPCTSTR dst, DWORD mode)                          */
/*                                                                                 */
/*                                                                                 */
/*                                                                                 */
/***********************************************************************************/


















/******************************************************************************/
/*                                                                            */
/*     T Y P E S    A N D    D A T A                                          */
/*                                                                            */
/******************************************************************************/



/* data for dynamic load and use of MoveFileEx functions */
/* (under nt4, 2000 and whistler)                        */
typedef BOOL (WINAPI* MOVEFILEEX) (LPCTSTR, LPCTSTR, DWORD);
static MOVEFILEEX p_MoveFileEx = NULL;
HINSTANCE kernel32Dll;









/******************************************************************************/
/*                                                                            */
/*     I N T E R N A L    B O D Y                                             */
/*                                                                            */
/*     G E N E R I C      F U N C T I O N S                                   */
/*                                                                            */
/******************************************************************************/




/**********************************************************/
/*                                                        */
/* LPTSTR ifopGetShortPath (LPCTSTR path)                 */
/*                                                        */
/* scol v 4                                               */
/*                                                        */
/* get the short path from the long one given as          */
/* parameter. returns the pointer on short path.          */
/* returns NULL if fails.                                 */
/*                                                        */
/* ! DON'T FORGET TO FREE IT WHEN IT'S USELESS !          */
/*                                                        */
/**********************************************************/

LPTSTR ifopGetShortPath (LPCTSTR path)
{
DWORD shortSize;
DWORD shortResult;
LPTSTR shortPath;

	shortSize = (DWORD)256;
	shortPath = (LPTSTR) malloc (shortSize * sizeof(TCHAR));
			
	shortResult = GetShortPathName (path, shortPath, shortSize);

	if (shortResult == 0)
		return NULL;

	if (shortResult >= shortSize)
	{
		shortSize = shortResult+1;
		shortPath = (LPTSTR) realloc (shortPath, shortSize*sizeof(TCHAR));
		GetShortPathName (path, shortPath, shortSize);
	}

	return shortPath;

}








/**********************************************************/
/*                                                        */
/* void ifopCutFilename (LPCTSTR filename,                */
/*                       LPTSTR dir, LPTSTR name)         */
/*                                                        */
/* scol v 4                                               */
/*                                                        */
/* take the filename given as first parameter, and        */
/* take directory and name of file from it.               */
/*                                                        */
/**********************************************************/

void ifopCutFilename (LPCTSTR filename, LPTSTR dir, LPTSTR name)
{
UINT i;
UINT size;

	size = strlen (filename);
	i = size - 1;
	while (filename[i] != '\\')
		i--;
	strncpy (dir, filename, (i+1)*sizeof(TCHAR));
	dir[i+1] = '\0';

	strncpy (name, &filename[i+1], (size-(i+1))*sizeof(TCHAR));
	name[size-(i+1)] = '\0';
}














/******************************************************************************/
/*                                                                            */
/*     I N T E R N A L    B O D Y                                             */
/*                                                                            */
/*     WIN NT4 / 2000 / WHISTLE      F U N C T I O N S                        */
/*                                                                            */
/******************************************************************************/





/**********************************************************/
/*                                                        */
/* BOOL ifopInitNT ()                                     */
/*                                                        */
/* scol v 4                                               */
/*                                                        */
/* initialize the dynamic kernel32 library and the        */
/* MoveFileEx function pointer.                           */
/*                                                        */
/* return 0 if failure. nonzero if success                */
/*                                                        */
/**********************************************************/

BOOL ifopInitFNT ()
{
	//open the kernel32 dll
	if ((kernel32Dll = LoadLibrary ("kernel32.dll")) == NULL)
	{
		return 0;
	}

	//get the function pointer
	if ((p_MoveFileEx = (MOVEFILEEX)GetProcAddress (kernel32Dll, "MoveFileExA")) == NULL)
	{
		return 0;
	}

	return 1;
}








/**********************************************************/
/*                                                        */
/* BOOL ifopCloseNT ()                                    */
/*                                                        */
/* scol v 4                                               */
/*                                                        */
/* Close the dynamic kernel32 library                     */
/*                                                        */
/**********************************************************/

BOOL ifopCloseFNT()
{
	if (p_MoveFileEx)
	{
		free (p_MoveFileEx);
		p_MoveFileEx = NULL;
	}

	FreeLibrary (kernel32Dll);
	return 0;
}















/**********************************************************/
/*                                                        */
/* BOOL ifopCopyFNT                                       */
/*        (LPCTSTR srcDir, LPCTSTR src, LPCTSTR fullDst)  */
/*                                                        */
/* scol v 4                                               */
/*                                                        */
/* Copy a file after reboot, on WinNT4 / 2000 / Whistler  */
/*                                                        */
/* return 0 if failure. nonzero if success                */
/*                                                        */
/**********************************************************/

BOOL ifopCopyFNT (LPCTSTR srcDir, LPCTSTR src, LPCTSTR fullDst)
{
TCHAR srcBuf[1024];
TCHAR tmpBuf[1024];



	if (!ifopInitFNT())
	{
		return ifopCloseFNT();
	}

	
	sprintf ((LPTSTR)srcBuf, "%s%s", srcDir, src);


	//copy or move a file
	if (fullDst != NULL)
	{
		//copy the source file into a temp directory
		//(the file moved after reboot must be moved in the same volumne)
		sprintf ((LPTSTR)tmpBuf, "%c:\\%s", fullDst[0], src);


		if (!CopyFile (srcBuf, tmpBuf, FALSE))
		{
			return ifopCloseFNT();
		}
	}


	//ask for windows to move this file after the reboot
	if (!p_MoveFileEx (tmpBuf, fullDst, MOVEFILE_DELAY_UNTIL_REBOOT|MOVEFILE_REPLACE_EXISTING))
		return ifopCloseFNT();

	//ask for reboot later
	iNeedReboot();

	ifopCloseFNT();
	return 1;
}


























/******************************************************************************/
/*                                                                            */
/*     I N T E R N A L    B O D Y                                             */
/*                                                                            */
/*     WIN 95 / 98 / ME   F U N C T I O N S                                   */
/*                                                                            */
/******************************************************************************/





/**********************************************************/
/*                                                        */
/* HANDLE ifopCloseFWindows (HANDLE winInitFile)          */
/*                                                        */
/* scol v 4                                               */
/*                                                        */
/* close the file handle                                  */
/*                                                        */
/**********************************************************/

HANDLE ifopCloseFWindows (HANDLE winInitFile)
{
	CloseHandle (winInitFile);
	return INVALID_HANDLE_VALUE;
}








/**********************************************************/
/*                                                        */
/* HANDLE ifopInitFWindows ()                             */
/*                                                        */
/* scol v 4                                               */
/*                                                        */
/* open the wininit file if it exists.                    */
/* if it doesn't, create it, and add a [rename] section   */
/*                                                        */
/**********************************************************/

HANDLE ifopInitFWindows ()
{
LPTSTR winInitFilename;
UINT code;
HANDLE winInitFile;
DWORD size;
DWORD returnedSize;


    //get Windows directory
	winInitFilename = (LPTSTR)malloc (1024 * sizeof(TCHAR));
    code = GetWindowsDirectory (winInitFilename, 1024);

	if (code > 1024)
	{
		winInitFilename = (LPTSTR)realloc ((LPTSTR)winInitFilename, code+256);
		code = GetWindowsDirectory (winInitFilename, code+256);
	}

	if (code == 0)
		return INVALID_HANDLE_VALUE;


	//set wininit.ini complete filename
	winInitFilename = strcat ((LPTSTR)winInitFilename, "\\wininit.ini");



	//try to open wininit file
	if ((winInitFile = CreateFile (winInitFilename, GENERIC_WRITE|GENERIC_READ, 0, NULL,
						OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
	{
	TCHAR buf[16];

		//if ti doesn't exist, create it, 
		if ((winInitFile = CreateFile (winInitFilename, GENERIC_WRITE|GENERIC_READ, 0, NULL,
						CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
		{
			//and add the [rename] section into it
			sprintf (buf, "[Rename]\n");
			size = (DWORD)strlen ((LPTSTR)buf);
			if (!WriteFile (winInitFile, (LPVOID)buf, size, &returnedSize, NULL))
				return ifopCloseFWindows (winInitFile);
		}
	}

	//otherwise, put the file pointer to the end
	else
		if (!SetFilePointer (winInitFile, 0, NULL, FILE_END))
			return ifopCloseFWindows (winInitFile);


	return winInitFile;
}











/**********************************************************/
/*                                                        */
/* BOOL ifopAddWinInitEntry (HANDLE file,                 */
/*        LPCTSTR src, LPCTSTR tmp, LPCTSTR dst)          */
/*                                                        */
/* scol v 4                                               */
/*                                                        */
/* add an entry to the wininit file in order to make      */
/* the src file copyied on dest file after reboot.        */
/* src -> tmp -> dst                                      */
/*                                                        */
/* return 0 if failure. nonzero if success                */
/*                                                        */
/* !! ASSUME THAT destination path is created !!          */
/* !! ASSUME THAT temporary path is a short one !!        */
/*                                                        */
/**********************************************************/

BOOL ifopAddWinInitEntry (HANDLE file, LPCTSTR src, LPCTSTR tmp, LPCTSTR dst)
{
TCHAR name[512];
LPTSTR shortSrc         = NULL;
TCHAR shortName    [512];
TCHAR dstDir       [512];
LPTSTR shortDstDir      = NULL;
TCHAR tmpDir       [512];
TCHAR tmpBuf       [512];

TCHAR buf[1024];
DWORD size;
DWORD returnedSize;


 
	//get short path and filename of source
	if ((shortSrc = ifopGetShortPath (src)) == NULL)
		return 0;



	//delete file 
	if (dst == NULL)
		sprintf ((LPTSTR)buf, "NUL=%s\n", shortSrc);


	//copy file
	else
	{

		//get source short filename without path
		ifopCutFilename (shortSrc, tmpBuf, shortName);
		ifopCutFilename (src, tmpBuf, name);


		//check if the source filename is already a short one : 
		//don't copy if the short name is different from the long one
		if (_strnicmp (name, shortName, strlen (name)))
		{	
			if (shortSrc)
			{
				free (shortSrc);
				shortSrc = NULL;
			}
			return 0;
		}

		//get short destination path
		ifopCutFilename (dst, dstDir, tmpBuf);

		//!! assume that dstDir has already been created !!
		shortDstDir = ifopGetShortPath (dstDir);

		//get tmp dir
		ifopCutFilename (tmp, tmpDir, tmpBuf);



		//copy srcfile to temp directory
		if (!CopyFile (src, tmp, FALSE))
		{
			if (shortSrc)
			{
				free (shortSrc);
				shortSrc = NULL;
			}

			if (shortDstDir)
			{
				free (shortDstDir);
				shortDstDir = NULL;
			}
			return 0;
		}

		//add a line into the wininit file, 
		// in order to copy the file after the reboot
		sprintf ((LPTSTR)buf, "%s%s=%s%s\n", shortDstDir, shortName, tmpDir, shortName);

	}

	size = (DWORD)strlen ((LPCTSTR)buf);


	//write line into file
	if (!WriteFile (file, (LPVOID)buf, size, &returnedSize, NULL))
	{

		if (shortSrc)
		{
			free (shortSrc);
			shortSrc = NULL;
		}


		if (shortDstDir)
		{
			free (shortDstDir);
			shortDstDir = NULL;
		}

		return 0;
	}

	if (shortSrc)
	{
		free (shortSrc);
		shortSrc = NULL;
	}


	if (shortDstDir)
	{
		free (shortDstDir);
		shortDstDir = NULL;
	}


	return 1;
}














/**********************************************************/
/*                                                        */
/* BOOL ifopCopyFWindows                                  */
/*        (LPCTSTR srcDir, LPCTSTR src, LPCTSTR fullDst)  */
/*                                                        */
/* scol v 4                                               */
/*                                                        */
/* Copy a file after reboot, on Win95 / 98 / ME           */
/*                                                        */
/* return 0 if failure. nonzero if success                */
/*                                                        */
/**********************************************************/

BOOL ifopCopyFWindows (LPCTSTR srcDir, LPCTSTR src, LPCTSTR fullDst)
{
TCHAR tmpFilename [1024];
TCHAR srcFilename [1024];
HANDLE winInitFile;

	
	//set the complete src filename
	sprintf ((LPTSTR)srcFilename, "%s%s", srcDir, src);

	//open or create the wininit file
	if ((winInitFile = ifopInitFWindows ()) == INVALID_HANDLE_VALUE)
		return 0;

	//by the way, set the temporary file destination
	sprintf ((LPTSTR)tmpFilename, "%c:\\%s", fullDst[0], src);

	//add this new entry to the wininit file
	if (!ifopAddWinInitEntry (winInitFile, srcFilename, tmpFilename, fullDst))
	{
		ifopCloseFWindows (winInitFile);
		return 0;
	}


	//ask for reboot later
	iNeedReboot();
	ifopCloseFWindows(winInitFile);
	return 1;
}



















/******************************************************************************/
/******************************************************************************/
/**                                                                          **/
/**     E X T E R N A L    B O D Y                                           **/
/**                                                                          **/
/******************************************************************************/
/******************************************************************************/









/**********************************************************/
/*                                                        */
/* DWORD ifopCopyF (LPCTSTR src, LPCTSTR dst, DWORD mode) */
/*                                                        */
/* scol v 4 : replace old function CopyF                  */
/*                                                        */
/* Copy a file.                                           */
/*                                                        */
/*                                                        */
/*                                                        */
/* parameter mode :                                       */
/*                                                        */
/*    - IFOP_MODE_UNSAFE (<=> NULL) : then function will  */
/* try to copy the file after reboot if a direct copy     */
/* goes wrong.                                            */
/*                                                        */
/*    - IFOP_MODE_SAFE : the function won't try to copy   */
/* file after reboot. It will check the file version      */
/* (stored in its name), and won't do anything if names   */
/* are the same.                                          */
/*                                                        */
/*                                                        */
/*                                                        */
/* return 0 if success. -1 means error on parameters      */
/* (filenames NULL...)                                    */
/*                                                        */
/* if error (file locked), call an internal function to   */
/* make the copy after the reboot.                        */
/*                                                        */
/* this method (copy a file when it's locked) is          */
/* different depending on the operating system version.   */
/* ifopCopyF manages all windows version :) yeah :)       */
/*                                                        */
/**********************************************************/

DWORD ifopCopyF (LPCTSTR src, LPCSTR dst, DWORD mode)
{
DWORD errorCode;
UINT winVersion;
TCHAR srcDir[1024];
TCHAR srcName[512];
TCHAR dstDir[1024];
TCHAR dstName[512];

   ifopCutFilename (src, srcDir, srcName);
   ifopCutFilename (dst, dstDir, dstName);

   SetFileAttributes(dst,0);
   DeleteFile(dst);


   //try to copy the file
   if (!CopyFile(src, dst, FALSE))
   {
	  errorCode = GetLastError();


	  if  (  (errorCode != ERROR_SHARING_VIOLATION) 
		  && (errorCode != ERROR_LOCK_VIOLATION))
	  {
		  return 0;
	  }

	  if ((mode == NULL) || (mode == IFOP_MODE_UNSAFE))
	  {

			//the file is locked, make it copy after reboot
			// Check OS version
			if ((winVersion = iGetWinVersion()) == I_WINVER_NULL)
			{
				return 0;
			}

			//call function, depending on OS version
			if (  (winVersion == I_WINVER_NT4)
				|| (winVersion == I_WINVER_2000)
				|| (winVersion == I_WINVER_WHISTLER))
			{


				if (!ifopCopyFNT (srcDir, srcName, dst))
				{

					return 0;
				}
			}
			else
				if (!ifopCopyFWindows (srcDir, srcName, dst))
				{
					return 0;
				}
	  }
	  else if (mode == IFOP_MODE_SAFE)
	  {

			//check the filenames
			if (!_strnicmp (srcName, dstName, strlen (srcName)))
			{
				return 1;
			}
			else 
			{
				return 0;
			}
	  }
	  else 
	  {
		  return 0;
	  }

   }
   else
      SetFileAttributes(dst,0);


   return 1;
}













/*****************************************************/
/*                                                   */
/* old CopyF function. deprecated,                   */
/*                                                   */
/*****************************************************/
/*
int CopyF (HWND hwnddialog, char* src, char* dst)
{
  if (src && dst)
  {
    SetFileAttributes(dst,0);
    DeleteFile(dst);
    if (!CopyFile(src,dst,FALSE))
    {
			if (!Silent)
				if (MsgBox(MainHWND,MB_YESNO,getvar("ERROR_COPY_TTL"),getvar("ERROR_COPY_MSG"),src,dst)==IDYES) reboot=true;
      StopINI=TRUE;
      StopALL=TRUE;
      oldinstallfailled=1;
      return -1;
    }
    SetFileAttributes(dst,0);
	//scol 4 : progress bar
	SetProgressBarPos (hwnddialog, src);
    return 0;
  }
  return -1;
}
*/








