TCF Agent: fix for older Windows versions

The SetThreadDescription() is not available on older Windows versions,
e.g. Windows Server 2016 (10.0.14393). Thus we need to check for this
function via GetProcAddress().

Change-Id: Iaa6e045c3e1e8bb8aa31e884f75e3644f33b1b24
Signed-off-by: Mircea Gherzan <mircea.gherzan@intel.com>
diff --git a/agent/system/Windows/tcf/pthreads-win32.c b/agent/system/Windows/tcf/pthreads-win32.c
index faf7997..45554c6 100644
--- a/agent/system/Windows/tcf/pthreads-win32.c
+++ b/agent/system/Windows/tcf/pthreads-win32.c
@@ -553,19 +553,40 @@
 
 int pthread_setname_np(pthread_t thread_id, const char * name) {
     int error = 0;
-#if defined(__CYGWIN__) || defined(__MINGW32__)
-#elif defined(_MSC_VER) && _MSC_VER <= 1900
-#else
-    size_t w_len = strlen(name) + 1;
-    wchar_t * w_name = (wchar_t *)loc_alloc_zero(sizeof(wchar_t) * w_len);
-    HANDLE thread = OpenThread(SYNCHRONIZE | THREAD_SET_INFORMATION, FALSE, (DWORD)(uintptr_t)thread_id);
+#if !defined(__CYGWIN__) && !defined(__MINGW32__)
+    typedef HRESULT (FAR WINAPI * ProcType)(HANDLE, wchar_t *);
+    static ProcType set_td;
+    static int init_done;
+    size_t w_len;
+    wchar_t * w_name = NULL;
+    HANDLE thread;
+
+    if (!init_done) {
+        init_done = 1;
+        HMODULE kernel_dll = LoadLibraryA("Kernel32.dll");
+        if (kernel_dll != NULL) {
+            set_td = (ProcType)GetProcAddress(kernel_dll, "SetThreadDescription");
+        }
+
+        if (set_td == NULL) {
+            /* Decrement the reference count. */
+            FreeLibrary(kernel_dll);
+        }
+    }
+
+    if (set_td == NULL)
+        return 0;
+
+    w_len = strlen(name) + 1;
+    w_name = (wchar_t *)loc_alloc_zero(sizeof(wchar_t) * w_len);
+    thread = OpenThread(SYNCHRONIZE | THREAD_SET_INFORMATION, FALSE, (DWORD)(uintptr_t)thread_id);
 
     if (thread == NULL) error = set_win32_errno(GetLastError());
     if (!error) {
         w_len = MultiByteToWideChar(CP_UTF8, 0, name, -1, w_name, w_len);
         if (w_len == 0) error = set_win32_errno(GetLastError());
     }
-    if (!error && SetThreadDescription(thread, w_name) < 0) error = set_win32_errno(GetLastError());
+    if (!error && set_td(thread, w_name) < 0) error = set_win32_errno(GetLastError());
     if (!CloseHandle(thread) && !error) error = set_win32_errno(GetLastError());
 
     loc_free(w_name);