diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp index bbc4b40..23eb759 100644 --- a/client/KernelManager.cpp +++ b/client/KernelManager.cpp @@ -1488,7 +1488,41 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) s_v2RecvInited = true; } // C2C/V2 文件接收(RecvFileChunkV2 内部会打印进度) - int n = RecvFileChunkV2((char*)szBuffer, ulLength, m_conn, + // 展开文件名中的环境变量(如 %USERPROFILE%),与 V1 的 COMMAND_FILE_SIZE 保持一致。 + // 快捷图标定位远程目录时,主控端下发的 targetDir 仍含未展开的 %USERPROFILE% + // (server/2015Remote/FileManagerDlg.cpp OnRemoteDesktop/Downloads/Home), + // 若不在接收端展开,RecvFileChunkV2 会按字面量建目录(如 CWD\%%USERPROFILE%%\...)。 + char* recvBuf = (char*)szBuffer; + size_t recvLen = ulLength; + std::vector rebuilt; + if (ulLength >= sizeof(FileChunkPacketV2) && szBuffer[0] == COMMAND_SEND_FILE_V2) { + const FileChunkPacketV2* pkt = (const FileChunkPacketV2*)szBuffer; + if (ulLength >= sizeof(FileChunkPacketV2) + pkt->nameLength + pkt->dataLength) { + // 文件名未必以 '\0' 结尾,先构造出以 '\0' 结尾的副本 + std::string name((const char*)szBuffer + sizeof(FileChunkPacketV2), (size_t)pkt->nameLength); + char expanded[MAX_PATH * 2] = { 0 }; + DWORD n = ExpandEnvironmentStringsA(name.c_str(), expanded, (DWORD)sizeof(expanded)); + if (n > 0 && n < (DWORD)sizeof(expanded)) { + std::string newName(expanded, n - 1); // n 含末尾 '\0' + if (newName.size() != pkt->nameLength) { + // 展开后长度变化,重建包:[header][展开后的 name][data] + size_t newLen = sizeof(FileChunkPacketV2) + newName.size() + pkt->dataLength; + rebuilt.resize(newLen); + memcpy(rebuilt.data(), szBuffer, sizeof(FileChunkPacketV2)); + FileChunkPacketV2* newPkt = (FileChunkPacketV2*)rebuilt.data(); + newPkt->nameLength = newName.size(); + memcpy(rebuilt.data() + sizeof(FileChunkPacketV2), newName.data(), newName.size()); + memcpy(rebuilt.data() + sizeof(FileChunkPacketV2) + newName.size(), + (const char*)szBuffer + sizeof(FileChunkPacketV2) + pkt->nameLength, + (size_t)pkt->dataLength); + recvBuf = (char*)rebuilt.data(); + recvLen = newLen; + } + } + } + } + + int n = RecvFileChunkV2(recvBuf, recvLen, m_conn, nullptr, m_hash, m_hmac, m_MyClientID); if (n) { Mprintf("[C2C] RecvFileChunkV2 failed: %d\n", n);