/* gstdio-private.c - private glib functions for gstdio.c * * Copyright 2004 Tor Lillqvist * Copyright 2018 Руслан Ижбулатов * * SPDX-License-Identifier: LGPL-2.1-or-later * * This library 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 2.1 of the License, or (at your option) any later version. * * This library 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 this library; if not, see . */ /* Strips "\\\\?\\" extended prefix or * "\\??\\" NT Object Manager prefix from * @str in-place, using memmove. * @str_size must point to the size of @str * in gunichar2s, including NUL-terminator * (if @str is NUL-terminated; it doesn't have to be). * On return @str_size will correctly reflect changes * in @str size (if any). * Returns TRUE if @str was modified. */ static gboolean _g_win32_strip_extended_ntobjm_prefix (gunichar2 *str, gsize *str_size) { const wchar_t *extended_prefix = L"\\\\?\\"; const gsize extended_prefix_len = wcslen (extended_prefix); const gsize extended_prefix_len_bytes = sizeof (gunichar2) * extended_prefix_len; const gsize extended_prefix_with_drive_len_bytes = sizeof (gunichar2) * (extended_prefix_len + 2); const wchar_t *ntobjm_prefix = L"\\??\\"; const gsize ntobjm_prefix_len = wcslen (ntobjm_prefix); const gsize ntobjm_prefix_len_bytes = sizeof (gunichar2) * ntobjm_prefix_len; const gsize ntobjm_prefix_with_drive_len_bytes = sizeof (gunichar2) * (ntobjm_prefix_len + 2); gboolean do_move = FALSE; gsize move_shift = 0; if ((*str_size) * sizeof (gunichar2) > extended_prefix_with_drive_len_bytes && memcmp (str, extended_prefix, extended_prefix_len_bytes) == 0 && iswascii (str[extended_prefix_len]) && iswalpha (str[extended_prefix_len]) && str[extended_prefix_len + 1] == L':') { do_move = TRUE; move_shift = extended_prefix_len; } else if ((*str_size) * sizeof (gunichar2) > ntobjm_prefix_with_drive_len_bytes && memcmp (str, ntobjm_prefix, ntobjm_prefix_len_bytes) == 0 && iswascii (str[ntobjm_prefix_len]) && iswalpha (str[ntobjm_prefix_len]) && str[ntobjm_prefix_len + 1] == L':') { do_move = TRUE; move_shift = ntobjm_prefix_len; } if (do_move) { *str_size -= move_shift; memmove (str, str + move_shift, (*str_size) * sizeof (gunichar2)); } return do_move; } static int _g_win32_copy_and_maybe_terminate (const guchar *data, gsize in_to_copy, gunichar2 *buf, gsize buf_size, gunichar2 **alloc_buf, gboolean terminate) { gsize to_copy = in_to_copy; /* Number of bytes we can use to add extra zeroes for NUL-termination. * 0 means that we can destroy up to 2 bytes of data, * 1 means that we can destroy up to 1 byte of data, * 2 means that we do not perform destructive NUL-termination */ gsize extra_bytes = terminate ? 2 : 0; char *buf_in_chars; if (to_copy == 0) return 0; /* 2 bytes is sizeof (wchar_t), for an extra NUL-terminator. */ if (buf) { if (to_copy >= buf_size) { extra_bytes = 0; to_copy = buf_size; } else if (to_copy > buf_size - 2) { extra_bytes = 1; } memcpy (buf, data, to_copy); } else { /* Note that SubstituteNameLength is USHORT, so to_copy + 2, being * gsize, never overflows. */ *alloc_buf = g_malloc (to_copy + extra_bytes); memcpy (*alloc_buf, data, to_copy); } if (!terminate) return to_copy; if (buf) buf_in_chars = (char *) buf; else buf_in_chars = (char *) *alloc_buf; if (to_copy >= 2 && buf_in_chars[to_copy - 2] == 0 && buf_in_chars[to_copy - 1] == 0) { /* Fully NUL-terminated, do nothing */ } else if ((to_copy == 1 || buf_in_chars[to_copy - 2] != 0) && buf_in_chars[to_copy - 1] == 0) { /* Have one zero, try to add another one */ if (extra_bytes > 0) { /* Append trailing zero */ buf_in_chars[to_copy] = 0; /* Be precise about the number of bytes we return */ to_copy += 1; } else if (to_copy >= 2) { /* No space for appending, destroy one byte */ buf_in_chars[to_copy - 2] = 0; } /* else there's no space at all (to_copy == 1), do nothing */ } else if (extra_bytes > 0 || to_copy >= 2) { buf_in_chars[to_copy - 2 + extra_bytes] = 0; buf_in_chars[to_copy - 1 + extra_bytes] = 0; to_copy += extra_bytes; } else /* extra_bytes == 0 && to_copy == 1 */ { buf_in_chars[0] = 0; } return to_copy; }