Rev 1530 | Blame | Compare with Previous | Last modification | View Log | RSS feed
// Include header files /////////////////////////////////////////////////////#include "ishieldlib.h"/*-------------------------------------------------------------------------*//* FileStrReplace - Search and replace a string in a file *//* Mark Kendzior - mrk@amlibs.com *//* *//* Function: FileStrReplace(svFileName, //Full path of file to be updated*//* szSubStr, //String to be replaced *//* szReplaceStr) //String to replace *//* *//* Descrip: Convienence procedure to replace the szSubStr with *//* with szRelpaceStr in the file specified. *//* Return Values: *//* 1 - String replace worked. *//* 0 - String replace failed. *//* *//* Update: 05 August 1999 - Fixed endless loop when the original string *//* is replaced with a string that contains the original string. *//* *//*-------------------------------------------------------------------------*/function islib_FileStrReplace (svFileName, szSubStr, szReplaceStr)NUMBER nvPos, nResult;STRING svString, svSubStr1, svSubStr2, svNewString;BOOL bListUpdated, bFound;LIST listID, listNew;begin// create listslistID = ListCreate(STRINGLIST);listNew = ListCreate(STRINGLIST);if (ListReadFromFile(listID, svFileName) < 0) then // read list from fileislib_MessageBox("ListReadFromFile failed.", SEVERE);return 0;endif;//// SdShowInfoList ("", "Before replace", listID);bListUpdated = FALSE;nResult = ListGetFirstString (listID, svString); // start at the top of the listwhile (nResult = 0)bFound = FALSE; svNewString = "";nvPos = StrFind (svString, szSubStr); // find position in stringwhile (nvPos >= 0)StrSub (svSubStr1, svString, 0, nvPos); // replace stringStrSub (svSubStr2, svString, nvPos+StrLength (szSubStr), StrLength (svString));svNewString = svNewString + svSubStr1 + szReplaceStr;svString = svSubStr2;bFound = TRUE;nvPos = StrFind (svString, szSubStr); // find position in stringendwhile;if bFound = TRUE thensvNewString = svNewString + svString; // append rest of lineListAddString (listNew, svNewString, AFTER); // insert new string into new listbListUpdated = TRUE; // flag to write new list to fileelse // Add unchanged string to new listListAddString (listNew, svString, AFTER); // insert string into new listendif;nResult = ListGetNextString (listID, svString);endwhile;if bListUpdated thenListWriteToFile (listNew, svFileName); // write list to fileendif;//// SdShowInfoList ("", "After replace", listNew);ListDestroy (listID);ListDestroy (listNew);return 1;end;////////////////////////////////////////////////////////////////////////////////////////////// Function: islib_ModString//// Purpose: Function to search and replace text in a string.// Handy for reversing forward slashes in path descriptions.////////////////////////////////////////////////////////////////////////////////////////////function islib_ModString( szSubStr, szReplaceStr, szTargetString)STRING szInputDirectory;STRING szNewString, szSubStr1, szSubStr2, szString;NUMBER nError, nPos;BOOL bFound;beginszString = szTargetString;bFound = FALSE;szNewString = "";nPos = StrFind (szString, szSubStr); // find position in stringwhile (nPos >= 0)StrSub (szSubStr1, szString, 0, nPos); // replace stringStrSub (szSubStr2, szString, nPos+StrLength (szSubStr), StrLength (szString));szNewString = szNewString + szSubStr1 + szReplaceStr;szString = szSubStr2;bFound = TRUE;nPos = StrFind (szString, szSubStr); // find position in stringendwhile;if bFound = TRUE thenszTargetString = szNewString + szString; // append rest of lineendif;end;/////////////////////////////////////////////////////////////////////////////////// Function: islib_UpdateIniFile//// Purpose: Add all configuration data to the properties files supplied.// General purpose function, calls specific functions to reduce code./////////////////////////////////////////////////////////////////////////////////function islib_UpdateIniFile(szMyFileName, szMyTag, szMyReplaceStr)beginif ( islib_FileStrReplace (szMyFileName, szMyTag, szMyReplaceStr) = 0 )thenislib_MessageBox ( "Failed to update file=[" + szMyFileName + "], replace tag=[" +szMyTag+ "], update string=[" + szMyReplaceStr + "].\n" +"Installation did not complete successfully.", SEVERE);endif;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_LocalHostname//// EVENT: Function to extract the system hostname from the registry. It// may not be accurate however, if the system has 2 ethernet cards or// runs on DHCP./////////////////////////////////////////////////////////////////////////////////function islib_LocalHostname( szHostname )STRING szRegKey;NUMBER nvType, nvSize;beginszRegKey = "\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters";RegDBSetDefaultRoot (HKEY_LOCAL_MACHINE);if (RegDBKeyExist (szRegKey) = 1) thenRegDBGetKeyValueEx ( szRegKey, "Hostname", nvType, szHostname, nvSize );return 1;elsereturn 0;endif;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_Interbase//// EVENT: Function to extract the install location of Borland or Firebird// Interbase from the registry. Function provides 2 strings of data// - first the location of the Interbase, and then the specific type./////////////////////////////////////////////////////////////////////////////////function islib_Interbase( szIBType, szIBDir )STRING szRegKey;NUMBER nvType, nvSize;beginRegDBSetDefaultRoot (HKEY_LOCAL_MACHINE);szRegKey = "\\SOFTWARE\\Borland\\InterBase\\CurrentVersion";if (RegDBKeyExist (szRegKey) = 1) thenRegDBGetKeyValueEx ( szRegKey, "RootDirectory", nvType, szIBDir, nvSize );szIBType = "BORLAND";return 1;elseszRegKey = "\\SOFTWARE\\FirebirdSQL\\Firebird\\CurrentVersion";if (RegDBKeyExist (szRegKey) = 1) thenRegDBGetKeyValueEx ( szRegKey, "RootDirectory", nvType, szIBDir, nvSize );szIBType = "FIREBIRD";return 1;elsereturn 0;endif;endif;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_AccessControl//// EVENT: Function to extract the install location of the access control// client and return the value./////////////////////////////////////////////////////////////////////////////////function islib_AccessControl( szACDir )STRING szRegKey;NUMBER nvType, nvSize;beginRegDBSetDefaultRoot (HKEY_LOCAL_MACHINE);szRegKey = ERGAFC_PKG_REGISTRY_BASE + "ERGacclnt";if (RegDBKeyExist (szRegKey) = 1) thenRegDBGetKeyValueEx ( szRegKey, "BaseInstallDir", nvType, szACDir, nvSize );return 1;elsereturn 0;endif;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_setErgAfcPkgRegistryKeys//// This function sets the predefined registry key// for an ERG AFC package.//// We assume the key(s) shall exist in the following// default location of the registry://// HKEY_LOCAL_MACHINE\SOFTWARE\ERG\AFC//// the key name shall be defined by the// InstallShield project string ID_STING2.//// i.e. PKG_NAME = "ERGpxyif"//// The function shall also create the following string// parameters under this key these shall incllude://// PkgName = PKG_NAME// PkgNameLong = PKG_NAMELONG// PkgVersion = PKG_VERSION// PkgBuilbNum = PKG_BUILDNUM// PkgProjAcronym = PKG_PROJECTACRONYM// PkgDesc = PKG_DESC// BaseInstallDir = [INSTALLDIR]// PkgInstalled = Date/Time Package was installed//// Return Values://// SUCCESS: 1// ERROR: -1//// The function shall abort the installation if the// package subject string is greater that the predefined// allowable length size @MAX_PKGNAME_LENGTH.////////////////////////////////////////////////////////////////////////////////function islib_setErgAfcPkgRegistryKeys( nzType )STRING szKey;STRING szItem;STRING szValue;STRING szClass;STRING szMaxPkgNameLength;STRING szTime;STRING szDate;NUMBER nzResult;NUMBER nzERROR;NUMBER nzSUCCESS;NUMBER nzMaxPkgNameLength;beginif ( nzType != DEVICE_REGTYPE && nzType != PKG_REGTYPE )thenislib_MessageBox("Invalid parameter passed to islib_setErgAfcPkgRegistryKeys().", SEVERE);abort;endif;// now we just check to see if the project version numbers entered match// if they do not we warn, it not good to exit at this point we need to ensure the rest of// the install completes so we have a chnace of uninstall.//// we canot however check the build number and project acronym easily.//if ( PKG_VERSION != @PRODUCT_VERSION )thenislib_MessageBox("The build.pl PKG_VERSION=[" +PKG_VERSION+ "] property does not match the Ishield PRODUCT_VERSION=["+@PRODUCT_VERSION+"] property.\n" +"Please review the IShield Product Properties with the local build.pl details before compiling.", SEVERE);endif;// Define my local return values.//nzMaxPkgNameLength = MAX_PKGNAME_LENGTH;NumToStr ( szMaxPkgNameLength, nzMaxPkgNameLength );// we shall check to ensure the package name// that is stored in the ID_STRING2 string// does not exceed the predeifned 10 character limit.if ( StrLengthChars ( PKG_NAME ) < 0 )thenislib_MessageBox ("ERROR: Installation could not determine the package subject [" +PKG_NAME + "].", SEVERE);return ISLIB_ERROR;endif;if ( StrLengthChars ( PKG_NAME ) > nzMaxPkgNameLength )thenislib_MessageBox ("ERROR: The package subject [" +PKG_NAME + "] exceeds the max allowable length of " +szMaxPkgNameLength + " characters.", SEVERE);return ISLIB_ERROR;endif;// lets define the base key root locationRegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);// lets stop the logging of this change// as we do not want to remove it on uninstall.//Disable(LOGGING);// lets deal with the reg type we have been// told about.if ( nzType = DEVICE_REGTYPE )thenszKey = ERGAFC_DEVICE_REGISTRY_BASE;elseszKey = ERGAFC_PKG_REGISTRY_BASE;endif;szClass = "";if(RegDBCreateKeyEx (szKey, szClass) < 0)thenislib_MessageBox( "ERROR creating registry.", SEVERE );return ISLIB_ERROR;endif;// re-enable logging.//Enable(LOGGING);// lets deal with the reg type we have been// told about.if ( nzType = DEVICE_REGTYPE )thenszKey = ERGAFC_DEVICE_REGISTRY_BASE + PKG_NAME + "_" + PKG_VERSION + "-" + PKG_BUILDNUM + "." + PKG_PROJACRONYM;elseszKey = ERGAFC_PKG_REGISTRY_BASE + PKG_NAME;endif;szClass = "";if(RegDBCreateKeyEx (szKey, szClass) < 0)thenislib_MessageBox( "ERROR creating registry key=["+szKey+"].", SEVERE );return ISLIB_ERROR;else// Check if the newly created multi-level key exists.//if (RegDBKeyExist (szKey) < 0)thenislib_MessageBox ("ERROR: [" + szKey + "] registry key does not exist.", SEVERE);return ISLIB_ERROR;else// lets create the Version item.szItem = "PkgVersion";// lets verify the version string before we set it.if ( islib_verifyVersionFormat( PKG_VERSION ) < 0 )thenislib_MessageBox ("ERROR: PKG_VERSION field [" + PKG_VERSION + "] failed verification.", SEVERE);return ISLIB_ERROR;endif;szValue = PKG_VERSION;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the PkgBuildNum item.szItem = "PkgBuildNum";szValue = PKG_BUILDNUM;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the PkgProjAcronym item.szItem = "PkgProjAcronym";szValue = PKG_PROJACRONYM;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the PkgName item.szItem = "PkgName";szValue = PKG_NAME;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the PkgNameLong item.szItem = "PkgNameLong";szValue = PKG_NAMELONG;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the PkgDesc item.szItem = "PkgDesc";szValue = PKG_DESC;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the BaseInstallDir item.szItem = "BaseInstallDir";szValue = INSTALLDIR;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING_EXPAND,szValue, -1 ) < 0)thenislib_MessageBox( "Error creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the Installed item.szItem = "PkgInstalled";GetSystemInfo ( TIME, nzResult, szTime );GetSystemInfo ( DATE, nzResult, szDate );szValue = szDate + " " + szTime;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the LatestPatchID item.szItem = "LatestPatchID";szValue = "0000000000000-00";if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the Installed item.szItem = "LatestPatchInstalled";szValue = "00-00-0000 0:00:00";if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue + "].", SEVERE );return ISLIB_ERROR;endif;endif;endif;// we are done dude.//return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_setSystemPathEntry//// This function is used to maniplulate the System// environement path variable, by adding a pre-specified// entry to a pre-spcified location in the path variable.//// We pass:// 1. the new path we wish to add to the system path.// 2. the type of path (ie FULL, PARTIAL)// 3. the position of the new path (i.e. BEFORE or AFTER)//// In the event that a parameter is passed that is not supported// shall result in the user being notified and the installation// being aborted.//// Return Values://// SUCCESSFULL PATH CREATION: 1// PATH EXISTS: 2// ERROR: -1////////////////////////////////////////////////////////////////////////////////function islib_setSystemPathEntry( szNewPathEntry, bType, bPosition )STRING szKey;STRING szName;STRING szPathBuff;NUMBER nType, nSize;NUMBER nERROR, nSUCCESS1, nSUCCESS2;beginnSUCCESS1 = ISLIB_SUCCESS;nSUCCESS2 = 2;nERROR = ISLIB_ERROR;// lets verify the supported parameters//if ( bPosition != BEFORE && bPosition != AFTER )thenislib_MessageBox("ERROR: Incorrect parameter [bPosition] supplied to setSystemPathVariable(), check config. Installation aborting.", SEVERE );abort;endif;// lets verify the supported parameters//if ( bType != FULL && bType != PARTIAL )thenislib_MessageBox("ERROR: Incorrect parameter [bType] supplied to setSystemPathVariable(), check config. Installation aborting.", SEVERE );abort;endif;// first we need to get access to the current system// path.//RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment";szName = "Path";// Read the system pathif (RegDBGetKeyValueEx(szKey, szName, nType, szPathBuff, nSize) < 0)thenislib_MessageBox("ERROR: SYSTEM path environment variable not found. Installation aborting.", SEVERE );abort;endif;// Check whether or new entry has already been added// to the system path.//if ( szPathBuff % ( szNewPathEntry ) = TRUE )then//islib_MessageBox("System PATH already contains a reference to [" + szNewPathEntry + "], not updating.", INFORMATION);return nSUCCESS2;endif;// Initialize the path buffer.PathSet (szPathBuff);// Add C:\MSOffice as the first path in the search path.if (PathAdd(szNewPathEntry, "", bType, bPosition) < 0)thenislib_MessageBox ("Unable to add [ " + szNewPathEntry + "] to path buffer.", SEVERE);abort;endif;// Get the search path from the path buffer;// this call also releases the memory allocated// for the path buffer.PathGet (szPathBuff);// lets stop the logging of this change// as we do not want to remove it on uninstall.//Disable(LOGGING);// Now we need to update the registry setting with// our change.//if (RegDBSetKeyValueEx( szKey, szName, REGDB_STRING_EXPAND, szPathBuff, -1 ) < 0)thenislib_MessageBox( "Error writing System PATH registry key. Installation aborting.", SEVERE );abort;endif;// re-enable logging.//Enable(LOGGING);// done dude.return nSUCCESS1;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_removeSystemPathEntry//// This function is used to maniplulate the System// environement path variable by deleting a pre-specified// entry.//// We pass:// 1. the new path we wish to add to the system path.// 2. the type of path (ie FULL, PARTIAL)//// In the event that a parameter is passed that is not supported// shall result in the user being notified and the installation// being aborted.//// Return Values://// SUCCESS: 1// ERROR: -1////////////////////////////////////////////////////////////////////////////////function islib_removeSystemPathEntry( szNewPathEntry, bType )STRING szKey;STRING szName;STRING szPathBuff;NUMBER nType, nSize;NUMBER nERROR, nSUCCESS;beginnSUCCESS = ISLIB_SUCCESS;nERROR = ISLIB_ERROR;// lets verify the supported parameters//if ( bType != FULL && bType != PARTIAL )thenislib_MessageBox("ERROR: Incorrect parameter [bType] supplied to setSystemPathVariable(), check config. Installation aborting.", SEVERE );abort;endif;// first we need to get access to the current system// path.//RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment";szName = "Path";// Read the system pathif (RegDBGetKeyValueEx(szKey, szName, nType, szPathBuff, nSize) < 0)thenislib_MessageBox("ERROR: SYSTEM path environment variable not found. Installation aborting.", SEVERE );abort;endif;// Check whether the entry is part of the buff//if ( szPathBuff % ( szNewPathEntry ) != TRUE )then//islib_MessageBox("System PATH does not contain a reference to [ " + szNewPathEntry + " ], not updating.", INFORMATION);return nSUCCESS;endif;// Initialize the path buffer.PathSet (szPathBuff);// Add C:\MSOffice as the first path in the search path.if (PathDelete(szNewPathEntry, bType) < 0)thenislib_MessageBox ("Unable to delete [ " + szNewPathEntry + " ] from path buffer.", SEVERE);abort;endif;// Get the search path from the path buffer;// this call also releases the memory allocated// for the path buffer.PathGet (szPathBuff);// lets stop the logging of this change// as we do not want to remove it on uninstall.//Disable(LOGGING);// Now we need to update the registry setting with// our change.//if (RegDBSetKeyValueEx( szKey, szName, REGDB_STRING_EXPAND, szPathBuff, -1 ) < 0)thenislib_MessageBox( "Error writing System PATH registry key. Installation aborting.", SEVERE );abort;endif;// re-enable logging.//Enable(LOGGING);// done dude.return nSUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_setErgAfcPatchRegistryKeys//// This function sets the predefined registry key// for an ERG AFC patch.//// We assume the key(s) shall exist in the following// default location of the registry://// HKEY_LOCAL_MACHINE\SOFTWARE\ERG\AFC\patch//// the key name shall be defined by PATCH_ID//// i.e. PATCH_ID = "ERGCDXML050100-01"//// The function shall also create the following// parameters under this key//// PatchNum = The patch number (taken from the PATCH_ID, the last 2 characters).// ParentPkgVersion = The version number of the parent package (PKG_VERSION).// Installed = The date and time the patch was installed ().//// Return Values://// ISLIB_SUCCESS: registry key set.// ISLIB_ERROR: failed to set registry key.////////////////////////////////////////////////////////////////////////////////function islib_setErgAfcPatchRegistryKeys()STRING szKey;STRING szItem;STRING szValue;STRING szClass;STRING szDate;STRING szTime;STRING szPatchNumber;STRING szPkgBaseInstallDir;STRING szPkgVersion;STRING szPkgInstalled;STRING szPkgLatestPatchID;STRING szPkgLatestPatchInstalled;STRING szPkgLatestPatchNumber;NUMBER nzPkgLatestPatchNumber;NUMBER nzResult;begin// lets verify our PatchID//if ( islib_verifyPatchIDFormat( PATCH_ID ) < 0 )thenislib_MessageBox("ERROR: PatchID [" + PATCH_ID +"] failed verification.", SEVERE);return ISLIB_ERROR;endif;// lets define the base key root locationRegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = ERGAFC_PATCH_REGISTRY_BASE + PATCH_ID;szClass = "";if(RegDBCreateKeyEx (szKey, szClass) < 0)thenislib_MessageBox( "ERROR: updating registry.", SEVERE );return ISLIB_ERROR;else// Check if the newly created multi-level key exists.//if (RegDBKeyExist (szKey) < 0)thenislib_MessageBox ("ERROR: [" + szKey + "] registry key does not exist.", SEVERE);return ISLIB_ERROR;else// lets create the ParentPkgVersion item.szItem = "ParentPkgVersion";// lets verify the version string before we set it.if ( islib_verifyVersionFormat( PKG_VERSION ) < 0 )thenislib_MessageBox ("ERROR: PKG_VERSION field [" + PKG_VERSION + "] failed verification.", SEVERE);return ISLIB_ERROR;endif;szValue = PKG_VERSION;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "ERROR: creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets get the patch number identifier//if ( islib_getPatchNumber ( PATCH_ID , szPatchNumber ) < 0 )thenislib_MessageBox("ERROR: islib_getPatchNumber() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;// lets create the PatchNum item.szItem = "PatchNumber";// lets write the reg item.//if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szPatchNumber, -1 ) < 0)thenislib_MessageBox( "ERROR: creating [" +szKey + "\\" + szItem +"] registry key, value [" +szPatchNumber +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the Installed item.szItem = "PatchInstalled";GetSystemInfo ( TIME, nzResult, szTime );GetSystemInfo ( DATE, nzResult, szDate );szValue = szDate + " " + szTime;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING_EXPAND,szValue, -1 ) < 0)thenislib_MessageBox( "ERROR: creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets create the obsoleted patch information.//// first we need to get the current product patch number// we are going to obsolete//if (islib_getErgAfcPkgLatestPatchIDRegistryDetails( szPkgLatestPatchID,szPkgLatestPatchInstalled) < 0 )thenislib_MessageBox("ERROR: islib_getErgAfcPkgLatestPatchIDRegistryDetails() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;// lets get our patch number.//if ( islib_getPatchNumber( szPkgLatestPatchID, szPkgLatestPatchNumber ) < 0 )thenislib_MessageBox("ERROR: islib_getPatchNumber() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;StrToNum(nzPkgLatestPatchNumber, szPkgLatestPatchNumber);// lets see what our latest patch is?//if ( nzPkgLatestPatchNumber = 0 )thenszValue = "0000000000-00";elseszValue = szPkgLatestPatchID;endif;// we have the product details lets update the// our patch details.//szItem = "ObsoletedPatchID";if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "ERROR: creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets see what our latest patch is?//if ( nzPkgLatestPatchNumber = 0 )thenszValue = "00-00-0000 0:00:00";elseszValue = szPkgLatestPatchInstalled;endif;szItem = "ObsoletedPatchInstalled";if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "ERROR: creating [" +szKey + "\\" + szItem +"] registry key, value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;endif;endif;// we are done dude.//return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_getPatchNumber//// This function extracts the numeric section from the supplied// PatchID. It sets the szPatchNum variable thus returning the// patch number to the calling function.//// Return Value://// ISLIB_SUCCESS: ok// ISLIB_ERROR: encountered a problem.////////////////////////////////////////////////////////////////////////////////function islib_getPatchNumber( szPatchID, szPatchIDNum )LIST listID;STRING szPatchIDName;begin// lets verify our PatchID passed in.//if ( islib_verifyPatchIDFormat( szPatchID ) < 0 )thenislib_MessageBox("ERROR: PatchID [" +szPatchID +"] failed verification.", SEVERE);return ISLIB_ERROR;endif;// Create a list to hold the bits that make up the// patch name.listID = ListCreate (STRINGLIST);// Get each bit from the passed value.// we have already verified that the format is ok// from above.//StrGetTokens (listID, szPatchID, "-");// lets get the patch number section.ListGetFirstString ( listID, szPatchIDName );ListGetNextString ( listID, szPatchIDNum );// Remove the list from memory.ListDestroy (listID);// we are done dure.//return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_verifyPatchIDFormat//// This function is used to verify the format of the parameter passed to that// of a PatchID. The format of a PatchID is defined in the Build & Release// Guidelines document.//// Return Values://// ISLIB_SUCCESS: format correct.// ISLIB_ERROR: format incorrect.//// The function shall abort processing if it detects that the PatchId is// of an incorrect format. This information is critical to the configuration// management and must be correct before proceeding.////////////////////////////////////////////////////////////////////////////////function islib_verifyPatchIDFormat( szPatchID )LIST listID;STRING szSection1;STRING szSection2;STRING szLengthSec1;STRING szLengthSec2;NUMBER nzLengthSec1;NUMBER nzLengthSec2;NUMBER nzNumSections;NUMBER nzPatchIDLength;NUMBER nzVar;BOOL bzReturnFlag;begin// Make available the predefined// definitions.//nzPatchIDLength = MAX_PATCHID_FORMAT_LENGTH;nzLengthSec1 = MAX_PATCHID_NAME_FORMAT_LENGTH;nzLengthSec2 = MAX_PATCHID_NUMBER_FORMAT_LENGTH;nzNumSections = NUM_PATCHID_SECTIONS;bzReturnFlag = TRUE;// Create a list to hold the bits that make up the// patch name.listID = ListCreate (STRINGLIST);// Get each path from the search path into the list.if (StrGetTokens (listID, szPatchID, "-") > 0)then// Report the error.islib_MessageBox ("Patch ID [" + szPatchID +"] has an incorrect format." +"\n\n(Info: A PatchID MUST use the following format, PPPPPPPPPPNNNNNN-NN).",SEVERE);bzReturnFlag = FALSE;else// we have our bits lets verify them// how many bits did we get?//if ( ListCount ( listID ) != nzNumSections )thenislib_MessageBox ( "Patch ID [" +szPatchID +"] has an incorrect format.\n\n(Info: A PatchID MUST use the following format, PPPPPPPPPPNNNNNN-NN) .",SEVERE );bzReturnFlag = FALSE;endif;// lets go through the sections,// lets check the patch name section.ListGetFirstString ( listID, szSection1 );if ( StrLengthChars ( szSection1 ) > nzLengthSec1 )thenNumToStr( szLengthSec1, nzLengthSec1 );islib_MessageBox ("Patch ID [" + szPatchID +"] has an incorrectly formatted patch name component [" +szSection1 +"].\n\n(Info: A PatchID name MUST use upto " + szLengthSec1 +" alpha-numeric characters, PPPPPPPPPPNNNNNN).",SEVERE);bzReturnFlag = FALSE;endif;// lets check the patch number section.// first we check the length.ListGetNextString ( listID, szSection2 );if ( StrLengthChars ( szSection2 ) != nzLengthSec2 )thenNumToStr( szLengthSec2, nzLengthSec2 );islib_MessageBox ("Patch ID [" + szPatchID +"] has an incorrectly formatted patch number component [" +szSection2 +"].\n\n(Info: A PatchID number MUST use " + szLengthSec2 + " numeric digits ONLY, NN).",SEVERE);bzReturnFlag = FALSE;endif;// second we check the contents to be numeric.if ( StrToNum ( nzVar, szSection2 ) < 0 )thenislib_MessageBox ("Patch ID [" + szPatchID +"] has an non-numeric patch number component [" + szSection2 +"].\n\n(Info: A PatchID number MUST use " + szLengthSec2 +" numeric digits ONLY, NN).",SEVERE);bzReturnFlag = FALSE;endif;endif;// Remove the list from memory.ListDestroy (listID);// we are done, and things are ok.if ( bzReturnFlag = TRUE )thenreturn ISLIB_SUCCESS;elsereturn ISLIB_ERROR;endif;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_verifyLocationIDFormat//// This function is used to ensure that the parameter passed is of the// required location ID format, i.e. PPPPPPPPPP-LLL-SSS-NNNNNNNN//// Return Values:// ISLIB_SUCCESS - correct format// ISLIB_ERROR - incorrect format////////////////////////////////////////////////////////////////////////////////function islib_verifyLocationIDFormat ( szLocationID )LIST listID;STRING svSearchPath;STRING szTitle, szMsg;NUMBER nzNumberLocationIDSections;STRING szSec1, szSec2, szSec3, szSec4;NUMBER nzLengthSec1, nzLengthSec2, nzLengthSec3, nzLengthSec4;beginnzNumberLocationIDSections = NUM_LOCATIONID_SECTIONS;nzLengthSec1 = MAX_LOCATIONID_SECTION_1_FORMAT_LENGTH;nzLengthSec2 = MAX_LOCATIONID_SECTION_2_FORMAT_LENGTH;nzLengthSec3 = MAX_LOCATIONID_SECTION_3_FORMAT_LENGTH;nzLengthSec4 = MAX_LOCATIONID_SECTION_4_FORMAT_LENGTH;// Create a list to hold the bits that make up the// location ID.listID = ListCreate (STRINGLIST);// Get each path from the search path into the list.if (StrGetTokens (listID, szLocationID, "-") > 0)then// Report the error.islib_MessageBox ("Location ID [" + szLocationID + "] has incorrect format,\n(use PPPPPPPPPP-LLL-SSSSSS-NNNNNNNN).",WARNING);else// We have our bits lets just check to see// if they are of the correct format.// how many bits did we get?//if ( ListCount ( listID ) != nzNumberLocationIDSections )thenislib_MessageBox ( "Location ID [" +szLocationID +"] has incorrect number of sections,\n(i.e. does not follow format PPPPPPPPPP-LLL-SSSSSS-NNNNNNNN) .",WARNING );endif;// lets go through the sections,ListGetFirstString ( listID, szSec1 );if ( StrLengthChars ( szSec1 ) != nzLengthSec1 )thenislib_MessageBox ("Location ID [" + szLocationID +"] has incorrectly formated section 1 [" +szSec1 + "],\n(use format PPPPPPPPPP-LLL-SSSSSS-NNNNNNNN).",WARNING);endif;ListGetNextString ( listID, szSec2 );if ( StrLengthChars ( szSec2 ) != nzLengthSec2 )thenislib_MessageBox ("Location ID [" + szLocationID +"] has incorrectly formated section 2 [" +szSec2 + "],\n(use format PPPPPPPPPP-LLL-SSSSSS-NNNNNNNN).",WARNING);endif;ListGetNextString ( listID, szSec3 );if ( StrLengthChars ( szSec3 ) != nzLengthSec3 )thenislib_MessageBox ("Location ID [" + szLocationID +"] has incorrectly formated section 3 [" +szSec3 + "],\n(use format PPPPPPPPPP-LLL-SSSSSS-NNNNNNNN).",WARNING);endif;ListGetNextString ( listID, szSec4 );if ( StrLengthChars ( szSec4 ) != nzLengthSec4 )thenislib_MessageBox ("Location ID [" + szLocationID +"] has incorrectly formated section 4 [" +szSec4 + "],\n(use format PPPPPPPPPP-LLL-SSSSSS-NNNNNNNN).",WARNING);endif;endif;// Remove the list from memory.ListDestroy (listID);return TRUE;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_patchPreInstall//// 1. initialise predefined parameters// 2. verifyPatchIDFormat.// 3. verifyPatch Installation can proceed.// 3. create patch save location// 4. extract the filelist// 5. create patchLog file// 6. copy old items and log original locations in patchLog file.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_patchPreInstall ()STRING szPatchIDDir;STRING szPatchIDSaveDir;STRING szPatchIDLogFileLocation;STRING szPatchIDLogFileName;STRING szMySrcFile;STRING szMyDstFile;STRING szResult;NUMBER nzResult;STRING szMsg;STRING szTitle;LIST PatchItemsListID;NUMBER nzRetVal;NUMBER nzFileHandle;begin// lets initialse the predefined parameter// so we can use them.//szPatchIDDir = PATCHID_DIR;szPatchIDSaveDir = PATCHID_SAVE_DIR;szPatchIDLogFileLocation = PATCHID_LOGFILE_LOCATION;szPatchIDLogFileName = PATCHID_LOGFILE_NAME;//SprintfBox (INFORMATION, "Debug Information",// "id=[%s], save=[%s], file=[%s]. ",// szPatchIDDir, szPatchIDSaveDir, szPatchIDLogFileLocation);// we need to determine if we can install this patch based on the// patching rules we have predefined. These rules govern the// patch sequencing and obseletion criteria.//if ( islib_checkInstallPatch () < 0 )thenislib_MessageBox("This patch cannot be installed on this system.", SEVERE);return ISLIB_ERROR;endif;// disable the logging// functions, we shall clean up later.//Disable(LOGGING);// Lets get our list of items that we are going to patch.//PatchItemsListID = ListCreate (STRINGLIST);if ( islib_getPatchItemsList(PatchItemsListID) < 0 )thenislib_MessageBox ("Error failed to create the patch items list.", SEVERE);return ISLIB_ERROR;endif;// lets see if anyone has left any junk// behind.//if ( Is(PATH_EXISTS, szPatchIDSaveDir) = TRUE )thenislib_MessageBox("Patch directory [" + szPatchIDDir + "] already exists." +"\nPlease rectify prior to installing patch.", SEVERE);return ISLIB_ERROR;endif;// lets create our patch store//if ( CreateDir ( szPatchIDSaveDir ) < 0 )thenislib_MessageBox("Failed to create [" + szPatchIDSaveDir + "] dir.", SEVERE);return ISLIB_ERROR;endif;// lets populate our patch store//if ( islib_savePatchItems(PatchItemsListID) < 0 )thenislib_MessageBox ("ERROR: Failed to complete patch save action.", SEVERE);return ISLIB_ERROR;endif;// lets free resources.//ListDestroy(PatchItemsListID);// lets re-enable logging here.// we have created our patch store// we need to clean it up later.//Enable(LOGGING);// we are done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_checkInstallPatch//// This function is used to check if the patch can be installed.// The rules that govern if a patch can be installed are://// 1. A parent package that has a name equal that defined in the// project Subject field has already been installed on the system.//// This condition shall be checked ensuring the BaseInstallDir registry key// exists for the parent package defined in the project Subject setting.//// If the parent package registry key does not exist the patch shall stop// the patch installation.//// 2. The parent package version number is equal to that of the patch.// The patch version number is defined in the PKG_VERSION variable.//// (i.e. The patch MYPKG010001-0N can only be used to patch any item installed by the package// MYPKG of version 1.0.1).//// This check shall be completed by comparing the Version registry setting of the package// with the PKG_VERSION variable of the patch.//// A patch can only be used to update a pre-defined specific parent package version.//// 3. The same patch has not already been installed.// (ie you cannot install MYPKG010001-01 twice.//// This shall be ensured by the use of the OnMaintUIBefore() function. This// function ensures that a package with the same product codes cannot be installed twice.//// 4. The patch has a patch number that is greater in value that the most recently// applied patch.//// (ie the patch MYPKG010001-01 cannot be applied after MYPKG010001-02).//// This shall be checked by retrieving the most parent package registry key// containing the patch number of the most recently installed patch and comparing it// to the current patch number.//// You can apply patch MYPKG010001-06 to a parent package that has had all// patches applied upto MYPKG010001-04.//// You will not how ever be able to subsequnetly apply patch MYPKG010001-05// as this patch has been obsoleted by MYPKG010001-06.////// Return Values://// ISLIB_SUCCESS - completed ok// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_checkInstallPatch ()STRING szPkgName;STRING szPatchID;STRING szPatchIDNumber;STRING szPatchPkgVersion;STRING szPatchPkgProjAcronym;STRING szPkgBaseInstallDir;STRING szPkgVersion;STRING szPkgInstalled;STRING szPkgLatestPatchID;STRING szPkgLatestPatchInstalled;STRING szPkgBuildNum;STRING szPkgProjAcronym;STRING szPkgDesc;STRING szMyPkgLatestPatchNumber;NUMBER nzPatchIDNumber;NUMBER nzMyPkgLatestPatchNumber;NUMBER nResult;begin// initialise local variables.//szPatchID = PATCH_ID;szPatchPkgVersion = PKG_VERSION;szPkgName = PKG_NAME;szPatchPkgProjAcronym = PKG_PROJACRONYM;// lets verify our PatchID format//if ( islib_verifyPatchIDFormat( szPatchID ) < 0 )thenislib_MessageBox("PatchID [" + szPatchID + "] failed format verification.", SEVERE);return ISLIB_ERROR;endif;// 1. lets check to see if our parent package exists//if ( islib_checkErgAfcPkgExists(szPkgName) < 0 )then// we could not confirm that the parent package exists// so we assume that the package was removed.//// This implies we cannot install this patch//islib_MessageBox("Failed to detect parent package, " + szPkgName + " on system.\n" +"Parent package may not be not installed.", SEVERE);return ISLIB_ERROR;else// our parent package exists lets get its current details//if (islib_getErgAfcPkgRegistryDetails( szPkgBaseInstallDir,szPkgVersion,szPkgInstalled,szPkgLatestPatchID,szPkgLatestPatchInstalled,szPkgBuildNum,szPkgProjAcronym,szPkgDesc ) < 0 )then// we encountered an error getting the details//islib_MessageBox("ERROR: islib_getErgAfcPkgRegistryDetails() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;// lets get our patch number.//if ( islib_getPatchNumber( szPatchID, szPatchIDNumber ) < 0 )thenislib_MessageBox("ERROR: islib_getPatchNumber() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;// we got our details lets apply the business rules// of our patch management strategy.//// 2. version numbers must be equal to install a patch//if ( islib_verifyVersionFormat(szPkgVersion) < 0 )thenislib_MessageBox("ERROR: Package version [" + szPkgVersion + "] failed format verification." +"\nCheck configuration.", SEVERE);return ISLIB_ERROR;endif;if ( islib_verifyVersionFormat(szPatchPkgVersion) < 0 )thenislib_MessageBox("ERROR: Patch version [" + szPatchPkgVersion + "] failed format verification." +"\nCheck configuration.", SEVERE);return ISLIB_ERROR;endif;// lets check to see that the patch projects are ok//if (szPatchPkgProjAcronym != szPkgProjAcronym)thenislib_MessageBox("ERROR: Patch project [" + szPatchPkgProjAcronym +"] does not match parent package project [" + szPkgProjAcronym +"].\n" +"Check configuration.", SEVERE);return ISLIB_ERROR;endif;// our versions are of the correct format lest// compare them.nResult = islib_compareVersions(szPkgVersion, szPatchPkgVersion);if ( nResult != ISLIB_VERSION_EQUALS )thenislib_MessageBox("The patch you trying to install does not have a compatible version number." +"\n\nThis patch [" + szPatchID + "] version [" + szPatchPkgVersion + "] is not the same as " +"\nthe [" + szPkgName + "] parent package version [" + szPkgVersion + "]." +"\n\nCheck patch configuration.", WARNING);return ISLIB_ERROR;endif;// 3 and 4. the patch number is greater than the latest// patch previously installed. You cannot install the same// patch number again.//// lets get the latest patch installed patch number.//if ( islib_getPatchNumber( szPkgLatestPatchID, szMyPkgLatestPatchNumber ) < 0 )thenislib_MessageBox("ERROR: islib_getPatchNumber() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;StrToNum(nzPatchIDNumber, szPatchIDNumber);StrToNum(nzMyPkgLatestPatchNumber, szMyPkgLatestPatchNumber);if ( nzPatchIDNumber = nzMyPkgLatestPatchNumber )thenislib_MessageBox("The patch you trying to install has already been installed on [" +szPkgLatestPatchInstalled + "].", WARNING);return ISLIB_ERROR;elseif (nzPatchIDNumber < nzMyPkgLatestPatchNumber )thenislib_MessageBox("The patch you trying to install [" + szPatchID + "] has been obsoleted " +"\nby a patch that has been previously installed." +"\n\nThe latest patch to be installed for the parent package [" + szPkgName + "] has " +"\npatch ID [" + szPkgLatestPatchID + "], installed on [" +szPkgLatestPatchInstalled + "].", WARNING);return ISLIB_ERROR;endif;endif;// if we got to here things are ok, we now need to ensure that the// INSTALLDIR variable is set to the PkgBaseInstallDir variable// we retieved from the registry. this ensures that the patch// starts from the same point as the parent package.//INSTALLDIR = szPkgBaseInstallDir;// done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_compareVersions//// This function is used to compare two string that contain version numbers// The version has a pre-defined format of M.M.M where M is any integer.//// Version A is passed in as parameter 1,// Version B is passed in as parameter 2.//// The priority for comparision shall be left to right,// (ie the left most integer is the major number, whilst the right mose integer// is the minor number).//// Return Values://// -1: encountered a processing error.// 0: versions are equal// 1: version A, is greater that version B// 2: version A, is less than version B////////////////////////////////////////////////////////////////////////////////function islib_compareVersions(szVersionA, szVersionB)LIST lzVersionA;LIST lzVersionB;STRING szVersionAMajor;STRING szVersionAMiddle;STRING szVersionAMinor;STRING szVersionBMajor;STRING szVersionBMiddle;STRING szVersionBMinor;NUMBER nzVersionAMajor;NUMBER nzVersionAMiddle;NUMBER nzVersionAMinor;NUMBER nzVersionBMajor;NUMBER nzVersionBMiddle;NUMBER nzVersionBMinor;begin// lets first verify that the format of each// version string is ok.//if ( islib_verifyVersionFormat(szVersionA) < 0 )thenislib_MessageBox("ERROR: Version [" + szVersionA + "] failed format verification." +"\nCheck version configuration.", SEVERE);return ISLIB_ERROR;endif;if ( islib_verifyVersionFormat(szVersionB) < 0 )thenislib_MessageBox("ERROR: Version [" + szVersionB + "] failed format verification." +"\nCheck version configuration.", SEVERE);return ISLIB_ERROR;endif;// first we need to check the formaat of each// version numberlzVersionA = ListCreate(STRINGLIST);// If an error occurred, report it.if (lzVersionA = LIST_NULL) thenislib_MessageBox ("ERROR: Unable to create list lzVersionA.", SEVERE);return ISLIB_ERROR;endif;// lets parse our version A string.// and load our local variables.StrGetTokens(lzVersionA, szVersionA, ".");ListGetFirstString( lzVersionA, szVersionAMajor );ListGetNextString ( lzVersionA, szVersionAMiddle);ListGetNextString ( lzVersionA, szVersionAMinor);StrToNum(nzVersionAMajor, szVersionAMajor);StrToNum(nzVersionAMiddle, szVersionAMiddle);StrToNum(nzVersionAMinor, szVersionAMinor);lzVersionB = ListCreate(STRINGLIST);// If an error occurred, report it.if (lzVersionB = LIST_NULL) thenislib_MessageBox ("ERROR: Unable to create list lzVersionB.", SEVERE);return ISLIB_ERROR;endif;// lets parse our version B string.// and load our local variables.//StrGetTokens(lzVersionB, szVersionB, ".");ListGetFirstString( lzVersionB, szVersionBMajor );ListGetNextString ( lzVersionB, szVersionBMiddle);ListGetNextString ( lzVersionB, szVersionBMinor);StrToNum(nzVersionBMajor, szVersionBMajor);StrToNum(nzVersionBMiddle, szVersionBMiddle);StrToNum(nzVersionBMinor, szVersionBMinor);// now we are ready to do the comparision.// remember we are comparing A to B// lets check the major numbers first//if ( nzVersionAMajor = nzVersionBMajor )then// we need to check the middle numbersif ( nzVersionAMiddle = nzVersionBMiddle)then// we need to check the minor numbersif ( nzVersionAMinor = nzVersionBMinor)then// if we get here the versions are equal//return ISLIB_VERSION_EQUALS;elseif(nzVersionAMinor > nzVersionBMinor)then// here version A minor is greater than version B minor// this implies the version A is greater than version B.//return ISLIB_VERSION_GREATER_THAN;else// here version A minor is less than version B minor// this implies the version A is less than version B.//return ISLIB_VERSION_LESS_THAN;endif;elseif (nzVersionAMiddle > nzVersionBMiddle)then// here version A middle is greater than version B middle// this implies the version A is greater than version B.//return ISLIB_VERSION_GREATER_THAN;else// here version A middle is less than version B middle// this implies that version A is less than version B.return ISLIB_VERSION_LESS_THAN;endif;elseif (nzVersionAMajor > nzVersionBMajor)then// here version A major is greater than version B major// this implies the version A is greater than version B.//return ISLIB_VERSION_GREATER_THAN;else// here version A major is less than version B major// this implies that version A is less than version B.return ISLIB_VERSION_LESS_THAN;endif;// free resources.//ListDestroy(lzVersionA);ListDestroy(lzVersionB);// done. but we should never get here.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_verifyVersionFormat//// This function is used to verify the format of version number.// A version has a pre-defined format of M.M.M where M is any integer.//// Return Values:// ISLIB_SUCCESS - format ok// ISLIB_ERROR - format NOT ok.////////////////////////////////////////////////////////////////////////////////function islib_verifyVersionFormat( szVersion )LIST lzVersionID;NUMBER nzCount;NUMBER nzRetVal;STRING szBit;NUMBER nzBit;beginlzVersionID = ListCreate(STRINGLIST);// If an error occurred, report it.if (lzVersionID = LIST_NULL) thenislib_MessageBox ("ERROR: Unable to create list lzVersionID.", SEVERE);return ISLIB_ERROR;endif;// lets parse our version string.StrGetTokens(lzVersionID, szVersion, ".");// Count the number of program folders in the list.nzCount = ListCount (lzVersionID);if ( nzCount != MAX_NUM_VERSION_FORMAT_SECTIONS )thenislib_MessageBox ("ERROR: Version [" + szVersion + "] has an incorrect format, " +"(i.e. use N.N.N).", SEVERE);return ISLIB_ERROR;endif;// lets confirm all the bits are numeric.//nzRetVal = ListGetFirstString ( lzVersionID, szBit );while ( nzRetVal != END_OF_LIST )if ( StrToNum(nzBit, szBit) < 0 )thenislib_MessageBox ("Version ["+szVersion+"] contains non-numeric component.", SEVERE);return ISLIB_ERROR;endif;// get next bit.nzRetVal = ListGetNextString ( lzVersionID, szBit );endwhile;// lets free resources.ListDestroy(lzVersionID);// done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_getPatchItemsList//// This function is used to retireive all file items to be delivered by this// patch package.//// We make use of the information avaiable in the installshield config// An we populate a List variable that can be accessed by the calling// function later.////// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_getPatchItemsList ( lzPatchItemsListID )NUMBER nzResult;NUMBER nzTmpVar;LIST lzTopFeatureListID;LIST lzSubFeatureListID;LIST lzSubFeatureItemListID;LIST lzParseFeatureListID;STRING szTmpVar;STRING szTopFeature;STRING szSubFeature;STRING szSubFeatureOnlyStr;STRING szTmpVar1;STRING szSubFeatureItem;STRING szSubFeatureItem_lc;STRING szSubFeatureDescField;STRING szSubFeatureDescType;STRING szSubFeatureItemsLocation;STRING szString;NUMBER nzSubFeatureItemRetVal;NUMBER nzTopFeatureCount;NUMBER nzSubFeatureCount;NUMBER nzSubFeatureItemCount;NUMBER nzTopFeatureRetVal;NUMBER nzSubFeatureRetVal;begin// Initialize the string list.lzTopFeatureListID = ListCreate (STRINGLIST);if (lzTopFeatureListID = LIST_NULL)thenislib_MessageBox ("System error, unable to create top-level feature list.", SEVERE);return ISLIB_ERROR;endif;// Create a list of top-level features in the specified media.if ( FeatureListItems (MEDIA, "", lzTopFeatureListID) < 0 )thenislib_MessageBox ("System error, failed to get top-level feature list.", SEVERE);return ISLIB_ERROR;endif;// Count the number of program folders in the list.nzTopFeatureCount = ListCount (lzTopFeatureListID);if ( nzTopFeatureCount <= 0 )thenislib_MessageBox ("Failed to detect any top-level features in patch configuration." +"\nCheck patch configuration.", SEVERE);return ISLIB_ERROR;endif;// check to see if we exceed the max supported top-level// features//if ( nzTopFeatureCount > MAX_NUM_TOP_LEVEL_FEATURES )thennzTmpVar = MAX_NUM_TOP_LEVEL_FEATURES;NumToStr(szTmpVar, nzTmpVar);islib_MessageBox ("ERROR: current patch strategy ONLY supports [" +szTmpVar + "] top-level feature. Check patch features configuration.", SEVERE);return ISLIB_ERROR;endif;// lets process the top level list.// now we need to get the sub-features of each top-level feature.//nzTopFeatureRetVal = ListGetFirstString ( lzTopFeatureListID, szTopFeature );while ( nzTopFeatureRetVal != END_OF_LIST )// Now for each top-level feature we need to get the associated// sub features.// Initialize the string list.lzSubFeatureListID = ListCreate (STRINGLIST);if (lzSubFeatureListID = LIST_NULL)thenislib_MessageBox ("System error, unable to create sub-feature list.", SEVERE);return ISLIB_ERROR;endif;// Create a list of sub-features in the specified media.if ( FeatureListItems (MEDIA, szTopFeature, lzSubFeatureListID) < 0 )thenislib_MessageBox ("System error, failed to get sub-feature list.", SEVERE);return ISLIB_ERROR;endif;// Count the number of program folders in the list.nzSubFeatureCount = ListCount (lzSubFeatureListID);if ( nzSubFeatureCount <= 0 )thenislib_MessageBox ("Failed to detect any sub-features in patch configuration." +"\nCheck patch configuration.", SEVERE);return ISLIB_ERROR;endif;// now we need to get the sub-features of each top-level// feature.nzSubFeatureRetVal = ListGetFirstString ( lzSubFeatureListID, szSubFeature );while ( nzSubFeatureRetVal != END_OF_LIST )// we need to process each sub-feature, tht directly relates to// a component that delivers a file.//// first we need to extract the sub-feature from the string we have,// the format is "topfeature\subfeature"lzParseFeatureListID = ListCreate(STRINGLIST);StrGetTokens (lzParseFeatureListID, szSubFeature, "\\");// Count the number of program folders in the list.nzResult = ListCount (lzParseFeatureListID);if ( nzResult != MAX_NUM_FEATURE_LEVELS )thenislib_MessageBox ("ERROR: [" + szSubFeature + "] feature exceedes 2 levels." +"\nCheck patch features configuration.", SEVERE);return ISLIB_ERROR;endif;ListGetFirstString ( lzParseFeatureListID, szTmpVar1 );ListGetNextString ( lzParseFeatureListID, szSubFeatureOnlyStr );// lets create the list to contain all sub-feature items//lzSubFeatureItemListID = ListCreate(STRINGLIST);// let extract all the items for my sub-feature//FeatureFileEnum ( MEDIA, szTopFeature, szSubFeatureOnlyStr+"\\*.*", lzSubFeatureItemListID, NO_SUBDIR );// Count the number of sub-feature component items in the list.nzSubFeatureItemCount = ListCount (lzSubFeatureItemListID);if ( nzSubFeatureItemCount <= 0 )thenislib_MessageBox ("Failed to detect any items to patch in configuration. " +"\nCheck [" + szSubFeature + "] features/components relationship in patch configuration.", SEVERE);return ISLIB_ERROR;endif;// Get the description property for sub-feature.// This field contains the relative path from the INSTALLDIR// for the items in the component == subFeature.//FeatureGetData (MEDIA, szSubFeature, FEATURE_FIELD_DESCRIPTION, nzResult, szSubFeatureDescField);if ( szSubFeatureDescField = "" )thenislib_MessageBox (szSubFeature + " feature description field is blank." +"Check feature in patch configuration.", SEVERE);return ISLIB_ERROR;endif;// we need to determine if the description field is relative or// absolute. This is done by looking for ":\" in the contents// if find this then it must be absolute, else it is a relative path// evaluated from INSTALLDIR.//if ( szSubFeatureDescField % ":\\" )thenszSubFeatureDescType = "Absolute";elseszSubFeatureDescType = "Relative";endif;// lets determine the location of our items//if ( szSubFeatureDescType = "Absolute" )thenszSubFeatureItemsLocation = szSubFeatureDescField;elseszSubFeatureItemsLocation = INSTALLDIR ^ szSubFeatureDescField;endif;// for each item in the list we need to add it to the// larger list in a pre-defined format.//// the format being://// item;location////nzSubFeatureItemRetVal = ListGetFirstString ( lzSubFeatureItemListID, szSubFeatureItem );while ( nzSubFeatureItemRetVal != END_OF_LIST )// we will only add an item to the list if it exist// on disk. a patch by definition cannot add new files// to a distribution.//// !!!! Need to think about libraries. these files// break the rule!!!!//szString = szSubFeatureItemsLocation ^ szSubFeatureItem;if ( Is (FILE_EXISTS, szString) = FALSE )then// there is a special case for dll items// if we do not locate them on disk we can still// proceed with the patch//StrToLower(szSubFeatureItem_lc, szSubFeatureItem);if ( (szSubFeatureItem_lc % ".dll") != TRUE )thenislib_MessageBox ("Failed to locate pre-installed package item [" +szString + "] on disk." +"\nA patch cannot add new items to an existing installation.", SEVERE);return ISLIB_ERROR;elseislib_MessageBox ("Patch is changing default installation by delivering new dll item [" +szSubFeatureItem + "].", INFORMATION);endif;else// we located the item on our disk// lets log it for patching.//szString = szSubFeatureItem+ ";" + szSubFeatureItemsLocation;if (ListAddString (lzPatchItemsListID, szString, AFTER) < 0)thenislib_MessageBox ("System error, failed to add entry to item list.", INFORMATION);return ISLIB_ERROR;endif;endif;// get next top-level feature.nzSubFeatureItemRetVal = ListGetNextString ( lzSubFeatureItemListID, szSubFeatureItem );endwhile;// lets free system resources//ListDestroy(lzSubFeatureItemListID);ListDestroy(lzParseFeatureListID);// get next top-level feature.nzSubFeatureRetVal = ListGetNextString ( lzSubFeatureListID, szSubFeature );endwhile;// Clear list for next cycle.//ListDestroy( lzSubFeatureListID );// get next top-level feature.nzTopFeatureRetVal = ListGetNextString ( lzTopFeatureListID, szTopFeature );endwhile;// Clear list for next cycle.//ListDestroy( lzTopFeatureListID );return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_patchSaveItems//// This function is used to create a copy of all items// that are to be updated by the patch.//// We pass the list of items to be saved and the location of the// directory to save the item in.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_savePatchItems(lzPatchItemsListID )NUMBER nzTmpVar;NUMBER nzRetVal;NUMBER nzItemCount;NUMBER nzItemRetVal;STRING szTmpVar;STRING szRetVal;STRING szMySrcFile;STRING szMyDstFile;STRING szListItem;STRING szItemName;STRING szItemLocation;STRING szPatchIDSaveDir;LIST lzParseItemListID;begin// we do not wnat to record// what we save in InstallShiell.//// we manage this stuff our-selves.//Disable(LOGGING);// we know where our save dir is// it is predefined.//szPatchIDSaveDir = PATCHID_SAVE_DIR;// lets count the number of items we have to save//nzItemCount = ListCount (lzPatchItemsListID);if ( nzItemCount = 0 )then// we have nothing to save the patch// must contain new dlls only//return ISLIB_SUCCESS;else// we have work to do.// Lets get our first item.//nzItemRetVal = ListGetFirstString ( lzPatchItemsListID, szListItem );while ( nzItemRetVal != END_OF_LIST )// lets parse the item from our list, we know// it contains item name and location delimited by a ";"//lzParseItemListID = ListCreate(STRINGLIST);StrGetTokens (lzParseItemListID, szListItem, ";");// lets load the bits so we can use the information//ListGetFirstString ( lzParseItemListID, szItemName );ListGetNextString ( lzParseItemListID, szItemLocation );// lets setup the source and destination items//szMySrcFile = szItemLocation ^ szItemName;szMyDstFile = szPatchIDSaveDir ^ szItemName;// lets save the item in our predefined// patch save dir.//nzRetVal = CopyFile (szMySrcFile, szMyDstFile );if ( nzRetVal < 0 )thenNumToStr(szRetVal, nzRetVal);islib_MessageBox("Failed to copy (save) item to be patched [" +szMySrcFile +"], retVal: [" +szRetVal +"].", SEVERE);return ISLIB_ERROR;endif;// now we need to record the fact that we saved something//if ( islib_updatePatchLog(szItemName, szItemLocation) < 0 )thenislib_MessageBox("Failed to update patch log item.", SEVERE);return ISLIB_ERROR;endif;// lets free resources for the next item//ListDestroy(lzParseItemListID);// lets get the next item.//nzItemRetVal = ListGetNextString ( lzPatchItemsListID, szListItem );endwhile;endif;// lets enable the log.//Enable(LOGGING);return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_updatePatchLog//// This function is used to create a copy of all items// that are to be updated by the patch.//// We pass the list of items to be saved and the location of the// directory to save the item in.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_updatePatchLog(szItemName, szItemLocation)STRING szPatchIDDir;STRING szPatchIDLogFileLocation;STRING szPatchIDLogFileName;STRING szLine;NUMBER nzFileHandle;begin// lets initialise where we believe the// patch log file exists//szPatchIDDir = PATCHID_DIR;szPatchIDLogFileLocation = PATCHID_LOGFILE_LOCATION;szPatchIDLogFileName = PATCHID_LOGFILE_NAME;// now we need to create the patchinfo file// that shall contain the details of what// we save abd where it goes back to.// format:// item;putBackLocation//// Set the file mode to read-write//OpenFileMode (FILE_MODE_APPEND);// lets check to see if the file// already exists.//if ( Is (EXISTS,szPatchIDLogFileLocation) = TRUE )then// Open the text file.if (OpenFile (nzFileHandle, szPatchIDDir, szPatchIDLogFileName) < 0)then// Report the error.islib_MessageBox ("System error, failed to open patch log file.", SEVERE);return ISLIB_ERROR;endif;else// Create a new file and leave it open.if (CreateFile (nzFileHandle, szPatchIDDir, szPatchIDLogFileName) < 0)then// Report the error.islib_MessageBox ("System error, failed to create patch log file.", SEVERE);return ISLIB_ERROR;endif;endif;// Set the message to write to the file.//szLine = szItemName + ";" + szItemLocation;// Write a line to the end of our file.//if (WriteLine(nzFileHandle, szLine) < 0)then// Report the error.islib_MessageBox ("System error, failed to write line to patch log.", SEVERE);return ISLIB_ERROR;endif;// Close the file.CloseFile (nzFileHandle);// we are done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_patchPostRemove//// 1. initialise predefined parameters//// 2. determine if patch can be removed.//// 3. if patch can be removed determine type of patch removal// (ie restore or no-restore)//// 4. if we are to restore,// 4.1 we need to load our patch log and put back each item.//// 5. remove patch store.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_patchPostRemove()STRING szPatchIDDir;STRING szPatchIDSaveDir;STRING szPatchIDLogFileLocation;STRING szPatchIDLogFileName;STRING szRemovalType;NUMBER nzSaveItemsCount;LIST lzPatchSavedItemsListID;begin// lets initialise info we are going to need//szPatchIDDir = PATCHID_DIR;szPatchIDSaveDir = PATCHID_SAVE_DIR;szPatchIDLogFileLocation = PATCHID_LOGFILE_LOCATION;// lets verify we can remove the package just in-case// we didn't do it in the preremove phase//// The type of removal is based on the parent package// if it still exist on the system then we need to rollback.// if the parent package for whatever reason has been removed// we can just need to clean-up.//if ( islib_checkRemovePatch(szRemovalType) < 0 )thenislib_MessageBox("This patch cannot be removed from this system yet.", SEVERE);return ISLIB_ERROR;endif;// we can remove the patch and we must restore// the save items//if ( szRemovalType = "Restore" )then// lets create save list//lzPatchSavedItemsListID = ListCreate(STRINGLIST);// If an error occurred, report it; then terminate.if (lzPatchSavedItemsListID = LIST_NULL) thenislib_MessageBox ("ERROR: Unable to create lzPatchSavedItemsListID.", SEVERE);return ISLIB_ERROR;endif;// lets get all the items we previously saved// into a manageble list//if ( islib_getPatchSaveItemsList(lzPatchSavedItemsListID) < 0 )thenislib_MessageBox("ERROR: islib_getPatchSaveItemsList() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;// lets restore the items in our list if we have some//nzSaveItemsCount = ListCount (lzPatchSavedItemsListID);if (nzSaveItemsCount > 0)then// we have work to do.//if ( islib_restorePatchItems(lzPatchSavedItemsListID) < 0 )thenislib_MessageBox("ERROR: islib_restorePatchItems() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;endif;// we have restored lets now putback// the parent pkg patch details.//if ( islib_updatePkgPatchRegistryKeys("Restore", svRestorePatchID, svRestorePatchInstalled) < 0 )thenislib_MessageBox("ERROR: islib_updatePkgPatchRegistryKeys() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;// lets free resources.//ListDestroy(lzPatchSavedItemsListID);endif;// everything is ok upto here// lets delete the evidence.//if ( islib_deletePatchIDDir() < 0 )thenislib_MessageBox("islib_deletePatchDir() did not complete successfully.", WARNING);endif;// we are done!return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_restorePatchItems//// This function restores all items in the saved list// back to the original location.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_restorePatchItems(lzPatchSavedItemsListID)STRING szPatchIDSaveDir;STRING szListItem;STRING szItemName;STRING szItemLocation;STRING szMySrcFile;STRING szMyDstFile;NUMBER nzItemCount;NUMBER nzItemRetVal;STRING szRetVal;NUMBER nzRetVal;LIST lzParseItemListID;begin// Stop recording of any// of these actions.//Disable(LOGGING);// we know where our save dir is// it is predefined.//szPatchIDSaveDir = PATCHID_SAVE_DIR;// lets count the number of items we have to restore//nzItemCount = ListCount (lzPatchSavedItemsListID);if ( nzItemCount = 0 )then// we have nothing to restore the patch//return ISLIB_SUCCESS;else// we have work to do.// Lets get our first item.//nzItemRetVal = ListGetFirstString ( lzPatchSavedItemsListID, szListItem );while ( nzItemRetVal != END_OF_LIST )// lets create a list to parse the retireved item.//lzParseItemListID = ListCreate(STRINGLIST);// If an error occurred, report it, and return error.if (lzParseItemListID = LIST_NULL) thenislib_MessageBox ("ERROR: Unable to create lzParseItemListID.", SEVERE);return ISLIB_ERROR;endif;// lets parse the item from our list, we know// it contains item name and location delimited by a ";"//StrGetTokens (lzParseItemListID, szListItem, ";");// lets load the bits so we can use the information//ListGetFirstString ( lzParseItemListID, szItemName );ListGetNextString ( lzParseItemListID, szItemLocation );// lets setup the source and destination items//szMySrcFile = szPatchIDSaveDir ^ szItemName;szMyDstFile = szItemLocation ^ szItemName;// lets restore the item from patch save dir.//nzRetVal = CopyFile (szMySrcFile, szMyDstFile );if ( nzRetVal < 0 )thenNumToStr(szRetVal, nzRetVal);islib_MessageBox("Failed to copy (restore) item [" +szMySrcFile +"], retVal: [" +szRetVal +"].", SEVERE);return ISLIB_ERROR;endif;// lets free resources for the next item//ListDestroy(lzParseItemListID);// lets get the next item.//nzItemRetVal = ListGetNextString ( lzPatchSavedItemsListID, szListItem );endwhile;endif;// lets enable the log.//Enable(LOGGING);// we are done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_getPatchSaveItemsList//// This function generates a manageable list of all// saved items.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_getPatchSaveItemsList(lzPatchSavedItemsListID)STRING szPatchIDDir;STRING szPatchIDLogFileName;STRING szPatchIDLogFileLocation;STRING szLine;NUMBER nzFileHandle;NUMBER nzRetVal;begin// initialise local variables.//szPatchIDDir = PATCHID_DIR;szPatchIDLogFileLocation = PATCHID_LOGFILE_LOCATION;szPatchIDLogFileName = PATCHID_LOGFILE_NAME;// Set the file mode to read-write//OpenFileMode (FILE_MODE_BINARY);// lets check to see if the file// already exists.//if ( Is (EXISTS,szPatchIDLogFileLocation) = TRUE )then// Open the text file.if (OpenFile (nzFileHandle, szPatchIDDir, szPatchIDLogFileName) < 0)then// Report the error.islib_MessageBox ("ERROR: Failed to open patch log file.", SEVERE);return ISLIB_ERROR;endif;// Get lines from the file into the list.//nzRetVal = islib_getline (nzFileHandle, szLine);while (nzRetVal = 0)ListAddString (lzPatchSavedItemsListID, szLine, AFTER);nzRetVal = islib_getline (nzFileHandle, szLine);endwhile;// Close the file.CloseFile (nzFileHandle);else// no save file, there is nothing to restore.//return ISLIB_SUCCESS;endif;// we are done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_deletePatchIDDir//// This function deletes the predefined// patch directory and all its contents.//// Return Values:// ISLIB_SUCCESS - completed//// we do not return an error if the directory is not removed// it may have been removed previously.////////////////////////////////////////////////////////////////////////////////function islib_deletePatchIDDir()STRING szPatchIDDir;beginszPatchIDDir = PATCHID_DIR;// lets check to see if the dir exists// before we try to remove it.//if ( Is (PATH_EXISTS, szPatchIDDir) = TRUE )thenif (DeleteDir (szPatchIDDir, ALLCONTENTS) < 0)thenislib_MessageBox ("ERROR: Unable to delete patch directory [" +szPatchIDDir + "].", SEVERE);// we still proceed...return ISLIB_SUCCESS;endif;endif;// done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_checkRemovePatch//// This function is used to check if the patch can be removed.// The rules that govern if a patch can be removed are://// 1. A parent package that has a name equal to that defined in the// project Subject field does not exists on the system.//// This condition shall be checked by ensuring the BaseInstallDir registry key// does not exist for the parent package defined in the project Subject setting.//// 2. If the a parent package exists see item 1) and the associated version number// is not equal to that that of the patch.//// The patch version number is defined in the PKG_VERSION variable.//// (i.e. The preinstalled patch MYPKG010001-0N can be removed if the parent package// MYPKG is of version 1.0.2).//// This check shall be completed by comparing the Version registry setting of the package// with the PKG_VERSION variable of the patch.//// This case implies a CLEAN install as the version number link no longer// exists.//// A patch can only be removed and thus used to restore a pre-defined specific// parent package version.//// 3. An obsoleted patch cannot be removed until the patch that obsoletes// it is removed first.//// (ie you cannot remove patch MYPKG010001-01 before patch MYPKG010001-02).//// 4. A patch can be removed and restored if it the most recently applied patch to an// existing parent package of the correct version number.////// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.//// The function also sets a variable szRemovalType to be one of// two possible values "Restore" or "Clean", this refers to the type of// removal action, assuming we can procceed.////////////////////////////////////////////////////////////////////////////////function islib_checkRemovePatch ( szRemovalType )STRING szPatchID;STRING szPkgName;STRING szPatchIDNumber;STRING szPatchVersion;STRING szPkgBaseInstallDir;STRING szPkgVersion;STRING szPkgInstalled;STRING szPkgLatestPatchID;STRING szPkgLatestPatchInstalled;STRING szPkgLatestPatchNumber;STRING szPkgBuildNum;STRING szPkgProjAcronym;STRING szPkgDesc;NUMBER nzPkgLatestPatchNumber;NUMBER nzPatchIDNumber;NUMBER nResult;begin// initialise local variables.//szRemovalType = "Restore";szPatchID = PATCH_ID;szPatchVersion= PKG_VERSION;szPkgName = PKG_NAME;// 1. lets extract my parent packages details//if ( islib_checkErgAfcPkgExists(szPkgName) < 0 )then// we could not confirm that the parent package exists// so we assume that the package was removed.//// This implies we need to simply cleanup our installation//islib_MessageBox("The patch you trying to remove [" + szPatchID + "] has no parent package." +"\n\nPatch shall not attempt to restore any previously saved items.", INFORMATION);szRemovalType = "Clean";return ISLIB_SUCCESS;else// our parent package exists lets get its current details//if (islib_getErgAfcPkgRegistryDetails( szPkgBaseInstallDir,szPkgVersion,szPkgInstalled,szPkgLatestPatchID,szPkgLatestPatchInstalled,szPkgBuildNum,szPkgProjAcronym,szPkgDesc ) < 0 )then// we encountered an error getting the details//islib_MessageBox("ERROR: islib_getErgAfcPkgRegistryDetails() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;// lets get our patch number.//if ( islib_getPatchNumber( szPatchID, szPatchIDNumber ) < 0 )thenislib_MessageBox("ERROR: islib_getPatchNumber() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;StrToNum(nzPatchIDNumber, szPatchIDNumber);// lets get the previous latest patch number.//if ( islib_getPatchNumber( szPkgLatestPatchID, szPkgLatestPatchNumber ) < 0 )thenislib_MessageBox("ERROR: islib_getPatchNumber() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;StrToNum(nzPkgLatestPatchNumber, szPkgLatestPatchNumber);// we got our details lets apply the business rules// of our patch management strategy.//// 2. we assume that our version are of the correct format// lets compare them.//// if the version differ then we can assume the version// of parent package we previously patched no longer// exists and we cannot restore anything we saved.// It is no longer relevant.//nResult = islib_compareVersions(szPkgVersion, szPatchVersion);if ( nResult != ISLIB_VERSION_EQUALS )then// we could not confirm that the parent package exists// so we assume that the package was removed.//// This implies we need to simply cleanup our installation//islib_MessageBox("The patch you trying to remove [" + szPatchID + "] has an incompatible version number" +"\nwith the current parent package." +"\n\nPatch shall not attempt to restore any previously saved items.", INFORMATION);szRemovalType = "Clean";return ISLIB_SUCCESS;endif;// our versions must equal so now we need to use the patch// number we have versus the lastest number install// for our package.//// 3. A patch cannot be removed if it is obsoleted.//// A patch is deemed obsoleted if an installed patch// has a patch number less than that of the latest patch// applied to the parent package.//if ( nzPatchIDNumber < nzPkgLatestPatchNumber )then// the patch we are trying to remove is obsolete// therefore we should not remove it until// all other patches that obsolete this patch// have sequentially been removed.//islib_MessageBox("The patch you trying to remove [" + szPatchID + "] has been obsoleted " +"by a patch that has been \npreviously installed." +"\n\nThis patch cannot be removed until all other patches that obsolete this " +"patch have been sequentially \nremoved." +"\n\nThis patch is currently obsoleted by patch [" + szPkgLatestPatchID + "], installed on [" +szPkgLatestPatchInstalled + "].", WARNING);return ISLIB_ERROR;elseif ( nzPatchIDNumber = nzPkgLatestPatchNumber )then// we are the lastest pkg patch// we can proceed with restore and removal//szRemovalType = "Restore";return ISLIB_SUCCESS;else// this is an impossible errorislib_MessageBox("ERROR: You have probably not updated your package GUIs, patches must be unique.", SEVERE);return ISLIB_ERROR;endif;endif;// if we got to here things are ok, we now need to ensure that the// INSTALLDIR variable is set to the PkgBaseInstallDir variable// we retieved from the registry. this ensures that the patch// starts from the same point as the parent package.//INSTALLDIR = szPkgBaseInstallDir;// done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_updatePkgPatchRegistryKeys//// This function is used to update the parent package// patch registry keys so we can identiffy the latest// patch that has been installed.//// It is passed 3 parameters, these include:// szUpdateType, szPatchNumber, szPatchInstalled,//// If the szUpdateType parameter == "Restore" then the// fuction uses the other two parameters to update the registry.//// If the szUpdateType != "Restore" the function uses the Patch configuration PATCH_ID and// current date/time values to upadte the registry.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_updatePkgPatchRegistryKeys( szUpdateType, szPatchID, szPatchInstalled)STRING szPkgName;STRING szTime;STRING szDate;STRING szMyPatchID;STRING szMyPatchInstalled;STRING szKey;STRING szClass;STRING szItem;STRING szValue;NUMBER nzResult;begin// we do not want to record this//Disable(LOGGING);szPkgName = PKG_NAME;// what type of action are we// performing.//if ( szUpdateType = "Restore" )then// use the passed values.szMyPatchInstalled = szPatchInstalled;szMyPatchID = szPatchID;else// this is a normal install lets// evaluate the information// lets extract the patch ID from the config//szMyPatchID = PATCH_ID;// use now as our instllation date/time//GetSystemInfo ( TIME, nzResult, szTime );GetSystemInfo ( DATE, nzResult, szDate );szMyPatchInstalled = szDate + " " + szTime;endif;// lets define the base key root locationRegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = ERGAFC_PKG_REGISTRY_BASE + szPkgName;szClass = "";// we assume here that the key must exist to// get this far. we check for it anyway.//// we do NOT create the key, if it happens// not to exist we need to report an error.//if (RegDBKeyExist (szKey) < 0)thenislib_MessageBox ("ERROR: [" + szKey + "] registry key does not exist.", SEVERE);return ISLIB_ERROR;else// lets update the LatestPatchID item.//szItem = "LatestPatchID";szValue = szMyPatchID;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error updating [" +szKey + "\\" + szItem +"] registry key, with value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;// lets update the LatestPatchInstalled item.szItem = "LatestPatchInstalled";GetSystemInfo ( TIME, nzResult, szTime );GetSystemInfo ( DATE, nzResult, szDate );szValue = szMyPatchInstalled;if (RegDBSetKeyValueEx(szKey,szItem,REGDB_STRING,szValue, -1 ) < 0)thenislib_MessageBox( "Error updating [" +szKey + "\\" + szItem +"] registry key, with value [" +szValue +"].", SEVERE );return ISLIB_ERROR;endif;endif;// lets enable the logging again.//Enable(LOGGING);return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_patchPostInstall//// 1. Set the patch registry key information//// 2. Update the product patch registry key information//// 3. Create the obsolete.txt file that shall contain the// details of the patch that we are obsoleting.////// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_patchPostInstall()begin// lets update our product registry setting.//if ( islib_setErgAfcPatchRegistryKeys() < 0 )thenislib_MessageBox("ERROR: islib_setErgAfcPatchRegistryKeys() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;// lets update the parent pkg patch registry keys//if ( islib_updatePkgPatchRegistryKeys("Install", "", "") < 0 )thenislib_MessageBox("ERROR: islib_updatePkgPatchRegistryKeys() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_patchPreRemove//// 1. Determine if we can remove the patch//// 2. Determine if we are going to restore the// previous patch//// 3. If we are to restore, determine the patch number that was// previously obsoloeted so we can restore its details.////// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_patchPreRemove()STRING szRemovalType;begin// initialse local variables.szRemovalType = "Restore";// assuming we are going to restore//if (islib_checkRemovePatch(szRemovalType) < 0 )thenislib_MessageBox("This patch cannot be removed from this system yet.", SEVERE);return ISLIB_ERROR;else// Display the AskYesNo dialog box. The default is set to Yes.if (AskYesNo("This patch can be removed. Would you like to proceed?", YES) = NO)thenislib_MessageBox("User has terminated installation.", SEVERE);abort;endif;endif;// lets get the details of the patch we are going to// restore//if ( szRemovalType = "Restore" )thenif ( islib_getPatchDetailsToRestore(svRestorePatchID,svRestorePatchInstalled) < 0 )thenislib_MessageBox("ERROR: islib_getPatchDetailsToRestore() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;endif;// done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_getPatchDetailsToRestore//// this function is used to get the patch number and installed date// recorded in the patch registry settings for the patch we// previously obsoleted.//// The items of interest are:// ObsoletedPatchInstalled, and ObsoletedPatchNumber//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error, product registry does not exist.////////////////////////////////////////////////////////////////////////////////function islib_getPatchDetailsToRestore(szRestorePatchID, szRestorePatchInstalled)STRING szPatchID;STRING szKey;STRING szClass;STRING szItem;NUMBER nzType;NUMBER nzSize;beginszPatchID = PATCH_ID;// lets define the base key root locationRegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = ERGAFC_PATCH_REGISTRY_BASE + szPatchID;szClass = "";// Check if the newly created multi-level key exists.//if (RegDBKeyExist (szKey) < 0)thenislib_MessageBox ("ERROR: [" + szKey + "] registry key does not exist.", SEVERE);return ISLIB_ERROR;else// Retrieve ObsoletedPatchID information.szItem = "ObsoletedPatchID";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szRestorePatchID, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;// Retrieve ObsoletedPatchInstalled information.szItem = "ObsoletedPatchInstalled";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szRestorePatchInstalled, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;endif;// we are done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_checkErgAfcPkgExists//// This function is used to determine if a parent package// exists. It check for the base registry key.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error, product registry does not exist.////////////////////////////////////////////////////////////////////////////////function islib_checkErgAfcPkgExists(szPkgName)STRING szKey, szClass, szItem;STRING szTmpVar;NUMBER nSize, nType;beginRegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = ERGAFC_PKG_REGISTRY_BASE + szPkgName;szClass = "";// Check if the base key exists.if (RegDBKeyExist (szKey) < 0)then/* The message box is only usefull when debugging.It becomes confusing to the operator in a production install. */// islib_MessageBox ("ERROR: Failed to access [" + szKey + "] registry key does not exist.", SEVERE);return ISLIB_ERROR;endif;/* We have found our base key. Lets check for the BaseInstallDir subkeyRetrieve BaseInstallDir information. */szItem = "BaseInstallDir";if (RegDBGetKeyValueEx (szKey, szItem, nType , szTmpVar, nSize) < 0)then// islib_MessageBox( "ERROR: Failed to access [" + szKey + "\\" + szItem + "] registry key.", SEVERE );return ISLIB_ERROR;endif;// We have confirmed the package has a registry key, and is probably installed correctly.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_preinstallCheckErgAfcPkgExists//// This function is used to display a message box// if the parent package does not exists.////////////////////////////////////////////////////////////////////////////////function islib_preinstallCheckErgAfcPkgExists(szPkgName, szPkgDesc)beginif ( islib_checkErgAfcPkgExists(szPkgName) < 0 )thenislib_MessageBox("The installer could not locate the prerequisite " + szPkgDesc + " package ("+szPkgName+"). Install will now abort.", SEVERE);abort;endif;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_preinstallCheckJavaJREExists//// This function is used to display a message box// if the JRE package does not exist.////////////////////////////////////////////////////////////////////////////////function islib_preinstallCheckJavaJREExists()beginislib_preinstallCheckJavaJREExists2("");end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_preinstallCheckJavaJREExists2//// This function is used to display a message box// if the JRE package does not exist.////////////////////////////////////////////////////////////////////////////////function islib_preinstallCheckJavaJREExists2(szJavaVer)STRING szKey;beginif ( szJavaVer = "" )thenszJavaVer = JAVA_JRE_VERSION;endif;RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = "SOFTWARE\\JavaSoft\\Java Runtime Environment\\"+szJavaVer;if (RegDBKeyExist (szKey) < 0)thenislib_MessageBox("The installer could not locate Java JRE version "+szJavaVer+". Install will now abort.", SEVERE);abort;endif;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_preinstallCheckJavaExists//// This function is used to display a message box// if the JRE package does not exist.//// islib_preinstallCheckJavaExists ( JRE|J2SDK|J2EE , VERSION , ABORT|WARN );//// Default values are JRE, 1.4 & WARN//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error, product registry does not exist.//////////////////////////////////////////////////////////////////////////////////function islib_preinstallCheckJavaExists(szJavaType, szJavaVer, szResponse)STRING szKey;STRING szRegPath;STRING szMessage;beginif ( szJavaVer = "" )thenszJavaVer = JAVA_JRE_VERSION;endif;switch (szJavaType)case "J2SDK":szRegPath = "SOFTWARE\\JavaSoft\\Java Development Kit";szMessage = "The installer could not locate Java SDK version " + szJavaVer + ".";case "J2EE":szRegPath = "SOFTWARE\\SUNW\\Java 2 SDK, Enterprise Edition";szMessage = "The installer could not locate the Java 2 Enterprise Edition SDK.";default:szJavaType = "JRE";szRegPath = "SOFTWARE\\JavaSoft\\Java Runtime Environment";szMessage = "The installer could not locate Java JRE version " + szJavaVer + ".";endswitch;if ( szResponse != "ABORT" )thenszResponse = "WARN";endif;RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = szRegPath ^ szJavaVer;if (RegDBKeyExist (szKey) < 0)thenislib_MessageBox( szMessage, SEVERE);if (szResponse = "ABORT")thenabort;endif;return ISLIB_ERROR;elsereturn ISLIB_SUCCESS;endif;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_getErgAfcPkgLatestPatchIDRegistryDetails////// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error, product registry does not exist.////////////////////////////////////////////////////////////////////////////////function islib_getErgAfcPkgLatestPatchIDRegistryDetails(szLatestPatchID, szPatchLatestInstalled)STRING szKey;STRING szClass;STRING szItem;NUMBER nzSize;NUMBER nzType;begin// lets define the base key root locationRegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = ERGAFC_PKG_REGISTRY_BASE + PKG_NAME;szClass = "";// Check if the newly created multi-level key exists.//if (RegDBKeyExist (szKey) < 0)thenislib_MessageBox ("ERROR: [" + szKey + "] registry key does not exist.", SEVERE);return ISLIB_ERROR;else// Retrieve key value information.szItem = "LatestPatchID";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szLatestPatchID, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;// Retrieve key value information.szItem = "LatestPatchInstalled";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szPatchLatestInstalled, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;endif;// we are done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_getErgAfcPkgRegistryDetails////// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error, product registry does not exist.////////////////////////////////////////////////////////////////////////////////function islib_getErgAfcPkgRegistryDetails(szPkgBaseInstallDir , szPkgVersion, szPkgInstalled,szLatestPatchID, szPatchLatestInstalled,szPkgBuildNum, szPkgProjAcronym, szPkgDesc)STRING szKey;STRING szClass;STRING szItem;NUMBER nzSize;NUMBER nzType;begin// lets define the base key root locationRegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = ERGAFC_PKG_REGISTRY_BASE + PKG_NAME;szClass = "";// Check if the newly created multi-level key exists.//if (RegDBKeyExist (szKey) < 0)thenislib_MessageBox ("ERROR: [" + szKey + "] registry key does not exist.", SEVERE);return ISLIB_ERROR;else// Retrieve key value information.szItem = "BaseInstallDir";if (RegDBGetKeyValueEx (szKey, szItem, nzType, szPkgBaseInstallDir, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;// Retrieve key value information.szItem = "PkgVersion";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szPkgVersion, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;// Retrieve key value information.szItem = "PkgInstalled";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szPkgInstalled, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;// Retrieve key value information.szItem = "LatestPatchID";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szLatestPatchID, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;// Retrieve key value information.szItem = "LatestPatchInstalled";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szPatchLatestInstalled, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;// Retrieve key value information.szItem = "PkgBuildNum";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szPkgBuildNum, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;// Retrieve key value information.szItem = "PkgProjAcronym";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szPkgProjAcronym, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;// Retrieve key value information.szItem = "PkgDesc";if (RegDBGetKeyValueEx (szKey, szItem, nzType , szPkgDesc, nzSize) < 0)thenislib_MessageBox( "Error reading [" +szKey + "\\" + szItem +"] registry key.", SEVERE );return ISLIB_ERROR;endif;endif;// we are done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_pkgPreRemove//// 1. Determine if we can remove the pkg by checking to// see if the LatestPatchID number is equal to "00".//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_pkgPreRemove()begin// assuming we are going to restore//if (islib_checkRemovePkg() < 0 )thenislib_MessageBox("This package cannot be removed from this system yet.", SEVERE);return ISLIB_ERROR;endif;// done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_checkRemovePkg//// This function is used to check if the pkg can be removed.// The rules that govern if a pkg can be removed are://// 1. It does not have any patches currently installed.// Patches should be removed prior to the package being removed.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_checkRemovePkg()STRING szPkgLatestPatchID;STRING szPkgLatestPatchInstalled;STRING szPkgLatestPatchNumber;NUMBER nzPkgLatestPatchNumber;NUMBER nResult;begin// our parent package exists lets get its current details//if (islib_getErgAfcPkgLatestPatchIDRegistryDetails( szPkgLatestPatchID,szPkgLatestPatchInstalled) < 0 )then// we encountered an error getting the details// if we are in maintenance mode anyway lets just remove the package.//if (MAINTENANCE)thenreturn ISLIB_SUCCESS;elseislib_MessageBox("ERROR: islib_getErgAfcPkgLatestPatchIDRegistryDetails() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;endif;// lets get our patch number.//if ( islib_getPatchNumber( szPkgLatestPatchID, szPkgLatestPatchNumber ) < 0 )thenislib_MessageBox("ERROR: islib_getPatchNumber() did not complete successfully.", SEVERE);return ISLIB_ERROR;endif;StrToNum(nzPkgLatestPatchNumber, szPkgLatestPatchNumber);// lets see what our latest patch is?//if ( nzPkgLatestPatchNumber != 0 )then// a patch must still be installed//islib_MessageBox("This package has an associated patch still installed." +"\n\nThe latest patch for this package is [" + szPkgLatestPatchID + "], " +"installed on [" + szPkgLatestPatchInstalled + "]." +"\n\nAll patches applied to a package must be sequentially removed prior to removing " +"the package.", WARNING);return ISLIB_ERROR;endif;// we are done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_setSystemEnvironmentVariable//// This function is used to set a System environment// variable.//// We pass:// 1. the name of the variable to be set (ie created).// 2. the value to set the new variable.//// In the event that a parameter is passed that is not supported// shall result in the user being notified and the installation// being aborted.//// Return Values://// SUCCESSFULL ENVIRONMENT CREATION: 1// ENVIRONMENT ALREADY EXISTS: 2// ERROR: -1////////////////////////////////////////////////////////////////////////////////function islib_setSystemEnvironmentVariable( szNewVar, szNewVal )STRING szKey;STRING szName;STRING szPathBuff;NUMBER nType, nSize;NUMBER nSUCCESS1, nSUCCESS2;beginnSUCCESS1 = ISLIB_SUCCESS;nSUCCESS2 = 2;// first we need to get access to the current system// path.//RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment";szName = szNewVar;// Read the system variable if it exists//if (RegDBGetKeyValueEx(szKey, szName, nType, szPathBuff, nSize) < 0)then// we did not find it so lets create it//if (RegDBSetKeyValueEx( szKey, szName, REGDB_STRING_EXPAND, szNewVal, -1 ) < 0)thenislib_MessageBox( "ERROR: Failed to create System variable registry key:\n" +"[" + szKey + "\\" + szName + "]=[" + szNewVal + "].", SEVERE );return ISLIB_ERROR;endif;else// we found the variable.//islib_MessageBox("INFO: SYSTEM environment variable previously created.\n" +"[" + szKey + "\\" + szName + "]=[" + szNewVal + "].", INFORMATION );return nSUCCESS2;endif;// done dude.return nSUCCESS1;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_forceSetSystemEnvironmentVariable//// Added by D.Greeve - 24/10/05//// This function is used to set a System environment// variable - code is based on islib_setSystemEnvironmentVariable.//// Unlike islib_setSystemEnvironmentVariable this// function will always overwrite an existing environment variable// and flag the change so that it is not uninstalled.//// We pass:// 1. the name of the variable to be set (ie created).// 2. the value to set the new variable.//// In the event that a parameter is passed that is not supported// shall result in the user being notified and the installation// being aborted.//// Return Values://// SUCCESSFULL ENVIRONMENT CREATION: 1// ENVIRONMENT ALREADY EXISTS: 2// ERROR: -1////////////////////////////////////////////////////////////////////////////////function islib_forceSetSystemEnvironmentVariable( szNewVar, szNewVal )STRING szKey;STRING szName;STRING szPathBuff;NUMBER nType, nSize;NUMBER nSUCCESS1, nSUCCESS2;beginnSUCCESS1 = ISLIB_SUCCESS;nSUCCESS2 = 2;// first we need to get access to the current system// path.//RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);szKey = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment";szName = szNewVar;// Read the system variable if it exists//if (RegDBGetKeyValueEx(szKey, szName, nType, szPathBuff, nSize) < 0)then// we did not find it so lets create it//if (RegDBSetKeyValueEx( szKey, szName, REGDB_STRING_EXPAND, szNewVal, -1 ) < 0)thenislib_MessageBox( "ERROR: Failed to create System variable registry key:\n" +"[" + szKey + "\\" + szName + "]=[" + szNewVal + "].", SEVERE );return ISLIB_ERROR;endif;else// we found the variable.//Disable(LOGGING);if (RegDBSetKeyValueEx( szKey, szName, REGDB_STRING_EXPAND, szNewVal, -1 ) < 0)thenislib_MessageBox( "ERROR: Failed to create System variable registry key:\n" +"[" + szKey + "\\" + szName + "]=[" + szNewVal + "].", SEVERE );return ISLIB_ERROR;endif;Enable(LOGGING);return nSUCCESS2;endif;// done dude.return nSUCCESS1;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_addAtItem//// This function is used to add an item to the system AT manager//// We pass:// 1. a tag to match against any possible existing items// 2. the item to be added//// Return Values://// SUCCESS: ISLIB_SUCCESS// ERROR: ISLIB_ERROR////////////////////////////////////////////////////////////////////////////////function islib_addAtItem( szTag, szItem )STRING szListItem;STRING szItemNo;NUMBER nzItemRetVal;LIST lzAtItemsListID;LIST lzParseItemListID;begin// lets remove any existing// entries that match our tag before// we add our new item//if ( islib_removeAtItem( szTag ) < 0 )thenislib_MessageBox("ERROR: returned by islib_removeAtItem().", SEVERE);return ISLIB_ERROR;endif;// if we get to here we should be able to// load our new AT item//LaunchAppAndWait ( "at", szItem, WAIT );// done dude.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_removeAtItem//// This function is used to remove an item to the system AT manager//// We pass:// 1. a tag to match against the item you wish to remove.//// Return Values://// SUCCESS: ISLIB_SUCCESS// ERROR: ISLIB_ERROR////////////////////////////////////////////////////////////////////////////////function islib_removeAtItem( szTag )STRING szListItem;STRING szItemNo;NUMBER nzItemRetVal;LIST lzAtItemsListID;LIST lzParseItemListID;STRING szMyCmd;beginszMyCmd = "at";// lets create save list.// if an error occurred, report it; then terminate.//lzAtItemsListID = ListCreate(STRINGLIST);if (lzAtItemsListID = LIST_NULL)thenislib_MessageBox ("ERROR: Unable to create lzAtItemsListID.", SEVERE);return ISLIB_ERROR;endif;// lets get a listing of what the AT mgr currently// contains.//if ( islib_getCmdOutputItemList(lzAtItemsListID, szMyCmd) < 0 )then// we could not get a listing so i will assume// there was nothing in the AT manager//islib_MessageBox ("ERROR: returned by islib_getAtItemList().", SEVERE);else// we have a list at this point.////SdShowInfoList ("Debug Display", "Current AT mgr listing...", lzAtItemsListID);// we have work to do.// Lets get our first item.//// the first two strings are not required in our// listing, they are just some frilly bit as seen below.// the good stuff usually begins at line 3.//// line1: There are no entries in the list.//// or//// line1: Status ID Day Time Command Line// line2: -------------------------------------------------------------------------------//ListGetFirstString ( lzAtItemsListID, szListItem );nzItemRetVal = ListGetNextString ( lzAtItemsListID, szListItem );if ( szListItem != "" && nzItemRetVal != END_OF_LIST )then// now lets deal with any content.//nzItemRetVal = ListGetNextString ( lzAtItemsListID, szListItem );while ( nzItemRetVal != END_OF_LIST )// lets create a list to parse the retireved item.//lzParseItemListID = ListCreate(STRINGLIST);// If an error occurred, report it, and return error.if (lzParseItemListID = LIST_NULL)thenislib_MessageBox ("ERROR: Unable to create lzParseItemListID.", SEVERE);return ISLIB_ERROR;endif;// we want to know if the item we are trying to add// already exists in the AT listing so we need to compare// our tag to the line, if we find a match we shall// proceed to delete the entry and add our new one.// This should not happen in normal practice as// when packages get removed they should remove the// AT items that belong to them.//if ( szListItem % (szTag) )then//islib_MessageBox("matched szListItem=[" + szListItem + "], szItemNo=[" + szItemNo + "].", INFORMATION);// we have found a match between my tag// and a list item (ie an AT entry).// lets parse the item, we know// it contains the item number as the first field// delimited by a whitespace or " "//StrGetTokens (lzParseItemListID, szListItem, " ");// lets load the bits so we can use the information//ListGetFirstString ( lzParseItemListID, szItemNo );// what do we do with this item.//LaunchApp("at", szItemNo + " /delete" );//islib_MessageBox ("INFO: we have deleted AT item number " + szItemNo, INFORMATION);// lets free resources for the next item//ListDestroy(lzParseItemListID);endif;// lets get the next item.//nzItemRetVal = ListGetNextString ( lzAtItemsListID, szListItem );endwhile;endif;endif;// lets free resources for the next item//ListDestroy(lzAtItemsListID);// done dude.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_updateRegistryKey//// This function is used to add a a registry key. Current version is// just an extention of the RegDBSetKeyValueEx function - with better// interaction for the user if the entry fails.//// We pass:// - The key name// - The specific key entry// - The type of key to be generated// - The value of the key we are changing/creating// - The size of the value.//// For further information check the help menus.//// Return Values://// SUCCESS: ISLIB_SUCCESS// ERROR: ISLIB_ERROR////////////////////////////////////////////////////////////////////////////////function islib_updateRegistryKey (szKey, szName, nType, szValue, nSize )beginRegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);if (RegDBSetKeyValueEx( szKey, szName, nType, szValue, nSize ) < 0)thenislib_MessageBox( "Error updating [" + szKey + "\\" + szName + "] registry key, with value [" + szValue + "].", SEVERE );return ISLIB_ERROR;endif;return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_getHostIPAddress//// This function is used to determine the host's primary// IP Address as returned by the 'ipconfig /all' system command//// We pass:// 1. a tag to match against the item you wish to remove.//// Return Values://// Set the string szIPAddress and return.//// SUCCESS: ISLIB_SUCCESS// ERROR: ISLIB_ERROR////////////////////////////////////////////////////////////////////////////////function islib_getHostIPAddress( szIPAddress )STRING szListItem;STRING szItemNo;NUMBER nzItemRetVal;LIST lzIpconfigItemsListID;LIST lzParseItemListID;STRING szMyCmd;STRING szTmpStr, szTmpIPAddress;NUMBER nzStrLength;beginszMyCmd = "ipconfig /all";// lets create save list.// if an error occurred, report it; then terminate.//lzIpconfigItemsListID = ListCreate(STRINGLIST);if (lzIpconfigItemsListID = LIST_NULL)thenislib_MessageBox ("ERROR: Unable to create lzIpconfigItemsListID.", SEVERE);return ISLIB_ERROR;endif;// lets get a listing of what the 'ipconfig /all' command//if ( islib_getCmdOutputItemList(lzIpconfigItemsListID, szMyCmd) < 0 )then// something went wrong with the command execution.//islib_MessageBox ("ERROR: returned by islib_getCmdOutputItemList().", SEVERE);else// we have a list at this point.////SdShowInfoList ("Debug Display", "Current command listing...", lzIpconfigItemsListID);// we have work to do.// we are looking for the line that contains the follwing// string "IP Address".//nzItemRetVal = ListGetFirstString ( lzIpconfigItemsListID, szListItem );if ( szListItem != "" && nzItemRetVal != END_OF_LIST )then// now lets deal with any content.//nzItemRetVal = ListGetNextString ( lzIpconfigItemsListID, szListItem );while ( nzItemRetVal != END_OF_LIST )// lets create a list to parse the retireved item.//lzParseItemListID = ListCreate(STRINGLIST);// If an error occurred, report it, and return error.if (lzParseItemListID = LIST_NULL)thenislib_MessageBox ("ERROR: Unable to create lzParseItemListID.", SEVERE);return ISLIB_ERROR;endif;// we are searching for the line with the "IP Address...if ( szListItem % ("IP Address.") )then// Debug help//islib_MessageBox("matched szListItem=[" + szListItem + "].", INFORMATION);// we have found a match between my tag// and a list item.// lets parse the item, we know something about the format.// it contains two bits delimited by a colon or ":"//StrGetTokens (lzParseItemListID, szListItem, ":");// lets load the bits so we can use the information//ListGetFirstString ( lzParseItemListID, szTmpStr );ListGetNextString ( lzParseItemListID, szTmpIPAddress );// we have our ip address but it contains a leading space//nzStrLength = StrLength(szTmpIPAddress);StrSub(szIPAddress,szTmpIPAddress,1,nzStrLength);// lets free resources for the next item//ListDestroy(lzParseItemListID);// done dude.return ISLIB_SUCCESS;endif;// lets get the next item.//nzItemRetVal = ListGetNextString ( lzIpconfigItemsListID, szListItem );endwhile;endif;endif;// lets free resources for the next item//ListDestroy(lzIpconfigItemsListID);// done dude.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_getCmdOutputItemList//// This function is used to get a listing of the current// content of the "ipconfig" system command.// It populates a string list that we pass by reference.//// We pass:// 1. a List (by ref) to populate.//// Return Values://// SUCCESS: ISLIB_SUCCESS// ERROR: ISLIB_ERROR////////////////////////////////////////////////////////////////////////////////function islib_getCmdOutputItemList (lzListID, szCmd)STRING szCmdDir;STRING szCmdOutputFileName;STRING szCmdFileName;STRING szCmdOutputFileLocation;STRING szCmdFileLocation;STRING szLine;NUMBER nzFileHandle;NUMBER nzRetVal;begin// lets initialise our variables.//szCmdDir = WINDIR^"temp\\xx_var\\";szCmdOutputFileName = "xx_cmd.txt";szCmdFileName = "xx_cmd.bat";szCmdOutputFileLocation = szCmdDir + szCmdOutputFileName;szCmdFileLocation = szCmdDir + szCmdFileName;// if the CmdDir does not already exist lets create// it for free//if (ExistsDir (szCmdDir) != EXISTS)then// lets create our cmd dir//if ( CreateDir ( szCmdDir ) < 0 )thenislib_MessageBox("Failed to create [" + szCmdDir + "] dir.", SEVERE);return ISLIB_ERROR;endif;endif;// we need to create an interim file to capture// a listing of the cmd. Trying to re-direct the output// using the LaunchApp command does not appear to work???// anyway...//OpenFileMode (FILE_MODE_APPEND);// Create a new file and leave it open.if (CreateFile (nzFileHandle, szCmdDir, szCmdFileName) < 0)then// Report the error.islib_MessageBox ("System error, failed to create file " + szCmdFileLocation, SEVERE);return ISLIB_ERROR;endif;// Write a line to the end of our file.//if (WriteLine(nzFileHandle, szCmd + " > " + szCmdOutputFileLocation) < 0)then// Report the error.islib_MessageBox ("System error, failed to write line to " + szCmdFileLocation, SEVERE);return ISLIB_ERROR;endif;// Close the file.CloseFile (nzFileHandle);// lets create the current view of the AT manager// by running our tmp bat file.//LaunchAppAndWait ( szCmdFileLocation, "", WAIT );// Set the file mode to read-only//OpenFileMode (FILE_MODE_BINARY);// lets check to see if the output file// exists.//if ( Is (EXISTS,szCmdOutputFileLocation) = TRUE )then// Open the text file.if (OpenFile (nzFileHandle, szCmdDir, szCmdOutputFileName) < 0)then// Report the error.islib_MessageBox ("System error, failed to open file [" +szCmdOutputFileLocation + "].", SEVERE);return ISLIB_ERROR;endif;// Get lines from the file into the list.//nzRetVal = islib_getline (nzFileHandle, szLine);while (nzRetVal = 0)ListAddString (lzListID, szLine, AFTER);nzRetVal = islib_getline (nzFileHandle, szLine);endwhile;// Close the file.CloseFile (nzFileHandle);else// output file does not exist...//islib_MessageBox ("System error, failed to find command output file [" +szCmdOutputFileLocation + "].", SEVERE);return ISLIB_ERROR;endif;// we are done.return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_MessageBox//// This function is an alternative to the MessageBox funtion.// It prevents errant warning messages from breaking Silent Installs.//////////////////////////////////////////////////////////////////////////////////function islib_MessageBox (szMsg, nType)begin// If we are running in silent mode or record mode we do not want// messages to pop upif ( MODE = NORMALMODE ) thenMessageBox( szMsg, nType);endif;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_CheckCSTrace//// This function checks for the existance/correctness of the DRWatson// debugger in the registry. If it finds an inconsistancy with the// default WinNT settings - it returns a failure code.//// Return Values://// SUCCESS: ISLIB_SUCCESS// ERROR: ISLIB_ERROR//////////////////////////////////////////////////////////////////////////////////function islib_CheckCSTrace ()NUMBER nResult, nType, nSize;STRING szAuto, szDebugger;STRING szAutoValue, szDebuggerValue;STRING szKey;beginszAuto = DEFAULT_DEBUGGER_AUTO;szDebugger = DEFAULT_DEBUGGER;szKey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug";RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);// Check for the basic key. The system is in a bad way if this isnt here.// We also check for the two key values and return the appropriate error codes.//if ( (RegDBGetKeyValueEx (szKey, "Auto", nType , szAutoValue, nSize) < 0) ||(RegDBGetKeyValueEx (szKey, "Debugger", nType , szDebuggerValue, nSize) < 0) )thenislib_MessageBox ("ERROR: Failed to locate [" + szKey + "] Registry key does not exist.", SEVERE);abort;else// If we get to here then both keys exist. Now to compare with the defaults.//if ( szAuto = szAutoValue) && ( szDebugger = szDebuggerValue)thenreturn ISLIB_SUCCESS;elsereturn ISLIB_ERROR;endif;endif;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_SetCSTrace//// This function sets the DRWatson debugger in the registry.// It sets the two important values to what is required by// ERG's core services system (which is coincidentally the same// as the NT4 default.//// This is an irreversible system change. Logging is disabled.//// Return Values://// SUCCESS: ISLIB_SUCCESS// ERROR: ABORT//////////////////////////////////////////////////////////////////////////////////function islib_SetCSTrace ()STRING szAuto, szDebugger;STRING szKey;beginszAuto = DEFAULT_DEBUGGER_AUTO;szDebugger = DEFAULT_DEBUGGER;szKey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug";RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);/*We wont check for the presence of the keys first. Two things are assumed.1. islib_CheckCSTrace() has been run first so you know the keys are there/need to be changed2. You are running this function because you _want_ the keys to be created/changed*/Disable (LOGGING);if ( RegDBSetKeyValueEx ( szKey, "Auto", REGDB_STRING, szAuto, -1 ) < 0 )thenMessageBox ("ERROR: Failed to set [" + szKey + " - Auto]", SEVERE);abort;endif;if ( RegDBSetKeyValueEx ( szKey, "Debugger", REGDB_STRING, szDebugger, -1 ) < 0 )thenMessageBox ("ERROR: Failed to set [" + szKey + " - Debugger]", SEVERE);abort;endif;Enable (LOGGING);return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_checkActiveStatePerl//// This function is used to check for the existence of a// specific version of PERL on the system.//// Parameters://// 1) Build Version,// the perl build version number (ie "635"),// it is recorded as a registry value string under the base key,//// HKEY_LOCAL_MACHINE\\SOFTWARE\\ActiveState\\ActivePerl\\CurrentVersion//// 2) PERL install dir,// the location of the PERL install, this is recored as a default regestry// value string entry under the base registry key,//// HKEY_LOCAL_MACHINE\\SOFTWARE\\ActiveState\\ActivePerl\\<BuildVersion>//// Return Values://// SUCCESS: ISLIB_SUCCESS// ERROR: abort////////////////////////////////////////////////////////////////////////////////function islib_checkActiveStatePerl(nzMinRequiredVersion, szInstallDir)NUMBER nzType, nzSize;STRING szCurrentVersion, szMinRequiredVersion;NUMBER nzCurrentVersion;STRING szCurrentInstallDir;STRING szCurrentInstallDir_lc;STRING szInstallDir_lc;STRING szRegKey;beginNumToStr(szMinRequiredVersion, nzMinRequiredVersion);RegDBSetDefaultRoot (HKEY_LOCAL_MACHINE);szRegKey = "\\SOFTWARE\\ActiveState\\ActivePerl";if (RegDBKeyExist (szRegKey) < 0)then// we did not find the keyislib_MessageBox("The installer could not locate the prerequisite package, ActiveState PERL [" +szMinRequiredVersion+ "]. Install will now abort.", SEVERE);abort;else// we found the key// lets see what version of perl is installedRegDBGetKeyValueEx ( szRegKey, "CurrentVersion", nzType, szCurrentVersion, nzSize );// need to convert the strings into numbers for comparisonStrToNum(nzCurrentVersion, szCurrentVersion);if( nzMinRequiredVersion > nzCurrentVersion )then// current version of perl required is not current// we assume that they are both the same version, though//islib_MessageBox("The installer has located and earlier version of ActiveState PERL "+szCurrentVersion+ "].\n" +"The recommended version of ActiveState PERL is [" +szMinRequiredVersion+ "].", WARNING);endif;// perl is installed, now lets check where...//szRegKey = "\\SOFTWARE\\ActiveState\\ActivePerl\\" + szCurrentVersion;RegDBGetKeyValueEx ( szRegKey, "", nzType, szCurrentInstallDir, nzSize );// lets make the string lower case so we can compare them//StrToLower(szCurrentInstallDir_lc, szCurrentInstallDir);StrToLower(szInstallDir_lc, szInstallDir);if ( szCurrentInstallDir_lc != szInstallDir_lc )then// default install is not where we expected it.//islib_MessageBox("The installer has detected that ActiveState PERL has been previously incorrectly installed in ["+szCurrentInstallDir_lc+"].\n" +"The required default install location is ["+szInstallDir_lc+"]. Install will now abort.", SEVERE);abort;endif;endif;end;/////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_verifyIPAddressStrFormat (STRING)//// This function is used to verify that the input parameter has// a correct format of an IP address.//// We know the string is delimeted by a "."s// We know that the string must have 4 components// We know that each components are integers// We know that each integer can have a value of 0 to 254// If any discrepancy is detected we return an error.//// Return Values:// ISLIB_SUCCESS = string has correct IP address format.// ISLIB_ERROR = string does NOT have a correct// IP address format./////////////////////////////////////////////////////////////////////////////////function islib_verifyIPAddressStrFormat(szIPAdress)LIST lzIPAddressComponents;NUMBER nCount;NUMBER nResult;STRING szItem;NUMBER nzItem;begin//islib_MessageBox("input szIPAdress=[" +szIPAdress+ "].", INFORMATION);// we need to break the input string into the 4 components// that define an IPAddress.// Create an empty number list.lzIPAddressComponents = ListCreate (STRINGLIST);// If an error occurred, report it; then terminate.if (lzIPAddressComponents = LIST_NULL)then// Report the error.islib_MessageBox ("Unable to create list.", SEVERE);return ISLIB_ERROR;endif;// Get each path from the search path into the list.if (StrGetTokens (lzIPAddressComponents, szIPAdress, "\.") > 0)then// Report the error.islib_MessageBox ("StrGetTokens failed.", SEVERE);return ISLIB_ERROR;endif;// Count the number of program folders in the list.nCount = ListCount (lzIPAddressComponents);// Report error or display the folder count.if (nCount < 0)thenislib_MessageBox ("ListCount failed.", SEVERE);return ISLIB_ERROR;elseif (nCount != 4)thenislib_MessageBox ("IP address supplied [" +szIPAdress+ "] has an incorrect format.\n" +"\nNote:\trequired IP address format: [NNN.NNN.NNN.NNN]\n" +"\twhere NNN is an integer 0 to 254.", WARNING);return ISLIB_ERROR;endif;// we have the correct number of sections// now lets check to see each segment is// a number and falls within the rewuired// range.//nResult = ListGetFirstString (lzIPAddressComponents, szItem);// Loop while not at end of list.while (nResult != END_OF_LIST)// check to see if the item is a number//if ( StrToNum(nzItem, szItem) < 0 )thenislib_MessageBox ("IP address supplied [" +szIPAdress+ "] has a NON-numeric " +"section ["+szItem+"].\n" +"\nNote:\trequired IP address format: [NNN.NNN.NNN.NNN]\n" +"\twhere NNN is an integer 0 to 254.", WARNING);return ISLIB_ERROR;endif;// we have a numeric section lets check to see if// it exists within the allowed range//if ( nzItem < 0 || nzItem > 254 )thenislib_MessageBox ("IP address supplied [" +szIPAdress+"] has a section ["+szItem+"] that is outside the allowable \nbounds of 0 to 254.\n" +"\nNote:\trequired IP address format: [NNN.NNN.NNN.NNN]\n" +"\twhere NNN is an integer 0 to 254.", WARNING);return ISLIB_ERROR;endif;// Get the next number from the list.nResult = ListGetNextString (lzIPAddressComponents, szItem);endwhile;// if we get to here things are ok.// Remove the list from memory.ListDestroy (lzIPAddressComponents);// we are done.return ISLIB_SUCCESS;end;/////////////////////////////////////////////////////////////////////////////////// Function: islib_WriteLineToEndOfFile//// Purpose: This function is used to write a line to the end of a file// and trap the error if the action does not succeed.//// Return Values:// ISLIB_ERROR : write fails// ISLIB_SUCCESS : write succeeds.///////////////////////////////////////////////////////////////////////////////////function islib_WriteLineToEndOfFile(szDir, szFile, szLine)NUMBER nzFileHandle;begin// Set the file mode to read-write//OpenFileMode (FILE_MODE_APPEND);// lets check to see if the file// already exists.//if ( Is (EXISTS,szDir + szFile) = TRUE )then// Open the text file.if (OpenFile (nzFileHandle, szDir, szFile) < 0)then// Report the error.islib_MessageBox ("System error, failed to open " + szDir + szFile + " file.", SEVERE);return ISLIB_ERROR;endif;else// Create a new file and leave it open.if (CreateFile (nzFileHandle, szDir, szFile) < 0)then// Report the error.islib_MessageBox ("System error, failed to create " + szDir + szFile + " file.", SEVERE);return ISLIB_ERROR;endif;endif;// lets update the file//if (WriteLine(nzFileHandle, szLine) < 0)then// Report the error.islib_MessageBox ("System error, failed to write line to " + szFile + "] file.", SEVERE);return ISLIB_ERROR;endif;// Close the file.CloseFile (nzFileHandle);// we are done.return ISLIB_SUCCESS;end;///////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_pkgPreInstall//// Determine if we can install the pkg by://// 1. checking to see if the PKG_VERSION definition == @PRODUCT_VERSION string.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_pkgPreInstall()begin// now we just check to see if the project version numbers entered match// if they do not we need to exit.// we canot however check the build number and project acronym easily.//if ( PKG_VERSION != @PRODUCT_VERSION )thenislib_MessageBox("The build.pl PKG_VERSION=[" +PKG_VERSION+ "] property does not match the Ishield PRODUCT_VERSION=["+@PRODUCT_VERSION+"] property.\n" +"Please review the IShield Product Properties with the local build.pl details before proceeding.", SEVERE);return ISLIB_ERROR;endif;// done.return ISLIB_SUCCESS;end;///////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_verifyProcmgrInstall//// Determine if we have successfully updated the Registry when registering// the pmsi service.//// 1. The service information exists in the CurrentControl set, under the// registry key://// HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services//// The Procmgr service is called "ERG Process Manager" if this key exists// we would be reasonably confident that the installation has// succeeded.//// Therefore we are looking for://// HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\ERG Process Manager\\Parameters////// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.////////////////////////////////////////////////////////////////////////////////function islib_verifyProcmgrInstall()NUMBER nzType, nzSize;STRING szRegKey;beginRegDBSetDefaultRoot (HKEY_LOCAL_MACHINE);szRegKey = "\\SYSTEM\\CurrentControlSet\\Services\\ERG Process Manager\\Parameters";if (RegDBKeyExist (szRegKey) < 0)then// we did not find the keyislib_MessageBox("ERROR: Failed to verify ERG Process Manager Service Installation.\n" +"The service did not install successfully!", SEVERE);return ISLIB_ERROR;endif;// we are done and all went well//return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_validateHexString(STRING)//// DESCRIPTION:// This function validates a Hexadecimal string. If the string isnt hex,// it returns an appropriate code.// This function also performs lowercase conversion.//// Return Values:// ISLIB_SUCCESS - It's a Hex string// ISLIB_ERROR - error during processing or it's not hex.//////////////////////////////////////////////////////////////////////////////////function islib_validateHexString (szString)NUMBER nSequence, nLength;STRING szElement;beginnSequence = 0;// Convert it to lowercaseif (StrToLower ( szElement, szString ) < 0)thenislib_MessageBox ("ERROR: Conversion of szString to lowercase failed.", WARNING);endif;szString = szElement;// Get the string's length in characters...//nLength = StrLengthChars (szString) - 1;// Check it character by character...//for nSequence = 0 to nLengthStrSub ( szElement, szString, nSequence, 1 );switch (szElement)case "0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","x":// This is okaydefault:// This is not.return ISLIB_ERROR;endswitch;endfor;return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_convertHexStringToIntString(STRING)//// DESCRIPTION:// This function converts a Hexadecimal string into an Integer string.//// Return Values:// ISLIB_SUCCESS - completed// ISLIB_ERROR - error during processing.//////////////////////////////////////////////////////////////////////////////////function islib_convertHexStringToIntString (szHexString)NUMBER nInteger;BOOL bResult;beginbResult = StrToIntExA ( szHexString, STIF_SUPPORT_HEX, &nInteger);// Verify conversion worked.if ( bResult = FALSE )thenreturn ISLIB_ERROR;endif;// verify conversion from Int to Str worked.if ( NumToStr ( szHexString, nInteger ) < 0 )thenreturn ISLIB_ERROR;endif;return ISLIB_SUCCESS;end;////////////////////////////////////////////////////////////////////////////////// FUNCTION: islib_getline(NUMBER, BYREF STRING)//// DESCRIPTION:// Replace the flawed GetLine() function//// This version will treat /r and /n as line endings// GetLine only works on lines that have both//// NOTE: The file MUSt be opened with OpenFileMode(FILE_MODE_BINARY)// as NORMAL mode appears to confuse line endings.////// Return Values:// 0 - Not end of file (there's more to read)// 1 - End of file is reached//////////////////////////////////////////////////////////////////////////////////function islib_getline(nzFileHandle, szLine)STRING szChar;BOOL bzMore, bzNotEof;beginbzMore = 1;bzNotEof = 1;szLine = "";//// Read data skipping /r and /n charcaters//while ( bzMore && bzNotEof )if ( ReadBytes (nzFileHandle, szChar, 0, 1) > 0)thenif ((szChar != "\n") && (szChar != "\r"))thenbzMore = 0;szLine = szLine + szChar;endif;elsebzNotEof = 0;endif;endwhile;//// Now read data up until the end of the line or end of file//bzMore = 1;while ( bzMore && bzNotEof )if ( ReadBytes (nzFileHandle, szChar, 0, 1) > 0)thenif ((szChar = "\n") || (szChar = "\r"))thenbzMore = 0;elseszLine = szLine + szChar;endif;elsebzNotEof = 0;endif;endwhile;//// Determine if we are at the end of the file// If bzMore is True then we have been looking for characters, but have not// bean able to read any. Thus we are at the end of the file.//return bzMore;end;