Branch data Line data Source code
1 : : /* gstdio-private.c - private glib functions for gstdio.c
2 : : *
3 : : * Copyright 2004 Tor Lillqvist
4 : : * Copyright 2018 Руслан Ижбулатов
5 : : *
6 : : * SPDX-License-Identifier: LGPL-2.1-or-later
7 : : *
8 : : * This library is free software; you can redistribute it and/or
9 : : * modify it under the terms of the GNU Lesser General Public
10 : : * License as published by the Free Software Foundation; either
11 : : * version 2.1 of the License, or (at your option) any later version.
12 : : *
13 : : * This library 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 GNU
16 : : * Lesser 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 library; if not, see <http://www.gnu.org/licenses/>.
20 : : */
21 : :
22 : : /* Strips "\\\\?\\" extended prefix or
23 : : * "\\??\\" NT Object Manager prefix from
24 : : * @str in-place, using memmove.
25 : : * @str_size must point to the size of @str
26 : : * in gunichar2s, including NUL-terminator
27 : : * (if @str is NUL-terminated; it doesn't have to be).
28 : : * On return @str_size will correctly reflect changes
29 : : * in @str size (if any).
30 : : * Returns TRUE if @str was modified.
31 : : */
32 : : static gboolean
33 : 38 : _g_win32_strip_extended_ntobjm_prefix (gunichar2 *str,
34 : : gsize *str_size)
35 : : {
36 : 38 : const wchar_t *extended_prefix = L"\\\\?\\";
37 : 38 : const gsize extended_prefix_len = wcslen (extended_prefix);
38 : 38 : const gsize extended_prefix_len_bytes = sizeof (gunichar2) * extended_prefix_len;
39 : 38 : const gsize extended_prefix_with_drive_len_bytes = sizeof (gunichar2) * (extended_prefix_len + 2);
40 : 38 : const wchar_t *ntobjm_prefix = L"\\??\\";
41 : 38 : const gsize ntobjm_prefix_len = wcslen (ntobjm_prefix);
42 : 38 : const gsize ntobjm_prefix_len_bytes = sizeof (gunichar2) * ntobjm_prefix_len;
43 : 38 : const gsize ntobjm_prefix_with_drive_len_bytes = sizeof (gunichar2) * (ntobjm_prefix_len + 2);
44 : 38 : gboolean do_move = FALSE;
45 : 38 : gsize move_shift = 0;
46 : :
47 : 38 : if ((*str_size) * sizeof (gunichar2) > extended_prefix_with_drive_len_bytes &&
48 : 54 : memcmp (str,
49 : 27 : extended_prefix,
50 : 54 : extended_prefix_len_bytes) == 0 &&
51 : 15 : iswascii (str[extended_prefix_len]) &&
52 : 13 : iswalpha (str[extended_prefix_len]) &&
53 : 13 : str[extended_prefix_len + 1] == L':')
54 : : {
55 : 10 : do_move = TRUE;
56 : 10 : move_shift = extended_prefix_len;
57 : 10 : }
58 : 28 : else if ((*str_size) * sizeof (gunichar2) > ntobjm_prefix_with_drive_len_bytes &&
59 : 34 : memcmp (str,
60 : 17 : ntobjm_prefix,
61 : 34 : ntobjm_prefix_len_bytes) == 0 &&
62 : 11 : iswascii (str[ntobjm_prefix_len]) &&
63 : 9 : iswalpha (str[ntobjm_prefix_len]) &&
64 : 9 : str[ntobjm_prefix_len + 1] == L':')
65 : : {
66 : 6 : do_move = TRUE;
67 : 6 : move_shift = ntobjm_prefix_len;
68 : 6 : }
69 : :
70 : 38 : if (do_move)
71 : : {
72 : 16 : *str_size -= move_shift;
73 : 48 : memmove (str,
74 : 16 : str + move_shift,
75 : 16 : (*str_size) * sizeof (gunichar2));
76 : 16 : }
77 : :
78 : 38 : return do_move;
79 : : }
80 : :
81 : : static int
82 : 156 : _g_win32_copy_and_maybe_terminate (const guchar *data,
83 : : gsize in_to_copy,
84 : : gunichar2 *buf,
85 : : gsize buf_size,
86 : : gunichar2 **alloc_buf,
87 : : gboolean terminate)
88 : : {
89 : 156 : gsize to_copy = in_to_copy;
90 : : /* Number of bytes we can use to add extra zeroes for NUL-termination.
91 : : * 0 means that we can destroy up to 2 bytes of data,
92 : : * 1 means that we can destroy up to 1 byte of data,
93 : : * 2 means that we do not perform destructive NUL-termination
94 : : */
95 : 156 : gsize extra_bytes = terminate ? 2 : 0;
96 : : char *buf_in_chars;
97 : :
98 : 156 : if (to_copy == 0)
99 : 8 : return 0;
100 : :
101 : : /* 2 bytes is sizeof (wchar_t), for an extra NUL-terminator. */
102 : 148 : if (buf)
103 : : {
104 : 124 : if (to_copy >= buf_size)
105 : : {
106 : 74 : extra_bytes = 0;
107 : 74 : to_copy = buf_size;
108 : 74 : }
109 : 50 : else if (to_copy > buf_size - 2)
110 : : {
111 : 18 : extra_bytes = 1;
112 : 18 : }
113 : :
114 : 124 : memcpy (buf, data, to_copy);
115 : 124 : }
116 : : else
117 : : {
118 : : /* Note that SubstituteNameLength is USHORT, so to_copy + 2, being
119 : : * gsize, never overflows.
120 : : */
121 : 24 : *alloc_buf = g_malloc (to_copy + extra_bytes);
122 : 24 : memcpy (*alloc_buf, data, to_copy);
123 : : }
124 : :
125 : 148 : if (!terminate)
126 : 71 : return to_copy;
127 : :
128 : 77 : if (buf)
129 : 62 : buf_in_chars = (char *) buf;
130 : : else
131 : 15 : buf_in_chars = (char *) *alloc_buf;
132 : :
133 : 77 : if (to_copy >= 2 && buf_in_chars[to_copy - 2] == 0 &&
134 : 34 : buf_in_chars[to_copy - 1] == 0)
135 : : {
136 : : /* Fully NUL-terminated, do nothing */
137 : 19 : }
138 : 58 : else if ((to_copy == 1 || buf_in_chars[to_copy - 2] != 0) &&
139 : 58 : buf_in_chars[to_copy - 1] == 0)
140 : : {
141 : : /* Have one zero, try to add another one */
142 : 32 : if (extra_bytes > 0)
143 : : {
144 : : /* Append trailing zero */
145 : 19 : buf_in_chars[to_copy] = 0;
146 : : /* Be precise about the number of bytes we return */
147 : 19 : to_copy += 1;
148 : 19 : }
149 : 13 : else if (to_copy >= 2)
150 : : {
151 : : /* No space for appending, destroy one byte */
152 : 13 : buf_in_chars[to_copy - 2] = 0;
153 : 13 : }
154 : : /* else there's no space at all (to_copy == 1), do nothing */
155 : 32 : }
156 : 26 : else if (extra_bytes > 0 || to_copy >= 2)
157 : : {
158 : 18 : buf_in_chars[to_copy - 2 + extra_bytes] = 0;
159 : 18 : buf_in_chars[to_copy - 1 + extra_bytes] = 0;
160 : 18 : to_copy += extra_bytes;
161 : 18 : }
162 : : else /* extra_bytes == 0 && to_copy == 1 */
163 : : {
164 : 8 : buf_in_chars[0] = 0;
165 : : }
166 : :
167 : 77 : return to_copy;
168 : 156 : }
|