- /*
- * MIT License
- *
- * Copyright (c) 2004-2026 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
- /*
- * winstreamsutil.c - Win32 named streams utility
- *
- * Written by Roland Mainz <roland.mainz@nrubsig.org>
- */
- /*
- * Compile with
- * $ clang -target x86_64-pc-windows-gnu -std=gnu17 -Wall -Wextra \
- * -municode -g winstreamsutil.c \
- * -lntdll -o winstreamsutil.exe
- */
- #define UNICODE 1
- #define _UNICODE 1
- #include <windows.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <wchar.h>
- #define EXIT_USAGE 2 /* Traditional UNIX exit for fore |usage()| */
- #define NT_MAX_LONG_PATH 1024/*32767*/
- static
- int lsstream_list_streams(const wchar_t *restrict path, bool skip_default_stream)
- {
- WIN32_FIND_STREAM_DATA sd;
- ZeroMemory(&sd, sizeof(sd));
- HANDLE h = FindFirstStreamW(path, FindStreamInfoStandard, &sd, 0);
- if (h == INVALID_HANDLE_VALUE) {
- DWORD e = GetLastError();
- if (e == ERROR_HANDLE_EOF)
- return 0;
- path, (int)e);
- return 3;
- }
- for (;;) {
- if (skip_default_stream) {
- goto nextstr;
- }
- nextstr:
- if (!FindNextStreamW(h, &sd)) {
- DWORD e = GetLastError();
- if (e == ERROR_HANDLE_EOF)
- break;
- FindClose(h);
- return 4;
- }
- }
- FindClose(h);
- return 0;
- }
- static
- int lsstream_walk(const wchar_t *restrict path, bool find_recursive)
- {
- wchar_t pattern[NT_MAX_LONG_PATH];
- WIN32_FIND_DATAW fd;
- HANDLE h = FindFirstFileW(pattern, &fd);
- if (h == INVALID_HANDLE_VALUE) {
- L"FindFirstFileW(path=%ls) returned lasterr=%d\n",
- path, (int)GetLastError());
- return EXIT_FAILURE;
- }
- do {
- continue;
- wchar_t full[NT_MAX_LONG_PATH];
- lsstream_list_streams(full, true);
- if (find_recursive && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
- lsstream_walk(full, find_recursive);
- }
- } while (FindNextFileW(h, &fd));
- DWORD e = GetLastError();
- if (e != ERROR_NO_MORE_FILES) {
- }
- FindClose(h);
- return EXIT_SUCCESS;
- }
- static
- int cmd_find(int ac, wchar_t *av[])
- {
- bool find_recursive = false;
- bool print_usage = false;
- int i;
- wchar_t *find_path = NULL;
- for (i=2 ; i < ac ; i++) {
- if (av[i][0] == L'/') {
- print_usage = true;
- find_recursive = true;
- find_recursive = false;
- else {
- return EXIT_FAILURE;
- }
- }
- else {
- find_path = av[i];
- }
- }
- if (print_usage) {
- L"Usage: winstreamutil find [/s} [path]\n"
- L"\t/s\tRecurse into subdirs.\n"
- L"\tpath\tPath to search.");
- return EXIT_USAGE;
- }
- if (find_path == NULL) {
- return EXIT_FAILURE;
- }
- lsstream_walk(find_path, find_recursive);
- return EXIT_SUCCESS;
- }
- typedef LONG NTSTATUS;
- #ifndef NT_SUCCESS
- #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
- #endif
- typedef struct _IO_STATUS_BLOCK {
- union { NTSTATUS Status; PVOID Pointer; } DUMMYUNIONNAME;
- ULONG_PTR Information;
- } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
- typedef enum _FILE_INFORMATION_CLASS {
- FileRenameInformation = 10
- } FILE_INFORMATION_CLASS;
- typedef struct _FILE_RENAME_INFORMATION {
- BOOLEAN ReplaceIfExists;
- HANDLE RootDirectory;
- ULONG FileNameLength;
- WCHAR FileName[1];
- } FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
- NTSTATUS NTAPI NtSetInformationFile(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
- ULONG NTAPI RtlNtStatusToDosError(NTSTATUS);
- static
- HANDLE OpenForRenameW(const wchar_t *restrict path)
- {
- DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- DWORD flags = FILE_FLAG_BACKUP_SEMANTICS;
- return CreateFileW(path, DELETE | SYNCHRONIZE, share, NULL, OPEN_EXISTING, flags, NULL);
- }
- static
- int cmd_renamestream(int ac, wchar_t *av[])
- {
- bool print_usage = false;
- int i;
- wchar_t *base_path = NULL;
- wchar_t *src_streamname = NULL;
- wchar_t *dst_streamname = NULL;
- for (i=2 ; i < ac ; i++) {
- if (av[i][0] == L'/') {
- print_usage = true;
- else {
- return EXIT_FAILURE;
- }
- }
- else {
- if (base_path == NULL)
- base_path = av[i];
- else if (src_streamname == NULL)
- src_streamname = av[i];
- else if (dst_streamname == NULL)
- dst_streamname = av[i];
- else {
- return EXIT_FAILURE;
- }
- }
- }
- if ((base_path == NULL) && (src_streamname == NULL) && (dst_streamname == NULL))
- print_usage = true;
- if (print_usage) {
- L"Usage: winstreamutil renamestream path srcstreamname dststreamname\n"
- L"\tpath\tPath of base file/dir (e.g. C:\\foo.txt)\n"
- L"\tsrcstreamname\tsrc stream bae (e.g. \":mystr1:$DATA\")\n"
- L"\tdststreamname\tdst stream bae (e.g. \":mystr2:$DATA\")\n");
- return EXIT_USAGE;
- }
- if ((base_path == NULL) || (src_streamname == NULL) || (dst_streamname == NULL)) {
- return EXIT_FAILURE;
- }
- if ((src_streamname[0] != L':') || (dst_streamname[0] != L':')) {
- return EXIT_FAILURE;
- }
- sizeof(FILE_RENAME_INFORMATION)+256*sizeof(wchar_t));
- if (fri == NULL) {
- return EXIT_FAILURE;
- }
- wchar_t src_stream_path[NT_MAX_LONG_PATH];
- L"%ls%ls", base_path, src_streamname);
- HANDLE bh = OpenForRenameW(src_stream_path);
- if (bh == INVALID_HANDLE_VALUE) {
- src_stream_path, (int)GetLastError());
- return EXIT_FAILURE;
- }
- fri->ReplaceIfExists = FALSE;
- fri->RootDirectory = NULL;
- IO_STATUS_BLOCK iosb = { 0 };
- NTSTATUS status = NtSetInformationFile(bh, &iosb,
- fri,
- (sizeof(FILE_RENAME_INFORMATION)+fri->FileNameLength),
- FileRenameInformation);
- bool ok = (bool)NT_SUCCESS(status);
- if (ok) {
- base_path, src_streamname,
- base_path, dst_streamname);
- }
- else {
- L"Renaming failed with lasterr=%d\n",
- (int)RtlNtStatusToDosError(status));
- }
- (void)CloseHandle(bh);
- return EXIT_SUCCESS;
- }
- static
- void usage(const wchar_t *restrict progname)
- {
- L"%ls: Available commands:\n"
- L"find\tfind all non-default named streams in path\n"
- L"renamestream\trename stream\n",
- progname);
- }
- int wmain(int argc, wchar_t *argv[])
- {
- if (argc < 2) {
- (void)usage(argv[0]);
- return EXIT_USAGE;
- }
- /*
- * FIXME: ToDO: Add more sub commands:
- * createnew, queryallocatedranges, delete
- */
- return cmd_find(argc, argv);
- }
- return cmd_renamestream(argc, argv);
- }
- else {
- L"%ls: Unknown subcmd '%ls':\n",
- argv[0], argv[1]);
- }
- return EXIT_SUCCESS;
- }
winstreamsutil.c - Win32 named streams utility
Posted by Anonymous on Wed 21st Jan 2026 03:22
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.
nrubsig.kpaste.net RSS