예제 #1
0
+++ Xi/chgdctl.c
@@ -78,7 +78,7 @@ SProcXChangeDeviceControl(ClientPtr clie
 
     REQUEST(xChangeDeviceControlReq);
     swaps(&stuff->length);
-    REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq);
+    REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl));
     swaps(&stuff->control);
     ctl = (xDeviceCtl *) &stuff[1];
     swaps(&ctl->control);
@@ -116,7 +116,7 @@ ProcXChangeDeviceControl(ClientPtr clien
     devicePresenceNotify dpn;
 
     REQUEST(xChangeDeviceControlReq);
-    REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq);
+    REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl));
 
     len = stuff->length - bytes_to_int32(sizeof(xChangeDeviceControlReq));
     ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess);
@@ -184,6 +184,10 @@ ProcXChangeDeviceControl(ClientPtr clien
         break;
     case DEVICE_ENABLE:
         e = (xDeviceEnableCtl *) &stuff[1];
+        if ((len != bytes_to_int32(sizeof(xDeviceEnableCtl)))) {
+            ret = BadLength;
+            goto out;
+        }
 
         status = ChangeDeviceControl(client, dev, (xDeviceCtl *) e);
 
예제 #2
0
int
ProcXChangeDeviceControl(ClientPtr client)
{
    unsigned len;
    int i, status, ret = BadValue;
    DeviceIntPtr dev;
    xDeviceResolutionCtl *r;
    xChangeDeviceControlReply rep;
    AxisInfoPtr a;
    CARD32 *resolution;
    xDeviceEnableCtl *e;

    REQUEST(xChangeDeviceControlReq);
    REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq);

    len = stuff->length - bytes_to_int32(sizeof(xChangeDeviceControlReq));
    ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess);
    if (ret != Success)
        goto out;

    rep = (xChangeDeviceControlReply) {
        .repType = X_Reply,
        .RepType = X_ChangeDeviceControl,
        .sequenceNumber = client->sequence,
        .length = 0
    };

    switch (stuff->control) {
    case DEVICE_RESOLUTION:
        r = (xDeviceResolutionCtl *) &stuff[1];
        if ((len < bytes_to_int32(sizeof(xDeviceResolutionCtl))) ||
            (len !=
             bytes_to_int32(sizeof(xDeviceResolutionCtl)) + r->num_valuators)) {
            ret = BadLength;
            goto out;
        }
        if (!dev->valuator) {
            ret = BadMatch;
            goto out;
        }
        if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client)) {
            rep.status = AlreadyGrabbed;
            ret = Success;
            goto out;
        }
        resolution = (CARD32 *) (r + 1);
        if (r->first_valuator + r->num_valuators > dev->valuator->numAxes) {
            ret = BadValue;
            goto out;
        }
        status = ChangeDeviceControl(client, dev, (xDeviceCtl *) r);
        if (status == Success) {
            a = &dev->valuator->axes[r->first_valuator];
            for (i = 0; i < r->num_valuators; i++)
                if (*(resolution + i) < (a + i)->min_resolution ||
                    *(resolution + i) > (a + i)->max_resolution)
                    return BadValue;
            for (i = 0; i < r->num_valuators; i++)
                (a++)->resolution = *resolution++;

            ret = Success;
        }
        else if (status == DeviceBusy) {
            rep.status = DeviceBusy;
            ret = Success;
        }
        else {
            ret = BadMatch;
        }
        break;
    case DEVICE_ABS_CALIB:
    case DEVICE_ABS_AREA:
        /* Calibration is now done through properties, and never had any effect
         * on anything (in the open-source world). Thus, be honest. */
        ret = BadMatch;
        break;
    case DEVICE_CORE:
        /* Sorry, no device core switching no more. If you want a device to
         * send core events, attach it to a master device */
        ret = BadMatch;
        break;
    case DEVICE_ENABLE:
        e = (xDeviceEnableCtl *) &stuff[1];

        status = ChangeDeviceControl(client, dev, (xDeviceCtl *) e);

        if (status == Success) {
            if (e->enable)
                EnableDevice(dev, TRUE);
            else
                DisableDevice(dev, TRUE);
            ret = Success;
        }
        else if (status == DeviceBusy) {
            rep.status = DeviceBusy;
            ret = Success;
        }
        else {
            ret = BadMatch;
        }

        break;
    default:
        ret = BadValue;
    }

 out:
    if (ret == Success) {
        devicePresenceNotify dpn = {
            .type = DevicePresenceNotify,
            .time = currentTime.milliseconds,
            .devchange = DeviceControlChanged,
            .deviceid = dev->id,
            .control = stuff->control
        };
        SendEventToAllWindows(dev, DevicePresenceNotifyMask,
                              (xEvent *) &dpn, 1);

        WriteReplyToClient(client, sizeof(xChangeDeviceControlReply), &rep);
    }

    return ret;
}

/***********************************************************************
 *
 * This procedure writes the reply for the xChangeDeviceControl function,
 * if the client and server have a different byte ordering.
 *
 */

void
SRepXChangeDeviceControl(ClientPtr client, int size,
                         xChangeDeviceControlReply * rep)
{
    swaps(&rep->sequenceNumber);
    swapl(&rep->length);
    WriteToClient(client, size, rep);
}