# SDL: stdinc: On Windows, uppercase the system environment table's var names.

**URL:** <https://discourse.libsdl.org/t/sdl-stdinc-on-windows-uppercase-the-system-environment-tables-var-names/69310>\
**Category:** SDL Commits\
**Created:** [September 13, 2026, 5:48pm UTC](https://discourse.libsdl.org/t/sdl-stdinc-on-windows-uppercase-the-system-environment-tables-var-names/69310 "2026-09-13T17:48:50Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![SDLPushPostBot](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/sdlpushpostbot/32/4370_2.png) [@SDLPushPostBot](https://discourse.libsdl.org/u/SDLPushPostBot)\
**Post date:** [September 13, 2026, 5:48pm UTC](https://discourse.libsdl.org/t/sdl-stdinc-on-windows-uppercase-the-system-environment-tables-var-names/69310/1 "2026-09-13T17:48:50Z")

</div>

> <https://github.com/libsdl-org/SDL/commit/b290793b78141d0131ff135d47cec0c095b807db>
>
> Fixes #15086.

```diff
From b290793b78141d0131ff135d47cec0c095b807db Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Sat, 11 Jul 2026 23:53:08 -0400
Subject: [PATCH] stdinc: On Windows, uppercase the system environment table's
 var names.

Fixes #15086.
---
 include/SDL3/SDL_stdinc.h | 14 +++++++++++++-
 src/stdlib/SDL_getenv.c | 12 ++++++++++++
 test/testprocess.c | 8 ++++----
 3 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h
index 22dbafb5669a6..6901ba59de518 100644
--- a/include/SDL3/SDL_stdinc.h
+++ b/include/SDL3/SDL_stdinc.h
@@ -1776,6 +1776,12 @@ typedef struct SDL_Environment SDL_Environment;
  * SDL_setenv_unsafe() or SDL_unsetenv_unsafe() if you want changes to persist
  * in the C runtime environment after SDL_Quit().
  *
+ * Note that on Windows, the variable names pulled in from the system at
+ * startup have their ASCII values uppercased, to match what most platforms
+ * expect even though the Windows system environment table is
+ * case-insensitive. Once those uppercased variable names are in an
+ * SDL_Environment, SDL treats them as case-sensitive.
+ *
  * \returns a pointer to the environment for the process or NULL on failure;
  * call SDL_GetError() for more information.
  *
@@ -1791,7 +1797,13 @@ typedef struct SDL_Environment SDL_Environment;
 extern SDL_DECLSPEC SDL_Environment * SDLCALL SDL_GetEnvironment(void);
 
 /**
- * Create a set of environment variables
+ * Create a set of environment variables.
+ *
+ * Note that on Windows, the variable names pulled in from the system, if
+ * `populated` is true, have their ASCII values uppercased, to match what most
+ * platforms expect even though the Windows system environment table is
+ * case-insensitive. Once those uppercased variable names are in an
+ * SDL_Environment, SDL treats them as case-sensitive.
  *
  * \param populated true to initialize it from the C runtime environment,
  * false to create an empty environment.
diff --git a/src/stdlib/SDL_getenv.c b/src/stdlib/SDL_getenv.c
index e058c0c90d3dd..ff32f632ae71d 100644
--- a/src/stdlib/SDL_getenv.c
+++ b/src/stdlib/SDL_getenv.c
@@ -119,6 +119,11 @@ SDL_Environment *SDL_CreateEnvironment(bool populated)
                 }
                 *value++ = '\0';
 
+ // uppercase ASCII chars in environment variable names on Windows, since the system environment table is case-insensitive.
+ for (char *ptr = variable; *ptr; ptr++) {
+ *ptr = (char) SDL_toupper((int) *ptr); // the only UTF-8 bytes that don't have the high-bit set are single-byte ASCII chars, so SDL_toupper will leave multichar stuff alone.
+ }
+
                 SDL_InsertIntoHashTable(env->strings, variable, value, true);
             }
             FreeEnvironmentStringsW(strings);
@@ -143,6 +148,13 @@ SDL_Environment *SDL_CreateEnvironment(bool populated)
                 }
                 *value++ = '\0';
 
+#ifdef SDL_PLATFORM_CYGWIN
+ // uppercase ASCII chars in environment variable names on Windows, since the system environment table is case-insensitive.
+ for (char *ptr = variable; *ptr; ptr++) {
+ *ptr = (char) SDL_toupper((int) *ptr); // the only UTF-8 bytes that don't have the high-bit set are single-byte ASCII chars, so SDL_toupper will leave multichar stuff alone.
+ }
+#endif
+
                 SDL_InsertIntoHashTable(env->strings, variable, value, true);
             }
         }
diff --git a/test/testprocess.c b/test/testprocess.c
index 2d8f56909935d..6721e2015c98a 100644
--- a/test/testprocess.c
+++ b/test/testprocess.c
@@ -197,8 +197,8 @@ static int SDLCALL process_testInheritedEnv(void *arg)
     int exit_code;
     char random_env1[64];
     char random_env2[64];
- static const char *const TEST_ENV_KEY1 = "testprocess_inherited_var";
- static const char *const TEST_ENV_KEY2 = "testprocess_other_var";
+ static const char *const TEST_ENV_KEY1 = "TESTPROCESS_INHERITED_VAR";
+ static const char *const TEST_ENV_KEY2 = "TESTPROCESS_OTHER_VAR";
     char *test_env_val1 = NULL;
     char *test_env_val2 = NULL;
     char *buffer = NULL;
@@ -269,8 +269,8 @@ static int SDLCALL process_testNewEnv(void *arg)
     int exit_code;
     char random_env1[64];
     char random_env2[64];
- static const char *const TEST_ENV_KEY1 = "testprocess_inherited_var";
- static const char *const TEST_ENV_KEY2 = "testprocess_other_var";
+ static const char *const TEST_ENV_KEY1 = "TESTPROCESS_INHERITED_VAR";
+ static const char *const TEST_ENV_KEY2 = "TESTPROCESS_OTHER_VAR";
     char *test_env_val1 = NULL;
     char *test_env_val2 = NULL;
     char *buffer = NULL;

```
