Example #1
0
/**
 * 发送本机共享文件信息入口.
 * @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;
}
Example #3
0
/**
 * 发送文件信息入口.
 * @param pal class PalInfo
 * @param flist 文件信息链表
 * @note 文件路径链表中的数据将被本函数处理掉
 */
void SendFile::SendFileInfoEntry(PalInfo *pal, GSList *flist)
{
        /* 发送文件信息 */
        SendFileInfo(pal, 0, flist);
}