Changeset 76108 in vbox for trunk/src/VBox/Additions/os2/VBoxSF/VBoxSF.cpp
- Timestamp:
- Dec 10, 2018 12:01:34 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 127349
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/os2/VBoxSF/VBoxSF.cpp
r75558 r76108 189 189 190 190 /** 191 * Allocates a SHFLSTRING buffer .191 * Allocates a SHFLSTRING buffer (UTF-16). 192 192 * 193 193 * @returns Pointer to a SHFLSTRING buffer, NULL if out of memory. 194 * @param cchLength The desired string buffer length (excluding terminator). 195 */ 196 PSHFLSTRING vboxSfOs2StrAlloc(size_t cchLength) 197 { 198 AssertReturn(cchLength <= 0x1000, NULL); 199 200 PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cchLength + 1); 194 * @param cwcLength The desired string buffer length in UTF-16 units 195 * (excluding terminator). 196 */ 197 PSHFLSTRING vboxSfOs2StrAlloc(size_t cwcLength) 198 { 199 AssertReturn(cwcLength <= 0x1000, NULL); 200 uint16_t cb = (uint16_t)cwcLength + 1; 201 cb *= sizeof(RTUTF16); 202 203 PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cb); 201 204 if (pStr) 202 205 { 203 pStr->u16Size = (uint16_t)(cchLength + 1);204 pStr->u16Length = 0;205 pStr->String. ach[0] = '\0';206 pStr->u16Size = cb; 207 pStr->u16Length = 0; 208 pStr->String.utf16[0] = '\0'; 206 209 return pStr; 207 210 } … … 211 214 212 215 /** 213 * Duplicates a UTF-8 string into a SHFLSTRING buffer.216 * Duplicates a shared folders string buffer (UTF-16). 214 217 * 215 218 * @returns Pointer to a SHFLSTRING buffer containing the copy. 216 219 * NULL if out of memory or the string is too long. 217 * @param pachSrc The string to clone. 218 * @param cchSrc The length of the substring, RTMAX_STR for the whole. 219 */ 220 PSHFLSTRING vboxSfOs2StrDup(const char *pachSrc, size_t cchSrc) 221 { 222 if (cchSrc == RTSTR_MAX) 223 cchSrc = strlen(pachSrc); 224 if (cchSrc < 0x1000) 225 { 226 PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cchSrc + 1); 227 if (pStr) 228 { 229 pStr->u16Size = (uint16_t)(cchSrc + 1); 230 pStr->u16Length = (uint16_t)cchSrc; 231 memcpy(pStr->String.ach, pachSrc, cchSrc); 232 pStr->String.ach[cchSrc] = '\0'; 233 return pStr; 234 } 220 * @param pSrc The string to clone. 221 */ 222 PSHFLSTRING vboxSfOs2StrDup(PCSHFLSTRING pSrc) 223 { 224 PSHFLSTRING pDst = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + pSrc->u16Length + sizeof(RTUTF16)); 225 if (pDst) 226 { 227 pDst->u16Size = pSrc->u16Length + (uint16_t)sizeof(RTUTF16); 228 pDst->u16Length = pSrc->u16Length; 229 memcpy(&pDst->String, &pSrc->String, pSrc->u16Length); 230 pDst->String.utf16[pSrc->u16Length / sizeof(RTUTF16)] = '\0'; 231 return pDst; 235 232 } 236 233 return NULL; … … 268 265 int rc = VbglR0SfConnect(&g_SfClient); 269 266 if (RT_SUCCESS(rc)) 270 { 271 rc = VbglR0SfSetUtf8(&g_SfClient); 272 if (RT_SUCCESS(rc)) 273 g_fIsConnectedToService = true; 274 else 275 { 276 LogRel(("VbglR0SfSetUtf8 failed: %Rrc\n", rc)); 277 VbglR0SfDisconnect(&g_SfClient); 278 } 279 } 267 g_fIsConnectedToService = true; 280 268 else 281 269 LogRel(("VbglR0SfConnect failed: %Rrc\n", rc)); … … 358 346 * 359 347 * @returns VBox status code. 360 * @param pName The name of the folder to map. 348 * @param pName The name of the folder to map - ASCII (not UTF-16!). 349 * Must be large enough to hold UTF-16 expansion of the 350 * string, will do so upon return. 361 351 * @param pszTag Folder tag (for the VBoxService automounter). Optional. 362 352 * @param ppFolder Where to return the folder structure on success. … … 386 376 memcpy(&pNew->szName[pName->u16Length + 1], pszTag, cbTag); 387 377 378 /* Expand the folder name to UTF-16. */ 379 uint8_t off = pNew->cchName; 380 uint8_t volatile const *pbSrc = &pName->String.utf8[0]; 381 RTUTF16 volatile *pwcDst = &pName->String.utf16[0]; 382 do 383 pwcDst[off] = pbSrc[off]; 384 while (off-- > 0); 385 pName->u16Length *= sizeof(RTUTF16); 386 Assert(pName->u16Length + sizeof(RTUTF16) <= pName->u16Size); 387 388 /* Try do the mapping.*/ 388 389 rc = VbglR0SfMapFolder(&g_SfClient, pName, &pNew->hHostFolder); 389 390 if (RT_SUCCESS(rc)) … … 397 398 else 398 399 { 399 LogRel(("vboxSfOs2MapFolder: VbglR0SfMapFolder(,% .*s,) -> %Rrc\n", pName->u16Length, pName->String.utf8, rc));400 LogRel(("vboxSfOs2MapFolder: VbglR0SfMapFolder(,%s,) -> %Rrc\n", pNew->szName, rc)); 400 401 RTMemFree(pNew); 401 402 } … … 465 466 466 467 /** 467 * Converts a path to UTF- 8and puts it in a VBGL friendly buffer.468 * Converts a path to UTF-16 and puts it in a VBGL friendly buffer. 468 469 * 469 470 * @returns OS/2 status code … … 474 475 APIRET vboxSfOs2ConvertPath(const char *pszFolderPath, PSHFLSTRING *ppStr) 475 476 { 476 /* Skip unnecessary leading slashes. */ 477 /* 478 * Skip unnecessary leading slashes. 479 */ 477 480 char ch = *pszFolderPath; 478 481 if (ch == '\\' || ch == '/') … … 480 483 pszFolderPath++; 481 484 482 /** @todo do proper codepage -> utf8 conversion and straighten out 483 * everything... */ 485 /* 486 * Since the KEE unicode conversion routines does not seem to know of 487 * surrogate pairs, we will get a very good output size estimate by 488 * using strlen() on the input. 489 */ 484 490 size_t cchSrc = strlen(pszFolderPath); 485 PSHFLSTRING pDst = vboxSfOs2StrAlloc(cchSrc );491 PSHFLSTRING pDst = vboxSfOs2StrAlloc(cchSrc + 4 /*fudge*/); 486 492 if (pDst) 487 493 { 488 pDst->u16Length = (uint16_t)cchSrc; 489 memcpy(pDst->String.utf8, pszFolderPath, cchSrc); 490 pDst->String.utf8[cchSrc] = '\0'; 491 *ppStr = pDst; 492 return NO_ERROR; 493 } 494 APIRET rc = KernStrToUcs(NULL, &pDst->String.utf16[0], (char *)pszFolderPath, cchSrc + 4, cchSrc); 495 if (rc == NO_ERROR) 496 { 497 pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16); 498 *ppStr = pDst; 499 return NO_ERROR; 500 } 501 VbglR0PhysHeapFree(pDst); 502 503 /* 504 * This shouldn't happen, but just in case we try again with 505 * twice the buffer size. 506 */ 507 if (rc == 0x20412 /*ULS_BUFFERFULL*/) 508 { 509 pDst = vboxSfOs2StrAlloc((cchSrc + 16) * 2); 510 if (pDst) 511 { 512 rc = KernStrToUcs(NULL, pDst->String.utf16, (char *)pszFolderPath, (cchSrc + 16) * 2, cchSrc); 513 if (rc == NO_ERROR) 514 { 515 pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16); 516 *ppStr = pDst; 517 return NO_ERROR; 518 } 519 VbglR0PhysHeapFree(pDst); 520 LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath)); 521 } 522 } 523 else 524 LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath)); 525 } 526 527 LogRel(("vboxSfOs2ConvertPath: Out of memory - cchSrc=%#x\n", cchSrc)); 494 528 *ppStr = NULL; 529 return ERROR_NOT_ENOUGH_MEMORY; 530 } 531 532 533 /** 534 * Converts a path to UTF-16 and puts it in a VBGL friendly buffer within a 535 * larger buffer. 536 * 537 * @returns OS/2 status code 538 * @param pszFolderPath The path to convert. 539 * @param offStrInBuf The offset of the SHLFSTRING in the return buffer. 540 * This first part of the buffer is zeroed. 541 * @param ppvBuf Where to return the pointer to the buffer. Free 542 * using vboxSfOs2FreePath. 543 */ 544 APIRET vboxSfOs2ConvertPathEx(const char *pszFolderPath, uint32_t offStrInBuf, void **ppvBuf) 545 { 546 /* 547 * Skip unnecessary leading slashes. 548 */ 549 char ch = *pszFolderPath; 550 if (ch == '\\' || ch == '/') 551 while ((ch = pszFolderPath[1]) == '\\' || ch == '/') 552 pszFolderPath++; 553 554 /* 555 * Since the KEE unicode conversion routines does not seem to know of 556 * surrogate pairs, we will get a very good output size estimate by 557 * using strlen() on the input. 558 */ 559 size_t cchSrc = strlen(pszFolderPath); 560 void *pvBuf = VbglR0PhysHeapAlloc(offStrInBuf + SHFLSTRING_HEADER_SIZE + (cchSrc + 4) * sizeof(RTUTF16)); 561 if (pvBuf) 562 { 563 RT_BZERO(pvBuf, offStrInBuf); 564 565 PSHFLSTRING pDst = (PSHFLSTRING)((uint8_t *)pvBuf + offStrInBuf); 566 APIRET rc = KernStrToUcs(NULL, &pDst->String.utf16[0], (char *)pszFolderPath, cchSrc + 4, cchSrc); 567 if (rc == NO_ERROR) 568 { 569 pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16); 570 pDst->u16Size = (uint16_t)((cchSrc + 4) * sizeof(RTUTF16)); 571 Assert(pDst->u16Length < pDst->u16Size); 572 *ppvBuf = pvBuf; 573 return NO_ERROR; 574 } 575 VbglR0PhysHeapFree(pvBuf); 576 577 #if 0 578 /* 579 * This shouldn't happen, but just in case we try again with 580 * twice the buffer size. 581 */ 582 if (rc == 0x20412 /*ULS_BUFFERFULL*/) 583 { 584 pDst = vboxSfOs2StrAlloc((cchSrc + 16) * 2); 585 if (pDst) 586 { 587 rc = KernStrToUcs(NULL, pDst->String.utf16, (char *)pszFolderPath, (cchSrc + 16) * 2, cchSrc); 588 if (rc == NO_ERROR) 589 { 590 pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16); 591 *ppStr = pDst; 592 return NO_ERROR; 593 } 594 VbglR0PhysHeapFree(pDst); 595 LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath)); 596 } 597 } 598 else 599 #endif 600 LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath)); 601 } 602 603 LogRel(("vboxSfOs2ConvertPath: Out of memory - cchSrc=%#x offStrInBuf=%#x\n", cchSrc, offStrInBuf)); 604 *ppvBuf = NULL; 495 605 return ERROR_NOT_ENOUGH_MEMORY; 496 606 } … … 553 663 * Copy the name into the buffer format that Vbgl desires. 554 664 */ 555 PSHFLSTRING pStrName = vboxSfOs2Str Dup(pachFolderName,cchFolderName);665 PSHFLSTRING pStrName = vboxSfOs2StrAlloc(cchFolderName); 556 666 if (pStrName) 557 667 { 668 memcpy(pStrName->String.ach, pachFolderName, cchFolderName); 669 pStrName->String.ach[cchFolderName] = '\0'; 670 pStrName->u16Length = (uint16_t)cchFolderName; 671 558 672 /* 559 673 * Do the attaching. … … 692 806 */ 693 807 rc = vboxSfOs2ConvertPath(&pszPath[3], ppStrFolderPath); 808 if (rc == NO_ERROR) 809 return rc; 810 811 vboxSfOs2ReleaseFolder(pFolder); 812 *ppFolder = NULL; 813 return rc; 814 } 815 KernReleaseSharedMutex(&g_MtxFolders); 816 LogRel(("vboxSfOs2ResolvePath: No folder mapped on '%s'. Detach race?\n", pszPath)); 817 return ERROR_PATH_NOT_FOUND; 818 } 819 LogRel(("vboxSfOs2ResolvePath: No root slash: '%s'\n", pszPath)); 820 return ERROR_PATH_NOT_FOUND; 821 } 822 LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath)); 823 RT_NOREF_PV(pCdFsd); RT_NOREF_PV(offCurDirEnd); 824 return ERROR_PATH_NOT_FOUND; 825 } 826 827 828 /** 829 * Resolves the given path to a folder structure and folder relative string, 830 * the latter placed within a larger request buffer. 831 * 832 * @returns OS/2 status code. 833 * @param pszPath The path to resolve. 834 * @param pCdFsd The IFS dependent CWD structure if present. 835 * @param offCurDirEnd The offset into @a pszPath of the CWD. -1 if not 836 * CWD relative path. 837 * @param offStrInBuf The offset of the SHLFSTRING in the return buffer. 838 * This first part of the buffer is zeroed. 839 * @param ppFolder Where to return the referenced pointer to the folder 840 * structure. Call vboxSfOs2ReleaseFolder() when done. 841 * @param ppvBuf Where to return the Pointer to the buffer. Free 842 * using VbglR0PhysHeapFree. 843 */ 844 APIRET vboxSfOs2ResolvePathEx(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd, uint32_t offStrInBuf, 845 PVBOXSFFOLDER *ppFolder, void **ppvBuf) 846 { 847 APIRET rc; 848 849 /* 850 * UNC path? Reject the prefix to be on the safe side. 851 */ 852 char ch = pszPath[0]; 853 if (ch == '\\' || ch == '/') 854 { 855 size_t cchPrefix = vboxSfOs2UncPrefixLength(pszPath); 856 if (cchPrefix > 0) 857 { 858 /* Find the length of the folder name (share). */ 859 const char *pszFolderName = &pszPath[cchPrefix]; 860 size_t cchFolderName = 0; 861 while ((ch = pszFolderName[cchFolderName]) != '\0' && ch != '\\' && ch != '/') 862 { 863 if ((uint8_t)ch >= 0x20 && (uint8_t)ch <= 0x7f && ch != ':') 864 cchFolderName++; 865 else 866 { 867 LogRel(("vboxSfOs2ResolvePath: Invalid share name (@%u): %.*Rhxs\n", 868 cchPrefix + cchFolderName, strlen(pszPath), pszPath)); 869 return ERROR_INVALID_NAME; 870 } 871 } 872 if (cchFolderName >= VBOXSFOS2_MAX_FOLDER_NAME) 873 { 874 LogRel(("vboxSfOs2ResolvePath: Folder name is too long: %u, max %u (%s)\n", 875 cchFolderName, VBOXSFOS2_MAX_FOLDER_NAME, pszPath)); 876 return ERROR_FILENAME_EXCED_RANGE; 877 } 878 879 /* 880 * Look for the share. 881 */ 882 KernRequestSharedMutex(&g_MtxFolders); 883 PVBOXSFFOLDER pFolder = *ppFolder = vboxSfOs2FindAndRetainFolder(pszFolderName, cchFolderName); 884 if (pFolder) 885 { 886 vboxSfOs2RetainFolder(pFolder); 887 KernReleaseSharedMutex(&g_MtxFolders); 888 } 889 else 890 { 891 uint32_t const uRevBefore = g_uFolderRevision; 892 KernReleaseSharedMutex(&g_MtxFolders); 893 rc = vboxSfOs2AttachUncAndRetain(pszFolderName, cchFolderName, uRevBefore, ppFolder); 894 if (rc == NO_ERROR) 895 pFolder = *ppFolder; 896 else 897 return rc; 898 } 899 900 /* 901 * Convert the path and put it in a Vbgl compatible buffer.. 902 */ 903 rc = vboxSfOs2ConvertPathEx(&pszFolderName[cchFolderName], offStrInBuf, ppvBuf); 904 if (rc == NO_ERROR) 905 return rc; 906 907 vboxSfOs2ReleaseFolder(pFolder); 908 *ppFolder = NULL; 909 return rc; 910 } 911 912 LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath)); 913 return ERROR_PATH_NOT_FOUND; 914 } 915 916 /* 917 * Drive letter? 918 */ 919 ch &= ~0x20; /* upper case */ 920 if ( ch >= 'A' 921 && ch <= 'Z' 922 && pszPath[1] == ':') 923 { 924 unsigned iDrive = ch - 'A'; 925 ch = pszPath[2]; 926 if (ch == '\\' || ch == '/') 927 { 928 KernRequestSharedMutex(&g_MtxFolders); 929 PVBOXSFFOLDER pFolder = *ppFolder = g_apDriveFolders[iDrive]; 930 if (pFolder) 931 { 932 vboxSfOs2RetainFolder(pFolder); 933 KernReleaseSharedMutex(&g_MtxFolders); 934 935 /* 936 * Convert the path and put it in a Vbgl compatible buffer.. 937 */ 938 rc = vboxSfOs2ConvertPathEx(&pszPath[3], offStrInBuf, ppvBuf); 694 939 if (rc == NO_ERROR) 695 940 return rc; … … 1006 1251 RT_NOREF(uType); /* pass 1 or pass 2 doesn't matter to us, we've only got one 'server'. */ 1007 1252 1008 if (vboxSfOs2UncPrefixLength(pszName) > 0 1253 if (vboxSfOs2UncPrefixLength(pszName) > 0) 1009 1254 return NO_ERROR; 1010 1255 return ERROR_NOT_SUPPORTED; … … 1074 1319 { 1075 1320 SHFLSTRING Path; 1076 uint8_t abPadding[SHFLSTRING_HEADER_SIZE + 4 ];1321 uint8_t abPadding[SHFLSTRING_HEADER_SIZE + 4 * sizeof(RTUTF16)]; 1077 1322 }; 1078 1323 } Open; … … 1096 1341 pu->Open.Params.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACT_OPEN_IF_EXISTS 1097 1342 | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ | SHFL_CF_ACCESS_DENYNONE; 1098 pu->Open.Path.u16Size = 3 ;1099 pu->Open.Path.u16Length = 2 ;1100 pu->Open.Path.String.utf 8[0] = '\\';1101 pu->Open.Path.String.utf 8[1] = '.';1102 pu->Open.Path.String.utf 8[2] = '\0';1343 pu->Open.Path.u16Size = 3 * sizeof(RTUTF16); 1344 pu->Open.Path.u16Length = 2 * sizeof(RTUTF16); 1345 pu->Open.Path.String.utf16[0] = '\\'; 1346 pu->Open.Path.String.utf16[1] = '.'; 1347 pu->Open.Path.String.utf16[2] = '\0'; 1103 1348 1104 1349 int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, &pu->Open.Path, &pu->Open.Params); … … 1272 1517 { 1273 1518 LogFlow(("FS32_MKDIR: pCdFsi=%p pCdFsd=%p pszDir=%p:{%s} pEAOp=%p fFlags=%#x\n", pCdFsi, pCdFsd, pszDir, pszDir, offCurDirEnd, pEaOp, fFlags)); 1519 RT_NOREF(fFlags); 1274 1520 1275 1521 /* … … 1626 1872 LogFlow(("FS32_FILEATTRIBUTE: fFlags=%#x pCdFsi=%p:{%#x,%s} pCdFsd=%p pszName=%p:{%s} offCurDirEnd=%d pfAttr=%p\n", 1627 1873 fFlags, pCdFsi, pCdFsi->cdi_hVPB, pCdFsi->cdi_curdir, pCdFsd, pszName, pszName, offCurDirEnd, pfAttr)); 1628 RT_NOREF( offCurDirEnd);1874 RT_NOREF(pCdFsi, offCurDirEnd); 1629 1875 1630 1876 APIRET rc;
Note:
See TracChangeset
for help on using the changeset viewer.