[AMSTREAM] Sync with Wine Staging 3.9. CORE-14656
[reactos.git] / dll / directx / ddraw / main.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: dll/directx/ddraw/main.c
5 * PURPOSE: DirectDraw Library
6 * PROGRAMMER: Magnus Olsen (greatlrd)
7 *
8 */
9
10
11 #include "rosdraw.h"
12 HMODULE hDllModule = 0;
13
14 CRITICAL_SECTION ddcs;
15
16 // This function is exported by the dll
17
18 typedef struct
19 {
20 LPVOID lpCallback;
21 LPVOID lpContext;
22 } DirectDrawEnumerateProcData;
23
24 BOOL
25 CALLBACK
26 TranslateCallbackA(GUID *lpGUID,
27 LPSTR lpDriverDescription,
28 LPSTR lpDriverName,
29 LPVOID lpContext,
30 HMONITOR hm)
31 {
32 DirectDrawEnumerateProcData *pEPD = (DirectDrawEnumerateProcData*)lpContext;
33 return ((LPDDENUMCALLBACKA) pEPD->lpCallback)(lpGUID, lpDriverDescription, lpDriverName, pEPD->lpContext);
34 }
35
36 /*++
37 * @name DirectDrawCreateClipper
38 *
39 * The DirectDrawCreateClipper routine <FILLMEIN>.
40 *
41 * @param dwFlags
42 * <FILLMEIN>.
43 *
44 * @param lplpDDClipper
45 * <FILLMEIN>.
46 *
47 * @param pUnkOuter
48 * <FILLMEIN>.
49 *
50 * @return <FILLMEIN>.
51 *
52 * @remarks None.
53 *
54 *--*/
55 HRESULT WINAPI DirectDrawCreateClipper (DWORD dwFlags,
56 LPDIRECTDRAWCLIPPER* lplpDDClipper, LPUNKNOWN pUnkOuter)
57 {
58 DX_WINDBG_trace();
59
60 return Main_DirectDraw_CreateClipper(NULL, dwFlags, lplpDDClipper, pUnkOuter);
61 }
62
63 /*++
64 * @name DirectDrawCreate
65 *
66 * The DirectDrawCreate routine <FILLMEIN>.
67 *
68 * @param lpGUID
69 * <FILLMEIN>.
70 *
71 * @param lplpDD
72 * <FILLMEIN>.
73 *
74 * @param pUnkOuter
75 * Always set to NULL otherwise DirectDrawCreate will fail and return
76 * error code CLASS_E_NOAGGREGATION
77 *
78 * @return <FILLMEIN>.
79 *
80 * @remarks None.
81 *
82 *--*/
83
84 HRESULT
85 WINAPI
86 DirectDrawCreate (LPGUID lpGUID,
87 LPDIRECTDRAW* lplpDD,
88 LPUNKNOWN pUnkOuter)
89 {
90 HRESULT retVal = DDERR_GENERIC;
91 /*
92 remove this when UML diagram is in place
93 this api is finished and is working as it should
94 */
95
96 DX_WINDBG_trace();
97 _SEH2_TRY
98 {
99 /* check if pUnkOuter is null or not */
100 if (pUnkOuter)
101 {
102 retVal = CLASS_E_NOAGGREGATION;
103 }
104 else
105 {
106 retVal = Create_DirectDraw (lpGUID, (LPDIRECTDRAW*)lplpDD, &IID_IDirectDraw, FALSE);
107 }
108 }
109 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
110 {
111 }
112 _SEH2_END;
113
114 return retVal;
115 }
116
117 /*++
118 * @name DirectDrawCreateEx
119 *
120 * The DirectDrawCreateEx routine <FILLMEIN>.
121 *
122 * @param lpGUID
123 * <FILLMEIN>.
124 *
125 * @param lplpDD
126 * <FILLMEIN>.
127 *
128 * @param pUnkOuter
129 * Always set to NULL otherwise DirectDrawCreateEx will fail and return
130 * error code CLASS_E_NOAGGREGATION
131 *
132 * @return <FILLMEIN>.
133 *
134 * @remarks None.
135 *
136 *--*/
137 HRESULT
138 WINAPI
139 DirectDrawCreateEx(LPGUID lpGUID,
140 LPVOID* lplpDD,
141 REFIID id,
142 LPUNKNOWN pUnkOuter)
143 {
144 HRESULT retVal = DDERR_GENERIC;
145 /*
146 remove this when UML diagram is in place
147 this api is finished and is working as it should
148 */
149 DX_WINDBG_trace();
150
151 _SEH2_TRY
152 {
153 /* check see if pUnkOuter is null or not */
154 if (pUnkOuter)
155 {
156 /* we are using same error code as MS*/
157 retVal = CLASS_E_NOAGGREGATION;
158 }/* Is it a DirectDraw 7 Request or not */
159 else if (!IsEqualGUID(id, &IID_IDirectDraw7))
160 {
161 retVal = DDERR_INVALIDPARAMS;
162 }
163 else
164 {
165 retVal = Create_DirectDraw (lpGUID, (LPDIRECTDRAW*)lplpDD, id, FALSE);
166 }
167
168 /* Create our DirectDraw interface */
169 }
170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
171 {
172 }
173 _SEH2_END;
174
175 return retVal;
176 }
177
178 HRESULT
179 WINAPI
180 DirectDrawEnumerateA( LPDDENUMCALLBACKA lpCallback,
181 LPVOID lpContext)
182 {
183 HRESULT retValue;
184 DirectDrawEnumerateProcData epd;
185
186 DX_WINDBG_trace();
187
188 epd.lpCallback = (LPVOID) lpCallback;
189 epd.lpContext = lpContext;
190
191 if (!IsBadCodePtr((LPVOID)lpCallback))
192 {
193 return DirectDrawEnumerateExA((LPDDENUMCALLBACKEXA)TranslateCallbackA, &epd, DDENUM_NONDISPLAYDEVICES);
194 }
195 else
196 {
197 retValue = DDERR_INVALIDPARAMS;
198 }
199 return retValue;
200 }
201
202 /*
203 * UNIMPLEMENT
204 */
205
206 HRESULT
207 WINAPI
208 DirectDrawEnumerateExA(LPDDENUMCALLBACKEXA lpCallback,
209 LPVOID lpContext,
210 DWORD dwFlags)
211 {
212 HKEY hKey;
213 DWORD cbData = 0;
214 DWORD Value = 0;
215 LONG rc;
216 BOOL EnumerateAttachedSecondaries = FALSE;
217 DWORD privateDWFlags = 0;
218 CHAR strMsg[RC_STRING_MAX_SIZE];
219 HRESULT retVal = DDERR_INVALIDPARAMS;
220
221 DX_WINDBG_trace();
222
223 if ((IsBadCodePtr((LPVOID)lpCallback) == 0) &&
224 ((dwFlags & ~(DDENUM_NONDISPLAYDEVICES |
225 DDENUM_DETACHEDSECONDARYDEVICES |
226 DDENUM_ATTACHEDSECONDARYDEVICES)) == 0))
227 {
228 LoadStringA(hDllModule, STR_PRIMARY_DISPLAY, (LPSTR)&strMsg, RC_STRING_MAX_SIZE);
229
230 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, REGSTR_PATH_DDHW, &hKey);
231 if (rc == ERROR_SUCCESS)
232 {
233 /* Enumerate Attached Secondaries */
234 cbData = sizeof(DWORD);
235 rc = RegQueryValueExA(hKey, "EnumerateAttachedSecondaries", NULL, NULL, (LPBYTE)&Value, &cbData);
236 if (rc == ERROR_SUCCESS)
237 {
238 if (Value != 0)
239 {
240 EnumerateAttachedSecondaries = TRUE;
241 privateDWFlags = DDENUM_ATTACHEDSECONDARYDEVICES;
242 }
243 }
244 RegCloseKey(hKey);
245 }
246
247 /* Call the user supplied callback function */
248 rc = lpCallback(NULL, strMsg, "display", lpContext, NULL);
249
250 /* If the callback function returns DDENUMRET_CANCEL, we will stop enumerating devices */
251 if(rc == DDENUMRET_CANCEL)
252 {
253 retVal = DD_OK;
254 }
255 else
256 {
257 // not finished
258 retVal = DDERR_UNSUPPORTED;
259 }
260 }
261
262 return retVal;
263 }
264
265 HRESULT
266 WINAPI
267 DirectDrawEnumerateW(LPDDENUMCALLBACKW lpCallback,
268 LPVOID lpContext)
269 {
270 DX_WINDBG_trace();
271
272 return DDERR_UNSUPPORTED;
273 }
274
275 HRESULT
276 WINAPI
277 DirectDrawEnumerateExW(LPDDENUMCALLBACKEXW lpCallback,
278 LPVOID lpContext,
279 DWORD dwFlags)
280 {
281 DX_WINDBG_trace();
282
283 return DDERR_UNSUPPORTED;
284 }
285
286
287
288
289 /*
290 See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
291 Display_d/hh/Display_d/d3d_21ac30ea-9803-401e-b541-6b08af79653d.xml.asp
292
293 for more info about this command see msdn documentation
294
295 The buffer start with D3DHAL_DP2COMMAND struct afer that follows either one struct or
296 no struct at at all
297 example for command D3DDP2OP_VIEWPORTINFO
298
299 then lpCmd will look like this
300 ----------------------------------------
301 | struct | Pos |
302 ----------------------------------------
303 | D3DHAL_DP2COMMAND | 0x00 - 0x03 |
304 ---------------------------------------
305 | D3DHAL_DP2VIEWPORTINFO | 0x04 - xxxx |
306 ---------------------------------------
307
308 to calculate the end of the lpCmd buffer in this example
309 D3DHAL_DP2COMMAND->wStateCount * sizeof(D3DHAL_DP2VIEWPORTINFO);
310 now you got number of bytes but we need to add the size of D3DHAL_DP2COMMAND
311 to get this right. the end should be
312 sizeof(D3DHAL_DP2COMMAND) + ( D3DHAL_DP2COMMAND->wStateCount * sizeof(D3DHAL_DP2VIEWPORTINFO));
313 to get the xxxx end positions.
314 */
315
316 /*++
317 * @name D3DParseUnknownCommand
318 *
319 * The D3DParseUnknownCommand routine <FILLMEIN>.
320 *
321 * @param lpCmd
322 * Is a typecast to LPD3DHAL_DP2COMMAND struct
323 * typedef struct _D3DHAL_DP2COMMAND
324 * {
325 * BYTE bCommand;
326 * BYTE bReserved;
327 * union
328 * {
329 * WORD wPrimitiveCount;
330 * WORD wStateCount;
331 * };
332 * } D3DHAL_DP2COMMAND, *LPD3DHAL_DP2COMMAND;
333 *
334 * lpCmd->bCommand
335 * only accept D3DDP2OP_VIEWPORTINFO, and undocumented command 0x0D
336 * anything else will result in an error
337 *
338 Command 0x0D
339 * dp2command->bReserved
340 * is the size of the struct we got in wStateCount or how many wStateCount we got
341 * do not known more about it, no info in msdn about it either.
342 *
343 * Command D3DDP2OP_VIEWPORTINFO
344 * <FILLMEIN>.
345 *
346 * @param lpRetCmd
347 * <FILLMEIN>.
348 *
349 * @return <FILLMEIN>.
350 *
351 * @remarks
352
353 *
354 *--*/
355
356 HRESULT WINAPI
357 D3DParseUnknownCommand( LPVOID lpCmd,
358 LPVOID *lpRetCmd)
359 {
360 DWORD retCode = DD_OK;
361 LPD3DHAL_DP2COMMAND dp2command = lpCmd;
362
363 DX_WINDBG_trace();
364
365 /* prevent it crash if null pointer are being sent */
366 if ( (lpCmd == NULL) || (lpRetCmd == NULL) )
367 {
368 return E_FAIL;
369 }
370
371 *lpRetCmd = lpCmd;
372
373 switch (dp2command->bCommand)
374 {
375 /* check for valid command, only 3 commands are valid */
376 case D3DDP2OP_VIEWPORTINFO:
377 *(PBYTE)lpRetCmd += ((dp2command->wStateCount * sizeof(D3DHAL_DP2VIEWPORTINFO)) + sizeof(D3DHAL_DP2COMMAND));
378 break;
379
380 case D3DDP2OP_WINFO:
381 *(PBYTE)lpRetCmd += (dp2command->wStateCount * sizeof(D3DHAL_DP2WINFO)) + sizeof(D3DHAL_DP2COMMAND);
382 break;
383
384 case 0x0d: /* Undocumented in MSDN */
385 *(PBYTE)lpRetCmd += ((dp2command->wStateCount * dp2command->bReserved) + sizeof(D3DHAL_DP2COMMAND));
386 break;
387
388
389 /* set the error code */
390 default:
391
392 if ( (dp2command->bCommand <= D3DDP2OP_INDEXEDTRIANGLELIST) || // dp2command->bCommand <= with 0 to 3
393 (dp2command->bCommand == D3DDP2OP_RENDERSTATE) || // dp2command->bCommand == with 8
394 (dp2command->bCommand >= D3DDP2OP_LINELIST) ) // dp2command->bCommand >= with 15 to 255
395 {
396 /* set error code for command 0 to 3, 8 and 15 to 255 */
397 retCode = DDERR_INVALIDPARAMS;
398 }
399 else
400 { /* set error code for 4 - 7, 9 - 12, 14 */
401 retCode = D3DERR_COMMAND_UNPARSED;
402 }
403
404 }
405
406 return retCode;
407 }
408
409
410 VOID
411 WINAPI
412 AcquireDDThreadLock()
413 {
414 DX_WINDBG_trace();
415
416 EnterCriticalSection(&ddcs);
417 }
418
419 VOID
420 WINAPI
421 ReleaseDDThreadLock()
422 {
423 DX_WINDBG_trace();
424
425 LeaveCriticalSection(&ddcs);
426 }
427
428
429 BOOL APIENTRY
430 DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
431 {
432
433 hDllModule = hModule;
434
435 DX_WINDBG_trace();
436
437
438 switch(ul_reason_for_call)
439 {
440 case DLL_PROCESS_DETACH:
441 DeleteCriticalSection( &ddcs );
442 break;
443
444 case DLL_PROCESS_ATTACH:
445 DisableThreadLibraryCalls( hModule );
446 InitializeCriticalSection( &ddcs );
447 EnterCriticalSection( &ddcs );
448 LeaveCriticalSection( &ddcs );
449 break;
450
451 default:
452 break;
453 }
454
455 return TRUE;
456 }