| File: | randr/rroutput.c |
| Location: | line 475, column 18 |
| Description: | Array access (from variable 'crtcs') results in a null pointer dereference |
| 1 | /* | |||
| 2 | * Copyright © 2006 Keith Packard | |||
| 3 | * Copyright © 2008 Red Hat, Inc. | |||
| 4 | * | |||
| 5 | * Permission to use, copy, modify, distribute, and sell this software and its | |||
| 6 | * documentation for any purpose is hereby granted without fee, provided that | |||
| 7 | * the above copyright notice appear in all copies and that both that copyright | |||
| 8 | * notice and this permission notice appear in supporting documentation, and | |||
| 9 | * that the name of the copyright holders not be used in advertising or | |||
| 10 | * publicity pertaining to distribution of the software without specific, | |||
| 11 | * written prior permission. The copyright holders make no representations | |||
| 12 | * about the suitability of this software for any purpose. It is provided "as | |||
| 13 | * is" without express or implied warranty. | |||
| 14 | * | |||
| 15 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
| 16 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
| 17 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
| 18 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |||
| 19 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| 20 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| 21 | * OF THIS SOFTWARE. | |||
| 22 | */ | |||
| 23 | ||||
| 24 | #include "randrstr.h" | |||
| 25 | ||||
| 26 | RESTYPE RROutputType; | |||
| 27 | ||||
| 28 | /* | |||
| 29 | * Notify the output of some change | |||
| 30 | */ | |||
| 31 | void | |||
| 32 | RROutputChanged(RROutputPtr output, Bool configChanged) | |||
| 33 | { | |||
| 34 | /* set changed bits on the master screen only */ | |||
| 35 | ScreenPtr pScreen = output->pScreen; | |||
| 36 | rrScrPrivPtr mastersp; | |||
| 37 | ||||
| 38 | output->changed = TRUE1; | |||
| 39 | if (!pScreen) | |||
| 40 | return; | |||
| 41 | ||||
| 42 | if (pScreen->isGPU) { | |||
| 43 | ScreenPtr master = pScreen->current_master; | |||
| 44 | if (!master) | |||
| 45 | return; | |||
| 46 | mastersp = rrGetScrPriv(master)((rrScrPrivPtr)dixLookupPrivate(&(master)->devPrivates , (&rrPrivKeyRec))); | |||
| 47 | } | |||
| 48 | else { | |||
| 49 | mastersp = rrGetScrPriv(pScreen)((rrScrPrivPtr)dixLookupPrivate(&(pScreen)->devPrivates , (&rrPrivKeyRec))); | |||
| 50 | } | |||
| 51 | ||||
| 52 | RRSetChanged(pScreen); | |||
| 53 | if (configChanged) | |||
| 54 | mastersp->configChanged = TRUE1; | |||
| 55 | } | |||
| 56 | ||||
| 57 | /* | |||
| 58 | * Create an output | |||
| 59 | */ | |||
| 60 | ||||
| 61 | RROutputPtr | |||
| 62 | RROutputCreate(ScreenPtr pScreen, | |||
| 63 | const char *name, int nameLength, void *devPrivate) | |||
| 64 | { | |||
| 65 | RROutputPtr output; | |||
| 66 | RROutputPtr *outputs; | |||
| 67 | rrScrPrivPtr pScrPriv; | |||
| 68 | ||||
| 69 | if (!RRInit()) | |||
| 70 | return NULL((void*)0); | |||
| 71 | ||||
| 72 | pScrPriv = rrGetScrPriv(pScreen)((rrScrPrivPtr)dixLookupPrivate(&(pScreen)->devPrivates , (&rrPrivKeyRec))); | |||
| 73 | ||||
| 74 | if (pScrPriv->numOutputs) | |||
| 75 | outputs = reallocarrayxreallocarray(pScrPriv->outputs, | |||
| 76 | pScrPriv->numOutputs + 1, sizeof(RROutputPtr)); | |||
| 77 | else | |||
| 78 | outputs = malloc(sizeof(RROutputPtr)); | |||
| 79 | if (!outputs) | |||
| 80 | return FALSE0; | |||
| 81 | ||||
| 82 | pScrPriv->outputs = outputs; | |||
| 83 | ||||
| 84 | output = malloc(sizeof(RROutputRec) + nameLength + 1); | |||
| 85 | if (!output) | |||
| 86 | return NULL((void*)0); | |||
| 87 | output->id = FakeClientID(0); | |||
| 88 | output->pScreen = pScreen; | |||
| 89 | output->name = (char *) (output + 1); | |||
| 90 | output->nameLength = nameLength; | |||
| 91 | memcpy(output->name, name, nameLength)__builtin___memcpy_chk (output->name, name, nameLength, __builtin_object_size (output->name, 0)); | |||
| 92 | output->name[nameLength] = '\0'; | |||
| 93 | output->connection = RR_UnknownConnection2; | |||
| 94 | output->subpixelOrder = SubPixelUnknown0; | |||
| 95 | output->mmWidth = 0; | |||
| 96 | output->mmHeight = 0; | |||
| 97 | output->crtc = NULL((void*)0); | |||
| 98 | output->numCrtcs = 0; | |||
| 99 | output->crtcs = NULL((void*)0); | |||
| 100 | output->numClones = 0; | |||
| 101 | output->clones = NULL((void*)0); | |||
| 102 | output->numModes = 0; | |||
| 103 | output->numPreferred = 0; | |||
| 104 | output->modes = NULL((void*)0); | |||
| 105 | output->numUserModes = 0; | |||
| 106 | output->userModes = NULL((void*)0); | |||
| 107 | output->properties = NULL((void*)0); | |||
| 108 | output->pendingProperties = FALSE0; | |||
| 109 | output->changed = FALSE0; | |||
| 110 | output->devPrivate = devPrivate; | |||
| 111 | ||||
| 112 | if (!AddResourceDarwin_X_AddResource(output->id, RROutputType, (void *) output)) | |||
| 113 | return NULL((void*)0); | |||
| 114 | ||||
| 115 | pScrPriv->outputs[pScrPriv->numOutputs++] = output; | |||
| 116 | ||||
| 117 | RRResourcesChanged(pScreen); | |||
| 118 | ||||
| 119 | return output; | |||
| 120 | } | |||
| 121 | ||||
| 122 | /* | |||
| 123 | * Notify extension that output parameters have been changed | |||
| 124 | */ | |||
| 125 | Bool | |||
| 126 | RROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones) | |||
| 127 | { | |||
| 128 | RROutputPtr *newClones; | |||
| 129 | int i; | |||
| 130 | ||||
| 131 | if (numClones == output->numClones) { | |||
| 132 | for (i = 0; i < numClones; i++) | |||
| 133 | if (output->clones[i] != clones[i]) | |||
| 134 | break; | |||
| 135 | if (i == numClones) | |||
| 136 | return TRUE1; | |||
| 137 | } | |||
| 138 | if (numClones) { | |||
| 139 | newClones = xallocarray(numClones, sizeof(RROutputPtr))xreallocarray(((void*)0), (numClones), (sizeof(RROutputPtr))); | |||
| 140 | if (!newClones) | |||
| 141 | return FALSE0; | |||
| 142 | } | |||
| 143 | else | |||
| 144 | newClones = NULL((void*)0); | |||
| 145 | free(output->clones); | |||
| 146 | memcpy(newClones, clones, numClones * sizeof(RROutputPtr))__builtin___memcpy_chk (newClones, clones, numClones * sizeof (RROutputPtr), __builtin_object_size (newClones, 0)); | |||
| 147 | output->clones = newClones; | |||
| 148 | output->numClones = numClones; | |||
| 149 | RROutputChanged(output, TRUE1); | |||
| 150 | return TRUE1; | |||
| 151 | } | |||
| 152 | ||||
| 153 | Bool | |||
| 154 | RROutputSetModes(RROutputPtr output, | |||
| 155 | RRModePtr * modes, int numModes, int numPreferred) | |||
| 156 | { | |||
| 157 | RRModePtr *newModes; | |||
| 158 | int i; | |||
| 159 | ||||
| 160 | if (numModes == output->numModes && numPreferred == output->numPreferred) { | |||
| 161 | for (i = 0; i < numModes; i++) | |||
| 162 | if (output->modes[i] != modes[i]) | |||
| 163 | break; | |||
| 164 | if (i == numModes) { | |||
| 165 | for (i = 0; i < numModes; i++) | |||
| 166 | RRModeDestroy(modes[i]); | |||
| 167 | return TRUE1; | |||
| 168 | } | |||
| 169 | } | |||
| 170 | ||||
| 171 | if (numModes) { | |||
| 172 | newModes = xallocarray(numModes, sizeof(RRModePtr))xreallocarray(((void*)0), (numModes), (sizeof(RRModePtr))); | |||
| 173 | if (!newModes) | |||
| 174 | return FALSE0; | |||
| 175 | } | |||
| 176 | else | |||
| 177 | newModes = NULL((void*)0); | |||
| 178 | if (output->modes) { | |||
| 179 | for (i = 0; i < output->numModes; i++) | |||
| 180 | RRModeDestroy(output->modes[i]); | |||
| 181 | free(output->modes); | |||
| 182 | } | |||
| 183 | memcpy(newModes, modes, numModes * sizeof(RRModePtr))__builtin___memcpy_chk (newModes, modes, numModes * sizeof(RRModePtr ), __builtin_object_size (newModes, 0)); | |||
| 184 | output->modes = newModes; | |||
| 185 | output->numModes = numModes; | |||
| 186 | output->numPreferred = numPreferred; | |||
| 187 | RROutputChanged(output, TRUE1); | |||
| 188 | return TRUE1; | |||
| 189 | } | |||
| 190 | ||||
| 191 | int | |||
| 192 | RROutputAddUserMode(RROutputPtr output, RRModePtr mode) | |||
| 193 | { | |||
| 194 | int m; | |||
| 195 | ScreenPtr pScreen = output->pScreen; | |||
| 196 | ||||
| 197 | rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(& (pScreen)->devPrivates, (&rrPrivKeyRec))); | |||
| 198 | RRModePtr *newModes; | |||
| 199 | ||||
| 200 | /* Check to see if this mode is already listed for this output */ | |||
| 201 | for (m = 0; m < output->numModes + output->numUserModes; m++) { | |||
| 202 | RRModePtr e = (m < output->numModes ? | |||
| 203 | output->modes[m] : | |||
| 204 | output->userModes[m - output->numModes]); | |||
| 205 | if (mode == e) | |||
| 206 | return Success0; | |||
| 207 | } | |||
| 208 | ||||
| 209 | /* Check with the DDX to see if this mode is OK */ | |||
| 210 | if (pScrPriv->rrOutputValidateMode) | |||
| 211 | if (!pScrPriv->rrOutputValidateMode(pScreen, output, mode)) | |||
| 212 | return BadMatch8; | |||
| 213 | ||||
| 214 | if (output->userModes) | |||
| 215 | newModes = reallocarrayxreallocarray(output->userModes, | |||
| 216 | output->numUserModes + 1, sizeof(RRModePtr)); | |||
| 217 | else | |||
| 218 | newModes = malloc(sizeof(RRModePtr)); | |||
| 219 | if (!newModes) | |||
| 220 | return BadAlloc11; | |||
| 221 | ||||
| 222 | output->userModes = newModes; | |||
| 223 | output->userModes[output->numUserModes++] = mode; | |||
| 224 | ++mode->refcnt; | |||
| 225 | RROutputChanged(output, TRUE1); | |||
| 226 | RRTellChanged(pScreen); | |||
| 227 | return Success0; | |||
| 228 | } | |||
| 229 | ||||
| 230 | int | |||
| 231 | RROutputDeleteUserMode(RROutputPtr output, RRModePtr mode) | |||
| 232 | { | |||
| 233 | int m; | |||
| 234 | ||||
| 235 | /* Find this mode in the user mode list */ | |||
| 236 | for (m = 0; m < output->numUserModes; m++) { | |||
| 237 | RRModePtr e = output->userModes[m]; | |||
| 238 | ||||
| 239 | if (mode == e) | |||
| 240 | break; | |||
| 241 | } | |||
| 242 | /* Not there, access error */ | |||
| 243 | if (m == output->numUserModes) | |||
| 244 | return BadAccess10; | |||
| 245 | ||||
| 246 | /* make sure the mode isn't active for this output */ | |||
| 247 | if (output->crtc && output->crtc->mode == mode) | |||
| 248 | return BadMatch8; | |||
| 249 | ||||
| 250 | memmove(output->userModes + m, output->userModes + m + 1,__builtin___memmove_chk (output->userModes + m, output-> userModes + m + 1, (output->numUserModes - m - 1) * sizeof (RRModePtr), __builtin_object_size (output->userModes + m, 0)) | |||
| 251 | (output->numUserModes - m - 1) * sizeof(RRModePtr))__builtin___memmove_chk (output->userModes + m, output-> userModes + m + 1, (output->numUserModes - m - 1) * sizeof (RRModePtr), __builtin_object_size (output->userModes + m, 0)); | |||
| 252 | output->numUserModes--; | |||
| 253 | RRModeDestroy(mode); | |||
| 254 | return Success0; | |||
| 255 | } | |||
| 256 | ||||
| 257 | Bool | |||
| 258 | RROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs) | |||
| 259 | { | |||
| 260 | RRCrtcPtr *newCrtcs; | |||
| 261 | int i; | |||
| 262 | ||||
| 263 | if (numCrtcs == output->numCrtcs) { | |||
| 264 | for (i = 0; i < numCrtcs; i++) | |||
| 265 | if (output->crtcs[i] != crtcs[i]) | |||
| 266 | break; | |||
| 267 | if (i == numCrtcs) | |||
| 268 | return TRUE1; | |||
| 269 | } | |||
| 270 | if (numCrtcs) { | |||
| 271 | newCrtcs = xallocarray(numCrtcs, sizeof(RRCrtcPtr))xreallocarray(((void*)0), (numCrtcs), (sizeof(RRCrtcPtr))); | |||
| 272 | if (!newCrtcs) | |||
| 273 | return FALSE0; | |||
| 274 | } | |||
| 275 | else | |||
| 276 | newCrtcs = NULL((void*)0); | |||
| 277 | free(output->crtcs); | |||
| 278 | memcpy(newCrtcs, crtcs, numCrtcs * sizeof(RRCrtcPtr))__builtin___memcpy_chk (newCrtcs, crtcs, numCrtcs * sizeof(RRCrtcPtr ), __builtin_object_size (newCrtcs, 0)); | |||
| 279 | output->crtcs = newCrtcs; | |||
| 280 | output->numCrtcs = numCrtcs; | |||
| 281 | RROutputChanged(output, TRUE1); | |||
| 282 | return TRUE1; | |||
| 283 | } | |||
| 284 | ||||
| 285 | Bool | |||
| 286 | RROutputSetConnection(RROutputPtr output, CARD8 connection) | |||
| 287 | { | |||
| 288 | if (output->connection == connection) | |||
| 289 | return TRUE1; | |||
| 290 | output->connection = connection; | |||
| 291 | RROutputChanged(output, TRUE1); | |||
| 292 | return TRUE1; | |||
| 293 | } | |||
| 294 | ||||
| 295 | Bool | |||
| 296 | RROutputSetSubpixelOrder(RROutputPtr output, int subpixelOrder) | |||
| 297 | { | |||
| 298 | if (output->subpixelOrder == subpixelOrder) | |||
| 299 | return TRUE1; | |||
| 300 | ||||
| 301 | output->subpixelOrder = subpixelOrder; | |||
| 302 | RROutputChanged(output, FALSE0); | |||
| 303 | return TRUE1; | |||
| 304 | } | |||
| 305 | ||||
| 306 | Bool | |||
| 307 | RROutputSetPhysicalSize(RROutputPtr output, int mmWidth, int mmHeight) | |||
| 308 | { | |||
| 309 | if (output->mmWidth == mmWidth && output->mmHeight == mmHeight) | |||
| 310 | return TRUE1; | |||
| 311 | output->mmWidth = mmWidth; | |||
| 312 | output->mmHeight = mmHeight; | |||
| 313 | RROutputChanged(output, FALSE0); | |||
| 314 | return TRUE1; | |||
| 315 | } | |||
| 316 | ||||
| 317 | void | |||
| 318 | RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output) | |||
| 319 | { | |||
| 320 | ScreenPtr pScreen = pWin->drawable.pScreen; | |||
| 321 | ||||
| 322 | rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(& (pScreen)->devPrivates, (&rrPrivKeyRec))); | |||
| 323 | RRCrtcPtr crtc = output->crtc; | |||
| 324 | RRModePtr mode = crtc ? crtc->mode : NULL((void*)0); | |||
| 325 | ||||
| 326 | xRROutputChangeNotifyEvent oe = { | |||
| 327 | .type = RRNotify1 + RREventBase, | |||
| 328 | .subCode = RRNotify_OutputChange1, | |||
| 329 | .timestamp = pScrPriv->lastSetTime.milliseconds, | |||
| 330 | .configTimestamp = pScrPriv->lastConfigTime.milliseconds, | |||
| 331 | .window = pWin->drawable.id, | |||
| 332 | .output = output->id, | |||
| 333 | .crtc = crtc ? crtc->id : None0L, | |||
| 334 | .mode = mode ? mode->mode.id : None0L, | |||
| 335 | .rotation = crtc ? crtc->rotation : RR_Rotate_01, | |||
| 336 | .connection = output->connection, | |||
| 337 | .subpixelOrder = output->subpixelOrder | |||
| 338 | }; | |||
| 339 | WriteEventsToClient(client, 1, (xEvent *) &oe); | |||
| 340 | } | |||
| 341 | ||||
| 342 | /* | |||
| 343 | * Destroy a Output at shutdown | |||
| 344 | */ | |||
| 345 | void | |||
| 346 | RROutputDestroy(RROutputPtr output) | |||
| 347 | { | |||
| 348 | FreeResource(output->id, 0); | |||
| 349 | } | |||
| 350 | ||||
| 351 | static int | |||
| 352 | RROutputDestroyResource(void *value, XID pid) | |||
| 353 | { | |||
| 354 | RROutputPtr output = (RROutputPtr) value; | |||
| 355 | ScreenPtr pScreen = output->pScreen; | |||
| 356 | int m; | |||
| 357 | ||||
| 358 | if (pScreen) { | |||
| 359 | rrScrPriv(pScreen)rrScrPrivPtr pScrPriv = ((rrScrPrivPtr)dixLookupPrivate(& (pScreen)->devPrivates, (&rrPrivKeyRec))); | |||
| 360 | int i; | |||
| 361 | ||||
| 362 | if (pScrPriv->primaryOutput == output) | |||
| 363 | pScrPriv->primaryOutput = NULL((void*)0); | |||
| 364 | ||||
| 365 | for (i = 0; i < pScrPriv->numOutputs; i++) { | |||
| 366 | if (pScrPriv->outputs[i] == output) { | |||
| 367 | memmove(pScrPriv->outputs + i, pScrPriv->outputs + i + 1,__builtin___memmove_chk (pScrPriv->outputs + i, pScrPriv-> outputs + i + 1, (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr), __builtin_object_size (pScrPriv->outputs + i , 0)) | |||
| 368 | (pScrPriv->numOutputs - (i + 1)) * sizeof(RROutputPtr))__builtin___memmove_chk (pScrPriv->outputs + i, pScrPriv-> outputs + i + 1, (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr), __builtin_object_size (pScrPriv->outputs + i , 0)); | |||
| 369 | --pScrPriv->numOutputs; | |||
| 370 | break; | |||
| 371 | } | |||
| 372 | } | |||
| 373 | ||||
| 374 | RRResourcesChanged(pScreen); | |||
| 375 | } | |||
| 376 | if (output->modes) { | |||
| 377 | for (m = 0; m < output->numModes; m++) | |||
| 378 | RRModeDestroy(output->modes[m]); | |||
| 379 | free(output->modes); | |||
| 380 | } | |||
| 381 | ||||
| 382 | for (m = 0; m < output->numUserModes; m++) | |||
| 383 | RRModeDestroy(output->userModes[m]); | |||
| 384 | free(output->userModes); | |||
| 385 | ||||
| 386 | free(output->crtcs); | |||
| 387 | free(output->clones); | |||
| 388 | RRDeleteAllOutputProperties(output); | |||
| 389 | free(output); | |||
| 390 | return 1; | |||
| 391 | } | |||
| 392 | ||||
| 393 | /* | |||
| 394 | * Initialize output type | |||
| 395 | */ | |||
| 396 | Bool | |||
| 397 | RROutputInit(void) | |||
| 398 | { | |||
| 399 | RROutputType = CreateNewResourceType(RROutputDestroyResource, "OUTPUT"); | |||
| 400 | if (!RROutputType) | |||
| 401 | return FALSE0; | |||
| 402 | ||||
| 403 | return TRUE1; | |||
| 404 | } | |||
| 405 | ||||
| 406 | /* | |||
| 407 | * Initialize output type error value | |||
| 408 | */ | |||
| 409 | void | |||
| 410 | RROutputInitErrorValue(void) | |||
| 411 | { | |||
| 412 | SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput0); | |||
| 413 | } | |||
| 414 | ||||
| 415 | #define OutputInfoExtra(36 - 32) (SIZEOF(xRRGetOutputInfoReply)36 - 32) | |||
| 416 | ||||
| 417 | int | |||
| 418 | ProcRRGetOutputInfo(ClientPtr client) | |||
| 419 | { | |||
| 420 | REQUEST(xRRGetOutputInfoReq)xRRGetOutputInfoReq *stuff = (xRRGetOutputInfoReq *)client-> requestBuffer; | |||
| 421 | xRRGetOutputInfoReply rep; | |||
| 422 | RROutputPtr output; | |||
| 423 | CARD8 *extra; | |||
| 424 | unsigned long extraLen; | |||
| 425 | ScreenPtr pScreen; | |||
| 426 | rrScrPrivPtr pScrPriv; | |||
| 427 | RRCrtc *crtcs; | |||
| 428 | RRMode *modes; | |||
| 429 | RROutput *clones; | |||
| 430 | char *name; | |||
| 431 | int i; | |||
| 432 | ||||
| 433 | REQUEST_SIZE_MATCH(xRRGetOutputInfoReq)if ((sizeof(xRRGetOutputInfoReq) >> 2) != client->req_len ) return(16); | |||
| 434 | VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess){ int rc = dixLookupResourceByType((void **)&(output), stuff ->output, RROutputType, client, (1<<0)); if (rc != 0 ) { client->errorValue = stuff->output; return rc; } }; | |||
| 435 | ||||
| 436 | pScreen = output->pScreen; | |||
| 437 | pScrPriv = rrGetScrPriv(pScreen)((rrScrPrivPtr)dixLookupPrivate(&(pScreen)->devPrivates , (&rrPrivKeyRec))); | |||
| 438 | ||||
| 439 | rep = (xRRGetOutputInfoReply) { | |||
| 440 | .type = X_Reply1, | |||
| 441 | .status = RRSetConfigSuccess0, | |||
| 442 | .sequenceNumber = client->sequence, | |||
| 443 | .length = bytes_to_int32(OutputInfoExtra(36 - 32)), | |||
| 444 | .timestamp = pScrPriv->lastSetTime.milliseconds, | |||
| 445 | .crtc = output->crtc ? output->crtc->id : None0L, | |||
| ||||
| 446 | .mmWidth = output->mmWidth, | |||
| 447 | .mmHeight = output->mmHeight, | |||
| 448 | .connection = output->connection, | |||
| 449 | .subpixelOrder = output->subpixelOrder, | |||
| 450 | .nCrtcs = output->numCrtcs, | |||
| 451 | .nModes = output->numModes + output->numUserModes, | |||
| 452 | .nPreferred = output->numPreferred, | |||
| 453 | .nClones = output->numClones, | |||
| 454 | .nameLength = output->nameLength | |||
| 455 | }; | |||
| 456 | extraLen = ((output->numCrtcs + | |||
| 457 | output->numModes + output->numUserModes + | |||
| 458 | output->numClones + bytes_to_int32(rep.nameLength)) << 2); | |||
| 459 | ||||
| 460 | if (extraLen) { | |||
| 461 | rep.length += bytes_to_int32(extraLen); | |||
| 462 | extra = malloc(extraLen); | |||
| 463 | if (!extra) | |||
| 464 | return BadAlloc11; | |||
| 465 | } | |||
| 466 | else | |||
| 467 | extra = NULL((void*)0); | |||
| 468 | ||||
| 469 | crtcs = (RRCrtc *) extra; | |||
| 470 | modes = (RRMode *) (crtcs + output->numCrtcs); | |||
| 471 | clones = (RROutput *) (modes + output->numModes + output->numUserModes); | |||
| 472 | name = (char *) (clones + output->numClones); | |||
| 473 | ||||
| 474 | for (i = 0; i < output->numCrtcs; i++) { | |||
| 475 | crtcs[i] = output->crtcs[i]->id; | |||
| ||||
| 476 | if (client->swapped) | |||
| 477 | swapl(&crtcs[i])do { if (sizeof(*(&crtcs[i])) != 4) wrong_size(); if (__builtin_constant_p ((uintptr_t)(&crtcs[i]) & 3) && ((uintptr_t)( &crtcs[i]) & 3) == 0) *(&crtcs[i]) = lswapl(*(& crtcs[i])); else swap_uint32((uint32_t *)(&crtcs[i])); } while (0); | |||
| 478 | } | |||
| 479 | for (i = 0; i < output->numModes + output->numUserModes; i++) { | |||
| 480 | if (i < output->numModes) | |||
| 481 | modes[i] = output->modes[i]->mode.id; | |||
| 482 | else | |||
| 483 | modes[i] = output->userModes[i - output->numModes]->mode.id; | |||
| 484 | if (client->swapped) | |||
| 485 | swapl(&modes[i])do { if (sizeof(*(&modes[i])) != 4) wrong_size(); if (__builtin_constant_p ((uintptr_t)(&modes[i]) & 3) && ((uintptr_t)( &modes[i]) & 3) == 0) *(&modes[i]) = lswapl(*(& modes[i])); else swap_uint32((uint32_t *)(&modes[i])); } while (0); | |||
| 486 | } | |||
| 487 | for (i = 0; i < output->numClones; i++) { | |||
| 488 | clones[i] = output->clones[i]->id; | |||
| 489 | if (client->swapped) | |||
| 490 | swapl(&clones[i])do { if (sizeof(*(&clones[i])) != 4) wrong_size(); if (__builtin_constant_p ((uintptr_t)(&clones[i]) & 3) && ((uintptr_t) (&clones[i]) & 3) == 0) *(&clones[i]) = lswapl(*( &clones[i])); else swap_uint32((uint32_t *)(&clones[i ])); } while (0); | |||
| 491 | } | |||
| 492 | memcpy(name, output->name, output->nameLength)__builtin___memcpy_chk (name, output->name, output->nameLength , __builtin_object_size (name, 0)); | |||
| 493 | if (client->swapped) { | |||
| 494 | swaps(&rep.sequenceNumber)do { if (sizeof(*(&rep.sequenceNumber)) != 2) wrong_size( ); if (__builtin_constant_p((uintptr_t)(&rep.sequenceNumber ) & 1) && ((uintptr_t)(&rep.sequenceNumber) & 1) == 0) *(&rep.sequenceNumber) = lswaps(*(&rep.sequenceNumber )); else swap_uint16((uint16_t *)(&rep.sequenceNumber)); } while (0); | |||
| 495 | swapl(&rep.length)do { if (sizeof(*(&rep.length)) != 4) wrong_size(); if (__builtin_constant_p ((uintptr_t)(&rep.length) & 3) && ((uintptr_t )(&rep.length) & 3) == 0) *(&rep.length) = lswapl (*(&rep.length)); else swap_uint32((uint32_t *)(&rep. length)); } while (0); | |||
| 496 | swapl(&rep.timestamp)do { if (sizeof(*(&rep.timestamp)) != 4) wrong_size(); if (__builtin_constant_p((uintptr_t)(&rep.timestamp) & 3 ) && ((uintptr_t)(&rep.timestamp) & 3) == 0) * (&rep.timestamp) = lswapl(*(&rep.timestamp)); else swap_uint32 ((uint32_t *)(&rep.timestamp)); } while (0); | |||
| 497 | swapl(&rep.crtc)do { if (sizeof(*(&rep.crtc)) != 4) wrong_size(); if (__builtin_constant_p ((uintptr_t)(&rep.crtc) & 3) && ((uintptr_t)( &rep.crtc) & 3) == 0) *(&rep.crtc) = lswapl(*(& rep.crtc)); else swap_uint32((uint32_t *)(&rep.crtc)); } while (0); | |||
| 498 | swapl(&rep.mmWidth)do { if (sizeof(*(&rep.mmWidth)) != 4) wrong_size(); if ( __builtin_constant_p((uintptr_t)(&rep.mmWidth) & 3) && ((uintptr_t)(&rep.mmWidth) & 3) == 0) *(&rep.mmWidth ) = lswapl(*(&rep.mmWidth)); else swap_uint32((uint32_t * )(&rep.mmWidth)); } while (0); | |||
| 499 | swapl(&rep.mmHeight)do { if (sizeof(*(&rep.mmHeight)) != 4) wrong_size(); if ( __builtin_constant_p((uintptr_t)(&rep.mmHeight) & 3) && ((uintptr_t)(&rep.mmHeight) & 3) == 0) *(&rep.mmHeight ) = lswapl(*(&rep.mmHeight)); else swap_uint32((uint32_t * )(&rep.mmHeight)); } while (0); | |||
| 500 | swaps(&rep.nCrtcs)do { if (sizeof(*(&rep.nCrtcs)) != 2) wrong_size(); if (__builtin_constant_p ((uintptr_t)(&rep.nCrtcs) & 1) && ((uintptr_t )(&rep.nCrtcs) & 1) == 0) *(&rep.nCrtcs) = lswaps (*(&rep.nCrtcs)); else swap_uint16((uint16_t *)(&rep. nCrtcs)); } while (0); | |||
| 501 | swaps(&rep.nModes)do { if (sizeof(*(&rep.nModes)) != 2) wrong_size(); if (__builtin_constant_p ((uintptr_t)(&rep.nModes) & 1) && ((uintptr_t )(&rep.nModes) & 1) == 0) *(&rep.nModes) = lswaps (*(&rep.nModes)); else swap_uint16((uint16_t *)(&rep. nModes)); } while (0); | |||
| 502 | swaps(&rep.nPreferred)do { if (sizeof(*(&rep.nPreferred)) != 2) wrong_size(); if (__builtin_constant_p((uintptr_t)(&rep.nPreferred) & 1) && ((uintptr_t)(&rep.nPreferred) & 1) == 0 ) *(&rep.nPreferred) = lswaps(*(&rep.nPreferred)); else swap_uint16((uint16_t *)(&rep.nPreferred)); } while (0); | |||
| 503 | swaps(&rep.nClones)do { if (sizeof(*(&rep.nClones)) != 2) wrong_size(); if ( __builtin_constant_p((uintptr_t)(&rep.nClones) & 1) && ((uintptr_t)(&rep.nClones) & 1) == 0) *(&rep.nClones ) = lswaps(*(&rep.nClones)); else swap_uint16((uint16_t * )(&rep.nClones)); } while (0); | |||
| 504 | swaps(&rep.nameLength)do { if (sizeof(*(&rep.nameLength)) != 2) wrong_size(); if (__builtin_constant_p((uintptr_t)(&rep.nameLength) & 1) && ((uintptr_t)(&rep.nameLength) & 1) == 0 ) *(&rep.nameLength) = lswaps(*(&rep.nameLength)); else swap_uint16((uint16_t *)(&rep.nameLength)); } while (0); | |||
| 505 | } | |||
| 506 | WriteToClient(client, sizeof(xRRGetOutputInfoReply), &rep); | |||
| 507 | if (extraLen) { | |||
| 508 | WriteToClient(client, extraLen, extra); | |||
| 509 | free(extra); | |||
| 510 | } | |||
| 511 | ||||
| 512 | return Success0; | |||
| 513 | } | |||
| 514 | ||||
| 515 | static void | |||
| 516 | RRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv, RROutputPtr output) | |||
| 517 | { | |||
| 518 | if (pScrPriv->primaryOutput == output) | |||
| 519 | return; | |||
| 520 | ||||
| 521 | /* clear the old primary */ | |||
| 522 | if (pScrPriv->primaryOutput) { | |||
| 523 | RROutputChanged(pScrPriv->primaryOutput, 0); | |||
| 524 | pScrPriv->primaryOutput = NULL((void*)0); | |||
| 525 | } | |||
| 526 | ||||
| 527 | /* set the new primary */ | |||
| 528 | if (output) { | |||
| 529 | pScrPriv->primaryOutput = output; | |||
| 530 | RROutputChanged(output, 0); | |||
| 531 | } | |||
| 532 | ||||
| 533 | pScrPriv->layoutChanged = TRUE1; | |||
| 534 | ||||
| 535 | RRTellChanged(pScreen); | |||
| 536 | } | |||
| 537 | ||||
| 538 | int | |||
| 539 | ProcRRSetOutputPrimary(ClientPtr client) | |||
| 540 | { | |||
| 541 | REQUEST(xRRSetOutputPrimaryReq)xRRSetOutputPrimaryReq *stuff = (xRRSetOutputPrimaryReq *)client ->requestBuffer; | |||
| 542 | RROutputPtr output = NULL((void*)0); | |||
| 543 | WindowPtr pWin; | |||
| 544 | rrScrPrivPtr pScrPriv; | |||
| 545 | int ret; | |||
| 546 | ScreenPtr slave; | |||
| 547 | ||||
| 548 | REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq)if ((sizeof(xRRSetOutputPrimaryReq) >> 2) != client-> req_len) return(16); | |||
| 549 | ||||
| 550 | ret = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess(1<<4)); | |||
| 551 | if (ret != Success0) | |||
| 552 | return ret; | |||
| 553 | ||||
| 554 | if (stuff->output) { | |||
| 555 | VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess){ int rc = dixLookupResourceByType((void **)&(output), stuff ->output, RROutputType, client, (1<<0)); if (rc != 0 ) { client->errorValue = stuff->output; return rc; } }; | |||
| 556 | ||||
| 557 | if (!output->pScreen->isGPU && output->pScreen != pWin->drawable.pScreen) { | |||
| 558 | client->errorValue = stuff->window; | |||
| 559 | return BadMatch8; | |||
| 560 | } | |||
| 561 | if (output->pScreen->isGPU && output->pScreen->current_master != pWin->drawable.pScreen) { | |||
| 562 | client->errorValue = stuff->window; | |||
| 563 | return BadMatch8; | |||
| 564 | } | |||
| 565 | } | |||
| 566 | ||||
| 567 | pScrPriv = rrGetScrPriv(pWin->drawable.pScreen)((rrScrPrivPtr)dixLookupPrivate(&(pWin->drawable.pScreen )->devPrivates, (&rrPrivKeyRec))); | |||
| 568 | if (pScrPriv) | |||
| 569 | { | |||
| 570 | RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output); | |||
| 571 | ||||
| 572 | xorg_list_for_each_entry(slave,for (slave = ((void*)0), slave = (typeof(*slave) *)((char *)( (&pWin->drawable.pScreen->output_slave_list)->next ) - __builtin_offsetof(typeof(*slave), output_head)); &slave ->output_head != (&pWin->drawable.pScreen->output_slave_list ); slave = (typeof(*slave) *)((char *)(slave->output_head. next) - __builtin_offsetof(typeof(*slave), output_head))) | |||
| 573 | &pWin->drawable.pScreen->output_slave_list,for (slave = ((void*)0), slave = (typeof(*slave) *)((char *)( (&pWin->drawable.pScreen->output_slave_list)->next ) - __builtin_offsetof(typeof(*slave), output_head)); &slave ->output_head != (&pWin->drawable.pScreen->output_slave_list ); slave = (typeof(*slave) *)((char *)(slave->output_head. next) - __builtin_offsetof(typeof(*slave), output_head))) | |||
| 574 | output_head)for (slave = ((void*)0), slave = (typeof(*slave) *)((char *)( (&pWin->drawable.pScreen->output_slave_list)->next ) - __builtin_offsetof(typeof(*slave), output_head)); &slave ->output_head != (&pWin->drawable.pScreen->output_slave_list ); slave = (typeof(*slave) *)((char *)(slave->output_head. next) - __builtin_offsetof(typeof(*slave), output_head))) { | |||
| 575 | rrScrPrivPtr pSlavePriv; | |||
| 576 | pSlavePriv = rrGetScrPriv(slave)((rrScrPrivPtr)dixLookupPrivate(&(slave)->devPrivates, (&rrPrivKeyRec))); | |||
| 577 | ||||
| 578 | RRSetPrimaryOutput(slave, pSlavePriv, output); | |||
| 579 | } | |||
| 580 | } | |||
| 581 | ||||
| 582 | return Success0; | |||
| 583 | } | |||
| 584 | ||||
| 585 | int | |||
| 586 | ProcRRGetOutputPrimary(ClientPtr client) | |||
| 587 | { | |||
| 588 | REQUEST(xRRGetOutputPrimaryReq)xRRGetOutputPrimaryReq *stuff = (xRRGetOutputPrimaryReq *)client ->requestBuffer; | |||
| 589 | WindowPtr pWin; | |||
| 590 | rrScrPrivPtr pScrPriv; | |||
| 591 | xRRGetOutputPrimaryReply rep; | |||
| 592 | RROutputPtr primary = NULL((void*)0); | |||
| 593 | int rc; | |||
| 594 | ||||
| 595 | REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq)if ((sizeof(xRRGetOutputPrimaryReq) >> 2) != client-> req_len) return(16); | |||
| 596 | ||||
| 597 | rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess(1<<4)); | |||
| 598 | if (rc != Success0) | |||
| 599 | return rc; | |||
| 600 | ||||
| 601 | pScrPriv = rrGetScrPriv(pWin->drawable.pScreen)((rrScrPrivPtr)dixLookupPrivate(&(pWin->drawable.pScreen )->devPrivates, (&rrPrivKeyRec))); | |||
| 602 | if (pScrPriv) | |||
| 603 | primary = pScrPriv->primaryOutput; | |||
| 604 | ||||
| 605 | rep = (xRRGetOutputPrimaryReply) { | |||
| 606 | .type = X_Reply1, | |||
| 607 | .sequenceNumber = client->sequence, | |||
| 608 | .output = primary ? primary->id : None0L | |||
| 609 | }; | |||
| 610 | ||||
| 611 | if (client->swapped) { | |||
| 612 | swaps(&rep.sequenceNumber)do { if (sizeof(*(&rep.sequenceNumber)) != 2) wrong_size( ); if (__builtin_constant_p((uintptr_t)(&rep.sequenceNumber ) & 1) && ((uintptr_t)(&rep.sequenceNumber) & 1) == 0) *(&rep.sequenceNumber) = lswaps(*(&rep.sequenceNumber )); else swap_uint16((uint16_t *)(&rep.sequenceNumber)); } while (0); | |||
| 613 | swapl(&rep.output)do { if (sizeof(*(&rep.output)) != 4) wrong_size(); if (__builtin_constant_p ((uintptr_t)(&rep.output) & 3) && ((uintptr_t )(&rep.output) & 3) == 0) *(&rep.output) = lswapl (*(&rep.output)); else swap_uint32((uint32_t *)(&rep. output)); } while (0); | |||
| 614 | } | |||
| 615 | ||||
| 616 | WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep); | |||
| 617 | ||||
| 618 | return Success0; | |||
| 619 | } |