From 814a3fa2a13d3d3970cf0eccc49448e0a5ec1bec Mon Sep 17 00:00:00 2001 From: "Gerhard W. Gruber" Date: Fri, 22 Feb 2002 21:30:22 +0000 Subject: [PATCH] MoveFileEx now enters the files in the registry when the boot delay flag is set. --- files/file.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 136 insertions(+), 13 deletions(-) diff --git a/files/file.c b/files/file.c index ebdb5767bf3..19a01739caf 100644 --- a/files/file.c +++ b/files/file.c @@ -2117,6 +2117,99 @@ inline static BOOL is_executable( const char *name ) } +/*********************************************************************** + * FILE_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. + * has to be valid and 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 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 if + * MOVEFILE_REPLACE_EXISTING is set. 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 + * + */ +static BOOL FILE_AddBootRenameEntry( const char *fn1, const char *fn2, DWORD flags ) +{ + static const char PreString[] = "\\??\\"; + static const char ValueName[] = "PendingFileRenameOperations"; + + BOOL rc = FALSE; + HKEY Reboot = 0; + DWORD Type, len1, len2, l; + DWORD DataSize = 0; + BYTE *Buffer = NULL; + + 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"); + return FALSE; + } + + l = strlen(PreString); + len1 = strlen(fn1) + l + 1; + if (fn2) + { + len2 = strlen(fn2) + l + 1; + if (flags & MOVEFILE_REPLACE_EXISTING) len2++; /* Plus 1 because of the leading '!' */ + } + else len2 = 1; /* minimum is the 0 byte for the empty second string */ + + /* First we check if the key exists and if so how many bytes it already contains. */ + if (RegQueryValueExA(Reboot, ValueName, NULL, &Type, NULL, &DataSize) == ERROR_SUCCESS) + { + if (Type != REG_MULTI_SZ) goto Quit; + if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + 1 ))) goto Quit; + if (RegQueryValueExA(Reboot, ValueName, NULL, &Type, Buffer, &DataSize) != ERROR_SUCCESS) + goto Quit; + if (DataSize) DataSize--; /* remove terminating null (will be added back later) */ + } + else + { + if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, len1 + len2 + 1 ))) goto Quit; + DataSize = 0; + } + sprintf( Buffer + DataSize, "%s%s", PreString, fn1 ); + DataSize += len1; + if (fn2) + { + sprintf( Buffer + DataSize, "%s%s%s", + (flags & MOVEFILE_REPLACE_EXISTING) ? "!" : "", PreString, fn2 ); + DataSize += len2; + } + else Buffer[DataSize++] = 0; + + Buffer[DataSize++] = 0; /* add final null */ + rc = !RegSetValueExA( Reboot, ValueName, 0, REG_MULTI_SZ, Buffer, DataSize ); + + Quit: + if (Reboot) RegCloseKey(Reboot); + if (Buffer) HeapFree( GetProcessHeap(), 0, Buffer ); + return(rc); +} + + /************************************************************************** * MoveFileExA (KERNEL32.@) */ @@ -2126,26 +2219,57 @@ BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag ) TRACE("(%s,%s,%04lx)\n", fn1, fn2, flag); + /* FIXME: sparhawk@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 )) + if (DOSFS_GetFullName( fn2, TRUE, &full_name2 )) { - /* target exists, check if we may overwrite */ - if (!(flag & MOVEFILE_REPLACE_EXISTING)) + if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT)) { - /* FIXME: Use right error code */ - SetLastError( ERROR_ACCESS_DENIED ); - return FALSE; + /* 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 )) + { + if(!(flag & MOVEFILE_DELAY_UNTIL_REBOOT)) + return FALSE; } } - else if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE; /* Source name and target path are valid */ @@ -2156,8 +2280,8 @@ BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag ) when exiting... What about using on_exit(2) */ FIXME("Please move existing file '%s' to file '%s' when Wine has finished\n", - full_name1.long_name, full_name2.long_name); - return TRUE; + fn1, fn2); + return FILE_AddBootRenameEntry( fn1, fn2, flag ); } if (full_name1.drive != full_name2.drive) @@ -2204,9 +2328,8 @@ BOOL WINAPI MoveFileExA( LPCSTR fn1, LPCSTR fn2, DWORD flag ) Perhaps we should queue these command and execute it when exiting... What about using on_exit(2) */ - FIXME("Please delete file '%s' when Wine has finished\n", - full_name1.long_name); - return TRUE; + FIXME("Please delete file '%s' when Wine has finished\n", fn1); + return FILE_AddBootRenameEntry( fn1, NULL, flag ); } if (unlink( full_name1.long_name ) == -1)