Listing 2: lzinst.c Main source for self-installing executable
/* the smallest setup app written by Janko Stamenovic 1998. */ #pragma comment(linker, "/nodefaultlib") #include <windows.h> #include "smallio.h" #define INFFOLNAME "jankodem" #define JSAPPNAME "Janko's Demo App for 32-bit Windows" char tempFolderName[ MAX_PATH ]; void AddBackIfNeeded( char* s ) { if ( s[ strlen( s ) - 1 ] != '\\' ) strcat( s, "\\" ); } void MergePathAndName( char* targ, LPCCH path, LPCCH name ) { strcpy( targ, path ); AddBackIfNeeded( targ ); strcat( targ, name ); } void CreateNameInTempDir( char* s, char* name, char* ext ) { if ( !GetTempPath( MAX_PATH, s ) ) strcpy( s, "c:" ); AddBackIfNeeded( s ); strcat( s, name ); strcat( s, ext ); } void PerformLZ( char* s ) { OFSTRUCT ofs1; OFSTRUCT ofs2; char destname[ MAX_PATH ]; INT in_f, out_f; GetExpandedName( s, destname ); in_f = LZOpenFile( s, &ofs1, OF_READ | OF_SHARE_EXCLUSIVE ); if ( in_f < 0 ) { MessageBox( 0, s, "Error openinig", MB_OK ); return; } out_f = LZOpenFile( destname, &ofs2, OF_CREATE ); if ( out_f < 0 ) { MessageBox( 0, destname, "Error creating", MB_OK ); return; } LZCopy( in_f, out_f ); LZClose( in_f ); LZClose( out_f ); } void PossiblyExtract( char* frombyte, char* tobyte, char* where ) { FILETIME ft[ 3 ]; char* name; char fullname[ MAX_PATH ]; int cp; if ( frombyte == 0 ) return; if ( tobyte - frombyte == 0 ) return; cp = sizeof( FILETIME ) * 3; where = (char*)&ft; while ( cp-- ) *where++ = *frombyte++; name = frombyte; frombyte = frombyte + strlen( name ) + 1; MergePathAndName( fullname, tempFolderName, name ); WriteWholeFile( fullname, frombyte, tobyte - frombyte ); PerformLZ( fullname ); DeleteFile( fullname ); } BOOL ExtractFromModuleToFolder( char* where ) { char a[ 256 ]; char *wf, *wfend, *p; int state; char* lastStart = 0; //"JSFHDR"" is magic string to search char* magic = "jsfhd"; // lowcase and no "r" INTENTIONALLY int magiclen = strlen( magic ); GetModuleFileName( 0, a, 256 ); ReadWholeFile( a, &wf, &wfend ); if ( !wf ) return FALSE; p = wf; state = 0; for ( ; p < wfend; p++ ) { if ( state < magiclen ) { if ( *p == ( magic[ state ] - 32 ) ) // ascii only! state++; else state = 0; } else { if ( *p == 'R' ) { PossiblyExtract( lastStart, p + 1, where ); lastStart = p + 1; } state = 0; } } PossiblyExtract( lastStart, p + 1, where ); ReleaseWholeFile( wf ); return TRUE; } BOOL ExecuteInfAndWait( char* inf ) { char tinf[ MAX_PATH + 2 ]; SHELLEXECUTEINFO si; MergePathAndName( tinf, tempFolderName, inf ); tinf[ strlen( tinf ) + 1 ] = 0; si.cbSize = sizeof( si ); si.fMask = SEE_MASK_NOCLOSEPROCESS; si.hwnd= 0; si.lpVerb= "Install"; si.lpFile = tinf; si.lpParameters=0; si.lpDirectory = tempFolderName; si.nShow =SW_SHOWNORMAL; if ( ShellExecuteEx( &si ) == 0 ) { DWORD r = GetLastError(); char t[ 20 ]; wsprintf( t, "%d", r ); MessageBox( NULL, "Execution of inf failed.", t, MB_OK ); return FALSE; } WaitForSingleObject( si.hProcess, INFINITE ); return TRUE; } BOOL DeleteFilesIn( char* s ) { char toFind[ MAX_PATH ]; WIN32_FIND_DATA FindFileData; HANDLE FindHandle; MergePathAndName( toFind, s, "*.*" ); FindHandle = FindFirstFile( toFind, &FindFileData ); if ( FindHandle == INVALID_HANDLE_VALUE ) return FALSE; do { DWORD attr = FindFileData.dwFileAttributes; DWORD dontProcess = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY; if ( ( attr & dontProcess ) == 0 ) { MergePathAndName( toFind, s, FindFileData.cFileName ); DeleteFile( toFind ); } } while ( FindNextFile( FindHandle, &FindFileData ) ); FindClose( FindHandle ); return TRUE; } int PASCAL WinMain( HANDLE n1, HANDLE n2, LPSTR n3, int n4 ) { int r = MessageBox( NULL, "Proceed with installation?", JSAPPNAME, MB_OKCANCEL ); if ( r != IDOK ) return 1; CreateNameInTempDir( tempFolderName, INFFOLNAME, ".dir" ); CreateDirectory( tempFolderName, 0 ); ExtractFromModuleToFolder( tempFolderName ); ExecuteInfAndWait( INFFOLNAME ".inf" ); DeleteFilesIn( tempFolderName ); RemoveDirectory( tempFolderName ); MessageBox( NULL, "Installation completed.", JSAPPNAME, MB_OK ); return 0; } /* End of File */