/*
 *  Versioner 2 Development Code
 *  Copyright (C) 1999 Kirby Kuehl (vacuum@technotronic.com)
 *
 *  Link with version.lib
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 1, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 */	  




#include <iostream.h> 
#include <windows.h>
#include <stdio.h>
#define VERSION "Versioner 0.3"


// prints information about a file in text format

void PrintFindData(FILE *stream, WIN32_FIND_DATA *findData, char *dirName)
{	
  FILETIME ft;
  SYSTEMTIME st;
  DWORD   dwVerInfoSize;        
  DWORD   dwVerHnd=0;
  BOOL    bRetCode;
  LPSTR   lpBuffer;
  UINT*    dwBytes = new UINT;
  char *fileName;
  char fullName[256];


  if(!GetFullPathName(findData->cFileName,
                      256,
					  fullName,
					  &fileName))
					  // return;
    	
  
  fprintf(stream, "__________________________________________________________________________\n");
  printf("%s\n",fullName);
  fprintf(stream, "Filename: %s\nSize: %d bytes\n",fullName, findData->nFileSizeLow);
    // ftCreation Time
    FileTimeToLocalFileTime(&findData->ftCreationTime, &ft);
	FileTimeToSystemTime(&ft, &st);
	// printf("Creation Time: %d/%d/%d %d:%d\n", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute);
    fprintf(stream, "Creation Time: %d/%d/%d %d:%d\n", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute);
    // ftLastAccessTime
	FileTimeToLocalFileTime(&findData->ftLastAccessTime , &ft);
	FileTimeToSystemTime(&ft, &st);
	// printf("Last Access Time: %d/%d/%d %d:%d\n", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute);
    fprintf(stream, "Last Access Time: %d/%d/%d %d:%d\n", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute);
    // ftLastWriteTime 
	FileTimeToLocalFileTime(&findData->ftLastWriteTime, &ft);
	FileTimeToSystemTime(&ft, &st);
	// printf("Last Write Time: %d/%d/%d %d:%d\n", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute);
    fprintf(stream, "Last Write Time: %d/%d/%d %d:%d\n", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute);


	dwVerInfoSize = GetFileVersionInfoSize(findData->cFileName, &dwVerHnd);
	if (dwVerInfoSize)
	{
		 LPTSTR   lpstrVffInfo; 
		 
		 HANDLE  hMem;
            hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
            lpstrVffInfo  = (char *)GlobalLock(hMem);
            GetFileVersionInfo(findData->cFileName, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
     
			// Company Name
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\CompanyName"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                // printf("Company Name: %s\n",lpBuffer);
				fprintf(stream, "Company Name: %s\n",lpBuffer);
            }
			else
				fprintf(stream, "Company Name:\n");
			// File Description		
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo, 
              TEXT("\\StringFileInfo\\040904E4\\FileDescription"), 
              (LPVOID *)&lpBuffer, dwBytes);
			if(bRetCode)
            {
                // printf("File Description: %s\n",lpBuffer);
                fprintf(stream, "File Description: %s\n",lpBuffer);
			}
			else
			fprintf(stream, "File Description: \n");
			
			// File Version
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\FileVersion"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                // printf("FileVersion: %s\n",lpBuffer);
				fprintf(stream, "FileVersion: %s\n",lpBuffer);
            }
			else
				fprintf(stream, "FileVersion: \n");

            // Internal Name
            bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
				TEXT("\\StringFileInfo\\040904E4\\InternalName"),
				(LPVOID *)&lpBuffer , dwBytes);

            if(bRetCode)
			{
				// printf("InternalName: %s\n",lpBuffer);
				fprintf(stream, "InternalName: %s\n",lpBuffer);
            }
			else
				fprintf(stream, "InternalName: \n");

            // LegalCopyright
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
				TEXT("\\StringFileInfo\\040904E4\\LegalCopyright"),
				(LPVOID *)&lpBuffer , dwBytes);

            if(bRetCode)
			{
				// printf("LegalCopyright: %s\n",lpBuffer);
				fprintf(stream, "LegalCopyright: %s\n",lpBuffer);
            }
			else
	            fprintf(stream, "LegalCopyright:\n");

			// OriginalFilename 

			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
				TEXT("\\StringFileInfo\\040904E4\\OriginalFilename"),
				(LPVOID *)&lpBuffer , dwBytes);

            if(bRetCode)
			{
				// printf("OriginalFilename: %s\n",lpBuffer);
				fprintf(stream, "OriginalFilename: %s\n",lpBuffer);
            }
			else
				fprintf(stream, "OriginalFilename: \n");
            // ProductName 

			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
				TEXT("\\StringFileInfo\\040904E4\\ProductName"),
				(LPVOID *)&lpBuffer , dwBytes);
			
            if(bRetCode)
			{
				// printf("ProductName: %s\n",lpBuffer);
				fprintf(stream, "ProductName: %s\n",lpBuffer);
            }
			else
				fprintf(stream, "ProductName: \n");

			// ProductVersion
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
				TEXT("\\StringFileInfo\\040904E4\\ProductVersion"),
				(LPVOID *)&lpBuffer , dwBytes);

            if(bRetCode)
			{
				// printf("ProductVersion: %s\n",lpBuffer);
				fprintf(stream, "ProductVersion: %s\n",lpBuffer);
            }
			else
				fprintf(stream, "ProductVersion: \n");
			
            // Comments
			            
            bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\Comments"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                // printf("Comments: %s\n",lpBuffer);
				fprintf(stream, "Comments: %s\n",lpBuffer);
            }
			else
				fprintf(stream, "Comments: \n");
	
			// LegalTrademarks 
	        
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\LegalTrademarks"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                // printf("LegalTrademarks: %s\n",lpBuffer);
				fprintf(stream, "LegalTrademarks: %s\n",lpBuffer);
            }
			else
				fprintf(stream, "LegalTrademarks: \n");
	        
			// PrivateBuild 
	
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\PrivateBuild"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                // printf("PrivateBuild: %s\n",lpBuffer);
				fprintf(stream, "PrivateBuild: %s\n",lpBuffer);
            }
			else
				fprintf(stream, "PrivateBuild: \n");
			
			// SpecialBuild 
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\SpecialBuild"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                // printf("SpecialBuild: %s\n",lpBuffer);
				fprintf(stream, "SpecialBuild: %s\n",lpBuffer);
            }
			else
				fprintf(stream, "SpecialBuild: \n");
	}

	// printf("\n\n");
	fprintf(stream, "\n\n");



}

// prints information about a file in cvs format

void PrintFindData2(FILE *stream, WIN32_FIND_DATA *findData, char *dirName)
{	
  FILETIME ft;
  SYSTEMTIME st;
  DWORD   dwVerInfoSize;        
  DWORD   dwVerHnd=0;
  BOOL    bRetCode;
  LPSTR   lpBuffer;
  UINT*    dwBytes = new UINT;
  char *fileName;
  char fullName[256];


    GetFullPathName(findData->cFileName, 256, fullName, &fileName);
    fprintf(stream, "%s, %d, ",fullName, findData->nFileSizeLow);
    // ftCreation Time
    FileTimeToLocalFileTime(&findData->ftCreationTime, &ft);
	FileTimeToSystemTime(&ft, &st);
	fprintf(stream, "%d/%d/%d %d:%d, ", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute);
    // ftLastAccessTime
	FileTimeToLocalFileTime(&findData->ftLastAccessTime , &ft);
	FileTimeToSystemTime(&ft, &st);
    fprintf(stream, "%d/%d/%d %d:%d, ", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute);
    // ftLastWriteTime 
	FileTimeToLocalFileTime(&findData->ftLastWriteTime, &ft);
	FileTimeToSystemTime(&ft, &st);
    fprintf(stream, "%d/%d/%d %d:%d, ", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute);


	dwVerInfoSize = GetFileVersionInfoSize(findData->cFileName, &dwVerHnd);
	if (dwVerInfoSize)
	{
		 LPTSTR   lpstrVffInfo; 
		 
		 HANDLE  hMem;
            hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
            lpstrVffInfo  = (char *)GlobalLock(hMem);
            GetFileVersionInfo(findData->cFileName, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
     
			// Company Name
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\CompanyName"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                fprintf(stream, "%s, ",lpBuffer);
            }
			else
				fprintf(stream, ", ");
			// File Description		
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo, 
              TEXT("\\StringFileInfo\\040904E4\\FileDescription"), 
              (LPVOID *)&lpBuffer, dwBytes);
			if(bRetCode)
            {
                fprintf(stream, "%s, ",lpBuffer);
			}
			else
			fprintf(stream, ", ");
			
			// File Version
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\FileVersion"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                fprintf(stream, "%s, ",lpBuffer);
            }
			else
				fprintf(stream, ", ");

            // Internal Name
            bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
				TEXT("\\StringFileInfo\\040904E4\\InternalName"),
				(LPVOID *)&lpBuffer , dwBytes);

            if(bRetCode)
			{
				fprintf(stream, "%s ",lpBuffer);
            }
			else
				fprintf(stream, ", ");

            // LegalCopyright
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
				TEXT("\\StringFileInfo\\040904E4\\LegalCopyright"),
				(LPVOID *)&lpBuffer , dwBytes);

            if(bRetCode)
			{
				fprintf(stream, "%s, ",lpBuffer);
            }
			else
	            fprintf(stream, ", ");

			// OriginalFilename 

			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
				TEXT("\\StringFileInfo\\040904E4\\OriginalFilename"),
				(LPVOID *)&lpBuffer , dwBytes);

            if(bRetCode)
			{
				fprintf(stream, "%s ",lpBuffer);
            }
			else
				fprintf(stream, ", ");
            // ProductName 

			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
				TEXT("\\StringFileInfo\\040904E4\\ProductName"),
				(LPVOID *)&lpBuffer , dwBytes);
			
            if(bRetCode)
			{
				// printf("ProductName: %s\n",lpBuffer);
				fprintf(stream, "%s, ",lpBuffer);
            }
			else
				fprintf(stream, ", ");

			// ProductVersion
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
				TEXT("\\StringFileInfo\\040904E4\\ProductVersion"),
				(LPVOID *)&lpBuffer , dwBytes);

            if(bRetCode)
			{
				fprintf(stream, "%s ",lpBuffer);
            }
			else
				fprintf(stream, ", ");
			
            // Comments
			            
            bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\Comments"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                fprintf(stream, "%s ",lpBuffer);
            }
			else
				fprintf(stream, ", ");
	
			// LegalTrademarks 
	        
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\LegalTrademarks"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                fprintf(stream, "%s ",lpBuffer);
            }
			else
				fprintf(stream, ", ");
	        
			// PrivateBuild 
	
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\PrivateBuild"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                fprintf(stream, "%s ,",lpBuffer);
            }
			else
				fprintf(stream, ", ");
			
			// SpecialBuild 
			bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
                TEXT("\\StringFileInfo\\040904E4\\SpecialBuild"),
                (LPVOID *)&lpBuffer,                dwBytes);
            if(bRetCode)
            {
                fprintf(stream, "%s\n",lpBuffer);
            }
			else
				fprintf(stream, "\n");
	}
	else
		fprintf(stream, ", , , , , , , , , , ,\n");
}



// Recursively lists directories

void ListDirectoryContents(FILE *stream, FILE *stream2, char *dirName, char *fileMask)

{

	char curDir[ 256 ];

	char printDir[ 256 ];

	HANDLE fileHandle;

	WIN32_FIND_DATA findData;



	// save current dir so it can restore it

	if( !GetCurrentDirectory( 256, curDir) ) 

		return;

	

	// if the directory name is neither . or .. then

	// change to it, otherwise ignore it

	if( strcmp( dirName, "." ) && 

		strcmp( dirName, ".." ) )

	{

		if( !SetCurrentDirectory( dirName ) ) 

			return;

		if( !GetCurrentDirectory( 256, printDir) ) 

			return;

	}

	else 

		return;



	// Loop through all files looking for 

	// the file name of interest.

	fileHandle = FindFirstFile( fileMask, 

		&findData );

	while ( fileHandle != INVALID_HANDLE_VALUE )

	{

		PrintFindData(stream, &findData, printDir );
        PrintFindData2(stream2, &findData, printDir );


  		// loop thru remaining entries in the dir

		if (!FindNextFile( fileHandle, &findData ))

			break;

 	}

	FindClose( fileHandle );



	// Loop through all files in the directory

	// looking for other directories

	fileHandle = FindFirstFile( "*.*", 

		&findData );

	while ( fileHandle != INVALID_HANDLE_VALUE )

	{

		// If the name is a directory,

		// recursively walk it. 

		if( findData.dwFileAttributes &

			FILE_ATTRIBUTE_DIRECTORY )

		{

			ListDirectoryContents(stream, stream2, findData.cFileName, fileMask );

		}

  		// loop thru remaining entries in the dir

		if (!FindNextFile( fileHandle, &findData ))

			break;

 	}

	

	// clean up and restore directory

	FindClose( fileHandle );

	SetCurrentDirectory( curDir );

}



int main(int argc, char *argv[])
{
    char *curDir, *findName, *output, *csv;
	FILE *stream, *stream2;
	if (argc!=5)
	{
	printf("\nusage : %s <starting directory> <filemask> <output.txt> <output.csv>\n\n",VERSION);
	printf("vacuum@technotronic.com\n");
	exit(0);
	}
	curDir = argv[1];
	findName = argv[2];
	output = argv[3];
	csv = argv[4];

	if( (stream = fopen(output, "w" )) == NULL ) 
    printf( "The file '%s' was not opened\n",output), exit(-1);

	if( (stream2 = fopen(csv, "w" )) == NULL ) 
    printf( "The file '%s' was not opened\n",csv), exit(-1);

	// CVS Headings
  fprintf(stream2, "Filename:, Size:, Creation Time:, Last Access Time:, Last Write Time:, ");
  fprintf(stream2, "Company Name:, File Description:, File Version:, Internal Name:, Legal Copyright:, ");
  fprintf(stream2, "Original File Name:, Product Name:, Product Version:, Comments:, Legal Trademark:, ");
  fprintf(stream2, "Original File Name:, Product Name:, Product Version:, Comments:, Legal Trademarks:, ");
  fprintf(stream2, "Private Build:, Special Build:\n");

 if (!SetCurrentDirectory(curDir))
	{
		printf("Couldn't get the starting directory.\n");
		return(-1);
	}
 else
 {
	ListDirectoryContents(stream, stream2, curDir, findName);
	
}	
   fclose(stream);
   fclose(stream2);
	return(0);}

