]> sigrok.org Git - libserialport.git/blob - serialport.c
Handle conversion of unicode names to char * on Windows.
[libserialport.git] / serialport.c
1 /*
2  * This file is part of the libserialport project.
3  *
4  * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
5  * Copyright (C) 2010-2012 Uwe Hermann <uwe@hermann-uwe.de>
6  * Copyright (C) 2013 Martin Ling <martin-libserialport@earth.li>
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation, either version 3 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #ifdef _WIN32
30 #include <windows.h>
31 #include <tchar.h>
32 #else
33 #include <termios.h>
34 #include <sys/ioctl.h>
35 #endif
36 #ifdef __APPLE__
37 #include <IOKit/IOKitLib.h>
38 #include <IOKit/serial/IOSerialKeys.h>
39 #include <sys/syslimits.h>
40 #endif
41 #ifdef __linux__
42 #include "libudev.h"
43 #include "linux/serial.h"
44 #endif
45
46 #include "serialport.h"
47
48 static struct sp_port *sp_port_new(char *portname, size_t len)
49 {
50         struct sp_port *port;
51
52         if (!(port = malloc(sizeof(struct sp_port))))
53                 return NULL;
54
55         if (!(port->name = malloc(len)))
56         {
57                 free(port);
58                 return NULL;
59         }
60
61         memcpy(port->name, portname, len);
62
63         return port;
64 }
65
66 static struct sp_port **sp_list_append(struct sp_port **list, char *portname, size_t len)
67 {
68         void *tmp;
69         unsigned int count;
70         for (count = 0; list[count]; count++);
71         if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2))))
72                 goto fail;
73         list = tmp;
74         if (!(list[count] = sp_port_new(portname, len)))
75                 goto fail;
76         list[count + 1] = NULL;
77         return list;
78 fail:
79         sp_free_port_list(list);
80         return NULL;
81 }
82
83 /**
84  * List the serial ports available on the system.
85  *
86  * @return A null-terminated array of port name strings.
87  */
88 struct sp_port **sp_list_ports(void)
89 {
90         struct sp_port **list;
91
92         if (!(list = malloc(sizeof(struct sp_port **))))
93                 return NULL;
94
95         list[0] = NULL;
96
97 #ifdef _WIN32
98         HKEY key;
99         TCHAR *value, *data;
100         DWORD max_value_len, max_data_size, max_data_len;
101         DWORD value_len, data_size, data_len;
102         DWORD type, index = 0;
103         char *name;
104         int name_len;
105
106         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
107                         0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS)
108                 return NULL;
109         if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
110                                 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS)
111                 goto out_close;
112         max_data_len = max_data_size / sizeof(TCHAR);
113         if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR))))
114                 goto out_close;
115         if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR))))
116                 goto out_free_value;
117         while (
118                 value_len = max_value_len,
119                 data_size = max_data_size,
120                 RegEnumValue(key, index, value, &value_len,
121                         NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
122         {
123                 data_len = data_size / sizeof(TCHAR);
124                 data[data_len] = '\0';
125 #ifdef UNICODE
126                 name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL)
127 #else
128                 name_len = data_len + 1;
129 #endif
130                 if (!(name = malloc(name_len)))
131                         goto out;
132 #ifdef UNICODE
133                 WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL);
134 #else
135                 strcpy(name, data);
136 #endif
137                 if (type == REG_SZ)
138                         if (!(list = sp_list_append(list, name, name_len)))
139                                 goto out;
140                 index++;
141         }
142 out:
143         free(data);
144 out_free_value:
145         free(value);
146 out_close:
147         RegCloseKey(key);
148         return list;
149 #endif
150 #ifdef __APPLE__
151         mach_port_t master;
152         CFMutableDictionaryRef classes;
153         io_iterator_t iter;
154         char *path;
155         io_object_t port;
156         CFTypeRef cf_path;
157         Boolean result;
158
159         if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS)
160                 return NULL;
161
162         if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue)))
163                 return NULL;
164
165         CFDictionarySetValue(classes,
166                         CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
167
168         if (!(IOServiceGetMatchingServices(master, classes, &iter)))
169                 return NULL;
170
171         if (!(path = malloc(PATH_MAX)))
172                 goto out_release;
173
174         while ((port = IOIteratorNext(iter))) {
175                 cf_path = IORegistryEntryCreateCFProperty(port,
176                                 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
177                 if (cf_path) {
178                         result = CFStringGetCString(cf_path,
179                                         path, PATH_MAX, kCFStringEncodingASCII);
180                         CFRelease(cf_path);
181                         if (result)
182                                 if (!(list = sp_list_append(list, path, strlen(path) + 1)))
183                                 {
184                                         IOObjectRelease(port);
185                                         goto out;
186                                 }
187                 }
188                 IOObjectRelease(port);
189         }
190
191 out:
192         free(path);
193 out_release:
194         IOObjectRelease(iter);
195         return list;
196 #endif
197 #ifdef __linux__
198         struct udev *ud;
199         struct udev_enumerate *ud_enumerate;
200         struct udev_list_entry *ud_list;
201         struct udev_list_entry *ud_entry;
202         const char *path;
203         struct udev_device *ud_dev, *ud_parent;
204         const char *name;
205         const char *driver;
206         int fd, ioctl_result;
207         struct serial_struct serial_info;
208
209         ud = udev_new();
210         ud_enumerate = udev_enumerate_new(ud);
211         udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
212         udev_enumerate_scan_devices(ud_enumerate);
213         ud_list = udev_enumerate_get_list_entry(ud_enumerate);
214         udev_list_entry_foreach(ud_entry, ud_list)
215         {
216                 path = udev_list_entry_get_name(ud_entry);
217                 ud_dev = udev_device_new_from_syspath(ud, path);
218                 /* If there is no parent device, this is a virtual tty. */
219                 ud_parent = udev_device_get_parent(ud_dev);
220                 if (ud_parent == NULL)
221                 {
222                         udev_device_unref(ud_dev);
223                         continue;
224                 }
225                 name = udev_device_get_devnode(ud_dev);
226                 /* The serial8250 driver has a hardcoded number of ports.
227                  * The only way to tell which actually exist on a given system
228                  * is to try to open them and make an ioctl call. */
229                 driver = udev_device_get_driver(ud_parent);
230                 if (driver && !strcmp(driver, "serial8250"))
231                 {
232                         if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0)
233                                 goto skip;
234                         ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
235                         close(fd);
236                         if (ioctl_result != 0)
237                                 goto skip;
238                         if (serial_info.type == PORT_UNKNOWN)
239                                 goto skip;
240                 }
241                 list = sp_list_append(list, (void *)name, strlen(name) + 1);
242 skip:
243                 udev_device_unref(ud_dev);
244                 if (!list)
245                         goto out;
246         }
247 out:
248         udev_enumerate_unref(ud_enumerate);
249         udev_unref(ud);
250         return list;
251 #endif
252 }
253
254 /**
255  * Free a port list returned by sp_list_ports.
256  */
257 void sp_free_port_list(struct sp_port **list)
258 {
259         unsigned int i;
260         for (i = 0; list[i]; i++)
261                 free(list[i]);
262         free(list);
263 }
264
265 static int sp_validate_port(struct sp_port *port)
266 {
267         if (port == NULL)
268                 return 0;
269 #ifdef _WIN32
270         if (port->hdl == INVALID_HANDLE_VALUE)
271                 return 0;
272 #else
273         if (port->fd < 0)
274                 return 0;
275 #endif
276         return 1;
277 }
278
279 #define CHECK_PORT() do { if (!sp_validate_port(port)) return SP_ERR_ARG; } while (0)
280
281 /**
282  * Open the specified serial port.
283  *
284  * @param port Pointer to empty port structure allocated by caller.
285  * @param portname Name of port to open.
286  * @param flags Flags to use when opening the serial port. Possible flags
287  *              are: SP_MODE_RDWR, SP_MODE_RDONLY, SP_MODE_NONBLOCK.
288  *
289  * @return SP_OK on success, SP_ERR_FAIL on failure,
290  *         or SP_ERR_ARG if an invalid port or name is passed.
291  */
292 int sp_open(struct sp_port *port, int flags)
293 {
294         if (!port)
295                 return SP_ERR_ARG;
296
297 #ifdef _WIN32
298         DWORD desired_access = 0, flags_and_attributes = 0;
299         /* Map 'flags' to the OS-specific settings. */
300         desired_access |= GENERIC_READ;
301         flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
302         if (flags & SP_MODE_RDWR)
303                 desired_access |= GENERIC_WRITE;
304         if (flags & SP_MODE_NONBLOCK)
305                 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
306
307         port->hdl = CreateFile(port->name, desired_access, 0, 0,
308                          OPEN_EXISTING, flags_and_attributes, 0);
309         if (port->hdl == INVALID_HANDLE_VALUE)
310                 return SP_ERR_FAIL;
311 #else
312         int flags_local = 0;
313         /* Map 'flags' to the OS-specific settings. */
314         if (flags & SP_MODE_RDWR)
315                 flags_local |= O_RDWR;
316         if (flags & SP_MODE_RDONLY)
317                 flags_local |= O_RDONLY;
318         if (flags & SP_MODE_NONBLOCK)
319                 flags_local |= O_NONBLOCK;
320
321         if ((port->fd = open(port->name, flags_local)) < 0)
322                 return SP_ERR_FAIL;
323 #endif
324
325         return SP_OK;
326 }
327
328 /**
329  * Close the specified serial port.
330  *
331  * @param port Pointer to port structure.
332  *
333  * @return SP_OK on success, SP_ERR_FAIL on failure,
334  *         or SP_ERR_ARG if an invalid port is passed.
335  */
336 int sp_close(struct sp_port *port)
337 {
338         CHECK_PORT();
339
340 #ifdef _WIN32
341         /* Returns non-zero upon success, 0 upon failure. */
342         if (CloseHandle(port->hdl) == 0)
343                 return SP_ERR_FAIL;
344 #else
345         /* Returns 0 upon success, -1 upon failure. */
346         if (close(port->fd) == -1)
347                 return SP_ERR_FAIL;
348 #endif
349
350         return SP_OK;
351 }
352
353 /**
354  * Flush serial port buffers.
355  *
356  * @param port Pointer to port structure.
357  *
358  * @return SP_OK on success, SP_ERR_FAIL on failure,
359  *         or SP_ERR_ARG if an invalid port is passed.
360  */
361 int sp_flush(struct sp_port *port)
362 {
363         CHECK_PORT();
364
365 #ifdef _WIN32
366         /* Returns non-zero upon success, 0 upon failure. */
367         if (PurgeComm(port->hdl, PURGE_RXCLEAR | PURGE_TXCLEAR) == 0)
368                 return SP_ERR_FAIL;
369 #else
370         /* Returns 0 upon success, -1 upon failure. */
371         if (tcflush(port->fd, TCIOFLUSH) < 0)
372                 return SP_ERR_FAIL;
373 #endif
374         return SP_OK;
375 }
376
377 /**
378  * Write a number of bytes to the specified serial port.
379  *
380  * @param port Pointer to port structure.
381  * @param buf Buffer containing the bytes to write.
382  * @param count Number of bytes to write.
383  *
384  * @return The number of bytes written, SP_ERR_FAIL on failure,
385  *         or SP_ERR_ARG if an invalid port is passed.
386  */
387 int sp_write(struct sp_port *port, const void *buf, size_t count)
388 {
389         CHECK_PORT();
390
391         if (!buf)
392                 return SP_ERR_ARG;
393
394 #ifdef _WIN32
395         DWORD written = 0;
396         /* Returns non-zero upon success, 0 upon failure. */
397         if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
398                 return SP_ERR_FAIL;
399         return written;
400 #else
401         /* Returns the number of bytes written, or -1 upon failure. */
402         ssize_t written = write(port->fd, buf, count);
403         if (written < 0)
404                 return SP_ERR_FAIL;
405         else
406                 return written;;
407 #endif
408 }
409
410 /**
411  * Read a number of bytes from the specified serial port.
412  *
413  * @param port Pointer to port structure.
414  * @param buf Buffer where to store the bytes that are read.
415  * @param count The number of bytes to read.
416  *
417  * @return The number of bytes read, SP_ERR_FAIL on failure,
418  *         or SP_ERR_ARG if an invalid port is passed.
419  */
420 int sp_read(struct sp_port *port, void *buf, size_t count)
421 {
422         CHECK_PORT();
423
424         if (!buf)
425                 return SP_ERR_ARG;
426
427 #ifdef _WIN32
428         DWORD bytes_read = 0;
429         /* Returns non-zero upon success, 0 upon failure. */
430         if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
431                 return SP_ERR_FAIL;
432         return bytes_read;
433 #else
434         ssize_t bytes_read;
435         /* Returns the number of bytes read, or -1 upon failure. */
436         if ((bytes_read = read(port->fd, buf, count)) < 0)
437                 return SP_ERR_FAIL;
438         return bytes_read;
439 #endif
440 }
441
442 /**
443  * Set serial parameters for the specified serial port.
444  *
445  * @param port Pointer to port structure.
446  * @param baudrate The baudrate to set.
447  * @param bits The number of data bits to use.
448  * @param parity The parity setting to use (0 = none, 1 = even, 2 = odd).
449  * @param stopbits The number of stop bits to use (1 or 2).
450  * @param flowcontrol The flow control settings to use (0 = none, 1 = RTS/CTS,
451  *                    2 = XON/XOFF).
452  *
453  * @return The number of bytes read, SP_ERR_FAIL on failure,
454  *         or SP_ERR_ARG if an invalid argument is passed.
455  */
456 int sp_set_params(struct sp_port *port, int baudrate,
457                               int bits, int parity, int stopbits,
458                               int flowcontrol, int rts, int dtr)
459 {
460         CHECK_PORT();
461
462 #ifdef _WIN32
463         DCB dcb;
464
465         if (!GetCommState(port->hdl, &dcb))
466                 return SP_ERR_FAIL;
467
468         switch (baudrate) {
469         /*
470          * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
471          * have documented CBR_* macros.
472          */
473         case 110:
474                 dcb.BaudRate = CBR_110;
475                 break;
476         case 300:
477                 dcb.BaudRate = CBR_300;
478                 break;
479         case 600:
480                 dcb.BaudRate = CBR_600;
481                 break;
482         case 1200:
483                 dcb.BaudRate = CBR_1200;
484                 break;
485         case 2400:
486                 dcb.BaudRate = CBR_2400;
487                 break;
488         case 4800:
489                 dcb.BaudRate = CBR_4800;
490                 break;
491         case 9600:
492                 dcb.BaudRate = CBR_9600;
493                 break;
494         case 14400:
495                 dcb.BaudRate = CBR_14400; /* Not available on Unix? */
496                 break;
497         case 19200:
498                 dcb.BaudRate = CBR_19200;
499                 break;
500         case 38400:
501                 dcb.BaudRate = CBR_38400;
502                 break;
503         case 57600:
504                 dcb.BaudRate = CBR_57600;
505                 break;
506         case 115200:
507                 dcb.BaudRate = CBR_115200;
508                 break;
509         case 128000:
510                 dcb.BaudRate = CBR_128000; /* Not available on Unix? */
511                 break;
512         case 256000:
513                 dcb.BaudRate = CBR_256000; /* Not available on Unix? */
514                 break;
515         default:
516                 return SP_ERR_ARG;
517         }
518
519         switch (stopbits) {
520         /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
521         case 1:
522                 dcb.StopBits = ONESTOPBIT;
523                 break;
524         case 2:
525                 dcb.StopBits = TWOSTOPBITS;
526                 break;
527         default:
528                 return SP_ERR_ARG;
529         }
530
531         switch (parity) {
532         /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
533         case SP_PARITY_NONE:
534                 dcb.Parity = NOPARITY;
535                 break;
536         case SP_PARITY_EVEN:
537                 dcb.Parity = EVENPARITY;
538                 break;
539         case SP_PARITY_ODD:
540                 dcb.Parity = ODDPARITY;
541                 break;
542         default:
543                 return SP_ERR_ARG;
544         }
545
546         if (rts != -1) {
547                 if (rts)
548                         dcb.fRtsControl = RTS_CONTROL_ENABLE;
549                 else
550                         dcb.fRtsControl = RTS_CONTROL_DISABLE;
551         }
552
553         if (dtr != -1) {
554                 if (dtr)
555                         dcb.fDtrControl = DTR_CONTROL_ENABLE;
556                 else
557                         dcb.fDtrControl = DTR_CONTROL_DISABLE;
558         }
559
560         if (!SetCommState(port->hdl, &dcb))
561                 return SP_ERR_FAIL;
562 #else
563         struct termios term;
564         speed_t baud;
565         int controlbits;
566
567         if (tcgetattr(port->fd, &term) < 0)
568                 return SP_ERR_FAIL;
569
570         switch (baudrate) {
571         case 50:
572                 baud = B50;
573                 break;
574         case 75:
575                 baud = B75;
576                 break;
577         case 110:
578                 baud = B110;
579                 break;
580         case 134:
581                 baud = B134;
582                 break;
583         case 150:
584                 baud = B150;
585                 break;
586         case 200:
587                 baud = B200;
588                 break;
589         case 300:
590                 baud = B300;
591                 break;
592         case 600:
593                 baud = B600;
594                 break;
595         case 1200:
596                 baud = B1200;
597                 break;
598         case 1800:
599                 baud = B1800;
600                 break;
601         case 2400:
602                 baud = B2400;
603                 break;
604         case 4800:
605                 baud = B4800;
606                 break;
607         case 9600:
608                 baud = B9600;
609                 break;
610         case 19200:
611                 baud = B19200;
612                 break;
613         case 38400:
614                 baud = B38400;
615                 break;
616         case 57600:
617                 baud = B57600;
618                 break;
619         case 115200:
620                 baud = B115200;
621                 break;
622         case 230400:
623                 baud = B230400;
624                 break;
625 #if !defined(__APPLE__) && !defined(__OpenBSD__)
626         case 460800:
627                 baud = B460800;
628                 break;
629 #endif
630         default:
631                 return SP_ERR_ARG;
632         }
633
634         if (cfsetospeed(&term, baud) < 0)
635                 return SP_ERR_FAIL;
636
637         if (cfsetispeed(&term, baud) < 0)
638                 return SP_ERR_FAIL;
639
640         term.c_cflag &= ~CSIZE;
641         switch (bits) {
642         case 8:
643                 term.c_cflag |= CS8;
644                 break;
645         case 7:
646                 term.c_cflag |= CS7;
647                 break;
648         default:
649                 return SP_ERR_ARG;
650         }
651
652         term.c_cflag &= ~CSTOPB;
653         switch (stopbits) {
654         case 1:
655                 term.c_cflag &= ~CSTOPB;
656                 break;
657         case 2:
658                 term.c_cflag |= CSTOPB;
659                 break;
660         default:
661                 return SP_ERR_ARG;
662         }
663
664         term.c_iflag &= ~(IXON | IXOFF | IXANY);
665         term.c_cflag &= ~CRTSCTS;
666         switch (flowcontrol) {
667         case 0:
668                 /* No flow control. */
669                 break;
670         case 1:
671                 term.c_cflag |= CRTSCTS;
672                 break;
673         case 2:
674                 term.c_iflag |= IXON | IXOFF | IXANY;
675                 break;
676         default:
677                 return SP_ERR_ARG;
678         }
679
680         term.c_iflag &= ~IGNPAR;
681         term.c_cflag &= ~(PARENB | PARODD);
682         switch (parity) {
683         case SP_PARITY_NONE:
684                 term.c_iflag |= IGNPAR;
685                 break;
686         case SP_PARITY_EVEN:
687                 term.c_cflag |= PARENB;
688                 break;
689         case SP_PARITY_ODD:
690                 term.c_cflag |= PARENB | PARODD;
691                 break;
692         default:
693                 return SP_ERR_ARG;
694         }
695
696         /* Turn off all serial port cooking. */
697         term.c_iflag &= ~(ISTRIP | INLCR | ICRNL);
698         term.c_oflag &= ~(ONLCR | OCRNL | ONOCR);
699 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
700         term.c_oflag &= ~OFILL;
701 #endif
702
703         /* Disable canonical mode, and don't echo input characters. */
704         term.c_lflag &= ~(ICANON | ECHO);
705
706         /* Ignore modem status lines; enable receiver */
707         term.c_cflag |= (CLOCAL | CREAD);
708
709         /* Write the configured settings. */
710         if (tcsetattr(port->fd, TCSADRAIN, &term) < 0)
711                 return SP_ERR_FAIL;
712
713         if (rts != -1) {
714                 controlbits = TIOCM_RTS;
715                 if (ioctl(port->fd, rts ? TIOCMBIS : TIOCMBIC,
716                                 &controlbits) < 0)
717                         return SP_ERR_FAIL;
718         }
719
720         if (dtr != -1) {
721                 controlbits = TIOCM_DTR;
722                 if (ioctl(port->fd, dtr ? TIOCMBIS : TIOCMBIC,
723                                 &controlbits) < 0)
724                         return SP_ERR_FAIL;
725         }
726 #endif
727
728         return SP_OK;
729 }
730
731 /**
732  * Get error code for failed operation.
733  *
734  * In order to obtain the correct result, this function should be called
735  * straight after the failure, before executing any other system operations.
736  *
737  * @return The system's numeric code for the error that caused the last
738  *         operation to fail.
739  */
740 int sp_last_error_code(void)
741 {
742 #ifdef _WIN32
743         return GetLastError();
744 #else
745         return errno;
746 #endif
747 }
748
749 /**
750  * Get error message for failed operation.
751  *
752  * In order to obtain the correct result, this function should be called
753  * straight after the failure, before executing other system operations.
754  *
755  * @return The system's message for the error that caused the last
756  *         operation to fail. This string may be allocated by the function,
757  *         and can be freed after use by calling sp_free_error_message.
758  */
759 char *sp_last_error_message(void)
760 {
761 #ifdef _WIN32
762         LPVOID message;
763         DWORD error = GetLastError();
764
765         FormatMessage(
766                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
767                 FORMAT_MESSAGE_FROM_SYSTEM |
768                 FORMAT_MESSAGE_IGNORE_INSERTS,
769                 NULL,
770                 error,
771                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
772                 (LPTSTR) &message,
773                 0, NULL );
774
775         return message;
776 #else
777         return strerror(errno);
778 #endif
779 }
780
781 /**
782  * Free error message.
783  *
784  * This function can be used to free a string returned by the
785  * sp_last_error_message function.
786  */
787 void sp_free_error_message(char *message)
788 {
789 #ifdef _WIN32
790         LocalFree(message);
791 #else
792         (void)message;
793 #endif
794 }