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