* Sync up to trunk r55544.
[reactos.git] / base / system / smss / initmv.c
1 /*
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
7 */
8
9 /* INCLUDES ******************************************************************/
10 #include "smss.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 #if 0
16
17 /* FUNCTIONS *****************************************************************/
18
19 /*++
20 * @name SmpDeleteFile
21 *
22 * The SmpDeleteFile function deletes a specify file.
23 *
24 * @param lpFileName
25 * the name of a file which should be deleted
26 *
27 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
28 * othwerwise.
29 *
30 * @remarks
31 * This function is called by SmpMoveFilesQueryRoutine().
32 *
33 *
34 *--*/
35 NTSTATUS
36 SmpDeleteFile( IN LPCWSTR lpFileName )
37 {
38 FILE_DISPOSITION_INFORMATION FileDispInfo;
39 OBJECT_ATTRIBUTES ObjectAttributes;
40 IO_STATUS_BLOCK IoStatusBlock;
41 UNICODE_STRING FileNameU;
42 HANDLE FileHandle;
43 NTSTATUS Status;
44
45 DPRINT("SmpDeleteFile ( %S )\n", lpFileName);
46
47 if( !lpFileName )
48 return (STATUS_INVALID_PARAMETER);
49
50 RtlInitUnicodeString(&FileNameU, lpFileName);
51
52 InitializeObjectAttributes(&ObjectAttributes,
53 &FileNameU,
54 OBJ_CASE_INSENSITIVE,
55 NULL,
56 NULL);
57
58 Status = NtCreateFile (&FileHandle,
59 DELETE,
60 &ObjectAttributes,
61 &IoStatusBlock,
62 NULL,
63 FILE_ATTRIBUTE_NORMAL,
64 FILE_SHARE_READ | FILE_SHARE_WRITE,
65 FILE_OPEN,
66 FILE_SYNCHRONOUS_IO_NONALERT,
67 NULL,
68 0);
69
70 if( !NT_SUCCESS(Status) ) {
71 DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
72 return (Status);
73 }
74
75 FileDispInfo.DeleteFile = TRUE;
76
77 Status = NtSetInformationFile(
78 FileHandle,
79 &IoStatusBlock,
80 &FileDispInfo,
81 sizeof(FILE_DISPOSITION_INFORMATION),
82 FileDispositionInformation );
83
84 NtClose(FileHandle);
85
86 return (Status);
87 }
88
89
90 /*++
91 * @name SmpMoveFile
92 *
93 * The SmpMoveFile function deletes a specify file.
94 *
95 * @param lpExistingFileName
96 * the name of an existing file which should be removed
97 *
98 * @param lpNewFileName
99 * a new name of an existing file.
100 *
101 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
102 * othwerwise.
103 *
104 * @remarks
105 * This function called from the SmpMoveFilesQueryRoutine function.
106 *
107 *
108 *--*/
109 NTSTATUS
110 SmpMoveFile( IN LPCWSTR lpExistingFileName,
111 IN LPCWSTR lpNewFileName
112 )
113 {
114 PFILE_RENAME_INFORMATION FileRenameInfo;
115 OBJECT_ATTRIBUTES ObjectAttributes;
116 IO_STATUS_BLOCK IoStatusBlock;
117 UNICODE_STRING ExistingFileNameU;
118 HANDLE FileHandle;
119 DWORD FileNameSize;
120 BOOLEAN ReplaceIfExists;
121 NTSTATUS Status;
122
123 if( !lpExistingFileName || !lpNewFileName )
124 return (STATUS_INVALID_PARAMETER);
125
126 DPRINT("SmpMoveFile (%S, %S)\n", lpExistingFileName, lpNewFileName);
127
128 RtlInitUnicodeString(&ExistingFileNameU, lpExistingFileName);
129
130 InitializeObjectAttributes(&ObjectAttributes,
131 &ExistingFileNameU,
132 OBJ_CASE_INSENSITIVE,
133 NULL,
134 NULL);
135
136 Status = NtCreateFile (&FileHandle,
137 FILE_ALL_ACCESS,
138 &ObjectAttributes,
139 &IoStatusBlock,
140 NULL,
141 FILE_ATTRIBUTE_NORMAL,
142 FILE_SHARE_READ | FILE_SHARE_WRITE,
143 FILE_OPEN,
144 FILE_SYNCHRONOUS_IO_NONALERT,
145 NULL,
146 0);
147
148 if( !NT_SUCCESS(Status) ) {
149 DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
150 return (Status);
151 }
152
153 FileNameSize = wcslen(lpNewFileName)*sizeof(*lpNewFileName);
154 FileRenameInfo = RtlAllocateHeap(
155 RtlGetProcessHeap(),
156 HEAP_ZERO_MEMORY,
157 sizeof(FILE_RENAME_INFORMATION)+FileNameSize);
158 if( !FileRenameInfo ) {
159 DPRINT("RtlAllocateHeap failed\n");
160 NtClose(FileHandle);
161 return (STATUS_NO_MEMORY);
162 }
163
164 if( L'!' == *lpNewFileName ) {
165 lpNewFileName++;
166 FileNameSize -= sizeof(*lpNewFileName);
167 ReplaceIfExists = TRUE;
168 }
169 else {
170 ReplaceIfExists = FALSE;
171 }
172
173 FileRenameInfo->RootDirectory = NULL;
174 FileRenameInfo->ReplaceIfExists = ReplaceIfExists;
175 FileRenameInfo->FileNameLength = FileNameSize;
176 RtlCopyMemory(FileRenameInfo->FileName, lpNewFileName, FileNameSize);
177
178 Status = NtSetInformationFile(
179 FileHandle,
180 &IoStatusBlock,
181 FileRenameInfo,
182 sizeof(FILE_RENAME_INFORMATION)+FileNameSize,
183 FileRenameInformation );
184
185 RtlFreeHeap(RtlGetProcessHeap(), 0, FileRenameInfo);
186
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 )
190 {
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;
197 BOOL EndOfFileFound;
198
199 Status = NtQueryInformationFile(
200 FileHandle,
201 &IoStatusBlock,
202 &FileBasicInfo,
203 sizeof(FILE_BASIC_INFORMATION),
204 FileBasicInformation);
205 if( !NT_SUCCESS(Status) ) {
206 DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
207 NtClose(FileHandle);
208 return (Status);
209 }
210
211 RtlInitUnicodeString(&NewFileNameU, lpNewFileName);
212
213 InitializeObjectAttributes(&ObjectAttributes,
214 &NewFileNameU,
215 OBJ_CASE_INSENSITIVE,
216 NULL,
217 NULL);
218
219 Status = NtCreateFile (&FileHandleNew,
220 FILE_ALL_ACCESS,
221 &ObjectAttributes,
222 &IoStatusBlock,
223 NULL,
224 FILE_ATTRIBUTE_NORMAL,
225 FILE_SHARE_READ | FILE_SHARE_WRITE,
226 ReplaceIfExists ? FILE_OVERWRITE_IF : FILE_CREATE,
227 FILE_SYNCHRONOUS_IO_NONALERT,
228 NULL,
229 0);
230
231 if( !NT_SUCCESS(Status) ) {
232 DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
233 NtClose(FileHandle);
234 return (Status);
235 }
236
237 Status = NtAllocateVirtualMemory(
238 NtCurrentProcess(),
239 (PVOID *)&lpBuffer,
240 2,
241 &RegionSize,
242 MEM_RESERVE | MEM_COMMIT,
243 PAGE_READWRITE);
244 if( !NT_SUCCESS(Status) ) {
245 DPRINT("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
246 NtClose(FileHandle);
247 SmpDeleteFile(lpNewFileName);
248 return (Status);
249 }
250 BytesCopied.QuadPart = 0;
251 EndOfFileFound = FALSE;
252 while( !EndOfFileFound
253 && NT_SUCCESS(Status) )
254 {
255 Status = NtReadFile(FileHandle,
256 NULL,
257 NULL,
258 NULL,
259 &IoStatusBlock,
260 lpBuffer,
261 RegionSize,
262 NULL,
263 NULL);
264 if( NT_SUCCESS(Status) ) {
265 Status = NtWriteFile(FileHandleNew,
266 NULL,
267 NULL,
268 NULL,
269 &IoStatusBlock,
270 lpBuffer,
271 IoStatusBlock.Information,
272 NULL,
273 NULL);
274 if( NT_SUCCESS(Status) ) {
275 BytesCopied.QuadPart += IoStatusBlock.Information;
276 }
277 else {
278 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
279 }
280 }
281 else {
282 if( STATUS_END_OF_FILE == Status ) {
283 EndOfFileFound = TRUE;
284 Status = STATUS_SUCCESS;
285 }
286 else {
287 DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
288 }
289 }
290 }
291
292 NtFreeVirtualMemory(NtCurrentProcess(),
293 (PVOID *)&lpBuffer,
294 &RegionSize,
295 MEM_RELEASE);
296
297 Status = NtQueryInformationFile(
298 FileHandleNew,
299 &IoStatusBlock,
300 &FileBasicInfo,
301 sizeof(FILE_BASIC_INFORMATION),
302 FileBasicInformation);
303 if( !NT_SUCCESS(Status) ) {
304 DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
305 }
306
307 Status = NtSetInformationFile(FileHandleNew,
308 &IoStatusBlock,
309 &FileBasicInfo,
310 sizeof(FILE_BASIC_INFORMATION),
311 FileBasicInformation);
312 if( !NT_SUCCESS(Status) ) {
313 DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
314 }
315 NtClose(FileHandleNew);
316 NtClose(FileHandle);
317
318 SmpDeleteFile(lpExistingFileName);
319
320 return (Status);
321 }
322
323 NtClose(FileHandle);
324
325 return (Status);
326 }
327
328
329 /*++
330 * @name SmpMoveFilesQueryRoutine
331 *
332 * The SmpMoveFilesQueryRoutine function processes registry entries.
333 *
334 * @param ValueName
335 * The name of the value.
336 *
337 * @param ValueType
338 * The type of the value.
339 *
340 * @param ValueData
341 * The null-terminated data for the value.
342 *
343 * @param ValueLength
344 * The length of ValueData.
345 *
346 * @param Context
347 * NULL
348 *
349 * @param EntryContext
350 * NULL
351 *
352 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
353 * othwerwise.
354 *
355 * @remarks
356 *
357 *
358 *
359 *--*/
360 static NTSTATUS NTAPI
361 SmpMoveFilesQueryRoutine(IN PWSTR ValueName,
362 IN ULONG ValueType,
363 IN PVOID ValueData,
364 IN ULONG ValueLength,
365 IN PVOID Context,
366 IN PVOID EntryContext)
367 {
368 NTSTATUS Status;
369 static LPWSTR FistFileName = NULL;
370
371 DPRINT("SmpMoveFilesQueryRoutine() called \n");
372 DPRINT("ValueData = %S \n", (PWSTR) ValueData);
373
374 if( !FistFileName )
375 {
376 /* save a first file name */
377 FistFileName = ValueData;
378 Status = STATUS_SUCCESS;
379 }
380 else
381 {
382 if( 0 == *((LPWSTR)ValueData) ) {
383 /* delete if second file name is absent */
384 Status = SmpDeleteFile( FistFileName );
385 } else {
386 /* remove a file */
387 Status = SmpMoveFile( FistFileName, (LPCWSTR)ValueData );
388 }
389 FistFileName = NULL;
390 }
391
392 return Status;
393 }
394
395
396 /*++
397 * @name SmProcessFileRenameList
398 * @implemented
399 *
400 * The SmProcessFileRenameList function moves or deletes files thats have been added to the specify registry key for delayed moving.
401 *
402 * @param VOID
403 *
404 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
405 * othwerwise.
406 *
407 * @remarks
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.
413 * For exapmle:
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.
417 *
418 *
419 *--*/
420 NTSTATUS
421 SmProcessFileRenameList( VOID )
422 {
423 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
424 NTSTATUS Status;
425
426 DPRINT("SmProcessFileRenameList() called\n");
427
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;
433
434 Status = RtlQueryRegistryValues(
435 RTL_REGISTRY_CONTROL,
436 L"\\Session Manager",
437 QueryTable,
438 NULL,
439 NULL);
440
441 if( !NT_SUCCESS(Status) ) {
442 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
443 }
444
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);
448 }
449
450 #endif
451
452 /* EOF */