cake
/
libcasio
Archived
1
1
Fork 0
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libcasio/lib/stream/builtin/windows/list_serial.c

184 lines
4.7 KiB
C

/* ****************************************************************************
* comlist/builtin/windows.c -- find out serial devices on MS-Windows.
* Copyright (C) 2016-2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libcasio.
* libcasio is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3.0 of the License,
* or (at your option) any later version.
*
* libcasio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libcasio; if not, see <http://www.gnu.org/licenses/>.
* ************************************************************************* */
#include "../../internals.h"
#ifndef LIBCASIO_DISABLED_WINDOWS
/* These headers only work because I've redefined the version at the
* beginning of `internals.h`! */
# include <windows.h>
# include <setupapi.h>
# include <usbiodef.h>
# include <winerror.h>
/* The cookie structure. */
typedef struct {
HKEY hkey;
char *value;
char *data;
int erroneous;
DWORD i; /* index of the key to read */
DWORD value_size;
DWORD data_size;
} cookie_t, *PSP_COOKIE;
/**
* next_serial_port:
* Get the next serial port.
*
* @arg cookie the cookie.
* @arg ptr the pointer to the next path.
* @return the error code (0 if ok).
*/
CASIO_LOCAL int CASIO_EXPORT next_serial_port(cookie_t *cookie,
char const **ptr)
{
DWORD werr;
DWORD curval, datasize, type;
if (cookie->erroneous)
return (casio_error_unknown);
while (1) {
/* Get the next iteration from the original function. */
curval = cookie->value_size;
curdata = cookie->data_size;
switch ((werr = RegEnumValue(hkey, cookie->i++, value, &curval, NULL,
&type, (BYTE *)data, &curdata))) {
case 0:
/* Nothing wrong, check what's next. */
break;
case ERROR_NO_MORE_ITEMS:
/* We've arrived at the end of the original iterator. */
return (casio_error_iter);
case ERROR_MORE_DATA:
/* Our buffers weren't big enough. Tough luck!
* Let's go to the next entry and just ignore this one. */
continue;
default:
/* Any error could have happened, and put the original iterator
* in an erroneous state. So we're going to be in an erroneous
* state too. */
msg((ll_error, "Error %08lu occurred, switching to erroneous "
"state."));
cookie->erroneous = 1;
return (casio_error_unknown);
}
/* Check the type. */
if (type != REG_SZ) {
/* Not the kind of register we were expecting.
* Never mind, let's carry on. */
continue;
}
break;
}
/* The key is useless to us, we just read it because we're obliged to.
* What is interesting is the register entry data. */
*ptr = cookie->data;
return (0);
}
/**
* end_iter:
* End the iterator by freeing all related allocated resources.
*
* @arg cookie the cookie.
*/
CASIO_LOCAL void CASIO_EXPORT end_iter(cookie_t *cookie)
{
RegCloseKey(cookie->hkey);
casio_free(cookie);
}
/* Functions to use for the iterator. */
CASIO_LOCAL casio_iter_funcs_t windows_serial_functions = {
(casio_next_t *)&next_serial_port,
NULL,
(casio_end_t *)&end_iter
};
/**
* casio_iter_windows_serial:
* Iterate on serial devices under MS-Windows.
*
* What I'm doing here is based on the source from Python 3.x's winreg
* module source and the MSDN documentation.
*
* @arg iterp the iterator to create.
* @return the error code (0 if ok).
*/
# define SERIAL_COMM_HKEY "HARDWARE\\DEVICEMAP\\SERIALCOMM"
int CASIO_EXPORT casio_iter_windows_serial(casio_iter_t **iterp)
{
cookie_t *cookie;
DWORD werr, value_size, data_size;
/* Create the cookie.
* 1024 should be enough for most cases (until a driver comes and
* makes up a name which is longer…). */
value_size = 1024;
data_size = 1024;
if (!(cookie = casio_alloc(1, sizeof(*cookie) + value_size + data_size)))
return (casio_error_alloc);
cookie->value = (char *)(void *)&cookie[1];
cookie->data = cookie->value + value_size;
cookie->value_size = value_size;
cookie->data_size = data_size;
cookie->erroneous = 0;
cookie->i = 0;
/* Opening the registry key. */
msg((ll_info, "Opening HKEY_LOCAL_MACHINE\\" SERIAL_COMM_HKEY));
if ((werr = RegOpenKey(HKEY_LOCAL_MACHINE, SERIAL_COMM_HKEY,
&cookie->hkey))) {
msg((ll_error, "Encountered error %08lu while opening registry.",
werr));
casio_free(cookie);
return (casio_error_unknown);
}
return (casio_iter(iterp, cookie, &windows_serial_functions));
}
#endif