comparison src/helper.cpp @ 38:a43d7a2867d2

Tidy up error handling, especially on Windows
author Chris Cannam
date Tue, 28 Aug 2018 14:33:41 +0100
parents 146d42909e71
children 40c6936c2fc9
comparison
equal deleted inserted replaced
37:3ccc384c0161 38:a43d7a2867d2
67 static const char programName[] = "vamp-plugin-load-checker"; 67 static const char programName[] = "vamp-plugin-load-checker";
68 68
69 #ifdef _WIN32 69 #ifdef _WIN32
70 #include <windows.h> 70 #include <windows.h>
71 #include <process.h> 71 #include <process.h>
72 #endif
73
72 #include <string> 74 #include <string>
73 #ifdef UNICODE 75 #include <iostream>
76
77 #ifdef _WIN32
78 #ifndef UNICODE
79 #error "This must be compiled with UNICODE defined"
80 #endif
74 static std::string lastLibraryName = ""; 81 static std::string lastLibraryName = "";
75 static HMODULE LoadLibraryUTF8(std::string name) { 82 static HMODULE LoadLibraryUTF8(std::string name) {
76 lastLibraryName = name; 83 lastLibraryName = name;
77 int n = name.size(); 84 int n = name.size();
78 int wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, 0, 0); 85 int wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, 0, 0);
82 HMODULE h = LoadLibraryW(wname); 89 HMODULE h = LoadLibraryW(wname);
83 delete[] wname; 90 delete[] wname;
84 return h; 91 return h;
85 } 92 }
86 static std::string GetErrorText() { 93 static std::string GetErrorText() {
94 DWORD err = GetLastError();
87 wchar_t *buffer; 95 wchar_t *buffer;
88 DWORD err = GetLastError(); 96 FormatMessageW(
89 FormatMessage(
90 FORMAT_MESSAGE_ALLOCATE_BUFFER | 97 FORMAT_MESSAGE_ALLOCATE_BUFFER |
91 FORMAT_MESSAGE_FROM_SYSTEM | 98 FORMAT_MESSAGE_FROM_SYSTEM |
92 FORMAT_MESSAGE_IGNORE_INSERTS, 99 FORMAT_MESSAGE_IGNORE_INSERTS,
93 NULL, 100 NULL,
94 err, 101 err,
95 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 102 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
96 (LPTSTR) &buffer, 103 (LPWSTR) &buffer,
97 0, NULL ); 104 0, NULL );
98 int wn = wcslen(buffer); 105 int wn = wcslen(buffer);
99 int n = WideCharToMultiByte(CP_UTF8, 0, buffer, wn, 0, 0, 0, 0); 106 int n = WideCharToMultiByte(CP_UTF8, 0, buffer, wn, 0, 0, 0, 0);
100 if (n < 0) { 107 if (n < 0) {
101 LocalFree(&buffer); 108 LocalFree(&buffer);
118 s.replace(pos, 2, lastLibraryName); 125 s.replace(pos, 2, lastLibraryName);
119 } 126 }
120 return s; 127 return s;
121 } 128 }
122 #define DLOPEN(a,b) LoadLibraryUTF8(a) 129 #define DLOPEN(a,b) LoadLibraryUTF8(a)
123 #else
124 #define DLOPEN(a,b) LoadLibrary((a).c_str())
125 #define GetErrorText() ""
126 #endif
127 #define DLSYM(a,b) (void *)GetProcAddress((HINSTANCE)(a),(b).c_str()) 130 #define DLSYM(a,b) (void *)GetProcAddress((HINSTANCE)(a),(b).c_str())
128 #define DLCLOSE(a) (!FreeLibrary((HINSTANCE)(a))) 131 #define DLCLOSE(a) (!FreeLibrary((HINSTANCE)(a)))
129 #define DLERROR() (GetErrorText()) 132 #define DLERROR() (GetErrorText())
130 #else 133 #else
131 #include <dlfcn.h> 134 #include <dlfcn.h>
133 #define DLSYM(a,b) dlsym((a),(b).c_str()) 136 #define DLSYM(a,b) dlsym((a),(b).c_str())
134 #define DLCLOSE(a) dlclose((a)) 137 #define DLCLOSE(a) dlclose((a))
135 #define DLERROR() dlerror() 138 #define DLERROR() dlerror()
136 #endif 139 #endif
137 140
138 #include <string>
139 #include <iostream>
140
141 //#include <unistd.h> 141 //#include <unistd.h>
142 142
143 using namespace std; 143 using namespace std;
144 144
145 string error() 145 string error()
154 typedef const void *(*DFn)(unsigned long); 154 typedef const void *(*DFn)(unsigned long);
155 DFn fn = DFn(f); 155 DFn fn = DFn(f);
156 unsigned long index = 0; 156 unsigned long index = 0;
157 while (fn(index)) ++index; 157 while (fn(index)) ++index;
158 if (index == 0) return "Library contains no plugins"; 158 if (index == 0) return "Library contains no plugins";
159 // else cerr << "Library contains " << index << " plugin(s)" << endl;
160 return ""; 159 return "";
161 } 160 }
162 161
163 string checkVampDescriptorFn(void *f) 162 string checkVampDescriptorFn(void *f)
164 { 163 {
165 typedef const void *(*DFn)(unsigned int, unsigned int); 164 typedef const void *(*DFn)(unsigned int, unsigned int);
166 DFn fn = DFn(f); 165 DFn fn = DFn(f);
167 unsigned int index = 0; 166 unsigned int index = 0;
168 while (fn(2, index)) ++index; 167 while (fn(2, index)) ++index;
169 if (index == 0) return "Library contains no plugins"; 168 if (index == 0) return "Library contains no plugins";
170 // else cerr << "Library contains " << index << " plugin(s)" << endl;
171 return ""; 169 return "";
172 } 170 }
173 171
174 string check(string soname, string descriptor) 172 string check(string soname, string descriptor)
175 { 173 {
176 void *handle = DLOPEN(soname, RTLD_NOW | RTLD_LOCAL); 174 void *handle = DLOPEN(soname, RTLD_NOW | RTLD_LOCAL);
177 if (!handle) { 175 if (!handle) {
178 return "Unable to open plugin library: " + error(); 176 return "Unable to open plugin library: " + error();
179 } 177 }
180 178
179 string msg = "";
180
181 void *fn = DLSYM(handle, descriptor); 181 void *fn = DLSYM(handle, descriptor);
182 if (!fn) { 182 if (!fn) {
183 return "Failed to find plugin descriptor " + descriptor + 183 msg = "Failed to find plugin descriptor " + descriptor +
184 " in library: " + error(); 184 " in library: " + error();
185 } 185 } else if (descriptor == "ladspa_descriptor") {
186 186 msg = checkLADSPAStyleDescriptorFn(fn);
187 if (descriptor == "ladspa_descriptor") {
188 return checkLADSPAStyleDescriptorFn(fn);
189 } else if (descriptor == "dssi_descriptor") { 187 } else if (descriptor == "dssi_descriptor") {
190 return checkLADSPAStyleDescriptorFn(fn); 188 msg = checkLADSPAStyleDescriptorFn(fn);
191 } else if (descriptor == "vampGetPluginDescriptor") { 189 } else if (descriptor == "vampGetPluginDescriptor") {
192 return checkVampDescriptorFn(fn); 190 msg = checkVampDescriptorFn(fn);
193 } else { 191 } else {
194 cerr << "Note: no descriptor logic known for descriptor function \"" 192 cerr << "Note: no descriptor logic known for descriptor function \""
195 << descriptor << "\"; not actually calling it" << endl; 193 << descriptor << "\"; not actually calling it" << endl;
196 } 194 }
197 195
198 return ""; 196 DLCLOSE(handle);
197
198 return msg;
199 } 199 }
200 200
201 int main(int argc, char **argv) 201 int main(int argc, char **argv)
202 { 202 {
203 bool allGood = true; 203 bool allGood = true;