// // File DllHandler.pkg // Author: Wil van Antwerpen // Company: Antwise Solutions // License: LGPL // Date: March 2, 2003 // // // This class helps you to manage the loading and unloading of DLLs in the address space // of our application. // // When you include this package into your application it will first create the class // and afterwards also create an object called oDllHandler // This object is automatically initialized and will try to set the psDllLoadPath property // with the workspace programs folder from the current application. // If no workspace is known, the current windows directory is taken instead and stored in // the psDllLoadPath property // // If a windows error occurs, the exact error is retrieved with the GetLastError function // and the code from that is stored in the piWindowsLastError property. // // // Benefits of using this class are: // - Easy loading a of DLL from the current programs workspace by calling the doLoadLibrary method // // - If a DLL is not found during runtime your application will by default show a // message in the UI to the user which DLL from which path is missing and abort the program. // This is desirable for most windows applications where DLLs are missing. // Without this you get a runtime error each time the function is called and it usually // results in a neverending number of warnings. // // This behaviour can be switched off by setting the pbErrorAbort method to false. // In that case it is expected that the developer properly handles the event. // You would need this for example in WebApps where the userinterface is the clients browser // // - Unloading of a DLL from the programs address space (hardly tested, but it seems to work fine) // // // // o ToDo Extend the DoLoadLibrary method to also check on VersionInfo //========================================================================================= // 03-02-2003 **WvA First Draft // Use vWin32fh.pkg Use Set.pkg Define CS_ERRMISSINGDLLLINE1 For "There are essential components missing for the program to function properly.\n" Define CS_ERRMISSINGDLLLINE2 For "\nThe program was unable to load the module:\n " Define CS_ERRMISSINGDLLCAPTION For "Program Halted" Class cDllHandler Is A DfObject Procedure Construct_Object Forward Send Construct_Object Property String psDllLoadPath Public "" // The default library path from where Dlls will be loaded Property Integer pbErrorAbort Public True // If true and a DLL fails to load then the application is aborted when using the doLoadLibrary method Property Integer pbErrorReport Public True // If true and a DLL fails, the error is displayed to the end-user by using a stop_box Property Integer piLastWindowsError Public 0 // Holds the Windows Error from GetLastError Object oModuleHandles Is A Array End_Object // oModuleHandles Object oModuleNames Is A Set End_Object // oModuleNames Send Init // Sets the DLlLoadpath End_Procedure // Construct_Object Procedure Set ModuleHandle Integer iModule Integer hModule Set Value Of oModuleHandles Item iModule To hModule End_Procedure // Set ModuleHandle // // If sPath is "" then the programsfolder of the current workspace will be the first // path which is searched // // Returns 0 if loading the dll was succesful // Precondition: // If a path is passed in sPath, then it must always end with a "\" // You must always supply a Dllname Function DllLoadLibrary String sPath String sFile Returns Integer Integer hModule iModule Integer iFailed iErr iFound Move 0 To iFailed Move 0 To hModule Move (Uppercase(sFile)) To sFile If sPath Eq "" Begin Get psDllLoadPath to sPath Get vFolderFormat sPath to sPath End Get vFilePathExists (sPath+sFile) To iFound If (iFound <>0) Begin Get Find_Element Of (oModuleNames(Self)) sFile To iModule If iModule Ne -1 Begin Get Value Item iModule To hModule If hModule Eq 0 Begin Move (LoadLibrary(sPath+sFile+character(0))) To hModule If hModule Ne 0 Begin Set Value Of (oModuleHandles(Self)) Item iModule To hModule End Else Begin // An error occured during the actual unloading by windows // Get extended error information, call GetLastError. Move 3 To iFailed Move (GetLastError(Self)) To iErr Set piLastWindowsError To iErr End End End Else Begin Move (LoadLibrary(sPath+sFile+character(0))) To hModule If hModule Ne 0 Begin Send Add_Item hModule sFile End Else Begin // An error occured during the actual unloading by windows // Get extended error information, call GetLastError. Move 3 To iFailed Move (GetLastError(Self)) To iErr Set piLastWindowsError To iErr End End End Else Move 1 To iFailed // The file was not found Function_Return iFailed End_Function // DllLoadLibrary // Tries to load the DLL passed as sModuleName // If pbErrorAbort is set the program is aborted and a message is displayed to // the user. // Calls DllLoadLibrary to actually load the DLL // // Does not return a value Procedure doLoadLibrary String sModuleName Integer iError bAbort bReport String sMessage sPath Move 0 To iError Get DllLoadLibrary "" sModuleName To iError If (iError <> 0) Begin Get pbErrorAbort To bAbort Get pbErrorReport To bReport If (bReport) Begin Get psDllLoadPath To sPath Move CS_ERRMISSINGDLLLINE1 To sMessage Move (sMessage+CS_ERRMISSINGDLLLINE2) To sMessage Move (sMessage+sPath+sModuleName+"\n\n") To sMessage Send Stop_Box sMessage CS_ERRMISSINGDLLCAPTION End If (bAbort) Abort End End_Procedure // doLoadLibrary // Internal, do not use // // Precondition: // sFile must be UPPERCASEd // hModule must contain the windows module handle of the library that was mapped // into our address space Procedure Add_Item Integer hModule Integer sFile Integer iModule Get Item_Count Of oModuleNames To iModule Set Value Of oModuleNames Item iModule To sFile Set ModuleHandle Item iModule To hModule End_Procedure // Add_Item // Clear the DLL handler Procedure Delete_Data Integer hModuleHandles Integer hModuleNames Move (oModuleHandles(Self)) To hModuleHandles If hModuleHandles Ne 0 Begin Send Delete_Data To hModuleHandles End Move (oModuleNames(Self)) To hModuleNames If hModuleNames Ne 0 Begin Send Delete_Data To hModuleNames End Forward Send Delete_Data End_Procedure // Delete_Data // Returns the total nr of DLL files that are still loaded in memory // Succesfully unloaded DLLs do not count. // // Precondition: // Only modules loaded by the DllLoadLibrary function count Function LoadCount Returns Integer Integer iModule iCount iLoaded Integer hModule hModuleHandles Move 0 To iLoaded Move (oModuleHandles(Self)) To hModuleHandles Move (Item_Count(hModuleHandles)-1) To iCount For iModule From 0 To iCount Get Value Of hModuleHandles Item iModule To hModule If (hModule <> 0) Increment iLoaded Loop Function_Return iLoaded End_Function // LoadCount // Get the total nr of modules that have been loaded using the Function ItemCount Returns Integer Function_Return (Item_Count(oModuleNames(Self))) End_Function // ItemCount // VDF syntax compatibility Function Item_Count Returns Integer Function_Return (ItemCount(Self)) End_Function // Item_Count // Unload a Dllfile from memory // // sFile is the filename which was used to Load the library using the // DllLoadLibrary function from this class. // // Returns the following values: // (False) if unloading of the dynamic Link library was succesful // 1 if the DLL was not loaded in memory by the DllLoadLibrary function // 2 if the DLL was already unloaded // 3 An error occured during the actual unloading by windows Function DllUnloadLibrary String sFile Returns Integer Integer iFailed iErr Integer iModule Integer hModule hModuleHandles Move 0 To iFailed Move (UpperCase(sFile)) To sFile Get Find_Element Of (oModuleNames(Self)) sFile To iModule If iModule Ne -1 Begin Move (oModuleHandles(Self)) To hModuleHandles Get Value Of hModuleHandles Item iModule To hModule If hModule Ne 0 Begin // Free ee Nelson Mandela - oh yeah oh yeah... Move (FreeLibrary(hModule)) To iErr If iErr Ne 0 Begin // If the function succeeds, the return value is nonzero. Set Value Of hModuleHandles Item iModule To 0 End Else Begin // An error occured during the actual unloading by windows // Get extended error information, call GetLastError. Move 3 To iFailed Move (GetLastError(Self)) To iErr Set piLastWindowsError To iErr End End Else Move 2 To iFailed // The DLL was already unloaded End Else Move 1 To iFailed // The DLL was not loaded in memory by the DllLoadLibrary function Function_Return iFailed End_Function // DllUnloadLibrary Procedure Init String sPath #IFDEF ghoWorkSpace If ghoWorkspace Ne 0 Begin Get CurrentProgramPath Of ghoWorkspace To sPath End #ENDIF If sPath Eq "" Begin Get_Current_Directory To sPath End Move (vFolderFormat(sPath)) To sPath Set psDllLoadPath To sPath End_Procedure // Init End_Class // cDllHandler Object oDllHandler Is A cDllHandler End_Object // oDllHandler