Can compile "loader" and "layers" on Windows and Linux ...

These directories build and are partially turned-on on Windows, using the "tri"
demo (follow-on commit) and a "NULL driver" that was created out of the
sample/Intel driver.  The GetProcAddress() is not yet finding symbols in the
NULL driver.

For now:

- "C:\Windows\System32" is the default XGL driver directory.  The getenv()
  isn't yet working.  I suggest creating your own #define in order to point to
  where a driver is.

- In order to recognize a Windows driver, we must look at both its prefix and
  suffix (i.e. it is named "XGL_*.dll", e.g. "XGL_i965.dll).

- We autogenerate Windows ".def" files for the layers.  Additional info is:

  - This is necessary in order for a DLL to export symbols that can be queried
    using GetProcAddress().  We can't use the normal Windows approach of
    declaring these functions using "__declspec(dllexport)", because these
    functions are declared in "xgl.h".

  - This involves adding and running the new "xgl-win-def-file-generate.py"
    file.

  - NOTE: Layers don't have the xglInitAndEnumerateGpus() entrypoint, just the
    xglGetProcAddr() entrypoint (and now the xglEnumerateLayers() entrypoint).
    Generating them is pretty simple.

NOTE: In order to build on a 64-bit Windows 7/8 system, I did the following:

- Install VisualStudio 2013 Professional

- Install CMake from: http://www.cmake.org/cmake/resources/software.html

  - I let it add itself to the system PATH environment variable.

- Install Python 3 from: https://www.python.org/downloads

  - I let it add itself to the system PATH environment variable.

- Obtain the Git repository, checkout the "ian-150127-WinBuild" branch.

- Using a Cygwin shell: I did the following:

  - "cd" to the top-level directory (i.e. the one that contains the ".git"
    directory).

  - "mkdir _out64"

  - "cd _out64"

  - "cmake -G "Visual Studio 12 Win64" .."

- At this point, I used WindowsExplorer to open the "XGL.sln" file.  I can
  build.  CMake causes the build shortcut to be "Ctrl-Shift-B" instead of the
  normal "F7".  I had to right-click the "ALL_BUILD" project, go to
  Properties->Debugging and change the debug Command and Working Directory to
  point to "tri.exe" and where the executable are.  At this point, I can debug
  (using the normal "F5" shortcut).
diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt
index b2250ad..13a4b5b 100644
--- a/loader/CMakeLists.txt
+++ b/loader/CMakeLists.txt
@@ -13,6 +13,11 @@
 
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXGL_PROTOTYPES")
 
-add_library(XGL SHARED loader.c dispatch.c table_ops.h)
+if (WIN32)
+    add_library(XGL SHARED loader.c dirent_on_windows.c dispatch.c table_ops.h)
+endif()
+if (NOT WIN32)
+    add_library(XGL SHARED loader.c dispatch.c table_ops.h)
+endif()
 set_target_properties(XGL PROPERTIES SOVERSION 0)
 target_link_libraries(XGL -ldl -lpthread)
diff --git a/loader/dirent_on_windows.c b/loader/dirent_on_windows.c
new file mode 100644
index 0000000..3564a26
--- /dev/null
+++ b/loader/dirent_on_windows.c
@@ -0,0 +1,148 @@
+/*
+
+    Implementation of POSIX directory browsing functions and types for Win32.
+
+    Author:  Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+    History: Created March 1997. Updated June 2003 and July 2012.
+    Rights:  See end of file.
+
+*/
+
+#include <dirent_on_windows.h>
+#include <errno.h>
+#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
+
+struct DIR
+{
+    handle_type         handle; /* -1 for failed rewind */
+    struct _finddata_t  info;
+    struct dirent       result; /* d_name null iff first time */
+    char                *name;  /* null-terminated char string */
+};
+
+DIR *opendir(const char *name)
+{
+    DIR *dir = 0;
+
+    if(name && name[0])
+    {
+        size_t base_length = strlen(name);
+        const char *all = /* search pattern must end with suitable wildcard */
+            strchr("/\\", name[base_length - 1]) ? "*" : "/*";
+
+        if((dir = (DIR *) malloc(sizeof *dir)) != 0 &&
+           (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
+        {
+            strcat(strcpy(dir->name, name), all);
+
+            if((dir->handle =
+                (handle_type) _findfirst(dir->name, &dir->info)) != -1)
+            {
+                dir->result.d_name = 0;
+            }
+            else /* rollback */
+            {
+                free(dir->name);
+                free(dir);
+                dir = 0;
+            }
+        }
+        else /* rollback */
+        {
+            free(dir);
+            dir   = 0;
+            errno = ENOMEM;
+        }
+    }
+    else
+    {
+        errno = EINVAL;
+    }
+
+    return dir;
+}
+
+int closedir(DIR *dir)
+{
+    int result = -1;
+
+    if(dir)
+    {
+        if(dir->handle != -1)
+        {
+            result = _findclose(dir->handle);
+        }
+
+        free(dir->name);
+        free(dir);
+    }
+
+    if(result == -1) /* map all errors to EBADF */
+    {
+        errno = EBADF;
+    }
+
+    return result;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+    struct dirent *result = 0;
+
+    if(dir && dir->handle != -1)
+    {
+        if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
+        {
+            result         = &dir->result;
+            result->d_name = dir->info.name;
+        }
+    }
+    else
+    {
+        errno = EBADF;
+    }
+
+    return result;
+}
+
+void rewinddir(DIR *dir)
+{
+    if(dir && dir->handle != -1)
+    {
+        _findclose(dir->handle);
+        dir->handle = (handle_type) _findfirst(dir->name, &dir->info);
+        dir->result.d_name = 0;
+    }
+    else
+    {
+        errno = EBADF;
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+
+    Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved.
+
+    Permission to use, copy, modify, and distribute this software and its
+    documentation for any purpose is hereby granted without fee, provided
+    that this copyright and permissions notice appear in all copies and
+    derivatives.
+    
+    This software is supplied "as is" without express or implied warranty.
+
+    But that said, if there are any problems please get in touch.
+
+*/
diff --git a/loader/dirent_on_windows.h b/loader/dirent_on_windows.h
new file mode 100644
index 0000000..a02a0d8
--- /dev/null
+++ b/loader/dirent_on_windows.h
@@ -0,0 +1,50 @@
+#ifndef DIRENT_INCLUDED
+#define DIRENT_INCLUDED
+
+/*
+
+    Declaration of POSIX directory browsing functions and types for Win32.
+
+    Author:  Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+    History: Created March 1997. Updated June 2003.
+    Rights:  See end of file.
+    
+*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct DIR DIR;
+
+struct dirent
+{
+    char *d_name;
+};
+
+DIR           *opendir(const char *);
+int           closedir(DIR *);
+struct dirent *readdir(DIR *);
+void          rewinddir(DIR *);
+
+/*
+
+    Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+    Permission to use, copy, modify, and distribute this software and its
+    documentation for any purpose is hereby granted without fee, provided
+    that this copyright and permissions notice appear in all copies and
+    derivatives.
+    
+    This software is supplied "as is" without express or implied warranty.
+
+    But that said, if there are any problems please get in touch.
+
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/loader/loader.c b/loader/loader.c
index 0aa2940..c4cdce0 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -34,11 +34,12 @@
 #include <string.h>
 
 #include <sys/types.h>
+#if defined(WIN32)
+#include "dirent_on_windows.h"
+#else // WIN32
 #include <dirent.h>
-#include <unistd.h>
-#include <dlfcn.h>
-#include <pthread.h>
-#include <assert.h>
+#endif // WIN32
+#include "loader_platform.h"
 #include "table_ops.h"
 #include "loader.h"
 
@@ -48,7 +49,7 @@
 };
 
 struct loader_layers {
-    void *lib_handle;
+    loader_platform_dl_handle lib_handle;
     char name[256];
 };
 
@@ -79,7 +80,7 @@
 };
 
 struct loader_scanned_icds {
-    void *handle;
+    loader_platform_dl_handle handle;
     xglGetProcAddrType GetProcAddr;
     xglCreateInstanceType CreateInstance;
     xglDestroyInstanceType DestroyInstance;
@@ -105,6 +106,7 @@
     bool break_on_warning;
 } loader;
 
+
 static XGL_RESULT loader_msg_callback_add(XGL_DBG_MSG_CALLBACK_FUNCTION func,
                                           void *data)
 {
@@ -206,7 +208,7 @@
 static void
 loader_icd_destroy(struct loader_icd *icd)
 {
-    dlclose(icd->scanned_icds->handle);
+    loader_platform_close_library(icd->scanned_icds->handle);
     free(icd);
 }
 
@@ -296,20 +298,21 @@
 
 static void loader_scanned_icd_add(const char *filename)
 {
-    void *handle;
+    loader_platform_dl_handle handle;
     void *fp_gpa, *fp_enumerate, *fp_create_inst, *fp_destroy_inst;
     struct loader_scanned_icds *new_node;
 
-    handle = dlopen(filename, RTLD_LAZY);
+    // Used to call: dlopen(filename, RTLD_LAZY);
+    handle = loader_platform_open_library(filename);
     if (!handle) {
-        loader_log(XGL_DBG_MSG_WARNING, 0, dlerror());
+        loader_log(XGL_DBG_MSG_WARNING, 0, loader_platform_open_library_error(filename));
         return;
     }
 
 #define LOOKUP(func_ptr, func) do {                            \
-    func_ptr = (xgl ##func## Type) dlsym(handle, "xgl" #func); \
+    func_ptr = (xgl ##func## Type) loader_platform_get_proc_address(handle, "xgl" #func); \
     if (!func_ptr) {                                           \
-        loader_log(XGL_DBG_MSG_WARNING, 0, dlerror());         \
+        loader_log(XGL_DBG_MSG_WARNING, 0, loader_platform_get_proc_address_error("xgl" #func)); \
         return;                                                \
     }                                                          \
 } while (0)
@@ -335,12 +338,50 @@
     loader.scanned_icd_list = new_node;
 }
 
+#if defined(WIN32)
+
+#define PATH_SEPERATOR ';'
+#define DIRECTORY_SYMBOL "\\"
+#ifndef DEFAULT_XGL_DRIVERS_PATH
+// TODO: Is this a good default location?
+// Need to search for both 32bit and 64bit ICDs
+#define DEFAULT_XGL_DRIVERS_PATH "C:\\Windows\\System32"
+// TODO/TBD: Is this an appropriate prefix for Windows?
+#define XGL_DRIVER_LIBRARY_PREFIX "XGL_"
+#define XGL_DRIVER_LIBRARY_PREFIX_LEN 4
+// TODO/TBD: Is this an appropriate suffix for Windows?
+#define XGL_LAYER_LIBRARY_PREFIX "XGLLayer"
+#define XGL_LAYER_LIBRARY_PREFIX_LEN 8
+#define XGL_LIBRARY_SUFFIX ".dll"
+#define XGL_LIBRARY_SUFFIX_LEN 4
+#endif //  DEFAULT_XGL_DRIVERS_PATH
+#ifndef DEFAULT_XGL_LAYERS_PATH
+// TODO: Is this a good default location?
+#define DEFAULT_XGL_LAYERS_PATH "C:\\Windows\\System32"
+#endif //  DEFAULT_XGL_LAYERS_PATH
+
+#else // WIN32
+
+#define PATH_SEPERATOR ':'
+#define DIRECTORY_SYMBOL "/"
 #ifndef DEFAULT_XGL_DRIVERS_PATH
 // TODO: Is this a good default location?
 // Need to search for both 32bit and 64bit ICDs
 #define DEFAULT_XGL_DRIVERS_PATH "/usr/lib/i386-linux-gnu/xgl:/usr/lib/x86_64-linux-gnu/xgl"
+#define XGL_DRIVER_LIBRARY_PREFIX "libXGL_"
+#define XGL_DRIVER_LIBRARY_PREFIX_LEN 7
+#define XGL_LAYER_LIBRARY_PREFIX "libXGLLayer"
+#define XGL_LAYER_LIBRARY_PREFIX_LEN 11
+#define XGL_LIBRARY_SUFFIX ".so"
+#define XGL_LIBRARY_SUFFIX_LEN 3
+#endif //  DEFAULT_XGL_DRIVERS_PATH
+#ifndef DEFAULT_XGL_LAYERS_PATH
+// TODO: Are these good default locations?
+#define DEFAULT_XGL_LAYERS_PATH ".:/usr/lib/i386-linux-gnu/xgl:/usr/lib/x86_64-linux-gnu/xgl"
 #endif
 
+#endif // WIN32
+
 /**
  * Try to \c loader_icd_scan XGL driver(s).
  *
@@ -361,15 +402,19 @@
     int len;
 
     libPaths = NULL;
+#if !defined(WIN32)
     if (geteuid() == getuid()) {
-       /* don't allow setuid apps to use LIBXGL_DRIVERS_PATH */
+       /* Don't allow setuid apps to use LIBXGL_DRIVERS_PATH */
+#endif // WIN32
        libPaths = getenv("LIBXGL_DRIVERS_PATH");
+#if !defined(WIN32)
     }
+#endif // WIN32
     if (libPaths == NULL)
        libPaths = DEFAULT_XGL_DRIVERS_PATH;
 
     for (p = libPaths; *p; p = next) {
-       next = strchr(p, ':');
+       next = strchr(p, PATH_SEPERATOR);
        if (next == NULL) {
           len = strlen(p);
           next = p + len;
@@ -381,16 +426,28 @@
           next++;
        }
 
+       // TODO/TBD: Do we want to do this on Windows, or just let Windows take
+       // care of its own search path (which it apparently has)?
        sysdir = opendir(p);
        if (sysdir) {
           dent = readdir(sysdir);
           while (dent) {
-             /* look for ICDs starting with "libXGL_" */
-             if (!strncmp(dent->d_name, "libXGL_", 7)) {
-                snprintf(icd_library, 1024, "%s/%s",p,dent->d_name);
-
-                loader_scanned_icd_add(icd_library);
-             }
+             /* Look for ICDs starting with XGL_DRIVER_LIBRARY_PREFIX and
+              * ending with XGL_LIBRARY_SUFFIX
+              */
+              if (!strncmp(dent->d_name,
+                          XGL_DRIVER_LIBRARY_PREFIX,
+                          XGL_DRIVER_LIBRARY_PREFIX_LEN)) {
+                 int nlen = strlen(dent->d_name);
+                 const char *suf = dent->d_name + nlen - XGL_LIBRARY_SUFFIX_LEN;
+                 if ((nlen > XGL_LIBRARY_SUFFIX_LEN) &&
+                     !strncmp(suf,
+                              XGL_LIBRARY_SUFFIX,
+                              XGL_LIBRARY_SUFFIX_LEN)) {
+                    snprintf(icd_library, 1024, "%s" DIRECTORY_SYMBOL "%s", p,dent->d_name);
+                    loader_scanned_icd_add(icd_library);
+                 }
+              }
 
              dent = readdir(sysdir);
           }
@@ -398,14 +455,9 @@
        }
     }
 
-
     loader.icds_scanned = true;
 }
 
-#ifndef DEFAULT_XGL_LAYERS_PATH
-// TODO: Are these good default locations?
-#define DEFAULT_XGL_LAYERS_PATH ".:/usr/lib/i386-linux-gnu/xgl:/usr/lib/x86_64-linux-gnu/xgl"
-#endif
 
 static void layer_lib_scan_path(const char * libInPaths)
 {
@@ -423,11 +475,15 @@
         p = libInPaths;
     }
     else {
+#if !defined(WIN32)
         if (geteuid() == getuid()) {
+#endif // WIN32
             p = getenv("LIBXGL_LAYERS_PATH");
             if (p != NULL)
                 len = strlen(p);
+#if !defined(WIN32)
         }
+#endif // WIN32
     }
 
     if (len == 0) {
@@ -456,7 +512,7 @@
     loader.scanned_layer_count = 0;
 
     for (p = libPaths; *p; p = next) {
-       next = strchr(p, ':');
+       next = strchr(p, PATH_SEPERATOR);
        if (next == NULL) {
           len = strlen(p);
           next = p + len;
@@ -471,25 +527,37 @@
        if (curdir) {
           dent = readdir(curdir);
           while (dent) {
-             /* look for wrappers starting with "libXGLlayer" */
-             if (!strncmp(dent->d_name, "libXGLLayer", strlen("libXGLLayer"))) {
-                void * handle;
-                snprintf(temp_str, sizeof(temp_str), "%s/%s",p,dent->d_name);
-                if ((handle = dlopen(temp_str, RTLD_LAZY)) == NULL) {
-                    dent = readdir(curdir);
-                    continue;
-                }
-                if (loader.scanned_layer_count == MAX_LAYER_LIBRARIES) {
-                    loader_log(XGL_DBG_MSG_ERROR, 0, "%s ignored: max layer libraries exceed", temp_str);
-                    break;
-                }
-                if ((loader.scanned_layer_names[loader.scanned_layer_count] = malloc(strlen(temp_str) + 1)) == NULL) {
-                     loader_log(XGL_DBG_MSG_ERROR, 0, "%s ignored: out of memory", temp_str);
-                     break;
-                }
-                strcpy(loader.scanned_layer_names[loader.scanned_layer_count], temp_str);
-                loader.scanned_layer_count++;
-                dlclose(handle);
+             /* Look for layers starting with XGL_LAYER_LIBRARY_PREFIX and
+              * ending with XGL_LIBRARY_SUFFIX
+              */
+              if (!strncmp(dent->d_name,
+                          XGL_LAYER_LIBRARY_PREFIX,
+                          XGL_LAYER_LIBRARY_PREFIX_LEN)) {
+                 int nlen = strlen(dent->d_name);
+                 const char *suf = dent->d_name + nlen - XGL_LIBRARY_SUFFIX_LEN;
+                 if ((nlen > XGL_LIBRARY_SUFFIX_LEN) &&
+                     !strncmp(suf,
+                              XGL_LIBRARY_SUFFIX,
+                              XGL_LIBRARY_SUFFIX_LEN)) {
+                     loader_platform_dl_handle handle;
+                     snprintf(temp_str, sizeof(temp_str), "%s" DIRECTORY_SYMBOL "%s",p,dent->d_name);
+                     // Used to call: dlopen(temp_str, RTLD_LAZY)
+                     if ((handle = loader_platform_open_library(temp_str)) == NULL) {
+                         dent = readdir(curdir);
+                         continue;
+                     }
+                     if (loader.scanned_layer_count == MAX_LAYER_LIBRARIES) {
+                         loader_log(XGL_DBG_MSG_ERROR, 0, "%s ignored: max layer libraries exceed", temp_str);
+                         break;
+                     }
+                     if ((loader.scanned_layer_names[loader.scanned_layer_count] = malloc(strlen(temp_str) + 1)) == NULL) {
+                         loader_log(XGL_DBG_MSG_ERROR, 0, "%s ignored: out of memory", temp_str);
+                         break;
+                     }
+                     strcpy(loader.scanned_layer_names[loader.scanned_layer_count], temp_str);
+                     loader.scanned_layer_count++;
+                     loader_platform_close_library(handle);
+                 }
              }
 
              dent = readdir(curdir);
@@ -556,8 +624,9 @@
             obj = &(icd->layer_libs[gpu_index][i]);
             strncpy(obj->name, (char *) pLayerNames[i].layer_name, sizeof(obj->name) - 1);
             obj->name[sizeof(obj->name) - 1] = '\0';
-            if ((obj->lib_handle = dlopen(pLayerNames[i].lib_name, RTLD_LAZY | RTLD_DEEPBIND)) == NULL) {
-                loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to open layer library %s got error %d", pLayerNames[i].lib_name, dlerror());
+            // Used to call: dlopen(pLayerNames[i].lib_name, RTLD_LAZY | RTLD_DEEPBIND)
+            if ((obj->lib_handle = loader_platform_open_library(pLayerNames[i].lib_name)) == NULL) {
+                loader_log(XGL_DBG_MSG_ERROR, 0, loader_platform_open_library_error(pLayerNames[i].lib_name));
                 continue;
             } else {
                 loader_log(XGL_DBG_MSG_UNKNOWN, 0, "Inserting layer %s from library %s", pLayerNames[i].layer_name, pLayerNames[i].lib_name);
@@ -570,7 +639,7 @@
 
 static bool find_layer_name(struct loader_icd *icd, uint32_t gpu_index, const char * layer_name, const char **lib_name)
 {
-    void *handle;
+    loader_platform_dl_handle handle;
     xglEnumerateLayersType fpEnumerateLayers;
     char layer_buf[16][256];
     char * layers[16];
@@ -580,14 +649,17 @@
 
     for (unsigned int j = 0; j < loader.scanned_layer_count; j++) {
         *lib_name = loader.scanned_layer_names[j];
-        if ((handle = dlopen(*lib_name, RTLD_LAZY)) == NULL)
+        // Used to call: dlopen(*lib_name, RTLD_LAZY)
+        if ((handle = loader_platform_open_library(*lib_name)) == NULL)
             continue;
-        if ((fpEnumerateLayers = dlsym(handle, "xglEnumerateLayers")) == NULL) {
-            //use default layer name based on library name libXGLLayer<name>.so
+        if ((fpEnumerateLayers = (xglEnumerateLayersType) loader_platform_get_proc_address(handle, "xglEnumerateLayers")) == NULL) {
             char * lib_str = malloc(strlen(*lib_name) + 1 + strlen(layer_name));
-            snprintf(lib_str, strlen(*lib_name) + strlen(layer_name), "libXGLLayer%s.so", layer_name);
-            dlclose(handle);
-            if (!strcmp(basename(*lib_name), lib_str)) {
+            //use default layer name
+            snprintf(lib_str, strlen(*lib_name) + strlen(layer_name),
+                     XGL_DRIVER_LIBRARY_PREFIX "%s" XGL_LIBRARY_SUFFIX,
+                     layer_name);
+            loader_platform_close_library(handle);
+            if (!strcmp(*lib_name, lib_str)) {
                 free(lib_str);
                 return true;
             }
@@ -598,16 +670,16 @@
         }
         else {
             size_t cnt;
-            fpEnumerateLayers(NULL, 16, 256, &cnt, layers, (void *) icd->gpus + gpu_index);
+            fpEnumerateLayers(NULL, 16, 256, &cnt, layers, (char *) icd->gpus + gpu_index);
             for (unsigned int i = 0; i < cnt; i++) {
                 if (!strcmp((char *) layers[i], layer_name)) {
-                    dlclose(handle);
+                    loader_platform_close_library(handle);
                     return true;
                 }
             }
         }
 
-        dlclose(handle);
+        loader_platform_close_library(handle);
     }
 
     return false;
@@ -630,7 +702,7 @@
 
     while (p && *p && count < MAX_LAYER_LIBRARIES) {
         const char *lib_name = NULL;
-        next = strchr(p, ':');
+        next = strchr(p, PATH_SEPERATOR);
         if (next == NULL) {
             len = strlen(p);
             next = p + len;
@@ -717,7 +789,7 @@
                 for (uint32_t i = 0; i < icd->layer_count[j]; i++) {
                     libs = &(icd->layer_libs[j][i]);
                     if (libs->lib_handle)
-                        dlclose(libs->lib_handle);
+                        loader_platform_close_library(libs->lib_handle);
                     libs->lib_handle = NULL;
                 }
                 if (icd->wrappedGpus[j])
@@ -763,8 +835,8 @@
 
             char funcStr[256];
             snprintf(funcStr, 256, "%sGetProcAddr",icd->layer_libs[gpu_index][i].name);
-            if ((nextGPA = dlsym(icd->layer_libs[gpu_index][i].lib_handle, funcStr)) == NULL)
-                nextGPA = dlsym(icd->layer_libs[gpu_index][i].lib_handle, "xglGetProcAddr");
+            if ((nextGPA = (xglGetProcAddrType) loader_platform_get_proc_address(icd->layer_libs[gpu_index][i].lib_handle, funcStr)) == NULL)
+                nextGPA = (xglGetProcAddrType) loader_platform_get_proc_address(icd->layer_libs[gpu_index][i].lib_handle, "xglGetProcAddr");
             if (!nextGPA) {
                 loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to find xglGetProcAddr in layer %s", icd->layer_libs[gpu_index][i].name);
                 continue;
@@ -803,17 +875,18 @@
         const XGL_ALLOC_CALLBACKS*                  pAllocCb,
         XGL_INSTANCE*                               pInstance)
 {
-    static pthread_once_t once_icd = PTHREAD_ONCE_INIT;
-    static pthread_once_t once_layer = PTHREAD_ONCE_INIT;
+    static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_icd);
+    static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_layer);
     struct loader_instance *ptr_instance = NULL;
     struct loader_scanned_icds *scanned_icds;
     struct loader_icd *icd;
     XGL_RESULT res;
 
-    pthread_once(&once_icd, loader_icd_scan);
+    /* Scan/discover all ICD libraries in a single-threaded manner */
+    loader_platform_thread_once(&once_icd, loader_icd_scan);
 
-    /* get layer libraries */
-    pthread_once(&once_layer, layer_lib_scan);
+    /* get layer libraries in a single-threaded manner */
+    loader_platform_thread_once(&once_layer, layer_lib_scan);
 
     ptr_instance = (struct loader_instance*) malloc(sizeof(struct loader_instance));
     if (ptr_instance == NULL) {
@@ -967,8 +1040,9 @@
 
 LOADER_EXPORT void * XGLAPI xglGetProcAddr(XGL_PHYSICAL_GPU gpu, const char * pName)
 {
-    if (gpu == NULL)
+    if (gpu == NULL) {
         return NULL;
+    }
     XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;
     XGL_LAYER_DISPATCH_TABLE * disp_table = * (XGL_LAYER_DISPATCH_TABLE **) gpuw->baseObject;
     void *addr;
@@ -992,7 +1066,7 @@
     uint32_t count = 0;
     char *lib_name;
     struct loader_icd *icd = loader_get_icd((const XGL_BASE_LAYER_OBJECT *) gpu, &gpu_index);
-    void *handle;
+    loader_platform_dl_handle handle;
     xglEnumerateLayersType fpEnumerateLayers;
     char layer_buf[16][256];
     char * layers[16];
@@ -1008,16 +1082,17 @@
 
     for (unsigned int j = 0; j < loader.scanned_layer_count && count < maxLayerCount; j++) {
         lib_name = loader.scanned_layer_names[j];
-        if ((handle = dlopen(lib_name, RTLD_LAZY)) == NULL)
+        // Used to call: dlopen(*lib_name, RTLD_LAZY)
+        if ((handle = loader_platform_open_library(lib_name)) == NULL)
             continue;
-        if ((fpEnumerateLayers = dlsym(handle, "xglEnumerateLayers")) == NULL) {
-            //use default layer name based on library name libXGLLayer<name>.so
+        if ((fpEnumerateLayers = loader_platform_get_proc_address(handle, "xglEnumerateLayers")) == NULL) {
+            //use default layer name based on library name XGL_LAYER_LIBRARY_PREFIX<name>.XGL_LIBRARY_SUFFIX
             char *pEnd, *cpyStr;
             int siz;
-            dlclose(handle);
+            loader_platform_close_library(handle);
             lib_name = basename(lib_name);
             pEnd = strrchr(lib_name, '.');
-            siz = pEnd - lib_name - strlen("libXGLLayer") + 1;
+            siz = pEnd - lib_name - strlen(XGL_LAYER_LIBRARY_PREFIX) + 1;
             if (pEnd == NULL || siz <= 0)
                 continue;
             cpyStr = malloc(siz);
@@ -1025,7 +1100,7 @@
                 free(cpyStr);
                 continue;
             }
-            strncpy(cpyStr, lib_name + strlen("libXGLLayer"), siz);
+            strncpy(cpyStr, lib_name + strlen(XGL_LAYER_LIBRARY_PREFIX), siz);
             cpyStr[siz - 1] = '\0';
             if (siz > maxStringSize)
                 siz = maxStringSize;
@@ -1039,8 +1114,8 @@
             uint32_t n;
             XGL_RESULT res;
             n = (maxStringSize < 256) ? maxStringSize : 256;
-            res = fpEnumerateLayers(NULL, 16, n, &cnt, layers, (void *) icd->gpus + gpu_index);
-            dlclose(handle);
+            res = fpEnumerateLayers(NULL, 16, n, &cnt, layers, (char *) icd->gpus + gpu_index);
+            loader_platform_close_library(handle);
             if (res != XGL_SUCCESS)
                 continue;
             if (cnt + count > maxLayerCount)
diff --git a/loader/loader.h b/loader/loader.h
index 18c05b7..397c5d3 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -30,7 +30,11 @@
 
 #include <xgl.h>
 #include <xglDbg.h>
+#if defined(WIN32)
+// FIXME: NEED WINDOWS EQUIVALENT
+#else // WIN32
 #include <xglWsiX11Ext.h>
+#endif // WIN32
 #include <xglLayer.h>
 #if defined(__GNUC__) && __GNUC__ >= 4
 #  define LOADER_EXPORT __attribute__((visibility("default")))
diff --git a/loader/loader_platform.h b/loader/loader_platform.h
new file mode 100644
index 0000000..a9cd4df
--- /dev/null
+++ b/loader/loader_platform.h
@@ -0,0 +1,238 @@
+/*
+ * XGL
+ *
+ * Copyright (C) 2015 LunarG, Inc.
+ * Copyright 2014 Valve Software
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Ian Elliott <ian@lunarg.com>
+ */
+
+#ifndef LOADER_PLATFORM_H
+#define LOADER_PLATFORM_H
+
+#if defined(__linux__)
+/* Linux-specific common code: */
+
+// Headers:
+//#define _GNU_SOURCE 1
+// TBD: Are the contents of the following file used?
+#include <unistd.h>
+// Note: The following file is for dynamic loading:
+#include <dlfcn.h>
+#include <pthread.h>
+#include <assert.h>
+
+// C99:
+#define STATIC_INLINE static inline
+
+// Dynamic Loading:
+typedef void * loader_platform_dl_handle;
+static inline loader_platform_dl_handle loader_platform_open_library(const char* libPath)
+{
+    // NOTE: The prior (Linux only) loader code always used RTLD_LAZY.  In one
+    // place, it used RTLD_DEEPBIND.  It probably doesn't hurt to always use
+    // RTLD_DEEPBIND, and so that is what is being done.
+    return dlopen(libPath, RTLD_LAZY | RTLD_DEEPBIND | RTLD_LOCAL);
+}
+static inline char * loader_platform_open_library_error(const char* libPath)
+{
+    return dlerror();
+}
+static inline void loader_platform_close_library(loader_platform_dl_handle library)
+{
+    dlclose(library);
+}
+static inline void * loader_platform_get_proc_address(loader_platform_dl_handle library,
+                                                      const char *name)
+{
+    assert(library);
+    assert(name);
+    return dlsym(library, name);
+}
+static inline char * loader_platform_get_proc_address_error(const char *name)
+{
+    return dlerror();
+}
+
+// Threads:
+typedef pthread_t loader_platform_thread;
+#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
+    pthread_once_t var = PTHREAD_ONCE_INIT;
+static inline void loader_platform_thread_once(void *ctl, void (* func) (void))
+{
+    assert(func != NULL);
+    assert(ctl != NULL);
+    pthread_once((pthread_once_t *) ctl, func);
+}
+
+// Thread IDs:
+typedef pthread_t loader_platform_thread_id;
+static inline loader_platform_thread_id loader_platform_get_thread_id()
+{
+    return pthread_self();
+}
+
+// Thread mutex:
+typedef pthread_mutex_t loader_platform_thread_mutex;
+static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
+{
+    pthread_mutex_init(pMutex, NULL);
+}
+static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
+{
+    pthread_mutex_lock(pMutex);
+}
+static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
+{
+    pthread_mutex_unlock(pMutex);
+}
+static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
+{
+    pthread_mutex_destroy(pMutex);
+}
+
+
+#elif defined(_WIN32) // defined(__linux__)
+/* Windows-specific common code: */
+
+// Headers:
+#include <windows.h>
+#include <assert.h>
+#ifdef __cplusplus
+#include <iostream>
+#include <string>
+using namespace std;
+#endif // __cplusplus
+
+// C99:
+// Microsoft didn't implement C99 in Visual Studio; but started adding it with
+// VS2013.  However, VS2013 still didn't have snprintf().  The following is a
+// work-around.
+#define snprintf _snprintf
+#define STATIC_INLINE static
+// Microsoft also doesn't have basename().  Paths are different on Windows, and
+// so this is just a temporary solution in order to get us compiling, so that we
+// can test some scenarios, and develop the correct solution for Windows.
+  // TODO: Develop a better, permanent solution for Windows, to replace this
+  // temporary code:
+static char *basename(char *pathname)
+{
+    char *current, *next;
+
+#define DIRECTORY_SYMBOL '\\'
+
+// TODO/TBD: Do we need to deal with the Windows's ":" character?
+
+    for (current = pathname; *current != '\0'; current = next) {
+        next = strchr(current, DIRECTORY_SYMBOL);
+        if (next == NULL) {
+            // No more DIRECTORY_SYMBOL's so return p:
+            return current;
+        } else {
+            // Point one character past the DIRECTORY_SYMBOL:
+            next++;
+        }
+    }
+}
+
+// Dynamic Loading:
+typedef HMODULE loader_platform_dl_handle;
+static loader_platform_dl_handle loader_platform_open_library(const char* libPath)
+{
+    return LoadLibrary(libPath);
+}
+static char * loader_platform_open_library_error(const char* libPath)
+{
+    static char errorMsg[120];
+    snprintf(errorMsg, 119, "Failed to open dynamic library \"%s\"", libPath);
+    return errorMsg;
+}
+static void loader_platform_close_library(loader_platform_dl_handle library)
+{
+    FreeLibrary(library);
+}
+static void * loader_platform_get_proc_address(loader_platform_dl_handle library,
+                                               const char *name)
+{
+    assert(library);
+    assert(name);
+    return GetProcAddress(library, name);
+}
+static char * loader_platform_get_proc_address_error(const char *name)
+{
+    static char errorMsg[120];
+    snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
+    return errorMsg;
+}
+
+// Threads:
+typedef HANDLE loader_platform_thread;
+#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
+    INIT_ONCE var = INIT_ONCE_STATIC_INIT;
+static void loader_platform_thread_once(void *ctl, void (* func) (void))
+{
+    assert(func != NULL);
+    assert(ctl != NULL);
+    InitOnceExecuteOnce((PINIT_ONCE) ctl, (PINIT_ONCE_FN) func, NULL, NULL);
+}
+
+// Thread IDs:
+typedef DWORD loader_platform_thread_id;
+static loader_platform_thread_id loader_platform_get_thread_id()
+{
+    return GetCurrentThreadId();
+}
+
+// Thread mutex:
+typedef CRITICAL_SECTION loader_platform_thread_mutex;
+static void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
+{
+    InitializeCriticalSection(pMutex);
+}
+static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
+{
+    EnterCriticalSection(pMutex);
+}
+static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
+{
+    LeaveCriticalSection(pMutex);
+}
+static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
+{
+    DeleteCriticalSection(pMutex);
+}
+
+#else // defined(_WIN32)
+
+#error The "loader_platform.h" file must be modified for this OS.
+
+// NOTE: In order to support another OS, an #elif needs to be added (above the
+// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
+// contents of this file must be created.
+
+// NOTE: Other OS-specific changes are also needed for this OS.  Search for
+// files with "WIN32" in it, as a quick way to find files that must be changed.
+
+#endif // defined(_WIN32)
+
+#endif /* LOADER_PLATFORM_H */