Commits

Palmer, 2E0EOL committed 748980c

All code from svn trunk, no other history

  • Participants
  • Tags 0.6.0

Comments (0)

Files changed (32)

+0.5
+DDRP - Changed to use new standard stdint.h99/stdbool.h99 Daybo Logic
+replacement files on systems not using C99 standards.
+DDRP - Added stringent compile warnings on GNU C
+
+0.4
+DDRP - Interlaced adding of files to the free list and digesting them
+
+0.3
+DDRP - Fixed listings of iterations
+DDRP - Optimised free list
+
+0.2
+DDRP - Initial release
+#
+#    Daybo Logic Dupfiles.
+#    Copyright (C) 2005 David Duncan Ross Palmer, Daybo Logic.
+#
+#    All rights reserved, see license.txt for more information.
+
+THISFILE=GNUmakefile
+LL_H=../ll.h
+LL_C=../ll.c
+LL_O=./ll.o
+HEADERS=$(LL_H)
+#LIBS=/usr/local/lib/libdaybocrypt.a
+LIBS=/opt/lib/libdaybocrypt.a
+MASTERDEPS=$(THISFILE) $(HEADERS)
+OPTLEVEL=-O3
+DBG=-g
+INSTDIR=/usr/local/bin/
+INCLUDE=-I.. -I/usr/local/include -I. -I../shared/c99.h -I/opt/include
+DEFINES=-DHAVE_STDINT_H -DNO_DPCRTLMM -DONE_OUTPUT -D__UNIX__ -DNDEBUG -DRCS_STAMPS -DHAVE_STDBOOL_H
+TARGET=./dupfiles
+ERASE=perl -w ../shared/scripts/erase.pl
+WARNINGS=-Wall -W
+
+ifndef DEBUG
+CFLAGS=$(OPTLEVEL) $(INCLUDE) $(DEFINES) $(WARNINGS)
+STRIP=strip
+else
+CFLAGS=$(DBG) $(INCLUDE) $(DEFINES) $(WARNINGS)
+STRIP=
+endif
+
+CC=cc
+
+$(TARGET) : dupfiles.o $(LL_O) $(MASTERDEPS) $(LIBS)
+	$(CC) -o $@ $< $(LL_O) $(LIBS)
+ifndef DEBUG
+	$(STRIP) $(TARGET)
+endif
+
+dupfiles.o : dupfiles.c $(MASTERDEPS) $(LL_H)
+	$(CC) -c -o $@ $< $(CFLAGS)
+
+$(LL_O) : $(LL_C) $(LL_H) $(MASTERDEPS)
+	$(CC) -c -o $@ $< $(CFLAGS)
+
+
+#----------- Commands ----------------------
+
+run : $(TARGET)
+	$(TARGET)
+
+#-------------------------------------------
+
+clean:
+	-$(ERASE) $(TARGET)
+	-$(ERASE) dupfiles.o
+	-$(ERASE) $(LL_O)
+
+#----------- Installation ------------------
+
+install : $(TARGET)
+	@cp -v $(TARGET) $(INSTDIR)
+
+uninstall : deinstall
+deinstall:
+	-@rm -v $(INSTDIR)$(TARGET)

File Makefile.bor

+#
+# Daybo Logic DupFiles
+# (C) Copyright 2004 David Duncan Ross Palmer, Daybo Logic,
+# all rights reserved.
+#
+# http://www.daybologic.co.uk/
+#
+#
+# To force a 32-bit compile, use make -f -DBCC32=1 Makefile.bor
+#
+
+#EXE=.exe
+THISFILE=Makefile.bor
+LL_H=../ll.h
+LL_C=../ll.c
+LL_O=ll.obj
+HEADERS=$(LL_H)
+LIBS=../shared/dybocryp/dybocryp.lib
+MASTERDEPS=$(THISFILE) $(HEADERS)
+OPTLEVEL=-O2
+DBG=-v
+INSTDIR=/usr/local/bin/
+INCLUDE=-I.. -I../shared/dybocryp -I../shared/c99.h -I.
+DEFINES=-DNO_DPCRTLMM -DONE_OUTPUT
+TARGET=dupfiles$(EXE)
+ERASE=erase
+
+!ifndef DEBUG
+CFLAGS=$(DEFINES) $(OPTLEVEL) $(INCLUDE)
+STRIP=tdstrp32
+!else
+CFLAGS=$(DEFINES) $(DBG) $(INCLUDE)
+STRIP=
+!endif
+
+!ifdef BCC32
+CC=bcc32
+!endif
+
+!ifndef CC
+CC=bcc32
+!endif
+
+$(TARGET) : dupfiles.obj $(LL_O) $(MASTERDEPS) $(LIBS)
+	$(CC) -e$@ dupfiles.obj $(LL_O) $(LIBS)
+!ifndef DEBUG
+	$(STRIP) $(TARGET)
+!endif
+
+dupfiles.o : dupfiles.c $(MASTERDEPS) $(LL_H)
+	$(CC) $(CFLAGS) -c -o$@ $<
+
+$(LL_O) : $(LL_C) $(MASTERDEPS) $(LL_H)
+	$(CC) $(CFLAGS) -c -oll.obj ..\ll.c
+
+
+#----------- Commands ----------------------
+
+run : $(TARGET)
+	$(TARGET)
+
+#-------------------------------------------
+
+clean:
+	-$(ERASE) $(TARGET)
+	-$(ERASE) dupfiles.obj
+	-$(ERASE) $(LL_O)
+
+#----------- Installation ------------------
+
+#install : $(TARGET)
+#       @cp -v $(TARGET) $(INSTDIR)
+
+#uninstall : deinstall
+#deinstall:
+#       -@rm -v $(INSTDIR)$(TARGET)
+dupfiles
+--------
+
+Willcommen!  Dupfiles by Daybo Logic is a tool to search for duplicate
+files, no matter what their names, dates or attributes.
+
+To run the tool, under DOS or Windows:
+
+dir /s /b | dupfiles
+
+or on UNIX or GNU systems:
+
+ls -1 | dupfiles
+
+The program will run for a few minutes (depending on the number of / size
+of files under the current directory.  The names of matching files are
+displayed, line by line, in this fashion:
+
+file1 == file2
+/*
+  Daybo Logic DupFiles by David Duncan Ross Palmer.
+  This source code remains the intellectual property of Daybo Logic.
+  Copyright 2005-2006 Daybo Logic, all rights reserved.
+
+  See license.txt for more information.
+*/
+
+#include <assert.h>
+#include <stdio.h> /* Output to the console */
+#include <stdlib.h> /* For EXIT_SUCCESS */
+#include <string.h>
+#include <limits.h>
+#include <sys/stat.h> /* POSIX dependant */
+
+#ifdef __UNIX__
+# include <unistd.h> /* UNIX specific header */
+#endif
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#else
+/*# include "../shared/dybocryp-1.1.0/stdint.h99"*/
+#endif /*HAVE_STDINT_H*/
+
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include "stdbool.h99"
+#endif /*HAVE_STDBOOL_H*/
+
+#ifdef HDRSTOP
+# pragma hdrstop
+#endif /*HDRSTOP*/
+
+#include "ll.h" /* Generic linked list */
+#include "daybocrypt.h" /* One way hash functions */
+/*-----------------------------------------------------------*/
+/*
+  If you want to use stdout for stderr output, define ONE_OUTPUT
+*/
+#ifdef ONE_OUTPUT
+# define HERROR stdout
+#else
+# define HERROR stderr
+#endif /*ONE_OUTPUT*/
+
+#define HASHLEN DAYBOCRYPT_MD5_HASHLEN
+#define HASHCTX MD5_CTX
+
+/* First we need a type to store the entry for one file */
+struct file_node {
+  char* fileName; /* Dynamically allocated */
+  unsigned char digest[HASHLEN];
+  bool matched; /* Used to stop bi-directional matches */
+};
+
+enum addFileError {
+  afSuccess,
+  afDuplicate, /* Duplicate filename dropped */
+  afMemory,    /* Memory exhausted */
+  afParam,     /* Invalid parameter */
+  afCantOpen   /* Cannot open the file */
+};
+
+/* Error numbers */
+#define ERROR_SUCCESS        (0)
+#define ERROR_MEMORY         (1)
+#define ERROR_BADOPT         (2)
+#define ERROR_DUPFILE        (3)
+#define ERROR_INTERNAL_PARAM (4)
+#define ERROR_UNKNOWN        (5)
+#define ERROR_CANTOPEN       (6)
+/*-------------------------------------------------------------------------*/
+static struct link_ptrs FileList;
+
+static struct {
+  bool Quiet;
+  bool Unlink;
+  bool Mismatches;
+  bool Verbose;
+  bool Debug;
+  bool Help;
+  bool NoMoreOptions;
+} Options;
+
+#ifdef RCS_STAMPS
+static char rcsid[] = "$Id: dupfiles.c,v 0.6 2006/12/30 11:19:00 ddrp Exp $";
+#endif /*RCS_STAMPS*/
+/*-------------------------------------------------------------------------*/
+static void Title(void);
+static void Help(void);
+static enum addFileError AddAndHashFile(
+  const char *FileName
+);
+static enum addFileError AddFileInternal(
+  const char *FileName
+);
+static bool IsFileHere(
+  const char *FileName
+);
+static const char *GetErrorMessage(
+  const unsigned int ErrNum
+);
+static void PrintErrorMessage(
+  const unsigned int ErrNum
+);
+static char *Chomp(
+  char *Str
+);
+static bool HashFile(
+  const char *FileName,
+  unsigned char Hash[HASHLEN]
+);
+static void SearchDups(void);
+#if 0
+static void PrintHash(
+  const char *FileName,
+  const unsigned char Hash[HASHLEN]
+);
+#endif /*0*/
+static bool AndMD5(
+  const unsigned char DigestA[HASHLEN],
+  const unsigned char DigestB[HASHLEN]
+);
+static bool TestZeroMD5Sum(
+  const unsigned char Digest[HASHLEN]
+);
+
+#ifdef RCS_STAMPS
+static void Unused(
+  void *Arg,
+  int FakeCall
+);
+#endif /*RCS_STAMPS*/
+/*-----------------------------------------------------------*/
+int main(
+  const int argc,
+  const char *argv[]
+)
+{
+  int argi;
+
+  #ifdef RCS_STAMPS
+    Unused(rcsid, 0);
+  #endif /*RCS_STAMPS*/
+
+  link_ptrs_init(&FileList, sizeof(struct file_node));
+  for ( argi = 1; argi < argc; argi++ ) {
+    if ( (!Options.NoMoreOptions) && argv[argi][0] == '-' ) { /* An option? */
+      if ( (strcmp(argv[argi], "--quiet") == 0) || (strcmp(argv[argi], "-q") == 0) ) {
+        Options.Quiet = 1;
+        continue;
+      }
+      if ( (strcmp(argv[argi], "--unlink") == 0 ) || (strcmp(argv[argi], "-u") == 0) ) {
+        Options.Unlink = 1;
+        continue;
+      }
+      if ( (strcmp(argv[argi], "--mismatches") == 0) || (strcmp(argv[argi], "-m") == 0) ) {
+        Options.Mismatches = 1;
+        continue;
+      }
+      if ( (strcmp(argv[argi], "--verbose") == 0) || (strcmp(argv[argi], "-v") == 0) ) {
+        Options.Verbose = 1;
+        continue;
+      }
+      if ( (strcmp(argv[argi], "--debug") == 0) || ( strcmp(argv[argi], "-d") == 0) ) {
+        Options.Verbose = 1; /* Implied */
+        Options.Debug = 1;
+        continue;
+      }
+      if ( (strcmp(argv[argi], "--help") == 0) || (strcmp(argv[argi], "-h") == 0) ) {
+        Options.Help = 1;
+        continue;
+      }
+      if ( (strcmp(argv[argi], "--") == 0) ) {
+        Options.NoMoreOptions = 1;
+        continue;
+      }
+      fprintf(HERROR, "%s: %s\n", GetErrorMessage(ERROR_BADOPT), argv[argi]);
+    }
+    else {
+      if ( AddAndHashFile(argv[argi]) == afMemory )
+        break;
+    }
+  }
+
+  if ( !Options.Quiet ) Title();
+
+  if ( Options.Help ) {
+    Help();
+  }
+  else {
+    if ( !FileList.Count(&FileList) ) { /* No command line files? */
+      /* Now move on to stdin filenames */
+      while ( !feof(stdin) ) {
+        char oneFile[FILENAME_MAX+1];
+        if ( fgets(oneFile, sizeof(oneFile), stdin) ) {
+          Chomp(oneFile);
+          if ( AddAndHashFile(oneFile) == afMemory )
+            break;
+        }
+      }
+    }
+  }
+
+  if ( !FileList.Count(&FileList) ) {
+    printf("No files specified.\nNothing to do.\n");
+  }
+  else
+    SearchDups();
+
+  return EXIT_SUCCESS;
+}
+/*-----------------------------------------------------------*/
+static void Title()
+{
+  const char* hashLegal;
+
+  printf(
+    "Daybo Logic DupFiles 0.6 (20061230) Copyright (C) "
+    "2005-2006 David D. R. Palmer\n"
+  );
+  hashLegal = daybocrypt_MD5GetLegalString();
+  if ( hashLegal )
+    printf("%s\n", hashLegal);
+  putchar('\n');
+}
+/*-----------------------------------------------------------*/
+static void Help()
+{
+  printf("dupfiles [options] [filenames ...]\n");
+  printf("-h (--help) : Get help for usage (this)\n");
+  printf("-q (--quiet) : Don't print copyright banner (useful for automation)\n");
+  printf("-u (--unlink) : Delete duplicates\n");
+  printf("-m (--mismatches) : Display mismatches as well as matches\n");
+  printf("-v (--verbose) : Display progress and such\n");
+  printf("-d (--debug) : Display extra verbose debug crap, implies -v\n");
+  printf("-V (--version) : Display version info and exit\n");
+  printf("--: Don\'t accept further options.\n\n");
+
+  printf("dupfiles can accept filenames via the command line or standard input\n");
+  printf("stdin is only read if no filenames are specified on the command line.\n\n");
+}
+/*-------------------------------------------------------------------------*/
+static enum addFileError AddAndHashFile(
+  const char *FileName
+)
+{
+  /* Wrapper which prints messages */
+  enum addFileError afe;
+
+  if ( Options.Debug )
+    printf("Adding \"%s\"...\n", FileName);
+
+  afe = AddFileInternal(FileName);
+  if ( afe == afSuccess ) {
+    struct file_node node;
+    FileList.GetTail(&FileList, &node);
+
+    if ( Options.Verbose )
+      printf("Digesting \"%s\"...", node.fileName);
+
+    if ( HashFile(node.fileName, node.digest) ) {
+      if ( Options.Verbose )
+        puts("OK");
+
+      FileList.SetTail(&FileList, &node);
+    }
+    else {
+      if ( Options.Verbose )
+        puts("FAIL");
+
+      afe = afCantOpen;
+    }
+  }
+
+  if ( afe != afSuccess ) {
+    if ( afe == afDuplicate )
+      fprintf(HERROR, "%s - %s\n", GetErrorMessage(ERROR_DUPFILE), FileName);
+    else if ( afe == afMemory )
+      fprintf(HERROR, "%s - %s\n", GetErrorMessage(ERROR_MEMORY), FileName);
+    else if ( afe == afCantOpen )
+      fprintf(HERROR, "%s - %s\n", GetErrorMessage(ERROR_CANTOPEN), FileName);
+    else if ( afe == afParam )
+      PrintErrorMessage(ERROR_INTERNAL_PARAM);
+    else
+      PrintErrorMessage(ERROR_UNKNOWN);
+  }
+
+  return afe;
+}
+/*-------------------------------------------------------------------------*/
+static enum addFileError AddFileInternal(
+  const char *FileName
+)
+{
+  struct file_node newFile;
+
+  assert(FileName);
+  if ( !FileName ) return afParam; /* Bad parameters */
+  if ( IsFileHere(FileName) ) return afDuplicate;
+
+  newFile.fileName = malloc( strlen(FileName) + 1 );
+  if ( newFile.fileName ) {
+    strcpy(newFile.fileName, FileName);
+    memset(newFile.digest, 0, sizeof(newFile.digest)); /* Zero message digest */
+    newFile.matched = false;
+    if ( FileList.AddToTail(&FileList, &newFile) )
+      return afSuccess;
+    else {
+      free(newFile.fileName);
+    }
+  }
+  return afMemory;
+}
+/*-----------------------------------------------------------*/
+static bool IsFileHere(
+  const char *FileName
+)
+{
+  struct file_node node;
+  unsigned int pos, count;
+
+  count = FileList.Count(&FileList);
+  for ( pos = 0U; pos < count; pos++ ) {
+    FileList.Get(&FileList, pos, &node);
+    assert(node.fileName);
+    if ( node.fileName ) {
+      if ( strcmp(node.fileName, FileName) == 0 )
+        return true;
+    }
+  }
+  return false;
+}
+/*-------------------------------------------------------------------------*/
+static const char* GetErrorMessage(const unsigned int ErrNum)
+{
+  static const char defaultMessage[] = "(error out of range)";
+  static const char* messages[] = {
+    "Success",                                              /*ERROR_SUCCESS*/
+    "Out of memory",                                         /*ERROR_MEMORY*/
+    "Unrecognised parameter",                                /*ERROR_BADOPT*/
+    "Duplicate filename",                                   /*ERROR_DUPFILE*/
+    "Internal parameter fault",                      /*ERROR_INTERNAL_PARAM*/
+    "ERROR_UNKNOWN",                                        /*ERROR_UNKNOWN*/
+    "Cannot open file",                                    /*ERROR_CANTOPEN*/
+  };
+  const char* msg = defaultMessage;
+
+  if ( ErrNum < sizeof(messages)/sizeof(messages[0]) )
+    msg = messages[ErrNum];
+
+  return msg;
+}
+/*-------------------------------------------------------------------------*/
+static void PrintErrorMessage(const unsigned int ErrNum)
+{
+  const char* errStr = GetErrorMessage(ErrNum);
+  fprintf(HERROR, "ERROR: %s\n", (errStr) ? (errStr) : ("???"));
+  return;
+}
+/*-------------------------------------------------------------------------*/
+static char* Chomp(char* Str)
+{
+  assert(Str);
+  if ( Str ) {
+    int len = strlen(Str);
+    if ( len ) {
+      if ( Str[len-1] == '\n' )
+        Str[len-1] = '\0';
+    }
+  }
+  return Str;
+}
+/*-------------------------------------------------------------------------*/
+static bool HashFile(const char* FileName, unsigned char Hash[HASHLEN])
+{
+  FILE* handle;
+  struct stat statInfo;
+
+  memset(&statInfo, 0, sizeof(statInfo));
+  stat(FileName, &statInfo);
+
+  if ( S_ISDIR(statInfo.st_mode) )
+    return false; /* Don't bother with directories */
+
+  handle = fopen(FileName, "rb");
+  if ( handle ) {
+    HASHCTX ctx;
+    unsigned long int bytesRead;
+    unsigned char byte;
+
+    daybocrypt_MD5Init(&ctx);
+
+    do {
+      bytesRead = fread(&byte, sizeof(byte), 1, handle);
+      if ( bytesRead ) daybocrypt_MD5Update(&ctx, &byte, sizeof(byte));
+    } while (bytesRead);
+
+    daybocrypt_MD5Final(Hash, &ctx);
+    fclose(handle);
+  }
+  else {
+    fprintf(HERROR, "Error: %s \"%s\"\n", GetErrorMessage(ERROR_CANTOPEN), FileName);
+    return false;
+  }
+
+  return true;
+}
+/*-------------------------------------------------------------------------*/
+static void SearchDups()
+{
+  unsigned int i, j, c;
+
+  c = FileList.Count(&FileList);
+  for ( i = 0U; i < c; i++ ) { /* Main search loop (file A) */
+    struct file_node nodeA;
+    FileList.Get(&FileList, i, &nodeA);
+    for ( j = 0U; j < c; j++ ) { /* Secondary search loop (file B) */
+      struct file_node nodeB;
+      FileList.Get(&FileList, j, &nodeB);
+
+      if ( i != j && !(nodeA.matched || nodeB.matched) ) {
+        /* OK we have both nodes, compare */
+        if ( AndMD5(nodeA.digest, nodeB.digest) ) {
+          if ( daybocrypt_MD5CompareDigests(nodeA.digest, nodeB.digest) ) {
+            printf("%s == %s\n", nodeA.fileName, nodeB.fileName);
+            nodeB.matched = true;
+            FileList.Set(&FileList, j, &nodeB);
+            if ( Options.Unlink ) {
+              if ( remove(nodeB.fileName) == -1 ) {
+                fprintf(stderr, "Error deleting \"%s\"\n", nodeB.fileName);
+              }
+            }
+          }
+          else {
+            if ( Options.Mismatches )
+              printf("%s != %s\n", nodeA.fileName, nodeB.fileName);
+          }
+        }
+      }
+    }
+  }
+  return;
+}
+/*-------------------------------------------------------------------------*/
+#if 0
+static void PrintHash(
+  const char* FileName,
+  const unsigned char Hash[HASHLEN]
+)
+{
+  unsigned int i;
+
+  if ( FileName ) printf("%s : ", FileName);
+
+  for ( i = 0U; i < HASHLEN; i++ )
+    printf("%02x", Hash[i]);
+
+  putchar('\n');
+}
+#endif /*0*/
+/*-------------------------------------------------------------------------*/
+static bool AndMD5(
+  const unsigned char DigestA[HASHLEN],
+  const unsigned char DigestB[HASHLEN]
+)
+{
+  if ( (!TestZeroMD5Sum(DigestA)) && (!TestZeroMD5Sum(DigestB)) )
+    return true;
+
+  return false;
+}
+/*-------------------------------------------------------------------------*/
+static bool TestZeroMD5Sum(const unsigned char Digest[HASHLEN])
+{
+  unsigned int i;
+
+  for ( i = 0U; i < HASHLEN; i++ ) {
+    if ( Digest[i] != '\0' )
+      return false;
+  }
+  return true;
+}
+/*-------------------------------------------------------------------------*/
+#ifdef RCS_STAMPS
+static void Unused(
+  void *Arg,
+  int FakeCall
+)
+{
+  if ( !FakeCall ) {
+    FakeCall = 1;
+    Unused(Arg, FakeCall);
+  }
+}
+#endif /*RCS_STAMPS*/
+/*-------------------------------------------------------------------------*/
+blah
+blah
+blah

File win32_gui/AboutUnit.cpp

+//---------------------------------------------------------------------------
+#include <vcl.h>
+#include <shellapi.h>
+#include <limits.h>
+#ifdef HAVE_STDINT_H // C99 compliant stdint.h present?
+# include <stdint.h>
+#else // No stdint.h, use my replacement
+# include "stdint.c99"
+#endif //HAVE_STDINT_H
+#pragma hdrstop
+
+#include "dupfiles.h"
+#include "daybocrypt.h" // For version info only
+#include "AboutUnit.h"
+//---------------------------------------------------------------------------
+#pragma package(smart_init)
+#pragma resource "*.dfm"
+TAboutForm *AboutForm = NULL; // Don't use the global version
+//---------------------------------------------------------------------------
+__fastcall TAboutForm::TAboutForm(TComponent* Owner)
+        : TForm(Owner)
+{
+}
+//---------------------------------------------------------------------------
+void __fastcall TAboutForm::FormCreate(TObject *Sender)
+{
+  HDC context; // Device context for Memo1
+  TEXTMETRIC metrics;
+  const AnsiString period("."); // For separating the version number
+  struct {
+    AnsiString str; // String represenation for dialog
+    unsigned int Major, Minor, Patch;
+  } dcVer;
+
+  // Determine DayboCrypt version
+  dcVer.Major = daybocrypt_GetVersion(&dcVer.Minor, &dcVer.Patch);
+  dcVer.str =
+    "DayboCrypt version: " +
+    (AnsiString)dcVer.Major + period +
+    (AnsiString)dcVer.Minor + period +
+    (AnsiString)dcVer.Patch;
+
+  Caption = "About " + Application->Title;
+  Memo1->Lines->Clear();
+  Memo1->Lines->Add(Application->Title);
+  Memo1->Lines->Add("Written by David Duncan Ross Palmer");
+  Memo1->Lines->Add("(C) Copyright 2004 Daybo Logic, all rights reserved.");
+  Memo1->Lines->Add(""); // Effectively a newline
+  Memo1->Lines->Add(dcVer.str);
+
+  // Now do some dynamic-sizing math
+  context = GetDC(this->Memo1->Handle);
+  GetTextMetrics(context, &metrics);
+  ReleaseDC(this->Memo1->Handle, context);
+  ClientHeight = MAX(
+    (metrics.tmHeight * 5) + this->Panel1->Height,
+    this->Image1->Height
+  );
+  Memo1->Left = Image1->Width;
+  ClientWidth = 64 +
+    (metrics.tmAveCharWidth * LongestLine(this->Memo1->Lines));
+  Memo1->Width = ClientWidth - Image1->Width;
+
+  this->OkBtn->Left = ( Width /2 ) - (this->OkBtn->Width /2);
+}
+//---------------------------------------------------------------------------
+unsigned int TAboutForm::LongestLine(TStrings *PLines)
+{
+  unsigned int longest = 0U;
+  unsigned int i, c;
+
+  if ( PLines && PLines->Count > 0 ) {
+    c = static_cast<unsigned int>(PLines->Count);
+    for ( i = 0U; i < c; i++ ) {
+      unsigned int length = static_cast<unsigned int>(
+        PLines->Strings[i].Length()
+      );
+
+      if ( length > longest )
+        longest = length;
+    }
+  }
+  return longest;
+}
+//---------------------------------------------------------------------------
+void __fastcall TAboutForm::Image1Click(TObject *Sender)
+{
+  TCursor oldCursor = Screen->Cursor;
+  Screen->Cursor = crHourGlass; // Look busy
+
+  // Display the Daybo Logic website
+  ShellExecute(
+    GetDesktopWindow(),
+    "open",
+    "http://www.daybologic.co.uk/",
+    0,
+    0,
+    SW_SHOWNORMAL
+  );
+
+ Screen->Cursor = oldCursor; // Restore cursor 
+}
+//---------------------------------------------------------------------------
+

File win32_gui/AboutUnit.dfm

Binary file added.

File win32_gui/AboutUnit.h

+//---------------------------------------------------------------------------
+#ifndef AboutUnitH
+#define AboutUnitH
+//---------------------------------------------------------------------------
+#include <Classes.hpp>
+#include <Controls.hpp>
+#include <StdCtrls.hpp>
+#include <Forms.hpp>
+#include <Buttons.hpp>
+#include <ExtCtrls.hpp>
+#include <jpeg.hpp>
+//---------------------------------------------------------------------------
+class TAboutForm : public TForm
+{
+__published:	// IDE-managed Components
+        TMemo *Memo1;
+        TPanel *Panel1;
+        TBitBtn *OkBtn;
+        TImage *Image1;
+        void __fastcall FormCreate(TObject *Sender);
+        void __fastcall Image1Click(TObject *Sender);
+private:	// User declarations
+        unsigned int LongestLine(TStrings *PLines);
+public:		// User declarations
+        __fastcall TAboutForm(TComponent* Owner);
+};
+//---------------------------------------------------------------------------
+extern PACKAGE TAboutForm *AboutForm;
+//---------------------------------------------------------------------------
+#endif

File win32_gui/AssertUnit.cpp

+//---------------------------------------------------------------------------
+#include <vcl.h>
+#pragma hdrstop
+
+#include "AssertUnit.h"
+#include "BsodUnit.h"
+//---------------------------------------------------------------------------
+void DupFilesAssert(const char* File, unsigned int Line, const char* Expression)
+{
+  AnsiString message;
+
+  message = "Internal error!\n";
+  message = message + (AnsiString)Expression + " in file " + File + " line " + (AnsiString)Line + "\n";
+  message = message + "Please report this bug to Daybo Logic at the Daybo Logic website.\n";
+  message = message + "\nThe program will now be terminated.";
+  
+  BsodForm->SetMessage(message);
+  BsodForm->ShowModal();
+  Application->Terminate();
+}
+//---------------------------------------------------------------------------
+#pragma package(smart_init)

File win32_gui/AssertUnit.h

+#ifndef AssertUnitH
+#define AssertUnitH
+//---------------------------------------------------------------------------
+
+void DupFilesAssert(const char* File, unsigned int Line, const char* Expression);
+
+#ifdef NDEBUG
+#  define assert(expression) \
+    ((void)0)
+#else // Debugging mode
+#  define assert(expression) \
+    ( (expression) ? (void)0 : DupFilesAssert(__FILE__, __LINE__, (#expression)))
+#endif //NDEBUG
+
+//---------------------------------------------------------------------------
+#endif

File win32_gui/BsodUnit.cpp

+//---------------------------------------------------------------------------
+#include <vcl.h>
+#pragma hdrstop
+
+#include "BsodUnit.h"
+//---------------------------------------------------------------------------
+#pragma package(smart_init)
+#pragma resource "*.dfm"
+TBsodForm *BsodForm;
+//---------------------------------------------------------------------------
+__fastcall TBsodForm::TBsodForm(TComponent* Owner)
+        : TForm(Owner)
+{
+}
+//---------------------------------------------------------------------------
+void TBsodForm::SetMessage(AnsiString& NewMessage)
+{
+  Msg->Caption = NewMessage;
+}
+//---------------------------------------------------------------------------
+void __fastcall TBsodForm::CloseAction(TObject *Sender)
+{
+  Close();
+}
+//---------------------------------------------------------------------------
+void __fastcall TBsodForm::CloseAction2(TObject *Sender, char &Key)
+{
+  CloseAction(NULL);
+}
+//---------------------------------------------------------------------------
+

File win32_gui/BsodUnit.dfm

Binary file added.

File win32_gui/BsodUnit.h

+//---------------------------------------------------------------------------
+#ifndef BsodUnitH
+#define BsodUnitH
+//---------------------------------------------------------------------------
+#include <Classes.hpp>
+#include <Controls.hpp>
+#include <StdCtrls.hpp>
+#include <Forms.hpp>
+//---------------------------------------------------------------------------
+class TBsodForm : public TForm
+{
+__published:	// IDE-managed Components
+        TLabel *Msg;
+        void __fastcall CloseAction(TObject *Sender);
+        void __fastcall CloseAction2(TObject *Sender, char &Key);
+private:	// User declarations
+public:		// User declarations
+        __fastcall TBsodForm(TComponent* Owner);
+        void SetMessage(AnsiString& NewMessage);
+};
+//---------------------------------------------------------------------------
+extern PACKAGE TBsodForm *BsodForm;
+//---------------------------------------------------------------------------
+#endif

File win32_gui/DentryUnit.cpp

+//---------------------------------------------------------------------------
+#include <string>
+#include <climits>
+#ifdef HAVE_STDINT_H // C99 compliant stdint.h present?
+# include <stdint.h>
+#else // No stdint.h, use my replacement
+# include "stdint.c99"
+#endif //HAVE_STDINT_H
+#pragma hdrstop
+
+#include "daybocrypt.h"
+#include "DentryUnit.h"
+//---------------------------------------------------------------------------
+Dentry::Dentry()
+:
+  FileName(""),
+  DigestType(owhfSha1),
+  Digest(NULL),
+  FileLen(0)
+{
+}
+//---------------------------------------------------------------------------
+Dentry::~Dentry()
+{
+  FreeDigest();
+}
+//---------------------------------------------------------------------------
+Dentry::operator == (const Dentry& OtherDentry)
+{
+  return Compare(&OtherDentry);
+}
+//---------------------------------------------------------------------------
+Dentry::operator == (const Dentry* OtherDentryPtr)
+{
+  return Compare(OtherDentryPtr);
+}
+//---------------------------------------------------------------------------
+bool Dentry::IsDup(const Dentry& OtherDentry)
+{
+  return IsDup(&OtherDentry);
+}
+//---------------------------------------------------------------------------
+bool Dentry::IsDup(const Dentry* OtherDentryPtr)
+{
+  if ( this->CompareDigests(OtherDentryPtr) &&
+       this->CompareFileLens(OtherDentryPtr) )
+    return true;
+
+  return false;
+}
+//---------------------------------------------------------------------------
+bool Dentry::CompareFileNames(const Dentry* OtherDentryPtr)
+{
+  return ( this->FileName == OtherDentryPtr->FileName ) ? (true) : (false);
+}
+//---------------------------------------------------------------------------
+bool Dentry::CompareDigests(const Dentry* OtherDentryPtr)
+{
+  int cmp; // Result of comparison
+  size_t len; // Length of digest
+
+  if ( this->DigestType != OtherDentryPtr->DigestType )
+    return false; // Different algorithm, cannot match
+
+  len = daybocrypt_DigestLengthFromType(this->DigestType);
+  cmp = daybocrypt_CompareDigests(this->Digest,
+                                  OtherDentryPtr->Digest,
+                                  len
+  );
+
+  return ( cmp == 1 ) ? (true) : (false);
+}
+//---------------------------------------------------------------------------
+bool Dentry::CompareFileLens(const Dentry* OtherDentryPtr)
+{
+  // I don't know why I'm allowed to access another class instance's
+  // private members, it's a bloody useful thing though.
+  return ( this->FileLen == OtherDentryPtr->FileLen ) ? (true) : (false);
+}
+//---------------------------------------------------------------------------
+bool Dentry::Compare(const Dentry* OtherDentryPtr)
+{
+  if ( CompareFileNames(OtherDentryPtr) &&
+       CompareDigests(OtherDentryPtr) &&
+       CompareFileLens(OtherDentryPtr) )
+    return true;
+
+  return false;
+}
+//---------------------------------------------------------------------------
+void Dentry::FreeDigest()
+{
+  if ( Digest ) {
+    delete[] Digest;
+    Digest = NULL;
+  }
+}
+//---------------------------------------------------------------------------
+#ifdef __BORLANDC__
+#  pragma package(smart_init)
+#endif //__BORLANDC__

File win32_gui/DentryUnit.h

+#ifndef INC_DENTRYUNIT_H
+#define INC_DENTRYUNIT_H
+//---------------------------------------------------------------------------
+class Dentry {
+private:
+  std::string FileName;
+  enum daybocrypt_owhf DigestType; // The digest type in Digest (from that we can determine it's length if necessary)
+  unsigned char* Digest; // Dynamically allocated digest
+  unsigned __int64 FileLen; // Length of file
+protected:
+  bool CompareFileNames(const Dentry* OtherDentryPtr);
+  bool CompareDigests(const Dentry* OtherDentryPtr);
+  bool CompareFileLens(const Dentry* OtherDentryPtr);
+  bool Compare(const Dentry* OtherDentryPtr); // Used by comparison operator
+  void FreeDigest();
+public:
+  Dentry(); // Constructor
+  virtual ~Dentry(); // Destructor
+  // Exact comparisons, tells you if it's the _same_ file
+  operator == (const Dentry&);
+  operator == (const Dentry*);
+  // IsDup() returns true if the size and hash of a file match
+  bool IsDup(const Dentry&);
+  bool IsDup(const Dentry*);
+};
+//---------------------------------------------------------------------------
+#endif //!INC_DENTRYUNIT_H

File win32_gui/DirSelDlgUnit.cpp

+//---------------------------------------------------------------------------
+#include <vcl.h>
+#pragma hdrstop
+
+#include "DirSelDlgUnit.h"
+//---------------------------------------------------------------------------
+#pragma package(smart_init)
+#pragma link "cdiroutl"
+#pragma resource "*.dfm"
+TDirSelDlg *DirSelDlg;
+//---------------------------------------------------------------------------
+__fastcall TDirSelDlg::TDirSelDlg(TComponent* Owner)
+        : TForm(Owner)
+{
+}
+//---------------------------------------------------------------------------
+void TDirSelDlg::CentreOfForm(const TForm* BackgroundForm)
+{
+  if ( BackgroundForm ) {
+    TForm* vclForm = const_cast<TForm*>(BackgroundForm);
+    if ( vclForm ) {
+      Left = vclForm->Left + ((vclForm->Width /2) - (Width/2));
+      Top = vclForm->Top + ((vclForm->Height /2) - (Height/2));
+    }
+  }
+}
+//---------------------------------------------------------------------------
+void TDirSelDlg::Execute(const TForm *const BackgroundForm, const bool Modal)
+{
+  if ( BackgroundForm ) CentreOfForm(BackgroundForm);
+
+  if ( Modal )
+    ShowModal();
+  else
+    Show();
+}
+//---------------------------------------------------------------------------
+void __fastcall TDirSelDlg::FormResize(TObject *Sender)
+{
+  CancelBtn->Left = (Panel1->Width/3) - CancelBtn->Width;
+  OkBtn->Left = (Panel1->Width - (Panel1->Width/3)) - OkBtn->Width;
+}
+//---------------------------------------------------------------------------
+void __fastcall TDirSelDlg::FormCreate(TObject *Sender)
+{
+  FormResize(NULL);
+}
+//---------------------------------------------------------------------------
+AnsiString& TDirSelDlg::GetDir()
+{
+  return CDirectoryOutline1->Directory;
+}
+//---------------------------------------------------------------------------

File win32_gui/DirSelDlgUnit.dfm

Binary file added.

File win32_gui/DirSelDlgUnit.h

+//---------------------------------------------------------------------------
+#ifndef DirSelDlgUnitH
+#define DirSelDlgUnitH
+//---------------------------------------------------------------------------
+#include <Classes.hpp>
+#include <Controls.hpp>
+#include <StdCtrls.hpp>
+#include <Forms.hpp>
+#include <Buttons.hpp>
+#include <ComCtrls.hpp>
+#include <ExtCtrls.hpp>
+#include "cdiroutl.h"
+#include <Grids.hpp>
+#include <Outline.hpp>
+//---------------------------------------------------------------------------
+class TDirSelDlg : public TForm
+{
+__published:	// IDE-managed Components
+        TPanel *Panel1;
+        TBitBtn *OkBtn;
+        TBitBtn *CancelBtn;
+        TCDirectoryOutline *CDirectoryOutline1;
+        void __fastcall FormResize(TObject *Sender);
+        void __fastcall FormCreate(TObject *Sender);
+private:	// User declarations
+        void CentreOfForm(const TForm* BackgroundForm);
+public:		// User declarations
+        __fastcall TDirSelDlg(TComponent* Owner);
+        void Execute(const TForm *const BackgroundForm, const bool Modal);
+        AnsiString& GetDir();
+};
+//---------------------------------------------------------------------------
+extern PACKAGE TDirSelDlg *DirSelDlg;
+//---------------------------------------------------------------------------
+#endif

File win32_gui/MainFormUnit.cpp

+//---------------------------------------------------------------------------
+#include <vcl.h>
+#include <limits.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H // C99 compliant stdint.h present?
+# include <stdint.h>
+#else // No stdint.h, use my replacement
+# include "stdint.c99"
+#endif //HAVE_STDINT_H
+#pragma hdrstop
+
+#include "strtab.rh" // String resources
+#include "daybocrypt.h"
+#include "MainFormUnit.h"
+#include "DirSelDlgUnit.h"
+#include "AssertUnit.h"
+#include "AboutUnit.h"
+//---------------------------------------------------------------------------
+#pragma package(smart_init)
+#pragma resource "*.dfm"
+TMainForm *MainForm;
+
+#define LOADRES(id) \
+  ::LoadString( \
+    GetModuleHandle(NULL), \
+    (id), \
+    buffer, \
+    MAX_LOADSTRING \
+  )
+//---------------------------------------------------------------------------
+__fastcall TMainForm::TMainForm(TComponent* Owner)
+        : TForm(Owner),
+          BaseDir("")
+{
+}
+//---------------------------------------------------------------------------
+void __fastcall TMainForm::MnuMainExitClick(TObject *Sender)
+{
+  this->Close();
+}
+//---------------------------------------------------------------------------
+void __fastcall TMainForm::MnuOptionsRecurseClick(TObject *Sender)
+{
+  this->MnuOptionsRecurse->Checked =
+    !this->MnuOptionsRecurse->Checked;
+}
+//---------------------------------------------------------------------------
+void __fastcall TMainForm::FormResize(TObject *Sender)
+{
+  this->TreeViewFiles->Width = this->ClientWidth / 2;
+  this->TreeViewMatches->Width = this->TreeViewFiles->Width;
+
+  this->TreeViewMatches->Left = this->TreeViewFiles->Width;
+}
+//---------------------------------------------------------------------------
+void __fastcall TMainForm::FormCreate(TObject *Sender)
+{
+  if ( this->LoadRes() ) {
+    this->BasicCaption = Application->Title;
+    Application->OnHint = this->HintHandler; // Install hint handler
+    this->Caption = this->BasicCaption; // Set the default, orignal caption
+  }
+  else { // Failed to load resources
+    this->StatusBar1->SimplePanel = true;
+    this->StatusBar1->SimpleText = "Warning! Failed to load resources";
+    this->Caption = this->StatusBar1->SimpleText;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TMainForm::HintHandler(TObject *HintString)
+{
+  if ( Application->Hint.IsEmpty() ) {
+    this->StatusBar1->SimplePanel = false;
+  }
+  else {
+    this->StatusBar1->SimplePanel = true;
+    this->StatusBar1->SimpleText = Application->Hint;
+  }
+}
+//---------------------------------------------------------------------------
+void __fastcall TMainForm::MnuMainDirselClick(TObject *Sender)
+{
+  DirSelDlg->Execute(this, true); /* Run modal directory selecter */
+  if ( DirSelDlg->ModalResult == mrOk ) {
+    this->UpdateBaseDir(DirSelDlg->GetDir());
+    this->MnuMainStart->Enabled = true;
+  }
+}
+//---------------------------------------------------------------------------
+void TMainForm::UpdateBaseDir(AnsiString& NewBaseDir)
+{
+  AnsiString Separator(" - ");
+
+  this->BaseDir = NewBaseDir;
+  this->Caption = this->BasicCaption + Separator + this->BaseDir;
+}
+//---------------------------------------------------------------------------
+void __fastcall TMainForm::MnuHelpAboutClick(TObject *Sender)
+{
+  TAboutForm *aboutForm;
+  TCursor oldCursor;
+
+  oldCursor = Screen->Cursor;
+  Screen->Cursor = crHourGlass; // Look busy
+  aboutForm = new TAboutForm(this);
+  Screen->Cursor = oldCursor;
+
+  if ( aboutForm ) {
+    aboutForm->ShowModal();
+    delete aboutForm;
+  }
+  else
+    fprintf(stderr, "Not enough memory to create aboutForm\n");
+}
+//---------------------------------------------------------------------------
+void __fastcall TMainForm::MnuMainStartClick(TObject *Sender)
+{
+  this->FeatureMissing("Scan engine");
+}
+//---------------------------------------------------------------------------
+void TMainForm::FeatureMissing(const char* FeatureDescription)
+{
+  if ( FeatureDescription ) {
+    char* vclFeatDesc = const_cast<char*>(FeatureDescription);
+    if ( vclFeatDesc ) {
+      Application->MessageBox(
+        "This feature has not been programmed yet,\n"
+        "I am sorry for any inconvinience.",
+        vclFeatDesc,
+        MB_ICONSTOP
+      );
+    }
+  }
+  else {
+    this->FeatureMissing("(null)");
+  }
+}
+//---------------------------------------------------------------------------
+void TMainForm::FeatureMissing(const AnsiString& FeatureDescription)
+{
+  this->FeatureMissing(FeatureDescription.c_str());
+}
+//---------------------------------------------------------------------------
+void __fastcall TMainForm::MnuOptionsDigHandler(TObject *Sender)
+{
+  TMenuItem *menuItem = dynamic_cast<TMenuItem*>(Sender);
+  if ( menuItem )
+    menuItem->Checked = true;
+
+  assert(menuItem);
+}
+//---------------------------------------------------------------------------
+enum daybocrypt_owhf TMainForm::GetCurrentHashFunction()
+{
+  if ( this->MnuOptionsDigMD2->Checked )
+    return owhfMd2;
+  if ( this->MnuOptionsDigMD4->Checked )
+    return owhfMd4;
+  if ( this->MnuOptionsDigMD5->Checked )
+    return owhfMd5;
+  if ( this->MnuOptionsDigSHA1->Checked )
+    return owhfSha1;
+
+  assert(0);
+  return owhfSha1; // My favourite algorithm as default
+}
+//---------------------------------------------------------------------------
+void TMainForm::SetCurrentHashFunction(const enum daybocrypt_owhf NewOWHF)
+{
+  switch ( NewOWHF ) {
+    case owhfMd2 : {
+      this->MnuOptionsDigMD2->Checked = true;
+      break;
+    }
+    case owhfMd4 : {
+      this->MnuOptionsDigMD4->Checked = true;
+      break;
+    }
+    case owhfMd5 : {
+      this->MnuOptionsDigMD5->Checked = true;
+      break;
+    }
+    case owhfSha1 : {
+      this->MnuOptionsDigSHA1->Checked = true;
+      break;
+    }
+    default : {
+      assert(0);
+    }
+  }
+  return;
+}
+//---------------------------------------------------------------------------
+bool TMainForm::LoadRes()
+{
+  TCHAR buffer[MAX_LOADSTRING];
+  int ret;
+  bool status = false;
+
+  // Load Application->Title
+  ret = LOADRES(R_S_TITLE);
+  if ( ret ) {
+    Application->Title = buffer;
+    status = true;
+  }
+  else return false;
+
+  status = LoadMainMenu1Res(buffer); // For MainMenu1
+  if ( !status ) return false;
+
+  return status;
+}
+//---------------------------------------------------------------------------
+bool TMainForm::LoadMainMenu1Res()
+{
+  char buffer[MAX_LOADSTRING];
+  return this->LoadMainMenu1Res(buffer);
+}
+//---------------------------------------------------------------------------
+bool TMainForm::LoadMainMenu1Res(TCHAR PBuff[MAX_LOADSTRING])
+{
+}
+//---------------------------------------------------------------------------

File win32_gui/MainFormUnit.dfm

Binary file added.

File win32_gui/MainFormUnit.h

+//---------------------------------------------------------------------------
+#ifndef MainFormUnitH
+#define MainFormUnitH
+//---------------------------------------------------------------------------
+#include <Classes.hpp>
+#include <Controls.hpp>
+#include <StdCtrls.hpp>
+#include <Forms.hpp>
+#include <Menus.hpp>
+#include <ExtCtrls.hpp>
+#include <ComCtrls.hpp>
+#include <Dialogs.hpp>
+//---------------------------------------------------------------------------
+class TMainForm : public TForm
+{
+__published:	// IDE-managed Components
+        TMainMenu *MainMenu1;
+        TMenuItem *MnuMain;
+        TMenuItem *MnuMainExit;
+        TMenuItem *MnuHelp;
+        TMenuItem *MnuHelpAbout;
+        TBevel *Bevel1;
+        TMenuItem *MnuOptions;
+        TMenuItem *MnuOptionsRecurse;
+        TMenuItem *MnuMainDirsel;
+        TMenuItem *N1;
+        TTreeView *TreeViewFiles;
+        TTreeView *TreeViewMatches;
+        TStatusBar *StatusBar1;
+        TMenuItem *MnuMainDonate;
+        TMenuItem *MnuMainStart;
+        TMenuItem *N2;
+        TMenuItem *MnuOptionsDig;
+        TMenuItem *MnuOptionsDigMD2;
+        TMenuItem *MnuOptionsDigMD4;
+        TMenuItem *MnuOptionsDigMD5;
+        TMenuItem *N3;
+        TMenuItem *MnuOptionsDigSHA1;
+        TMenuItem *MnuOptionsDigSHA256;
+        void __fastcall MnuMainExitClick(TObject *Sender);
+        void __fastcall MnuOptionsRecurseClick(TObject *Sender);
+        void __fastcall FormResize(TObject *Sender);
+        void __fastcall FormCreate(TObject *Sender);
+        void __fastcall MnuMainDirselClick(TObject *Sender);
+        void __fastcall MnuHelpAboutClick(TObject *Sender);
+        void __fastcall MnuMainStartClick(TObject *Sender);
+        void __fastcall MnuOptionsDigHandler(TObject *Sender);
+private:	// User declarations
+        AnsiString BaseDir; // Base directory we are scanning
+        AnsiString BasicCaption; // Original caption of program
+        void UpdateBaseDir(AnsiString& NewBaseDir); // Update BaseDir and display
+        bool LoadRes(); // Load strings etc. from resource file
+        bool LoadMainMenu1Res(); // Called by LoadRes()
+        bool LoadMainMenu1Res(TCHAR PBuff[MAX_LOADSTRING]);
+public:		// User declarations
+        __fastcall TMainForm(TComponent* Owner);
+        __fastcall void HintHandler(TObject *HintString);
+        void FeatureMissing(const AnsiString& FeatureDescrption);
+        void FeatureMissing(const char* FeatureDescription);
+        enum daybocrypt_owhf GetCurrentHashFunction();
+        void SetCurrentHashFunction(const enum daybocrypt_owhf NewOWHF);
+};
+//---------------------------------------------------------------------------
+extern PACKAGE TMainForm *MainForm;
+//---------------------------------------------------------------------------
+#endif

File win32_gui/dupfiles.bpr

+# ---------------------------------------------------------------------------
+!if !$d(BCB)
+BCB = $(MAKEDIR)\..
+!endif
+
+# ---------------------------------------------------------------------------
+# IDE SECTION
+# ---------------------------------------------------------------------------
+# The following section of the project makefile is managed by the BCB IDE.
+# It is recommended to use the IDE to change any of the values in this
+# section.
+# ---------------------------------------------------------------------------
+
+VERSION = BCB.04.04
+# ---------------------------------------------------------------------------
+PROJECT = dupfiles.exe
+OBJFILES = dupfiles.obj MainFormUnit.obj DirSelDlgUnit.obj AssertUnit.obj DentryUnit.obj \
+  BsodUnit.obj AboutUnit.obj
+RESFILES = dupfiles.res strtab.res
+RESDEPEN = $(RESFILES) MainFormUnit.dfm DirSelDlgUnit.dfm BsodUnit.dfm AboutUnit.dfm
+LIBFILES = dybocrypi.lib
+LIBRARIES =
+SPARELIBS = Vcl40.lib Vclx40.lib bcbsmp40.lib vcljpg40.lib
+PACKAGES = Vcl40.bpi Vclx40.bpi vcljpg40.bpi bcbsmp40.bpi Vcldb40.bpi vcldbx40.bpi \
+  dclocx40.bpi Qrpt40.bpi TeeUI40.bpi teedb40.bpi tee40.bpi
+DEFFILE =
+# ---------------------------------------------------------------------------
+PATHCPP = .;
+PATHASM = .;
+PATHPAS = .;
+PATHRC = .;
+DEBUGLIBPATH = $(BCB)\lib\debug
+RELEASELIBPATH = $(BCB)\lib\release
+USERDEFINES = DAYBOCRYPT_DLL
+SYSDEFINES = _RTLDLL;NO_STRICT;USEPACKAGES
+# ---------------------------------------------------------------------------
+CFLAG1 = -I"..\..\..\Program Files\Borland\CBuilder4\Projects";$(BCB)\include;$(BCB)\include\vcl;..\..\shared\dybocryp;..\..\shared\c99.h \
+  -Od -Hc -H=$(BCB)\lib\vcl40.csm -w -Ve -r- -a8 -6 -k -y -v -vi- -c -b- -w-par \
+  -w-inl -Vx -tW -tWM -D$(SYSDEFINES);$(USERDEFINES)
+PFLAGS = -U"..\..\..\Program Files\Borland\CBuilder4\Projects";$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \
+  -I"..\..\..\Program Files\Borland\CBuilder4\Projects";$(BCB)\include;$(BCB)\include\vcl;..\..\shared\dybocryp;..\..\shared\c99.h \
+  -DDAYBOCRYPT_DLL -$YD -$W -$O- -v -JPHNE -M
+RFLAGS = -i"..\..\..\Program Files\Borland\CBuilder4\Projects";$(BCB)\include;$(BCB)\include\vcl;..\..\shared\dybocryp;..\..\shared\c99.h \
+  -DDAYBOCRYPT_DLL
+AFLAGS = /i"..\..\..\Program Files\Borland\CBuilder4\Projects" /i$(BCB)\include \
+  /i$(BCB)\include\vcl /i..\..\shared\dybocryp /i..\..\shared\c99.h \
+  /dDAYBOCRYPT_DLL /mx /w2 /zd
+LFLAGS = -L"..\..\..\Program Files\Borland\CBuilder4\Projects";$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \
+  -aa -Tpe -x -Gn -v
+# ---------------------------------------------------------------------------
+ALLOBJ = c0w32.obj Memmgr.Lib $(PACKAGES) sysinit.obj $(OBJFILES)
+ALLRES = $(RESFILES)
+ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mti.lib
+# ---------------------------------------------------------------------------
+!ifdef IDEOPTIONS
+
+[Version Info]
+IncludeVerInfo=1
+AutoIncBuild=1
+MajorVer=0
+MinorVer=3
+Release=0
+Build=50
+Debug=1
+PreRelease=1
+Special=0
+Private=1
+DLL=0
+Locale=2057
+CodePage=1252
+
+[Version Info Keys]
+CompanyName=Daybo Logic
+FileDescription=Duplicate file finder
+FileVersion=0.3.0.50
+InternalName=dupfiles
+LegalCopyright=Copyright 2004 Daybo Logic, all rights reserved.
+LegalTrademarks=
+OriginalFilename=dupfiles.exe
+ProductName=Daybo Logic DupFiles
+ProductVersion=0.3.0.0
+Comments=This binary is the protected property of Daybo Logic, it is available at little expense from Daybo Logic's website
+PrivateBuild=DDRP in lab or in pub build
+Contact=http://www.daybologic.co.uk/mailddrp/
+URL=http://www.daybologic.co.uk/
+
+[Excluded Packages]
+$(BCB)\Bin\bcbdrt40.bpl=C++ Builder Direct module
+$(BCB)\Bin\proide40.bpl=Borland Core IDE Package
+$(BCB)\Bin\stride40.bpl=String Resource Editor IDE Package
+
+[HistoryLists\hlIncludePath]
+Count=3
+Item0=..\..\..\Program Files\Borland\CBuilder4\Projects;$(BCB)\include;$(BCB)\include\vcl;..\..\shared\dybocryp;..\..\shared\c99.h
+Item1=..\..\..\Program Files\Borland\CBuilder4\Projects;$(BCB)\include;$(BCB)\include\vcl;..\..\shared\dybocryp
+Item2=..\..\..\Program Files\Borland\CBuilder4\Projects;$(BCB)\include;$(BCB)\include\vcl;..\shared\dybocryp
+
+[HistoryLists\hlLibraryPath]
+Count=1
+Item0=..\..\..\Program Files\Borland\CBuilder4\Projects;$(BCB)\lib\obj;$(BCB)\lib
+
+[HistoryLists\hlDebugSourcePath]
+Count=1
+Item0=$(BCB)\source\vcl
+
+[HistoryLists\hlConditionals]
+Count=1
+Item0=DAYBOCRYPT_DLL
+
+[Debugging]
+DebugSourceDirs=$(BCB)\source\vcl
+
+[Parameters]
+RunParams=
+HostApplication=
+RemoteHost=
+RemotePath=
+RemoteDebug=0
+
+[Compiler]
+InMemoryExe=0
+ShowInfoMsgs=1
+
+!endif
+
+# ---------------------------------------------------------------------------
+# MAKE SECTION
+# ---------------------------------------------------------------------------
+# This section of the project file is not used by the BCB IDE.  It is for
+# the benefit of building from the command-line using the MAKE utility.
+# ---------------------------------------------------------------------------
+
+.autodepend
+# ---------------------------------------------------------------------------
+!if !$d(BCC32)
+BCC32 = bcc32
+!endif
+
+!if !$d(CPP32)
+CPP32 = cpp32
+!endif
+
+!if !$d(DCC32)
+DCC32 = dcc32
+!endif
+
+!if !$d(TASM32)
+TASM32 = tasm32
+!endif
+
+!if !$d(LINKER)
+LINKER = ilink32
+!endif
+
+!if !$d(BRCC32)
+BRCC32 = brcc32
+!endif
+
+# ---------------------------------------------------------------------------
+!if $d(PATHCPP)
+.PATH.CPP = $(PATHCPP)
+.PATH.C   = $(PATHCPP)
+!endif
+
+!if $d(PATHPAS)
+.PATH.PAS = $(PATHPAS)
+!endif
+
+!if $d(PATHASM)
+.PATH.ASM = $(PATHASM)
+!endif
+
+!if $d(PATHRC)
+.PATH.RC  = $(PATHRC)
+!endif
+# ---------------------------------------------------------------------------
+$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE)
+    $(BCB)\BIN\$(LINKER) @&&!
+    $(LFLAGS) +
+    $(ALLOBJ), +
+    $(PROJECT),, +
+    $(ALLLIB), +
+    $(DEFFILE), +
+    $(ALLRES)
+!
+# ---------------------------------------------------------------------------
+.pas.hpp:
+    $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< }
+
+.pas.obj:
+    $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< }
+
+.cpp.obj:
+    $(BCB)\BIN\$(BCC32) $(CFLAG1) -n$(@D) {$< }
+
+.c.obj:
+    $(BCB)\BIN\$(BCC32) $(CFLAG1) -n$(@D) {$< }
+
+.c.i:
+    $(BCB)\BIN\$(CPP32) $(CFLAG1) -n. {$< }
+
+.cpp.i:
+    $(BCB)\BIN\$(CPP32) $(CFLAG1) -n. {$< }
+
+.asm.obj:
+    $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@
+
+.rc.res:
+    $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $<
+# ---------------------------------------------------------------------------

File win32_gui/dupfiles.cpp

+//---------------------------------------------------------------------------
+#include <vcl.h>
+#pragma hdrstop
+USERES("dupfiles.res");
+USEFORM("MainFormUnit.cpp", MainForm);
+USEFORM("DirSelDlgUnit.cpp", DirSelDlg);
+USEUNIT("AssertUnit.cpp");
+USEUNIT("DentryUnit.cpp");
+USEFORM("BsodUnit.cpp", BsodForm);
+USEFORM("AboutUnit.cpp", AboutForm);
+USELIB("dybocrypi.lib");
+USERC("strtab.rc");
+//---------------------------------------------------------------------------
+WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
+{
+        try
+        {
+                 Application->Initialize();
+                 Application->Title = "DupFiles";
+                 Application->CreateForm(__classid(TMainForm), &MainForm);
+                 Application->CreateForm(__classid(TDirSelDlg), &DirSelDlg);
+                 Application->CreateForm(__classid(TBsodForm), &BsodForm);
+                 Application->Run();
+        }
+        catch (Exception &exception)
+        {
+                 Application->ShowException(&exception);
+        }
+        return 0;
+}
+//---------------------------------------------------------------------------

File win32_gui/dupfiles.h

+/*
+  DupFiles
+  (C) Copyright 2003-2004 David Duncan Ross Palmer, Daybo Logic,
+  all rights reserved.
+
+  http://www.daybologic.co.uk/
+*/
+
+#ifndef INC_DUPFILES_H
+#define INC_DUPFILES_H
+//---------------------------------------------------------------------------
+
+// Simple MAX/MIN macro
+#define MIN(a,b) \
+  ( ((a)<(b)) ? (a) : (b) )
+
+#define MAX(a,b) \
+  ( ((a)>(b)) ? (a) : (b) )
+//---------------------------------------------------------------------------
+#endif //!INC_DUPFILES_H

File win32_gui/dupfiles.res

Binary file added.

File win32_gui/edit.bat

+@echo off
+echo Borland C++Builder startup for DupFiles internal project
+echo development.  NOT FOR DISTRIBUTION
+echo (C) Copyright 2004, Daybo Logic, all rights reserved.
+echo See David Palmer incase of problems
+echo.
+echo http://www.daybologic.co.uk/ddrp
+echo.
+if not '%_PATH%' == '' goto setalready
+
+set _PATH=%PATH%
+path=%PATH%;..\..\shared\dybocryp
+bcb dupfiles.bpr
+path=%_PATH%
+set _PATH=
+goto quitit
+
+:setalready
+echo Error 1: A temporary environment variable (_PATH) is already
+echo          used on this system.  Please investigate it's contents
+echo          before removing it, it may be temporary.  There may be
+echo          another instance of this program running on the system.
+echo          Try again before reporting this error to your system
+echo          administrator.
+goto quitit
+
+:quitit
+echo Program ended

File win32_gui/strtab.rc

+/*
+  Daybo Logic DupFiles - string table for the Win32 version
+  of DupFiles.
+
+  (C) Copyright 2004 Daybo Logic, all rights reserved.
+  http://www.daybologic.co.uk/
+
+  Translations provided by BabelFish
+  http://babelfish.altavista.com/
+*/
+
+#include "windows.h"
+#include "strtab.rh" /* Resource header */
+
+STRINGTABLE
+DISCARDABLE
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+BEGIN
+  R_S_TITLE "Daybo Logic DupFiles 0.3"
+  R_S_NO_SUCH_FEATURE "This feature has not been programmed yet,\021Get yourself a cup of tea"
+END
+
+STRINGTABLE
+DISCARDABLE
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+BEGIN
+  R_S_TITLE "Daybo Logic DupFiles 0.3"
+  R_S_NO_SUCH_FEATURE "Feature not done yet, go and get a BigMac"
+END
+
+STRINGTABLE
+DISCARDABLE
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
+BEGIN
+  R_S_TITLE "Daybo Logic DupFiles 0.3"
+  R_S_NO_SUCH_FEATURE "Regarde feature, pending mon ami"
+END
+
+STRINGTABLE
+DISCARDABLE
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+BEGIN
+  R_S_TITLE "Daybo Logic DupFiles 0.3"
+  R_S_NO_SUCH_FEATURE "Feature nein yet sieg, ein minute whilst arbeiten"
+END

File win32_gui/strtab.res

Binary file added.

File win32_gui/strtab.rh

+/*
+  Daybo Logic DupFiles
+  C compatible header for the string table for the Win32 version of
+  DupFiles.
+
+  (C) Copyright 2004 Daybo Logic, all rights reserved.
+  http://www.daybologic.co.uk/
+*/
+
+#ifndef INC_STRTAB_RH
+#define INC_STRTAB_RH
+/*-------------------------------------------------------------------------*/
+/*
+  I am basing this definition of MAX_LOADSTRING on the Microsoft
+  Windows Win32 MSDN page for "STRINGTABLE Resource" at this URL:
+  http://msdn.microsoft.com/library/default.asp?url=/library/ \
+  en-us/tools/stringtable_resource.asp
+*/
+#define MAX_LOADSTRING (4097)
+
+/*
+  R_BASE is the resource base.  Change it if it conflicts
+  with any other resources in the binary.
+*/
+#define R_BASE               (100)
+
+/*
+  These are the resource identifiers.  See strtab.rc for the
+  actual strings.  They should all be based on R_BASE so they
+  can easily be relocated.
+*/
+#define R_S_TITLE            (R_BASE+0)
+#define R_S_NO_SUCH_FEATURE  (R_BASE+1)
+/*-------------------------------------------------------------------------*/
+#endif /*!INC_STRTAB_H*/