<div dir="ltr">It seems that after all this patch is unnecessary at all. By default all of the driver code is nonpaged unless stated otherwise using pragma directives.</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Aug 18, 2016 at 8:25 PM, Frediano Ziglio <span dir="ltr"><<a href="mailto:fziglio@redhat.com" target="_blank">fziglio@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
> ><br>
> > From: Sandy Stutsman <<a href="mailto:sstutsma@redhat.com">sstutsma@redhat.com</a>><br>
> ><br>
> > There is no way to guarantee that the static vtable will be in<br>
> > non-pageable memory. This patch converts 3 virtual non-pageble functions<br>
> > to functions private to each device class, the parent class will make<br>
> > an explicit call (based on a new device type initialized at object<br>
> > creation) to the correct function.<br>
> ><br>
> > Fixed one misspelling: HwDeviceInterface<br>
><br>
> Ok for the spelling.<br>
> This patch is moving some code around instead of marking function<br>
> to specific sections with #pragma code_seg.<br>
> vtable are generated in the constant section (by default .rodata) if this<br>
> is pageable I would rather define a section (#pragma section) and generate<br>
> all constants in this new section (#pragma const_seg).<br>
><br>
<br>
</span>Had a look at some driver.<br>
Looks like all main sections (.rdata, .data, etc) are not pageable.<br>
A better check where the vtable are allocated should be done but this<br>
looks like a false positive.<br>
<br>
Where can I get the last repository or the binary (not sure the binary<br>
is however enough, perhaps object files would be better) ?<br>
<div><div class="h5"><br>
Frediano<br>
<br>
><br>
> > ---<br>
> > qxldod/QxlDod.cpp | 114<br>
> > ++++++++++++++++++++++++++++++<wbr>++++++++++++------------<br>
> > qxldod/QxlDod.h | 48 +++++++++++++++--------<br>
> > 2 files changed, 120 insertions(+), 42 deletions(-)<br>
> ><br>
> > diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp<br>
> > index 1b3bdf1..ec960e5 100755<br>
> > --- a/qxldod/QxlDod.cpp<br>
> > +++ b/qxldod/QxlDod.cpp<br>
> > @@ -2294,7 +2294,7 @@ VOID BltBits (<br>
> > }<br>
> > #pragma code_seg(pop) // End Non-Paged Code<br>
> ><br>
> > -VgaDevice::VgaDevice(_In_ QxlDod* pQxlDod)<br>
> > +VgaDevice::VgaDevice(_In_ QxlDod* pQxlDod) : HwDeviceInterface(pQxlDod)<br>
> > {<br>
> > m_pQxlDod = pQxlDod;<br>
> > m_ModeInfo = NULL;<br>
> > @@ -2302,6 +2302,7 @@ VgaDevice::VgaDevice(_In_ QxlDod* pQxlDod)<br>
> > m_ModeNumbers = NULL;<br>
> > m_CurrentMode = 0;<br>
> > m_Id = 0;<br>
> > + m_type = VGA_DEVICE;<br>
> > }<br>
> ><br>
> > VgaDevice::~VgaDevice(void)<br>
> > @@ -2881,18 +2882,18 @@ VOID VgaDevice::BlackOutScreen(<wbr>CURRENT_BDD_MODE*<br>
> > pCurrentBddMod)<br>
> > #pragma code_seg()<br>
> > // BEGIN: Non-Paged Code Segment<br>
> ><br>
> > -BOOLEAN VgaDevice::InterruptRoutine(_<wbr>In_ PDXGKRNL_INTERFACE<br>
> > pDxgkInterface,<br>
> > _In_ ULONG MessageNumber)<br>
> > +BOOLEAN VgaDevice::HWInterruptRoutine(<wbr>_In_ PDXGKRNL_INTERFACE<br>
> > pDxgkInterface, _In_ ULONG MessageNumber)<br>
> > {<br>
> > UNREFERENCED_PARAMETER(<wbr>pDxgkInterface);<br>
> > UNREFERENCED_PARAMETER(<wbr>MessageNumber);<br>
> > return FALSE;<br>
> > }<br>
> ><br>
> > -VOID VgaDevice::DpcRoutine(PVOID)<br>
> > +VOID VgaDevice::HWDpcRoutine(<wbr>PDXGKRNL_INTERFACE pDxgkInterface)<br>
> > {<br>
> > }<br>
> ><br>
> > -VOID VgaDevice::ResetDevice(VOID)<br>
> > +VOID VgaDevice::HWResetDevice(VOID)<br>
> > {<br>
> > }<br>
> > #pragma code_seg(pop) //end non-paged code<br>
> > @@ -2916,7 +2917,7 @@ NTSTATUS VgaDevice::Escape(_In_ CONST DXGKARG_ESCAPE*<br>
> > pEscap)<br>
> > return STATUS_NOT_IMPLEMENTED;<br>
> > }<br>
> ><br>
> > -QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod)<br>
> > +QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) : HwDeviceInterface(pQxlDod)<br>
> > {<br>
> > m_pQxlDod = pQxlDod;<br>
> > m_ModeInfo = NULL;<br>
> > @@ -2926,6 +2927,7 @@ QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod)<br>
> > m_CustomMode = 0;<br>
> > m_FreeOutputs = 0;<br>
> > m_Pending = 0;<br>
> > + m_type = QXL_DEVICE;<br>
> > }<br>
> ><br>
> > QxlDevice::~QxlDevice(void)<br>
> > @@ -3152,7 +3154,7 @@ NTSTATUS QxlDevice::SetPowerState(_In_<br>
> > DEVICE_POWER_STATE DevicePowerState, DXGK<br>
> > NTSTATUS QxlDevice::HWInit(PCM_<wbr>RESOURCE_LIST pResList,<br>
> > DXGK_DISPLAY_INFORMATION* pDispInfo)<br>
> > {<br>
> > DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));<br>
> > - PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterrface()<wbr>;<br>
> > + PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterface();<br>
> > UINT pci_range = QXL_RAM_RANGE_INDEX;<br>
> > for (ULONG i = 0; i < pResList->Count; ++i)<br>
> > {<br>
> > @@ -3329,7 +3331,7 @@ void QxlDevice::QxlClose()<br>
> ><br>
> > void QxlDevice::UnmapMemory(void)<br>
> > {<br>
> > - PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterrface()<wbr>;<br>
> > + PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterface();<br>
> > if (m_IoMapped && m_IoBase)<br>
> > {<br>
> > pDxgkInterface-><wbr>DxgkCbUnmapMemory( pDxgkInterface->DeviceHandle,<br>
> > &m_IoBase);<br>
> > @@ -4498,7 +4500,8 @@ VOID QxlDevice::PushCursor(VOID)<br>
> > #pragma code_seg(push)<br>
> > #pragma code_seg()<br>
> > // BEGIN: Non-Paged Code Segment<br>
> > -BOOLEAN QxlDevice::InterruptRoutine(_<wbr>In_ PDXGKRNL_INTERFACE<br>
> > pDxgkInterface,<br>
> > _In_ ULONG MessageNumber)<br>
> > +<br>
> > +BOOLEAN QxlDevice::HWInterruptRoutine(<wbr>_In_ PDXGKRNL_INTERFACE<br>
> > pDxgkInterface, _In_ ULONG MessageNumber)<br>
> > {<br>
> > UNREFERENCED_PARAMETER(<wbr>MessageNumber);<br>
> > DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));<br>
> > @@ -4523,10 +4526,8 @@ BOOLEAN QxlDevice::InterruptRoutine(_<wbr>In_<br>
> > PDXGKRNL_INTERFACE pDxgkInterface, _In_<br>
> > return TRUE;<br>
> > }<br>
> ><br>
> > -VOID QxlDevice::DpcRoutine(PVOID ptr)<br>
> > +VOID QxlDevice::HWDpcRoutine(<wbr>PDXGKRNL_INTERFACE pDxgkInterface)<br>
> > {<br>
> > - PDXGKRNL_INTERFACE pDxgkInterface = (PDXGKRNL_INTERFACE)ptr;<br>
> > -<br>
> > DbgPrint(TRACE_LEVEL_<wbr>INFORMATION, ("---> %s\n", __FUNCTION__));<br>
> > DPC_CB_CONTEXT ctx;<br>
> > BOOLEAN dummy;<br>
> > @@ -4557,13 +4558,89 @@ VOID QxlDevice::DpcRoutine(PVOID ptr)<br>
> > DbgPrint(TRACE_LEVEL_<wbr>INFORMATION, ("<--- %s\n", __FUNCTION__));<br>
> > }<br>
> ><br>
> > -void QxlDevice::ResetDevice(void)<br>
> > +void QxlDevice::HWResetDevice(void)<br>
> > {<br>
> > DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));<br>
> > m_RamHdr->int_mask = ~0;<br>
> > WRITE_PORT_UCHAR(m_IoBase + QXL_IO_MEMSLOT_ADD, 0);<br>
> > DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));<br>
> > }<br>
> > +<br>
> > +// Given bits per pixel, return the pixel format at the same bpp<br>
> > +D3DDDIFORMAT PixelFormatFromBPP(UINT BPP)<br>
> > +{<br>
> > + switch (BPP)<br>
> > + {<br>
> > + case 8: return D3DDDIFMT_P8;<br>
> > + case 16: return D3DDDIFMT_R5G6B5;<br>
> > + case 24: return D3DDDIFMT_R8G8B8;<br>
> > + case 32: return D3DDDIFMT_X8R8G8B8;<br>
> > + default: QXL_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not<br>
> > supported.", BPP); return D3DDDIFMT_UNKNOWN;<br>
> > + }<br>
> > +}<br>
> > +<br>
> > +<br>
> > +BOOLEAN HwDeviceInterface::<wbr>InterruptRoutine(_In_ PDXGKRNL_INTERFACE<br>
> > pDxgkInterface, _In_ ULONG MessageNumber)<br>
> > +{<br>
> > + QxlDevice * qxl_device;<br>
> > + VgaDevice * vga_device;<br>
> > +<br>
> > + switch (m_type) {<br>
> > + case QXL_DEVICE:<br>
> > + qxl_device = (QxlDevice *)this;<br>
> > + return qxl_device-><wbr>HWInterruptRoutine(<wbr>pDxgkInterface,<br>
> > MessageNumber);<br>
> > + case VGA_DEVICE:<br>
> > + vga_device = (VgaDevice *)this;<br>
> > + return vga_device-><wbr>HWInterruptRoutine(<wbr>pDxgkInterface,<br>
> > MessageNumber);<br>
> > + default:<br>
> > + DbgPrint(TRACE_LEVEL_ERROR, ("%s called with invalid device type<br>
> > of<br>
> > %d\n",<br>
> > + __FUNCTION__, m_type));<br>
> > + return FALSE;<br>
> > + }<br>
> > +}<br>
> > +<br>
> > +VOID HwDeviceInterface::DpcRoutine(<wbr>PDXGKRNL_INTERFACE pDxgkInterface)<br>
> > +{<br>
> > + QxlDevice * qxl_device;<br>
> > + VgaDevice * vga_device;<br>
> > +<br>
> > + switch (m_type) {<br>
> > + case QXL_DEVICE:<br>
> > + qxl_device = (QxlDevice *)this;<br>
> > + qxl_device->HWDpcRoutine(<wbr>pDxgkInterface);<br>
> > + return;<br>
> > + case VGA_DEVICE:<br>
> > + vga_device = (VgaDevice *)this;<br>
> > + vga_device->HWDpcRoutine(<wbr>pDxgkInterface);<br>
> > + return;<br>
> > + default:<br>
> > + DbgPrint(TRACE_LEVEL_ERROR, ("%s called with invalid device type<br>
> > of<br>
> > %d\n",<br>
> > + __FUNCTION__, m_type));<br>
> > + return;<br>
> > + }<br>
> > +}<br>
> > +<br>
> > +VOID HwDeviceInterface::<wbr>ResetDevice(void)<br>
> > +{<br>
> > + QxlDevice * qxl_device;<br>
> > + VgaDevice * vga_device;<br>
> > +<br>
> > + switch (m_type) {<br>
> > + case QXL_DEVICE:<br>
> > + qxl_device = (QxlDevice *)this;<br>
> > + qxl_device->HWResetDevice();<br>
> > + return;<br>
> > + case VGA_DEVICE:<br>
> > + vga_device = (VgaDevice *)this;<br>
> > + vga_device->HWResetDevice();<br>
> > + return;<br>
> > + default:<br>
> > + DbgPrint(TRACE_LEVEL_ERROR, ("%s called with invalid device type<br>
> > of<br>
> > %d\n",<br>
> > + __FUNCTION__, m_type));<br>
> > + return;<br>
> > + }<br>
> > +}<br>
> > +<br>
> > #pragma code_seg(pop) //end non-paged code<br>
> ><br>
> > VOID QxlDevice::UpdateArea(CONST RECT* area, UINT32 surface_id)<br>
> > @@ -4592,19 +4669,6 @@ VOID QxlDevice::DpcCallback(PDPC_<wbr>CB_CONTEXT ctx)<br>
> ><br>
> > }<br>
> ><br>
> > -// Given bits per pixel, return the pixel format at the same bpp<br>
> > -D3DDDIFORMAT PixelFormatFromBPP(UINT BPP)<br>
> > -{<br>
> > - switch (BPP)<br>
> > - {<br>
> > - case 8: return D3DDDIFMT_P8;<br>
> > - case 16: return D3DDDIFMT_R5G6B5;<br>
> > - case 24: return D3DDDIFMT_R8G8B8;<br>
> > - case 32: return D3DDDIFMT_X8R8G8B8;<br>
> > - default: QXL_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not<br>
> > supported.", BPP); return D3DDDIFMT_UNKNOWN;<br>
> > - }<br>
> > -}<br>
> > -<br>
> > UINT SpiceFromPixelFormat(<wbr>D3DDDIFORMAT Format)<br>
> > {<br>
> > switch (Format)<br>
> > diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h<br>
> > index eb9bea7..db343e9 100755<br>
> > --- a/qxldod/QxlDod.h<br>
> > +++ b/qxldod/QxlDod.h<br>
> > @@ -212,21 +212,34 @@ typedef struct _CURRENT_BDD_MODE<br>
> ><br>
> > class QxlDod;<br>
> ><br>
> > -class HwDeviceIntrface {<br>
> > +//<br>
> > +// Can't use virtual for functions that are non-pageable because there is<br>
> > no guarantee<br>
> > +// that the vtable will not be paged out. Will test for type in the<br>
> > parent<br>
> > call and<br>
> > +// cast to call in the correct device class.<br>
> > +//<br>
> > +<br>
> > +typedef enum {<br>
> > + QXL_DEVICE,<br>
> > + VGA_DEVICE,<br>
> > + INVALID_DEVICE,<br>
> > +}WIN_QXL_DEVICE_TYPE;<br>
> > +<br>
> > +class HwDeviceInterface {<br>
> > public:<br>
> > -// HwDeviceIntrface(_In_ QxlDod* pQxlDod) {;}<br>
> > - virtual ~HwDeviceIntrface() {;}<br>
> > + HwDeviceInterface(_In_ QxlDod* pQxlDod) {m_type = INVALID_DEVICE;}<br>
> > + virtual ~HwDeviceInterface() {;}<br>
> > virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0;<br>
> > virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0;<br>
> > virtual NTSTATUS GetCurrentMode(ULONG* Mode) = 0;<br>
> > virtual NTSTATUS SetPowerState(DEVICE_POWER_<wbr>STATE DevicePowerState,<br>
> > DXGK_DISPLAY_INFORMATION* pDispInfo) = 0;<br>
> > virtual NTSTATUS HWInit(PCM_RESOURCE_LIST pResList,<br>
> > DXGK_DISPLAY_INFORMATION* pDispInfo) = 0;<br>
> > virtual NTSTATUS HWClose(void) = 0;<br>
> > - virtual BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE<br>
> > pDxgkInterface,<br>
> > _In_ ULONG MessageNumber) = 0;<br>
> > - virtual VOID DpcRoutine(PVOID) = 0;<br>
> > - virtual VOID ResetDevice(void) = 0;<br>
> > -<br>
> > virtual ULONG GetModeCount(void) = 0;<br>
> > +<br>
> > + BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_<br>
> > ULONG MessageNumber);;<br>
> > + VOID DpcRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface);<br>
> > + VOID ResetDevice(void);;<br>
> > +<br>
> > PVIDEO_MODE_INFORMATION GetModeInfo(UINT idx) {return<br>
> > &m_ModeInfo[idx];}<br>
> > USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];}<br>
> > USHORT GetCurrentModeIndex(void) {return m_CurrentMode;}<br>
> > @@ -259,10 +272,11 @@ protected:<br>
> > USHORT m_CurrentMode;<br>
> > USHORT m_CustomMode;<br>
> > ULONG m_Id;<br>
> > + WIN_QXL_DEVICE_TYPE m_type;<br>
> > };<br>
> ><br>
> > class VgaDevice :<br>
> > - public HwDeviceIntrface<br>
> > + public HwDeviceInterface<br>
> > {<br>
> > public:<br>
> > VgaDevice(_In_ QxlDod* pQxlDod);<br>
> > @@ -287,9 +301,9 @@ public:<br>
> > _In_ D3DKMDT_VIDPN_PRESENT_PATH_<wbr>ROTATION<br>
> > Rotation,<br>
> > _In_ const CURRENT_BDD_MODE* pModeCur);<br>
> > VOID BlackOutScreen(CURRENT_BDD_<wbr>MODE* pCurrentBddMod);<br>
> > - BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_<br>
> > ULONG MessageNumber);<br>
> > - VOID DpcRoutine(PVOID);<br>
> > - VOID ResetDevice(VOID);<br>
> > + BOOLEAN HWInterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface,<br>
> > _In_<br>
> > ULONG MessageNumber);<br>
> > + VOID HWDpcRoutine(PDXGKRNL_<wbr>INTERFACE pDxgkInterface);<br>
> > + VOID HWResetDevice(VOID);<br>
> > NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE*<br>
> > pSetPointerShape);<br>
> > NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION*<br>
> > pSetPointerPosition);<br>
> > NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap);<br>
> > @@ -435,7 +449,7 @@ typedef struct DpcCbContext {<br>
> > #define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))<br>
> ><br>
> > class QxlDevice :<br>
> > - public HwDeviceIntrface<br>
> > + public HwDeviceInterface<br>
> > {<br>
> > public:<br>
> > QxlDevice(_In_ QxlDod* pQxlDod);<br>
> > @@ -460,9 +474,9 @@ public:<br>
> > _In_ D3DKMDT_VIDPN_PRESENT_PATH_<wbr>ROTATION Rotation,<br>
> > _In_ const CURRENT_BDD_MODE* pModeCur);<br>
> > VOID BlackOutScreen(CURRENT_BDD_<wbr>MODE* pCurrentBddMod);<br>
> > - BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_<br>
> > ULONG MessageNumber);<br>
> > - VOID DpcRoutine(PVOID);<br>
> > - VOID ResetDevice(VOID);<br>
> > + BOOLEAN HWInterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface,<br>
> > _In_<br>
> > ULONG MessageNumber);<br>
> > + VOID HWDpcRoutine(PDXGKRNL_<wbr>INTERFACE pDxgkInterface);<br>
> > + VOID HWResetDevice(VOID);<br>
> > NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE*<br>
> > pSetPointerShape);<br>
> > NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION*<br>
> > pSetPointerPosition);<br>
> > NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap);<br>
> > @@ -592,7 +606,7 @@ private:<br>
> ><br>
> > D3DDDI_VIDEO_PRESENT_SOURCE_ID m_SystemDisplaySourceId;<br>
> > DXGKARG_SETPOINTERSHAPE m_PointerShape;<br>
> > - HwDeviceIntrface* m_pHWDevice;<br>
> > + HwDeviceInterface* m_pHWDevice;<br>
> > public:<br>
> > QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject);<br>
> > ~QxlDod(void);<br>
> > @@ -685,7 +699,7 @@ public:<br>
> > _In_<br>
> > UINT<br>
> > SourceStride,<br>
> > _In_<br>
> > INT<br>
> > PositionX,<br>
> > _In_<br>
> > INT<br>
> > PositionY);<br>
> > - PDXGKRNL_INTERFACE GetDxgkInterrface(void) { return &m_DxgkInterface;}<br>
> > + PDXGKRNL_INTERFACE GetDxgkInterface(void) { return &m_DxgkInterface;}<br>
> > private:<br>
> > VOID CleanUp(VOID);<br>
> > NTSTATUS CheckHardware();<br>
</div></div>> ______________________________<wbr>_________________<br>
> Spice-devel mailing list<br>
> <a href="mailto:Spice-devel@lists.freedesktop.org">Spice-devel@lists.freedesktop.<wbr>org</a><br>
> <a href="https://lists.freedesktop.org/mailman/listinfo/spice-devel" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/spice-devel</a><br>
><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><font size="4" color="#0b5394" face="times new roman, serif">Respectfully,<br></font><div style="font-size:12.8px;color:rgb(136,136,136)"><font size="4" color="#0b5394" face="times new roman, serif"><b><i>Sameeh Jubran</i></b></font></div><div style="font-size:12.8px;color:rgb(136,136,136)"><i style="color:rgb(7,55,99);font-family:"times new roman",serif;font-size:large"><span style="line-height:15px"><a href="https://il.linkedin.com/pub/sameeh-jubran/87/747/a8a" title="View public profile" name="UNIQUE_ID_SafeHtmlFilter_UNIQUE_ID_SafeHtmlFilter_UNIQUE_ID_SafeHtmlFilter_UNIQUE_ID_SafeHtmlFilter_14e2c1de96f8c195_UNIQUE_ID_SafeHtmlFilter_SafeHtmlFilter_SafeHtmlFilter_webProfileURL" style="color:rgb(17,85,204);margin:0px;padding:0px;border-width:0px;outline:none;vertical-align:baseline;text-decoration:none" target="_blank">Linkedin</a></span></i><br></div><div style="font-size:12.8px;color:rgb(136,136,136)"><font size="4" face="times new roman, serif" color="#073763"><i>Junior Software Engineer @ <a href="http://www.daynix.com" target="_blank">Daynix</a>.</i></font></div></div></div></div></div></div></div>
</div>