Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmonitor.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * PURPOSE: pMonitor support 00005 * FILE: subsys/win32k/ntuser/monitor.c 00006 * PROGRAMERS: Anich Gregor (blight@blight.eu.org) 00007 * Rafal Harabien (rafalh@reactos.org) 00008 */ 00009 00010 #include <win32k.h> 00011 DBG_DEFAULT_CHANNEL(UserMonitor); 00012 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* GLOBALS *******************************************************************/ 00017 00018 /* List of monitors */ 00019 static PMONITOR gMonitorList = NULL; 00020 00021 /* PRIVATE FUNCTIONS **********************************************************/ 00022 00023 /* IntCreateMonitorObject 00024 * 00025 * Creates a MONITOR 00026 * 00027 * Return value 00028 * If the function succeeds a pointer to a MONITOR is returned. On failure 00029 * NULL is returned. 00030 */ 00031 static 00032 PMONITOR 00033 IntCreateMonitorObject() 00034 { 00035 return UserCreateObject(gHandleTable, NULL, NULL, otMonitor, sizeof(MONITOR)); 00036 } 00037 00038 /* IntDestroyMonitorObject 00039 * 00040 * Destroys a MONITOR 00041 * You have to be the owner of the monitors lock to safely destroy it. 00042 * 00043 * Arguments 00044 * 00045 * pMonitor 00046 * Pointer to the MONITOR which shall be deleted 00047 */ 00048 static 00049 void 00050 IntDestroyMonitorObject(IN PMONITOR pMonitor) 00051 { 00052 /* Remove monitor region */ 00053 if (pMonitor->hrgnMonitor) 00054 { 00055 GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); 00056 GreDeleteObject(pMonitor->hrgnMonitor); 00057 } 00058 00059 /* Destroy monitor object */ 00060 UserDereferenceObject(pMonitor); 00061 UserDeleteObject(UserHMGetHandle(pMonitor), otMonitor); 00062 } 00063 00064 /* UserGetMonitorObject 00065 * 00066 * Returns monitor object from handle or sets last error if handle is invalid 00067 * 00068 * Arguments 00069 * 00070 * hMonitor 00071 * Handle of MONITOR object 00072 */ 00073 PMONITOR NTAPI 00074 UserGetMonitorObject(IN HMONITOR hMonitor) 00075 { 00076 PMONITOR pMonitor; 00077 00078 if (!hMonitor) 00079 { 00080 EngSetLastError(ERROR_INVALID_MONITOR_HANDLE); 00081 return NULL; 00082 } 00083 00084 pMonitor = (PMONITOR)UserGetObject(gHandleTable, hMonitor, otMonitor); 00085 if (!pMonitor) 00086 { 00087 EngSetLastError(ERROR_INVALID_MONITOR_HANDLE); 00088 return NULL; 00089 } 00090 00091 return pMonitor; 00092 } 00093 00094 /* UserGetPrimaryMonitor 00095 * 00096 * Returns a PMONITOR for the primary monitor 00097 * 00098 * Return value 00099 * PMONITOR 00100 */ 00101 PMONITOR NTAPI 00102 UserGetPrimaryMonitor() 00103 { 00104 PMONITOR pMonitor; 00105 00106 /* Find primary monitor */ 00107 for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext) 00108 { 00109 if (pMonitor->IsPrimary) 00110 break; 00111 } 00112 00113 return pMonitor; 00114 } 00115 00116 /* UserAttachMonitor 00117 * 00118 * Creates a new MONITOR and appends it to the list of monitors. 00119 * 00120 * Arguments 00121 * 00122 * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached 00123 * DisplayNumber Display Number (starting with 0) 00124 * 00125 * Return value 00126 * Returns a NTSTATUS 00127 */ 00128 NTSTATUS NTAPI 00129 UserAttachMonitor(IN HDEV hDev) 00130 { 00131 PMONITOR pMonitor; 00132 00133 TRACE("Attaching monitor...\n"); 00134 00135 /* Create new monitor object */ 00136 pMonitor = IntCreateMonitorObject(); 00137 if (pMonitor == NULL) 00138 { 00139 TRACE("Couldnt create monitor object\n"); 00140 return STATUS_INSUFFICIENT_RESOURCES; 00141 } 00142 00143 pMonitor->hDev = hDev; 00144 pMonitor->cWndStack = 0; 00145 00146 if (gMonitorList == NULL) 00147 { 00148 TRACE("Primary monitor is beeing attached\n"); 00149 pMonitor->IsPrimary = TRUE; 00150 gMonitorList = pMonitor; 00151 } 00152 else 00153 { 00154 PMONITOR pmonLast = gMonitorList; 00155 TRACE("Additional monitor is beeing attached\n"); 00156 while (pmonLast->pMonitorNext != NULL) 00157 pmonLast = pmonLast->pMonitorNext; 00158 00159 pmonLast->pMonitorNext = pMonitor; 00160 } 00161 00162 UserUpdateMonitorSize(hDev); 00163 00164 return STATUS_SUCCESS; 00165 } 00166 00167 /* UserDetachMonitor 00168 * 00169 * Deletes a MONITOR and removes it from the list of monitors. 00170 * 00171 * Arguments 00172 * 00173 * pGdiDevice Pointer to the PDEVOBJ from which the monitor was detached 00174 * 00175 * Return value 00176 * Returns a NTSTATUS 00177 */ 00178 NTSTATUS NTAPI 00179 UserDetachMonitor(IN HDEV hDev) 00180 { 00181 PMONITOR pMonitor = gMonitorList, *pLink = &gMonitorList; 00182 00183 /* Find monitor attached to given device */ 00184 while (pMonitor != NULL) 00185 { 00186 if (pMonitor->hDev == hDev) 00187 break; 00188 00189 pLink = &pMonitor->pMonitorNext; 00190 pMonitor = pMonitor->pMonitorNext; 00191 } 00192 00193 if (pMonitor == NULL) 00194 { 00195 /* No monitor has been found */ 00196 return STATUS_INVALID_PARAMETER; 00197 } 00198 00199 /* We destroy primary monitor - set next as primary */ 00200 if (pMonitor->IsPrimary && pMonitor->pMonitorNext != NULL) 00201 pMonitor->pMonitorNext->IsPrimary = TRUE; 00202 00203 /* Update Next ptr in previous monitor */ 00204 *pLink = pMonitor->pMonitorNext; 00205 00206 /* Finally destroy monitor */ 00207 IntDestroyMonitorObject(pMonitor); 00208 00209 return STATUS_SUCCESS; 00210 } 00211 00212 /* UserUpdateMonitorSize 00213 * 00214 * Reset size of the monitor using atached device 00215 * 00216 * Arguments 00217 * 00218 * PMONITOR 00219 * pGdiDevice Pointer to the PDEVOBJ, which size has changed 00220 * 00221 * Return value 00222 * Returns a NTSTATUS 00223 */ 00224 NTSTATUS NTAPI 00225 UserUpdateMonitorSize(IN HDEV hDev) 00226 { 00227 PMONITOR pMonitor; 00228 SIZEL DeviceSize; 00229 00230 /* Find monitor attached to given device */ 00231 for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext) 00232 { 00233 if (pMonitor->hDev == hDev) 00234 break; 00235 } 00236 00237 if (pMonitor == NULL) 00238 { 00239 /* No monitor has been found */ 00240 return STATUS_INVALID_PARAMETER; 00241 } 00242 00243 /* Get the size of the hdev */ 00244 PDEVOBJ_sizl((PPDEVOBJ)hDev, &DeviceSize); 00245 00246 /* Update monitor size */ 00247 pMonitor->rcMonitor.left = 0; 00248 pMonitor->rcMonitor.top = 0; 00249 pMonitor->rcMonitor.right = pMonitor->rcMonitor.left + DeviceSize.cx; 00250 pMonitor->rcMonitor.bottom = pMonitor->rcMonitor.top + DeviceSize.cy; 00251 pMonitor->rcWork = pMonitor->rcMonitor; 00252 00253 /* Destroy monitor region... */ 00254 if (pMonitor->hrgnMonitor) 00255 { 00256 GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); 00257 GreDeleteObject(pMonitor->hrgnMonitor); 00258 } 00259 00260 /* ...and create new one */ 00261 pMonitor->hrgnMonitor = IntSysCreateRectRgnIndirect(&pMonitor->rcMonitor); 00262 if (pMonitor->hrgnMonitor) 00263 IntGdiSetRegionOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC); 00264 00265 return STATUS_SUCCESS; 00266 } 00267 00268 /* IntGetMonitorsFromRect 00269 * 00270 * Returns a list of monitor handles/rectangles. The rectangles in the list are 00271 * the areas of intersection with the monitors. 00272 * 00273 * Arguments 00274 * 00275 * pRect 00276 * Rectangle in desktop coordinates. If this is NULL all monitors are 00277 * returned and the rect list is filled with the sizes of the monitors. 00278 * 00279 * phMonitorList 00280 * Pointer to an array of HMONITOR which is filled with monitor handles. 00281 * Can be NULL 00282 * 00283 * prcMonitorList 00284 * Pointer to an array of RECT which is filled with intersection rects in 00285 * desktop coordinates. 00286 * Can be NULL, will be ignored if no intersecting monitor is found and 00287 * flags is MONITOR_DEFAULTTONEAREST 00288 * 00289 * dwListSize 00290 * Size of the phMonitorList and prcMonitorList arguments. If this is zero 00291 * phMonitorList and prcMonitorList are ignored. 00292 * 00293 * dwFlags 00294 * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL) 00295 * 00296 * Returns 00297 * The number of monitors which intersect the specified region. 00298 */ 00299 static 00300 UINT 00301 IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect, 00302 OPTIONAL OUT HMONITOR *phMonitorList, 00303 OPTIONAL OUT PRECTL prcMonitorList, 00304 OPTIONAL IN DWORD dwListSize, 00305 OPTIONAL IN DWORD dwFlags) 00306 { 00307 PMONITOR pMonitor, pNearestMonitor = NULL, pPrimaryMonitor = NULL; 00308 UINT cMonitors = 0; 00309 ULONG iNearestDistance = 0xffffffff; 00310 00311 /* Find monitors which intersects the rectangle */ 00312 for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext) 00313 { 00314 RECTL MonitorRect, IntersectionRect; 00315 00316 MonitorRect = pMonitor->rcMonitor; 00317 00318 TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n", 00319 MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom); 00320 00321 /* Save primary monitor for later usage */ 00322 if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pMonitor->IsPrimary) 00323 pPrimaryMonitor = pMonitor; 00324 00325 /* Check if a rect is given */ 00326 if (pRect == NULL) 00327 { 00328 /* No rect given, so use the full monitor rect */ 00329 IntersectionRect = MonitorRect; 00330 } 00331 /* We have a rect, calculate intersection */ 00332 else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect)) 00333 { 00334 /* Rects did not intersect */ 00335 if (dwFlags == MONITOR_DEFAULTTONEAREST) 00336 { 00337 ULONG cx, cy, iDistance; 00338 00339 /* Get x and y distance */ 00340 cx = min(abs(MonitorRect.left - pRect->right), 00341 abs(pRect->left - MonitorRect.right)); 00342 cy = min(abs(MonitorRect.top - pRect->bottom), 00343 abs(pRect->top - MonitorRect.bottom)); 00344 00345 /* Calculate distance square */ 00346 iDistance = cx * cx + cy * cy; 00347 00348 /* Check if this is the new nearest monitor */ 00349 if (iDistance < iNearestDistance) 00350 { 00351 iNearestDistance = iDistance; 00352 pNearestMonitor = pMonitor; 00353 } 00354 } 00355 00356 continue; 00357 } 00358 00359 /* Check if there's space in the buffer */ 00360 if (cMonitors < dwListSize) 00361 { 00362 /* Save monitor data */ 00363 if (phMonitorList != NULL) 00364 phMonitorList[cMonitors] = UserHMGetHandle(pMonitor); 00365 if (prcMonitorList != NULL) 00366 prcMonitorList[cMonitors] = IntersectionRect; 00367 } 00368 00369 /* Increase count of found monitors */ 00370 cMonitors++; 00371 } 00372 00373 /* Nothing has been found? */ 00374 if (cMonitors == 0) 00375 { 00376 /* Check if we shall default to the nearest monitor */ 00377 if (dwFlags == MONITOR_DEFAULTTONEAREST && pNearestMonitor) 00378 { 00379 if (phMonitorList && dwListSize > 0) 00380 phMonitorList[cMonitors] = UserHMGetHandle(pNearestMonitor); 00381 cMonitors++; 00382 } 00383 /* Check if we shall default to the primary monitor */ 00384 else if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pPrimaryMonitor) 00385 { 00386 if (phMonitorList != NULL && dwListSize > 0) 00387 phMonitorList[cMonitors] = UserHMGetHandle(pPrimaryMonitor); 00388 cMonitors++; 00389 } 00390 } 00391 00392 return cMonitors; 00393 } 00394 00395 PMONITOR NTAPI 00396 UserMonitorFromRect( 00397 PRECTL pRect, 00398 DWORD dwFlags) 00399 { 00400 ULONG cMonitors, LargestArea = 0, i; 00401 PRECTL prcMonitorList = NULL; 00402 HMONITOR *phMonitorList = NULL; 00403 HMONITOR hMonitor = NULL; 00404 00405 /* Check if flags are valid */ 00406 if (dwFlags != MONITOR_DEFAULTTONULL && 00407 dwFlags != MONITOR_DEFAULTTOPRIMARY && 00408 dwFlags != MONITOR_DEFAULTTONEAREST) 00409 { 00410 EngSetLastError(ERROR_INVALID_FLAGS); 00411 return NULL; 00412 } 00413 00414 /* Find intersecting monitors */ 00415 cMonitors = IntGetMonitorsFromRect(pRect, &hMonitor, NULL, 1, dwFlags); 00416 if (cMonitors <= 1) 00417 { 00418 /* No or one monitor found. Just return handle. */ 00419 goto cleanup; 00420 } 00421 00422 /* There is more than one monitor. Find monitor with largest intersection. 00423 Temporary reset hMonitor */ 00424 hMonitor = NULL; 00425 00426 /* Allocate helper buffers */ 00427 phMonitorList = ExAllocatePoolWithTag(PagedPool, 00428 sizeof(HMONITOR) * cMonitors, 00429 USERTAG_MONITORRECTS); 00430 if (phMonitorList == NULL) 00431 { 00432 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 00433 goto cleanup; 00434 } 00435 00436 prcMonitorList = ExAllocatePoolWithTag(PagedPool, 00437 sizeof(RECT) * cMonitors, 00438 USERTAG_MONITORRECTS); 00439 if (prcMonitorList == NULL) 00440 { 00441 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 00442 goto cleanup; 00443 } 00444 00445 /* Get intersecting monitors again but now with rectangle list */ 00446 cMonitors = IntGetMonitorsFromRect(pRect, phMonitorList, prcMonitorList, 00447 cMonitors, 0); 00448 00449 /* Find largest intersection */ 00450 for (i = 0; i < cMonitors; i++) 00451 { 00452 ULONG Area = (prcMonitorList[i].right - prcMonitorList[i].left) * 00453 (prcMonitorList[i].bottom - prcMonitorList[i].top); 00454 if (Area >= LargestArea) 00455 { 00456 hMonitor = phMonitorList[i]; 00457 LargestArea = Area; 00458 } 00459 } 00460 00461 cleanup: 00462 if (phMonitorList) 00463 ExFreePoolWithTag(phMonitorList, USERTAG_MONITORRECTS); 00464 if (prcMonitorList) 00465 ExFreePoolWithTag(prcMonitorList, USERTAG_MONITORRECTS); 00466 00467 return UserGetMonitorObject(hMonitor); 00468 } 00469 00470 00471 /* PUBLIC FUNCTIONS ***********************************************************/ 00472 00473 /* NtUserEnumDisplayMonitors 00474 * 00475 * Enumerates display monitors which intersect the given HDC/cliprect 00476 * 00477 * Arguments 00478 * 00479 * hdc 00480 * Handle to a DC for which to enum intersecting monitors. If this is NULL 00481 * it returns all monitors which are part of the current virtual screen. 00482 * 00483 * pUnsafeRect 00484 * Clipping rectangle with coordinate system origin at the DCs origin if the 00485 * given HDC is not NULL or in virtual screen coordinated if it is NULL. 00486 * Can be NULL 00487 * 00488 * phUnsafeMonitorList 00489 * Pointer to an array of HMONITOR which is filled with monitor handles. 00490 * Can be NULL 00491 * 00492 * prcUnsafeMonitorList 00493 * Pointer to an array of RECT which is filled with intersection rectangles. 00494 * Can be NULL 00495 * 00496 * dwListSize 00497 * Size of the hMonitorList and monitorRectList arguments. If this is zero 00498 * hMonitorList and monitorRectList are ignored. 00499 * 00500 * Returns 00501 * The number of monitors which intersect the specified region or -1 on failure. 00502 */ 00503 INT 00504 APIENTRY 00505 NtUserEnumDisplayMonitors( 00506 OPTIONAL IN HDC hdc, 00507 OPTIONAL IN LPCRECTL pUnsafeRect, 00508 OPTIONAL OUT HMONITOR *phUnsafeMonitorList, 00509 OPTIONAL OUT PRECTL prcUnsafeMonitorList, 00510 OPTIONAL IN DWORD dwListSize) 00511 { 00512 INT cMonitors, iRet = -1, i; 00513 HMONITOR *phMonitorList = NULL; 00514 PRECTL prcMonitorList = NULL; 00515 RECTL rc, *pRect; 00516 RECTL DcRect = {0}; 00517 NTSTATUS Status; 00518 00519 /* Get rectangle */ 00520 if (pUnsafeRect != NULL) 00521 { 00522 Status = MmCopyFromCaller(&rc, pUnsafeRect, sizeof(RECT)); 00523 if (!NT_SUCCESS(Status)) 00524 { 00525 TRACE("MmCopyFromCaller() failed!\n"); 00526 SetLastNtError(Status); 00527 return -1; 00528 } 00529 } 00530 00531 if (hdc != NULL) 00532 { 00533 PDC pDc; 00534 INT iRgnType; 00535 00536 /* Get visible region bounding rect */ 00537 pDc = DC_LockDc(hdc); 00538 if (pDc == NULL) 00539 { 00540 TRACE("DC_LockDc() failed!\n"); 00541 /* FIXME: setlasterror? */ 00542 return -1; 00543 } 00544 iRgnType = REGION_GetRgnBox(pDc->prgnVis, &DcRect); 00545 DC_UnlockDc(pDc); 00546 00547 if (iRgnType == 0) 00548 { 00549 TRACE("NtGdiGetRgnBox() failed!\n"); 00550 return -1; 00551 } 00552 if (iRgnType == NULLREGION) 00553 return 0; 00554 if (iRgnType == COMPLEXREGION) 00555 { 00556 /* TODO: Warning */ 00557 } 00558 00559 /* If hdc and pRect are given the area of interest is pRect with 00560 coordinate origin at the DC position */ 00561 if (pUnsafeRect != NULL) 00562 { 00563 rc.left += DcRect.left; 00564 rc.right += DcRect.left; 00565 rc.top += DcRect.top; 00566 rc.bottom += DcRect.top; 00567 } 00568 /* If hdc is given and pRect is not the area of interest is the 00569 bounding rect of hdc */ 00570 else 00571 { 00572 rc = DcRect; 00573 } 00574 } 00575 00576 if (hdc == NULL && pUnsafeRect == NULL) 00577 pRect = NULL; 00578 else 00579 pRect = &rc; 00580 00581 UserEnterShared(); 00582 00583 /* Find intersecting monitors */ 00584 cMonitors = IntGetMonitorsFromRect(pRect, NULL, NULL, 0, MONITOR_DEFAULTTONULL); 00585 if (cMonitors == 0 || dwListSize == 0 || 00586 (phUnsafeMonitorList == NULL && prcUnsafeMonitorList == NULL)) 00587 { 00588 /* Simple case - just return monitors count */ 00589 TRACE("cMonitors = %d\n", cMonitors); 00590 iRet = cMonitors; 00591 goto cleanup; 00592 } 00593 00594 /* Allocate safe buffers */ 00595 if (phUnsafeMonitorList != NULL && dwListSize != 0) 00596 { 00597 phMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * dwListSize, USERTAG_MONITORRECTS); 00598 if (phMonitorList == NULL) 00599 { 00600 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 00601 goto cleanup; 00602 } 00603 } 00604 if (prcUnsafeMonitorList != NULL && dwListSize != 0) 00605 { 00606 prcMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (RECT) * dwListSize, USERTAG_MONITORRECTS); 00607 if (prcMonitorList == NULL) 00608 { 00609 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 00610 goto cleanup; 00611 } 00612 } 00613 00614 /* Get intersecting monitors */ 00615 cMonitors = IntGetMonitorsFromRect(pRect, phMonitorList, prcMonitorList, 00616 dwListSize, MONITOR_DEFAULTTONULL); 00617 00618 if (hdc != NULL && pRect != NULL && prcMonitorList != NULL) 00619 for (i = 0; i < cMonitors; i++) 00620 { 00621 prcMonitorList[i].left -= DcRect.left; 00622 prcMonitorList[i].right -= DcRect.left; 00623 prcMonitorList[i].top -= DcRect.top; 00624 prcMonitorList[i].bottom -= DcRect.top; 00625 } 00626 00627 /* Output result */ 00628 if (phUnsafeMonitorList != NULL && dwListSize != 0) 00629 { 00630 Status = MmCopyToCaller(phUnsafeMonitorList, phMonitorList, sizeof(HMONITOR) * dwListSize); 00631 if (!NT_SUCCESS(Status)) 00632 { 00633 SetLastNtError(Status); 00634 goto cleanup; 00635 } 00636 } 00637 if (prcUnsafeMonitorList != NULL && dwListSize != 0) 00638 { 00639 Status = MmCopyToCaller(prcUnsafeMonitorList, prcMonitorList, sizeof(RECT) * dwListSize); 00640 if (!NT_SUCCESS(Status)) 00641 { 00642 SetLastNtError(Status); 00643 goto cleanup; 00644 } 00645 } 00646 00647 /* Return monitors count on success */ 00648 iRet = cMonitors; 00649 00650 cleanup: 00651 if (phMonitorList) 00652 ExFreePoolWithTag(phMonitorList, USERTAG_MONITORRECTS); 00653 if (prcMonitorList) 00654 ExFreePoolWithTag(prcMonitorList, USERTAG_MONITORRECTS); 00655 00656 UserLeave(); 00657 return iRet; 00658 } 00659 00660 /* NtUserGetMonitorInfo 00661 * 00662 * Retrieves information about a given monitor 00663 * 00664 * Arguments 00665 * 00666 * hMonitor 00667 * Handle to a monitor for which to get information 00668 * 00669 * pMonitorInfoUnsafe 00670 * Pointer to a MONITORINFO struct which is filled with the information. 00671 * The cbSize member must be set to sizeof(MONITORINFO) or 00672 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts 00673 * from MONITORINFO will be filled. 00674 * 00675 * pDevice 00676 * Pointer to a UNICODE_STRING which will recieve the device's name. The 00677 * length should be CCHDEVICENAME 00678 * Can be NULL 00679 * 00680 * Return value 00681 * TRUE on success; FALSE on failure (calls SetLastNtError()) 00682 * 00683 */ 00684 BOOL 00685 APIENTRY 00686 NtUserGetMonitorInfo( 00687 IN HMONITOR hMonitor, 00688 OUT LPMONITORINFO pMonitorInfoUnsafe) 00689 { 00690 PMONITOR pMonitor; 00691 MONITORINFOEXW MonitorInfo; 00692 NTSTATUS Status; 00693 BOOL bRet = FALSE; 00694 PWCHAR pwstrDeviceName; 00695 00696 TRACE("Enter NtUserGetMonitorInfo\n"); 00697 UserEnterShared(); 00698 00699 /* Get monitor object */ 00700 pMonitor = UserGetMonitorObject(hMonitor); 00701 if (!pMonitor) 00702 { 00703 TRACE("Couldnt find monitor 0x%lx\n", hMonitor); 00704 goto cleanup; 00705 } 00706 00707 /* Check if pMonitorInfoUnsafe is valid */ 00708 if(pMonitorInfoUnsafe == NULL) 00709 { 00710 SetLastNtError(STATUS_INVALID_PARAMETER); 00711 goto cleanup; 00712 } 00713 00714 pwstrDeviceName = ((PPDEVOBJ)(pMonitor->hDev))->pGraphicsDevice->szWinDeviceName; 00715 00716 /* Get size of pMonitorInfoUnsafe */ 00717 Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfoUnsafe->cbSize, sizeof(MonitorInfo.cbSize)); 00718 if (!NT_SUCCESS(Status)) 00719 { 00720 SetLastNtError(Status); 00721 goto cleanup; 00722 } 00723 00724 /* Check if size of struct is valid */ 00725 if (MonitorInfo.cbSize != sizeof(MONITORINFO) && 00726 MonitorInfo.cbSize != sizeof(MONITORINFOEXW)) 00727 { 00728 SetLastNtError(STATUS_INVALID_PARAMETER); 00729 goto cleanup; 00730 } 00731 00732 /* Fill monitor info */ 00733 MonitorInfo.rcMonitor = pMonitor->rcMonitor; 00734 MonitorInfo.rcWork = pMonitor->rcWork; 00735 MonitorInfo.dwFlags = 0; 00736 if (pMonitor->IsPrimary) 00737 MonitorInfo.dwFlags |= MONITORINFOF_PRIMARY; 00738 00739 /* Fill device name */ 00740 if (MonitorInfo.cbSize == sizeof(MONITORINFOEXW)) 00741 { 00742 RtlStringCbCopyNExW(MonitorInfo.szDevice, 00743 sizeof(MonitorInfo.szDevice), 00744 pwstrDeviceName, 00745 (wcslen(pwstrDeviceName)+1) * sizeof(WCHAR), 00746 NULL, NULL, STRSAFE_FILL_BEHIND_NULL); 00747 } 00748 00749 /* Output data */ 00750 Status = MmCopyToCaller(pMonitorInfoUnsafe, &MonitorInfo, MonitorInfo.cbSize); 00751 if (!NT_SUCCESS(Status)) 00752 { 00753 TRACE("GetMonitorInfo: MmCopyToCaller failed\n"); 00754 SetLastNtError(Status); 00755 goto cleanup; 00756 } 00757 00758 TRACE("GetMonitorInfo: success\n"); 00759 bRet = TRUE; 00760 00761 cleanup: 00762 TRACE("Leave NtUserGetMonitorInfo, ret=%i\n", bRet); 00763 UserLeave(); 00764 return bRet; 00765 } 00766 00767 /* NtUserMonitorFromPoint 00768 * 00769 * Returns a handle to the monitor containing the given point. 00770 * 00771 * Arguments 00772 * 00773 * pt 00774 * Point for which to find monitor 00775 * 00776 * dwFlags 00777 * Specifies the behaviour if the point isn't on any of the monitors. 00778 * 00779 * Return value 00780 * If the point is found a handle to the monitor is returned; if not the 00781 * return value depends on dwFlags 00782 */ 00783 HMONITOR 00784 APIENTRY 00785 NtUserMonitorFromPoint( 00786 IN POINT pt, 00787 IN DWORD dwFlags) 00788 { 00789 INT cMonitors; 00790 RECTL rc; 00791 HMONITOR hMonitor = NULL; 00792 00793 /* Check if flags are valid */ 00794 if (dwFlags != MONITOR_DEFAULTTONULL && 00795 dwFlags != MONITOR_DEFAULTTOPRIMARY && 00796 dwFlags != MONITOR_DEFAULTTONEAREST) 00797 { 00798 EngSetLastError(ERROR_INVALID_FLAGS); 00799 return NULL; 00800 } 00801 00802 /* Fill rect (bottom-right exclusive) */ 00803 rc.left = pt.x; 00804 rc.right = pt.x + 1; 00805 rc.top = pt.y; 00806 rc.bottom = pt.y + 1; 00807 00808 UserEnterShared(); 00809 00810 /* Find intersecting monitor */ 00811 cMonitors = IntGetMonitorsFromRect(&rc, &hMonitor, NULL, 1, dwFlags); 00812 00813 UserLeave(); 00814 return hMonitor; 00815 } 00816 00817 /* NtUserMonitorFromRect 00818 * 00819 * Returns a handle to the monitor having the largest intersection with a 00820 * given rectangle 00821 * 00822 * Arguments 00823 * 00824 * pRectUnsafe 00825 * Pointer to a RECT for which to find monitor 00826 * 00827 * dwFlags 00828 * Specifies the behaviour if no monitor intersects the given rect 00829 * 00830 * Return value 00831 * If a monitor intersects the rect a handle to it is returned; if not the 00832 * return value depends on dwFlags 00833 */ 00834 HMONITOR 00835 APIENTRY 00836 NtUserMonitorFromRect( 00837 IN LPCRECTL pRectUnsafe, 00838 IN DWORD dwFlags) 00839 { 00840 ULONG cMonitors, LargestArea = 0, i; 00841 PRECTL prcMonitorList = NULL; 00842 HMONITOR *phMonitorList = NULL; 00843 HMONITOR hMonitor = NULL; 00844 RECTL Rect; 00845 NTSTATUS Status; 00846 00847 /* Check if flags are valid */ 00848 if (dwFlags != MONITOR_DEFAULTTONULL && 00849 dwFlags != MONITOR_DEFAULTTOPRIMARY && 00850 dwFlags != MONITOR_DEFAULTTONEAREST) 00851 { 00852 EngSetLastError(ERROR_INVALID_FLAGS); 00853 return NULL; 00854 } 00855 00856 /* Copy rectangle to safe buffer */ 00857 Status = MmCopyFromCaller(&Rect, pRectUnsafe, sizeof (RECT)); 00858 if (!NT_SUCCESS(Status)) 00859 { 00860 SetLastNtError(Status); 00861 return NULL; 00862 } 00863 00864 UserEnterShared(); 00865 00866 /* Find intersecting monitors */ 00867 cMonitors = IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags); 00868 if (cMonitors <= 1) 00869 { 00870 /* No or one monitor found. Just return handle. */ 00871 goto cleanup; 00872 } 00873 00874 /* There is more than one monitor. Find monitor with largest intersection. 00875 Temporary reset hMonitor */ 00876 hMonitor = NULL; 00877 00878 /* Allocate helper buffers */ 00879 phMonitorList = ExAllocatePoolWithTag(PagedPool, 00880 sizeof(HMONITOR) * cMonitors, 00881 USERTAG_MONITORRECTS); 00882 if (phMonitorList == NULL) 00883 { 00884 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 00885 goto cleanup; 00886 } 00887 00888 prcMonitorList = ExAllocatePoolWithTag(PagedPool, 00889 sizeof(RECT) * cMonitors, 00890 USERTAG_MONITORRECTS); 00891 if (prcMonitorList == NULL) 00892 { 00893 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); 00894 goto cleanup; 00895 } 00896 00897 /* Get intersecting monitors again but now with rectangle list */ 00898 cMonitors = IntGetMonitorsFromRect(&Rect, phMonitorList, prcMonitorList, 00899 cMonitors, 0); 00900 00901 /* Find largest intersection */ 00902 for (i = 0; i < cMonitors; i++) 00903 { 00904 ULONG Area = (prcMonitorList[i].right - prcMonitorList[i].left) * 00905 (prcMonitorList[i].bottom - prcMonitorList[i].top); 00906 if (Area >= LargestArea) 00907 { 00908 hMonitor = phMonitorList[i]; 00909 LargestArea = Area; 00910 } 00911 } 00912 00913 cleanup: 00914 if (phMonitorList) 00915 ExFreePoolWithTag(phMonitorList, USERTAG_MONITORRECTS); 00916 if (prcMonitorList) 00917 ExFreePoolWithTag(prcMonitorList, USERTAG_MONITORRECTS); 00918 UserLeave(); 00919 00920 return hMonitor; 00921 } 00922 00923 00924 HMONITOR 00925 APIENTRY 00926 NtUserMonitorFromWindow( 00927 IN HWND hWnd, 00928 IN DWORD dwFlags) 00929 { 00930 PWND pWnd; 00931 HMONITOR hMonitor = NULL; 00932 RECTL Rect = {0, 0, 0, 0}; 00933 00934 TRACE("Enter NtUserMonitorFromWindow\n"); 00935 00936 /* Check if flags are valid */ 00937 if (dwFlags != MONITOR_DEFAULTTONULL && 00938 dwFlags != MONITOR_DEFAULTTOPRIMARY && 00939 dwFlags != MONITOR_DEFAULTTONEAREST) 00940 { 00941 EngSetLastError(ERROR_INVALID_FLAGS); 00942 return NULL; 00943 } 00944 00945 UserEnterShared(); 00946 00947 /* If window is given, use it first */ 00948 if (hWnd) 00949 { 00950 /* Get window object */ 00951 pWnd = UserGetWindowObject(hWnd); 00952 if (!pWnd) 00953 goto cleanup; 00954 00955 /* Find only monitors which have intersection with given window */ 00956 Rect.left = Rect.right = pWnd->rcWindow.left; 00957 Rect.top = Rect.bottom = pWnd->rcWindow.bottom; 00958 } 00959 00960 /* Find monitors now */ 00961 IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags); 00962 00963 cleanup: 00964 TRACE("Leave NtUserMonitorFromWindow, ret=%p\n", hMonitor); 00965 UserLeave(); 00966 return hMonitor; 00967 } Generated on Sun May 27 2012 04:38:34 for ReactOS by
1.7.6.1
|