IOReturn IOI2CInterfaceUserClient::extAcquireBus( void )
{
    IOReturn            ret = kIOReturnNotReady;
    IOI2CInterface *    provider;

    if ((provider = (IOI2CInterface *) copyParentEntry(gIOServicePlane)))
    {
        ret = provider->open( this ) ? kIOReturnSuccess : kIOReturnBusy;
        provider->release();
    }

    return (ret);
}
IOReturn IOI2CInterfaceUserClient::extReleaseBus( void )
{
    IOReturn            ret = kIOReturnNotReady;
    IOI2CInterface *    provider;

    if ((provider = (IOI2CInterface *) copyParentEntry(gIOServicePlane)))
    {
        provider->close( this );
        provider->release();
        ret = kIOReturnSuccess;
    }

    return (ret);
}
bool IOHIDInterface::matchPropertyTable(
                                OSDictionary *              table, 
                                SInt32 *                    score)
{
    IOService * provider;
    bool        ret;
    RETAIN_ON_STACK(this);
    
    if ( !super::matchPropertyTable(table, score) || !(provider = OSDynamicCast(IOService, copyParentEntry(gIOServicePlane))) )
        return false;
        
    // We should retain a reference to our provider while calling matchPropertyTable.
    // This is necessary in a situation where a user space process could be searching
    // the registry during termination.    
    ret = provider->matchPropertyTable(table, score);
    
    provider->release();
    
    return ret;
}
IOReturn IOI2CInterfaceUserClient::extIO(
    void * inStruct, void * outStruct,
    IOByteCount inSize, IOByteCount * outSize )
{
    IOReturn            err = kIOReturnNotReady;
    IOI2CInterface *    provider;
    IOI2CBuffer *       buffer;

    IOI2CRequest *                request;
    IOI2CRequest_10_5_0 * requestV1 = NULL;
    IOI2CRequest          requestV2;

    if (inSize < sizeof(IOI2CBuffer))
        return (kIOReturnNoSpace);
    if (*outSize < inSize)
        return (kIOReturnNoSpace);

        buffer = (IOI2CBuffer *) inStruct;
        request = &buffer->request;

        if (!request->sendTransactionType && !request->replyTransactionType)
        {
                requestV1 = (typeof (requestV1)) &buffer->request;
                bzero(&requestV2, sizeof(requestV2));
                request = &requestV2;

                request->sendTransactionType  = requestV1->sendTransactionType;
                request->replyTransactionType = requestV1->replyTransactionType;
                request->sendAddress          = requestV1->sendAddress;
                request->replyAddress         = requestV1->replyAddress;
                request->sendBytes            = requestV1->sendBytes;
                request->replyBytes           = requestV1->replyBytes;
                request->sendSubAddress       = requestV1->sendSubAddress;
                request->replySubAddress      = requestV1->replySubAddress;
                request->commFlags            = requestV1->commFlags;
                request->minReplyDelay        = requestV1->minReplyDelay;
        }
        else
        {
            /*
             <rdar://problem/23955672> ZDI-CAN-3453: Apple OS X IOGraphicsFamily Untrusted Pointer Dereference Privilege Escalation Vulnerability IOI2CInterfaceUserClient::extIO
             <rdar://problem/24172232> ZDI-CAN-3453: Apple OS X IOGraphicsFamily Untrusted Pointer Dereference Privilege Escalation Vulnerability IOI2CInterfaceUserClient::extIO
             <rdar://problem/24065934> ZDI- CAN-3489: Apple OS X IOGraphicsFamily Untrusted Pointer Dereference Privilege Escalation Vulnerability
             <rdar://problem/24172270> ZDI- CAN-3489: Apple OS X IOGraphicsFamily Untrusted Pointer Dereference Privilege Escalation Vulnerability

             Force completion to NULL if passed in from user land (V1 only case), V2 case handled by the bzero of the V2 structure (above).
             */
            request->completion = NULL;
        }

    if ((provider = (IOI2CInterface *) copyParentEntry(gIOServicePlane)))
        do
        {
            if (!provider->isOpen(this))
            {
                err = kIOReturnNotOpen;
                continue;
            }

            if (request->sendBytes)
            {
                if (!request->sendBuffer)
                    request->sendBuffer = (vm_address_t)  &buffer->inlineBuffer[0];
                else
                {
                    err = kIOReturnMessageTooLarge;
                    continue;
                }
            }
            if (request->replyBytes)
            {
                if (!request->replyBuffer)
                    request->replyBuffer = (vm_address_t) &buffer->inlineBuffer[0];
                else
                {
                    err = kIOReturnMessageTooLarge;
                    continue;
                }
            }

            err = provider->startIO( request );

                        if (requestV1)
                                requestV1->result = request->result;
        }
        while (false);

    if (provider)
        provider->release();

    if (kIOReturnSuccess == err)
    {
        *outSize = inSize;
        bcopy(inStruct, outStruct, inSize);
    }
    else
        *outSize = 0;

    return (err);
}