HRESULT CTsTeleportShellExt::AnnounceTransfer(__in_z LPTSTR szPartial, BOOL bDir)
{
    HRESULT hr;
    PTELEP_PACKET_HEADER pPacket = NULL;
    //
    // Send start packet for file or dir
    //

    size_t Len = _tcslen(szPartial);
    USHORT DataLen;
    hr = SizeTToUShort(Len, &DataLen);
    LEAVE_IF_FAILED("SizeTToUShort (0x%Ix) failed", Len);

    hr = UShortAdd(DataLen, 1, &DataLen);
    LEAVE_IF_FAILED("UShortAdd (0x%4x, 1) failed", DataLen);

    hr = UShortMult(DataLen, sizeof(TCHAR), &DataLen);
    LEAVE_IF_FAILED("UShortMult (0x%4x, %d) failed", DataLen, sizeof(TCHAR));

    hr = UShortAdd(DataLen, sizeof(TELEP_PACKET_HEADER), &DataLen);
    LEAVE_IF_FAILED("UShortMult (0x%4x, %d) failed", DataLen, sizeof(TELEP_PACKET_HEADER));
     
    USHORT Flags = 0;

    if (bDir)
    {
        Flags |= TELET_FLAG_DIRECTORY;
    }

    pPacket = NewPacket(PacketTypeFileStart, DataLen, Flags); // throwing!

    LPWSTR pData = (LPWSTR) (pPacket+1);

    CopyMemory(pData, szPartial, pPacket->PacketSize);

    hr = SendPacket(pPacket);
    LEAVE_IF_FAILED("SendPacket (Start, %s) failed", szPartial);

_Function_Exit:

    if (pPacket)
    {
        delete [] pPacket;
    }

    return hr;
}
HRESULT CTsTeleportShellExt::SendPacket(PTELEP_PACKET_HEADER pPacket)
{
    HRESULT hr;

    OVERLAPPED ovr = { 0 };

    //
    // Add header to len
    //

    USHORT RequiredLen;
    hr = UShortAdd(pPacket->PacketSize, sizeof(TELEP_PACKET_HEADER), &RequiredLen);
    ASSERT(SUCCEEDED(hr)); // since we allocate the packet and previously supply the proper len
    
    //
    // Write packet to DVC
    //

    ULONG BytesWrit = 0;
    BOOL bRet = WriteFile(_hDVC, pPacket, RequiredLen, &BytesWrit, &ovr);
    
    if (!bRet && ERROR_IO_PENDING == GetLastError())
    {
        bRet = GetOverlappedResult(_hDVC, &ovr, &BytesWrit, TRUE);
    }

    if (!bRet)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
    }
    LEAVE_IF_FAILED("WriteFile failed");

    //
    // Packet committed to client but we need the client
    // result so read it - per our protocol
    //

    ULONG BytesRead = 0;

    BYTE ReadBuf[CHANNEL_PDU_LENGTH];
    PRESPONSE_FORMAT prf = (PRESPONSE_FORMAT) ReadBuf;
    
    //
    // We have to read at least channel PDU len on the DVC
    //

    bRet = ReadFile(_hDVC, ReadBuf, CHANNEL_PDU_LENGTH, &BytesRead, &ovr);

    if (!bRet && ERROR_IO_PENDING == GetLastError())
    {
        DWORD to = RESPONSE_TIMEOUT_MS;

#if _DEBUG || DBG
        if (g_bNoTimeout)
        {
            to = INFINITE;
        }
#endif

        DWORD dwRet = WaitForSingleObject(_hDVC, to);

        if (WAIT_TIMEOUT == dwRet)
        {
            //
            // Read timed out so fail
            //

            hr = TELEP_E_TIMEOUT;
        }
        LEAVE_IF_FAILED("Read response timeout");

        bRet = GetOverlappedResult(_hDVC, &ovr, &BytesRead, TRUE);
    }

    if (!bRet)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
    }
    LEAVE_IF_FAILED("ReadFile response failed");

    //
    // We do not expect packet fragmentation 
    //

    ASSERT((CHANNEL_FLAG_FIRST & prf->PDUHeader.flags) &&
        (CHANNEL_FLAG_LAST & prf->PDUHeader.flags));

    //
    // Copy client HRESULT
    //

    hr = prf->hrAck;
    LEAVE_IF_FAILED("Client indicated failure");

_Function_Exit:

    return hr;
}
// Add an ACE to an ACL, expanding the ACL if needed.
HRESULT AddAceToAcl(LPVOID pNewAce, PACL *ppAcl, bool bAddToEndOfList)
{
    DWORD addPosition = bAddToEndOfList ? MAXDWORD : 0;
    BOOL bResult = FALSE;
    DWORD errorCode = S_OK;
    PACL biggerDACL = nullptr;
    HRESULT hr = S_OK;
    ACL_SIZE_INFORMATION aclInformation;
    WORD aceSize;
    DWORD oldSize;
    USHORT uSize;
    DWORD dwNewSizeNeeded;

    if ( !ARGUMENT_PRESENT(pNewAce) || !ARGUMENT_PRESENT(*ppAcl) )
    {
        return E_INVALIDARG;
    }

    bResult = AddAce(
        *ppAcl,
        ACL_REVISION, 
        addPosition,
        pNewAce,
        ((PACE_HEADER)pNewAce)->AceSize
        );

    // See if we failed due to an insufficient buffer size
    if ( !bResult )
    {
        errorCode = GetLastError();
        if ( errorCode == ERROR_INSUFFICIENT_BUFFER )
        {
            // Not enough space. Allocate a bigger ACL.

            bResult = GetAclInformation(
                *ppAcl,
                &aclInformation,
                sizeof(aclInformation),
                AclSizeInformation
                );
            FailGracefullyGLE(bResult, L"GetAclInformation");
                            
            aceSize = ((PACE_HEADER)pNewAce)->AceSize;
            oldSize = aclInformation.AclBytesInUse;

            // Can't overflow WORD boundary
            hr = UShortAdd(aceSize, (USHORT)oldSize, &uSize);
            FailGracefully(hr, L"UShortAdd");
            
            // Give us some extra space so that we don't have to keep
            // reallocating.
            hr = UShortMult(uSize, 2, &uSize);
            FailGracefully(hr, L"UShortMult");

            dwNewSizeNeeded = (DWORD)uSize;
            // Align to a DWORD
            dwNewSizeNeeded = (dwNewSizeNeeded + (sizeof(DWORD) - 1)) & 0xfffffffc;

            // Make sure the alignment didn't overflow the size of a WORD
            // (the process of aligning can add up to 3)
            if ( dwNewSizeNeeded > USHORT_MAX )
            {
                // It's safe to subtrat now (despite the "size needed" name)
                // because we overestimated earlier by multiplying by 2.
                dwNewSizeNeeded -= 4;
            }

            biggerDACL = (PACL)LocalAlloc(LPTR, dwNewSizeNeeded);
            if ( !biggerDACL )
            {
                wprintf(L"LocalAlloc failed.\n");
                hr = E_OUTOFMEMORY;
                goto exit_gracefully;
            }
                            
            // Note: no need to initialize the new ACL
            memcpy(biggerDACL, *ppAcl, oldSize);

            // This cast is safe because we checked for overflow earlier
            biggerDACL->AclSize = (WORD)dwNewSizeNeeded;

            *ppAcl = biggerDACL;
            
            // Make sure this doesn't get freed later
            biggerDACL = nullptr;

            bResult = AddAce(
                *ppAcl,
                ACL_REVISION, 
                addPosition,
                pNewAce,
                ((PACE_HEADER)pNewAce)->AceSize
                );
            FailGracefullyGLE(bResult, L"AddAce");
        }
        else
        {
            return HRESULT_FROM_WIN32(errorCode);
        }
    }
exit_gracefully:
    LocalFree(biggerDACL);

    return hr;
}