Changeset 10930 in vbox for trunk/src/VBox/Additions/common
- Timestamp:
- Jul 29, 2008 1:25:47 PM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 33778
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestProp.cpp
r10865 r10930 28 28 #include <iprt/mem.h> 29 29 #include <iprt/assert.h> 30 #include <iprt/autores> 30 31 #include <iprt/stdarg.h> 31 32 #include <VBox/log.h> … … 33 34 34 35 #include "VBGLR3Internal.h" 36 37 /******************************************************************************* 38 * Structures and Typedefs * 39 *******************************************************************************/ 40 /** 41 * Structure containing information needed to enumerate through guest 42 * properties. 43 */ 44 struct VBGLR3GUESTPROPENUM 45 { 46 /** The buffer containing the raw enumeration data */ 47 char *pchBuf; 48 /** The size of the buffer */ 49 uint32_t cchBuf; 50 /** Index into the buffer pointing to the next entry to enumerate */ 51 uint32_t iBuf; 52 }; 35 53 36 54 using namespace guestProp; … … 235 253 * @param u32ClientId The client id returned by VbglR3ClipboardConnect(). 236 254 * @param pszName The value to read. Utf8 237 * @param p cBuf A scratch buffer to store the data retrieved into.255 * @param pvBuf A scratch buffer to store the data retrieved into. 238 256 * The returned data is only valid for it's lifetime. 257 * @a ppszValue will point to the start of this buffer. 239 258 * @param cbBuf The size of @a pcBuf 240 259 * @param pszValue Where to store the pointer to the value retrieved. 260 * Optional. 241 261 * @param pu64Timestamp Where to store the timestamp. Optional. 242 262 * @param pszFlags Where to store the pointer to the flags. Optional. … … 273 293 if (RT_SUCCESS(rc) && (pu64Timestamp != NULL)) 274 294 rc = VbglHGCMParmUInt64Get(&Msg.timestamp, pu64Timestamp); 275 if (RT_SUCCESS(rc) )295 if (RT_SUCCESS(rc) && (ppszValue != NULL)) 276 296 *ppszValue = reinterpret_cast<char *>(pvBuf); 277 297 if (RT_SUCCESS(rc) && (ppszFlags != NULL)) … … 320 340 * report the problem if that fails. 321 341 */ 322 char *pszValue = NULL; 323 void *pvBuf = NULL; 324 uint32_t cchBuf = MAX_VALUE_LEN; 325 int rc = VERR_BUFFER_OVERFLOW; 342 uint32_t cchBuf = MAX_VALUE_LEN; 343 RTMemAutoPtr<char> pcBuf; 344 int rc = VERR_BUFFER_OVERFLOW; 326 345 for (unsigned i = 0; i < 10 && rc == VERR_BUFFER_OVERFLOW; ++i) 327 346 { 328 347 /* We leave a bit of space here in case the maximum value is raised. */ 329 348 cchBuf += 1024; 330 void *pvTmpBuf = RTMemRealloc(pvBuf, cchBuf); 331 if (pvTmpBuf) 332 { 333 pvBuf = pvTmpBuf; 334 rc = VbglR3GuestPropRead(u32ClientId, pszName, pvBuf, cchBuf, 335 &pszValue, NULL, NULL, &cchBuf); 336 } 349 if (!pcBuf.realloc<RTMemRealloc>(cchBuf)) 350 rc = VERR_NO_MEMORY; 351 if (RT_SUCCESS(rc)) 352 rc = VbglR3GuestPropRead(u32ClientId, pszName, pcBuf.get(), cchBuf, 353 NULL, NULL, NULL, &cchBuf); 337 354 else 338 355 rc = VERR_NO_MEMORY; 339 356 } 340 357 if (RT_SUCCESS(rc)) 341 { 342 Assert(pszValue == (char *)pvBuf); 343 *ppszValue = pszValue; 344 } 345 else 346 { 347 RTMemFree(pvBuf); 348 if (rc == VERR_BUFFER_OVERFLOW) 349 /* VERR_BUFFER_OVERFLOW has a different meaning here as a 350 * return code, but we need to report the race. */ 351 rc = VERR_TOO_MUCH_DATA; 352 } 358 *ppszValue = pcBuf.release(); 359 else if (rc == VERR_BUFFER_OVERFLOW) 360 /* VERR_BUFFER_OVERFLOW has a different meaning here as a 361 * return code, but we need to report the race. */ 362 rc = VERR_TOO_MUCH_DATA; 353 363 354 364 return rc; … … 407 417 return rc; 408 418 } 419 420 421 /** 422 * Raw API for enumerating guest properties which match a given pattern. 423 * 424 * @returns VINF_SUCCESS on success and pcBuf points to a packed array 425 * of the form <name>, <value>, <timestamp string>, <flags>, 426 * terminated by four empty strings. pcbBufActual will contain the 427 * total size of the array. 428 * @returns VERR_BUFFER_OVERFLOW if the buffer provided was too small. In 429 * this case pcbBufActual will contain the size of the buffer needed. 430 * @returns IPRT error code in other cases, and pchBufActual is undefined. 431 * @param u32ClientId The client ID returned by VbglR3GuestPropConnect 432 * @param paszPatterns A packed array of zero terminated strings, terminated 433 * by an empty string. 434 * @param pcBuf The buffer to store the results to. 435 * @param cbBuf The size of the buffer 436 * @param pcbBufActual Where to store the size of the returned data on 437 * success or the buffer size needed if @a pcBuf is too 438 * small. 439 */ 440 VBGLR3DECL(int) VbglR3GuestPropEnumRaw(uint32_t u32ClientId, 441 const char *paszPatterns, 442 char *pcBuf, 443 uint32_t cbBuf, 444 uint32_t *pcbBufActual) 445 { 446 EnumProperties Msg; 447 448 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */ 449 Msg.hdr.u32ClientID = u32ClientId; 450 Msg.hdr.u32Function = ENUM_PROPS; 451 Msg.hdr.cParms = 3; 452 /* Get the length of the patterns array... */ 453 uint32_t cchPatterns = 0; 454 for (uint32_t cchCurrent = strlen(paszPatterns); cchCurrent != 0; 455 cchCurrent = strlen(paszPatterns + cchPatterns)) 456 cchPatterns += cchCurrent + 1; 457 /* ...including the terminator. */ 458 ++cchPatterns; 459 VbglHGCMParmPtrSet(&Msg.patterns, const_cast<char *>(paszPatterns), 460 cchPatterns); 461 VbglHGCMParmPtrSet(&Msg.strings, pcBuf, cbBuf); 462 VbglHGCMParmUInt32Set(&Msg.size, 0); 463 464 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 465 if (RT_SUCCESS(rc)) 466 rc = Msg.hdr.result; 467 if ( (RT_SUCCESS(rc) || (VERR_BUFFER_OVERFLOW == rc)) 468 && (pcbBufActual != NULL) 469 ) 470 { 471 int rc2 = VbglHGCMParmUInt32Get(&Msg.size, pcbBufActual); 472 if (!RT_SUCCESS(rc2)) 473 rc = rc2; 474 } 475 return rc; 476 } 477 478 479 /** 480 * Start enumerating guest properties which match a given pattern. 481 * This function creates a handle which can be used to continue enumerating. 482 * @returns VINF_SUCCESS on success, ppHandle points to a handle for continuing 483 * the enumeration and ppszName, ppszValue, pu64Timestamp and 484 * ppszFlags are set. 485 * @returns VERR_NOT_FOUND if no matching properties were found. In this case 486 * the return parameters are not initialised. 487 * @returns VERR_TOO_MUCH_DATA if it was not possible to determine the amount 488 * of local space needed to store all the enumeration data. This is 489 * due to a race between allocating space and the host adding new 490 * data, so retrying may help here. Other parameters are left 491 * uninitialised 492 * @returns IPRT status value otherwise. Other parameters are left 493 * uninitialised. 494 * @param ppaszPatterns the patterns against which the properties are 495 * matched. Pass NULL if everything should be matched. 496 * @param cPatterns the number of patterns in @a ppaszPatterns. 0 means 497 * match everything. 498 * @param ppHandle where the handle for continued enumeration is stored 499 * on success. This must be freed with 500 * VbglR3GuestPropEnumFree when it is no longer needed. 501 * @param ppszName Where to store the first property name on success. 502 * Should not be freed. 503 * @param ppszValue Where to store the first property value on success. 504 * Should not be freed. 505 * @param ppszValue Where to store the first timestamp value on success. 506 * @param ppszFlags Where to store the first flags value on success. 507 * Should not be freed. 508 */ 509 VBGLR3DECL(int) VbglR3GuestPropEnum(uint32_t u32ClientId, 510 char **ppaszPatterns, 511 int cPatterns, 512 PVBGLR3GUESTPROPENUM *ppHandle, 513 char **ppszName, 514 char **ppszValue, 515 uint64_t *pu64Timestamp, 516 char **ppszFlags) 517 { 518 int rc = VINF_SUCCESS; 519 RTMemAutoPtr<VBGLR3GUESTPROPENUM, VbglR3GuestPropEnumFree> pHandle; 520 pHandle = reinterpret_cast<PVBGLR3GUESTPROPENUM>( 521 RTMemAllocZ(sizeof(VBGLR3GUESTPROPENUM)) 522 ); 523 if (NULL == pHandle.get()) 524 rc = VERR_NO_MEMORY; 525 526 /* Get the length of the pattern string, including the final terminator. */ 527 uint32_t cchPatterns = 1; 528 for (int i = 0; i < cPatterns; ++i) 529 cchPatterns += strlen(ppaszPatterns[i]) + 1; 530 /* Pack the pattern array */ 531 RTMemAutoPtr<char> pPatterns; 532 pPatterns = reinterpret_cast<char *>(RTMemAlloc(cchPatterns)); 533 char *pPatternsRaw = pPatterns.get(); 534 for (int i = 0; i < cPatterns; ++i) 535 pPatternsRaw = strcpy(pPatternsRaw, ppaszPatterns[i]) + strlen(ppaszPatterns[i]) + 1; 536 *pPatternsRaw = 0; 537 538 /* Randomly chosen initial size for the buffer to hold the enumeration 539 * information. */ 540 uint32_t cchBuf = 4096; 541 RTMemAutoPtr<char> pchBuf; 542 /* In reading the guest property data we are racing against the host 543 * adding more of it, so loop a few times and retry on overflow. */ 544 bool finish = false; 545 if (RT_SUCCESS(rc)) 546 for (int i = 0; (i < 10) && !finish; ++i) 547 { 548 if (!pchBuf.realloc<RTMemRealloc>(cchBuf)) 549 rc = VERR_NO_MEMORY; 550 if (RT_SUCCESS(rc) || (VERR_BUFFER_OVERFLOW == rc)) 551 rc = VbglR3GuestPropEnumRaw(u32ClientId, pPatterns.get(), 552 pchBuf.get(), cchBuf, &cchBuf); 553 if (rc != VERR_BUFFER_OVERFLOW) 554 finish = true; 555 else 556 cchBuf += 4096; /* Just to increase our chances */ 557 } 558 if (VERR_BUFFER_OVERFLOW == rc) 559 rc = VERR_TOO_MUCH_DATA; 560 if (RT_SUCCESS(rc)) 561 { 562 /* Transfer ownership of the buffer to the handle structure. */ 563 pHandle->pchBuf = pchBuf.release(); 564 pHandle->cchBuf = cchBuf; 565 } 566 if (RT_SUCCESS(rc)) 567 rc = VbglR3GuestPropEnumNext(pHandle.get(), ppszName, ppszValue, 568 pu64Timestamp, ppszFlags); 569 if (RT_SUCCESS(rc) && (NULL == ppszName)) 570 /* No matching properties found */ 571 rc = VERR_NOT_FOUND; 572 /* And transfer ownership of the handle to the caller. */ 573 if (RT_SUCCESS(rc)) 574 *ppHandle = pHandle.release(); 575 return rc; 576 } 577 578 579 /** 580 * Get the next guest property. See @a VbglR3GuestPropEnum. 581 * @param pHandle handle obtained from @a VbglR3GuestPropEnum. 582 * @param ppszName where to store the next property name. This will be 583 * set to NULL if there are no more properties to 584 * enumerate. This pointer should not be freed. 585 * @param ppszValue where to store the next property value. This will be 586 * set to NULL if there are no more properties to 587 * enumerate. This pointer should not be freed. 588 * @param pu64Timestamp where to store the next property timestamp. This 589 * will be set to zero if there are no more properties 590 * to enumerate. 591 * @param ppszFlags where to store the next property flags. This will be 592 * set to NULL if there are no more properties to 593 * enumerate. This pointer should not be freed. 594 */ 595 VBGLR3DECL(int) VbglR3GuestPropEnumNext(PVBGLR3GUESTPROPENUM pHandle, 596 char **ppszName, 597 char **ppszValue, 598 uint64_t *pu64Timestamp, 599 char **ppszFlags) 600 { 601 uint32_t iBuf = pHandle->iBuf; 602 char *pszName = pHandle->pchBuf + iBuf; 603 /** @todo replace these with safe strlen's and return an error if needed. */ 604 iBuf += strlen(pszName) + 1; 605 char *pszValue = pHandle->pchBuf + iBuf; 606 iBuf += strlen(pszValue) + 1; 607 char *pszTimestamp = pHandle->pchBuf + iBuf; 608 iBuf += strlen(pszTimestamp) + 1; 609 uint64_t u64Timestamp = RTStrToUInt64(pszTimestamp); 610 char *pszFlags = pHandle->pchBuf + iBuf; 611 iBuf += strlen(pszFlags) + 1; 612 /* Otherwise we just stay at the end of the list. */ 613 if ((iBuf != pHandle->iBuf + 4) && (iBuf < pHandle->cchBuf) /* sanity */) 614 pHandle->iBuf = iBuf; 615 *ppszName = *pszName != 0 ? pszName : NULL; 616 *ppszValue = pszValue != 0 ? pszValue : NULL; 617 *pu64Timestamp = u64Timestamp; 618 *ppszFlags = pszFlags != 0 ? pszFlags : NULL; 619 return VINF_SUCCESS; 620 } 621 622 623 /** 624 * Free an enumeration handle returned by @a VbglR3GuestPropEnum. 625 * @param pHandle the handle to free 626 */ 627 VBGLR3DECL(void) VbglR3GuestPropEnumFree(PVBGLR3GUESTPROPENUM pHandle) 628 { 629 RTMemFree(pHandle->pchBuf); 630 RTMemFree(pHandle); 631 }
Note:
See TracChangeset
for help on using the changeset viewer.