VirtualBox

source: vbox/trunk/src/VBox/Devices/Serial/DrvNamedPipe.cpp@ 1776

Last change on this file since 1776 was 1776, checked in by vboxsync, 18 years ago

Shutdown fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.8 KB
Line 
1/** @file
2 *
3 * VBox stream devices:
4 * Named pipe stream
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#define LOG_GROUP LOG_GROUP_DRV_NAMEDPIPE
28#include <VBox/pdm.h>
29#include <VBox/cfgm.h>
30#include <VBox/err.h>
31
32#include <VBox/log.h>
33#include <VBox/mm.h>
34#include <iprt/assert.h>
35#include <iprt/file.h>
36#include <iprt/stream.h>
37#include <iprt/alloc.h>
38#include <iprt/string.h>
39
40#include "Builtins.h"
41
42#ifdef __WIN__
43#include <windows.h>
44#else /* !__WIN__ */
45#include <errno.h>
46#include <unistd.h>
47#include <sys/types.h>
48#include <sys/socket.h>
49#include <sys/un.h>
50#endif /* !__WIN__ */
51
52/*******************************************************************************
53* Defined Constants And Macros *
54*******************************************************************************/
55
56/** Converts a pointer to DRVNAMEDPIPE::IMedia to a PDRVNAMEDPIPE. */
57#define PDMISTREAM_2_DRVNAMEDPIPE(pInterface) ( (PDRVNAMEDPIPE)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAMEDPIPE, IStream)) )
58
59/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
60#define PDMIBASE_2_DRVINS(pInterface) ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
61
62/*******************************************************************************
63* Structures and Typedefs *
64*******************************************************************************/
65/**
66 * Named pipe driver instance data.
67 */
68typedef struct DRVNAMEDPIPE
69{
70 /** The stream interface. */
71 PDMISTREAM IStream;
72 /** Pointer to the driver instance. */
73 PPDMDRVINS pDrvIns;
74 /** Pointer to the named pipe file name. (Freed by MM) */
75 char *pszLocation;
76 /** Flag whether VirtualBox represents the server or client side. */
77 bool fIsServer;
78#ifdef __WIN__
79 /* File handle of the named pipe. */
80 RTFILE NamedPipe;
81 /* Overlapped structure for writes. */
82 OVERLAPPED OverlappedWrite;
83 /* Overlapped structure for reads. */
84 OVERLAPPED OverlappedRead;
85#else /* !__WIN__ */
86 /** Socket handle of the local socket for server. */
87 RTSOCKET LocalSocketServer;
88 /** Socket handle of the local socket. */
89 RTSOCKET LocalSocket;
90#endif /* !__WIN__ */
91 /** Thread for listening for new connections. */
92 RTTHREAD ListenThread;
93 /** Flag to signal listening thread to shut down. */
94 bool fShutdown;
95} DRVNAMEDPIPE, *PDRVNAMEDPIPE;
96
97
98/*******************************************************************************
99* Internal Functions *
100*******************************************************************************/
101
102
103/** @copydoc PDMISTREAM::pfnRead */
104static DECLCALLBACK(int) drvNamedPipeRead(PPDMISTREAM pInterface, void *pvBuf, size_t *cbRead)
105{
106 int rc = VINF_SUCCESS;
107 PDRVNAMEDPIPE pData = PDMISTREAM_2_DRVNAMEDPIPE(pInterface);
108 LogFlow(("%s: pvBuf=%p cbRead=%#x (%s)\n", __FUNCTION__, pvBuf, cbRead, pData->pszLocation));
109
110 Assert(pvBuf);
111#ifdef __WIN__
112 if (pData->NamedPipe != NIL_RTFILE)
113 {
114 DWORD cbReallyRead;
115 pData->OverlappedRead.Offset = 0;
116 pData->OverlappedRead.OffsetHigh = 0;
117 if (!ReadFile((HANDLE)pData->NamedPipe, pvBuf, *cbRead, &cbReallyRead, &pData->OverlappedRead))
118 {
119 DWORD uError = GetLastError();
120
121 if ( uError == ERROR_PIPE_LISTENING
122 || uError == ERROR_PIPE_NOT_CONNECTED)
123 {
124 /* No connection yet/anymore */
125 cbReallyRead = 0;
126
127 /* wait a bit or else we'll be called right back. */
128 RTThreadSleep(100);
129 }
130 else
131 {
132 if (uError == ERROR_IO_PENDING)
133 {
134 uError = 0;
135
136 /* Wait for incoming bytes. */
137 if (GetOverlappedResult((HANDLE)pData->NamedPipe, &pData->OverlappedRead, &cbReallyRead, TRUE) == FALSE)
138 uError = GetLastError();
139 }
140
141 rc = RTErrConvertFromWin32(uError);
142 Log(("drvNamedPipeRead: ReadFile returned %d (%Vrc)\n", uError, rc));
143 }
144 }
145
146 if (VBOX_FAILURE(rc))
147 {
148 Log(("drvNamedPipeRead: RTFileRead returned %Vrc fShutdown=%d\n", rc, pData->fShutdown));
149 if ( !pData->fShutdown
150 && ( rc == VERR_EOF
151 || rc == VERR_BROKEN_PIPE
152 )
153 )
154
155 {
156 RTFILE tmp = pData->NamedPipe;
157 FlushFileBuffers((HANDLE)tmp);
158 DisconnectNamedPipe((HANDLE)tmp);
159 if (!pData->fIsServer)
160 {
161 pData->NamedPipe = NIL_RTFILE;
162 RTFileClose(tmp);
163 }
164 /* pretend success */
165 rc = VINF_SUCCESS;
166 }
167 cbReallyRead = 0;
168 }
169 *cbRead = (size_t)cbReallyRead;
170 }
171#else /* !__WIN__ */
172 if (pData->LocalSocket != NIL_RTSOCKET)
173 {
174 ssize_t cbReallyRead;
175 cbReallyRead = recv(pData->LocalSocket, pvBuf, *cbRead, 0);
176 if (cbReallyRead == 0)
177 {
178 RTSOCKET tmp = pData->LocalSocket;
179 pData->LocalSocket = NIL_RTSOCKET;
180 close(tmp);
181 }
182 else if (cbReallyRead == -1)
183 {
184 cbReallyRead = 0;
185 rc = RTErrConvertFromErrno(errno);
186 }
187 *cbRead = cbReallyRead;
188 }
189#endif /* !__WIN__ */
190 else
191 {
192 RTThreadSleep(100);
193 *cbRead = 0;
194 }
195
196 LogFlow(("%s: cbRead=%d returns %Vrc\n", __FUNCTION__, *cbRead, rc));
197 return rc;
198}
199
200
201/** @copydoc PDMISTREAM::pfnWrite */
202static DECLCALLBACK(int) drvNamedPipeWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *cbWrite)
203{
204 int rc = VINF_SUCCESS;
205 PDRVNAMEDPIPE pData = PDMISTREAM_2_DRVNAMEDPIPE(pInterface);
206 LogFlow(("%s: pvBuf=%p cbWrite=%#x (%s)\n", __FUNCTION__, pvBuf, cbWrite, pData->pszLocation));
207
208 Assert(pvBuf);
209#ifdef __WIN__
210 if (pData->NamedPipe != NIL_RTFILE)
211 {
212 unsigned cbWritten;
213 pData->OverlappedWrite.Offset = 0;
214 pData->OverlappedWrite.OffsetHigh = 0;
215 if (!WriteFile((HANDLE)pData->NamedPipe, pvBuf, *cbWrite, NULL, &pData->OverlappedWrite))
216 {
217 DWORD uError = GetLastError();
218
219 if ( uError == ERROR_PIPE_LISTENING
220 || uError == ERROR_PIPE_NOT_CONNECTED)
221 {
222 /* No connection yet/anymore; just discard the write. */
223 cbWritten = *cbWrite;
224 }
225 else
226 if (uError != ERROR_IO_PENDING)
227 {
228 rc = RTErrConvertFromWin32(uError);
229 Log(("drvNamedPipeWrite: WriteFile returned %d (%Vrc)\n", uError, rc));
230 }
231 else
232 {
233 /* Wait for the write to complete. */
234 if (GetOverlappedResult((HANDLE)pData->NamedPipe, &pData->OverlappedWrite, (DWORD *)&cbWritten, TRUE) == FALSE)
235 uError = GetLastError();
236 }
237 }
238 else
239 cbWritten = *cbWrite;
240
241 if (VBOX_FAILURE(rc))
242 {
243 if ( rc == VERR_EOF
244 || rc == VERR_BROKEN_PIPE)
245 {
246 RTFILE tmp = pData->NamedPipe;
247 FlushFileBuffers((HANDLE)tmp);
248 DisconnectNamedPipe((HANDLE)tmp);
249 if (!pData->fIsServer)
250 {
251 pData->NamedPipe = NIL_RTFILE;
252 RTFileClose(tmp);
253 }
254 /* pretend success */
255 rc = VINF_SUCCESS;
256 }
257 cbWritten = 0;
258 }
259 *cbWrite = cbWritten;
260 }
261#else /* !__WIN__ */
262 if (pData->LocalSocket != NIL_RTSOCKET)
263 {
264 ssize_t cbWritten;
265 cbWritten = send(pData->LocalSocket, pvBuf, *cbWrite, 0);
266 if (cbWritten == 0)
267 {
268 RTSOCKET tmp = pData->LocalSocket;
269 pData->LocalSocket = NIL_RTSOCKET;
270 close(tmp);
271 }
272 else if (cbWritten == -1)
273 {
274 cbWritten = 0;
275 rc = RTErrConvertFromErrno(errno);
276 }
277 *cbWrite = cbWritten;
278 }
279#endif /* !__WIN__ */
280
281 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
282 return rc;
283}
284
285
286/**
287 * Queries an interface to the driver.
288 *
289 * @returns Pointer to interface.
290 * @returns NULL if the interface was not supported by the driver.
291 * @param pInterface Pointer to this interface structure.
292 * @param enmInterface The requested interface identification.
293 * @thread Any thread.
294 */
295static DECLCALLBACK(void *) drvNamedPipeQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
296{
297 PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
298 PDRVNAMEDPIPE pDrv = PDMINS2DATA(pDrvIns, PDRVNAMEDPIPE);
299 switch (enmInterface)
300 {
301 case PDMINTERFACE_BASE:
302 return &pDrvIns->IBase;
303 case PDMINTERFACE_STREAM:
304 return &pDrv->IStream;
305 default:
306 return NULL;
307 }
308}
309
310
311/* -=-=-=-=- listen thread -=-=-=-=- */
312
313/**
314 * Receive thread loop.
315 *
316 * @returns 0 on success.
317 * @param ThreadSelf Thread handle to this thread.
318 * @param pvUser User argument.
319 */
320static DECLCALLBACK(int) drvNamedPipeListenLoop(RTTHREAD ThreadSelf, void *pvUser)
321{
322 PDRVNAMEDPIPE pData = (PDRVNAMEDPIPE)pvUser;
323 int rc = VINF_SUCCESS;
324#ifdef __WIN__
325 RTFILE NamedPipe = pData->NamedPipe;
326 HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, 0);
327#endif
328
329 while (RT_LIKELY(!pData->fShutdown))
330 {
331#ifdef __WIN__
332 OVERLAPPED overlapped;
333
334 memset(&overlapped, 0, sizeof(overlapped));
335 overlapped.hEvent = hEvent;
336
337 BOOL fConnected = ConnectNamedPipe((HANDLE)NamedPipe, &overlapped);
338 if ( !fConnected
339 && !pData->fShutdown)
340 {
341 DWORD hrc = GetLastError();
342
343 if (hrc == ERROR_IO_PENDING)
344 {
345 DWORD dummy;
346
347 hrc = 0;
348 if (GetOverlappedResult((HANDLE)pData->NamedPipe, &overlapped, &dummy, TRUE) == FALSE)
349 hrc = GetLastError();
350
351 }
352
353 if (!pData->fShutdown)
354 break;
355
356 if (hrc == ERROR_PIPE_CONNECTED)
357 {
358 RTThreadSleep(250);
359 }
360 else
361 if (hrc != ERROR_SUCCESS)
362 {
363 rc = RTErrConvertFromWin32(hrc);
364 LogRel(("NamedPipe%d: ConnectNamedPipe failed, rc=%Vrc\n", pData->pDrvIns->iInstance, rc));
365 break;
366 }
367 }
368#else /* !__WIN__ */
369 if (listen(pData->LocalSocketServer, 0) == -1)
370 {
371 rc = RTErrConvertFromErrno(errno);
372 LogRel(("NamedPipe%d: listen failed, rc=%Vrc\n", pData->pDrvIns->iInstance, rc));
373 break;
374 }
375 int s = accept(pData->LocalSocketServer, NULL, NULL);
376 if (s == -1)
377 {
378 rc = RTErrConvertFromErrno(errno);
379 LogRel(("NamedPipe%d: accept failed, rc=%Vrc\n", pData->pDrvIns->iInstance, rc));
380 break;
381 }
382 else
383 {
384 if (pData->LocalSocket != NIL_RTSOCKET)
385 {
386 LogRel(("NamedPipe%d: only single connection supported\n", pData->pDrvIns->iInstance));
387 close(s);
388 }
389 else
390 pData->LocalSocket = s;
391 }
392#endif /* !__WIN__ */
393 }
394
395#ifdef __WIN__
396 CloseHandle(hEvent);
397#endif
398 return VINF_SUCCESS;
399}
400
401
402/**
403 * Construct a named pipe stream driver instance.
404 *
405 * @returns VBox status.
406 * @param pDrvIns The driver instance data.
407 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
408 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
409 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
410 * iInstance it's expected to be used a bit in this function.
411 */
412static DECLCALLBACK(int) drvNamedPipeConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
413{
414 int rc;
415 PDRVNAMEDPIPE pData = PDMINS2DATA(pDrvIns, PDRVNAMEDPIPE);
416
417 /*
418 * Init the static parts.
419 */
420 pData->pDrvIns = pDrvIns;
421 pData->pszLocation = NULL;
422 pData->fIsServer = false;
423#ifdef __WIN__
424 pData->NamedPipe = NIL_RTFILE;
425#else /* !__WIN__ */
426 pData->LocalSocketServer = NIL_RTSOCKET;
427 pData->LocalSocket = NIL_RTSOCKET;
428#endif /* !__WIN__ */
429 pData->ListenThread = NIL_RTTHREAD;
430 pData->fShutdown = false;
431 /* IBase */
432 pDrvIns->IBase.pfnQueryInterface = drvNamedPipeQueryInterface;
433 /* IStream */
434 pData->IStream.pfnRead = drvNamedPipeRead;
435 pData->IStream.pfnWrite = drvNamedPipeWrite;
436
437 /*
438 * Read the configuration.
439 */
440 if (!CFGMR3AreValuesValid(pCfgHandle, "Location\0IsServer\0"))
441 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
442
443 char *pszLocation;
444 rc = CFGMR3QueryStringAlloc(pCfgHandle, "Location", &pszLocation);
445 if (VBOX_FAILURE(rc))
446 {
447 AssertMsgFailed(("Configuration error: query \"Location\" resulted in %Vrc.\n", rc));
448 return rc;
449 }
450 pData->pszLocation = pszLocation;
451
452 bool fIsServer;
453 rc = CFGMR3QueryBool(pCfgHandle, "IsServer", &fIsServer);
454 if (VBOX_FAILURE(rc))
455 {
456 AssertMsgFailed(("Configuration error: query \"IsServer\" resulted in %Vrc.\n", rc));
457 goto out;
458 }
459 pData->fIsServer = fIsServer;
460
461#ifdef __WIN__
462 if (fIsServer)
463 {
464 HANDLE hPipe = CreateNamedPipe(pData->pszLocation, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 32, 32, 10000, NULL);
465 if (hPipe == INVALID_HANDLE_VALUE)
466 {
467 rc = RTErrConvertFromWin32(GetLastError());
468 LogRel(("NamedPipe%d: CreateNamedPipe failed rc=%Vrc\n", pData->pDrvIns->iInstance));
469 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create named pipe %s"), pDrvIns->iInstance, pszLocation);
470 }
471 pData->NamedPipe = (HFILE)hPipe;
472
473 rc = RTThreadCreate(&pData->ListenThread, drvNamedPipeListenLoop, (void *)pData, 0, RTTHREADTYPE_IO, 0, "NamedPipe");
474 if VBOX_FAILURE(rc)
475 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread\n"), pDrvIns->iInstance);
476 }
477 else
478 {
479 /* Connect to the named pipe. */
480 rc = RTFileOpen(&pData->NamedPipe, pszLocation, RTFILE_O_READWRITE);
481 if (VBOX_FAILURE(rc))
482 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to connect to named pipe %s"), pDrvIns->iInstance, pszLocation);
483 }
484
485 memset(&pData->OverlappedWrite, 0, sizeof(pData->OverlappedWrite));
486 memset(&pData->OverlappedRead, 0, sizeof(pData->OverlappedRead));
487 pData->OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
488 pData->OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
489
490#else /* !__WIN__ */
491 int s;
492 struct sockaddr_un addr;
493
494 if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
495 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to create local socket"), pDrvIns->iInstance);
496
497 memset(&addr, 0, sizeof(addr));
498 addr.sun_family = AF_UNIX;
499 strncpy(addr.sun_path, pszLocation, sizeof(addr.sun_path)-1);
500
501 if (fIsServer)
502 {
503 /* Bind address to the local socket. */
504 RTFileDelete(pszLocation);
505 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
506 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to bind to local socket %s"), pDrvIns->iInstance, pszLocation);
507 rc = RTThreadCreate(&pData->ListenThread, drvNamedPipeListenLoop, (void *)pData, 0, RTTHREADTYPE_IO, 0, "NamedPipe");
508 if VBOX_FAILURE(rc)
509 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread\n"), pDrvIns->iInstance);
510 pData->LocalSocketServer = s;
511 }
512 else
513 {
514 /* Connect to the local socket. */
515 if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
516 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to connect to local socket %s"), pDrvIns->iInstance, pszLocation);
517 pData->LocalSocket = s;
518 }
519#endif /* !__WIN__ */
520
521out:
522 if (VBOX_FAILURE(rc))
523 {
524 if (pszLocation)
525 MMR3HeapFree(pszLocation);
526 }
527 else
528 {
529 LogFlow(("drvNamedPipeConstruct: location %s isServer %d\n", pszLocation, fIsServer));
530 LogRel(("NamedPipe: location %s, %s\n", pszLocation, fIsServer ? "server" : "client"));
531 }
532 return rc;
533}
534
535
536/**
537 * Destruct a named pipe stream driver instance.
538 *
539 * Most VM resources are freed by the VM. This callback is provided so that
540 * any non-VM resources can be freed correctly.
541 *
542 * @param pDrvIns The driver instance data.
543 */
544static DECLCALLBACK(void) drvNamedPipeDestruct(PPDMDRVINS pDrvIns)
545{
546 PDRVNAMEDPIPE pData = PDMINS2DATA(pDrvIns, PDRVNAMEDPIPE);
547 LogFlow(("%s: %s\n", __FUNCTION__, pData->pszLocation));
548
549 pData->fShutdown = true;
550
551#ifdef __WIN__
552 if (pData->NamedPipe != NIL_RTFILE)
553 {
554 FlushFileBuffers((HANDLE)pData->NamedPipe);
555 if (!pData->fIsServer)
556 DisconnectNamedPipe((HANDLE)pData->NamedPipe);
557
558 RTFileClose(pData->NamedPipe);
559 pData->NamedPipe = NIL_RTFILE;
560 CloseHandle(pData->OverlappedRead.hEvent);
561 CloseHandle(pData->OverlappedWrite.hEvent);
562 }
563#else /* !__WIN__ */
564 if (pData->fIsServer)
565 {
566 if (pData->LocalSocketServer != NIL_RTSOCKET)
567 close(pData->LocalSocketServer);
568 if (pData->pszLocation)
569 RTFileDelete(pData->pszLocation);
570 }
571 else
572 {
573 if (pData->LocalSocket != NIL_RTSOCKET)
574 close(pData->LocalSocket);
575 }
576#endif /* !__WIN__ */
577 if (pData->pszLocation)
578 MMR3HeapFree(pData->pszLocation);
579}
580
581
582/**
583 * Named pipe driver registration record.
584 */
585const PDMDRVREG g_DrvNamedPipe =
586{
587 /* u32Version */
588 PDM_DRVREG_VERSION,
589 /* szDriverName */
590 "NamedPipe",
591 /* pszDescription */
592 "Named Pipe stream driver.",
593 /* fFlags */
594 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
595 /* fClass. */
596 PDM_DRVREG_CLASS_STREAM,
597 /* cMaxInstances */
598 ~0,
599 /* cbInstance */
600 sizeof(DRVNAMEDPIPE),
601 /* pfnConstruct */
602 drvNamedPipeConstruct,
603 /* pfnDestruct */
604 drvNamedPipeDestruct,
605 /* pfnIOCtl */
606 NULL,
607 /* pfnPowerOn */
608 NULL,
609 /* pfnReset */
610 NULL,
611 /* pfnSuspend */
612 NULL,
613 /* pfnResume */
614 NULL,
615 /* pfnDetach */
616 NULL,
617 /* pfnPowerOff */
618 NULL
619};
Note: See TracBrowser for help on using the repository browser.

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