VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp@ 27948

Last change on this file since 27948 was 27889, checked in by vboxsync, 15 years ago

crOpenGL: more code for multiscreen support

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 19.7 KB
Line 
1/* $Id: crservice.cpp 27889 2010-03-31 12:57:09Z vboxsync $ */
2
3/** @file
4 * VBox crOpenGL: Host service entry points.
5 */
6
7/*
8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#define __STDC_CONSTANT_MACROS /* needed for a definition in iprt/string.h */
24
25#ifdef RT_OS_WINDOWS
26#include <iprt/alloc.h>
27#include <iprt/string.h>
28#include <iprt/assert.h>
29#include <iprt/stream.h>
30#include <VBox/ssm.h>
31#include <VBox/hgcmsvc.h>
32#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
33#include "cr_server.h"
34#define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
35#include <VBox/log.h>
36
37#include <VBox/com/com.h>
38#include <VBox/com/string.h>
39#include <VBox/com/array.h>
40#include <VBox/com/Guid.h>
41#include <VBox/com/ErrorInfo.h>
42#include <VBox/com/EventQueue.h>
43#include <VBox/com/VirtualBox.h>
44#include <VBox/com/assert.h>
45
46#else
47#include <VBox/com/VirtualBox.h>
48#include <iprt/assert.h>
49#include <VBox/ssm.h>
50#include <VBox/hgcmsvc.h>
51#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
52
53#include "cr_server.h"
54#define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
55#include <VBox/log.h>
56#include <VBox/com/ErrorInfo.h>
57#endif /* RT_OS_WINDOWS */
58
59#include <VBox/com/errorprint.h>
60
61PVBOXHGCMSVCHELPERS g_pHelpers;
62static IConsole* g_pConsole = NULL;
63static PVM g_pVM = NULL;
64
65#ifndef RT_OS_WINDOWS
66#define DWORD int
67#define WINAPI
68#endif
69
70static const char* gszVBoxOGLSSMMagic = "***OpenGL state data***";
71#define SHCROGL_SSM_VERSION 17
72
73static DECLCALLBACK(int) svcUnload (void *)
74{
75 int rc = VINF_SUCCESS;
76
77 Log(("SHARED_CROPENGL svcUnload\n"));
78
79 crVBoxServerTearDown();
80
81 return rc;
82}
83
84static DECLCALLBACK(int) svcConnect (void *, uint32_t u32ClientID, void *pvClient)
85{
86 int rc = VINF_SUCCESS;
87
88 NOREF(pvClient);
89
90 Log(("SHARED_CROPENGL svcConnect: u32ClientID = %d\n", u32ClientID));
91
92 rc = crVBoxServerAddClient(u32ClientID);
93
94 return rc;
95}
96
97static DECLCALLBACK(int) svcDisconnect (void *, uint32_t u32ClientID, void *pvClient)
98{
99 int rc = VINF_SUCCESS;
100
101 NOREF(pvClient);
102
103 Log(("SHARED_CROPENGL svcDisconnect: u32ClientID = %d\n", u32ClientID));
104
105 crVBoxServerRemoveClient(u32ClientID);
106
107 return rc;
108}
109
110static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
111{
112 int rc = VINF_SUCCESS;
113
114 NOREF(pvClient);
115
116 Log(("SHARED_CROPENGL svcSaveState: u32ClientID = %d\n", u32ClientID));
117
118 /* Start*/
119 rc = SSMR3PutStrZ(pSSM, gszVBoxOGLSSMMagic);
120 AssertRCReturn(rc, rc);
121
122 /* Version */
123 rc = SSMR3PutU32(pSSM, (uint32_t) SHCROGL_SSM_VERSION);
124 AssertRCReturn(rc, rc);
125
126 /* The state itself */
127 rc = crVBoxServerSaveState(pSSM);
128 AssertRCReturn(rc, rc);
129
130 /* End */
131 rc = SSMR3PutStrZ(pSSM, gszVBoxOGLSSMMagic);
132 AssertRCReturn(rc, rc);
133
134 return VINF_SUCCESS;
135}
136
137static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
138{
139 int rc = VINF_SUCCESS;
140
141 NOREF(pvClient);
142
143 Log(("SHARED_CROPENGL svcLoadState: u32ClientID = %d\n", u32ClientID));
144
145 char psz[2000];
146 uint32_t ui32;
147
148 /* Start of data */
149 rc = SSMR3GetStrZEx(pSSM, psz, 2000, NULL);
150 AssertRCReturn(rc, rc);
151 if (strcmp(gszVBoxOGLSSMMagic, psz))
152 return VERR_SSM_UNEXPECTED_DATA;
153
154 /* Version */
155 rc = SSMR3GetU32(pSSM, &ui32);
156 AssertRCReturn(rc, rc);
157 if ((SHCROGL_SSM_VERSION != ui32)
158 && ((SHCROGL_SSM_VERSION!=4) || (3!=ui32)))
159 {
160 /*@todo: add some warning here*/
161 /*@todo: in many cases saved states would be made without any opengl guest app running.
162 * that means we could safely restore the default context.
163 */
164 rc = SSMR3SkipToEndOfUnit(pSSM);
165 return rc;
166 }
167
168 /* The state itself */
169 rc = crVBoxServerLoadState(pSSM, ui32);
170 AssertRCReturn(rc, rc);
171
172 /* End of data */
173 rc = SSMR3GetStrZEx(pSSM, psz, 2000, NULL);
174 AssertRCReturn(rc, rc);
175 if (strcmp(gszVBoxOGLSSMMagic, psz))
176 return VERR_SSM_UNEXPECTED_DATA;
177
178 return VINF_SUCCESS;
179}
180
181static void svcClientVersionUnsupported(uint32_t minor, uint32_t major)
182{
183 LogRel(("SHARED_CROPENGL: unsupported client version %d.%d\n", minor, major));
184
185 /*MS's opengl32 tryes to load our ICD around 30 times on failure...this is to prevent unnecessary spam*/
186 static int shown = 0;
187
188 if (g_pVM && !shown)
189 {
190 VMSetRuntimeError(g_pVM, VMSETRTERR_FLAGS_NO_WAIT, "3DSupportIncompatibleAdditions",
191 "An attempt by the virtual machine to use hardware 3D acceleration failed. "
192 "The version of the Guest Additions installed in the virtual machine does not match the "
193 "version of VirtualBox on the host. Please install appropriate Guest Additions to fix this issue");
194 shown = 1;
195 }
196}
197
198static DECLCALLBACK(void) svcPresentFBO(void *data, int32_t screenId, int32_t x, int32_t y, uint32_t w, uint32_t h)
199{
200#if 0
201 ComPtr<IDisplay> pDisplay;
202 BYTE *data;
203 int i,j;
204 CHECK_ERROR(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
205
206 data = (BYTE*) RTMemTmpAllocZ(100*100*4);
207
208 for (i=0; i<100; i+=2)
209 {
210 for (j=0; j<100; ++j)
211 {
212 *(data+i*100*4+j*4+0) = 0xFF;
213 *(data+i*100*4+j*4+1) = 0xFF;
214 *(data+i*100*4+j*4+2) = 0xFF;
215 *(data+i*100*4+j*4+3) = 0xFF;
216 }
217 }
218
219 CHECK_ERROR(pDisplay, DrawToScreen(data, 0, 0, 100, 100));
220
221 RTMemTmpFree(data);
222#endif
223 HRESULT rc;
224 ComPtr<IDisplay> pDisplay;
225
226 CHECK_ERROR(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
227 CHECK_ERROR(pDisplay, DrawToScreen((BYTE*)data, x, y, w, h));
228}
229
230static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
231{
232 int rc = VINF_SUCCESS;
233
234 NOREF(pvClient);
235
236 Log(("SHARED_CROPENGL svcCall: u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n", u32ClientID, u32Function, cParms, paParms));
237
238#ifdef DEBUG
239 uint32_t i;
240
241 for (i = 0; i < cParms; i++)
242 {
243 /** @todo parameters other than 32 bit */
244 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
245 }
246#endif
247
248 switch (u32Function)
249 {
250 case SHCRGL_GUEST_FN_WRITE:
251 {
252 Log(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
253
254 /* Verify parameter count and types. */
255 if (cParms != SHCRGL_CPARMS_WRITE)
256 {
257 rc = VERR_INVALID_PARAMETER;
258 }
259 else
260 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
261 )
262 {
263 rc = VERR_INVALID_PARAMETER;
264 }
265 else
266 {
267 /* Fetch parameters. */
268 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
269 uint32_t cbBuffer = paParms[0].u.pointer.size;
270
271 /* Execute the function. */
272 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
273 if (!RT_SUCCESS(rc))
274 {
275 Assert(VERR_NOT_SUPPORTED==rc);
276 svcClientVersionUnsupported(0, 0);
277 }
278
279 }
280 break;
281 }
282
283 case SHCRGL_GUEST_FN_READ:
284 {
285 Log(("svcCall: SHCRGL_GUEST_FN_READ\n"));
286
287 /* Verify parameter count and types. */
288 if (cParms != SHCRGL_CPARMS_READ)
289 {
290 rc = VERR_INVALID_PARAMETER;
291 }
292 else
293 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
294 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cbBuffer */
295 )
296 {
297 rc = VERR_INVALID_PARAMETER;
298 }
299
300 /* Fetch parameters. */
301 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
302 uint32_t cbBuffer = paParms[0].u.pointer.size;
303
304 /* Execute the function. */
305 rc = crVBoxServerClientRead(u32ClientID, pBuffer, &cbBuffer);
306
307 if (RT_SUCCESS(rc))
308 {
309 /* Update parameters.*/
310 paParms[0].u.pointer.size = cbBuffer; //@todo guest doesn't see this change somehow?
311 } else if (VERR_NOT_SUPPORTED==rc)
312 {
313 svcClientVersionUnsupported(0, 0);
314 }
315
316 /* Return the required buffer size always */
317 paParms[1].u.uint32 = cbBuffer;
318
319 break;
320 }
321
322 case SHCRGL_GUEST_FN_WRITE_READ:
323 {
324 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
325
326 /* Verify parameter count and types. */
327 if (cParms != SHCRGL_CPARMS_WRITE_READ)
328 {
329 rc = VERR_INVALID_PARAMETER;
330 }
331 else
332 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
333 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pWriteback */
334 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* cbWriteback */
335 )
336 {
337 rc = VERR_INVALID_PARAMETER;
338 }
339 else
340 {
341 /* Fetch parameters. */
342 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
343 uint32_t cbBuffer = paParms[0].u.pointer.size;
344
345 uint8_t *pWriteback = (uint8_t *)paParms[1].u.pointer.addr;
346 uint32_t cbWriteback = paParms[1].u.pointer.size;
347
348 /* Execute the function. */
349 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
350 if (!RT_SUCCESS(rc))
351 {
352 Assert(VERR_NOT_SUPPORTED==rc);
353 svcClientVersionUnsupported(0, 0);
354 }
355
356 rc = crVBoxServerClientRead(u32ClientID, pWriteback, &cbWriteback);
357
358 if (RT_SUCCESS(rc))
359 {
360 /* Update parameters.*/
361 paParms[1].u.pointer.size = cbWriteback;
362 }
363 /* Return the required buffer size always */
364 paParms[2].u.uint32 = cbWriteback;
365 }
366
367 break;
368 }
369
370 case SHCRGL_GUEST_FN_SET_VERSION:
371 {
372 Log(("svcCall: SHCRGL_GUEST_FN_SET_VERSION\n"));
373
374 /* Verify parameter count and types. */
375 if (cParms != SHCRGL_CPARMS_SET_VERSION)
376 {
377 rc = VERR_INVALID_PARAMETER;
378 }
379 else
380 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* vMajor */
381 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* vMinor */
382 )
383 {
384 rc = VERR_INVALID_PARAMETER;
385 }
386 else
387 {
388 /* Fetch parameters. */
389 uint32_t vMajor = paParms[0].u.uint32;
390 uint32_t vMinor = paParms[1].u.uint32;
391
392 /* Execute the function. */
393 rc = crVBoxServerClientSetVersion(u32ClientID, vMajor, vMinor);
394
395 if (!RT_SUCCESS(rc))
396 {
397 svcClientVersionUnsupported(vMajor, vMinor);
398 }
399 }
400
401 break;
402 }
403
404 default:
405 {
406 rc = VERR_NOT_IMPLEMENTED;
407 }
408 }
409
410
411 LogFlow(("svcCall: rc = %Rrc\n", rc));
412
413 g_pHelpers->pfnCallComplete (callHandle, rc);
414}
415
416/*
417 * We differentiate between a function handler for the guest and one for the host.
418 */
419static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
420{
421 int rc = VINF_SUCCESS;
422
423 Log(("SHARED_CROPENGL svcHostCall: fn = %d, cParms = %d, pparms = %d\n", u32Function, cParms, paParms));
424
425#ifdef DEBUG
426 uint32_t i;
427
428 for (i = 0; i < cParms; i++)
429 {
430 /** @todo parameters other than 32 bit */
431 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
432 }
433#endif
434
435 switch (u32Function)
436 {
437 case SHCRGL_HOST_FN_SET_CONSOLE:
438 {
439 Log(("svcCall: SHCRGL_HOST_FN_SET_DISPLAY\n"));
440
441 /* Verify parameter count and types. */
442 if (cParms != SHCRGL_CPARMS_SET_CONSOLE)
443 {
444 rc = VERR_INVALID_PARAMETER;
445 }
446 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
447 {
448 rc = VERR_INVALID_PARAMETER;
449 }
450 else
451 {
452 /* Fetch parameters. */
453 IConsole* pConsole = (IConsole*)paParms[0].u.pointer.addr;
454 uint32_t cbData = paParms[0].u.pointer.size;
455
456 /* Verify parameters values. */
457 if (cbData != sizeof (IConsole*))
458 {
459 rc = VERR_INVALID_PARAMETER;
460 }
461 else if (!pConsole)
462 {
463 rc = VERR_INVALID_PARAMETER;
464 }
465 else /* Execute the function. */
466 {
467 ComPtr<IMachine> pMachine;
468 ComPtr<IDisplay> pDisplay;
469 ComPtr<IFramebuffer> pFramebuffer;
470 LONG xo, yo;
471 ULONG64 winId = 0;
472 ULONG monitorCount, i, w, h;
473
474 CHECK_ERROR_BREAK(pConsole, COMGETTER(Machine)(pMachine.asOutParam()));
475 CHECK_ERROR_BREAK(pMachine, COMGETTER(MonitorCount)(&monitorCount));
476 CHECK_ERROR_BREAK(pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
477
478 rc = crVBoxServerSetScreenCount(monitorCount);
479 AssertRCReturn(rc, rc);
480
481 for (i=0; i<monitorCount; ++i)
482 {
483 CHECK_ERROR_RET(pDisplay, GetFramebuffer(i, pFramebuffer.asOutParam(), &xo, &yo), rc);
484
485 if (!pDisplay)
486 {
487 rc = crVBoxServerUnmapScreen(i);
488 AssertRCReturn(rc, rc);
489 }
490 else
491 {
492 CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
493 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
494 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
495
496 rc = crVBoxServerMapScreen(i, xo, yo, w, h, winId);
497 AssertRCReturn(rc, rc);
498 }
499 }
500
501 g_pConsole = pConsole;
502 rc = VINF_SUCCESS;
503 }
504 }
505 break;
506 }
507 case SHCRGL_HOST_FN_SET_VM:
508 {
509 Log(("svcCall: SHCRGL_HOST_FN_SET_VM\n"));
510
511 /* Verify parameter count and types. */
512 if (cParms != SHCRGL_CPARMS_SET_VM)
513 {
514 rc = VERR_INVALID_PARAMETER;
515 }
516 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
517 {
518 rc = VERR_INVALID_PARAMETER;
519 }
520 else
521 {
522 /* Fetch parameters. */
523 PVM pVM = (PVM)paParms[0].u.pointer.addr;
524 uint32_t cbData = paParms[0].u.pointer.size;
525
526 /* Verify parameters values. */
527 if (cbData != sizeof (PVM))
528 {
529 rc = VERR_INVALID_PARAMETER;
530 }
531 else
532 {
533 /* Execute the function. */
534 g_pVM = pVM;
535 rc = VINF_SUCCESS;
536 }
537 }
538 break;
539 }
540 case SHCRGL_HOST_FN_SET_VISIBLE_REGION:
541 {
542 Log(("svcCall: SHCRGL_HOST_FN_SET_VISIBLE_REGION\n"));
543
544 if (cParms != SHCRGL_CPARMS_SET_VISIBLE_REGION)
545 {
546 rc = VERR_INVALID_PARAMETER;
547 break;
548 }
549
550 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pRects */
551 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cRects */
552 )
553 {
554 rc = VERR_INVALID_PARAMETER;
555 break;
556 }
557
558 Assert(sizeof(RTRECT)==4*sizeof(GLint));
559
560 rc = crVBoxServerSetRootVisibleRegion(paParms[1].u.uint32, (GLint*)paParms[0].u.pointer.addr);
561 break;
562 }
563 case SHCRGL_HOST_FN_SCREEN_CHANGED:
564 {
565 Log(("svcCall: SHCRGL_HOST_FN_SCREEN_CHANGED\n"));
566
567 /* Verify parameter count and types. */
568 if (cParms != SHCRGL_CPARMS_SCREEN_CHANGED)
569 {
570 rc = VERR_INVALID_PARAMETER;
571 }
572 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
573 {
574 rc = VERR_INVALID_PARAMETER;
575 }
576 else
577 {
578 /* Fetch parameters. */
579 uint32_t screenId = paParms[0].u.uint32;
580
581 /* Execute the function. */
582 ComPtr<IDisplay> pDisplay;
583 ComPtr<IFramebuffer> pFramebuffer;
584 LONG xo, yo;
585 ULONG64 winId = 0;
586 ULONG w, h;
587
588 Assert(g_pConsole);
589 CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc);
590 CHECK_ERROR_RET(pDisplay, GetFramebuffer(screenId, pFramebuffer.asOutParam(), &xo, &yo), rc);
591
592 if (!pFramebuffer)
593 {
594 rc = crVBoxServerUnmapScreen(screenId);
595 AssertRCReturn(rc, rc);
596 }
597 else
598 {
599 CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
600 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
601 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
602
603 rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId);
604 AssertRCReturn(rc, rc);
605 }
606
607 rc = VINF_SUCCESS;
608 }
609 break;
610 }
611 default:
612 rc = VERR_NOT_IMPLEMENTED;
613 break;
614 }
615
616 LogFlow(("svcHostCall: rc = %Rrc\n", rc));
617 return rc;
618}
619
620extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
621{
622 int rc = VINF_SUCCESS;
623
624 Log(("SHARED_CROPENGL VBoxHGCMSvcLoad: ptable = %p\n", ptable));
625
626 if (!ptable)
627 {
628 rc = VERR_INVALID_PARAMETER;
629 }
630 else
631 {
632 Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
633
634 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
635 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
636 {
637 rc = VERR_INVALID_PARAMETER;
638 }
639 else
640 {
641 g_pHelpers = ptable->pHelpers;
642
643 ptable->cbClient = sizeof (void*);
644
645 ptable->pfnUnload = svcUnload;
646 ptable->pfnConnect = svcConnect;
647 ptable->pfnDisconnect = svcDisconnect;
648 ptable->pfnCall = svcCall;
649 ptable->pfnHostCall = svcHostCall;
650 ptable->pfnSaveState = svcSaveState;
651 ptable->pfnLoadState = svcLoadState;
652 ptable->pvService = NULL;
653
654 if (!crVBoxServerInit())
655 return VERR_NOT_SUPPORTED;
656
657 crVBoxServerSetPresentFBOCB(svcPresentFBO);
658 }
659 }
660
661 return rc;
662}
663
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette