Jason Edmeades : cmd.exe: setlocal and endlocal should preserve drive and directory.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Mar 8 07:17:10 CST 2007


Module: wine
Branch: master
Commit: 86140e3fbb0ac108314f4db6d504c62a4a7cf3bb
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=86140e3fbb0ac108314f4db6d504c62a4a7cf3bb

Author: Jason Edmeades <us at edmeades.me.uk>
Date:   Thu Mar  8 00:48:49 2007 +0000

cmd.exe: setlocal and endlocal should preserve drive and directory.

---

 programs/cmd/builtins.c |   24 ++++++++++++++++++++++--
 programs/cmd/wcmd.h     |    5 ++++-
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 5149159..6a1a3a6 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -893,6 +893,7 @@ static WCHAR *WCMD_dupenv( const WCHAR *env )
 void WCMD_setlocal (const char *s) {
   WCHAR *env;
   struct env_stack *env_copy;
+  char cwd[MAX_PATH];
 
   /* DISABLEEXTENSIONS ignored */
 
@@ -910,11 +911,16 @@ void WCMD_setlocal (const char *s) {
   {
     env_copy->next = saved_environment;
     saved_environment = env_copy;
+
+    /* Save the current drive letter */
+    GetCurrentDirectory (MAX_PATH, cwd);
+    env_copy->cwd = cwd[0];
   }
   else
     LocalFree (env_copy);
 
   FreeEnvironmentStringsW (env);
+
 }
 
 /*****************************************************************************
@@ -935,6 +941,8 @@ static inline WCHAR *WCMD_strchrW(WCHAR *str, WCHAR ch)
  * WCMD_endlocal
  *
  *  endlocal pops the environment off a stack
+ *  Note: When searching for '=', search from char position 1, to handle
+ *        special internal environment variables =C:, =D: etc
  */
 void WCMD_endlocal (void) {
   WCHAR *env, *old, *p;
@@ -954,7 +962,7 @@ void WCMD_endlocal (void) {
   len = 0;
   while (old[len]) {
     n = lstrlenW(&old[len]) + 1;
-    p = WCMD_strchrW(&old[len], '=');
+    p = WCMD_strchrW(&old[len] + 1, '=');
     if (p)
     {
       *p++ = 0;
@@ -970,7 +978,7 @@ void WCMD_endlocal (void) {
   len = 0;
   while (env[len]) {
     n = lstrlenW(&env[len]) + 1;
-    p = WCMD_strchrW(&env[len], '=');
+    p = WCMD_strchrW(&env[len] + 1, '=');
     if (p)
     {
       *p++ = 0;
@@ -978,6 +986,18 @@ void WCMD_endlocal (void) {
     }
     len += n;
   }
+
+  /* Restore current drive letter */
+  if (IsCharAlpha(temp->cwd)) {
+    char envvar[4];
+    char cwd[MAX_PATH];
+    sprintf(envvar, "=%c:", temp->cwd);
+    if (GetEnvironmentVariable(envvar, cwd, MAX_PATH)) {
+      WINE_TRACE("Resetting cwd to %s\n", cwd);
+      SetCurrentDirectory(cwd);
+    }
+  }
+
   LocalFree (env);
   LocalFree (temp);
 }
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index 53f163c..e7ffa94 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -101,7 +101,10 @@ typedef struct {
 struct env_stack
 {
   struct env_stack *next;
-  int    stackdepth;       /* Only used for pushd and popd */
+  union {
+    int    stackdepth;       /* Only used for pushd and popd */
+    char   cwd;              /* Only used for set/endlocal   */
+  };
   WCHAR *strings;
 };
 




More information about the wine-cvs mailing list