This is Unofficial EPICS BASE Doxygen Site
osdFindSymbol.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2013 Dirk Zimoch, PSI
3 * EPICS BASE is distributed subject to a Software License Agreement found
4 * in file LICENSE that is included with this distribution.
5 \*************************************************************************/
6 /* osi/os/WIN32/osdFindSymbol.c */
7 
8 /* Avoid need to link against psapi.dll. requires windows 7 or later.
9  * MinGW doesn't provide wrappers until 6.0, so fallback to psapi.dll
10  */
11 #ifdef _MSC_VER
12 # define PSAPI_VERSION 2
13 # define epicsEnumProcessModules K32EnumProcessModules
14 #else
15 # define epicsEnumProcessModules EnumProcessModules
16 #endif
17 
18 #include <windows.h>
19 #include <psapi.h>
20 
21 #include "epicsStdio.h"
22 #include "epicsFindSymbol.h"
23 
24 #ifdef _MSC_VER
25 # define STORE static __declspec( thread )
26 #elif __GNUC__
27 # define STORE static __thread
28 #else
29 # define STORE static
30 #endif
31 
32 STORE
34 
35 LIBCOM_API void * epicsLoadLibrary(const char *name)
36 {
37  HMODULE lib;
38 
40  lib = LoadLibrary(name);
41  epicsLoadErrorCode = lib ? 0 : GetLastError();
42  return lib;
43 }
44 
45 LIBCOM_API const char *epicsLoadError(void)
46 {
47  STORE char buffer[100];
48  DWORD n;
49 
50  n = FormatMessage(
51  FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
52  NULL,
54  0,
55  buffer,
56  sizeof(buffer)-1, NULL );
57 
58  if(n) {
59  /* n - number of chars stored excluding nil.
60  *
61  * Some messages include a trailing newline, which we strip.
62  */
63  for(; n>=1 && (buffer[n-1]=='\n' || buffer[n-1]=='\r'); n--)
64  buffer[n-1] = '\0';
65  } else {
66  epicsSnprintf(buffer, sizeof(buffer),
67  "Unable to format WIN32 error code %lu",
68  (unsigned long)epicsLoadErrorCode);
69  buffer[sizeof(buffer)-1] = '\0';
70 
71  }
72 
73  return buffer;
74 }
75 
76 LIBCOM_API void * epicsStdCall epicsFindSymbol(const char *name)
77 {
78  HANDLE proc = GetCurrentProcess();
79  HMODULE *dlls=NULL;
80  DWORD nalloc=0u, needed=0u;
81  void* ret = NULL;
82 
83  /* As a handle returned by LoadLibrary() isn't available to us,
84  * try all loaded modules in arbitrary order.
85  */
86 
87  if(!epicsEnumProcessModules(proc, NULL, 0, &needed)) {
88  epicsLoadErrorCode = GetLastError();
89  return ret;
90  }
91 
92  if(!(dlls = malloc(nalloc = needed))) {
93  epicsLoadErrorCode = ERROR_NOT_ENOUGH_MEMORY;
94  return ret;
95  }
96 
97  if(epicsEnumProcessModules(proc, dlls, nalloc, &needed)) {
98  DWORD i, ndlls;
99 
100  /* settle potential races w/o retry by iterating smaller of nalloc or needed */
101  if(nalloc > needed)
102  nalloc = needed;
103 
104  for(i=0, ndlls = nalloc/sizeof(*dlls); !ret && i<ndlls; i++) {
105  ret = GetProcAddress(dlls[i], name);
106  if(!ret && GetLastError()!=ERROR_PROC_NOT_FOUND) {
107  break;
108  }
109  }
110  }
111 
112  epicsLoadErrorCode = ret ? 0 : GetLastError();
113  free(dlls);
114  return ret;
115 }
LIBCOM_API void * epicsLoadLibrary(const char *name)
Definition: osdFindSymbol.c:13
LIBCOM_API void *epicsStdCall epicsFindSymbol(const char *name)
Definition: osdFindSymbol.c:23
STORE DWORD epicsLoadErrorCode
Definition: osdFindSymbol.c:33
int i
Definition: scan.c:967
#define NULL
Definition: catime.c:38
#define STORE
Definition: osdFindSymbol.c:29
LIBCOM_API const char * epicsLoadError(void)
Definition: osdFindSymbol.c:18
#define epicsEnumProcessModules
Definition: osdFindSymbol.c:15
LIBCOM_API int epicsStdCall epicsSnprintf(char *str, size_t size, const char *format,...) EPICS_PRINTF_STYLE(3