summaryrefslogtreecommitdiff
path: root/src/openvpnmsica/msica_arg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpnmsica/msica_arg.c')
-rw-r--r--src/openvpnmsica/msica_arg.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/openvpnmsica/msica_arg.c b/src/openvpnmsica/msica_arg.c
new file mode 100644
index 0000000..cde0577
--- /dev/null
+++ b/src/openvpnmsica/msica_arg.c
@@ -0,0 +1,139 @@
+/*
+ * openvpnmsica -- Custom Action DLL to provide OpenVPN-specific support to MSI packages
+ * https://community.openvpn.net/openvpn/wiki/OpenVPNMSICA
+ *
+ * Copyright (C) 2018-2021 Simon Rozman <simon@rozman.si>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#elif defined(_MSC_VER)
+#include <config-msvc.h>
+#endif
+
+#include "msica_arg.h"
+#include "../tapctl/error.h"
+#include "../tapctl/tap.h"
+
+#include <windows.h>
+#include <malloc.h>
+
+
+void
+msica_arg_seq_init(_Inout_ struct msica_arg_seq *seq)
+{
+ seq->head = NULL;
+ seq->tail = NULL;
+}
+
+
+void
+msica_arg_seq_free(_Inout_ struct msica_arg_seq *seq)
+{
+ while (seq->head)
+ {
+ struct msica_arg *p = seq->head;
+ seq->head = seq->head->next;
+ free(p);
+ }
+ seq->tail = NULL;
+}
+
+
+void
+msica_arg_seq_add_head(
+ _Inout_ struct msica_arg_seq *seq,
+ _In_z_ LPCTSTR argument)
+{
+ size_t argument_size = (_tcslen(argument) + 1) * sizeof(TCHAR);
+ struct msica_arg *p = malloc(sizeof(struct msica_arg) + argument_size);
+ if (p == NULL)
+ {
+ msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, sizeof(struct msica_arg) + argument_size);
+ }
+ memcpy(p->val, argument, argument_size);
+ p->next = seq->head;
+ seq->head = p;
+ if (seq->tail == NULL)
+ {
+ seq->tail = p;
+ }
+}
+
+
+void
+msica_arg_seq_add_tail(
+ _Inout_ struct msica_arg_seq *seq,
+ _Inout_ LPCTSTR argument)
+{
+ size_t argument_size = (_tcslen(argument) + 1) * sizeof(TCHAR);
+ struct msica_arg *p = malloc(sizeof(struct msica_arg) + argument_size);
+ if (p == NULL)
+ {
+ msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, sizeof(struct msica_arg) + argument_size);
+ }
+ memcpy(p->val, argument, argument_size);
+ p->next = NULL;
+ *(seq->tail ? &seq->tail->next : &seq->head) = p;
+ seq->tail = p;
+}
+
+
+LPTSTR
+msica_arg_seq_join(_In_ const struct msica_arg_seq *seq)
+{
+ /* Count required space. */
+ size_t size = 2 /*x + zero-terminator*/;
+ for (struct msica_arg *p = seq->head; p != NULL; p = p->next)
+ {
+ size += _tcslen(p->val) + 1 /*space delimiter|zero-terminator*/;
+ }
+ size *= sizeof(TCHAR);
+
+ /* Allocate. */
+ LPTSTR str = malloc(size);
+ if (str == NULL)
+ {
+ msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, size);
+ return NULL;
+ }
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4996) /* Using unsafe string functions: The space in s and termination of p->val has been implicitly verified at the beginning of this function. */
+#endif
+
+ /* Dummy argv[0] (i.e. executable name), for CommandLineToArgvW to work correctly when parsing this string. */
+ _tcscpy(str, TEXT("x"));
+
+ /* Join. */
+ LPTSTR s = str + 1 /*x*/;
+ for (struct msica_arg *p = seq->head; p != NULL; p = p->next)
+ {
+ /* Convert zero-terminator into space delimiter. */
+ s[0] = TEXT(' ');
+ s++;
+ /* Append argument. */
+ _tcscpy(s, p->val);
+ s += _tcslen(p->val);
+ }
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+ return str;
+}