/** * 发送本机共享文件信息入口. * @param pal class PalInfo */ void SendFile::SendSharedInfoEntry(PalInfo *pal) { GSList *list; pthread_mutex_lock(cthrd.GetMutex()); list = cthrd.GetPublicFileList(); SendFileInfo(pal, IPTUX_SHAREDOPT, list); pthread_mutex_unlock(cthrd.GetMutex()); }
// Performs the actual file transfer. // This function will fail to produce a valid file on the client if the file was changed in between requests for chunks. // There are ways to work around that, but doing so is beyond the scope of this version of the sample. A simple fix would be // to keep the file open between requests and prevent writing, but in the spirit of web services this app does not maintain // state between requests. HRESULT CFileRepServer::ReadAndSendFile( __in CRequest* request, __in const LPWSTR fileName, __in LONGLONG chunkPosition, __in_opt WS_ERROR* error) { PrintVerbose(L"Entering CFileRepServer::ReadAndSendFile"); HANDLE file = NULL; HRESULT hr = S_OK; file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == file) { PrintInfo(L"Invalid file name"); if (-1 != chunkPosition) { hr = SendError(request, GlobalStrings::invalidFileName); } else { hr = SendFileInfo(request, fileName, -1, chunkSize); } PrintVerbose(L"Leaving CFileRepServer::ReadAndSendFile"); return hr; } LARGE_INTEGER len; if (!GetFileSizeEx(file, &len)) { hr = HRESULT_FROM_WIN32(GetLastError()); PrintError(L"Unable to determine file length", true); if (FAILED(SendError(request, GlobalStrings::unableToDetermineFileLength))) { PrintError(L"Unable to send failure back", true); } if (!CloseHandle(file)) { PrintError(L"Unable to close file handle", true); } // This has its own return path to ensure that the right error info is returned. // The main error path would overwrite it. PrintVerbose(L"Leaving CFileRepServer::ReadAndSendFile"); return hr; } LONGLONG fileLength = len.QuadPart; if (chunkPosition == DISCOVERY_REQUEST) { PrintInfo(L"Processing discovery message"); hr = SendFileInfo(request, fileName, fileLength, chunkSize); } else if (chunkPosition < -1) { PrintInfo(L"Invalid request"); hr = SendError(request, GlobalStrings::invalidRequest); } else if (chunkPosition >= fileLength) { PrintInfo(L"Request out of range of the file"); hr = SendError(request, GlobalStrings::outOfRange); } else { long chunkSize = this->chunkSize; if (fileLength - chunkPosition < chunkSize) { chunkSize = (DWORD)(fileLength - chunkPosition); } LARGE_INTEGER pos; pos.QuadPart = chunkPosition; if (!SetFilePointerEx(file, pos, NULL, FILE_BEGIN)) { PrintError(L"Unable to set file pointer", true); hr = E_FAIL; // Ignore return value as we already have a failure. SendError(request, GlobalStrings::unableToSetFilePointer); } else { hr = ReadAndSendChunk(request, chunkSize, chunkPosition, file); } } if (FAILED(hr)) { PrintError(L"CFileRepServer::ReadAndSendFile\n", true); PrintError(hr, error, true); } if (!CloseHandle(file)) { hr = HRESULT_FROM_WIN32(GetLastError()); PrintError(L"Unable to close file handle", true); } PrintVerbose(L"Leaving CFileRepServer::ReadAndSendFile"); return hr; }
/** * 发送文件信息入口. * @param pal class PalInfo * @param flist 文件信息链表 * @note 文件路径链表中的数据将被本函数处理掉 */ void SendFile::SendFileInfoEntry(PalInfo *pal, GSList *flist) { /* 发送文件信息 */ SendFileInfo(pal, 0, flist); }