pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: Patches for EXIT_USAGE, tests, winrunassystem+misc, 2025-08-26
Posted by Anonymous on Tue 26th Aug 2025 14:41
raw | new post

  1. From df466334121c3c6e366145bcf3ffc5675cc2eb13 Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Mon, 25 Aug 2025 18:28:03 +0200
  4. Subject: [PATCH 1/4] tests: winfsinfo1: Implement "getfilefssizeinformation"
  5.  subcmd
  6.  
  7. Implement "getfilefssizeinformation" subcmd to query
  8. |FileFsSizeInformation| volume information.
  9.  
  10. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  11. ---
  12. tests/winfsinfo1/winfsinfo.c | 57 ++++++++++++++++++++++++++++++++++++
  13.  1 file changed, 57 insertions(+)
  14.  
  15. diff --git a/tests/winfsinfo1/winfsinfo.c b/tests/winfsinfo1/winfsinfo.c
  16. index 5aa3041..b36fc6f 100644
  17. --- a/tests/winfsinfo1/winfsinfo.c
  18. +++ b/tests/winfsinfo1/winfsinfo.c
  19. @@ -382,6 +382,59 @@ int getfilefssectorsizeinformation(const char *progname, const char *filename)
  20.      (void)printf(")\n");
  21.      res = EXIT_SUCCESS;
  22.  
  23. +done:
  24. +    (void)CloseHandle(fileHandle);
  25. +    return res;
  26. +}
  27. +
  28. +static
  29. +int getfilefssizeinformation(const char *progname, const char *filename)
  30. +{
  31. +    int res = EXIT_FAILURE;
  32. +
  33. +    HANDLE fileHandle = CreateFileA(filename,
  34. +        GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
  35. +        FILE_FLAG_BACKUP_SEMANTICS, NULL);
  36. +    if (fileHandle == INVALID_HANDLE_VALUE) {
  37. +        (void)fprintf(stderr,
  38. +            "%s: Error opening file '%s'. Last error was %d.\n",
  39. +            progname,
  40. +            filename,
  41. +            (int)GetLastError());
  42. +        return EXIT_FAILURE;
  43. +    }
  44. +
  45. +    FILE_FS_SIZE_INFORMATION ffsi = { 0 };
  46. +    NTSTATUS status;
  47. +    IO_STATUS_BLOCK io;
  48. +
  49. +    status = ZwQueryVolumeInformationFile(fileHandle, &io, &ffsi, sizeof(ffsi),
  50. +        FileFsSizeInformation);
  51. +
  52. +    switch (status) {
  53. +        case STATUS_SUCCESS:
  54. +            break;
  55. +        default:
  56. +            (void)fprintf(stderr, "ZwQueryVolumeInformationFile() failed with 0x%lx\n", (long)status);
  57. +            res = EXIT_FAILURE;
  58. +            goto done;
  59. +    }
  60. +
  61. +    (void)printf("(\n");
  62. +    (void)printf("\tfilename='%s'\n", filename);
  63. +
  64. +    (void)printf("\tTotalAllocationUnits=%lld\n",
  65. +        (long long)ffsi.TotalAllocationUnits.QuadPart);
  66. +    (void)printf("\tAvailableAllocationUnits=%lld\n",
  67. +        (long long)ffsi.AvailableAllocationUnits.QuadPart);
  68. +    (void)printf("\tSectorsPerAllocationUnit=%lu\n",
  69. +        (unsigned long)ffsi.SectorsPerAllocationUnit);
  70. +    (void)printf("\tBytesPerSector=%lu\n",
  71. +        (unsigned long)ffsi.BytesPerSector);
  72. +
  73. +    (void)printf(")\n");
  74. +    res = EXIT_SUCCESS;
  75. +
  76.  done:
  77.      (void)CloseHandle(fileHandle);
  78.      return res;
  79. @@ -1401,6 +1454,7 @@ void usage(void)
  80.          "getfinalpath|"
  81.  #ifdef NTDLL_HAS_ZWQUERYVOLUMEINFORMATIONFILE
  82.          "getfilefssectorsizeinformation|"
  83. +        "getfilefssizeinformation|"
  84.  #endif /* NTDLL_HAS_ZWQUERYVOLUMEINFORMATIONFILE */
  85.          "filebasicinfo|"
  86.          "fileexinfostandard|"
  87. @@ -1453,6 +1507,9 @@ int main(int ac, char *av[])
  88.      else if (!strcmp(subcmd, "getfilefssectorsizeinformation")) {
  89.          return getfilefssectorsizeinformation(av[0], av[2]);
  90.      }
  91. +    else if (!strcmp(subcmd, "getfilefssizeinformation")) {
  92. +        return getfilefssizeinformation(av[0], av[2]);
  93. +    }
  94.  #endif /* NTDLL_HAS_ZWQUERYVOLUMEINFORMATIONFILE */
  95.      else if (!strcmp(subcmd, "filebasicinfo")) {
  96.          return get_file_basic_info(av[0], av[2]);
  97. --
  98. 2.45.1
  99.  
  100. From 9f0073f8a72ac8b97610d4b0dcb6704fb5060b75 Mon Sep 17 00:00:00 2001
  101. From: Roland Mainz <roland.mainz@nrubsig.org>
  102. Date: Tue, 26 Aug 2025 14:35:49 +0200
  103. Subject: [PATCH 2/4] cygwin,tests: Add new /sbin/winrunassystem utility to run
  104.  Windows executables as user SYSTEM
  105.  
  106. Add new /sbin/winrunassystem utility to run Windows executables as Windows
  107. user SYSTEM (S-1-5-18).
  108.  
  109. Example:
  110. Create global mount (for all users/services on a machine):
  111. $ /sbin/winrunassystem "$(cygpath -w /sbin/nfs_mount.exe)" -o sec=sys,rw 'N' nfs://derfwnb4966_ipv6linklocal//bigdis
  112.  
  113. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  114. ---
  115. cygwin/Makefile                       |   4 +
  116.  cygwin/Makefile.install               |   7 +
  117.  tests/winrunassystem/Makefile         |  23 +
  118.  tests/winrunassystem/winrunassystem.c | 579 ++++++++++++++++++++++++++
  119.  4 files changed, 613 insertions(+)
  120.  create mode 100644 tests/winrunassystem/Makefile
  121.  create mode 100644 tests/winrunassystem/winrunassystem.c
  122.  
  123. diff --git a/cygwin/Makefile b/cygwin/Makefile
  124. index 6fbb7f0..13d0a03 100644
  125. --- a/cygwin/Makefile
  126. +++ b/cygwin/Makefile
  127. @@ -25,6 +25,7 @@ $(PROJECT_BASEDIR_DIR)/tests/ea/nfs_ea.exe \
  128.         $(PROJECT_BASEDIR_DIR)/tests/filemmaptests/qsortonmmapedfile1.exe \
  129.         $(PROJECT_BASEDIR_DIR)/tests/winclonefile/winclonefile.exe \
  130.         $(PROJECT_BASEDIR_DIR)/tests/winoffloadcopyfile/winoffloadcopyfile.exe \
  131. +       $(PROJECT_BASEDIR_DIR)/tests/winrunassystem/winrunassystem.exe \
  132.         $(PROJECT_BASEDIR_DIR)/tests/winsg/winsg.exe: build_testutils
  133.  
  134.  #
  135. @@ -72,6 +73,7 @@ build_testutils:
  136.         (cd "$(PROJECT_BASEDIR_DIR)/tests/filemmaptests" && make all)
  137.         (cd "$(PROJECT_BASEDIR_DIR)/tests/winclonefile" && make all)
  138.         (cd "$(PROJECT_BASEDIR_DIR)/tests/winoffloadcopyfile" && make all)
  139. +       (cd "$(PROJECT_BASEDIR_DIR)/tests/winrunassystem" && make all)
  140.         (cd "$(PROJECT_BASEDIR_DIR)/tests/winsg" && make all)
  141.  
  142.  build: build_32bit_release build_32bit_debug build_64bit_release build_64bit_debug build_arm_64bit_debug build_testutils
  143. @@ -109,6 +111,7 @@ clean:
  144.         (cd "$(PROJECT_BASEDIR_DIR)/tests/filemmaptests" && make clean)
  145.         (cd "$(PROJECT_BASEDIR_DIR)/tests/winclonefile" && make clean)
  146.         (cd "$(PROJECT_BASEDIR_DIR)/tests/winoffloadcopyfile" && make clean)
  147. +       (cd "$(PROJECT_BASEDIR_DIR)/tests/winrunassystem" && make clean)
  148.         (cd "$(PROJECT_BASEDIR_DIR)/tests/winsg" && make clean)
  149.  
  150.  installdest_util: \
  151. @@ -121,6 +124,7 @@ installdest_util: \
  152.         $(PROJECT_BASEDIR_DIR)/tests/filemmaptests/qsortonmmapedfile1.exe \
  153.         $(PROJECT_BASEDIR_DIR)/tests/winclonefile/winclonefile.exe \
  154.         $(PROJECT_BASEDIR_DIR)/tests/winoffloadcopyfile/winoffloadcopyfile.exe \
  155. +       $(PROJECT_BASEDIR_DIR)/tests/winrunassystem/winrunassystem.exe \
  156.         $(PROJECT_BASEDIR_DIR)/tests/winsg/winsg.exe \
  157.         $(CYGWIN_MAKEFILE_DIR)/devel/msnfs41client.bash
  158.  
  159. diff --git a/cygwin/Makefile.install b/cygwin/Makefile.install
  160. index 2ad96b0..d0574a4 100644
  161. --- a/cygwin/Makefile.install
  162. +++ b/cygwin/Makefile.install
  163. @@ -126,6 +126,13 @@ installdest:
  164.         else \
  165.                 (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/ && $(LINKEXE) winoffloadcopyfile.i686.exe winoffloadcopyfile.exe) \
  166.         fi
  167. +       cp "$(PROJECT_BASEDIR_DIR)/tests/winrunassystem/winrunassystem.x86_64.exe" $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/winrunassystem.x86_64.exe
  168. +       cp "$(PROJECT_BASEDIR_DIR)/tests/winrunassystem/winrunassystem.i686.exe" $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/winrunassystem.i686.exe
  169. +       if [[ "$(CYGWIN_BASEPATH)" == *64* ]] ; then \
  170. +               (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/ && $(LINKEXE) winrunassystem.x86_64.exe winrunassystem.exe) \
  171. +       else \
  172. +               (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/ && $(LINKEXE) winrunassystem.i686.exe winrunassystem.exe) \
  173. +       fi
  174.         cp "$(PROJECT_BASEDIR_DIR)/tests/lssparse/lssparse.x86_64.exe" $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/lssparse.x86_64.exe
  175.         if [[ "$(CYGWIN_BASEPATH)" == *64* ]] ; then \
  176.                 (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/ && $(LINKEXE) lssparse.x86_64.exe lssparse.exe) \
  177. diff --git a/tests/winrunassystem/Makefile b/tests/winrunassystem/Makefile
  178. new file mode 100644
  179. index 0000000..9ade5ec
  180. --- /dev/null
  181. +++ b/tests/winrunassystem/Makefile
  182. @@ -0,0 +1,23 @@
  183. +#
  184. +# Makefile for winrunassystem
  185. +#
  186. +
  187. +# POSIX Makefile
  188. +
  189. +all: winrunassystem.i686.exe winrunassystem.x86_64.exe winrunassystem.exe
  190. +
  191. +winrunassystem.i686.exe: winrunassystem.c
  192. +       clang -target i686-pc-windows-gnu -std=gnu17 -municode -Wall -Wextra -DUNICODE=1 -D_UNICODE=1 -g winrunassystem.c -lWtsapi32 -o winrunassystem.i686.exe
  193. +
  194. +winrunassystem.x86_64.exe: winrunassystem.c
  195. +       clang -target x86_64-pc-windows-gnu -std=gnu17 -municode -Wall -Wextra -DUNICODE=1 -D_UNICODE=1 -g winrunassystem.c -lWtsapi32 -o winrunassystem.x86_64.exe
  196. +
  197. +winrunassystem.exe: winrunassystem.x86_64.exe
  198. +       ln -s winrunassystem.x86_64.exe winrunassystem.exe
  199. +
  200. +clean:
  201. +       rm -fv \
  202. +               winrunassystem.i686.exe \
  203. +               winrunassystem.x86_64.exe \
  204. +               winrunassystem.exe
  205. +# EOF.
  206. diff --git a/tests/winrunassystem/winrunassystem.c b/tests/winrunassystem/winrunassystem.c
  207. new file mode 100644
  208. index 0000000..80b9fbc
  209. --- /dev/null
  210. +++ b/tests/winrunassystem/winrunassystem.c
  211. @@ -0,0 +1,579 @@
  212. +
  213. +/*
  214. + * MIT License
  215. + *
  216. + * Copyright (c) 2025 Roland Mainz <roland.mainz@nrubsig.org>
  217. + *
  218. + * Permission is hereby granted, free of charge, to any person obtaining a copy
  219. + * of this software and associated documentation files (the "Software"), to deal
  220. + * in the Software without restriction, including without limitation the rights
  221. + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  222. + * copies of the Software, and to permit persons to whom the Software is
  223. + * furnished to do so, subject to the following conditions:
  224. + *
  225. + * The above copyright notice and this permission notice shall be included in
  226. + * allcopies or substantial portions of the Software.
  227. + *
  228. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  229. + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  230. + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  231. + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  232. + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  233. + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  234. + * THE SOFTWARE.
  235. + */
  236. +
  237. +/*
  238. + * runassystem.c - run Win32 program as Windows user "SYSTEM"
  239. + *
  240. + * Written by Roland Mainz <roland.mainz@nrubsig.org>
  241. + */
  242. +
  243. +/*
  244. + * Compile with:
  245. + * $ clang -target x86_64-pc-windows-gnu -Wall -municode runassystem.c \
  246. + *      -lWtsapi32 -o runassystem.exe
  247. + */
  248. +
  249. +#define WIN32_LEAN_AND_MEAN 1
  250. +
  251. +#include <windows.h>
  252. +#include <strsafe.h>
  253. +#include <stdbool.h>
  254. +#include <stdio.h>
  255. +#include <wchar.h>
  256. +#include <WtsApi32.h>
  257. +#include <sddl.h>
  258. +#include <fcntl.h>
  259. +
  260. +#define EXIT_USAGE (2) /* Traditional UNIX exit code for usage */
  261. +
  262. +/* Global variables */
  263. +/*
  264. + * |service_name_buffer| - only valid after calling
  265. + * |SetupTemporaryServiceName()|
  266. + */
  267. +static wchar_t service_name_buffer[512];
  268. +static const wchar_t* SERVICE_DISPLAY_NAME = L"runassystem temporary service";
  269. +
  270. +static SERVICE_STATUS g_ServiceStatus = {0};
  271. +static SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
  272. +static HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE;
  273. +
  274. +/*
  275. + * Store argument array passed to |wmain()| because the argument
  276. + * array for |ServiceMain()| does not have these arguments
  277. + *
  278. + * service_argv[0] == *.exe name
  279. + * service_argv[1] == "--service"
  280. + * service_argv[2] == <Service name>
  281. + * service_argv[3] == <command-to-run>
  282. + * service_argv[4..n] == <command-args>
  283. + */
  284. +static int service_argc = 0;
  285. +static wchar_t **service_argv = NULL;
  286. +
  287. +
  288. +/* Local prototypes */
  289. +static void ReportError(const char* context);
  290. +static void LaunchInteractiveProcess(void);
  291. +static void WINAPI ServiceCtrlHandler(DWORD CtrlCode);
  292. +static void WINAPI ServiceMain(DWORD argc, LPWSTR* argv);
  293. +
  294. +
  295. +// #define DBG 1
  296. +
  297. +#ifdef DBG
  298. +#define D(x) x
  299. +#define DbgP(_x_) RASDbgPrint _x_
  300. +#else
  301. +#define DbgP(_x_)
  302. +#define D(x)
  303. +#endif
  304. +#define TRACE_TAG   L"[RAS]"
  305. +
  306. +#define PTR2PTRDIFF_T(p) (((char *)(p))-((char *)0))
  307. +#define HANDLE2INT(h) ((int)PTR2PTRDIFF_T(h))
  308. +
  309. +#ifdef DBG
  310. +static
  311. +ULONG _cdecl RASDbgPrint(__in LPWSTR fmt, ...)
  312. +{
  313. +    DWORD saved_lasterr;
  314. +    ULONG rc = 0;
  315. +#define SZBUFFER_SIZE 1024
  316. +    wchar_t szbuffer[SZBUFFER_SIZE+1];
  317. +    wchar_t *szbp = szbuffer;
  318. +
  319. +    saved_lasterr = GetLastError();
  320. +
  321. +    va_list marker;
  322. +    va_start(marker, fmt);
  323. +
  324. +    (void)StringCchPrintfW(szbp, SZBUFFER_SIZE-(szbp - szbuffer),
  325. +        TRACE_TAG L"[thr=%04x] ", (int)GetCurrentThreadId());
  326. +    szbp += wcslen(szbp);
  327. +
  328. +    (void)StringCchVPrintfW(szbp, SZBUFFER_SIZE-(szbp - szbuffer),
  329. +        fmt, marker);
  330. +    szbuffer[SZBUFFER_SIZE-1] = L'\0';
  331. +
  332. +    OutputDebugStringW(szbuffer);
  333. +
  334. +    va_end(marker);
  335. +
  336. +    SetLastError(saved_lasterr);
  337. +
  338. +    return rc;
  339. +}
  340. +#endif /* DBG */
  341. +
  342. +static
  343. +void ReportError(const char* context)
  344. +{
  345. +    (void)fprintf(stderr,
  346. +        "ERROR in %s: %d\n",
  347. +        context,
  348. +        (int)GetLastError());
  349. +}
  350. +
  351. +static
  352. +int remove_fmt(const char *fmt, ...)
  353. +{
  354. +    int retval;
  355. +    char buffer[16384];
  356. +
  357. +    va_list args;
  358. +    va_start(args, fmt);
  359. +
  360. +    (void)vsnprintf(buffer, sizeof(buffer), fmt, args);
  361. +    retval = remove(buffer);
  362. +
  363. +    va_end(args);
  364. +
  365. +    return retval;
  366. +}
  367. +
  368. +static
  369. +int system_fmt(const char *fmt, ...)
  370. +{
  371. +    int retval;
  372. +    char buffer[16384];
  373. +
  374. +    va_list args;
  375. +    va_start(args, fmt);
  376. +
  377. +    (void)vsnprintf(buffer, sizeof(buffer), fmt, args);
  378. +    retval = system(buffer);
  379. +
  380. +    va_end(args);
  381. +
  382. +    return retval;
  383. +}
  384. +
  385. +static
  386. +void LaunchInteractiveProcess(void)
  387. +{
  388. +    STARTUPINFOA si;
  389. +    PROCESS_INFORMATION pi;
  390. +    DWORD child_retval = 120;
  391. +
  392. +    const wchar_t *service_name = service_argv[2];
  393. +    char namebuff[256];
  394. +
  395. +    char buffer[16384];
  396. +    char *s = buffer;
  397. +
  398. +    HANDLE hFile_stdout = INVALID_HANDLE_VALUE;
  399. +    HANDLE hFile_stderr = INVALID_HANDLE_VALUE;
  400. +    HANDLE hFile_status = INVALID_HANDLE_VALUE;
  401. +
  402. +    SECURITY_ATTRIBUTES sa = { 0 };
  403. +
  404. +    (void)memset(&si, 0, sizeof(si));
  405. +    (void)memset(&pi, 0, sizeof(pi));
  406. +
  407. +    si.cb = sizeof(si);
  408. +
  409. +    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  410. +    sa.bInheritHandle = TRUE;
  411. +
  412. +    (void)snprintf(namebuff, sizeof(namebuff),
  413. +        "C:\\Windows\\Temp\\%ls_stdout", service_name);
  414. +    hFile_stdout = CreateFileA(namebuff,
  415. +        GENERIC_READ|GENERIC_WRITE,
  416. +        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  417. +        &sa,
  418. +        CREATE_ALWAYS,
  419. +        FILE_ATTRIBUTE_TEMPORARY,
  420. +        NULL);
  421. +    if (hFile_stdout == INVALID_HANDLE_VALUE) {
  422. +        DbgP((L"LaunchInteractiveProcess: cannot open stdout, lasterr=%d\n",
  423. +            (int)GetLastError()));
  424. +        goto done;
  425. +    }
  426. +    (void)snprintf(namebuff, sizeof(namebuff),
  427. +        "C:\\Windows\\Temp\\%ls_stderr", service_name);
  428. +    hFile_stderr = CreateFileA(namebuff,
  429. +        GENERIC_READ|GENERIC_WRITE,
  430. +        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  431. +        &sa,
  432. +        CREATE_ALWAYS,
  433. +        FILE_ATTRIBUTE_TEMPORARY,
  434. +        NULL);
  435. +    if (hFile_stderr == INVALID_HANDLE_VALUE) {
  436. +        DbgP((L"LaunchInteractiveProcess: cannot open stderr, lasterr=%d\n",
  437. +            (int)GetLastError()));
  438. +        goto done;
  439. +    }
  440. +    (void)snprintf(namebuff, sizeof(namebuff),
  441. +        "C:\\Windows\\Temp\\%ls_status_not_ready", service_name);
  442. +    hFile_status = CreateFileA(namebuff,
  443. +        GENERIC_READ|GENERIC_WRITE,
  444. +        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
  445. +        &sa,
  446. +        CREATE_ALWAYS,
  447. +        FILE_ATTRIBUTE_TEMPORARY,
  448. +        NULL);
  449. +    if (hFile_status == INVALID_HANDLE_VALUE) {
  450. +        DbgP((L"LaunchInteractiveProcess: "
  451. +            L"cannot open status file, lasterr=%d\n",
  452. +            (int)GetLastError()));
  453. +        goto done;
  454. +    }
  455. +    (void)SetHandleInformation(hFile_stdout, HANDLE_FLAG_INHERIT, TRUE);
  456. +    (void)SetHandleInformation(hFile_stderr, HANDLE_FLAG_INHERIT, TRUE);
  457. +
  458. +    /* Command name + <space> separator */
  459. +    s += sprintf(s, "%ls ", service_argv[3]);
  460. +
  461. +    int i;
  462. +    for (i=4 ; i < service_argc ; i++) {
  463. +        s += sprintf(s, " \"%ls\"", service_argv[i]);
  464. +    }
  465. +
  466. +    si.dwFlags = STARTF_USESTDHANDLES;
  467. +    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
  468. +    si.hStdOutput = hFile_stdout;
  469. +    si.hStdError = hFile_stderr;
  470. +
  471. +    if (!CreateProcessA(NULL,
  472. +        buffer,
  473. +        NULL,
  474. +        NULL,
  475. +        TRUE,
  476. +        0,
  477. +        NULL,
  478. +        NULL,
  479. +        &si,
  480. +        &pi)) {
  481. +        (void)printf("CreateProcess failed (%d).\n", (int)GetLastError());
  482. +        return;
  483. +    }
  484. +
  485. +    (void)WaitForSingleObject(pi.hProcess, INFINITE);
  486. +
  487. +    (void)GetExitCodeProcess(pi.hProcess, &child_retval);
  488. +
  489. +done:
  490. +    (void)CloseHandle(pi.hProcess);
  491. +    (void)CloseHandle(pi.hThread);
  492. +
  493. +    (void)CloseHandle(hFile_stdout);
  494. +    (void)CloseHandle(hFile_stderr);
  495. +
  496. +    if (hFile_status != INVALID_HANDLE_VALUE) {
  497. +        char statusbuff[16];
  498. +
  499. +        (void)sprintf(statusbuff, "%d", (int)child_retval);
  500. +        (void)WriteFile(hFile_status,
  501. +            statusbuff, strlen(statusbuff), NULL, NULL);
  502. +        (void)CloseHandle(hFile_status);
  503. +
  504. +        /*
  505. +         * Atomically rename file, parent will wait until the file
  506. +         * is available
  507. +         */
  508. +        char oldnamebuff[256];
  509. +        char newnamebuff[256];
  510. +        (void)snprintf(oldnamebuff, sizeof(oldnamebuff),
  511. +            "C:\\Windows\\Temp\\%ls_status_not_ready", service_name);
  512. +        (void)snprintf(newnamebuff, sizeof(newnamebuff),
  513. +            "C:\\Windows\\Temp\\%ls_status", service_name);
  514. +        (void)rename(oldnamebuff, newnamebuff);
  515. +    }
  516. +}
  517. +
  518. +static
  519. +void WINAPI ServiceCtrlHandler(DWORD CtrlCode)
  520. +{
  521. +    switch (CtrlCode) {
  522. +        case SERVICE_CONTROL_STOP:
  523. +            if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
  524. +                break;
  525. +
  526. +            g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  527. +            SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
  528. +            SetEvent(g_ServiceStopEvent);
  529. +            break;
  530. +        default:
  531. +            break;
  532. +    }
  533. +}
  534. +
  535. +static
  536. +void WINAPI ServiceMain(DWORD argc, wchar_t *argv[])
  537. +{
  538. +    (void)argc; /* unused */
  539. +    (void)argv; /* unused */
  540. +
  541. +    g_StatusHandle = RegisterServiceCtrlHandlerW(service_argv[2],
  542. +        ServiceCtrlHandler);
  543. +    if (!g_StatusHandle) {
  544. +        ReportError("RegisterServiceCtrlHandlerW");
  545. +        return;
  546. +    }
  547. +
  548. +    g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  549. +    g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  550. +    g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  551. +    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
  552. +
  553. +    g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  554. +    if (g_ServiceStopEvent == NULL) {
  555. +        g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  556. +        SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
  557. +        return;
  558. +    }
  559. +
  560. +    g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  561. +    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
  562. +
  563. +    LaunchInteractiveProcess();
  564. +
  565. +    (void)WaitForSingleObject(g_ServiceStopEvent, INFINITE);
  566. +
  567. +    g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  568. +    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
  569. +    (void)CloseHandle(g_ServiceStopEvent);
  570. +}
  571. +
  572. +static
  573. +void SetupTemporaryServiceName(void)
  574. +{
  575. +    FILETIME ft;
  576. +    SYSTEMTIME st;
  577. +
  578. +    /*
  579. +     * Create service name for our temporary service
  580. +     *
  581. +     * Naming requirements:
  582. +     * - unique name
  583. +     * - includes the word "temporary" to give Admins a hint
  584. +     * what we are doing
  585. +     */
  586. +    GetSystemTimePreciseAsFileTime(&ft);
  587. +    (void)FileTimeToSystemTime(&ft, &st);
  588. +    ULONGLONG ullTime =
  589. +        (ULONGLONG)(ft.dwHighDateTime) << 32 | ft.dwLowDateTime;
  590. +    ULONGLONG nanoseconds = (ullTime % 10000000ULL) * 100ULL;
  591. +
  592. +    /* "RunAsSYSTEM_temporary_service0001_<yyyy-dd-mm_hhmmss.ns>" */
  593. +    (void)swprintf(service_name_buffer, sizeof(service_name_buffer),
  594. +        L"RunAsSYSTEM_%stemporary_service001_%04d%02d%02d_%02d%02d%02d.%09llu",
  595. +        "", /* site-prefix */
  596. +        (int)st.wYear, (int)st.wMonth, (int)st.wDay,
  597. +        (int)st.wHour, (int)st.wMinute, (int)st.wSecond,
  598. +        (unsigned long long)nanoseconds);
  599. +}
  600. +
  601. +static
  602. +bool InstallService(int argc, wchar_t *argv[])
  603. +{
  604. +    bool retval = false;
  605. +    wchar_t szPath[MAX_PATH+1];
  606. +    wchar_t szPathWithArg[16384];
  607. +    wchar_t *s;
  608. +    SC_HANDLE hSCManager;
  609. +
  610. +    hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  611. +    if (!hSCManager) {
  612. +        ReportError("OpenSCManager");
  613. +        return false;
  614. +    }
  615. +
  616. +    /* Get our *.exe name */
  617. +    if (GetModuleFileNameW(NULL, szPath, MAX_PATH) == 0) {
  618. +        ReportError("GetModuleFileNameW");
  619. +        retval = false;
  620. +        goto done;
  621. +    }
  622. +
  623. +    /* Manually construct the path with the argument for the service */
  624. +    s = szPathWithArg;
  625. +    s += swprintf(s, 1024, L"\"%ls\" --service %ls",
  626. +        szPath, service_name_buffer);
  627. +    int i;
  628. +    for (i=1 ; i < argc ; i++) {
  629. +        /* FIXME: Quoting */
  630. +        s += swprintf(s, 1024, L" \"%ls\"", argv[i]);
  631. +    }
  632. +
  633. +    /* Print arguments */
  634. +    D((void)wprintf(L"szPathWithArg='%ls'\n", szPathWithArg));
  635. +
  636. +    /*
  637. +     * FIXME: We should implement -u and -g to define username and primary
  638. +     * group name
  639. +     */
  640. +    SC_HANDLE hService = CreateServiceW(hSCManager,
  641. +        service_name_buffer, SERVICE_DISPLAY_NAME, SERVICE_ALL_ACCESS,
  642. +        SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
  643. +        szPathWithArg, NULL, NULL, NULL, L"NT AUTHORITY\\SYSTEM", NULL);
  644. +    if (!hService) {
  645. +        ReportError("CreateServiceW");
  646. +        retval = false;
  647. +        goto done;
  648. +    }
  649. +
  650. +    D((void)wprintf(L"Service '%ls' created successfully.\n",
  651. +        service_name_buffer));
  652. +    if (!StartServiceW(hService, 0, NULL)) {
  653. +        ReportError("StartServiceW");
  654. +        retval = false;
  655. +        goto done;
  656. +    }
  657. +
  658. +    D((void)wprintf(L"Service '%ls' started successfully.\n",
  659. +        service_name_buffer));
  660. +
  661. +    /* Wait until *_status file appears  */
  662. +    char namebuff[256];
  663. +    (void)snprintf(namebuff, sizeof(namebuff),
  664. +        "C:\\Windows\\Temp\\%ls_status",
  665. +        service_name_buffer);
  666. +    while (_access(namebuff, 00) != 0) {
  667. +        /*
  668. +         * FIXME: We should have a timeout, test for <CTRL-C>, and decrease
  669. +         * the threads priority while polling (to avoid starving the child
  670. +         * process)
  671. +         */
  672. +        Sleep(200);
  673. +    }
  674. +
  675. +    (void)CloseServiceHandle(hService);
  676. +
  677. +    /* Success! */
  678. +    retval = true;
  679. +
  680. +done:
  681. +    (void)CloseServiceHandle(hSCManager);
  682. +    return retval;
  683. +}
  684. +
  685. +static
  686. +void UninstallService(void)
  687. +{
  688. +    SC_HANDLE hSCManager;
  689. +    SERVICE_STATUS status;
  690. +
  691. +    hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  692. +    if (!hSCManager) {
  693. +        ReportError("UninstallService: OpenSCManager");
  694. +        return;
  695. +    }
  696. +
  697. +    SC_HANDLE hService = OpenServiceW(hSCManager,
  698. +        service_name_buffer, SERVICE_ALL_ACCESS);
  699. +    if (!hService) {
  700. +        ReportError("UninstallService: OpenServiceW");
  701. +        goto done;
  702. +    }
  703. +
  704. +    (void)ControlService(hService, SERVICE_CONTROL_STOP, &status);
  705. +    D((void)wprintf(L"Service stopped.\n"));
  706. +
  707. +    if (!DeleteService(hService)) {
  708. +        ReportError("UninstallService: DeleteService");
  709. +    } else {
  710. +        D((void)wprintf(L"UninstallService: Service deleted.\n"));
  711. +    }
  712. +
  713. +    (void)CloseServiceHandle(hService);
  714. +
  715. +done:
  716. +    (void)CloseServiceHandle(hSCManager);
  717. +}
  718. +
  719. +static
  720. +void usage(const wchar_t *av0)
  721. +{
  722. +    (void)fwprintf(stderr,
  723. +        L"%ls: Run command as user SYSTEM\n",
  724. +        av0);
  725. +}
  726. +
  727. +int wmain(int argc, wchar_t *argv[])
  728. +{
  729. +    int retval = EXIT_FAILURE;
  730. +
  731. +    if ((argc == 1) ||
  732. +        ((argc == 2) &&
  733. +            ((wcscmp(argv[1], L"--help") == 0) ||
  734. +            (wcscmp(argv[1], L"-h") == 0) ||
  735. +            (wcscmp(argv[1], L"/?") == 0)))) {
  736. +        usage(argv[0]);
  737. +        return EXIT_USAGE;
  738. +    }
  739. +
  740. +    /*
  741. +     * If started with "--service", run as a service
  742. +     */
  743. +    if ((argc > 2) && (wcscmp(argv[1], L"--service") == 0)) {
  744. +        service_argc = argc;
  745. +        service_argv = argv;
  746. +
  747. +        SERVICE_TABLE_ENTRYW ServiceTable[] = {
  748. +            { .lpServiceName = argv[2], .lpServiceProc = ServiceMain },
  749. +            { .lpServiceName = NULL,    .lpServiceProc = NULL }
  750. +        };
  751. +
  752. +        if (!StartServiceCtrlDispatcherW(ServiceTable)) {
  753. +            ReportError("StartServiceCtrlDispatcherW");
  754. +            return 1;
  755. +        }
  756. +        return 0;
  757. +    }
  758. +
  759. +    /* Otherwise, run as the client to manage the service */
  760. +    D((void)wprintf(L"Running as client to install and start the service...\n"));
  761. +
  762. +    SetupTemporaryServiceName();
  763. +
  764. +    /* Remove old status file */
  765. +    (void)remove_fmt("C:\\Windows\\Temp\\%ls_status", service_name_buffer);
  766. +
  767. +    /* Install and Start */
  768. +    if (InstallService(argc, argv)) {
  769. +        /* Stop and Uninstall */
  770. +        UninstallService();
  771. +
  772. +        (void)system_fmt("C:\\cygwin64\\bin\\bash.exe -c "
  773. +            "'cat \"/cygdrive/c/Windows/Temp/%ls_stderr\" 1>&2'",
  774. +            service_name_buffer);
  775. +        (void)system_fmt("C:\\cygwin64\\bin\\bash.exe -c "
  776. +            "'cat \"/cygdrive/c/Windows/Temp/%ls_stdout\"'",
  777. +            service_name_buffer);
  778. +        (void)system_fmt("C:\\cygwin64\\bin\\bash.exe -c "
  779. +            "'printf \"# Child status %%d.\\\\n\" "
  780. +            "\"$( <\"/cygdrive/c/Windows/Temp/%ls_status\" )\" 1>&2'",
  781. +            service_name_buffer);
  782. +        (void)remove_fmt("C:\\Windows\\Temp\\%ls_stdout", service_name_buffer);
  783. +        (void)remove_fmt("C:\\Windows\\Temp\\%ls_stderr", service_name_buffer);
  784. +        (void)remove_fmt("C:\\Windows\\Temp\\%ls_status", service_name_buffer);
  785. +
  786. +        retval = EXIT_SUCCESS;
  787. +    }
  788. +
  789. +    return retval;
  790. +}
  791. --
  792. 2.45.1
  793.  
  794. From a9a8ff080a96199f51e827e2b26fcab04e60301f Mon Sep 17 00:00:00 2001
  795. From: Roland Mainz <roland.mainz@nrubsig.org>
  796. Date: Tue, 26 Aug 2025 15:05:26 +0200
  797. Subject: [PATCH 3/4] mount: nfs_mount.exe --usage should return exit code 2
  798.  per UNIX tradition
  799.  
  800. nfs_mount.exe --usage should return exit code 2 per UNIX tradition.
  801.  
  802. Reported-by: Aurelien Couderc <aurelien.couderc2002@gmail.com>
  803. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  804. ---
  805. mount/mount.c | 23 ++++++++++++++++-------
  806.  1 file changed, 16 insertions(+), 7 deletions(-)
  807.  
  808. diff --git a/mount/mount.c b/mount/mount.c
  809. index 5fd1dda..8afb199 100644
  810. --- a/mount/mount.c
  811. +++ b/mount/mount.c
  812. @@ -50,6 +50,8 @@
  813.   */
  814.  #include "git_version.h"
  815.  
  816. +#define EXIT_USAGE (2) /* Traditional UNIX exit code for usage */
  817. +
  818.  /*
  819.   * Disable "warning C4996: 'wcscpy': This function or variable may be
  820.   * unsafe." because in this case the buffers are properly sized,
  821. @@ -249,7 +251,7 @@ int mount_main(int argc, wchar_t *argv[])
  822.              if ((!wcscmp(argv[i], L"-h")) ||
  823.                  (!wcscmp(argv[i], L"--help"))) {
  824.                  PrintMountUsage(argv[0]);
  825. -                result = 1;
  826. +                result = ERROR_INVALID_COMMAND_LINE;
  827.                  goto out;
  828.              }
  829.              /* print version info */
  830. @@ -425,7 +427,7 @@ opt_o_argv_i_again:
  831.          /* Windows-style "nfs_mount /?" help */
  832.          else if (!wcscmp(argv[i], L"/?")) {
  833.              PrintMountUsage(argv[0]);
  834. -            result = 1;
  835. +            result = ERROR_INVALID_COMMAND_LINE;
  836.              goto out;
  837.         }
  838.          /* drive letter */
  839. @@ -532,7 +534,7 @@ int umount_main(int argc, wchar_t *argv[])
  840.              if ((!wcscmp(argv[i], L"-h")) ||
  841.                  (!wcscmp(argv[i], L"--help"))) {
  842.                  PrintUmountUsage(argv[0]);
  843. -                result = 1;
  844. +                result = ERROR_INVALID_COMMAND_LINE;
  845.                  goto out;
  846.              }
  847.              /* print version info */
  848. @@ -556,7 +558,7 @@ int umount_main(int argc, wchar_t *argv[])
  849.          /* Windows-style "nfs_umount /?" help */
  850.          else if (!wcscmp(argv[i], L"/?")) {
  851.              PrintUmountUsage(argv[0]);
  852. -            result = 1;
  853. +            result = ERROR_INVALID_COMMAND_LINE;
  854.              goto out;
  855.         }
  856.          /* drive letter */
  857. @@ -573,7 +575,6 @@ int umount_main(int argc, wchar_t *argv[])
  858.      if (pLocalName == NULL) {
  859.          result = ERROR_BAD_ARGUMENTS;
  860.          (void)fwprintf(stderr, L"Drive letter expected.\n");
  861. -        PrintUmountUsage(argv[0]);
  862.          goto out;
  863.      }
  864.  
  865. @@ -702,9 +703,17 @@ int __cdecl wmain(int argc, wchar_t *argv[])
  866.  out:
  867.      /*
  868.       * POSIX return value of a command can only in the range from
  869. -     * |0|...|SCHAR_MAX|, so map the |ERROR_*| to |1|,|0|.
  870. +     * |0|...|SCHAR_MAX|, so map the |ERROR_*| to { |2|,|1|,|0| }.
  871.       */
  872. -    return (result != NO_ERROR)?1:0;
  873. +    if (result == ERROR_INVALID_COMMAND_LINE) {
  874. +        return EXIT_USAGE;
  875. +    }
  876. +    else if (result != NO_ERROR) {
  877. +        return EXIT_FAILURE;
  878. +    }
  879. +    else {
  880. +        return EXIT_SUCCESS;
  881. +    }
  882.  }
  883.  
  884.  
  885. --
  886. 2.45.1
  887.  
  888. From 21330b3cbcc1008840bea0d7eb915d4d1f9ce854 Mon Sep 17 00:00:00 2001
  889. From: Roland Mainz <roland.mainz@nrubsig.org>
  890. Date: Tue, 26 Aug 2025 15:10:00 +0200
  891. Subject: [PATCH 4/4] tests: Add comment about |EXIT_USAGE| being an UNIX
  892.  tradition
  893.  
  894. Add comment about |EXIT_USAGE| being an UNIX tradition.
  895.  
  896. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  897. ---
  898. tests/filemmaptests/qsortonmmapedfile1.c      | 2 +-
  899.  tests/lssparse/lssparse.c                     | 2 +-
  900.  tests/winclonefile/winclonefile.c             | 2 +-
  901.  tests/winoffloadcopyfile/winoffloadcopyfile.c | 2 +-
  902.  4 files changed, 4 insertions(+), 4 deletions(-)
  903.  
  904. diff --git a/tests/filemmaptests/qsortonmmapedfile1.c b/tests/filemmaptests/qsortonmmapedfile1.c
  905. index 976c325..31c5da8 100644
  906. --- a/tests/filemmaptests/qsortonmmapedfile1.c
  907. +++ b/tests/filemmaptests/qsortonmmapedfile1.c
  908. @@ -61,7 +61,7 @@
  909.  #include <stdlib.h>
  910.  #include <string.h>
  911.  
  912. -#define EXIT_USAGE 2
  913. +#define EXIT_USAGE (2) /* Traditional UNIX exit code for usage */
  914.  
  915.  #define RECORD_DATA_SIZE 15
  916.  #define RECORD_SIZE (RECORD_DATA_SIZE+1)
  917. diff --git a/tests/lssparse/lssparse.c b/tests/lssparse/lssparse.c
  918. index ae1c73e..5c56a4d 100644
  919. --- a/tests/lssparse/lssparse.c
  920. +++ b/tests/lssparse/lssparse.c
  921. @@ -41,7 +41,7 @@
  922.  #include <unistd.h>
  923.  #include <errno.h>
  924.  
  925. -#define        EXIT_USAGE      (2)
  926. +#define EXIT_USAGE     (2) /* Traditional UNIX exit code for usage */
  927.  
  928.  static
  929.  void
  930. diff --git a/tests/winclonefile/winclonefile.c b/tests/winclonefile/winclonefile.c
  931. index c79672d..80bf35a 100644
  932. --- a/tests/winclonefile/winclonefile.c
  933. +++ b/tests/winclonefile/winclonefile.c
  934. @@ -35,7 +35,7 @@
  935.  #include <winioctl.h>
  936.  #include <stdio.h>
  937.  
  938. -#define EXIT_USAGE (2)
  939. +#define EXIT_USAGE (2) /* Traditional UNIX exit code for usage */
  940.  
  941.  #ifdef DUPLICATE_EXTENTS_DATA_EX_SOURCE_ATOMIC
  942.  /*
  943. diff --git a/tests/winoffloadcopyfile/winoffloadcopyfile.c b/tests/winoffloadcopyfile/winoffloadcopyfile.c
  944. index db1a209..5669140 100644
  945. --- a/tests/winoffloadcopyfile/winoffloadcopyfile.c
  946. +++ b/tests/winoffloadcopyfile/winoffloadcopyfile.c
  947. @@ -35,7 +35,7 @@
  948.  #include <winioctl.h>
  949.  #include <stdio.h>
  950.  
  951. -#define EXIT_USAGE (2)
  952. +#define EXIT_USAGE (2) /* Traditional UNIX exit code for usage */
  953.  
  954.  /* MinGW headers are currently missing these defines and types */
  955.  #ifndef OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE
  956. --
  957. 2.45.1

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.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at