diff options
| author | Sean Hall <r.sean.hall@gmail.com> | 2022-06-03 17:48:39 -0500 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2022-06-07 19:44:36 -0500 |
| commit | 6b0f2d978504da82070523eb6adb0b59f9812e93 (patch) | |
| tree | 6f0b258519a0f51bf589e4313206b3ffeaa32a41 /src/libs/dutil/WixToolset.DUtil/pathutil.cpp | |
| parent | b652e93a460b4b822a01382e5992f96f1d805ffe (diff) | |
| download | wix-6b0f2d978504da82070523eb6adb0b59f9812e93.tar.gz wix-6b0f2d978504da82070523eb6adb0b59f9812e93.tar.bz2 wix-6b0f2d978504da82070523eb6adb0b59f9812e93.zip | |
Add PathSkipPastRoot.
Diffstat (limited to '')
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/pathutil.cpp | 296 |
1 files changed, 178 insertions, 118 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp index abbf4d4b..1ac76626 100644 --- a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp | |||
| @@ -120,13 +120,34 @@ LExit: | |||
| 120 | 120 | ||
| 121 | DAPI_(HRESULT) PathGetParentPath( | 121 | DAPI_(HRESULT) PathGetParentPath( |
| 122 | __in_z LPCWSTR wzPath, | 122 | __in_z LPCWSTR wzPath, |
| 123 | __out_z LPWSTR *psczParent | 123 | __out_z LPWSTR* psczParent, |
| 124 | __out_opt SIZE_T* pcchRoot | ||
| 124 | ) | 125 | ) |
| 125 | { | 126 | { |
| 126 | HRESULT hr = S_OK; | 127 | HRESULT hr = S_OK; |
| 128 | LPCWSTR wzPastRoot = NULL; | ||
| 127 | LPCWSTR wzParent = NULL; | 129 | LPCWSTR wzParent = NULL; |
| 130 | LPCWSTR wz = NULL; | ||
| 128 | 131 | ||
| 129 | for (LPCWSTR wz = wzPath; *wz; ++wz) | 132 | wzPastRoot = PathSkipPastRoot(wzPath, NULL, NULL, NULL); |
| 133 | |||
| 134 | if (pcchRoot) | ||
| 135 | { | ||
| 136 | *pcchRoot = !wzPastRoot ? 0 : wzPastRoot - wzPath; | ||
| 137 | } | ||
| 138 | |||
| 139 | if (wzPastRoot && *wzPastRoot) | ||
| 140 | { | ||
| 141 | Assert(wzPastRoot > wzPath); | ||
| 142 | wz = wzPastRoot; | ||
| 143 | wzParent = wzPastRoot - 1; | ||
| 144 | } | ||
| 145 | else | ||
| 146 | { | ||
| 147 | wz = wzPath; | ||
| 148 | } | ||
| 149 | |||
| 150 | for (; *wz; ++wz) | ||
| 130 | { | 151 | { |
| 131 | if (IsPathSeparatorChar(*wz) && wz[1]) | 152 | if (IsPathSeparatorChar(*wz) && wz[1]) |
| 132 | { | 153 | { |
| @@ -143,7 +164,7 @@ DAPI_(HRESULT) PathGetParentPath( | |||
| 143 | } | 164 | } |
| 144 | else | 165 | else |
| 145 | { | 166 | { |
| 146 | ReleaseNullStr(psczParent); | 167 | ReleaseNullStr(*psczParent); |
| 147 | } | 168 | } |
| 148 | 169 | ||
| 149 | LExit: | 170 | LExit: |
| @@ -164,9 +185,8 @@ DAPI_(HRESULT) PathExpand( | |||
| 164 | LPWSTR sczExpandedPath = NULL; | 185 | LPWSTR sczExpandedPath = NULL; |
| 165 | SIZE_T cchWritten = 0; | 186 | SIZE_T cchWritten = 0; |
| 166 | DWORD cchExpandedPath = 0; | 187 | DWORD cchExpandedPath = 0; |
| 167 | SIZE_T cbSize = 0; | ||
| 168 | |||
| 169 | LPWSTR sczFullPath = NULL; | 188 | LPWSTR sczFullPath = NULL; |
| 189 | DWORD dwPrefixFlags = 0; | ||
| 170 | 190 | ||
| 171 | // | 191 | // |
| 172 | // First, expand any environment variables. | 192 | // First, expand any environment variables. |
| @@ -201,20 +221,7 @@ DAPI_(HRESULT) PathExpand( | |||
| 201 | } | 221 | } |
| 202 | } | 222 | } |
| 203 | 223 | ||
| 204 | if (MAX_PATH < cch) | 224 | cchWritten = cch; |
| 205 | { | ||
| 206 | hr = PathPrefix(&sczExpandedPath); // ignore invald arg from path prefix because this may not be a complete path yet | ||
| 207 | if (E_INVALIDARG == hr) | ||
| 208 | { | ||
| 209 | hr = S_OK; | ||
| 210 | } | ||
| 211 | PathExitOnFailure(hr, "Failed to prefix long path after expanding environment variables."); | ||
| 212 | |||
| 213 | hr = StrMaxLength(sczExpandedPath, &cbSize); | ||
| 214 | PathExitOnFailure(hr, "Failed to get max length of expanded path."); | ||
| 215 | |||
| 216 | cchExpandedPath = (DWORD)min(DWORD_MAX, cbSize); | ||
| 217 | } | ||
| 218 | } | 225 | } |
| 219 | 226 | ||
| 220 | // | 227 | // |
| @@ -227,11 +234,7 @@ DAPI_(HRESULT) PathExpand( | |||
| 227 | hr = PathGetFullPathName(wzPath, &sczFullPath, NULL, &cchWritten); | 234 | hr = PathGetFullPathName(wzPath, &sczFullPath, NULL, &cchWritten); |
| 228 | PathExitOnFailure(hr, "Failed to get full path for string: %ls", wzPath); | 235 | PathExitOnFailure(hr, "Failed to get full path for string: %ls", wzPath); |
| 229 | 236 | ||
| 230 | if (MAX_PATH < cchWritten) | 237 | dwPrefixFlags |= PATH_PREFIX_EXPECT_FULLY_QUALIFIED; |
| 231 | { | ||
| 232 | hr = PathPrefix(&sczFullPath); | ||
| 233 | PathExitOnFailure(hr, "Failed to prefix long path after expanding."); | ||
| 234 | } | ||
| 235 | } | 238 | } |
| 236 | else | 239 | else |
| 237 | { | 240 | { |
| @@ -239,6 +242,12 @@ DAPI_(HRESULT) PathExpand( | |||
| 239 | sczExpandedPath = NULL; | 242 | sczExpandedPath = NULL; |
| 240 | } | 243 | } |
| 241 | 244 | ||
| 245 | if (dwResolveFlags) | ||
| 246 | { | ||
| 247 | hr = PathPrefix(&sczFullPath, cchWritten, dwPrefixFlags); | ||
| 248 | PathExitOnFailure(hr, "Failed to prefix path after expanding."); | ||
| 249 | } | ||
| 250 | |||
| 242 | hr = StrAllocString(psczFullPath, sczFullPath ? sczFullPath : wzRelativePath, 0); | 251 | hr = StrAllocString(psczFullPath, sczFullPath ? sczFullPath : wzRelativePath, 0); |
| 243 | PathExitOnFailure(hr, "Failed to copy relative path into full path."); | 252 | PathExitOnFailure(hr, "Failed to copy relative path into full path."); |
| 244 | 253 | ||
| @@ -319,29 +328,54 @@ LExit: | |||
| 319 | 328 | ||
| 320 | 329 | ||
| 321 | DAPI_(HRESULT) PathPrefix( | 330 | DAPI_(HRESULT) PathPrefix( |
| 322 | __inout LPWSTR *psczFullPath | 331 | __inout_z LPWSTR* psczFullPath, |
| 332 | __in SIZE_T cchFullPath, | ||
| 333 | __in DWORD dwPrefixFlags | ||
| 323 | ) | 334 | ) |
| 324 | { | 335 | { |
| 325 | Assert(psczFullPath && *psczFullPath); | 336 | Assert(psczFullPath); |
| 326 | 337 | ||
| 327 | HRESULT hr = S_OK; | 338 | HRESULT hr = S_OK; |
| 328 | LPWSTR wzFullPath = *psczFullPath; | 339 | LPWSTR wzFullPath = *psczFullPath; |
| 329 | BOOL fFullyQualified = FALSE; | 340 | BOOL fFullyQualified = FALSE; |
| 330 | BOOL fHasPrefix = FALSE; | 341 | BOOL fHasPrefix = FALSE; |
| 342 | BOOL fUNC = FALSE; | ||
| 331 | SIZE_T cbFullPath = 0; | 343 | SIZE_T cbFullPath = 0; |
| 332 | 344 | ||
| 333 | fFullyQualified = PathIsFullyQualified(wzFullPath, &fHasPrefix); | 345 | PathSkipPastRoot(wzFullPath, &fHasPrefix, &fFullyQualified, &fUNC); |
| 346 | |||
| 334 | if (fHasPrefix) | 347 | if (fHasPrefix) |
| 335 | { | 348 | { |
| 336 | ExitFunction(); | 349 | ExitFunction(); |
| 337 | } | 350 | } |
| 338 | 351 | ||
| 339 | if (fFullyQualified && L':' == wzFullPath[1]) // normal path | 352 | // The prefix is only allowed on fully qualified paths. |
| 353 | if (!fFullyQualified) | ||
| 340 | { | 354 | { |
| 341 | hr = StrAllocPrefix(psczFullPath, L"\\\\?\\", 4); | 355 | if (dwPrefixFlags & PATH_PREFIX_EXPECT_FULLY_QUALIFIED) |
| 342 | PathExitOnFailure(hr, "Failed to add prefix to file path."); | 356 | { |
| 357 | PathExitWithRootFailure(hr, E_INVALIDARG, "Expected fully qualified path provided to prefix: %ls.", wzFullPath); | ||
| 358 | } | ||
| 359 | |||
| 360 | ExitFunction(); | ||
| 361 | } | ||
| 362 | |||
| 363 | if (!(dwPrefixFlags & PATH_PREFIX_SHORT_PATHS)) | ||
| 364 | { | ||
| 365 | // The prefix is not necessary unless the path is longer than MAX_PATH. | ||
| 366 | if (!cchFullPath) | ||
| 367 | { | ||
| 368 | hr = ::StringCchLengthW(wzFullPath, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cchFullPath)); | ||
| 369 | PathExitOnFailure(hr, "Failed to get length of path to prefix."); | ||
| 370 | } | ||
| 371 | |||
| 372 | if (MAX_PATH >= cchFullPath) | ||
| 373 | { | ||
| 374 | ExitFunction(); | ||
| 375 | } | ||
| 343 | } | 376 | } |
| 344 | else if (fFullyQualified && IsPathSeparatorChar(wzFullPath[1])) // UNC | 377 | |
| 378 | if (fUNC) | ||
| 345 | { | 379 | { |
| 346 | hr = StrSize(*psczFullPath, &cbFullPath); | 380 | hr = StrSize(*psczFullPath, &cbFullPath); |
| 347 | PathExitOnFailure(hr, "Failed to get size of full path."); | 381 | PathExitOnFailure(hr, "Failed to get size of full path."); |
| @@ -352,10 +386,10 @@ DAPI_(HRESULT) PathPrefix( | |||
| 352 | hr = StrAllocPrefix(psczFullPath, L"\\\\?\\UNC", 7); | 386 | hr = StrAllocPrefix(psczFullPath, L"\\\\?\\UNC", 7); |
| 353 | PathExitOnFailure(hr, "Failed to add prefix to UNC path."); | 387 | PathExitOnFailure(hr, "Failed to add prefix to UNC path."); |
| 354 | } | 388 | } |
| 355 | else | 389 | else // must be a normal path |
| 356 | { | 390 | { |
| 357 | hr = E_INVALIDARG; | 391 | hr = StrAllocPrefix(psczFullPath, L"\\\\?\\", 4); |
| 358 | PathExitOnFailure(hr, "Invalid path provided to prefix: %ls.", wzFullPath); | 392 | PathExitOnFailure(hr, "Failed to add prefix to file path."); |
| 359 | } | 393 | } |
| 360 | 394 | ||
| 361 | LExit: | 395 | LExit: |
| @@ -970,55 +1004,114 @@ LExit: | |||
| 970 | } | 1004 | } |
| 971 | 1005 | ||
| 972 | 1006 | ||
| 973 | DAPI_(BOOL) PathIsFullyQualified( | 1007 | DAPI_(LPCWSTR) PathSkipPastRoot( |
| 974 | __in_z LPCWSTR wzPath, | 1008 | __in_z_opt LPCWSTR wzPath, |
| 975 | __out_opt BOOL* pfHasLongPathPrefix | 1009 | __out_opt BOOL* pfHasExtendedPrefix, |
| 1010 | __out_opt BOOL* pfFullyQualified, | ||
| 1011 | __out_opt BOOL* pfUNC | ||
| 976 | ) | 1012 | ) |
| 977 | { | 1013 | { |
| 1014 | LPCWSTR wzPastRoot = NULL; | ||
| 1015 | BOOL fHasPrefix = FALSE; | ||
| 978 | BOOL fFullyQualified = FALSE; | 1016 | BOOL fFullyQualified = FALSE; |
| 979 | BOOL fHasLongPathPrefix = FALSE; | 1017 | BOOL fUNC = FALSE; |
| 1018 | DWORD dwRootMissingSlashes = 0; | ||
| 980 | 1019 | ||
| 981 | if (!wzPath || !wzPath[0] || !wzPath[1]) | 1020 | if (!wzPath || !*wzPath) |
| 982 | { | 1021 | { |
| 983 | // There is no way to specify a fully qualified path with one character (or less). | ||
| 984 | ExitFunction(); | 1022 | ExitFunction(); |
| 985 | } | 1023 | } |
| 986 | 1024 | ||
| 987 | if (!IsPathSeparatorChar(wzPath[0])) | 1025 | if (IsPathSeparatorChar(wzPath[0])) |
| 988 | { | 1026 | { |
| 989 | // The only way to specify a fully qualified path that doesn't begin with a slash | 1027 | if (IsPathSeparatorChar(wzPath[1]) && (L'?' == wzPath[2] || L'.' == wzPath[2]) && IsPathSeparatorChar(wzPath[3]) || |
| 990 | // is the drive, colon, slash format (C:\). | 1028 | L'?' == wzPath[1] && L'?' == wzPath[2] && IsPathSeparatorChar(wzPath[3])) |
| 991 | if (IsValidDriveChar(wzPath[0]) && | ||
| 992 | L':' == wzPath[1] && | ||
| 993 | IsPathSeparatorChar(wzPath[2])) | ||
| 994 | { | 1029 | { |
| 995 | fFullyQualified = TRUE; | 1030 | fHasPrefix = TRUE; |
| 996 | } | ||
| 997 | 1031 | ||
| 998 | ExitFunction(); | 1032 | if (L'U' == wzPath[4] && L'N' == wzPath[5] && L'C' == wzPath[6] && IsPathSeparatorChar(wzPath[7])) |
| 1033 | { | ||
| 1034 | fUNC = TRUE; | ||
| 1035 | wzPastRoot = wzPath + 8; | ||
| 1036 | dwRootMissingSlashes = 2; | ||
| 1037 | } | ||
| 1038 | else | ||
| 1039 | { | ||
| 1040 | wzPastRoot = wzPath + 4; | ||
| 1041 | dwRootMissingSlashes = 1; | ||
| 1042 | } | ||
| 1043 | } | ||
| 1044 | else if (IsPathSeparatorChar(wzPath[1])) | ||
| 1045 | { | ||
| 1046 | fUNC = TRUE; | ||
| 1047 | wzPastRoot = wzPath + 2; | ||
| 1048 | dwRootMissingSlashes = 2; | ||
| 1049 | } | ||
| 999 | } | 1050 | } |
| 1000 | 1051 | ||
| 1001 | // Non-drive fully qualified paths must start with \\ or \?. | 1052 | if (dwRootMissingSlashes) |
| 1002 | // \??\ is an archaic form of \\?\. | ||
| 1003 | if (L'?' != wzPath[1] && !IsPathSeparatorChar(wzPath[1])) | ||
| 1004 | { | 1053 | { |
| 1005 | ExitFunction(); | 1054 | Assert(wzPastRoot); |
| 1055 | fFullyQualified = TRUE; | ||
| 1056 | |||
| 1057 | for (; *wzPastRoot && dwRootMissingSlashes; ++wzPastRoot) | ||
| 1058 | { | ||
| 1059 | if (IsPathSeparatorChar(*wzPastRoot)) | ||
| 1060 | { | ||
| 1061 | --dwRootMissingSlashes; | ||
| 1062 | } | ||
| 1063 | } | ||
| 1006 | } | 1064 | } |
| 1065 | else | ||
| 1066 | { | ||
| 1067 | Assert(!wzPastRoot); | ||
| 1007 | 1068 | ||
| 1008 | fFullyQualified = TRUE; | 1069 | if (IsPathSeparatorChar(wzPath[0])) |
| 1070 | { | ||
| 1071 | wzPastRoot = wzPath + 1; | ||
| 1072 | } | ||
| 1073 | else if (IsValidDriveChar(wzPath[0]) && wzPath[1] == L':') | ||
| 1074 | { | ||
| 1075 | if (IsPathSeparatorChar(wzPath[2])) | ||
| 1076 | { | ||
| 1077 | fFullyQualified = TRUE; | ||
| 1078 | wzPastRoot = wzPath + 3; | ||
| 1079 | } | ||
| 1080 | else | ||
| 1081 | { | ||
| 1082 | wzPastRoot = wzPath + 2; | ||
| 1083 | } | ||
| 1084 | } | ||
| 1085 | } | ||
| 1009 | 1086 | ||
| 1010 | if (L'?' == wzPath[2] && IsPathSeparatorChar(wzPath[3])) | 1087 | LExit: |
| 1088 | if (pfHasExtendedPrefix) | ||
| 1011 | { | 1089 | { |
| 1012 | fHasLongPathPrefix = TRUE; | 1090 | *pfHasExtendedPrefix = fHasPrefix; |
| 1013 | } | 1091 | } |
| 1014 | 1092 | ||
| 1093 | if (pfFullyQualified) | ||
| 1094 | { | ||
| 1095 | *pfFullyQualified = fFullyQualified; | ||
| 1096 | } | ||
| 1015 | 1097 | ||
| 1016 | LExit: | 1098 | if (pfUNC) |
| 1017 | if (pfHasLongPathPrefix) | ||
| 1018 | { | 1099 | { |
| 1019 | *pfHasLongPathPrefix = fHasLongPathPrefix; | 1100 | *pfUNC = fUNC; |
| 1020 | } | 1101 | } |
| 1021 | 1102 | ||
| 1103 | return wzPastRoot; | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | |||
| 1107 | DAPI_(BOOL) PathIsFullyQualified( | ||
| 1108 | __in_z LPCWSTR wzPath | ||
| 1109 | ) | ||
| 1110 | { | ||
| 1111 | BOOL fFullyQualified = FALSE; | ||
| 1112 | |||
| 1113 | PathSkipPastRoot(wzPath, NULL, &fFullyQualified, NULL); | ||
| 1114 | |||
| 1022 | return fFullyQualified; | 1115 | return fFullyQualified; |
| 1023 | } | 1116 | } |
| 1024 | 1117 | ||
| @@ -1027,9 +1120,7 @@ DAPI_(BOOL) PathIsRooted( | |||
| 1027 | __in_z LPCWSTR wzPath | 1120 | __in_z LPCWSTR wzPath |
| 1028 | ) | 1121 | ) |
| 1029 | { | 1122 | { |
| 1030 | return wzPath && | 1123 | return NULL != PathSkipPastRoot(wzPath, NULL, NULL, NULL); |
| 1031 | (IsPathSeparatorChar(wzPath[0]) || | ||
| 1032 | IsValidDriveChar(wzPath[0]) && wzPath[1] == L':'); | ||
| 1033 | } | 1124 | } |
| 1034 | 1125 | ||
| 1035 | 1126 | ||
| @@ -1118,78 +1209,47 @@ DAPI_(HRESULT) PathGetHierarchyArray( | |||
| 1118 | ) | 1209 | ) |
| 1119 | { | 1210 | { |
| 1120 | HRESULT hr = S_OK; | 1211 | HRESULT hr = S_OK; |
| 1121 | LPWSTR sczPathCopy = NULL; | 1212 | LPCWSTR wz = NULL; |
| 1122 | LPWSTR sczNewPathCopy = NULL; | 1213 | SIZE_T cch = 0; |
| 1123 | DWORD cArraySpacesNeeded = 0; | 1214 | *pcPathArray = 0; |
| 1124 | size_t cchPath = 0; | ||
| 1125 | 1215 | ||
| 1126 | hr = ::StringCchLengthW(wzPath, STRSAFE_MAX_LENGTH, &cchPath); | 1216 | PathExitOnNull(wzPath, hr, E_INVALIDARG, "wzPath is required."); |
| 1127 | PathExitOnRootFailure(hr, "Failed to get string length of path: %ls", wzPath); | ||
| 1128 | 1217 | ||
| 1129 | if (!cchPath) | 1218 | wz = PathSkipPastRoot(wzPath, NULL, NULL, NULL); |
| 1219 | if (wz) | ||
| 1130 | { | 1220 | { |
| 1131 | ExitFunction1(hr = E_INVALIDARG); | 1221 | cch = wz - wzPath; |
| 1132 | } | ||
| 1133 | 1222 | ||
| 1134 | for (size_t i = 0; i < cchPath; ++i) | 1223 | hr = MemEnsureArraySize(reinterpret_cast<void**>(prgsczPathArray), 1, sizeof(LPWSTR), 5); |
| 1135 | { | 1224 | PathExitOnFailure(hr, "Failed to allocate array."); |
| 1136 | if (IsPathSeparatorChar(wzPath[i])) | ||
| 1137 | { | ||
| 1138 | ++cArraySpacesNeeded; | ||
| 1139 | } | ||
| 1140 | } | ||
| 1141 | 1225 | ||
| 1142 | if (!IsPathSeparatorChar(wzPath[cchPath - 1])) | 1226 | hr = StrAllocString(*prgsczPathArray, wzPath, cch); |
| 1143 | { | 1227 | PathExitOnFailure(hr, "Failed to copy root into array."); |
| 1144 | ++cArraySpacesNeeded; | ||
| 1145 | } | ||
| 1146 | 1228 | ||
| 1147 | // If it's a UNC path, cut off the first three paths, 2 because it starts with a double backslash, and another because the first ("\\servername\") isn't a path. | 1229 | *pcPathArray += 1; |
| 1148 | if (IsPathSeparatorChar(wzPath[0]) && IsPathSeparatorChar(wzPath[1])) | 1230 | } |
| 1231 | else | ||
| 1149 | { | 1232 | { |
| 1150 | if (3 > cArraySpacesNeeded) | 1233 | wz = wzPath; |
| 1151 | { | ||
| 1152 | ExitFunction1(hr = E_INVALIDARG); | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | cArraySpacesNeeded -= 3; | ||
| 1156 | } | 1234 | } |
| 1157 | 1235 | ||
| 1158 | Assert(cArraySpacesNeeded >= 1); | 1236 | for (; *wz; ++wz) |
| 1159 | |||
| 1160 | hr = MemEnsureArraySize(reinterpret_cast<void **>(prgsczPathArray), cArraySpacesNeeded, sizeof(LPWSTR), 0); | ||
| 1161 | PathExitOnFailure(hr, "Failed to allocate array of size %u for parent directories", cArraySpacesNeeded); | ||
| 1162 | *pcPathArray = cArraySpacesNeeded; | ||
| 1163 | |||
| 1164 | hr = StrAllocString(&sczPathCopy, wzPath, 0); | ||
| 1165 | PathExitOnFailure(hr, "Failed to allocate copy of original path"); | ||
| 1166 | |||
| 1167 | for (DWORD i = 0; i < cArraySpacesNeeded; ++i) | ||
| 1168 | { | 1237 | { |
| 1169 | hr = StrAllocString((*prgsczPathArray) + cArraySpacesNeeded - 1 - i, sczPathCopy, 0); | 1238 | ++cch; |
| 1170 | PathExitOnFailure(hr, "Failed to copy path"); | ||
| 1171 | 1239 | ||
| 1172 | DWORD cchPathCopy = lstrlenW(sczPathCopy); | 1240 | if (IsPathSeparatorChar(*wz) || !wz[1]) |
| 1173 | |||
| 1174 | // If it ends in a backslash, it's a directory path, so cut off everything the last backslash before we get the directory portion of the path | ||
| 1175 | if (IsPathSeparatorChar(wzPath[cchPathCopy - 1])) | ||
| 1176 | { | 1241 | { |
| 1177 | sczPathCopy[cchPathCopy - 1] = L'\0'; | 1242 | hr = MemEnsureArraySizeForNewItems(reinterpret_cast<void**>(prgsczPathArray), *pcPathArray, 1, sizeof(LPWSTR), 5); |
| 1178 | } | 1243 | PathExitOnFailure(hr, "Failed to allocate array."); |
| 1179 | |||
| 1180 | hr = PathGetDirectory(sczPathCopy, &sczNewPathCopy); | ||
| 1181 | PathExitOnFailure(hr, "Failed to get directory portion of path"); | ||
| 1182 | 1244 | ||
| 1183 | ReleaseStr(sczPathCopy); | 1245 | hr = StrAllocString(*prgsczPathArray + *pcPathArray, wzPath, cch); |
| 1184 | sczPathCopy = sczNewPathCopy; | 1246 | PathExitOnFailure(hr, "Failed to copy path into array."); |
| 1185 | sczNewPathCopy = NULL; | ||
| 1186 | } | ||
| 1187 | 1247 | ||
| 1188 | hr = S_OK; | 1248 | *pcPathArray += 1; |
| 1249 | } | ||
| 1250 | } | ||
| 1189 | 1251 | ||
| 1190 | LExit: | 1252 | LExit: |
| 1191 | ReleaseStr(sczPathCopy); | ||
| 1192 | |||
| 1193 | return hr; | 1253 | return hr; |
| 1194 | } | 1254 | } |
| 1195 | 1255 | ||
