Code:
/*++
Copyright (c) Rocket Division Software 2001-2004. All rights reserved.
Module Name:
UDFBuildImage.c
Abstract:
UDFBuildImage is StarBurn sample application - Pure UDF file system image generation.
[ This is external sample that has StarBurn toolkit in a separate DLL ]
Author:
Anton A. Kolomyeytsev
Environment:
Windows 95/98/ME/NT/2K/XP/2003 UserMode only
Notes:
Known bugs/Illegal behavior:
ToDo:
Revision/Development History:
2002-01-14 : * Project restarted "from the scratch".
2004-02-28 : * Rocket Division Software port.
--*/
//
// Define this file __BUILDIMAGE_C__ (begin)
//
#ifndef __UDFBuildImage_C__
#define __UDFBuildImage_C__
//
// Own includes (begin)
//
#ifndef _WINDOWS_
#include <windows.h> // Target OS
#endif
#ifndef _INC_STDIO
#include <stdio.h> // Generic I/O stuff
#endif
#ifndef __STARBURN_H__
#include "inc\StarBurn.h" // Our public header
#endif
//
// Own includes (end)
//
//
// Own definitions (begin)
//
//
// Store packet size in UCHARs
//
#define STORE_PACKET_SIZE_IN_UCHARS 65536
//
// Own definitions (end)
//
//
// Own global data region (begin)
//
UCHAR g__UCHAR__DataBuffer[ STORE_PACKET_SIZE_IN_UCHARS ];
unsigned char g__UCHAR__FileSystemHead[ ( UDF_HEAD_SIZE_IN_LOGICAL_BLOCKS * UDF_LOGICAL_BLOCK_SIZE_IN_UCHARS ) ];
unsigned char g__UCHAR__FileSystemTail[ ( UDF_TAIL_SIZE_IN_LOGICAL_BLOCKS * UDF_LOGICAL_BLOCK_SIZE_IN_UCHARS ) ];
unsigned char g__UCHAR__FileSystemStructures[ ( 1024 * UDF_LOGICAL_BLOCK_SIZE_IN_UCHARS ) ];
unsigned char g__UCHAR__IsIfoPatch = 0x00; // 0x01; // Assume IFO patch present by default
UDF_TREE_ITEM g__UDF_TREE_ITEM__File[ 200 ]; // File[ 0 ] is not used
//
// Own global data region (end)
//
//
// Own global function bodies (begin)
//
VOID
__cdecl
Callback(
IN CALLBACK_NUMBER p__CALLBACK_NUMBER,
IN PVOID p__PVOID__CallbackContext,
IN PVOID p__PVOID__CallbackSpecial1,
IN PVOID p__PVOID__CallbackSpecial2
)
/*++
Routine Description:
Callback passed to library objects to show progress indication (tree node item added or removed, LBA assigned, file
opened etc)
Arguments:
Callback number,
Passed callback context,
Parameter 1,
Parameter 2
Return Value:
Nothing
--*/
{
//
// Process depending of callback number.
//
switch ( p__CALLBACK_NUMBER )
{
//
// Unhandled callback number
//
default:
{
/*
printf(
"UDFBuildImage:Callback(): Unhandled callback number 0x%08X, parameter 0x%08X\n",
( ULONG )( p__CALLBACK_NUMBER ),
( ULONG )( p__PVOID__CallbackContext )
);
*/
}
}
}
ULONG
__cdecl
main(
IN INT p__INT__Argc,
IN PCHAR p__PCHAR__Argv[]
)
/*++
Routine Description:
Main application entry called by OS loader
Arguments:
Number of virtual arguments,
Virtual arguments list
Return Value:
Execution status
--*/
{
LARGE_INTEGER l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs;
LARGE_INTEGER l__LARGE_INTEGER__TotalSizeInUCHARs;
LARGE_INTEGER l__LARGE_INTEGER__IoTransferSizeInUCHARs;
LARGE_INTEGER l__LARGE_INTEGER__LastPrintedPercent;
LARGE_INTEGER l__LARGE_INTEGER__CurrentPercent;
LARGE_INTEGER l__LARGE_INTEGER__ProcessedUCHARs;
HANDLE l__HANDLE = INVALID_HANDLE_VALUE;
ULONG l__ULONG__UCHARsWritten = 0;
LONG l__LONG__Index = 0;
CHAR l__CHAR__DirName[ MAX_PATH ];
ULARGE_INTEGER l__ULARGE_INTEGER__FreeUCHARs;
ULARGE_INTEGER l__ULARGE_INTEGER__TotalUCHARs;
ULARGE_INTEGER l__ULARGE_INTETER__FreeTotalUCHARs;
ULONG l__ULONG__Status = ERROR_GEN_FAILURE;
CHAR l__CHAR__ExceptionText[ 1024 ];
EXCEPTION_NUMBER l__EXCEPTION_NUMBER = EN_SUCCESS; // Assume success by default
UDF_TREE_ITEM l__UDF_TREE_ITEM__Directory[ 20 ]; // Directory[ 0 ] is not used
ULONG l__ULONG__GUID = 0; // Start assigning GUIDs with zero
UDF_CONTROL_BLOCK l__UDF_CONTROL_BLOCK;
printf(
"\nUDFBuildImage:main(): ENTERed for %ld argument(s)\n",
p__INT__Argc
);
//
// Check are there enough input parameters
//
if ( p__INT__Argc < 2 )
{
printf( "\nUDFBuildImage:main(): EXITing with failure!!!\n\n" );
printf( "UDFBuildImage:main(): Target UDF image name required!!!\n" );
printf( "UDFBuildImage:main(): Example: UDFBuildImage.exe c:\\UDFImage.iso\n" );
//
// Return invalid status
//
return ERROR_INVALID_PARAMETER;
}
//
// Prepare some memory buffers
//
memset(
&g__UCHAR__FileSystemHead,
0,
sizeof( g__UCHAR__FileSystemHead )
);
memset(
&g__UCHAR__FileSystemTail,
0,
sizeof( g__UCHAR__FileSystemTail )
);
memset(
&g__UCHAR__FileSystemStructures,
0,
sizeof( g__UCHAR__FileSystemStructures )
);
memset(
&l__UDF_TREE_ITEM__Directory[ 0 ],
0,
sizeof( l__UDF_TREE_ITEM__Directory )
);
memset(
&g__UDF_TREE_ITEM__File[ 0 ],
0,
sizeof( g__UDF_TREE_ITEM__File )
);
memset(
&l__UDF_CONTROL_BLOCK,
0,
sizeof( UDF_CONTROL_BLOCK )
);
RtlZeroMemory(
&l__CHAR__ExceptionText,
sizeof( l__CHAR__ExceptionText )
);
//
// Try to create output file
//
l__HANDLE =
CreateFile(
p__PCHAR__Argv[ 1 ],
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
0,
NULL
);
//
// Check for success
//
if ( l__HANDLE == INVALID_HANDLE_VALUE )
{
printf( "\nUDFBuildImage:main(): EXITing with failure!!!\n\n" );
//
// Get last error
//
l__ULONG__Status = GetLastError();
printf(
"UDFBuildImage:main(): CreateFile( '%s' ) failed, status %ld!!!\n",
p__PCHAR__Argv[ 1 ],
l__ULONG__Status
);
//
// Return invalid status
//
return l__ULONG__Status;
}
//
// Start processing cleanup
//
__try
{
printf( "\nUDFBuildImage:main(): Formatting directories...\n" );
//
// Format Directory[ 1 ] as root
//
StarBurn_UDF_FormatTreeItemAsDirectory(
&l__UDF_TREE_ITEM__Directory[ 1 ],
( ++l__ULONG__GUID ),
"",
NULL
);
//
// Format some directory
//
StarBurn_UDF_FormatTreeItemAsDirectory(
&l__UDF_TREE_ITEM__Directory[ 2 ],
( ++l__ULONG__GUID ),
"UDF_FOLDER",
&l__UDF_TREE_ITEM__Directory[ 1 ]
);
printf( "\nUDFBuildImage:main(): Formatting files...\n" );
//
// Format files (begin)
//
l__ULONG__Status =
StarBurn_UDF_FormatTreeItemAsFile(
&g__UDF_TREE_ITEM__File[ 1 ],
( ++l__ULONG__GUID ),
"my_file.bin",
"c:\\my_file.bin",
&l__UDF_TREE_ITEM__Directory[ 2 ]
);
//
// Check for success
//
if ( l__ULONG__Status != 0 )
{
printf(
"\nUDFBuildImage:main(): EXITing with failure, StarBurn_UDF_FormatTreeItemAsFile( %p, %ld, '%s', '%s', %p ) failed, status %ld ( 0x%X )\n",
&g__UDF_TREE_ITEM__File[ 1 ],
l__ULONG__GUID,
"my_file.bin",
"c:\\my_file.bin",
&l__UDF_TREE_ITEM__Directory[ 2 ],
l__ULONG__Status,
l__ULONG__Status
);
//
// Get out of here
//
__leave;
}
//
// Try to create UDF
//
l__EXCEPTION_NUMBER =
StarBurn_UDF_Create(
( PUCHAR )( &g__UCHAR__FileSystemHead ),
sizeof( g__UCHAR__FileSystemHead ),
( PUCHAR )( &g__UCHAR__FileSystemTail ),
sizeof( g__UCHAR__FileSystemTail ),
( PUCHAR )( &g__UCHAR__FileSystemStructures ),
&l__UDF_TREE_ITEM__Directory[ 1 ], // This is ROOT
NULL,
NULL,
&l__UDF_CONTROL_BLOCK,
( CHAR * )( &l__CHAR__ExceptionText ),
sizeof( l__CHAR__ExceptionText ),
&l__ULONG__Status,
"VolumeLabel"
);
//
// Check for success
//
if ( l__EXCEPTION_NUMBER != EN_SUCCESS )
{
printf(
"\nUDFBuildImage:main(): StarBurn_UDF_Create() failed, exception %ld, status %ld, text '%s'\n",
l__EXCEPTION_NUMBER,
l__ULONG__Status,
l__CHAR__ExceptionText
);
//
// Get out of here
//
__leave;
}
//
// Get size of image we'll store
//
l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs.LowPart =
StarBurn_ISO9660JolietFileTree_GetSizeInUCHARs(
l__UDF_CONTROL_BLOCK.m__PVOID__Body,
&l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs.HighPart
);
//
// Generate target directory name
//
RtlZeroMemory(
l__CHAR__DirName,
sizeof( l__CHAR__DirName )
);
strcpy(
l__CHAR__DirName,
p__PCHAR__Argv[ 1 ]
);
//
// Check is this UNC or absolute path
//
if (
( ( UCHAR )( l__CHAR__DirName[ 0 ] ) == ( UCHAR )( '\\' ) ) ||
( ( UCHAR )( l__CHAR__DirName[ 1 ] ) == ( UCHAR )( ':' ) )
)
{
//
// Process name UCHAR by UCHAR
//
for ( l__LONG__Index = strlen( l__CHAR__DirName ); l__LONG__Index > 0; l__LONG__Index-- )
{
//
// Check is current UCHAR is '\\'
//
if ( l__CHAR__DirName[ l__LONG__Index ] == '\\' )
{
//
// Put terminating symbol
//
l__CHAR__DirName[ l__LONG__Index ] = 0;
//
// Get out of here
//
break;
}
//
// Reset current symbol
//
l__CHAR__DirName[ l__LONG__Index ] = 0;
}
}
else
{
//
// Generate current directory name
//
RtlZeroMemory(
&l__CHAR__DirName,
sizeof( l__CHAR__DirName )
);
//
// Try to get current directory name, no need to check for return code if this function will fail next call to
// GetDiskFreeSpaceEx will fail as well with exception '' invalid path
//
GetCurrentDirectory(
sizeof( l__CHAR__DirName ),
( PCHAR )( &l__CHAR__DirName )
);
}
//
// Try to get amount of free disk space in the target directory
//
if (
GetDiskFreeSpaceEx(
l__CHAR__DirName,
&l__ULARGE_INTEGER__FreeUCHARs,
&l__ULARGE_INTEGER__TotalUCHARs,
&l__ULARGE_INTETER__FreeTotalUCHARs
) == FALSE
)
{
//
// Get error code
//
l__ULONG__Status = GetLastError();
printf(
"\nUDFBuildImage:main(): GetDiskFreeSpaceEx( '%s' ) failed, status %ld!!!",
l__CHAR__DirName,
l__ULONG__Status
);
//
// Get out of here
//
__leave;
}
printf(
"\nUDFBuildImage:main(): Free %I64d UCHARs of %I64d UCHARs in directory '%s'\n",
l__ULARGE_INTEGER__FreeUCHARs,
l__ULARGE_INTEGER__TotalUCHARs,
l__CHAR__DirName
);
//
// Check does the generating image will fit into free space
//
if ( l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs.QuadPart > l__ULARGE_INTEGER__FreeUCHARs.QuadPart )
{
//
// Set error code
//
l__ULONG__Status = ERROR_DISK_FULL;
printf(
"\nUDFBuildImage:main(): %I64d UCHARs of UDF image will not fit into %I64d UCHARs of free space in '%s'!!!\n",
l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs,
l__ULARGE_INTEGER__FreeUCHARs,
l__CHAR__DirName
);
//
// Get out of here
//
__leave;
}
printf(
"\nUDFBuildImage:main(): Storing %I64d UCHARs of UDF image to file '%s'\n",
l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs,
p__PCHAR__Argv[ 1 ]
);
l__LARGE_INTEGER__TotalSizeInUCHARs.LowPart =
StarBurn_ISO9660JolietFileTree_GetSizeInUCHARs(
l__UDF_CONTROL_BLOCK.m__PVOID__Body,
&l__LARGE_INTEGER__TotalSizeInUCHARs.HighPart
);
//
// Reset last printed percent
//
l__LARGE_INTEGER__LastPrintedPercent.QuadPart = 0;
printf( "\nUDFBuildImage:main(): Progress: " );
//
// Process until something will be in the file
//
for ( ; ; )
{
//
// Calculate currently processed size
//
l__LARGE_INTEGER__ProcessedUCHARs.QuadPart =
( l__LARGE_INTEGER__TotalSizeInUCHARs.QuadPart - l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs.QuadPart );
//
// Calculate currently processed percent
//
l__LARGE_INTEGER__CurrentPercent.QuadPart =
( l__LARGE_INTEGER__ProcessedUCHARs.QuadPart * 100 / l__LARGE_INTEGER__TotalSizeInUCHARs.QuadPart );
//
// Check do we need to print this percent
//
if (
( l__LARGE_INTEGER__LastPrintedPercent.QuadPart == l__LARGE_INTEGER__CurrentPercent.QuadPart ) ||
( l__LARGE_INTEGER__CurrentPercent.QuadPart == 100 )
)
{
//
// Do nothing
//
}
else
{
//
// Update last printed percent
//
l__LARGE_INTEGER__LastPrintedPercent.QuadPart = l__LARGE_INTEGER__CurrentPercent.QuadPart;
printf(
"%I64d%% ",
l__LARGE_INTEGER__LastPrintedPercent
);
}
//
// Check do we need to exit
//
if ( l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs.QuadPart == 0 )
{
//
// Get out of here
//
break;
}
//
// Check if the number of UCHARs till end is less then our packet size
//
if ( l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs.QuadPart < STORE_PACKET_SIZE_IN_UCHARS )
{
//
// Set current I/O transfer size to number of UCHARs till the end of the image
//
l__LARGE_INTEGER__IoTransferSizeInUCHARs.QuadPart = l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs.QuadPart;
}
else
{
//
// Set current I/O transfer size to default store packet size
//
l__LARGE_INTEGER__IoTransferSizeInUCHARs.QuadPart = STORE_PACKET_SIZE_IN_UCHARS;
}
//
// Try to read current data
//
l__EXCEPTION_NUMBER =
StarBurn_ISO9660JolietFileTree_Read(
l__UDF_CONTROL_BLOCK.m__PVOID__Body,
( PCHAR )( &l__CHAR__ExceptionText ),
sizeof( l__CHAR__ExceptionText ),
&l__ULONG__Status,
l__LARGE_INTEGER__IoTransferSizeInUCHARs.LowPart,
( PUCHAR )( &g__UCHAR__DataBuffer )
);
//
// Check for success
//
if ( l__EXCEPTION_NUMBER != EN_SUCCESS )
{
printf(
"\nUDFBuildImage:main(): StarBurn_ISO9660FileTree_Read( loop ) failed, exception %ld, status %ld, text '%s'\n",
l__EXCEPTION_NUMBER,
l__ULONG__Status,
l__CHAR__ExceptionText
);
//
// Get out of here
//
__leave;
}
//
// Try to write
//
if (
WriteFile(
l__HANDLE,
&g__UCHAR__DataBuffer,
( ULONG )( l__LARGE_INTEGER__IoTransferSizeInUCHARs.QuadPart ),
&l__ULONG__UCHARsWritten,
NULL
) == FALSE
)
{
//
// Get error code
//
l__ULONG__Status = GetLastError();
printf(
"\nUDFBuildImage:main(): WriteFile( %I64d ) failed, status %ld!!!",
l__LARGE_INTEGER__IoTransferSizeInUCHARs,
l__ULONG__Status
);
//
// Get out of here
//
__leave;
}
//
// Check for number of UCHARs written here
//
//
// Update current unstored size
//
l__LARGE_INTEGER__CurrentUnstoredSizeInUCHARs.QuadPart -= l__LARGE_INTEGER__IoTransferSizeInUCHARs.QuadPart;
}
printf( "100%%... Done!\n\n" );
//
// Set status to good one
//
l__ULONG__Status = ERROR_SUCCESS;
}
__finally
{
//
// Flush file to the disk
//
FlushFileBuffers( l__HANDLE );
//
// Close file
//
CloseHandle( l__HANDLE );
//
// UDF clean up here
//
StarBurn_UDF_CleanUp(
&g__UDF_TREE_ITEM__File[ 0 ],
20
);
//
// UDF tree kill here
//
if ( l__UDF_CONTROL_BLOCK.m__PVOID__Body != NULL )
{
//
// Destroy UDF
//
StarBurn_UDF_Destroy(
&l__UDF_TREE_ITEM__Directory[ 1 ], // Root
&l__UDF_CONTROL_BLOCK
);
}
}
//
// Check for success
//
if ( l__ULONG__Status == ERROR_SUCCESS )
{
printf( "\nUDFBuildImage:main(): EXITing with success\n" );
}
else
{
printf( "\nUDFBuildImage:main(): EXITing with failure\n" );
}
//
// Return execution status
//
return l__ULONG__Status;
}
//
// Own global function bodies (end)
//
#endif // Define this file __UDFBuildImage_C__ (end)