main
cpp 171 lines 6.52 KB
Raw
1 // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 #include "precomp.h"
4
5
6 // Exit macros
7 #define FileExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__)
8 #define FileExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__)
9 #define FileExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__)
10 #define FileExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__)
11 #define FileExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__)
12 #define FileExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_FILEUTIL, x, s, __VA_ARGS__)
13 #define FileExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_FILEUTIL, p, x, e, s, __VA_ARGS__)
14 #define FileExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_FILEUTIL, p, x, s, __VA_ARGS__)
15 #define FileExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_FILEUTIL, p, x, e, s, __VA_ARGS__)
16 #define FileExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_FILEUTIL, p, x, s, __VA_ARGS__)
17 #define FileExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_FILEUTIL, e, x, s, __VA_ARGS__)
18 #define FileExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_FILEUTIL, g, x, s, __VA_ARGS__)
19 #define FileExitOnPathFailure(x, b, s, ...) ExitOnPathFailureSource(DUTIL_SOURCE_FILEUTIL, x, b, s, __VA_ARGS__)
20
21 // constants
22
23 const LPCWSTR REGISTRY_PENDING_FILE_RENAME_KEY = L"SYSTEM\\CurrentControlSet\\Control\\Session Manager";
24 const LPCWSTR REGISTRY_PENDING_FILE_RENAME_VALUE = L"PendingFileRenameOperations";
25
26
27 /*******************************************************************
28 FileExistsAfterRestart - checks that a file exists and will continue
29 to exist after restart.
30
31 ********************************************************************/
32 extern "C" BOOL DAPI FileExistsAfterRestart(
33 __in_z LPCWSTR wzPath,
34 __out_opt DWORD *pdwAttributes
35 )
36 {
37 HRESULT hr = S_OK;
38 BOOL fExists = FALSE;
39 BOOL fRegExists = FALSE;
40 HKEY hkPendingFileRename = NULL;
41 LPWSTR* rgsczRenames = NULL;
42 DWORD cRenames = 0;
43 BOOL fPathEqual = FALSE;
44
45 fExists = FileExistsEx(wzPath, pdwAttributes);
46 if (fExists)
47 {
48 hr = RegOpen(HKEY_LOCAL_MACHINE, REGISTRY_PENDING_FILE_RENAME_KEY, KEY_QUERY_VALUE, &hkPendingFileRename);
49 FileExitOnPathFailure(hr, fRegExists, "Failed to open pending file rename registry key.");
50
51 if (!fRegExists)
52 {
53 ExitFunction();
54 }
55
56 hr = RegReadStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, &rgsczRenames, &cRenames);
57 FileExitOnPathFailure(hr, fRegExists, "Failed to read pending file renames.");
58
59 if (!fRegExists)
60 {
61 ExitFunction();
62 }
63
64 // The pending file renames array is pairs of source and target paths. We only care
65 // about checking the source paths so skip the target paths (i += 2).
66 for (DWORD i = 0; i < cRenames; i += 2)
67 {
68 LPWSTR wzRename = rgsczRenames[i];
69 if (wzRename && *wzRename)
70 {
71 hr = PathCompareCanonicalized(wzPath, wzRename, &fPathEqual);
72 FileExitOnFailure(hr, "Failed to compare path from pending file rename to check path.");
73
74 if (fPathEqual)
75 {
76 fExists = FALSE;
77 break;
78 }
79 }
80 }
81 }
82
83 LExit:
84 ReleaseStrArray(rgsczRenames, cRenames);
85 ReleaseRegKey(hkPendingFileRename);
86
87 return fExists;
88 }
89
90
91 /*******************************************************************
92 FileRemoveFromPendingRename - removes the file path from the pending
93 file rename list.
94
95 ********************************************************************/
96 extern "C" HRESULT DAPI FileRemoveFromPendingRename(
97 __in_z LPCWSTR wzPath
98 )
99 {
100 HRESULT hr = S_OK;
101 HKEY hkPendingFileRename = NULL;
102 BOOL fExists = FALSE;
103 LPWSTR* rgsczRenames = NULL;
104 DWORD cRenames = 0;
105 BOOL fPathEqual = FALSE;
106 BOOL fRemoved = FALSE;
107 DWORD cNewRenames = 0;
108
109 hr = RegOpen(HKEY_LOCAL_MACHINE, REGISTRY_PENDING_FILE_RENAME_KEY, KEY_QUERY_VALUE | KEY_SET_VALUE, &hkPendingFileRename);
110 FileExitOnPathFailure(hr, fExists, "Failed to open pending file rename registry key.");
111
112 if (!fExists)
113 {
114 ExitFunction();
115 }
116
117 hr = RegReadStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, &rgsczRenames, &cRenames);
118 FileExitOnPathFailure(hr, fExists, "Failed to read pending file renames.");
119
120 if (!fExists)
121 {
122 ExitFunction();
123 }
124
125 // The pending file renames array is pairs of source and target paths. We only care
126 // about checking the source paths so skip the target paths (i += 2).
127 for (DWORD i = 0; i < cRenames; i += 2)
128 {
129 LPWSTR wzRename = rgsczRenames[i];
130 if (wzRename && *wzRename)
131 {
132 hr = PathCompareCanonicalized(wzPath, wzRename, &fPathEqual);
133 FileExitOnFailure(hr, "Failed to compare path from pending file rename to check path.");
134
135 // If we find our path in the list, null out the source and target slot and
136 // we'll compact the array next.
137 if (fPathEqual)
138 {
139 ReleaseNullStr(rgsczRenames[i]);
140 ReleaseNullStr(rgsczRenames[i + 1]);
141 fRemoved = TRUE;
142 }
143 }
144 }
145
146 if (fRemoved)
147 {
148 // Compact the array by removing any nulls.
149 for (DWORD i = 0; i < cRenames; ++i)
150 {
151 LPWSTR wzRename = rgsczRenames[i];
152 if (wzRename)
153 {
154 rgsczRenames[cNewRenames] = wzRename;
155 ++cNewRenames;
156 }
157 }
158
159 cRenames = cNewRenames; // ignore the pointers on the end of the array since an early index points to them already.
160
161 // Write the new array back to the pending file rename key.
162 hr = RegWriteStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, rgsczRenames, cRenames);
163 FileExitOnFailure(hr, "Failed to update pending file renames.");
164 }
165
166 LExit:
167 ReleaseStrArray(rgsczRenames, cRenames);
168 ReleaseRegKey(hkPendingFileRename);
169
170 return hr;
171 }