/*++ MangleObjectNameW Mangle an object name to be side-by-side with other Rotors lplpObjectName - [in out] pointer to pointer to object name to mangle lpMangledObjectName - buffer of MAX_PATH characters to store the mangled object name in Returns TRUE on success. On failure, returns FALSE with LastError set. --*/ BOOL MangleObjectNameW(LPCWSTR *lplpObjectName, LPWSTR lpMangledObjectName) { size_t ObjectNameLength; LPCWSTR lpObjectName; WCHAR *pSlash; lpObjectName = *lplpObjectName; if (!lpObjectName) { // No object name, so no work to do. return TRUE; } ObjectNameLength = PAL_wcslen(lpObjectName); if (ObjectNameLength+NameManglerLength+1 >= MAX_PATH) { SetLastError(ERROR_FILENAME_EXCED_RANGE); return FALSE; } *lplpObjectName = lpMangledObjectName; pSlash = PAL_wcschr(lpObjectName, L'\\'); if (pSlash) { size_t PathPartLength; // The mangling needs to be done after the Global\\ or Local\\ portion PathPartLength = pSlash-lpObjectName+1; memcpy(lpMangledObjectName, lpObjectName, PathPartLength*sizeof(WCHAR)); lpObjectName+=PathPartLength; lpMangledObjectName+=PathPartLength; } PAL_wcsncpy(lpMangledObjectName, NameManglerW, NameManglerLength); PAL_wcscpy(lpMangledObjectName+NameManglerLength, lpObjectName); return TRUE; }
/*++ Function : PAL_GetPALDirectoryW Returns the fully qualified path name where the PALL DLL was loaded from. On failure it returns FALSE and sets the proper LastError code. See rotor_pal.doc for more details. --*/ PALIMPORT BOOL PALAPI PAL_GetPALDirectoryW( OUT LPWSTR lpDirectoryName, IN OUT UINT* cchDirectoryName ) { PathWCharString directory; BOOL bRet; PERF_ENTRY(PAL_GetPALDirectoryW); ENTRY( "PAL_GetPALDirectoryW( %p, %d )\n", lpDirectoryName, *cchDirectoryName ); bRet = PAL_GetPALDirectoryW(directory); if (bRet) { if (directory.GetCount() > *cchDirectoryName) { SetLastError( ERROR_INSUFFICIENT_BUFFER ); bRet = FALSE; } else { PAL_wcscpy(lpDirectoryName, directory.GetString()); } *cchDirectoryName = directory.GetCount(); } LOGEXIT( "PAL_GetPALDirectoryW returns BOOL %d.\n", bRet); PERF_EXIT(PAL_GetPALDirectoryW); return bRet; }
/*++ Function: PAL_GetUserConfigurationDirectoryW Abstract: Returns the user configuration directory, which is a ".rotor" subdirectory of the user's home directory. ~/.rotor is created if it doesn't exist. --*/ BOOL PALAPI PAL_GetUserConfigurationDirectoryW( OUT LPWSTR lpDirectoryName, IN UINT cbDirectoryName) { BOOL retval; ENTRY("PAL_GetUserConfigurationDirectoryW (lpDirectoryName=%p " "cbDirectoryName=%d)\n", lpDirectoryName, cbDirectoryName); if (PALUserDirNameLength >= cbDirectoryName) { retval = FALSE; } else { PAL_wcscpy(lpDirectoryName, PALUserDirName); retval = TRUE; } LOGEXIT("PAL_GetUserConfigurationDirectoryW returns BOOL %d\n", retval); return(retval); }
/*++ Function: FMTMSG_GetMessageString Returns the message as a wide string. --*/ static LPWSTR FMTMSG_GetMessageString( DWORD dwErrCode ) { TRACE("Entered FMTMSG_GetMessageString\n"); LPCWSTR lpErrorString = GetPalErrorString(dwErrCode); int allocChars; if (lpErrorString != NULL) { allocChars = PAL_wcslen(lpErrorString) + 1; } else { allocChars = MAX_ERROR_STRING_LENGTH + 1; } LPWSTR lpRetVal = (LPWSTR)LocalAlloc(LMEM_FIXED, allocChars * sizeof(WCHAR)); if (lpRetVal) { if (lpErrorString != NULL) { PAL_wcscpy(lpRetVal, lpErrorString); } else { swprintf_s(lpRetVal, MAX_ERROR_STRING_LENGTH, W("Error %u"), dwErrCode); } } else { ERROR("Unable to allocate memory.\n"); } return lpRetVal; }
/*++ Function: _wsplitpath See MSDN doc. Notes : This implementation ignores drive letters as they should not be present. If the drive argument is non-NULL, it always returns an empty string. File names in which the only period is at the beginning (like .bashrc, but not .bashrc.bak), the file is treated as having no extension (fname is ".bashrc", ext is "") --*/ void __cdecl _wsplitpath( const wchar_16 *dospath, wchar_16 *drive, wchar_16 *dir, wchar_16 *fname, wchar_16 *ext) { WCHAR path[_MAX_PATH+1]; LPCWSTR slash_ptr = NULL; LPCWSTR period_ptr = NULL; INT size = 0; PERF_ENTRY(_wsplitpath); ENTRY("_wsplitpath (path=%p (%S), drive=%p, dir=%p, fname=%p, ext=%p)\n", path?path:W16_NULLSTRING, path?path:W16_NULLSTRING, drive, dir, fname, ext); /* Do performance intensive error checking only in debug builds. NOTE: This function must fail predictably across all platforms. Under Windows this function throw an access violation if NULL was passed in as the value for path. */ #if _DEBUG if ( !dospath ) { ERROR( "path cannot be NULL!\n" ); } #endif if( lstrlenW( dospath ) >= _MAX_PATH ) { ERROR("Path length is > _MAX_PATH (%d)!\n", _MAX_PATH); ON_ERROR; } PAL_wcscpy(path, dospath); FILEDosToUnixPathW(path); /* no drive letters in the PAL */ if( drive != NULL ) { drive[0] = 0; } /* find last path separator char */ slash_ptr = PAL_wcsrchr(path, '/'); if( slash_ptr == NULL ) { TRACE("No path separator in path\n"); slash_ptr = path - 1; } /* find extension separator, if any */ period_ptr = PAL_wcsrchr(path, '.'); /* make sure we only consider periods after the last path separator */ if( period_ptr < slash_ptr ) { period_ptr = NULL; } /* if the only period in the file is a leading period (denoting a hidden file), don't treat what follows as an extension */ if( period_ptr == slash_ptr+1 ) { period_ptr = NULL; } if( period_ptr == NULL ) { TRACE("No extension in path\n"); period_ptr = path + lstrlenW(path); } size = slash_ptr - path + 1; if( dir != NULL ) { INT i; if( (size + 1 ) > _MAX_DIR ) { ERROR("Directory component needs %d characters, _MAX_DIR is %d\n", size+1, _MAX_DIR); ON_ERROR; } memcpy(dir, path, size*sizeof(WCHAR)); dir[size] = 0; /* only allow / separators in returned path */ i = 0; while( dir[ i ] ) { if( dir[ i ] == '\\' ) { dir[i]='/'; } i++; } } size = period_ptr-slash_ptr-1; if( fname != NULL ) { if( (size+1) > _MAX_FNAME ) { ERROR("Filename component needs %d characters, _MAX_FNAME is %d\n", size+1, _MAX_FNAME); ON_ERROR; } memcpy(fname, slash_ptr+1, size*sizeof(WCHAR)); fname[size] = 0; } size = 1 + lstrlenW( period_ptr ); if( ext != NULL ) { if( size > _MAX_EXT ) { ERROR("Extension component needs %d characters, _MAX_EXT is %d\n", size, _MAX_EXT); ON_ERROR; } memcpy(ext, period_ptr, size*sizeof(WCHAR)); ext[size-1] = 0; } TRACE("Path components are '%S' '%S' '%S'\n", dir, fname, ext); done: LOGEXIT("_wsplitpath returns.\n"); PERF_EXIT(_wsplitpath); }
/*++ Function: SearchPathW See MSDN doc. PAL-specific notes : -lpPath must be non-NULL; path delimiters are platform-dependent (':' for Unix) -lpFileName must be non-NULL, may be an absolute path -lpExtension must be NULL -lpFilePart (if non-NULL) doesn't need to be used (but we do) --*/ DWORD PALAPI SearchPathW( IN LPCWSTR lpPath, IN LPCWSTR lpFileName, IN LPCWSTR lpExtension, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart ) { DWORD nRet = 0; WCHAR FullPath[MAX_PATH]; LPCWSTR pPathStart; LPCWSTR pPathEnd; size_t PathLength; size_t FileNameLength; DWORD dw; char AnsiPath[MAX_PATH]; WCHAR CanonicalPath[MAX_PATH]; PERF_ENTRY(SearchPathW); ENTRY("SearchPathW(lpPath=%p (%S), lpFileName=%p (%S), lpExtension=%p, " "nBufferLength=%u, lpBuffer=%p, lpFilePart=%p)\n", lpPath, lpPath, lpFileName, lpFileName, lpExtension, nBufferLength, lpBuffer, lpFilePart); /* validate parameters */ if(NULL == lpPath) { ASSERT("lpPath may not be NULL\n"); SetLastError(ERROR_INVALID_PARAMETER); goto done; } if(NULL == lpFileName) { ASSERT("lpFileName may not be NULL\n"); SetLastError(ERROR_INVALID_PARAMETER); goto done; } if(NULL != lpExtension) { ASSERT("lpExtension must be NULL, is %p instead\n", lpExtension); SetLastError(ERROR_INVALID_PARAMETER); goto done; } /* special case : if file name contains absolute path, don't search the provided path */ if('\\' == lpFileName[0] || '/' == lpFileName[0]) { /* Canonicalize the path to deal with back-to-back '/', etc. */ dw = GetFullPathNameW(lpFileName, MAX_PATH, CanonicalPath, NULL); if (dw == 0 || dw >= MAX_PATH) { WARN("couldn't canonicalize path <%S>, error is %#x. failing.\n", lpPath, GetLastError()); SetLastError(ERROR_INVALID_PARAMETER); goto done; } /* see if the file exists */ WideCharToMultiByte(CP_ACP, 0, CanonicalPath, -1, AnsiPath, MAX_PATH, NULL, NULL); if(0 == access(AnsiPath, F_OK)) { /* found it */ nRet = dw; } } else { LPCWSTR pNextPath; pNextPath = lpPath; FileNameLength = PAL_wcslen(lpFileName); while (*pNextPath) { pPathStart = pNextPath; /* get a pointer to the end of the first path in pPathStart */ pPathEnd = PAL_wcschr(pPathStart, ':'); if (!pPathEnd) { pPathEnd = pPathStart + PAL_wcslen(pPathStart); /* we want to break out of the loop after this pass, so let *pNextPath be '\0' */ pNextPath = pPathEnd; } else { /* point to the next component in the path string */ pNextPath = pPathEnd+1; } PathLength = pPathEnd-pPathStart; if (PathLength+FileNameLength+1 >= MAX_PATH) { /* The path+'/'+file length is too long. Skip it. */ WARN("path component %.*S is too long, skipping it\n", (int)PathLength, pPathStart); continue; } else if(0 == PathLength) { /* empty component : there were 2 consecutive ':' */ continue; } /* Construct a pathname by concatenating one path from lpPath, '/' and lpFileName */ memcpy(FullPath, pPathStart, PathLength*sizeof(WCHAR)); FullPath[PathLength] = '/'; PAL_wcscpy(&FullPath[PathLength+1], lpFileName); /* Canonicalize the path to deal with back-to-back '/', etc. */ dw = GetFullPathNameW(FullPath, MAX_PATH, CanonicalPath, NULL); if (dw == 0 || dw >= MAX_PATH) { /* Call failed - possibly low memory. Skip the path */ WARN("couldn't canonicalize path <%S>, error is %#x. " "skipping it\n", FullPath, GetLastError()); continue; } /* see if the file exists */ WideCharToMultiByte(CP_ACP, 0, CanonicalPath, -1, AnsiPath, MAX_PATH, NULL, NULL); if(0 == access(AnsiPath, F_OK)) { /* found it */ nRet = dw; break; } } } if (nRet == 0) { /* file not found anywhere; say so. in Windows, this always seems to say FILE_NOT_FOUND, even if path doesn't exist */ SetLastError(ERROR_FILE_NOT_FOUND); } else { /* find out the required buffer size, copy path to buffer if it's large enough */ nRet = PAL_wcslen(CanonicalPath)+1; if(nRet <= nBufferLength) { if(NULL == lpBuffer) { /* Windows merily crashes here, but let's not */ ERROR("caller told us buffer size was %d, but buffer is NULL\n", nBufferLength); SetLastError(ERROR_INVALID_PARAMETER); nRet = 0; goto done; } PAL_wcscpy(lpBuffer, CanonicalPath); /* don't include the null-terminator in the count if buffer was large enough */ nRet--; if(NULL != lpFilePart) { *lpFilePart = PAL_wcsrchr(lpBuffer, '/'); if(NULL == *lpFilePart) { ASSERT("no '/' in full path!\n"); } else { /* point to character after last '/' */ (*lpFilePart)++; } } } } done: LOGEXIT("SearchPathW returns DWORD %u\n", nRet); PERF_EXIT(SearchPathW); return nRet; }