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 ******************************************************************/
17 /* FUNCTIONS *****************************************************************/
22 * The SmpDeleteFile function deletes a specify file.
25 * the name of a file which should be deleted
27 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
31 * This function is called by SmpMoveFilesQueryRoutine().
36 SmpDeleteFile( IN LPCWSTR lpFileName
)
38 FILE_DISPOSITION_INFORMATION FileDispInfo
;
39 OBJECT_ATTRIBUTES ObjectAttributes
;
40 IO_STATUS_BLOCK IoStatusBlock
;
41 UNICODE_STRING FileNameU
;
45 DPRINT("SmpDeleteFile ( %S )\n", lpFileName
);
48 return (STATUS_INVALID_PARAMETER
);
50 RtlInitUnicodeString(&FileNameU
, lpFileName
);
52 InitializeObjectAttributes(&ObjectAttributes
,
58 Status
= NtCreateFile (&FileHandle
,
63 FILE_ATTRIBUTE_NORMAL
,
64 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
66 FILE_SYNCHRONOUS_IO_NONALERT
,
70 if( !NT_SUCCESS(Status
) ) {
71 DPRINT("NtCreateFile() failed (Status %lx)\n", Status
);
75 FileDispInfo
.DeleteFile
= TRUE
;
77 Status
= NtSetInformationFile(
81 sizeof(FILE_DISPOSITION_INFORMATION
),
82 FileDispositionInformation
);
93 * The SmpMoveFile function deletes a specify file.
95 * @param lpExistingFileName
96 * the name of an existing file which should be removed
98 * @param lpNewFileName
99 * a new name of an existing file.
101 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
105 * This function called from the SmpMoveFilesQueryRoutine function.
110 SmpMoveFile( IN LPCWSTR lpExistingFileName
,
111 IN LPCWSTR lpNewFileName
114 PFILE_RENAME_INFORMATION FileRenameInfo
;
115 OBJECT_ATTRIBUTES ObjectAttributes
;
116 IO_STATUS_BLOCK IoStatusBlock
;
117 UNICODE_STRING ExistingFileNameU
;
120 BOOLEAN ReplaceIfExists
;
123 if( !lpExistingFileName
|| !lpNewFileName
)
124 return (STATUS_INVALID_PARAMETER
);
126 DPRINT("SmpMoveFile (%S, %S)\n", lpExistingFileName
, lpNewFileName
);
128 RtlInitUnicodeString(&ExistingFileNameU
, lpExistingFileName
);
130 InitializeObjectAttributes(&ObjectAttributes
,
132 OBJ_CASE_INSENSITIVE
,
136 Status
= NtCreateFile (&FileHandle
,
141 FILE_ATTRIBUTE_NORMAL
,
142 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
144 FILE_SYNCHRONOUS_IO_NONALERT
,
148 if( !NT_SUCCESS(Status
) ) {
149 DPRINT("NtCreateFile() failed (Status %lx)\n", Status
);
153 FileNameSize
= wcslen(lpNewFileName
)*sizeof(*lpNewFileName
);
154 FileRenameInfo
= RtlAllocateHeap(
157 sizeof(FILE_RENAME_INFORMATION
)+FileNameSize
);
158 if( !FileRenameInfo
) {
159 DPRINT("RtlAllocateHeap failed\n");
161 return (STATUS_NO_MEMORY
);
164 if( L
'!' == *lpNewFileName
) {
166 FileNameSize
-= sizeof(*lpNewFileName
);
167 ReplaceIfExists
= TRUE
;
170 ReplaceIfExists
= FALSE
;
173 FileRenameInfo
->RootDirectory
= NULL
;
174 FileRenameInfo
->ReplaceIfExists
= ReplaceIfExists
;
175 FileRenameInfo
->FileNameLength
= FileNameSize
;
176 RtlCopyMemory(FileRenameInfo
->FileName
, lpNewFileName
, FileNameSize
);
178 Status
= NtSetInformationFile(
182 sizeof(FILE_RENAME_INFORMATION
)+FileNameSize
,
183 FileRenameInformation
);
185 RtlFreeHeap(RtlGetProcessHeap(), 0, FileRenameInfo
);
187 /* FIXME: After the FileRenameInformation parameter will be implemented into the fs driver
188 the following code can be removed */
189 if( STATUS_NOT_IMPLEMENTED
== Status
)
191 HANDLE FileHandleNew
;
192 UNICODE_STRING NewFileNameU
;
193 FILE_BASIC_INFORMATION FileBasicInfo
;
194 UCHAR
*lpBuffer
= NULL
;
195 SIZE_T RegionSize
= 0x10000;
196 LARGE_INTEGER BytesCopied
;
199 Status
= NtQueryInformationFile(
203 sizeof(FILE_BASIC_INFORMATION
),
204 FileBasicInformation
);
205 if( !NT_SUCCESS(Status
) ) {
206 DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status
);
211 RtlInitUnicodeString(&NewFileNameU
, lpNewFileName
);
213 InitializeObjectAttributes(&ObjectAttributes
,
215 OBJ_CASE_INSENSITIVE
,
219 Status
= NtCreateFile (&FileHandleNew
,
224 FILE_ATTRIBUTE_NORMAL
,
225 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
226 ReplaceIfExists
? FILE_OVERWRITE_IF
: FILE_CREATE
,
227 FILE_SYNCHRONOUS_IO_NONALERT
,
231 if( !NT_SUCCESS(Status
) ) {
232 DPRINT("NtCreateFile() failed (Status %lx)\n", Status
);
237 Status
= NtAllocateVirtualMemory(
242 MEM_RESERVE
| MEM_COMMIT
,
244 if( !NT_SUCCESS(Status
) ) {
245 DPRINT("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
247 SmpDeleteFile(lpNewFileName
);
250 BytesCopied
.QuadPart
= 0;
251 EndOfFileFound
= FALSE
;
252 while( !EndOfFileFound
253 && NT_SUCCESS(Status
) )
255 Status
= NtReadFile(FileHandle
,
264 if( NT_SUCCESS(Status
) ) {
265 Status
= NtWriteFile(FileHandleNew
,
271 IoStatusBlock
.Information
,
274 if( NT_SUCCESS(Status
) ) {
275 BytesCopied
.QuadPart
+= IoStatusBlock
.Information
;
278 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
282 if( STATUS_END_OF_FILE
== Status
) {
283 EndOfFileFound
= TRUE
;
284 Status
= STATUS_SUCCESS
;
287 DPRINT("NtWriteFile() failed (Status %lx)\n", Status
);
292 NtFreeVirtualMemory(NtCurrentProcess(),
297 Status
= NtQueryInformationFile(
301 sizeof(FILE_BASIC_INFORMATION
),
302 FileBasicInformation
);
303 if( !NT_SUCCESS(Status
) ) {
304 DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status
);
307 Status
= NtSetInformationFile(FileHandleNew
,
310 sizeof(FILE_BASIC_INFORMATION
),
311 FileBasicInformation
);
312 if( !NT_SUCCESS(Status
) ) {
313 DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status
);
315 NtClose(FileHandleNew
);
318 SmpDeleteFile(lpExistingFileName
);
330 * @name SmpMoveFilesQueryRoutine
332 * The SmpMoveFilesQueryRoutine function processes registry entries.
335 * The name of the value.
338 * The type of the value.
341 * The null-terminated data for the value.
344 * The length of ValueData.
349 * @param EntryContext
352 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
360 static NTSTATUS NTAPI
361 SmpMoveFilesQueryRoutine(IN PWSTR ValueName
,
364 IN ULONG ValueLength
,
366 IN PVOID EntryContext
)
369 static LPWSTR FistFileName
= NULL
;
371 DPRINT("SmpMoveFilesQueryRoutine() called \n");
372 DPRINT("ValueData = %S \n", (PWSTR
) ValueData
);
376 /* save a first file name */
377 FistFileName
= ValueData
;
378 Status
= STATUS_SUCCESS
;
382 if( 0 == *((LPWSTR
)ValueData
) ) {
383 /* delete if second file name is absent */
384 Status
= SmpDeleteFile( FistFileName
);
387 Status
= SmpMoveFile( FistFileName
, (LPCWSTR
)ValueData
);
397 * @name SmProcessFileRenameList
400 * The SmProcessFileRenameList function moves or deletes files thats have been added to the specify registry key for delayed moving.
404 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
408 * This function reads the following registry value:
409 * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations
410 * This registry value is of type REG_MULTI_SZ. The each operation is specifed as two file names.
411 * A first name is a source file, a second name is a destination file.
412 * In the case of deleting operation a second file name must be the empty string.
414 * szxSrcFile\0szxDestFile\0\0 <-- the szxSrcFile file will be renamed to the szxDestFile file
415 * szxSomeFile\0\0\0 <-- the szxSomeFile file will be removed
416 * After it will be done, the registry value will be deleted.
421 SmProcessFileRenameList( VOID
)
423 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
426 DPRINT("SmProcessFileRenameList() called\n");
428 RtlZeroMemory( &QueryTable
, sizeof(QueryTable
) );
429 QueryTable
[0].Name
= L
"PendingFileRenameOperations";
430 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DELETE
;
431 QueryTable
[0].DefaultType
= REG_NONE
;
432 QueryTable
[0].QueryRoutine
= SmpMoveFilesQueryRoutine
;
434 Status
= RtlQueryRegistryValues(
435 RTL_REGISTRY_CONTROL
,
436 L
"\\Session Manager",
441 if( !NT_SUCCESS(Status
) ) {
442 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
445 /* FIXME: RtlQueryRegistryValues can return an error status if the PendingFileRenameOperations value
446 does not exist, in this case smss hungs, therefore we always return STATUS_SUCCESS */
447 return (STATUS_SUCCESS
);