/////////////////////////////////////////////////////////////////////////////// // loads a gls extension. #TODO: Robust name to path resolution. GLS_EXTENSION_MODULE *gls::gls_extension_load ( const char *name, unsigned long req_options, ExtensionHost *pHost ) { // validate name size_t lenName = strlen(name); if (lenName == 0 || lenName > GLS_EXTENSION_MAX_PATH_LEN) { return NULL; } // make lib path; keep enough space for path expanding { // char libPath [GLS_EXTENSION_MAX_LIB_NAME_LEN + 50]; char libPath [MAX_PATH]; #ifdef GLS_EXTENSION_LOAD_TREAT_NAME_AS_PATH strcpy (libPath, name); #else sprintf (libPath, "extensions\\%s%s.%s", EXT_MOD_NAME_PREFIX, name, EXT_MOD_EXT_NAME ); #endif // } make lib path // load the extension module #ifdef WIN32 HMODULE hExtMod = EXT_LOAD(libPath); #else void *hExtMod = NULL; #endif if (hExtMod == NULL) { return NULL; // failed to load the module } // get extension module entry points pfn_gls_extension_initialize pfn_ext_init; pfn_gls_extension_terminate pfn_ext_term; pfn_gls_extension_get_interface pfn_ext_get_int; EXT_ENTRY_POINT (hExtMod, pfn_ext_init, gls_extension_initialize); EXT_ENTRY_POINT (hExtMod, pfn_ext_term, gls_extension_terminate); EXT_ENTRY_POINT (hExtMod, pfn_ext_get_int, gls_extension_get_interface); // check for missing exports if (!pfn_ext_init || !pfn_ext_term || !pfn_ext_get_int) { EXT_UNLOAD(hExtMod); return NULL; } // try to initialize the extension if (!pfn_ext_init (pHost)) { EXT_UNLOAD(hExtMod); return NULL; // failed to initialize the extension } // get the extension interface and query extension capabilities Extension *pExtension = pfn_ext_get_int (); if (pExtension == NULL) { EXT_UNLOAD(hExtMod); return NULL; } // get extension's interface version unsigned short ext_int_ver = pExtension->GetInterfaceVersion (); unsigned char ext_int_ver_maj, ext_int_ver_min; ext_int_ver_maj = GLS_VERSION_GET_MAJOR(ext_int_ver); ext_int_ver_min = GLS_VERSION_GET_MINOR(ext_int_ver); // check for minimum interface version; extension's interface version // must be atleast equal to the required interface version unsigned char req_int_ver_maj, req_int_ver_min; req_int_ver_maj = 0; req_int_ver_min = 1; if ( (ext_int_ver_maj < req_int_ver_maj) || (ext_int_ver_maj == req_int_ver_maj && ext_int_ver_min < req_int_ver_min) ) { EXT_UNLOAD(hExtMod); // extension interface version is lower than required return NULL; } // query extension capabilities unsigned long capabilities = pExtension->GetCapabilities (); if ( (capabilities & req_options) != req_options ) { EXT_UNLOAD(hExtMod); // one or more capability not supported return NULL; } // query lib features GLS_EXTENSION_LIB_INFO libInfo; void *pLibInterface; if (req_options & GLS_EXTENSION_LIBRARY) { pExtension->GetLibInfo (&libInfo); pLibInterface = pExtension->GetLibInterface (); if (pLibInterface == NULL) { EXT_UNLOAD(hExtMod); // library interface not returned return NULL; } } // alloc a new extension module instance and return it GLS_EXTENSION_MODULE *pExtMod = new GLS_EXTENSION_MODULE (); memset (pExtMod, 0, sizeof(GLS_EXTENSION_MODULE)); strcpy ( pExtMod->path, name ); pExtMod->interfaceVersion = ext_int_ver; pExtMod->capabilities = capabilities; pExtMod->hModule = (void *)hExtMod; pExtMod->pExtInterface = pExtension; if (req_options & GLS_EXTENSION_LIBRARY) { memcpy (&pExtMod->libInfo, &libInfo, sizeof(GLS_EXTENSION_LIB_INFO)); // pExtMod->pLibInterface = reinterpret_cast<_GLScriptExtLib *> (pLibInterface); pExtMod->pLibInterface = pLibInterface; } return pExtMod; }
HRESULT STDMETHODCALLTYPE GLScript_Engine::require (BSTR bstr_path, VARIANT var_options, IDispatch **ppDispatchExtLib) { // default loading options to use for the 'require' call for loading extensions const long DEF_LOAD_OPTIONS = GLS_EXTENSION_LIBRARY; // supported loading options const long SUPPORTED_LOAD_OPTIONS = (GLS_EXTENSION_RENDERER | GLS_EXTENSION_LIBRARY); // check for invalud arguments if (bstr_path == NULL || ppDispatchExtLib == NULL) { return E_POINTER; } *ppDispatchExtLib = NULL; // parse the variant options argument for the loading options. The loading options // can be specified as a string encoded options or as a long interger bitmask. the // loading options is optional, in which case default loading options is used. long load_options; if (var_options.vt == VT_ERROR) { // use default loading options variant's internal type is VT_ERROR, which means // no value was supplied for this parameter. load_options = DEF_LOAD_OPTIONS; } else if (var_options.vt == VT_BSTR) { // parse load options from string encoded options if (!ParseExtensionLoadOptions (var_options.bstrVal, load_options)) { return E_INVALIDARG; } } else { // assume load options as a long type and fetch the value from the variant if (!gls_comvariant_get_long_value (&var_options, &load_options)) { return E_INVALIDARG; } } // check for any option that is not supported in the current environment if ( (load_options & SUPPORTED_LOAD_OPTIONS) != load_options ) { return E_INVALIDARG; } GLScriptHost_Win32 *pHost = reinterpret_cast<GLScriptHost_Win32 *>(GetParent()); // extension load options has been successfully parsed so next task is to build the // extension path to load it UINT path_length = ::SysStringLen(bstr_path); char *ascii_path_buff = new char [path_length + 1]; ::wcstombs (ascii_path_buff, bstr_path, path_length); ascii_path_buff [path_length] = '\0'; // load the extension using the extension host object Extension *pExtension = pHost->m_ext_host.LoadExtension (ascii_path_buff, load_options); delete ascii_path_buff; // check if extension failed to load if (pExtension == NULL) { // failed to load the extension. notify the host about the error. if (pHost->m_pEventListener != NULL) { tstring str_error (_T("Failed to load the extension '")); #ifdef UNICODE str_error+= bstr_path; #else str_error+= WS2MBS(bstr_path); #endif str_error+= _T("'."); pHost->RaiseHostError (str_error.c_str()); } // #TODO: return error only if strict mode is set return E_FAIL; } // hook render proc if "renderer" option is specified if (load_options & GLS_EXTENSION_RENDERER) { pHost->m_ext_host.HookRenderProc (pExtension->GetRenderProc(), pExtension); } // Return the lib interface if required if (load_options & GLS_EXTENSION_LIBRARY) { // return the IDispatch interface *ppDispatchExtLib = reinterpret_cast<IDispatch *>(pExtension->GetLibInterface()); (*ppDispatchExtLib)->AddRef (); } return NOERROR; }