OpenVPN
msica_arg.c
Go to the documentation of this file.
1 /*
2  * openvpnmsica -- Custom Action DLL to provide OpenVPN-specific support to MSI packages
3  * https://community.openvpn.net/openvpn/wiki/OpenVPNMSICA
4  *
5  * Copyright (C) 2018-2023 Simon Rozman <simon@rozman.si>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2
9  * as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 #include "msica_arg.h"
26 #include "../tapctl/error.h"
27 #include "../tapctl/tap.h"
28 
29 #include <windows.h>
30 #include <malloc.h>
31 
32 
33 void
35 {
36  seq->head = NULL;
37  seq->tail = NULL;
38 }
39 
40 
41 void
43 {
44  while (seq->head)
45  {
46  struct msica_arg *p = seq->head;
47  seq->head = seq->head->next;
48  free(p);
49  }
50  seq->tail = NULL;
51 }
52 
53 
54 void
56  _Inout_ struct msica_arg_seq *seq,
57  _In_z_ LPCTSTR argument)
58 {
59  size_t argument_size = (_tcslen(argument) + 1) * sizeof(TCHAR);
60  struct msica_arg *p = malloc(sizeof(struct msica_arg) + argument_size);
61  if (p == NULL)
62  {
63  msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, sizeof(struct msica_arg) + argument_size);
64  }
65  memcpy(p->val, argument, argument_size);
66  p->next = seq->head;
67  seq->head = p;
68  if (seq->tail == NULL)
69  {
70  seq->tail = p;
71  }
72 }
73 
74 
75 void
77  _Inout_ struct msica_arg_seq *seq,
78  _Inout_ LPCTSTR argument)
79 {
80  size_t argument_size = (_tcslen(argument) + 1) * sizeof(TCHAR);
81  struct msica_arg *p = malloc(sizeof(struct msica_arg) + argument_size);
82  if (p == NULL)
83  {
84  msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, sizeof(struct msica_arg) + argument_size);
85  }
86  memcpy(p->val, argument, argument_size);
87  p->next = NULL;
88  *(seq->tail ? &seq->tail->next : &seq->head) = p;
89  seq->tail = p;
90 }
91 
92 
93 LPTSTR
95 {
96  /* Count required space. */
97  size_t size = 2 /*x + zero-terminator*/;
98  for (struct msica_arg *p = seq->head; p != NULL; p = p->next)
99  {
100  size += _tcslen(p->val) + 1 /*space delimiter|zero-terminator*/;
101  }
102  size *= sizeof(TCHAR);
103 
104  /* Allocate. */
105  LPTSTR str = malloc(size);
106  if (str == NULL)
107  {
108  msg(M_FATAL, "%s: malloc(%u) failed", __FUNCTION__, size);
109  return NULL;
110  }
111 
112 #ifdef _MSC_VER
113 #pragma warning(push)
114 #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. */
115 #endif
116 
117  /* Dummy argv[0] (i.e. executable name), for CommandLineToArgvW to work correctly when parsing this string. */
118  _tcscpy(str, TEXT("x"));
119 
120  /* Join. */
121  LPTSTR s = str + 1 /*x*/;
122  for (struct msica_arg *p = seq->head; p != NULL; p = p->next)
123  {
124  /* Convert zero-terminator into space delimiter. */
125  s[0] = TEXT(' ');
126  s++;
127  /* Append argument. */
128  _tcscpy(s, p->val);
129  s += _tcslen(p->val);
130  }
131 
132 #ifdef _MSC_VER
133 #pragma warning(pop)
134 #endif
135 
136  return str;
137 }
msica_arg
Argument list.
Definition: msica_arg.h:38
M_FATAL
#define M_FATAL
Definition: error.h:95
msica_arg_seq_join
LPTSTR msica_arg_seq_join(_In_ const struct msica_arg_seq *seq)
Join arguments of the argument sequence into a space delimited string.
Definition: msica_arg.c:94
msica_arg_seq
Argument sequence.
Definition: msica_arg.h:48
msica_arg::next
struct msica_arg * next
Definition: msica_arg.h:40
msica_arg_seq_add_head
void msica_arg_seq_add_head(_Inout_ struct msica_arg_seq *seq, _In_z_ LPCTSTR argument)
Inserts argument to the beginning of the argument sequence.
Definition: msica_arg.c:55
_In_
#define _In_
Definition: basic.h:42
msica_arg_seq_add_tail
void msica_arg_seq_add_tail(_Inout_ struct msica_arg_seq *seq, _Inout_ LPCTSTR argument)
Appends argument to the end of the argument sequence.
Definition: msica_arg.c:76
msica_arg.h
_Inout_
#define _Inout_
Definition: basic.h:51
msica_arg_seq_init
void msica_arg_seq_init(_Inout_ struct msica_arg_seq *seq)
Initializes argument sequence.
Definition: msica_arg.c:34
config.h
_In_z_
#define _In_z_
Definition: basic.h:48
msica_arg_seq_free
void msica_arg_seq_free(_Inout_ struct msica_arg_seq *seq)
Frees argument sequence.
Definition: msica_arg.c:42
msg
#define msg(flags,...)
Definition: error.h:150
msica_arg::val
TCHAR val[]
Pointer to the next argument in the sequence.
Definition: msica_arg.h:41