summaryrefslogtreecommitdiff
path: root/src/vm/profattachserver.inl
blob: 1b77f59c52cb4afbfe085a01ab56e33558697fba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// 
// ProfAttachServer.inl
// 

// 
// Inlined implementations of portions of ProfilingAPIAttachServer and helpers, which are
// used by the AttachThread running in the target profilee (server end of the pipe) to
// receive and carry out requests that are sent by the trigger (client end of the pipe).
// 

// ======================================================================================


// ----------------------------------------------------------------------------
// RequestMessageVerifier::RequestMessageVerifier()
//
// Description: 
//    Constructor that takes stream of bytes read by the target profilee on its pipe. 
//    After construction, call Verify() to verify the stream of bytes makes a
//    well-formed message.
//
// Arguments:
//    * pbRequestMessage - Bytes read from pipe
//    * cbRequestMessage - Number of bytes read from pipe.
//

inline RequestMessageVerifier::RequestMessageVerifier(
    LPCBYTE pbRequestMessage,
    DWORD cbRequestMessage) :
        m_pbRequestMessage(pbRequestMessage),
        m_cbRequestMessage(cbRequestMessage)
{
    LIMITED_METHOD_CONTRACT;

    INDEBUG(m_fVerified = FALSE);
}
        
// ----------------------------------------------------------------------------
// ProfilingAPIAttachServer::ProfilingAPIAttachServer()
//
// Description: 
//     Constructor for ProfilingAPIAttachServer, which owns the server end of the pipe
//     running in the target profilee

inline ProfilingAPIAttachServer::ProfilingAPIAttachServer() :
        m_dwMillisecondsMaxPerWait(0)
{
    LIMITED_METHOD_CONTRACT;
}

inline ProfilingAPIAttachServer::~ProfilingAPIAttachServer()
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
        CANNOT_TAKE_LOCK;
    }
    CONTRACTL_END;

    if (IsValidHandle(m_hPipeServer))
    {
        // m_hPipeServer's destructor is about to destroy the pipe
        LOG((
            LF_CORPROF, 
            LL_INFO10, 
            "**PROF: Finished communication; closing attach pipe server.\n"));
    }
}


// ----------------------------------------------------------------------------
// ProfilingAPIAttachServer::WriteResponseToPipe
// 
// Description:
//    Sends response bytes across pipe to trigger process.
//    
// Arguments:
//    * pvResponse - Pointer to bytes to send
//    * cbResponse - How many bytes to send
//        
// Return Value:
//    HRESULT indicating success or failure.
//    
// Notes:
//    * Purposely does NOT log an event on failure, as an event at this stage would be
//        confusing to the user. The requested operation (e.g., Attach) has already been
//        performed; this is just the part that communicates the result back to the
//        trigger. There's nothing the user could (or would want to) do if response
//        communication failed. Either the attach worked or not, and that's already been
//        logged to the event log.
//        

inline HRESULT ProfilingAPIAttachServer::WriteResponseToPipe(
    LPVOID pvResponse,
    DWORD cbResponse)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
        CAN_TAKE_LOCK;
    }
    CONTRACTL_END;

    _ASSERTE(IsValidHandle(m_hPipeServer));
    _ASSERTE(pvResponse != NULL);

    DWORD cbWritten;

    HRESULT hr = WriteResponseToPipeNoBufferSizeCheck(
        pvResponse,
        cbResponse,
        &cbWritten);

    // Check the buffer size against what was written
    if (SUCCEEDED(hr) && (cbResponse != cbWritten))
    {
        // Partial response sent.  Be sure hr reflects there was a problem
        hr = E_UNEXPECTED;
    }

    return hr;
}