Checks if the given file resides in a directory in a network share. If it does, returns its corresponding network path. Ex: C:\SharedDir\File.txt -> \\thiscomputer\SharedDir\File.txt @param p_rFilePath Local file path. Upon exit, will contain network path. @param p_UseHiddenShares Whether to consider hidden shares when looking for valid shares. @return true if the file was in a network share and
| 244 | // @return true if the file was in a network share and we fetched its network path. |
| 245 | // |
| 246 | bool PluginUtils::GetNetworkShareFilePath(std::wstring& p_rFilePath, |
| 247 | const bool p_UseHiddenShares) |
| 248 | { |
| 249 | bool converted = false; |
| 250 | |
| 251 | // Scan registry to see if we can find a share that contains this path. |
| 252 | // Shares are stored in multi-string registry values in the Lanmanserver service keys. |
| 253 | ATL::CRegKey shareKey; |
| 254 | if (shareKey.Open(HKEY_LOCAL_MACHINE, SHARES_KEY_NAME, KEY_READ) == ERROR_SUCCESS) { |
| 255 | // Iterate registry values to check each share. |
| 256 | std::wstring valueName(MAX_REG_KEY_NAME_SIZE + 1, L'\0'); |
| 257 | std::wstring multiStringValue; |
| 258 | std::wstring path; |
| 259 | LONG ret = 0; |
| 260 | DWORD i = 0; |
| 261 | do { |
| 262 | DWORD valueNameSize = MAX_REG_KEY_NAME_SIZE; |
| 263 | DWORD valueType = 0; |
| 264 | ret = ::RegEnumValue(shareKey, i, &*valueName.begin(), &valueNameSize, nullptr, &valueType, nullptr, nullptr); |
| 265 | if (ret == ERROR_SUCCESS && valueType == REG_MULTI_SZ) { |
| 266 | // Get the multi-string values. |
| 267 | ULONG bufferSize = INITIAL_BUFFER_SIZE; |
| 268 | std::vector<wchar_t> vBuffer; |
| 269 | do { |
| 270 | vBuffer.resize(bufferSize, L'\0'); |
| 271 | ret = shareKey.QueryMultiStringValue(valueName.c_str(), vBuffer.data(), &bufferSize); |
| 272 | } while (ret == ERROR_MORE_DATA); |
| 273 | if (ret == ERROR_SUCCESS) { |
| 274 | // Make sure this is not a hidden share (unless we use them). |
| 275 | if (valueNameSize != 0 && (p_UseHiddenShares || valueName.at(valueNameSize - 1) != HIDDEN_SHARE_SUFFIX)) { |
| 276 | // Find the "Path=" part of the mult-string. This contains the share path. |
| 277 | multiStringValue.assign(vBuffer.data(), bufferSize); |
| 278 | path = GetMultiStringLineBeginningWith(multiStringValue, SHARE_PATH_VALUE); |
| 279 | if (!path.empty()) { |
| 280 | // Check if our path is in that share. |
| 281 | if (p_rFilePath.find(path) == 0) { |
| 282 | // Success: this is a share that contains our path. |
| 283 | // Replace the start of the path with the computer and share name. |
| 284 | std::wstringstream ss; |
| 285 | ss << L"\\\\" << GetLocalComputerName() << L"\\" << valueName.c_str(); |
| 286 | if (*path.rbegin() == L'\\' || *path.rbegin() == L'/') { |
| 287 | // The substr below will remove the terminator if the share path |
| 288 | // ends with one (for example, for drives' administrative shares). |
| 289 | // We'll have to add an extra one manually. |
| 290 | ss << L'\\'; |
| 291 | } |
| 292 | ss << p_rFilePath.substr(path.size()); |
| 293 | p_rFilePath = ss.str(); |
| 294 | converted = true; |
| 295 | break; |
| 296 | } |
| 297 | } |
| 298 | } |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | // Go to next share. |
| 303 | ++i; |