2 * PROJECT: ReactOS Session Manager
3 * LICENSE: GPL v2 or later - See COPYING in the top level directory
4 * FILE: base/system/smss/initmv.c
5 * PURPOSE: Process the file rename list.
6 * PROGRAMMERS: ReactOS Development Team
9 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
21 * The SmpDeleteFile function deletes a specify file.
24 * the name of a file which should be deleted
26 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
30 * This function is called by SmpMoveFilesQueryRoutine().
35 SmpDeleteFile( IN LPCWSTR lpFileName
)
37 FILE_DISPOSITION_INFORMATION FileDispInfo
;
38 OBJECT_ATTRIBUTES ObjectAttributes
;
39 IO_STATUS_BLOCK IoStatusBlock
;
40 UNICODE_STRING FileNameU
;
44 DPRINT("SmpDeleteFile ( %S )\n", lpFileName
);
47 return (STATUS_INVALID_PARAMETER
);
49 RtlInitUnicodeString(&FileNameU
, lpFileName
);
51 InitializeObjectAttributes(&ObjectAttributes
,
57 Status
= NtCreateFile (&FileHandle
,
62 FILE_ATTRIBUTE_NORMAL
,
63 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
65 FILE_SYNCHRONOUS_IO_NONALERT
,
69 if( !NT_SUCCESS(Status
) ) {
70 DPRINT("NtCreateFile() failed (Status %lx)\n", Status
);
74 FileDispInfo
.DeleteFile
= TRUE
;
76 Status
= NtSetInformationFile(
80 sizeof(FILE_DISPOSITION_INFORMATION
),
81 FileDispositionInformation
);
92 * The SmpMoveFile function deletes a specify file.
94 * @param lpExistingFileName
95 * the name of an existing file which should be removed
97 * @param lpNewFileName
98 * a new name of an existing file.
100 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
104 * This function called from the SmpMoveFilesQueryRoutine function.
109 SmpMoveFile( IN LPCWSTR lpExistingFileName
,
110 IN LPCWSTR lpNewFileName
113 PFILE_RENAME_INFORMATION FileRenameInfo
;
114 OBJECT_ATTRIBUTES ObjectAttributes
;
115 IO_STATUS_BLOCK IoStatusBlock
;
116 UNICODE_STRING ExistingFileNameU
;
119 BOOLEAN ReplaceIfExists
;
122 if( !lpExistingFileName
|| !lpNewFileName
)
123 return (STATUS_INVALID_PARAMETER
);
125 DPRINT("SmpMoveFile (%S, %S)\n", lpExistingFileName
, lpNewFileName
);
127 RtlInitUnicodeString(&ExistingFileNameU
, lpExistingFileName
);
129 InitializeObjectAttributes(&ObjectAttributes
,
131 OBJ_CASE_INSENSITIVE
,
135 Status
= NtCreateFile (&FileHandle
,
140 FILE_ATTRIBUTE_NORMAL
,
141 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
143 FILE_SYNCHRONOUS_IO_NONALERT
,
147 if( !NT_SUCCESS(Status
) ) {
148 DPRINT("NtCreateFile() failed (Status %lx)\n", Status
);
152 FileNameSize
= wcslen(lpNewFileName
)*sizeof(*lpNewFileName
);
153 FileRenameInfo
= RtlAllocateHeap(
156 sizeof(FILE_RENAME_INFORMATION
)+FileNameSize
);
157 if( !FileRenameInfo
) {
158 DPRINT("RtlAllocateHeap failed\n");
160 return (STATUS_NO_MEMORY
);
163 if( L
'!' == *lpNewFileName
) {
165 FileNameSize
-= sizeof(*lpNewFileName
);
166 ReplaceIfExists
= TRUE
;
169 ReplaceIfExists
= FALSE
;
172 FileRenameInfo
->RootDirectory
= NULL
;
173 FileRenameInfo
->ReplaceIfExists
= ReplaceIfExists
;
174 FileRenameInfo
->FileNameLength
= FileNameSize
;
175 RtlCopyMemory(FileRenameInfo
->FileName
, lpNewFileName
, FileNameSize
);
177 Status
= NtSetInformationFile(
181 sizeof(FILE_RENAME_INFORMATION
)+FileNameSize
,
182 FileRenameInformation
);
184 RtlFreeHeap(RtlGetProcessHeap(), 0, FileRenameInfo
);
186 /* FIXME: After the FileRenameInformation parameter will be implemented into the fs driver
187 the following code can be removed */
188 if( STATUS_NOT_IMPLEMENTED
== Status
)
190 HANDLE FileHandleNew
;
191 UNICODE_STRING NewFileNameU
;
192 FILE_BASIC_INFORMATION FileBasicInfo
;
193 UCHAR
*lpBuffer
= NULL
;
194 SIZE_T RegionSize
= 0x10000;
195 LARGE_INTEGER BytesCopied
;
198 Status
= NtQueryInformationFile(
202 sizeof(FILE_BASIC_INFORMATION
),
203 FileBasicInformation
);
204 if( !NT_SUCCESS(Status
) ) {
205 DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status
);
210 RtlInitUnicodeString(&NewFileNameU
, lpNewFileName
);
212 InitializeObjectAttributes(&ObjectAttributes
,
214 OBJ_CASE_INSENSITIVE
,
218 Status
= NtCreateFile (&FileHandleNew
,
223 FILE_ATTRIBUTE_NORMAL
,
224 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
225 ReplaceIfExists
? FILE_OVERWRITE_IF
: FILE_CREATE
,
226 FILE_SYNCHRONOUS_IO_NONALERT
,
230 if( !NT_SUCCESS(Status
) ) {
231 DPRINT("NtCreateFile() failed (Status %lx)\n", Status
);
236 Status
= NtAllocateVirtualMemory(
241 MEM_RESERVE
| MEM_COMMIT
,
243 if( !NT_SUCCESS(Status
) ) {
244 DPRINT("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
246 SmpDeleteFile(lpNewFileName
);
249 BytesCopied
.QuadPart
= 0;
250 EndOfFileFound
= FALSE
;
251 while( !EndOfFileFound
252 && NT_SUCCESS(Status
) )
254 Status
= NtReadFile(FileHandle
,
263 if( NT_SUCCESS(Status
) ) {
264 Status
= NtWriteFile(FileHandleNew
,
270 IoStatusBlock
.Information
,
273 if( NT_SUCCESS(Status
) ) {
274 BytesCopied
.QuadPart
+= IoStatusBlock
.Information
;
277 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
281 if( STATUS_END_OF_FILE
== Status
) {
282 EndOfFileFound
= TRUE
;
283 Status
= STATUS_SUCCESS
;
286 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
291 NtFreeVirtualMemory(NtCurrentProcess(),
296 Status
= NtQueryInformationFile(
300 sizeof(FILE_BASIC_INFORMATION
),
301 FileBasicInformation
);
302 if( !NT_SUCCESS(Status
) ) {
303 DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status
);
306 Status
= NtSetInformationFile(FileHandleNew
,
309 sizeof(FILE_BASIC_INFORMATION
),
310 FileBasicInformation
);
311 if( !NT_SUCCESS(Status
) ) {
312 DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status
);
314 NtClose(FileHandleNew
);
317 SmpDeleteFile(lpExistingFileName
);
329 * @name SmpMoveFilesQueryRoutine
331 * The SmpMoveFilesQueryRoutine function processes registry entries.
334 * The name of the value.
337 * The type of the value.
340 * The null-terminated data for the value.
343 * The length of ValueData.
348 * @param EntryContext
351 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
359 static NTSTATUS NTAPI
360 SmpMoveFilesQueryRoutine(IN PWSTR ValueName
,
363 IN ULONG ValueLength
,
365 IN PVOID EntryContext
)
368 static LPWSTR FistFileName
= NULL
;
370 DPRINT("SmpMoveFilesQueryRoutine() called \n");
371 DPRINT("ValueData = %S \n", (PWSTR
) ValueData
);
375 /* save a first file name */
376 FistFileName
= ValueData
;
377 Status
= STATUS_SUCCESS
;
381 if( 0 == *((LPWSTR
)ValueData
) ) {
382 /* delete if second file name is absent */
383 Status
= SmpDeleteFile( FistFileName
);
386 Status
= SmpMoveFile( FistFileName
, (LPCWSTR
)ValueData
);
396 * @name SmProcessFileRenameList
399 * The SmProcessFileRenameList function moves or deletes files thats have been added to the specify registry key for delayed moving.
403 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
407 * This function reads the following registry value:
408 * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations
409 * This registry value is of type REG_MULTI_SZ. The each operation is specifed as two file names.
410 * A first name is a source file, a second name is a destination file.
411 * In the case of deleting operation a second file name must be the empty string.
413 * szxSrcFile\0szxDestFile\0\0 <-- the szxSrcFile file will be renamed to the szxDestFile file
414 * szxSomeFile\0\0\0 <-- the szxSomeFile file will be removed
415 * After it will be done, the registry value will be deleted.
420 SmProcessFileRenameList( VOID
)
422 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
425 DPRINT("SmProcessFileRenameList() called\n");
427 RtlZeroMemory( &QueryTable
, sizeof(QueryTable
) );
428 QueryTable
[0].Name
= L
"PendingFileRenameOperations";
429 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DELETE
;
430 QueryTable
[0].DefaultType
= REG_NONE
;
431 QueryTable
[0].QueryRoutine
= SmpMoveFilesQueryRoutine
;
433 Status
= RtlQueryRegistryValues(
434 RTL_REGISTRY_CONTROL
,
435 L
"\\Session Manager",
440 if( !NT_SUCCESS(Status
) ) {
441 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
444 /* FIXME: RtlQueryRegistryValues can return an error status if the PendingFileRenameOperations value
445 does not exist, in this case smss hungs, therefore we always return STATUS_SUCCESS */
446 return (STATUS_SUCCESS
);