MoveFileEx BootRename Patch

Gerhard W. Gruber sparhawk at gmx.at
Sat Feb 16 15:42:49 CST 2002


- BEHAVIOUR: MoveFilEx should ignore non-existent files when the boot
delay flag is set. In that case the returncode may still be TRUE even
though the files may not exist at the time MoveFileEx is called.
- ADDED: MoveFileEx now enters the files in the registry when the boot
delay flag is set. The returncode in that case reflects the success of
the registry manipulation instead of the file move operation. This is
needed for applying the boot phase with deleting and renaming files on
startup of windows.
-------------- next part --------------
Index: options.h
===================================================================
RCS file: /home/wine/wine/include/options.h,v
retrieving revision 1.34
diff -u -r1.34 options.h
--- options.h	23 Jul 2001 00:04:02 -0000	1.34
+++ options.h	16 Feb 2002 21:29:40 -0000
@@ -33,6 +33,7 @@
 extern int PROFILE_GetWineIniInt( const char *section, const char *key_name, int def );
 extern int PROFILE_GetWineIniBool( char const *section, char const *key_name, int def );
 extern char* PROFILE_GetStringItem( char* );
+extern BOOL PROFILE_AddBootRenameEntry(char *Filename1, char *Filename2 /* May be NULL */);
 
 /* Version functions */
 extern void VERSION_ParseWinVersion( const char *arg );
-------------- next part --------------
Index: file.c
===================================================================
RCS file: /home/wine/wine/files/file.c,v
retrieving revision 1.131
diff -u -r1.131 file.c
--- file.c	21 Jan 2002 17:37:24 -0000	1.131
+++ file.c	16 Feb 2002 21:31:00 -0000
@@ -2126,26 +2126,57 @@
 
     TRACE("(%s,%s,%04lx)\n", fn1, fn2, flag);
 
+	/* FIXME: <Gerhard W. Gruber>sparhawk at gmx.at
+	   In case of W9x and lesser this function should return 120 (ERROR_CALL_NOT_IMPLEMENTED)
+	   to be really compatible. Most programs wont have any problems though. In case
+	   you encounter one, this is what you should return here. I don't know what's up 
+	   with NT 3.5. Is this function available there or not?
+	   Does anybody really care about 3.5? :)
+	*/
+
+	/* Filename1 has to be always set to a valid path. Filename2 may be NULL
+	   if the source file has to be deleted.
+	*/
     if (!fn1) {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
-    if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE;
+	/* This function has to be run through in order to process the name properly.
+	   If the BOOTDELAY flag is set, the file doesn't need to exist though. At least
+	   that is the behaviour on NT 4.0. The operation accepts the filenames as
+	   they are given but it can't reply with a reasonable returncode. Success
+	   means in that case success for entering the values into the registry.
+	*/
+    if(!DOSFS_GetFullName( fn1, TRUE, &full_name1 ))
+	{
+		 if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
+			  return FALSE;
+	}
 
     if (fn2)  /* !fn2 means delete fn1 */
     {
         if (DOSFS_GetFullName( fn2, TRUE, &full_name2 )) 
         {
-            /* target exists, check if we may overwrite */
-            if (!(flag & MOVEFILE_REPLACE_EXISTING))
-            {
-                /* FIXME: Use right error code */
-                SetLastError( ERROR_ACCESS_DENIED );
-                return FALSE;
-            }
+			 if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
+			 {
+				  /* target exists, check if we may overwrite */
+				  if (!(flag & MOVEFILE_REPLACE_EXISTING))
+				  {
+					   /* FIXME: Use right error code */
+					   SetLastError( ERROR_ACCESS_DENIED );
+					   return FALSE;
+				  }
+			 }
         }
-        else if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE;
+        else
+		{
+			 if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 ))
+			 {
+				  if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT))
+					   return FALSE;
+			 }
+		}
 
         /* Source name and target path are valid */
 
@@ -2157,7 +2188,7 @@
             */
             FIXME("Please move existing file '%s' to file '%s' when Wine has finished\n",
                   full_name1.long_name, full_name2.long_name);
-            return TRUE;
+			return PROFILE_AddBootRenameEntry(fn1, fn2);
         }
 
         if (full_name1.drive != full_name2.drive)
@@ -2206,7 +2237,7 @@
             */
             FIXME("Please delete file '%s' when Wine has finished\n",
                   full_name1.long_name);
-            return TRUE;
+			return PROFILE_AddBootRenameEntry(fn1, NULL);
         }
 
         if (unlink( full_name1.long_name ) == -1)
-------------- next part --------------
Index: profile.c
===================================================================
RCS file: /home/wine/wine/files/profile.c,v
retrieving revision 1.64
diff -u -r1.64 profile.c
--- profile.c	5 Feb 2002 19:44:54 -0000	1.64
+++ profile.c	16 Feb 2002 21:32:05 -0000
@@ -83,6 +83,125 @@
 
 static const char hex[16] = "0123456789ABCDEF";
 
+
+/***********************************************************************
+ *           PROFILE_AddBootRenameEntry
+ *
+ * Adds an entry to the registry that is loaded when windows boots and
+ * checks if there are some files to be removed or renamed/moved.
+ * <fn1> has to be valid and <fn2> may be NULL. If both pointers are
+ * non-NULL then the file is moved, otherwise it is deleted.
+ * The entry of the registrykey is always appended with two zero
+ * terminated strings. If <fn2> is NULL then the second entry is simply
+ * a single 0-byte. Otherwise the second filename goes there. The entries
+ * are prepended with \??\ before the path and the second filename gets
+ * also a '!' as the first character. After the final string another 0-byte
+ * follows to indicate the end of the strings.
+ * i.e.:
+ * \??\D:\test\file1[0]
+ * !\??\D:\test\file1_renamed[0]
+ * \??\D:\Test|delete[0]
+ * [0]                        <- file is to be deleted, second string empty
+ * \??\D:\test\file2[0]
+ * !\??\D:\test\file2_renamed[0]
+ * [0]                        <- indicates end of strings
+ *
+ * or:
+ * \??\D:\test\file1[0]
+ * !\??\D:\test\file1_renamed[0]
+ * \??\D:\Test|delete[0]
+ * [0]                        <- file is to be deleted, second string empty
+ * [0]                        <- indicates end of strings
+ *
+ */
+BOOL PROFILE_AddBootRenameEntry(char *fn1, char *fn2)
+{
+	 BOOL rc = FALSE;
+	 HKEY Reboot = INVALID_HANDLE_VALUE;
+	 DWORD Type = 0, len1 = 0, len2 = 0, l;
+	 DWORD DataSize = 0, OrigIndex, h;
+	 BYTE *Buffer = NULL;
+	 BYTE p[1], *PreString = "\\??\\";
+	 BYTE *ValueName = "PendingFileRenameOperations";
+	 LONG val;
+	 
+	 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager", &Reboot) != ERROR_SUCCESS)
+	 {
+		  WARN("Error creating key for reboot managment [%s]\n", "SYSTEM\\CurrentControlSet\\Control\\Session Manager");
+		  goto Quit;
+	 }
+
+	 l = strlen(PreString);
+	 len1 = strlen(fn1) + l + 1;
+	 if(fn2)
+		  len2 = strlen(fn2) + l + 1;  /* Plus 1 because of the leading '!' */
+
+	 /* minimum is the 0 byte for the empty second string */
+	 len2++;
+
+	 /* First we check if the key exists and if so how many bytes it already contains. */
+	 Buffer = &p[0];
+	 if((val = RegQueryValueExA(Reboot, ValueName, NULL, &Type, Buffer, &DataSize)) != ERROR_SUCCESS)
+	 {
+		  /* If ERROR_MORE_DATA is returned, then this means that the key exists and our buffer is too small.
+			 The needed buffersize is stored in the DataSize argument. If any other error code is returned we
+			 try to create they value.
+		  */
+		  if(val != ERROR_MORE_DATA)
+		  {
+			   /* The key probably doesn't exist so we try to create it. */
+			   p[0] = 0;
+			   RegSetValueExA(Reboot, ValueName, NULL, REG_BINARY, (CONST BYTE *)&p[0], (DWORD)sizeof(&p[0]));
+
+               /* Just to be sure in case RegQueryValueEx
+				  alters this value unexpectedly on other errors.
+			   */
+			   DataSize = 0;
+		  }
+	 }
+
+	 if(DataSize)
+		  DataSize--;
+
+	 OrigIndex = DataSize;
+
+	 DataSize += len1 + len2 + 1;
+	 if((Buffer = malloc(DataSize)) == NULL)
+	 {
+		  WARN("Unable to allocate %ld bytes for adding bootfiles\n", DataSize);
+		  goto Quit;
+	 }
+
+	 memset(Buffer, 0, DataSize);
+
+	 /* Retrieve the current buffer content */
+	 if((val = RegQueryValueExA(Reboot, ValueName, NULL, &Type, Buffer, &h)) != ERROR_SUCCESS)
+	 {
+		  FIXME("RegQueryValueExA returned %ld (Size: %lu) somethings wrong here.\n", val, DataSize);
+		  goto Quit;
+	 }
+
+	 sprintf(&Buffer[OrigIndex], "%s%s", PreString, fn1);
+	 OrigIndex += len1;
+	 if(fn2)
+		  sprintf(&Buffer[OrigIndex], "!%s%s", PreString, (fn2 == NULL) ? "" : fn2);
+
+	 OrigIndex += len2;
+	 RegSetValueExA(Reboot, ValueName, NULL, REG_BINARY, Buffer, DataSize);
+
+	 rc = TRUE;
+
+Quit:
+	 if(Reboot == INVALID_HANDLE_VALUE)
+		  RegCloseKey(Reboot);
+
+	 if(Buffer)
+		  free(Buffer);
+
+	 return(rc);
+}
+
+
 /***********************************************************************
  *           PROFILE_CopyEntry
  *
@@ -1893,3 +2012,4 @@
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     return FALSE;
 }
+


More information about the wine-patches mailing list