diff options
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/file2utl.cpp')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/file2utl.cpp | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/file2utl.cpp b/src/libs/dutil/WixToolset.DUtil/file2utl.cpp new file mode 100644 index 00000000..88f8377c --- /dev/null +++ b/src/libs/dutil/WixToolset.DUtil/file2utl.cpp | |||
@@ -0,0 +1,164 @@ | |||
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 | |||
20 | // constants | ||
21 | |||
22 | const LPCWSTR REGISTRY_PENDING_FILE_RENAME_KEY = L"SYSTEM\\CurrentControlSet\\Control\\Session Manager"; | ||
23 | const LPCWSTR REGISTRY_PENDING_FILE_RENAME_VALUE = L"PendingFileRenameOperations"; | ||
24 | |||
25 | |||
26 | /******************************************************************* | ||
27 | FileExistsAfterRestart - checks that a file exists and will continue | ||
28 | to exist after restart. | ||
29 | |||
30 | ********************************************************************/ | ||
31 | extern "C" BOOL DAPI FileExistsAfterRestart( | ||
32 | __in_z LPCWSTR wzPath, | ||
33 | __out_opt DWORD *pdwAttributes | ||
34 | ) | ||
35 | { | ||
36 | HRESULT hr = S_OK; | ||
37 | BOOL fExists = FALSE; | ||
38 | HKEY hkPendingFileRename = NULL; | ||
39 | LPWSTR* rgsczRenames = NULL; | ||
40 | DWORD cRenames = 0; | ||
41 | BOOL fPathEqual = FALSE; | ||
42 | |||
43 | fExists = FileExistsEx(wzPath, pdwAttributes); | ||
44 | if (fExists) | ||
45 | { | ||
46 | hr = RegOpen(HKEY_LOCAL_MACHINE, REGISTRY_PENDING_FILE_RENAME_KEY, KEY_QUERY_VALUE, &hkPendingFileRename); | ||
47 | if (E_FILENOTFOUND == hr) | ||
48 | { | ||
49 | ExitFunction1(hr = S_OK); | ||
50 | } | ||
51 | FileExitOnFailure(hr, "Failed to open pending file rename registry key."); | ||
52 | |||
53 | hr = RegReadStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, &rgsczRenames, &cRenames); | ||
54 | if (E_FILENOTFOUND == hr) | ||
55 | { | ||
56 | ExitFunction1(hr = S_OK); | ||
57 | } | ||
58 | FileExitOnFailure(hr, "Failed to read pending file renames."); | ||
59 | |||
60 | // The pending file renames array is pairs of source and target paths. We only care | ||
61 | // about checking the source paths so skip the target paths (i += 2). | ||
62 | for (DWORD i = 0; i < cRenames; i += 2) | ||
63 | { | ||
64 | LPWSTR wzRename = rgsczRenames[i]; | ||
65 | if (wzRename && *wzRename) | ||
66 | { | ||
67 | hr = PathCompareCanonicalized(wzPath, wzRename, &fPathEqual); | ||
68 | FileExitOnFailure(hr, "Failed to compare path from pending file rename to check path."); | ||
69 | |||
70 | if (fPathEqual) | ||
71 | { | ||
72 | fExists = FALSE; | ||
73 | break; | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | } | ||
78 | |||
79 | LExit: | ||
80 | ReleaseStrArray(rgsczRenames, cRenames); | ||
81 | ReleaseRegKey(hkPendingFileRename); | ||
82 | |||
83 | return fExists; | ||
84 | } | ||
85 | |||
86 | |||
87 | /******************************************************************* | ||
88 | FileRemoveFromPendingRename - removes the file path from the pending | ||
89 | file rename list. | ||
90 | |||
91 | ********************************************************************/ | ||
92 | extern "C" HRESULT DAPI FileRemoveFromPendingRename( | ||
93 | __in_z LPCWSTR wzPath | ||
94 | ) | ||
95 | { | ||
96 | HRESULT hr = S_OK; | ||
97 | HKEY hkPendingFileRename = NULL; | ||
98 | LPWSTR* rgsczRenames = NULL; | ||
99 | DWORD cRenames = 0; | ||
100 | BOOL fPathEqual = FALSE; | ||
101 | BOOL fRemoved = FALSE; | ||
102 | DWORD cNewRenames = 0; | ||
103 | |||
104 | hr = RegOpen(HKEY_LOCAL_MACHINE, REGISTRY_PENDING_FILE_RENAME_KEY, KEY_QUERY_VALUE | KEY_SET_VALUE, &hkPendingFileRename); | ||
105 | if (E_FILENOTFOUND == hr) | ||
106 | { | ||
107 | ExitFunction1(hr = S_OK); | ||
108 | } | ||
109 | FileExitOnFailure(hr, "Failed to open pending file rename registry key."); | ||
110 | |||
111 | hr = RegReadStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, &rgsczRenames, &cRenames); | ||
112 | if (E_FILENOTFOUND == hr) | ||
113 | { | ||
114 | ExitFunction1(hr = S_OK); | ||
115 | } | ||
116 | FileExitOnFailure(hr, "Failed to read pending file renames."); | ||
117 | |||
118 | // The pending file renames array is pairs of source and target paths. We only care | ||
119 | // about checking the source paths so skip the target paths (i += 2). | ||
120 | for (DWORD i = 0; i < cRenames; i += 2) | ||
121 | { | ||
122 | LPWSTR wzRename = rgsczRenames[i]; | ||
123 | if (wzRename && *wzRename) | ||
124 | { | ||
125 | hr = PathCompareCanonicalized(wzPath, wzRename, &fPathEqual); | ||
126 | FileExitOnFailure(hr, "Failed to compare path from pending file rename to check path."); | ||
127 | |||
128 | // If we find our path in the list, null out the source and target slot and | ||
129 | // we'll compact the array next. | ||
130 | if (fPathEqual) | ||
131 | { | ||
132 | ReleaseNullStr(rgsczRenames[i]); | ||
133 | ReleaseNullStr(rgsczRenames[i + 1]); | ||
134 | fRemoved = TRUE; | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | |||
139 | if (fRemoved) | ||
140 | { | ||
141 | // Compact the array by removing any nulls. | ||
142 | for (DWORD i = 0; i < cRenames; ++i) | ||
143 | { | ||
144 | LPWSTR wzRename = rgsczRenames[i]; | ||
145 | if (wzRename) | ||
146 | { | ||
147 | rgsczRenames[cNewRenames] = wzRename; | ||
148 | ++cNewRenames; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | cRenames = cNewRenames; // ignore the pointers on the end of the array since an early index points to them already. | ||
153 | |||
154 | // Write the new array back to the pending file rename key. | ||
155 | hr = RegWriteStringArray(hkPendingFileRename, REGISTRY_PENDING_FILE_RENAME_VALUE, rgsczRenames, cRenames); | ||
156 | FileExitOnFailure(hr, "Failed to update pending file renames."); | ||
157 | } | ||
158 | |||
159 | LExit: | ||
160 | ReleaseStrArray(rgsczRenames, cRenames); | ||
161 | ReleaseRegKey(hkPendingFileRename); | ||
162 | |||
163 | return hr; | ||
164 | } | ||