Index: ddraw/glDirectDrawClipper.cpp |
— | — | @@ -123,6 +123,9 @@ |
124 | 124 |
|
125 | 125 | HRESULT WINAPI glDirectDrawClipper_GetClipList(glDirectDrawClipper *This, LPRECT lpRect, LPRGNDATA lpClipList, LPDWORD lpdwSize)
|
126 | 126 | {
|
| 127 | + int error;
|
| 128 | + POINT origin;
|
| 129 | + HDC hdc;
|
127 | 130 | HRGN rgnrect;
|
128 | 131 | HRGN rgncliplist;
|
129 | 132 | RGNDATA *rgn;
|
— | — | @@ -130,7 +133,86 @@ |
131 | 134 | TRACE_ENTER(4,14,This,26,lpRect,14,lpClipList,14,lpdwSize);
|
132 | 135 | if(!This) TRACE_RET(HRESULT,23,DDERR_INVALIDOBJECT);
|
133 | 136 | if (!lpdwSize) TRACE_RET(HRESULT, 23, DDERR_INVALIDPARAMS);
|
134 | | - if (!This->clipsize) TRACE_RET(HRESULT, 23, DDERR_NOCLIPLIST);
|
| 137 | + if (!This->clipsize)
|
| 138 | + {
|
| 139 | + if (!This->hWnd) TRACE_RET(HRESULT, 23, DDERR_NOCLIPLIST);
|
| 140 | + hdc = GetDC(This->hWnd);
|
| 141 | + if (!hdc) TRACE_RET(HRESULT, 23, DDERR_GENERIC);
|
| 142 | + rgncliplist = CreateRectRgn(0, 0, 0, 0);
|
| 143 | + if (!rgncliplist)
|
| 144 | + {
|
| 145 | + ReleaseDC(This->hWnd, hdc);
|
| 146 | + TRACE_RET(HRESULT, 23, DDERR_GENERIC);
|
| 147 | + }
|
| 148 | + error = GetRandomRgn(hdc, rgncliplist, SYSRGN);
|
| 149 | + if (error == -1)
|
| 150 | + {
|
| 151 | + DeleteObject(rgncliplist);
|
| 152 | + ReleaseDC(This->hWnd, hdc);
|
| 153 | + TRACE_RET(HRESULT, 23, DDERR_GENERIC);
|
| 154 | + }
|
| 155 | + if (GetVersion() & 0x80000000)
|
| 156 | + {
|
| 157 | + GetDCOrgEx(hdc, &origin);
|
| 158 | + OffsetRgn(rgncliplist, origin.x, origin.y);
|
| 159 | + }
|
| 160 | + ReleaseDC(This->hWnd, hdc);
|
| 161 | + if (lpRect)
|
| 162 | + {
|
| 163 | + rgnrect = CreateRectRgnIndirect(lpRect);
|
| 164 | + if (CombineRgn(rgncliplist, rgnrect, rgncliplist, RGN_AND) == ERROR)
|
| 165 | + {
|
| 166 | + DeleteObject(rgnrect);
|
| 167 | + DeleteObject(rgncliplist);
|
| 168 | + TRACE_RET(HRESULT, 23, DDERR_GENERIC);
|
| 169 | + }
|
| 170 | + DeleteObject(rgnrect);
|
| 171 | + }
|
| 172 | + rgnsize = GetRegionData(rgncliplist, 0, NULL);
|
| 173 | + rgn = (RGNDATA*)malloc(rgnsize);
|
| 174 | + if (!rgn)
|
| 175 | + {
|
| 176 | + DeleteObject(rgncliplist);
|
| 177 | + TRACE_RET(HRESULT, 23, DDERR_OUTOFMEMORY);
|
| 178 | + }
|
| 179 | + GetRegionData(rgncliplist, rgnsize, rgn);
|
| 180 | + if (!lpClipList)
|
| 181 | + {
|
| 182 | + *lpdwSize = sizeof(RGNDATAHEADER) + (rgn->rdh.nCount*sizeof(RECT));
|
| 183 | + free(rgn);
|
| 184 | + DeleteObject(rgncliplist);
|
| 185 | + TRACE_EXIT(23, DD_OK);
|
| 186 | + return DD_OK;
|
| 187 | + }
|
| 188 | + else
|
| 189 | + {
|
| 190 | + if (*lpdwSize < (sizeof(RGNDATAHEADER) + (rgn->rdh.nCount*sizeof(RECT))))
|
| 191 | + {
|
| 192 | + free(rgn);
|
| 193 | + DeleteObject(rgncliplist);
|
| 194 | + TRACE_RET(HRESULT, 23, DDERR_REGIONTOOSMALL);
|
| 195 | + }
|
| 196 | + *lpdwSize = sizeof(RGNDATAHEADER) + (rgn->rdh.nCount*sizeof(RECT));
|
| 197 | +#ifdef _MSC_VER
|
| 198 | + __try
|
| 199 | + {
|
| 200 | +#endif
|
| 201 | + memcpy(lpClipList, rgn, sizeof(RGNDATAHEADER) + (rgn->rdh.nCount*sizeof(RECT)));
|
| 202 | +#ifdef _MSC_VER
|
| 203 | + }
|
| 204 | + __except (GetExceptionCode() == STATUS_ACCESS_VIOLATION)
|
| 205 | + {
|
| 206 | + free(rgn);
|
| 207 | + DeleteObject(rgncliplist);
|
| 208 | + TRACE_RET(HRESULT, 23, DDERR_INVALIDCLIPLIST);
|
| 209 | + }
|
| 210 | +#endif
|
| 211 | + free(rgn);
|
| 212 | + DeleteObject(rgncliplist);
|
| 213 | + TRACE_EXIT(23, DD_OK);
|
| 214 | + return DD_OK;
|
| 215 | + }
|
| 216 | + }
|
135 | 217 | if (!lpClipList)
|
136 | 218 | {
|
137 | 219 | if (lpRect)
|