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; }