-
Notifications
You must be signed in to change notification settings - Fork 1
/
cogetserverpid.h
87 lines (72 loc) · 2.56 KB
/
cogetserverpid.h
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
/*******************************************************************************
Copyright (c) 2012, Kim Gräsman
All rights reserved.
Released under the Modified BSD license. For details, please see LICENSE file.
*******************************************************************************/
#ifndef INCLUDED_COGETSERVERPID_H__
#define INCLUDED_COGETSERVERPID_H__
#include <objbase.h>
/* This structure represents the OBJREF up to the PID at offset 52 bytes.
1-byte structure packing to make sure offsets are deterministic. */
#pragma pack(push, 1)
typedef struct tagCOGETSERVERPID_OBJREFHDR
{
DWORD signature; /* Should be 'MEOW'. */
DWORD flags;
BYTE padding[44];
USHORT pid;
} COGETSERVERPID_OBJREFHDR;
#pragma pack(pop)
inline HRESULT CoGetServerPID(IUnknown* punk, DWORD* pdwPID)
{
HRESULT hr;
IUnknown* pProxyManager = NULL;
IStream* pMarshalStream = NULL;
HGLOBAL hg = NULL;
COGETSERVERPID_OBJREFHDR *pObjRefHdr = NULL;
LARGE_INTEGER zero = {0};
if(pdwPID == NULL) return E_POINTER;
if(punk == NULL) return E_INVALIDARG;
/* Make sure this is a standard proxy, otherwise we can't make any
assumptions about OBJREF wire format. */
hr = punk->QueryInterface(IID_IProxyManager, (void**)&pProxyManager);
if(FAILED(hr)) return hr;
pProxyManager->Release();
/* Marshal the interface to get a new OBJREF. */
hr = ::CreateStreamOnHGlobal(NULL, TRUE, &pMarshalStream);
if(SUCCEEDED(hr))
{
hr = ::CoMarshalInterface(pMarshalStream, IID_IUnknown, punk,
MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
if(SUCCEEDED(hr))
{
/* We just created the stream so it's safe to go back to a raw pointer. */
hr = ::GetHGlobalFromStream(pMarshalStream, &hg);
if(SUCCEEDED(hr))
{
/* Start out pessimistic. */
hr = RPC_E_INVALID_OBJREF;
pObjRefHdr = (COGETSERVERPID_OBJREFHDR*)GlobalLock(hg);
if(pObjRefHdr != NULL)
{
/* Validate what we can. */
if(pObjRefHdr->signature == 0x574f454d && /* 'MEOW' */
pObjRefHdr->flags == 1 && /* OBJREF_STANDARD */
pObjRefHdr->pid != 0xFFFF) /* PIDs are sometimes clamped at 64K */
{
/* We got the remote PID! */
*pdwPID = pObjRefHdr->pid;
hr = S_OK;
}
GlobalUnlock(hg);
}
}
/* Rewind stream and release marshal data to keep refcount in order. */
pMarshalStream->Seek(zero, SEEK_SET, NULL);
CoReleaseMarshalData(pMarshalStream);
}
pMarshalStream->Release();
}
return hr;
}
#endif // INCLUDED_COGETSERVERPID_H__