
// zlib open source license
//
// Copyright (c) 2010 to 2013 David Forsgren Piuva
// 
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// 
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 
//    1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would be
//    appreciated but is not required.
// 
//    2. Altered source versions must be plainly marked as such, and must not be
//    misrepresented as being the original software.
// 
//    3. This notice may not be removed or altered from any source
//    distribution.

#include "../stdafx.h"
#include <ctype.h>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <tchar.h>

using namespace std;

char GetChar(char* sInput, int index) {
	if (index < 0) {
		// Out of bound
		return '?';
	} else {
		// Unsafe but might work
		return sInput[index];
	}
}
wchar_t GetChar(wchar_t* sInput, int index) {
	if (index < 0) {
		// Out of bound
		return L'?';
	} else {
		// Unsafe but might work
		return sInput[index];
	}
}
void SetChar(char* sOutput, int index, char newCharacter) {
	if (index < 0) {
		// Out of bound
	} else {
		// Unsafe but might work
		sOutput[index] = newCharacter;
	}
}
void SetChar(wchar_t* sOutput, int index, wchar_t newCharacter) {
	if (index < 0) {
		// Out of bound
	} else {
		// Unsafe but might work
		sOutput[index] = newCharacter;
	}
}
char GetSafeChar(char sInput[260], int index) {
	if (index < 0 || index > 259) {
		// Out of bound
		return '?';
	} else {
		// Safe
		return sInput[index];
	}
}
wchar_t GetSafeChar(wchar_t sInput[260], int index) {
	if (index < 0 || index > 259) {
		// Out of bound
		return L'?';
	} else {
		// Safe
		return sInput[index];
	}
}
void SetSafeChar(char sOutput[260], int index, char newCharacter) {
	if (index < 0 || index > 259) {
		// Out of bound
	} else if (index == 259) {
		// The last character must be a terminator
		sOutput[index] = 0;
	} else {
		// Safe
		sOutput[index] = newCharacter;
	}
}
void SetSafeChar(wchar_t sOutput[260], int index, wchar_t newCharacter) {
	if (index < 0 || index > 259) {
		// Out of bound
	} else if (index == 259) {
		// The last character must be a terminator
		sOutput[index] = 0;
	} else {
		// Safe
		sOutput[index] = newCharacter;
	}
}

int lengthOfString_wide(wchar_t* sInput) {
	int I;
	I = 0;
	while (true) {
		if (sInput[I] == L'\0') {
			return I;
		}
		I++;
	}
}

int lengthOfString(char* sInput) {
	int I;
	I = 0;
	while (true) {
		if (sInput[I] == '\0') {
			return I;
		}
		I++;
	}
}

int firstOfLetter_wide(int iStart, wchar_t* sInput, wchar_t cFind) {
	int I;
	I = iStart;
	while (true) {
		if (sInput[I] == cFind) {
			return I;
		} else if (sInput[I] == L'\0') {
			return -1;
		}
		I++;
	}
}

int firstOfLetter(int iStart, char* sInput, char cFind) {
	int I;
	I = iStart;
	while (true) {
		if (sInput[I] == cFind) {
			return I;
		} else if (sInput[I] == '\0') {
			return -1;
		}
		I++;
	}
}

int lastOfLetter_wide(int iStart, wchar_t* sInput, wchar_t cFind) {
	int I;
	I = iStart;
	while (true) {
		if (I < 0) {
			return -1;
		} else if (sInput[I] == '\0') {
			return -1;
		} else if (sInput[I] == cFind) {
			return I;
		}
		I--;
	}
}

int lastOfLetter(int iStart, char* sInput, char cFind) {
	int I;
	I = iStart;
	while (true) {
		if (I < 0) {
			return -1;
		} else if (sInput[I] == '\0') {
			return -1;
		} else if (sInput[I] == cFind) {
			return I;
		}
		I--;
	}
}

int lastSlash(wchar_t* sInput) {
	int I;
	int Result;
	I = 0;
	Result = -1;
	while (sInput[I] != '\0') {
		if (sInput[I] == L'\\' || sInput[I] == L'/') {
			Result = I;
		}
		I++;
	}
	return Result;
}

bool withoutPath(wchar_t* sInput, wchar_t sOutput[260]) {
	int iSlashIndex;
	int iLenInput;
	iLenInput = lengthOfString_wide(sInput);
	iSlashIndex = lastSlash(sInput);
	if (iLenInput > 259) {
		SetSafeChar(sOutput,0,L'\0');
		return false;
	} else {
		//iLenInput < 260
		int I;
		if (iSlashIndex > -1) {
			//iSlashIndex > -1
			int J;
			J = 0;
			
			//J = 0
			
			// Print after slash
			LoopForward(iSlashIndex + 1, I, iLenInput - 1) {
				SetSafeChar(sOutput,J,GetChar(sInput,I)); J++;
			}
			
			//iSlashIndex > -1 {Variable propagation}
			//iSlashIndex >= 0 {Integer comparison}
			//iLenInput < 260 {Variable propagation}
			//J = iLenInput - iSlashIndex {Length of A to B = B - A + 1}
			//J < 260 {Double loose substitution}
			
			// Close the string
			SetSafeChar(sOutput,J,L'\0');
		} else {
			// Return the input
			LoopForward(0, I, iLenInput) {
				SetSafeChar(sOutput,I,GetChar(sInput,I));
			}
		}
		return true;
	}
}

bool replaceAfterDot(wchar_t* sInput, wchar_t sOutput[260], wchar_t* sReplace) {
	int iDotIndex;
	int iLenInput;
	int iLenReplace;
	int iLastSlash;
	iLenInput = lengthOfString_wide(sInput);
	//iLenInput >= 0
	iLenReplace = lengthOfString_wide(sReplace);
	iDotIndex = lastOfLetter_wide(iLenInput - 1, sInput, L'.');
	iLastSlash = lastSlash(sInput);
	if (iDotIndex < iLastSlash) {
		// If the last dot is in a folder name, ignore it.
		iDotIndex = -1;
		
		//iDotIndex = -1
		//iLenInput >= 0 {Variable propagation}
		//iDotIndex <= iLenInput {Loose substitution}
	} else {
		//if iDotIndex <= -1 then iDotIndex <= iLenInput {By precondition}
		//if iDotIndex > -1 then iDotIndex <= iLenInput {By postcondition}
		//iDotIndex <= iLenInput {True for all values of iDotIndex}
	}
	//iDotIndex <= iLenInput {True for both cases}
	if (iLenInput + iLenReplace + 1 > 259) {
		SetSafeChar(sOutput,0,L'\0');
		return false;
	} else {
		//iLenInput + iLenReplace + 1 < 260
		int I;
		int J;
		J = 0;
		if (iDotIndex > -1) {
			//J = 0 {Constant propagation}
			
			// Print input before and including dot
			LoopForward(0, I, iDotIndex) {
				SetSafeChar(sOutput,J,GetChar(sInput,I)); J++;
			}
			
			//J = iDotIndex + 1 {Increment}
			
			// Print replacing
			LoopForward(0, I, iLenReplace - 1) {
				sOutput[J] = sReplace[I]; J++;
			}
			
			//iDotIndex <= iLenInput {Variable propagation}
			//J = iDotIndex + iLenReplace + 1 {Increment}
			//iLenInput + iLenReplace + 1 < 260 {Variable propagation}
			//iDotIndex + iLenReplace + 1 <= iLenInput + iLenReplace + 1 {Equal addition}
			//iDotIndex + iLenReplace + 1 < 260 {Loose substitution}
			//J < 260 {Substitution}
			
			// Close the string
			sOutput[J] = L'\0';
		} else {
			//J = 0 {Constant propagation}
			
			// Print input
			LoopForward(0, I, iLenInput - 1) {
				SetSafeChar(sOutput,J,GetChar(sInput,I)); J++;
			}
			
			//J = iLenInput {Increment}
			
			// Print new dot
			sOutput[J] = L'.'; J++;
			
			//J = iLenInput + 1 {Increment}
			
			// Print including
			LoopForward(0, I, iLenReplace - 1) {
				sOutput[J] = sReplace[I]; J++;
			}
			
			//J = iLenInput + iLenReplace + 1 {Increment}
			//iLenInput + iLenReplace + 1 < 260 {Variable propagation}
			//J < 260 {Substibution}
			
			// Close the string
			sOutput[J] = L'\0';
		}
		return true;
	}
}

void CopyToFixedSizePath(wchar_t* sInput, wchar_t sOutput[260]) {
	int I;
	int iLenInput;
	iLenInput = lengthOfString_wide(sInput);
	if (iLenInput < 260) {
		//iLenInput < 260
		LoopForward(0, I, iLenInput - 1) {
			//0 <= I <= 258 {Loose substitution}
			SetSafeChar(sOutput,I,GetChar(sInput,I));
		}
		//iLenInput <= 259 {Integer comparison}
		SetSafeChar(sOutput,iLenInput,L'\0');
	} else {
		// Give an invalid result just to avoid crashing since the precondition is broken
		LoopForward(0, I, 258) {
			//0 <= I <= 258 {From bounded loop range}
			SetSafeChar(sOutput,I,GetChar(sInput,I));
		}
		sOutput[259] = L'\0';
	}
}

// Code above seems okay after formal verification
// Code below should at least not crash because a memory bound check is used

// Remember to release the result after using it.
wchar_t* CopyToNewString(wchar_t* sInput) {
	int I;
	int iLenInput;
	wchar_t* sOutput;
	iLenInput = lengthOfString_wide(sInput);
	sOutput = new wchar_t[iLenInput+1];
	LoopForward(0, I, iLenInput) { //Both content and terminator
		SetSafeChar(sOutput,I,GetChar(sInput,I));
	}
	return sOutput;
}

bool CompareStrings_Exact(wchar_t* sA, wchar_t* sB) {
	int i;
	i = 0;
	// We compare each character until we reach an end.
	while (GetChar(sA,i) != L'\0' && GetChar(sB,i) != L'\0') {
		if (GetChar(sA,i) != GetChar(sB,i)) return false;
		i++;
	}
	// They are equal if they both ended here.
	return (GetChar(sA,i) == L'\0' && GetChar(sB,i) == L'\0');
}

bool CompareStrings_CaseInsensitive(wchar_t* sA, wchar_t* sB) {
	int i;
	i = 0;
	
	// We compare each character until we reach an end.
	while (GetChar(sA,i) != L'\0' && GetChar(sB,i) != L'\0') {
		if (towupper(GetChar(sA,i)) != towupper(GetChar(sB,i))) return false;
		i++;
	}
	// The are equal if they both ended here.
	return (GetChar(sA,i) == L'\0' && GetChar(sB,i) == L'\0');
}

bool CompareStrings_FileNames(wchar_t* sA, wchar_t* sB) {
	int aStart; int aCurrent; int aEnd;
	int bStart; int bCurrent; int bEnd;
	
	// Find a's interval
	aStart = lastSlash(sA) + 1;
	aEnd = lengthOfString_wide(sA) - 1;
	
	// Find b's interval
	bStart = lastSlash(sB) + 1;
	bEnd = lengthOfString_wide(sB) - 1;
	
	if (aEnd - aStart != bEnd - bStart) return false; // They have different length
	if (aEnd - aStart == 0) return true; // Empty
	if (aEnd - aStart < 0) return false; // Invalid length
	
	// We compare each character until we reach an end.
	aCurrent = aStart;
	bCurrent = bStart;
	while (aCurrent <= aEnd) {
		if (towupper(GetChar(sA,bCurrent)) != towupper(GetChar(sB,bCurrent))) return false;
		aCurrent++; bCurrent++;
	}
	 return true;
}

bool CompareStrings_PartOfACaseInsensitive(wchar_t* sA, int aStart, int aEnd, wchar_t* sB) {
	int i; int j;
	i = aStart; j = 0;
	
	// We compare each character until we reach an end.
	while (i <= aEnd && sB[j] != L'\0') {
		if (towupper(sA[i]) != towupper(sB[j])) return false;
		i++; j++;
	}
	// The are equal if they both ended here.
	return (i == aEnd + 1 && sB[j] == L'\0');
}

bool CompareStrings_PartOfACaseInsensitive_Ansi(char* sA, int aStart, int aEnd, char* sB) {
	int i; int j;
	i = aStart; j = 0;
	
	// We compare each character until we reach an end.
	while (i <= aEnd && sB[j] != '\0') {
		if (towupper(sA[i]) != towupper(sB[j])) return false;
		i++; j++;
	}
	// The are equal if they both ended here.
	return (i == aEnd + 1 && sB[j] == '\0');
}

double ParseDoubleFromPartOfString(wchar_t* sInput,int start,int end) {
	int i;
	double result;
	bool negated;
	bool reachedDecimal;
	int digitDivider;
	wchar_t c;
	result = 0.0;
	negated = false;
	reachedDecimal = false;
	digitDivider = 1;
	LoopForward(start,i,end) {
		c = sInput[i];
		if (c == L'-' || c == L'~') {
			negated = !negated;
		} else if (c >= L'0' && c <= L'9') {
			if (reachedDecimal) {
				digitDivider = digitDivider * 10;
				result = result + ((double)(c - L'0') / (double)digitDivider);
			} else {
				result = (result * 10) + (double)(c - L'0');
			}
		} else if (c == L',' || c == L'.') {
			reachedDecimal = true;
		}
	}
	if (negated) {
		return -result;
	} else {
		return result;
	}
}

double ParseDouble(wchar_t* sInput) {
	return ParseDoubleFromPartOfString(sInput,0,lengthOfString_wide(sInput));
}

void SimplifyFloatInString_wide(wchar_t* sRef) {
	int i; int Decimal;
	Decimal = firstOfLetter_wide(0,sRef,L'.');
	if (Decimal > -1) {
		i = lengthOfString_wide(sRef) - 1;
		while ((GetChar(sRef,i) == L'0' || GetChar(sRef,i) == L'.') && i >= Decimal) {
			sRef[i] = L'\0';
			i--;
		}
	}
}

void SimplifyFloatInString(char* sRef) {
	int i; int Decimal;
	Decimal = firstOfLetter(0,sRef,'.');
	if (Decimal > -1) {
		i = lengthOfString(sRef) - 1;
		while ((GetChar(sRef,i) == '0' || GetChar(sRef,i) == '.') && i >= Decimal) {
			SetChar(sRef,i,'\0');
			i--;
		}
	}
}

wchar_t* LoadTextAsANSI_wide(wchar_t* filename) {
	// Open the file for reading
	ifstream inputStream;
	char c; int i; int Size;
	wchar_t* sOutput;
	inputStream.open (filename);
	if (inputStream.is_open()) {
		
		// Get file size
		inputStream.seekg (0, ios::end);
		Size = inputStream.tellg();
		inputStream.seekg (0, ios::beg);
		
		// Allocate enough for BOM check
		if (Size < 4) Size = 4;
		
		// Allocate string
		sOutput = new wchar_t[Size + 2];
		i = 0;
		while ( inputStream.good() ) {
			inputStream.read(&c,1);
			if (i < Size) {
				sOutput[i] = (wchar_t)c;
			}
			i++;
		}
		sOutput[i] = L'\0';
		inputStream.close();
	} else {
		// Return nothing
		sOutput = NULL;
	}
	return sOutput;
}

char* LoadTextAsANSI(wchar_t* filename) {
	// Open the file for reading
	ifstream inputStream;
	char c; int i; int Size;
	char* sOutput;
	inputStream.open (filename);
	if (inputStream.is_open()) {
		
		// Get file size
		inputStream.seekg (0, ios::end);
		Size = inputStream.tellg();
		inputStream.seekg (0, ios::beg);
		
		// Allocate enough for BOM check
		if (Size < 4) Size = 4;
		
		// Allocate string
		sOutput = new char[Size + 2];
		i = 0;
		while ( inputStream.good() ) {
			inputStream.read(&c,1);
			if (i < Size) {
				sOutput[i] = c;
			}
			i++;
		}
		sOutput[i] = L'\0';
		inputStream.close();
	} else {
		// Return nothing
		sOutput = NULL;
	}
	return sOutput;
}

bool SaveTextAsANSI(wchar_t* filename,char* content) {
	ofstream outputStream;
	outputStream.open(filename);
	if (outputStream.is_open()) {
		outputStream << content;
		outputStream.close();
		return true; // Success
	} else {
		return false; // Unable to save
	}
}

bool IsANSI(wchar_t* sRef) {
	int I;
	I = 0;
	while (GetChar(sRef,I) != L'\0') {
		if ((int)sRef[I] < 0 || (int)sRef[I] > 255) {
			return false;
		}
		I++;
	}
	return true;
}

bool IsSimpleName(wchar_t* sRef) {
	int I;
	I = 0;
	while (GetChar(sRef,I) != L'\0') {
		if ( GetChar(sRef,I) == L'<' || GetChar(sRef,I) == L'>' || GetChar(sRef,I) == L'(' || GetChar(sRef,I) == L')' || GetChar(sRef,I) == L'[' || GetChar(sRef,I) == L']' || GetChar(sRef,I) == L'{' || GetChar(sRef,I) == L'}' || GetChar(sRef,I) == L'*' || GetChar(sRef,I) == L'?' || GetChar(sRef,I) == L'"' || GetChar(sRef,I) == L'|' ) {
			return false;
		}
		I++;
	}
	return true;
}

bool removeExtension(wchar_t* sInput, wchar_t sOutput[260]) {
	int I;
	int J;
	int iDotIndex;
	int iLenInput;
	iLenInput = lengthOfString_wide(sInput);
	iDotIndex = lastOfLetter_wide(iLenInput - 1, sInput, L'.');
	if (iDotIndex < lastSlash(sInput)) {
		// If the last dot is in a folder name, ignore it.
		iDotIndex = -1;
	}
	if (iLenInput > 259) {
		SetSafeChar(sOutput,0,L'\0');
		return false;
	}
	if (iDotIndex > -1) {
		J = 0;
		// Print input before dot
		LoopForward(0, I, iDotIndex - 1) {
			SetSafeChar(sOutput,J,GetChar(sInput,I)); J++;
		}
		// Close the string
		sOutput[J] = L'\0';
	} else {
		J = 0;
		// Print input
		LoopForward(0, I, iLenInput - 1) {
			SetSafeChar(sOutput,J,GetChar(sInput,I)); J++;
		}
		// Close the string
		sOutput[J] = L'\0';
	}
	return true;
}

#define MBOM2_wide(mA,mB) (iA == (wchar_t)mA && iB == (wchar_t)mB)
#define MBOM3_wide(mA,mB,mC) (iA == (wchar_t)mA && iB == (wchar_t)mB && iC == (wchar_t)mC)
#define MBOM4_wide(mA,mB,mC,mD) (iA == (wchar_t)mA && iB == (wchar_t)mB && iC == (wchar_t)mC && iD == (wchar_t)mD)

#define MBOM2(mA,mB) (iA == (char)mA && iB == (char)mB)
#define MBOM3(mA,mB,mC) (iA == (char)mA && iB == (char)mB && iC == (char)mC)
#define MBOM4(mA,mB,mC,mD) (iA == (char)mA && iB == (char)mB && iC == (char)mC && iD == (char)mD)

wchar_t* GetBOM_wide(wchar_t* sRef) {
	wchar_t iA; wchar_t iB; wchar_t iC; wchar_t iD;
	iA = (sRef[0] + 65536) % 256;
	iB = (sRef[1] + 65536) % 256;
	iC = (sRef[2] + 65536) % 256;
	iD = (sRef[3] + 65536) % 256;
	if MBOM3_wide(239,187,191) return L"UTF-8";
	if MBOM2_wide(254,255) return L"UTF-16 big endian";
	if MBOM2_wide(255,254) return L"UTF-16 big endian";
	if MBOM4_wide(0,0,254,255) return L"UTF-32 big endian";
	if MBOM4_wide(255,254,0,0) return L"UTF-32 little endian";
	if MBOM3_wide(43,47,118) return L"UTF-7";
	if MBOM3_wide(247,100,76) return L"UTF-1";
	if MBOM4_wide(221,115,102,115) return L"UTF-EBCDIC";
	if MBOM3_wide(14,254,255) return L"SCSU";
	if MBOM3_wide(251,238,40) return L"BOCU-1";
	if MBOM4_wide(132,49,149,51) return L"GB-18030";
	return NULL;
}

wchar_t* GetBOM(char* sRef) {
	char iA; char iB; char iC; char iD;
	iA = sRef[0]; iB = sRef[1]; iC = sRef[2]; iD = sRef[3];
	if MBOM3(239,187,191) return L"UTF-8";
	if MBOM2(254,255) return L"UTF-16 big endian";
	if MBOM2(255,254) return L"UTF-16 big endian";
	if MBOM4(0,0,254,255) return L"UTF-32 big endian";
	if MBOM4(255,254,0,0) return L"UTF-32 little endian";
	if MBOM3(43,47,118) return L"UTF-7";
	if MBOM3(247,100,76) return L"UTF-1";
	if MBOM4(221,115,102,115) return L"UTF-EBCDIC";
	if MBOM3(14,254,255) return L"SCSU";
	if MBOM3(251,238,40) return L"BOCU-1";
	if MBOM4(132,49,149,51) return L"GB-18030";
	return NULL;
}

void OnlyPath(wchar_t* sRef) {
	int Slash;
	int I;
	Slash = lastSlash(sRef);
	if (Slash > -1) {
		LoopBackward(0,I,Slash) {
			if (GetChar(sRef,I) == L'\\' || GetChar(sRef,I) == L'/') {
				SetChar(sRef,I,L'\0');
			} else {
				return;
			}
		}
	} else {
		sRef[0] = L'\0';
	}
}

int ParseIntFromPartOfString(char* sInput,int start,int end) {
	int i;
	int result;
	bool negated;
	wchar_t c;
	result = 0;
	negated = false;
	LoopForward(start,i,end) {
		c = GetChar(sInput,i);
		if (c == '-' || c == '~') {
			negated = !negated;
		} else if (c >= '0' && c <= '9') {
			result = (result * 10) + (c - '0');
		}
	}
	if (negated) {
		return -result;
	} else {
		return result;
	}
}

UINT64 CheckSumFromString(char* Content) {
	UINT64 checksum;
	unsigned char Random[8];
	int I;
	int CounterA, CounterB, CounterC, CounterD, CounterE;
	checksum = 0;
	Random[0] = 17;
	Random[1] = 212;
	Random[2] = 32;
	Random[3] = 68;
	Random[4] = 11;
	Random[5] = 248;
	Random[6] = 12;
	Random[7] = 223;
	CounterA = 5;
	CounterB = 1;
	CounterC = 6;
	CounterD = 3;
	CounterE = 4;
	
	I = 0;
	while (Content[I] != 0) {
		Random[CounterA] = (Random[CounterA] + Content[I]) % 256;
		Random[(CounterA + 1) % 8] = (Random[(CounterA + 1) % 8] ^ Content[I]) % 256;
		Random[(CounterA + 2) % 8] = (Random[(CounterA + 2) % 8] + Content[I]) % 256;
		Random[(CounterA + 3) % 8] = (Random[(CounterA + 3) % 8] ^ Random[CounterC % 8]) % 256;
		Random[(CounterA + 4) % 8] = (Random[(CounterA + 4) % 8] + Random[CounterB % 8]) % 256;
		Random[(CounterA + 5) % 8] = (Random[(CounterA + 5) % 8] + Random[CounterE % 8]) % 256;
		Random[(CounterA + 6) % 8] = (Random[(CounterA + 6) % 8] ^ Random[CounterC % 8]) % 256;
		Random[(CounterA + 7) % 8] = (Random[(CounterA + 7) % 8] ^ Random[CounterE % 8]) % 256;
		
		CounterA = (CounterA + 1) % 8;
		CounterB = (CounterB + (Random[1] % 8)) % 8;
		CounterC = (CounterC + (Random[3] % 8)) % 8;
		CounterD = (CounterD + (Random[4] % 8)) % 8;
		CounterE = (CounterE + (Random[6] % 8)) % 8;
		
		I++;
	}
	memcpy(&checksum,Random,8);
	
	return checksum;
}

bool AddSubDir(wchar_t* sInput, wchar_t sOutput[260], wchar_t* sDirName) {
	int I;
	int J;
	int iLastSlash;
	int iLenInput;
	int iLenDirName;
	
	iLenInput = lengthOfString_wide(sInput);
	iLenDirName = lengthOfString_wide(sDirName);
	iLastSlash = lastSlash(sInput);
	if (iLenInput + iLenDirName + 1 > 259) {
		SetSafeChar(sOutput,0,L'\0');
		return false;
	}
	J = 0;
	// Print input before and including last slash
	LoopForward(0, I, iLastSlash) {
		SetSafeChar(sOutput,J,GetChar(sInput,I)); J++;
	}
	// Print dir
	LoopForward(0, I, iLenDirName - 1) {
		SetSafeChar(sOutput,J,GetChar(sDirName,I)); J++;
	}
	// Print back slash
	sOutput[J] = L'\\'; J++;
	// Print input after any last slash
	LoopForward(iLastSlash + 1, I, iLenInput - 1) {
		SetSafeChar(sOutput,J,GetChar(sInput,I)); J++;
	}
	// Close the string
	sOutput[J] = L'\0';
	return true;
}
