Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
January 2022
- 86 participants
- 2418 messages
[PATCH v4 02/10] loader: Refactor number parsing to own function.
by Jinoh Kang
Improve readability of WINEPRELOADRESERVE parsing code, and also make
the parser available for other purposes in future patches.
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
Notes:
v3 -> v4:
- document parse_ul() function
- don't remove constness of preload_reserve() argument
loader/preloader.c | 62 ++++++++++++++++++++++++++++++++++------------
1 file changed, 46 insertions(+), 16 deletions(-)
diff --git a/loader/preloader.c b/loader/preloader.c
index 73df8b591f0..c23f1f087b5 100644
--- a/loader/preloader.c
+++ b/loader/preloader.c
@@ -68,6 +68,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -719,6 +720,42 @@ static inline void *wld_memmove( void *dest, const void *src, size_t len )
return dest;
}
+/*
+ * parse_ul - parse an unsigned long number with given radix
+ *
+ * Differences from strtoul():
+ * - Does not support radix prefixes ("0x", etc)
+ * - Does not saturate to ULONG_MAX on overflow, wrap around instead
+ * - Indicates overflow via output argument, not errno
+ */
+static inline unsigned long parse_ul( const char *nptr, char **endptr, unsigned int radix, int *overflow )
+{
+ const char *p = nptr;
+ unsigned long value, thresh;
+ int ovfl = 0;
+
+ value = 0;
+ thresh = ULONG_MAX / radix;
+ for (;;)
+ {
+ unsigned int digit;
+ if (*p >= '0' && *p <= '9') digit = *p - '0';
+ else if (*p >= 'a' && *p <= 'z') digit = *p - 'a' + 10;
+ else if (*p >= 'A' && *p <= 'Z') digit = *p - 'A' + 10;
+ else break;
+ if (digit >= radix) break;
+ if (value > thresh) ovfl = 1;
+ value *= radix;
+ if (value > value + digit) ovfl = 1;
+ value += digit;
+ p++;
+ }
+
+ if (endptr) *endptr = (char *)p;
+ if (overflow) *overflow = ovfl;
+ return value;
+}
+
/*
* wld_printf - just the basics
*
@@ -1385,27 +1422,20 @@ found:
*/
static void preload_reserve( const char *str )
{
- const char *p;
+ char *p = (char *)str;
unsigned long result = 0;
void *start = NULL, *end = NULL;
- int i, first = 1;
+ int i;
- for (p = str; *p; p++)
+ result = parse_ul( p, &p, 16, NULL );
+ if (*p == '-')
{
- if (*p >= '0' && *p <= '9') result = result * 16 + *p - '0';
- else if (*p >= 'a' && *p <= 'f') result = result * 16 + *p - 'a' + 10;
- else if (*p >= 'A' && *p <= 'F') result = result * 16 + *p - 'A' + 10;
- else if (*p == '-')
- {
- if (!first) goto error;
- start = (void *)(result & ~page_mask);
- result = 0;
- first = 0;
- }
- else goto error;
+ start = (void *)(result & ~page_mask);
+ result = parse_ul( p + 1, &p, 16, NULL );
+ if (*p) goto error;
+ end = (void *)((result + page_mask) & ~page_mask);
}
- if (!first) end = (void *)((result + page_mask) & ~page_mask);
- else if (result) goto error; /* single value '0' is allowed */
+ else if (*p || result) goto error; /* single value '0' is allowed */
/* sanity checks */
if (end <= start) start = end = NULL;
--
2.34.1
Jan. 28, 2022
[PATCH v4 01/10] loader: Refactor argv/envp/auxv management.
by Jinoh Kang
Collect scattered variables holding stack addresses (e.g. pargc, argv,
envp, auxv) in one place.
This facilitates modifying stack values (e.g. removing argv[0],
switching stacks due to address conflict with reserved regions) without
leaving pointer variables stale.
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
Notes:
v1 -> v2:
- Zero argc slot before writing to it
- s/stackargs_eat_args/stackargs_shift_args/
- s/shift_stackargs/stackargs_switch_stack/
- s/offset/delta/
- slightly change auxv append logic to match the original closer
v3 -> v4:
- add comments
loader/preloader.c | 269 +++++++++++++++++++++++++++++++++------------
1 file changed, 199 insertions(+), 70 deletions(-)
diff --git a/loader/preloader.c b/loader/preloader.c
index 585be50624f..73df8b591f0 100644
--- a/loader/preloader.c
+++ b/loader/preloader.c
@@ -164,6 +164,25 @@ struct wld_auxv
} a_un;
};
+/* Aggregates information about initial program stack and variables
+ * (e.g. argv and envp) that reside in it.
+ */
+struct stackarg_info
+{
+ void *stack;
+ int argc;
+ char **argv;
+ char **envp;
+ struct wld_auxv *auxv;
+ struct wld_auxv *auxv_end;
+};
+
+/* Currently only contains the main stackarg_info. */
+struct preloader_state
+{
+ struct stackarg_info s;
+};
+
/*
* The __bb_init_func is an empty function only called when file is
* compiled with gcc flags "-fprofile-arcs -ftest-coverage". This
@@ -674,6 +693,32 @@ static inline void *wld_memset( void *dest, int val, size_t len )
return dest;
}
+static size_t wld_strlen( const char *str )
+{
+ const char *ptr = str;
+ while (*ptr) ptr++;
+ return ptr - str;
+}
+
+static inline void *wld_memmove( void *dest, const void *src, size_t len )
+{
+ unsigned char *destp = dest;
+ const unsigned char *srcp = src;
+
+ if ((unsigned long)dest - (unsigned long)src < len)
+ {
+ destp += len;
+ srcp += len;
+ while (len--) *--destp = *--srcp;
+ }
+ else
+ {
+ while (len--) *destp++ = *srcp++;
+ }
+
+ return dest;
+}
+
/*
* wld_printf - just the basics
*
@@ -794,72 +839,167 @@ static void dump_auxiliary( struct wld_auxv *av )
}
#endif
+/*
+ * parse_stackargs
+ *
+ * parse out the initial stack for argv, envp, and etc., and store the
+ * information into the given stackarg_info structure.
+ */
+static void parse_stackargs( struct stackarg_info *outinfo, void *stack )
+{
+ int argc;
+ char **argv, **envp, **env_end;
+ struct wld_auxv *auxv, *auxv_end;
+
+ argc = *(int *)stack;
+ argv = (char **)stack + 1;
+ envp = argv + (unsigned int)argc + 1;
+
+ env_end = envp;
+ while (*env_end++)
+ ;
+ auxv = (struct wld_auxv *)env_end;
+
+ auxv_end = auxv;
+ while ((auxv_end++)->a_type != AT_NULL)
+ ;
+
+ outinfo->stack = stack;
+ outinfo->argc = argc;
+ outinfo->argv = argv;
+ outinfo->envp = envp;
+ outinfo->auxv = auxv;
+ outinfo->auxv_end = auxv_end;
+}
+
+/*
+ * stackargs_getenv
+ *
+ * Retrieve the value of an environment variable from stackarg_info.
+ */
+static char *stackargs_getenv( const struct stackarg_info *info, const char *name )
+{
+ char **envp = info->envp;
+ size_t namelen = wld_strlen( name );
+
+ while (*envp)
+ {
+ if (wld_strncmp( *envp, name, namelen ) == 0 &&
+ (*envp)[namelen] == '=') return *envp + namelen + 1;
+ envp++;
+ }
+ return NULL;
+}
+
+/*
+ * stackargs_shift_args
+ *
+ * Remove the specific number of arguments from the start of argv.
+ */
+static void stackargs_shift_args( struct stackarg_info *info, int num_args )
+{
+ info->stack = (char **)info->stack + num_args;
+ info->argc -= num_args;
+ info->argv = (char **)info->stack + 1;
+
+ wld_memset( info->stack, 0, sizeof(char *) );
+ /* Don't coalesce zeroing and setting argc -- we *might* support big endian in the future */
+ *(int *)info->stack = info->argc;
+}
+
+/*
+ * stackargs_switch_stack
+ *
+ * Fix up variables in oldinfo to the given stack base, and return
+ * the new information to newinfo (does not modify oldinfo).
+ */
+static void stackargs_switch_stack( struct stackarg_info *newinfo, struct stackarg_info *oldinfo, void *newstack )
+{
+ unsigned long delta = (unsigned long)newstack - (unsigned long)oldinfo->stack;
+
+ /* NOTE it is legal that newinfo == oldinfo */
+ newinfo->stack = newstack;
+ newinfo->argc = oldinfo->argc;
+ newinfo->argv = (void *)((unsigned long)oldinfo->argv + delta);
+ newinfo->envp = (void *)((unsigned long)oldinfo->envp + delta);
+ newinfo->auxv = (void *)((unsigned long)oldinfo->auxv + delta);
+ newinfo->auxv_end = (void *)((unsigned long)oldinfo->auxv_end + delta);
+}
+
/*
* set_auxiliary_values
*
* Set the new auxiliary values
*/
-static void set_auxiliary_values( struct wld_auxv *av, const struct wld_auxv *new_av,
- const struct wld_auxv *delete_av, void **stack )
+static void set_auxiliary_values( struct preloader_state *state,
+ const struct wld_auxv *new_av,
+ const struct wld_auxv *delete_av )
{
- int i, j, av_count = 0, new_count = 0, delete_count = 0;
- char *src, *dst;
-
- /* count how many aux values we have already */
- while (av[av_count].a_type != AT_NULL) av_count++;
+ size_t i, new_count = 0, delete_count = 0;
+ unsigned long dst;
+ struct wld_auxv *avpd, *avps, *avp;
+ int is_deleted;
/* delete unwanted values */
- for (j = 0; delete_av[j].a_type != AT_NULL; j++)
+ for (avps = avpd = state->s.auxv; avps + 1 != state->s.auxv_end; avps++)
{
- for (i = 0; i < av_count; i++) if (av[i].a_type == delete_av[j].a_type)
+ is_deleted = 0;
+ for (i = 0; delete_av[i].a_type != AT_NULL; i++)
+ {
+ if (avps->a_type == new_av[i].a_type)
+ {
+ is_deleted = 1;
+ break;
+ }
+ }
+ if (is_deleted)
{
- av[i].a_type = av[av_count-1].a_type;
- av[i].a_un.a_val = av[av_count-1].a_un.a_val;
- av[--av_count].a_type = AT_NULL;
delete_count++;
- break;
+ continue;
}
+ if (avpd != avps)
+ {
+ avpd->a_type = avps->a_type;
+ avpd->a_un.a_val = avps->a_un.a_val;
+ }
+ avpd++;
}
+ avpd->a_type = AT_NULL;
+ avpd->a_un.a_val = 0;
+ state->s.auxv_end = avpd + 1;
/* count how many values we have in new_av that aren't in av */
- for (j = 0; new_av[j].a_type != AT_NULL; j++)
+ for (i = 0; new_av[i].a_type != AT_NULL; i++)
{
- for (i = 0; i < av_count; i++) if (av[i].a_type == new_av[j].a_type) break;
- if (i == av_count) new_count++;
+ for (avp = state->s.auxv; avp + 1 != state->s.auxv_end; avp++) if (avp->a_type == new_av[i].a_type) break;
+ if (avp + 1 == state->s.auxv_end) new_count++;
}
- src = (char *)*stack;
- dst = src - (new_count - delete_count) * sizeof(*av);
- dst = (char *)((unsigned long)dst & ~15);
- if (dst < src) /* need to make room for the extra values */
- {
- int len = (char *)(av + av_count + 1) - src;
- for (i = 0; i < len; i++) dst[i] = src[i];
- }
- else if (dst > src) /* get rid of unused values */
- {
- int len = (char *)(av + av_count + 1) - src;
- for (i = len - 1; i >= 0; i--) dst[i] = src[i];
- }
- *stack = dst;
- av = (struct wld_auxv *)((char *)av + (dst - src));
+ dst = ((unsigned long)state->s.stack -
+ (new_count - delete_count) * sizeof(struct wld_auxv)) & ~15;
+ wld_memmove( (void *)dst, state->s.stack,
+ (unsigned long)state->s.auxv_end -
+ (unsigned long)state->s.stack );
+ stackargs_switch_stack( &state->s, &state->s, (void *)dst );
/* now set the values */
- for (j = 0; new_av[j].a_type != AT_NULL; j++)
+ for (i = 0; new_av[i].a_type != AT_NULL; i++)
{
- for (i = 0; i < av_count; i++) if (av[i].a_type == new_av[j].a_type) break;
- if (i < av_count) av[i].a_un.a_val = new_av[j].a_un.a_val;
+ for (avp = state->s.auxv; avp + 1 != state->s.auxv_end; avp++) if (avp->a_type == new_av[i].a_type) break;
+ if (avp + 1 != state->s.auxv_end) avp->a_un.a_val = new_av[i].a_un.a_val;
else
{
- av[av_count].a_type = new_av[j].a_type;
- av[av_count].a_un.a_val = new_av[j].a_un.a_val;
- av_count++;
+ avp->a_type = new_av[i].a_type;
+ avp->a_un.a_val = new_av[i].a_un.a_val;
+ state->s.auxv_end++;
}
}
+ state->s.auxv_end[-1].a_type = AT_NULL;
+ state->s.auxv_end[-1].a_un.a_val = 0;
#ifdef DUMP_AUX_INFO
wld_printf("New auxiliary info:\n");
- dump_auxiliary( av );
+ dump_auxiliary( state->s.auxv );
#endif
}
@@ -1369,47 +1509,36 @@ static void set_process_name( int argc, char *argv[] )
*/
void* wld_start( void **stack )
{
- long i, *pargc;
- char **argv, **p;
- char *interp, *reserve = NULL;
- struct wld_auxv new_av[8], delete_av[3], *av;
+ long i;
+ char *interp, *reserve;
+ struct wld_auxv new_av[8], delete_av[3];
struct wld_link_map main_binary_map, ld_so_map;
struct wine_preload_info **wine_main_preload_info;
+ struct preloader_state state = { 0 };
- pargc = *stack;
- argv = (char **)pargc + 1;
- if (*pargc < 2) fatal_error( "Usage: %s wine_binary [args]\n", argv[0] );
+ parse_stackargs( &state.s, *stack );
- /* skip over the parameters */
- p = argv + *pargc + 1;
+ if (state.s.argc < 2) fatal_error( "Usage: %s wine_binary [args]\n", state.s.argv[0] );
- /* skip over the environment */
- while (*p)
- {
- static const char res[] = "WINEPRELOADRESERVE=";
- if (!wld_strncmp( *p, res, sizeof(res)-1 )) reserve = *p + sizeof(res) - 1;
- p++;
- }
-
- av = (struct wld_auxv *)(p+1);
- page_size = get_auxiliary( av, AT_PAGESZ, 4096 );
+ page_size = get_auxiliary( state.s.auxv, AT_PAGESZ, 4096 );
page_mask = page_size - 1;
preloader_start = (char *)_start - ((unsigned long)_start & page_mask);
preloader_end = (char *)((unsigned long)(_end + page_mask) & ~page_mask);
#ifdef DUMP_AUX_INFO
- wld_printf( "stack = %p\n", *stack );
- for( i = 0; i < *pargc; i++ ) wld_printf("argv[%lx] = %s\n", i, argv[i]);
- dump_auxiliary( av );
+ wld_printf( "stack = %p\n", state.s.stack );
+ for( i = 0; i < state.s.argc; i++ ) wld_printf("argv[%lx] = %s\n", i, state.s.argv[i]);
+ dump_auxiliary( state.s.auxv );
#endif
/* reserve memory that Wine needs */
+ reserve = stackargs_getenv( &state.s, "WINEPRELOADRESERVE" );
if (reserve) preload_reserve( reserve );
for (i = 0; preload_info[i].size; i++)
{
- if ((char *)av >= (char *)preload_info[i].addr &&
- (char *)pargc <= (char *)preload_info[i].addr + preload_info[i].size)
+ if ((char *)state.s.auxv >= (char *)preload_info[i].addr &&
+ (char *)state.s.stack <= (char *)preload_info[i].addr + preload_info[i].size)
{
remove_preload_range( i );
i--;
@@ -1436,7 +1565,7 @@ void* wld_start( void **stack )
wld_mprotect( (char *)0x80000000 - page_size, page_size, PROT_EXEC | PROT_READ );
/* load the main binary */
- map_so_lib( argv[1], &main_binary_map );
+ map_so_lib( state.s.argv[1], &main_binary_map );
/* load the ELF interpreter */
interp = (char *)main_binary_map.l_addr + main_binary_map.l_interp;
@@ -1453,14 +1582,14 @@ void* wld_start( void **stack )
SET_NEW_AV( 2, AT_PHNUM, main_binary_map.l_phnum );
SET_NEW_AV( 3, AT_PAGESZ, page_size );
SET_NEW_AV( 4, AT_BASE, ld_so_map.l_addr );
- SET_NEW_AV( 5, AT_FLAGS, get_auxiliary( av, AT_FLAGS, 0 ) );
+ SET_NEW_AV( 5, AT_FLAGS, get_auxiliary( state.s.auxv, AT_FLAGS, 0 ) );
SET_NEW_AV( 6, AT_ENTRY, main_binary_map.l_entry );
SET_NEW_AV( 7, AT_NULL, 0 );
#undef SET_NEW_AV
i = 0;
/* delete sysinfo values if addresses conflict */
- if (is_in_preload_range( av, AT_SYSINFO ) || is_in_preload_range( av, AT_SYSINFO_EHDR ))
+ if (is_in_preload_range( state.s.auxv, AT_SYSINFO ) || is_in_preload_range( state.s.auxv, AT_SYSINFO_EHDR ))
{
delete_av[i++].a_type = AT_SYSINFO;
delete_av[i++].a_type = AT_SYSINFO_EHDR;
@@ -1468,14 +1597,13 @@ void* wld_start( void **stack )
delete_av[i].a_type = AT_NULL;
/* get rid of first argument */
- set_process_name( *pargc, argv );
- pargc[1] = pargc[0] - 1;
- *stack = pargc + 1;
+ set_process_name( state.s.argc, state.s.argv );
+ stackargs_shift_args( &state.s, 1 );
- set_auxiliary_values( av, new_av, delete_av, stack );
+ set_auxiliary_values( &state, new_av, delete_av );
#ifdef DUMP_AUX_INFO
- wld_printf("new stack = %p\n", *stack);
+ wld_printf("new stack = %p\n", state.s.stack);
wld_printf("jumping to %p\n", (void *)ld_so_map.l_entry);
#endif
#ifdef DUMP_MAPS
@@ -1490,6 +1618,7 @@ void* wld_start( void **stack )
}
#endif
+ *stack = state.s.stack;
return (void *)ld_so_map.l_entry;
}
--
2.34.1
Jan. 28, 2022
[PATCH v4 00/10] Avoid performance degradation due to vDSO unmapping (#52313)
by Jinoh Kang
Commit f558741fabc116534fa598aa890ffed683a7153b removes vDSO if it
conflicts with reserved ranges:
Remove the AT_SYSINFO and AT_SYSINFO_EHDR values if the sysinfo page
is in one of our reserved ranges.
However, missing vDSO leads to performance issues on some syscalls (e.g.
clock_gettime, gettimeofday) and may even lead to crash when run with
some ancient C libraries that does not supply a custom signal restorer.
vDSO pages can clash with reserved ranges especially in a 32-bit address
space with address space layout randomization (ASLR) turned on.
Recent versions of the Linux kernel introduced support for mremap()-ping
vDSO pages, partly in an effort to support checkpoint restore in
userspace (CRIU). Special programs that require specific memory layout
constraints (such as Wine preloader) can take advantage of this support
to modify the address space to meet its requirements.
Changelog:
- v3 -> v4:
- address review comments
- add more comments and documentation
The following test script has been used to test each changes (use with
git rebase --exec=...):
set -e
make -C ../wine64-build -j5
make -C ../wine32-build -j5
cd ../wine64-build
export WINEPRELOADREMAPSTACK
export WINEPRELOADREMAPVDSO
for WINEPRELOADREMAPSTACK in skip never always force auto on-demand ''
do
for WINEPRELOADREMAPVDSO in skip never always force auto on-demand ''
do
./loader/wine64 wineboot
./loader/wine wineboot
done
done
Jinoh Kang (10):
loader: Refactor argv/envp/auxv management.
loader: Refactor number parsing to own function.
loader: Generalise is_addr_reserved to find overlapping address
ranges.
loader: Explicitly munmap() the preloader's ELF EHDR.
loader: Don't clobber existing memory mappings when reserving
addresses.
loader: Fix return type of get_auxiliary().
loader: Relocate vDSO on conflict with reserved ranges.
loader: Relocate sigpage on conflict with reserved ranges in ARM.
loader: Switch stack if the old stack address is in reserved range.
loader: Enable all remap logic by default.
loader/preloader.c | 1523 ++++++++++++++++++++++++++++++++++++++++----
1 file changed, 1407 insertions(+), 116 deletions(-)
--
2.34.1
Jan. 28, 2022
[tools 3/3] testbot/SetWinLocale: Move the intl.cpl code to Powershell.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/SetWinLocale | 103 +++++---------------------
testbot/bin/SetWinLocale.ps1 | 136 +++++++++++++++++++++++++++++++++--
2 files changed, 145 insertions(+), 94 deletions(-)
diff --git a/testbot/bin/SetWinLocale b/testbot/bin/SetWinLocale
index b8908e6a0a..2ff8348fb3 100755
--- a/testbot/bin/SetWinLocale
+++ b/testbot/bin/SetWinLocale
@@ -42,7 +42,6 @@ use WineTestBot::TestAgent;
use WineTestBot::Utils;
my $HKCU_USER_PROFILE = "HKCU\\Control Panel\\International\\User Profile";
-my $HKLM_CODE_PAGE = "HKLM\\System\\CurrentControlSet\\Control\\Nls\\CodePage";
#
@@ -53,6 +52,11 @@ my $name0 = $0;
$name0 =~ s+^.*/++;
+sub Info(@)
+{
+ print STDERR "$name0:info: ", @_;
+}
+
sub Warning(@)
{
print STDERR "$name0:warning: ", @_;
@@ -612,19 +616,6 @@ sub RegGetValue($;$)
return $Values->{defined $VName ? $VName : "(Default)"};
}
-sub RegSetValue($$$$)
-{
- my ($Key, $VName, $Type, $Value) = @_;
-
- my $Cmd = ["reg.exe", "add", $Key, "/f"];
- push @$Cmd, (defined $VName ? ("/v", $VName) : ("/ve"));
- $Value = join("\\0", @$Value) if (ref($Value) eq "ARRAY");
- push @$Cmd, "/t" , $Type, "/d", $Value;
-
- my $Ret = $TA->RunAndWait($Cmd, 0, 10);
- FatalError("@$Cmd failed: ", GetRunError($Ret), "\n") if ($Ret);
-}
-
#
# Show the host's locale settings
@@ -823,84 +814,22 @@ $OptKeyboard ||= $OptDefault;
#
-# Generate the intl.cpl configuration
+# Change the Windows locale
#
-my $CopyToSys = $OptSysCopy ? "true" : "false";
-my $CopyToDef = $OptDefCopy ? "true" : "false";
-my @Config = (
- # intl.cpl does not want single quotes on that one line!
- "<gs:GlobalizationServices xmlns:gs=\"urn:longhornGlobalizationUnattend\">",
- " <gs:UserList>",
- " <gs:User UserID='Current' CopySettingsToDefaultUserAcct='$CopyToDef' CopySettingsToSystemAcct='$CopyToSys'/>",
- " </gs:UserList>",
-);
-if (defined $CountryId)
-{
- push @Config, " <gs:LocationPreferences>",
- " <gs:GeoID Value='$CountryId'/>",
- " </gs:LocationPreferences>";
-}
-if ($OptMUI)
-{
- push @Config, " <gs:MUILanguagePreferences>",
- " <gs:MUILanguage Value='$OptMUI'/>",
- " </gs:MUILanguagePreferences>";
-}
-if ($OptSystem)
-{
- push @Config, " <gs:SystemLocale Name='$OptSystem'/>";
-}
-if ($KeyboardIds)
-{
- push @Config, " <gs:InputPreferences>";
- my $Default = " Default='true'";
- foreach my $Id (@$KeyboardIds)
- {
- push @Config, " <gs:InputLanguageID Action='add' ID='$Id'$Default/>";
- $Default = "";
- }
- push @Config, " </gs:InputPreferences>";
-}
-if ($OptLocale)
-{
- push @Config, " <gs:UserLocale>",
- " <gs:Locale Name='$OptLocale' SetAsCurrent='true' ResetAllSettings='true'>",
- " </gs:Locale>",
- " </gs:UserLocale>";
-}
-push @Config, "</gs:GlobalizationServices>";
-
-
-#
-# Change the Windows locale using intl.cpl
-#
-
-Debug(Elapsed($Start), join("\n", " Sending the configuration file\n$name0.xml:", @Config, ""));
-
-if (!$TA->SendFileFromString(join("\r\n", @Config, ""), "$name0.xml", 0))
-{
- FatalError("could not send the configuration file:", $TA->GetLastError(), "\n");
-}
-
my $Cmd = ["powershell.exe", "-ExecutionPolicy", "ByPass", "-File",
- "$name0.ps1", "locales", "$name0.xml"];
-Debug(Elapsed($Start), " Running ", join(" ", @$Cmd), "\n");
-my $Ret = $TA->RunAndWait($Cmd, 0, 120);
+ "$name0.ps1", "locales", $OptLocale || ".", $CountryId || ".",
+ $OptSystem || ".", $OptUTF8 ? "true" : "false", $OptMUI || ".",
+ $KeyboardIds ? $KeyboardIds->[0] : ".",
+ $OptSysCopy ? "true" : "false", $OptDefCopy ? "true" : "false"];
+Debug(Elapsed($Start), " Running: ", join(" ", @$Cmd), "\n");
+my $Ret = $TA->RunAndWait($Cmd, 0, 30, undef, "$name0.out", "$name0.out");
FatalError("$name0.ps1 locales failed: ", $TA->GetLastError(), "\n") if ($Ret < 0);
-
-
-#
-# Change the code pages manually
-#
-
-if ($OptUTF8)
+my $Out = $TA->GetFileToString("$name0.out");
+foreach my $Line (split /\n/, $Out || "")
{
- # intl.cpl does not support setting a specific code page
- foreach my $VName ("ACP", "MACCP", "OEMCP")
- {
- RegSetValue($HKLM_CODE_PAGE, $VName, "REG_SZ", "65001");
- }
+ $Line =~ s/\r$//;
+ Info("$Line\n");
}
diff --git a/testbot/bin/SetWinLocale.ps1 b/testbot/bin/SetWinLocale.ps1
index b893755ccb..afb60d6ee5 100644
--- a/testbot/bin/SetWinLocale.ps1
+++ b/testbot/bin/SetWinLocale.ps1
@@ -105,13 +105,65 @@ function ShowSettings()
#
-# Modify the Windows locales settings
+# Modify the Windows locales settings through intl.cpl
#
-function SetLocales($Argv)
+function WriteIntlCplConfig([string]$Locale, [string]$CountryId, [string]$System, [string]$MUI, [string]$KeyboardId, [bool]$SysCopy, [bool]$DefCopy)
{
- $XmlFile = $Argv[1]
- $IntlArg = 'intl.cpl,,/f:"' + $XmlFile + '"'
+ # intl.cpl does not want single quotes on that first line!
+ Write-Output '<gs:GlobalizationServices xmlns:gs="urn:longhornGlobalizationUnattend">'
+
+ Write-Output " <gs:UserList>"
+ $CopyToSys = if ($SysCopy) { "true" } else { "false" }
+ $CopyToDef = if ($DefCopy) { "true" } else { "false" }
+ Write-Output " <gs:User UserID='Current' CopySettingsToDefaultUserAcct='$CopyToDef' CopySettingsToSystemAcct='$CopyToSys'/>"
+ Write-Output " </gs:UserList>"
+
+ if ($CountryId)
+ {
+ Write-Output " <gs:LocationPreferences>"
+ Write-Output " <gs:GeoID Value='$CountryId'/>"
+ Write-Output " </gs:LocationPreferences>"
+ }
+
+ # Takes effect on the next log out + log in.
+ if ($MUI)
+ {
+ # Note that specifying something like en-CA instead of en-GB fails here.
+ # See the Set-WinUILanguageOverride comment above.
+ Write-Output " <gs:MUILanguagePreferences>"
+ Write-Output " <gs:MUILanguage Value='$MUI'/>"
+ Write-Output " </gs:MUILanguagePreferences>"
+ }
+
+ # Takes effect on the next reboot.
+ if ($System)
+ {
+ Write-Output " <gs:SystemLocale Name='$System'/>"
+ }
+
+ # Takes effect on the next log out + log in.
+ if ($KeyboardId)
+ {
+ Write-Output " <gs:InputPreferences>"
+ Write-Output " <gs:InputLanguageID Action='add' ID='$KeyboardId' Default='true'/>"
+ Write-Output " </gs:InputPreferences>"
+ }
+
+ if ($Locale)
+ {
+ Write-Output " <gs:UserLocale>"
+ Write-Output " <gs:Locale Name='$Locale' SetAsCurrent='true' ResetAllSettings='true'>"
+ Write-Output " </gs:Locale>"
+ Write-Output " </gs:UserLocale>"
+ }
+
+ Write-Output "</gs:GlobalizationServices>"
+}
+
+function RunIntlCpl($XmlFilename)
+{
+ $IntlArg = 'intl.cpl,,/f:"' + $XmlFilename + '"'
Write-Output "Running: control.exe $IntlArg"
control.exe $IntlArg
# intl.cpl executes asynchronously which means that:
@@ -121,6 +173,64 @@ function SetLocales($Argv)
# be done after intl.cpl is done to avoid races.
# So 'wait' for intl.cpl to be done by introducing an arbitrary pause.
Start-Sleep 2
+}
+
+
+#
+# Modify the Windows locales through Powershell
+#
+
+function SetCodePages($Value)
+{
+ foreach ($CodePage in $CODE_PAGES)
+ {
+ Set-ItemProperty -Path $HKLM_CODE_PAGE -Name $CodePage -Type String -Value $Value
+ }
+}
+
+
+#
+# The locale-change actions
+#
+
+function GetStringArg($Arg)
+{
+ # Treat '.' as equivalent to an empty string for convenience
+ if ($Arg -ne ".") { $Arg } else { "" }
+}
+
+function ShowIntlConfig($Argv)
+{
+ $Locale = GetStringArg($Argv[1])
+ $CountryId = GetStringArg($Argv[2])
+ $System = GetStringArg($Argv[3])
+ # The UTF8 parameter is irrelevant here
+ $MUI = GetStringArg($Argv[5])
+ $KeyboardId = GetStringArg($Argv[6])
+ $SysCopy = $Argv[7] -ne "false"
+ $DefCopy = $Argv[8] -ne "false"
+
+ WriteIntlCplConfig $Locale $CountryId $System $MUI $KeyboardId $SysCopy $DefCopy
+ exit 0
+}
+
+function SetLocales($Argv)
+{
+ $Locale = GetStringArg($Argv[1])
+ $CountryId = GetStringArg($Argv[2])
+ $System = GetStringArg($Argv[3])
+ $UTF8 = $Argv[4] -eq "true"
+ $MUI = GetStringArg($Argv[5])
+ $KeyboardId = GetStringArg($Argv[6])
+ $SysCopy = $Argv[7] -ne "false"
+ $DefCopy = $Argv[8] -ne "false"
+ $UseIntlCpl = $Argv[9] -eq "true"
+
+ WriteIntlCplConfig $Locale $CountryId $System $MUI $KeyboardId $SysCopy $DefCopy >"$Name0.xml"
+ RunIntlCpl "$Name0.xml"
+ Remove-Item -Path "$Name0.xml"
+
+ if ($UTF8) { SetCodePages(65001) }
exit 0
}
@@ -132,20 +242,32 @@ function SetLocales($Argv)
function ShowUsage()
{
Write-Output "Usage: $Name0 settings"
- Write-Output "or $Name0 locales XMLFILE"
+ Write-Output "or $Name0 intlconfig LOCALE COUNTRYID SYSTEM UTF8 MUI KEYBOARDID SYSCOPY DEFCOPY"
+ Write-Output "or $Name0 locales LOCALE COUNTRYID SYSTEM UTF8 MUI KEYBOARDID SYSCOPY DEFCOPY"
Write-Output "or $Name0 -?"
Write-Output ""
Write-Output "Shows or modifies the Windows locales."
Write-Output ""
Write-Output "Where:"
Write-Output " settings Show the current Windows locale settings."
- Write-Output " locales Modifies the locales by passing the $Name0.xml file to intl.cpl."
- Write-Output " XMLFILE The filename of the intl.cpl XML configuration."
+ Write-Output " intlconfig Generates an XML configuration file for intl.cpl."
+ Write-Output " locales Modifies the locales by invoking intl.cpl."
+ Write-Output " LOCALE Is the BCP-47 locale to use for formats, date and time."
+ Write-Output " COUNTRYID Is the numerical country code."
+ Write-Output " SYSTEM Is the BCP-47 locale to use as the system locale."
+ Write-Output " UTF8 If set to 'true' the code pages will be changed to UTF-8."
+ Write-Output " MUI Is the BCP-47 locale to use for the display language."
+ Write-Output " KEYBOARDID Is the keyboard identifier to set as the default."
+ Write-Output " SYSCOPY If 'true' the locale settings will be copied to the system accounts"
+ Write-Output " (such as used for the logon screen). This is the default."
+ Write-Output " DEFCOPY If 'true' the locale settings will be copied to the default account"
+ Write-Output " (for new users). This is the default."
Write-Output " -? Shows this help message."
}
$Action = $args[0]
if ($Action -eq "settings") { ShowSettings }
+if ($Action -eq "intlconfig") { ShowIntlConfig $args }
if ($Action -eq "locales") { SetLocales $args }
$Rc = 0
if ($Action -and $Action -ne "-?" -and $Action -ne "-h" -and $Action -ne "help")
--
2.30.2
Jan. 28, 2022
[tools 2/3] testbot/SetWinLocale: Use the Powershell script to run intl.cpl.
by Francois Gouget
Also use RunAndWait() to simplify the code.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/SetWinLocale | 42 +++++++-----------------------------
testbot/bin/SetWinLocale.ps1 | 29 +++++++++++++++++++++++--
2 files changed, 35 insertions(+), 36 deletions(-)
diff --git a/testbot/bin/SetWinLocale b/testbot/bin/SetWinLocale
index e544a580d3..b8908e6a0a 100755
--- a/testbot/bin/SetWinLocale
+++ b/testbot/bin/SetWinLocale
@@ -79,7 +79,7 @@ sub Cleanup()
}
else
{
- $TA->Rm("$name0.out", "$name0.ps1");
+ $TA->Rm("$name0.out", "$name0.ps1", "$name0.xml");
}
}
@@ -876,44 +876,18 @@ push @Config, "</gs:GlobalizationServices>";
# Change the Windows locale using intl.cpl
#
-Debug(Elapsed($Start), join("\n", " Sending the configuration file\nlocales.xml:", @Config, ""));
+Debug(Elapsed($Start), join("\n", " Sending the configuration file\n$name0.xml:", @Config, ""));
-if (!$TA->SendFileFromString(join("\r\n", @Config, ""), "locales.xml", 0))
+if (!$TA->SendFileFromString(join("\r\n", @Config, ""), "$name0.xml", 0))
{
FatalError("could not send the configuration file:", $TA->GetLastError(), "\n");
}
-# For some reason this only works when run from a batch script!
-Debug(Elapsed($Start), " Sending the batch file\n");
-my $Cmd = 'control.exe intl.cpl,,/f:"locales.xml"';
-if (!$TA->SendFileFromString($Cmd, "script.bat", $TestAgent::SENDFILE_EXE))
-{
- FatalError("could not send the batch file:", $TA->GetLastError(), "\n");
-}
-
-Debug(Elapsed($Start), " Running intl.cpl\n");
-my $Pid = $TA->Run(["./script.bat"], 0);
-if (!$Pid)
-{
- FatalError("failed to run intl.cpl\n");
-}
-
-# Unfortunately the control.exe and/or intl.cpl exit code is unusable so
-# there is no way to check for errors
-Debug(Elapsed($Start), " Waiting for intl.cpl\n");
-if (!defined $TA->Wait($Pid, 120))
-{
- FatalError("could not run intl.cpl: ", $TA->GetLastError(), "\n");
-}
-
-if ($Debug)
-{
- print STDERR "Not deleting script.bat and locales.xml\n";
-}
-else
-{
- $TA->Rm("script.bat", "locales.xml");
-}
+my $Cmd = ["powershell.exe", "-ExecutionPolicy", "ByPass", "-File",
+ "$name0.ps1", "locales", "$name0.xml"];
+Debug(Elapsed($Start), " Running ", join(" ", @$Cmd), "\n");
+my $Ret = $TA->RunAndWait($Cmd, 0, 120);
+FatalError("$name0.ps1 locales failed: ", $TA->GetLastError(), "\n") if ($Ret < 0);
#
diff --git a/testbot/bin/SetWinLocale.ps1 b/testbot/bin/SetWinLocale.ps1
index 702b3301dc..b893755ccb 100644
--- a/testbot/bin/SetWinLocale.ps1
+++ b/testbot/bin/SetWinLocale.ps1
@@ -1,4 +1,4 @@
-# Shows the Windows locale settings
+# Shows or sets the Windows locale settings
#
# Copyright 2022 Francois Gouget
#
@@ -104,6 +104,27 @@ function ShowSettings()
}
+#
+# Modify the Windows locales settings
+#
+
+function SetLocales($Argv)
+{
+ $XmlFile = $Argv[1]
+ $IntlArg = 'intl.cpl,,/f:"' + $XmlFile + '"'
+ Write-Output "Running: control.exe $IntlArg"
+ control.exe $IntlArg
+ # intl.cpl executes asynchronously which means that:
+ # - The exit code cannot be used to check for failures.
+ # - The configuration file should not be removed too early.
+ # - Further locale modifications (e.g. setting the code pages) should only
+ # be done after intl.cpl is done to avoid races.
+ # So 'wait' for intl.cpl to be done by introducing an arbitrary pause.
+ Start-Sleep 2
+ exit 0
+}
+
+
#
# Main
#
@@ -111,17 +132,21 @@ function ShowSettings()
function ShowUsage()
{
Write-Output "Usage: $Name0 settings"
+ Write-Output "or $Name0 locales XMLFILE"
Write-Output "or $Name0 -?"
Write-Output ""
- Write-Output "Shows the Windows locales."
+ Write-Output "Shows or modifies the Windows locales."
Write-Output ""
Write-Output "Where:"
Write-Output " settings Show the current Windows locale settings."
+ Write-Output " locales Modifies the locales by passing the $Name0.xml file to intl.cpl."
+ Write-Output " XMLFILE The filename of the intl.cpl XML configuration."
Write-Output " -? Shows this help message."
}
$Action = $args[0]
if ($Action -eq "settings") { ShowSettings }
+if ($Action -eq "locales") { SetLocales $args }
$Rc = 0
if ($Action -and $Action -ne "-?" -and $Action -ne "-h" -and $Action -ne "help")
{
--
2.30.2
Jan. 28, 2022
[tools 1/3] testbot/SetWinLocale: Add --sys-copy and --def-copy options.
by Francois Gouget
These provide control over copying the new locale to the system and
default user accounts.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/SetWinLocale | 94 ++++++++++++++++++++++++++++++++++++----
1 file changed, 86 insertions(+), 8 deletions(-)
diff --git a/testbot/bin/SetWinLocale b/testbot/bin/SetWinLocale
index fa5f90cdbb..e544a580d3 100755
--- a/testbot/bin/SetWinLocale
+++ b/testbot/bin/SetWinLocale
@@ -310,7 +310,7 @@ sub CheckLocale($$)
return undef;
}
-my ($OptHostName, $OptShow, $OptReboot);
+my ($OptHostName, $OptShow, $OptSysCopy, $OptDefCopy, $OptReboot);
my ($OptDefault, $OptLocale, $OptCountry, $OptSystem, $OptUTF8, $OptMUI, $OptKeyboard);
while (@ARGV)
{
@@ -323,6 +323,22 @@ while (@ARGV)
{
$OptShow = 1;
}
+ elsif ($Arg eq "--sys-copy")
+ {
+ $OptSysCopy = 1;
+ }
+ elsif ($Arg eq "--no-sys-copy")
+ {
+ $OptSysCopy = 0;
+ }
+ elsif ($Arg eq "--def-copy")
+ {
+ $OptDefCopy = 1;
+ }
+ elsif ($Arg eq "--no-def-copy")
+ {
+ $OptDefCopy = 0;
+ }
elsif ($Arg eq "--reboot")
{
if (defined $OptReboot and !$OptReboot)
@@ -426,13 +442,32 @@ if (!defined $Usage)
}
}
- if (!$OptLocale and !$OptSystem and !$OptMUI and !$OptKeyboard and
- !$OptCountry and !$OptUTF8 and !$OptShow)
+ if (!$OptLocale and !$OptCountry and !$OptSystem and !$OptUTF8 and
+ !$OptMUI and !$OptKeyboard and !defined $OptSysCopy and
+ !defined $OptDefCopy)
+ {
+ if (!$OptShow)
+ {
+ Error("you must specify at least one locale to change\n");
+ $Usage = 2;
+ }
+ if (defined $OptReboot)
+ {
+ Error("--(no-)reboot can only be used when changing a locale\n");
+ $Usage = 2;
+ }
+ }
+ if ($OptShow and ($OptLocale or $OptCountry or $OptSystem or $OptUTF8 or
+ $OptMUI or $OptKeyboard or defined $OptSysCopy or
+ defined $OptDefCopy or defined $OptReboot))
{
- Error("you must specify at least one locale to change\n");
+ Error("--show and the locale options are mutually incompatible\n");
$Usage = 2;
}
+ $OptSysCopy = 1 if (!defined $OptSysCopy);
+ $OptDefCopy = 1 if (!defined $OptDefCopy);
+
# Two settings only take effect after a reboot:
# - System locale changes.
# - Display language changes only require a log out + log in but that cannot
@@ -447,7 +482,7 @@ if (defined $Usage)
exit $Usage;
}
print "Usage: $name0 [options] --show HOSTNAME\n";
- print "or $name0 [options] [--default DEF] [--locale LOC] [--country CTY] [--system SYS] [--utf8] [--mui MUI] [--keyboard KBD] [--no-reboot] HOSTNAME\n";
+ print "or $name0 [options] [--default DEF] [--locale LOC] [--country CTY] [--system SYS] [--utf8] [--mui MUI] [--keyboard KBD] [--no-sys-copy] [--no-def-copy] [--no-reboot] HOSTNAME\n";
print "\n";
print "Sets the locale of the specified Windows machine.\n";
print "\n";
@@ -490,13 +525,32 @@ if (defined $Usage)
print " . Only takes effect after a log out + log in.\n";
print " . Windows 10 GUI: Time & language -> Language -> Windows\n";
print " display language.\n";
- print " . APIs: GetSystemPreferredUILanguages(),\n";
+ print " . APIs: GetSystemPreferredUILanguages() (--sys-copy case),\n";
print " GetUserDefaultUILanguage(), GetThreadUILanguage().\n";
print " . Powershell: Set-WinUILanguageOverride -Language MUI\n";
print " --keyboard KBD Specifies the keyboard layout (see --defaults).\n";
print " . Windows 10 GUI: Time & language -> Language -> Keyboard ->\n";
print " Override for default input method.\n";
print " . Powershell: Set-WinDefaultInputMethodOverride -InputTip KBD-ID\n";
+ print " --sys-copy Copy the current locales (--locale --country --mui --keyboard)\n";
+ print " to the system accounts (System/LocalSystem, NT Authority) and\n";
+ print " in particular the one used by the logon screen. This is the\n";
+ print " default.\n";
+ print " . This requires elevated privileges.\n";
+ print " . Windows 10 GUI: Time & language -> Language -> Administrative\n";
+ print " language settings -> Copy Settings -> Welcome Screen and\n";
+ print " system accounts.\n";
+ print " . Powershell (Windows 11+): Copy-UserInternationalSettingsToSystem -WelcomeScreen \$True\n";
+ print " . Intl.cpl: CopySettingsToSystemAcct='true'\n";
+ print " --no-sys-copy Do not copy the current locale to the system accounts such as\n";
+ print " the one used by the logon screen.\n";
+ print " --def-copy Copy the current locales (--locale --country --mui --keyboard)\n";
+ print " to the default user account. This is the default.\n";
+ print " . Windows 10 GUI: Time & language -> Language -> Administrative\n";
+ print " language settings -> Copy Settings -> New user accounts.\n";
+ print " . Powershell (Windows 11+): Copy-UserInternationalSettingsToSystem -NewUser \$True\n";
+ print " . Intl.cpl: CopySettingsToDefaultUserAcct='true'\n";
+ print " --no-def-copy Do not copy the current locales to the default user account.\n";
print " --no-reboot Do not reboot Windows. Some locale changes only take effect\n";
print " after a reboot so this option should only be used for\n";
print " debugging.\n";
@@ -652,7 +706,7 @@ sub ShowWinSettings($)
print "OEMCP (--utf8) = ", Value2Str($Settings->{OEMCP}), "\n";
print "\n";
- print ".DEFAULT account:\n";
+ print ".DEFAULT account (see --sys-copy):\n";
# Locale used for the date and time in the logon screen
print "Locale (--locale) = ", Value2Str($Settings->{DefLocale}), "\n";
print "LocaleName (--locale) = ", Value2Str($Settings->{DefLocaleName}), "\n";
@@ -772,11 +826,13 @@ $OptKeyboard ||= $OptDefault;
# Generate the intl.cpl configuration
#
+my $CopyToSys = $OptSysCopy ? "true" : "false";
+my $CopyToDef = $OptDefCopy ? "true" : "false";
my @Config = (
# intl.cpl does not want single quotes on that one line!
"<gs:GlobalizationServices xmlns:gs=\"urn:longhornGlobalizationUnattend\">",
" <gs:UserList>",
- " <gs:User UserID='Current' CopySettingsToDefaultUserAcct='true' CopySettingsToSystemAcct='true'/>",
+ " <gs:User UserID='Current' CopySettingsToDefaultUserAcct='$CopyToDef' CopySettingsToSystemAcct='$CopyToSys'/>",
" </gs:UserList>",
);
if (defined $CountryId)
@@ -952,6 +1008,28 @@ if ($KeyboardIds)
CheckSetting($Settings, "InputMethod", $KeyboardIds->[0], "for --keyboard $OptKeyboard", 1);
}
+if ($OptSysCopy)
+{
+ if ($OptLocale)
+ {
+ CheckSetting($Settings, "DefLocale", "0000$LCIDLocale", "for --locale $OptLocale", 1);
+ CheckSetting($Settings, "DefLocaleName", $OptLocale, "for --locale $OptLocale");
+ }
+ if ($OptCountry)
+ {
+ CheckSetting($Settings, "DefCountry", $CountryId, "for --country $OptCountry");
+ CheckSetting($Settings, "DefCountryName", $OptCountry, "for --country $OptCountry");
+ }
+ if ($OptMUI)
+ {
+ CheckSetting($Settings, "DefMachinePreferredUILanguages", $OptMUI, "for --mui $OptMUI");
+ }
+ if ($KeyboardIds)
+ {
+ CheckSetting($Settings, "DefInputMethod", $KeyboardIds->[0], "for --keyboard $OptKeyboard", 1);
+ }
+}
+
Cleanup();
exit(1) if (!$Success);
Debug(Elapsed($Start), " All done!\n");
--
2.30.2
Jan. 28, 2022
Re: [PATCH 20/24] ntoskrnl/tests: Avoid "misleading indentation" warnings.
by Fabian Maurer
Not sure why the patches fail, it works for me.
Is there something I need to change here?
Regards,
Fabian Maurer
On Freitag, 28. Januar 2022 03:36:52 CET you wrote:
> Hi,
>
> While running your changed tests, I think I found new failures.
> Being a bot and all I'm not very good at pattern recognition, so I might be
> wrong, but could you please double-check?
>
> Full results can be found at:
> https://testbot.winehq.org/JobDetails.pl?Key=106271
>
> Your paranoid android.
>
>
> === build (build log) ===
>
> error: patch failed: dlls/dxva2/tests/dxva2.c:356
> error: patch failed: dlls/evr/tests/evr.c:645
> error: patch failed: dlls/hlink/tests/hlink.c:2364
> error: patch failed: dlls/kernel32/tests/actctx.c:2668
> error: patch failed: dlls/kernel32/tests/file.c:5313
> error: patch failed: dlls/kernel32/tests/loader.c:2442
> error: patch failed: dlls/kernel32/tests/locale.c:5519
> error: patch failed: dlls/kernel32/tests/mailslot.c:88
> error: patch failed: dlls/kernel32/tests/sync.c:202
> error: patch failed: dlls/kernel32/tests/thread.c:2338
> error: patch failed: dlls/msscript.ocx/tests/msscript.c:1453
> error: patch failed: dlls/msvfw32/tests/msvfw.c:477
> error: patch failed: dlls/ntdll/tests/file.c:1113
> error: patch failed: dlls/ntdll/tests/info.c:2251
> error: patch failed: dlls/ntdll/tests/reg.c:374
> error: patch failed: dlls/ntoskrnl.exe/tests/driver.c:280
> Task: Patch failed to apply
>
> === debian11 (build log) ===
>
> error: patch failed: dlls/dxva2/tests/dxva2.c:356
> error: patch failed: dlls/evr/tests/evr.c:645
> error: patch failed: dlls/hlink/tests/hlink.c:2364
> error: patch failed: dlls/kernel32/tests/actctx.c:2668
> error: patch failed: dlls/kernel32/tests/file.c:5313
> error: patch failed: dlls/kernel32/tests/loader.c:2442
> error: patch failed: dlls/kernel32/tests/locale.c:5519
> error: patch failed: dlls/kernel32/tests/mailslot.c:88
> error: patch failed: dlls/kernel32/tests/sync.c:202
> error: patch failed: dlls/kernel32/tests/thread.c:2338
> error: patch failed: dlls/msscript.ocx/tests/msscript.c:1453
> error: patch failed: dlls/msvfw32/tests/msvfw.c:477
> error: patch failed: dlls/ntdll/tests/file.c:1113
> error: patch failed: dlls/ntdll/tests/info.c:2251
> error: patch failed: dlls/ntdll/tests/reg.c:374
> error: patch failed: dlls/ntoskrnl.exe/tests/driver.c:280
> Task: Patch failed to apply
>
> === debian11 (build log) ===
>
> error: patch failed: dlls/dxva2/tests/dxva2.c:356
> error: patch failed: dlls/evr/tests/evr.c:645
> error: patch failed: dlls/hlink/tests/hlink.c:2364
> error: patch failed: dlls/kernel32/tests/actctx.c:2668
> error: patch failed: dlls/kernel32/tests/file.c:5313
> error: patch failed: dlls/kernel32/tests/loader.c:2442
> error: patch failed: dlls/kernel32/tests/locale.c:5519
> error: patch failed: dlls/kernel32/tests/mailslot.c:88
> error: patch failed: dlls/kernel32/tests/sync.c:202
> error: patch failed: dlls/kernel32/tests/thread.c:2338
> error: patch failed: dlls/msscript.ocx/tests/msscript.c:1453
> error: patch failed: dlls/msvfw32/tests/msvfw.c:477
> error: patch failed: dlls/ntdll/tests/file.c:1113
> error: patch failed: dlls/ntdll/tests/info.c:2251
> error: patch failed: dlls/ntdll/tests/reg.c:374
> error: patch failed: dlls/ntoskrnl.exe/tests/driver.c:280
> Task: Patch failed to apply
Jan. 28, 2022
[PATCH 15/15] programs/ping: enable compilation with long types
by Eric Pouech
---
programs/ping/Makefile.in | 1 -
programs/ping/ping_main.c | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/programs/ping/Makefile.in b/programs/ping/Makefile.in
index 9ac4f6e4a3b..0ed66f470ea 100644
--- a/programs/ping/Makefile.in
+++ b/programs/ping/Makefile.in
@@ -1,4 +1,3 @@
-EXTRADEFS = -DWINE_NO_LONG_TYPES
MODULE = ping.exe
IMPORTS = ws2_32 iphlpapi
diff --git a/programs/ping/ping_main.c b/programs/ping/ping_main.c
index 51246e3f5bf..cf91f051a39 100644
--- a/programs/ping/ping_main.c
+++ b/programs/ping/ping_main.c
@@ -184,7 +184,7 @@ int __cdecl main(int argc, char** argv)
{
reply = (ICMP_ECHO_REPLY *) reply_buffer;
if (reply->RoundTripTime >= 1)
- sprintf(rtt, "=%d", reply->RoundTripTime);
+ sprintf(rtt, "=%ld", reply->RoundTripTime);
else
strcpy(rtt, "<1");
printf("Reply from %s: bytes=%d time%sms TTL=%d\n", ip, l,
Jan. 28, 2022
[PATCH 14/15] programs/netstat: enable compilation with long types
by Eric Pouech
---
programs/netstat/Makefile.in | 1 -
programs/netstat/netstat.c | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/programs/netstat/Makefile.in b/programs/netstat/Makefile.in
index 693fde0c1f4..e16d01ba4e9 100644
--- a/programs/netstat/Makefile.in
+++ b/programs/netstat/Makefile.in
@@ -1,4 +1,3 @@
-EXTRADEFS = -DWINE_NO_LONG_TYPES
MODULE = netstat.exe
IMPORTS = iphlpapi user32 ws2_32
diff --git a/programs/netstat/netstat.c b/programs/netstat/netstat.c
index 243fca56055..16238ee097f 100644
--- a/programs/netstat/netstat.c
+++ b/programs/netstat/netstat.c
@@ -145,7 +145,7 @@ static WCHAR *NETSTAT_load_message(UINT id) {
static const WCHAR failedW[] = {'F','a','i','l','e','d','!','\0'};
if (!LoadStringW(GetModuleHandleW(NULL), id, msg, ARRAY_SIZE(msg))) {
- WINE_FIXME("LoadString failed with %d\n", GetLastError());
+ WINE_FIXME("LoadString failed with %ld\n", GetLastError());
lstrcpyW(msg, failedW);
}
return msg;
Jan. 28, 2022
[PATCH 13/15] programs/net: enable compilation with long types
by Eric Pouech
---
programs/net/Makefile.in | 1 -
programs/net/net.c | 4 ++--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/programs/net/Makefile.in b/programs/net/Makefile.in
index a4c0f2f238a..eb8e1e48ff3 100644
--- a/programs/net/Makefile.in
+++ b/programs/net/Makefile.in
@@ -1,4 +1,3 @@
-EXTRADEFS = -DWINE_NO_LONG_TYPES
MODULE = net.exe
IMPORTS = netapi32 user32 advapi32
diff --git a/programs/net/net.c b/programs/net/net.c
index a8073956019..f9e64d2e2b9 100644
--- a/programs/net/net.c
+++ b/programs/net/net.c
@@ -61,7 +61,7 @@ static int output_vprintf(const WCHAR* fmt, va_list va_args)
len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt, 0, 0, str, ARRAY_SIZE(str), &va_args);
if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE)
- WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt));
+ WINE_FIXME("Could not format string: le=%lu, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt));
else
output_write(str, len);
return 0;
@@ -184,7 +184,7 @@ static BOOL net_enum_services(void)
for(i = 0; i < count; i++)
{
output_printf(L" %1\n", services[i].lpDisplayName);
- WINE_TRACE("service=%s state=%d controls=%x\n",
+ WINE_TRACE("service=%s state=%ld controls=%lx\n",
wine_dbgstr_w(services[i].lpServiceName),
services[i].ServiceStatusProcess.dwCurrentState,
services[i].ServiceStatusProcess.dwControlsAccepted);
Jan. 28, 2022