static int module_create(MODULE_HOST * module_host, BROKER_HANDLE broker, GATEWAY_MODULE_LOADER_INFO * gw_loader_info, const char * remote_module_args)
{
    int result;
    if (remote_module_args == NULL)
    {
        /*Codes_SRS_NATIVEMODULEHOST_17_026: [ If any step above fails, then NativeModuleHost_Create shall free all resources allocated and return NULL. ]*/
        LogError("An error occurred getting module args for module");
        result = __LINE__;
    }
    else
    {
        /*Codes_SRS_NATIVEMODULEHOST_17_019: [ NativeModuleHost_Create shall load the module library with the pasred entrypoint. ]*/
        module_host->module_library_handle = gw_loader_info->loader->api->Load(
            gw_loader_info->loader,
            gw_loader_info->entrypoint);
        if (module_host->module_library_handle == NULL)
        {
            /*Codes_SRS_NATIVEMODULEHOST_17_026: [ If any step above fails, then NativeModuleHost_Create shall free all resources allocated and return NULL. ]*/
            result = __LINE__;
        }
        else
        {
            MODULE_LOADER_API* loader_api = gw_loader_info->loader->api;
            /*Codes_SRS_NATIVEMODULEHOST_17_020: [ NativeModuleHost_Create shall get the MODULE_API pointer from the loader. ]*/
            const MODULE_API* module_apis = loader_api->GetApi(gw_loader_info->loader, module_host->module_library_handle);
            if (module_apis == NULL)
            {
                /*Codes_SRS_NATIVEMODULEHOST_17_026: [ If any step above fails, then NativeModuleHost_Create shall free all resources allocated and return NULL. ]*/
                loader_api->Unload(gw_loader_info->loader, module_host->module_library_handle);
                result = __LINE__;
            }
            else
            {
                /*Codes_SRS_NATIVEMODULEHOST_17_021: [ NativeModuleHost_Create shall call the module's _ParseConfigurationFromJson on the "module.args" object. ]*/
                const void* module_configuration = MODULE_PARSE_CONFIGURATION_FROM_JSON(module_apis)(remote_module_args);
                /*Codes_SRS_NATIVEMODULEHOST_17_022: [ NativeModuleHost_Create shall build the module confguration from the parsed entrypoint and parsed module arguments. ]*/
                const void* transformed_module_configuration = loader_api->BuildModuleConfiguration(
                    gw_loader_info->loader,
                    gw_loader_info->entrypoint,
                    module_configuration
                );
                /*Codes_SRS_NATIVEMODULEHOST_17_023: [ NativeModuleHost_Create shall call the module's _Create on the built module configuration. ]*/
                module_host->module = MODULE_CREATE(module_apis)(broker, transformed_module_configuration);
                if (module_host->module == NULL)
                {
                    /*Codes_SRS_NATIVEMODULEHOST_17_026: [ If any step above fails, then NativeModuleHost_Create shall free all resources allocated and return NULL. ]*/
                    loader_api->Unload(gw_loader_info->loader, module_host->module_library_handle);
                    result = __LINE__;
                }
                else
                {
                    /*Codes_SRS_NATIVEMODULEHOST_17_025: [ NativeModuleHost_Create shall return a non-null pointer to a MODULE_HANDLE on success. ]*/
                    module_host->module_loader = gw_loader_info->loader;
                    module_host->module_host_broker = broker;
                        
                    result = 0;
                }
                /*Codes_SRS_NATIVEMODULEHOST_17_024: [ NativeModuleHost_Create shall free all resources used during module loading. ]*/
                MODULE_FREE_CONFIGURATION(module_apis)((void*)module_configuration);
                loader_api->FreeModuleConfiguration(gw_loader_info->loader, transformed_module_configuration);
            }
        }
    }
    return result;
}
static MODULE_LIBRARY_HANDLE NodeModuleLoader_Load(const MODULE_LOADER* loader, const void* entrypoint)
{
    NODE_MODULE_HANDLE_DATA* result;

    // loader cannot be null
    if (loader == NULL)
    {
        //Codes_SRS_NODE_MODULE_LOADER_13_001 : [NodeModuleLoader_Load shall return NULL if loader is NULL.]
        result = NULL;
        LogError("invalid inputs - loader = %p", loader);
    }
    else
    {
        if (loader->type != NODEJS)
        {
            //Codes_SRS_NODE_MODULE_LOADER_13_002 : [NodeModuleLoader_Load shall return NULL if loader->type is not NODEJS.]
            result = NULL;
            LogError("loader->type is not NODEJS");
        }
        else
        {
            result = (NODE_MODULE_HANDLE_DATA*)malloc(sizeof(NODE_MODULE_HANDLE_DATA));
            if (result == NULL)
            {
                //Codes_SRS_NODE_MODULE_LOADER_13_003 : [NodeModuleLoader_Load shall return NULL if an underlying platform call fails.]
                LogError("malloc returned NULL");
            }
            else
            {
                result->binding_module = NodeModuleLoader_LoadBindingModule(loader);
                if (result->binding_module == NULL)
                {
                    LogError("NodeModuleLoader_LoadBindingModule returned NULL");
                    //Codes_SRS_NODE_MODULE_LOADER_13_003 : [NodeModuleLoader_Load shall return NULL if an underlying platform call fails.]
                    free(result);
                    result = NULL;
                }
                else
                {
                    //Codes_SRS_NODE_MODULE_LOADER_13_033: [ NodeModuleLoader_Load shall call DynamicLibrary_FindSymbol on the binding module handle with the symbol name Module_GetApi to acquire the function that returns the module's API table. ]
                    pfModule_GetApi pfnGetAPI = (pfModule_GetApi)DynamicLibrary_FindSymbol(result->binding_module, MODULE_GETAPI_NAME);
                    if (pfnGetAPI == NULL)
                    {
                        DynamicLibrary_UnloadLibrary(result->binding_module);
                        free(result);
                        //Codes_SRS_NODE_MODULE_LOADER_13_003 : [NodeModuleLoader_Load shall return NULL if an underlying platform call fails.]
                        result = NULL;
                        LogError("DynamicLibrary_FindSymbol() returned NULL");
                    }
                    else
                    {
                        //Codes_SRS_NODE_MODULE_LOADER_13_005 : [NodeModuleLoader_Load shall return a non - NULL pointer of type MODULE_LIBRARY_HANDLE when successful.]
                        result->api = pfnGetAPI(Module_ApiGatewayVersion);

                        //Codes_SRS_NODE_MODULE_LOADER_13_034: [ NodeModuleLoader_Load shall return NULL if the MODULE_API pointer returned by the binding module is NULL. ]
                        //Codes_SRS_NODE_MODULE_LOADER_13_035: [ NodeModuleLoader_Load shall return NULL if MODULE_API::version is greater than Module_ApiGatewayVersion. ]
                        //Codes_SRS_NODE_MODULE_LOADER_13_036: [ NodeModuleLoader_Load shall return NULL if the Module_Create function in MODULE_API is NULL. ]
                        //Codes_SRS_NODE_MODULE_LOADER_13_037: [ NodeModuleLoader_Load shall return NULL if the Module_Receive function in MODULE_API is NULL. ]
                        //Codes_SRS_NODE_MODULE_LOADER_13_038: [ NodeModuleLoader_Load shall return NULL if the Module_Destroy function in MODULE_API is NULL. ]

                        /* if any of the required functions is NULL then we have a misbehaving module */
                        if (result->api == NULL ||
                            result->api->version > Module_ApiGatewayVersion ||
                            MODULE_CREATE(result->api) == NULL ||
                            MODULE_DESTROY(result->api) == NULL ||
                            MODULE_RECEIVE(result->api) == NULL)
                        {
                            LogError(
                                "pfnGetapi() returned an invalid MODULE_API instance. "
                                "result->api = %p, "
                                "result->api->version = %d, "
                                "MODULE_CREATE(result->api) = %p, "
                                "MODULE_DESTROY(result->api) = %p, "
                                "MODULE_RECEIVE(result->api) = %p, ",
                                result->api,
                                result->api != NULL ? result->api->version : 0x0,
                                result->api != NULL ? MODULE_CREATE(result->api) : NULL,
                                result->api != NULL ? MODULE_DESTROY(result->api) : NULL,
                                result->api != NULL ? MODULE_RECEIVE(result->api) : NULL
                            );

                            DynamicLibrary_UnloadLibrary(result->binding_module);
                            free(result);
                            //Codes_SRS_NODE_MODULE_LOADER_13_003 : [NodeModuleLoader_Load shall return NULL if an underlying platform call fails.]
                            result = NULL;
                        }
                    }
                }
            }
        }
    }

    return result;
}