/*++ Function: FMTMSG_GetMessageString Returns the message as a wide string. --*/ static LPWSTR FMTMSG_GetMessageString( DWORD dwErrCode ) { LPWSTR lpRetVal = NULL; HSATELLITE hSatellite; TRACE( "Entered FMTMSG_GetMessageString\n" ); hSatellite = s_hSatellite; if ( hSatellite == NULL ) { hSatellite = FMTMSG_FormatMessageInit(); if ( !hSatellite ) { ASSERT( "Unable to continue due to missing library.\n" ); SetLastError( ERROR_INTERNAL_ERROR ); goto error; } } lpRetVal = (LPWSTR)LocalAlloc( LMEM_FIXED, (MAX_SAT_STRING_LENGTH + 1 ) * sizeof( WCHAR ) ); if ( lpRetVal ) { if ( ((*LoadSatelliteStringW)( hSatellite, dwErrCode, lpRetVal, MAX_SAT_STRING_LENGTH ) ) != 0 ) { /* Lets see if we can save memory here. */ UINT Length; LPWSTR temp; Length = PAL_wcslen( lpRetVal ) + 1; temp = LocalAlloc( LMEM_FIXED, Length * sizeof( WCHAR ) ); if ( temp ) { memcpy( temp, lpRetVal, Length*sizeof(WCHAR) ); LocalFree( lpRetVal ); lpRetVal = temp; } else { WARN( "Memory is running low. Continuing " "with original memory allocation.\n" ); } } else { ERROR( "LoadSatelliteStringW failed!\n" ); LocalFree( lpRetVal ); lpRetVal = NULL; } } else { ERROR( "Unable to allocate memory.\n" ); } error: return lpRetVal; }
void SetString( const WCHAR *pwsz ) { SetStringWithLength(pwsz, PAL_wcslen(pwsz)); };
/*++ 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: GetLongPathNameW See MSDN doc. Note: Since short path names are not implemented (nor supported) in the PAL, this function simply copies the given path into the new buffer. --*/ DWORD PALAPI GetLongPathNameW( IN LPCWSTR lpszShortPath, OUT LPWSTR lpszLongPath, IN DWORD cchBuffer) { DWORD dwPathLen = 0; PERF_ENTRY(GetLongPathNameW); ENTRY("GetLongPathNameW(lpszShortPath=%p (%S), lpszLongPath=%p (%S), " "cchBuffer=%d\n", lpszShortPath, lpszShortPath, lpszLongPath, lpszLongPath, cchBuffer); if ( !lpszShortPath ) { ERROR( "lpszShortPath was not a valid pointer.\n" ) SetLastError( ERROR_INVALID_PARAMETER ); LOGEXIT("GetLongPathNameW returns DWORD 0\n"); PERF_EXIT(GetLongPathNameW); return 0; } else if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW( lpszShortPath )) { // last error has been set by GetFileAttributes ERROR( "lpszShortPath does not exist.\n" ) LOGEXIT("GetLongPathNameW returns DWORD 0\n"); PERF_EXIT(GetLongPathNameW); return 0; } /* all lengths are # of TCHAR characters */ /* "required size" includes space for the terminating null character */ dwPathLen = PAL_wcslen(lpszShortPath)+1; /* lpszLongPath == 0 means caller is asking only for size */ if ( lpszLongPath ) { if ( dwPathLen > cchBuffer ) { ERROR("Buffer is too small, need %d characters\n", dwPathLen); SetLastError( ERROR_INSUFFICIENT_BUFFER ); } else { if ( lpszShortPath != lpszLongPath ) { // Note: MSDN doesn’t specify the behavior of GetLongPathName API // if the buffers are overlap. PAL_wcsncpy( lpszLongPath, lpszShortPath, cchBuffer ); } /* actual size not including terminating null is returned */ dwPathLen--; } } LOGEXIT("GetLongPathNameW returns DWORD %u\n", dwPathLen); PERF_EXIT(GetLongPathNameW); return dwPathLen; }
/*++ Function: RemoveDirectoryW See MSDN doc. --*/ BOOL PALAPI RemoveDirectoryW( IN LPCWSTR lpPathName) { PathCharString mb_dirPathString; int mb_size; DWORD dwLastError = 0; BOOL bRet = FALSE; size_t length; char * mb_dir = NULL; PERF_ENTRY(RemoveDirectoryW); ENTRY("RemoveDirectoryW(lpPathName=%p (%S))\n", lpPathName?lpPathName:W16_NULLSTRING, lpPathName?lpPathName:W16_NULLSTRING); if (lpPathName == NULL) { dwLastError = ERROR_PATH_NOT_FOUND; goto done; } length = (PAL_wcslen(lpPathName)+1) * 3; mb_dir = mb_dirPathString.OpenStringBuffer(length); if (NULL == mb_dir) { dwLastError = ERROR_NOT_ENOUGH_MEMORY; goto done; } mb_size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, mb_dir, length, NULL, NULL ); if( mb_size == 0 ) { mb_dirPathString.CloseBuffer(0); ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); dwLastError = ERROR_INTERNAL_ERROR; goto done; } mb_dirPathString.CloseBuffer(mb_size - 1); if ((bRet = RemoveDirectoryHelper (mb_dirPathString, &dwLastError))) { TRACE("Removal of directory [%s] was successful.\n", mb_dir); } done: if( dwLastError ) { SetLastError( dwLastError ); } LOGEXIT("RemoveDirectoryW returns BOOL %d\n", bRet); PERF_EXIT(RemoveDirectoryW); return bRet; }
__cdecl PAL_wcsncat( wchar_16 * strDest, const wchar_16 *strSource, size_t count ) { wchar_16 *start = strDest; UINT LoopCount = 0; UINT StrSourceLength = 0; PERF_ENTRY(wcsncat); ENTRY( "wcsncat (strDestination=%p (%S), strSource=%p (%S), count=%lu )\n", strDest ? strDest : W16_NULLSTRING, strDest ? strDest : W16_NULLSTRING, strSource ? strSource : W16_NULLSTRING, strSource ? strSource : W16_NULLSTRING, (unsigned long) count); if ( strDest == NULL ) { ERROR("invalid strDest argument\n"); LOGEXIT("wcsncat returning wchar_t NULL\n"); PERF_EXIT(wcsncat); return NULL; } if ( strSource == NULL ) { ERROR("invalid strSource argument\n"); LOGEXIT("wcsncat returning wchar_t NULL\n"); PERF_EXIT(wcsncat); return NULL; } /* find end of source string */ while ( *strDest ) { strDest++; } StrSourceLength = PAL_wcslen( strSource ); if ( StrSourceLength < count ) { count = StrSourceLength; } /* concatenate new string */ while( *strSource && LoopCount < count ) { *strDest++ = *strSource++; LoopCount++; } /* add terminating null */ *strDest = '\0'; LOGEXIT("wcsncat returning wchar_t %p (%S)\n", start, start); PERF_EXIT(wcsncat); return start; }
__cdecl PAL_wcsncpy( wchar_16 * strDest, const wchar_16 *strSource, size_t count ) { UINT length = sizeof( wchar_16 ) * count; ENTRY("wcsncpy( strDest:%p, strSource:%p (%S), count:%lu)\n", strDest, strSource, strSource, (unsigned long) count); memset( strDest, 0, length ); length = min( count, PAL_wcslen( strSource ) ) * sizeof( wchar_16 ); memcpy( strDest, strSource, length ); LOGEXIT("wcsncpy returning (wchar_16*): %p\n", strDest); return strDest; }
__cdecl PAL_wcscat( wchar_16 *strDestination, const wchar_16 *strSource) { wchar_16 *ret; ENTRY("wcscat (strDestination=%p (%S), strSource=%p (%S))\n", strDestination?strDestination:W16_NULLSTRING, strDestination?strDestination:W16_NULLSTRING, strSource?strSource:W16_NULLSTRING, strSource?strSource:W16_NULLSTRING); ret = PAL_wcsncat( strDestination, strSource, PAL_wcslen( strSource ) ); LOGEXIT("wcscat returnng wchar_t %p (%S)\n", ret, ret); return ret; }
int PALAPI GetDateFormatW( IN LCID Locale, IN DWORD dwFlags, IN CONST SYSTEMTIME *lpDate, IN LPCWSTR lpFormat, OUT LPWSTR lpDateStr, IN int cchDate) { LCID localeID = (LCID)0; WCHAR GG_string[] = {'g','g','\0'}; localeID = MAKELCID(GetSystemDefaultLangID(), SORT_DEFAULT); ENTRY("GetDateFormatW(Locale=%#x, dwFlags=%#x, lpDate=%p, lpFormat=%p (%S), " "lpDateStr=%p, cchDate=%d)\n", Locale, dwFlags, lpDate, lpFormat ? lpFormat : W16_NULLSTRING, lpFormat ? lpFormat : W16_NULLSTRING, lpDateStr, cchDate); /* The implementation of this function is not reqd as of now *as this is called only for CAL_TAIWAN Calendar and we are supporting *only CAL_GREGORIAN*/ if(((Locale == localeID) || (Locale == 0x0404)) && (dwFlags & DATE_USE_ALT_CALENDAR) && (lpDate == NULL) && lpFormat ? (PAL_wcsncmp(lpFormat, GG_string, PAL_wcslen(lpFormat)) == 0) : FALSE) { /*Need to make a call to strftime() with appropriate params when functionality to use alternate calendars is implemented */ ERROR("Not Implemented\n"); } else { ASSERT("One of the input parameters is invalid\n"); SetLastError(ERROR_INVALID_PARAMETER); } LOGEXIT ("GetDateFormatW returns int 0\n"); return 0; }
/*++ 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: CompareStringW See MSDN doc. --*/ int PALAPI CompareStringW( IN LCID Locale, IN DWORD dwCmpFlags, IN LPCWSTR lpString1, IN int cchCount1, IN LPCWSTR lpString2, IN int cchCount2) { INT nRetVal =0; /*return Value*/ INT nStrLen =0; ENTRY("CompareStringW(Locale=%#x, dwCmpFlags=%#x,lpString1 = %p (%S), " "cchCount1 =%d,lpString2 = %p (%S),cchCount2 =%d )\n", Locale, dwCmpFlags, lpString1, lpString1, cchCount1,lpString2,lpString2, cchCount2 ); if ( Locale != 0x0409 ) { ASSERT("Error Locale(%#x) parameter is invalid\n",Locale); SetLastError(ERROR_INVALID_PARAMETER); LOGEXIT ("CompareStringW returns int 0\n"); return 0; } if( dwCmpFlags != ( NORM_IGNORECASE | NORM_IGNOREWIDTH ) ) { ASSERT("Error dwCmpFlags(%#x) parameter is invalid\n",dwCmpFlags); SetLastError(ERROR_INVALID_PARAMETER); LOGEXIT ("CompareStringW returns int 0\n"); return 0; } if ( !lpString1 || !lpString2 ) { ERROR("One of the two params %p and %p is Invalid\n",lpString1,lpString2); SetLastError( ERROR_INVALID_PARAMETER ); LOGEXIT ("CompareStringW returns 0\n" ); return 0; } if(cchCount1 == 0 && cchCount2 == 0 ) { LOGEXIT ("CompareStringW returns int %d\n", CSTR_EQUAL ); return CSTR_EQUAL; } if ( cchCount1 == 0 ) { LOGEXIT ("CompareStringW returns int %d\n", CSTR_LESS_THAN ); return CSTR_LESS_THAN; } if ( cchCount2 == 0 ) { LOGEXIT ("CompareStringW returns int %d\n", CSTR_GREATER_THAN ); return CSTR_GREATER_THAN; } if( cchCount1 == -1) { cchCount1 = PAL_wcslen( lpString1 ); } if( cchCount2 == -1 ) { cchCount2 = PAL_wcslen( lpString2 ); } /*take the length of the smaller of the 2 strings*/ nStrLen = ( ( cchCount1 > cchCount2 ) ? cchCount2 : cchCount1 ); nRetVal = _wcsnicmp( lpString1, lpString2, nStrLen ); if(nRetVal ==0) { if(cchCount1>cchCount2) { nRetVal = 1; } else if (cchCount1 < cchCount2) { nRetVal = -1; } } if ( nRetVal == 0 ) { LOGEXIT ("CompareStringW returns int %d\n", CSTR_EQUAL ); return CSTR_EQUAL; } else if ( nRetVal > 0 ) { LOGEXIT ("CompareStringW returns int %d\n", CSTR_EQUAL ); return CSTR_GREATER_THAN; } else { LOGEXIT ("CompareStringW returns int %d\n", CSTR_LESS_THAN ); return CSTR_LESS_THAN; } }
/*++ Function: GetDiskFreeSpaceW See MSDN doc. --*/ PALIMPORT BOOL PALAPI GetDiskFreeSpaceW( LPCWSTR lpDirectoryName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, /* Caller will ignore output value */ LPDWORD lpTotalNumberOfClusters) /* Caller will ignore output value */ { BOOL bRetVal = FALSE; pal_statfs fsInfoBuffer; INT statfsRetVal = 0; DWORD dwLastError = NO_ERROR; CHAR DirNameBuffer[ MAX_LONGPATH ]; PERF_ENTRY(GetDiskFreeSpaceW); ENTRY( "GetDiskFreeSpaceW( lpDirectoryName=%p (%S), lpSectorsPerCluster=%p," "lpBytesPerSector=%p, lpNumberOfFreeClusters=%p, " "lpTotalNumberOfClusters=%p )\n", lpDirectoryName ? lpDirectoryName : W16_NULLSTRING, lpDirectoryName ? lpDirectoryName : W16_NULLSTRING, lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters ); /* Sanity checks. */ if ( !lpSectorsPerCluster ) { ERROR( "lpSectorsPerCluster cannot be NULL!\n" ); dwLastError = ERROR_INVALID_PARAMETER; goto exit; } if ( !lpBytesPerSector ) { ERROR( "lpBytesPerSector cannot be NULL!\n" ); dwLastError = ERROR_INVALID_PARAMETER; goto exit; } if ( lpNumberOfFreeClusters || lpTotalNumberOfClusters ) { TRACE("GetDiskFreeSpaceW is ignoring lpNumberOfFreeClusters" " and lpTotalNumberOfClusters\n" ); } if ( lpDirectoryName && PAL_wcslen( lpDirectoryName ) == 0 ) { ERROR( "lpDirectoryName is empty.\n" ); dwLastError = ERROR_INVALID_PARAMETER; goto exit; } /* Fusion uses this API to round file sizes up to their actual size on-disk based on the BytesPerSector * SectorsPerCluster. The intent is to avoid computing the sum of all file sizes in the cache just in bytes and not account for the cluster-sized slop, when determining if the cache is too large or not. */ if ( lpDirectoryName ) { if ( WideCharToMultiByte( CP_ACP, 0, lpDirectoryName, -1, DirNameBuffer,MAX_LONGPATH, 0, 0 ) != 0 ) { FILEDosToUnixPathA( DirNameBuffer ); statfsRetVal = statfs( DirNameBuffer, &fsInfoBuffer ); } else { ASSERT( "Unable to convert the lpDirectoryName to multibyte.\n" ); dwLastError = ERROR_INTERNAL_ERROR; goto exit; } } else { statfsRetVal = statfs( "/", &fsInfoBuffer ); } if ( statfsRetVal == 0 ) { *lpBytesPerSector = fsInfoBuffer.f_bsize; *lpSectorsPerCluster = 1; bRetVal = TRUE; } else { if ( errno == ENOTDIR || errno == ENOENT ) { FILEGetProperNotFoundError( DirNameBuffer, &dwLastError ); goto exit; } dwLastError = FILEGetLastErrorFromErrno(); if ( ERROR_INTERNAL_ERROR == dwLastError ) { ASSERT("statfs() not expected to fail with errno:%d (%s)\n", errno, strerror(errno)); } else { TRACE("statfs() failed, errno:%d (%s)\n", errno, strerror(errno)); } } exit: if ( NO_ERROR != dwLastError ) { SetLastError( dwLastError ); } LOGEXIT( "GetDiskFreeSpace returning %s.\n", bRetVal == TRUE ? "TRUE" : "FALSE" ); PERF_EXIT(GetDiskFreeSpaceW); return bRetVal; }
__cdecl PAL_wcstok(wchar_16 *strToken, const wchar_16 *strDelimit) { wchar_16 *retval = NULL; wchar_16 *delim_ptr; wchar_16 *next_context; /* string to save in TLS for future calls */ int ret; ENTRY("wcstok (strToken=%p (%S), strDelimit=%p (%S))\n", strToken?strToken:W16_NULLSTRING, strToken?strToken:W16_NULLSTRING, strDelimit?strDelimit:W16_NULLSTRING, strDelimit?strDelimit:W16_NULLSTRING); if(NULL == strDelimit) { ERROR("delimiter string is NULL\n"); goto done; } /* get token string from TLS if none is provided */ if(NULL == strToken) { TRACE("wcstok() called with NULL string, using previous string\n"); strToken = pthread_getspecific(wcstokKey); if(NULL == strToken) { ERROR("wcstok called with NULL string without a previous call\n"); goto done; } } /* first, skip all leading delimiters */ while(PAL_wcschr(strDelimit,*strToken)) { strToken++; } /* if there were only delimiters, there's no string */ if('\0' == strToken[0]) { TRACE("end of string already reached, returning NULL\n"); goto done; } /* we're now at the beginning of the token; look for the first delimiter */ delim_ptr = PAL_wcspbrk(strToken,strDelimit); if(NULL == delim_ptr) { TRACE("no delimiters found, this is the last token\n"); /* place the next context at the end of the string, so that subsequent calls will return NULL */ next_context = strToken+PAL_wcslen(strToken); retval = strToken; } else { /* null-terminate current token */ *delim_ptr=0; /* place the next context right after the delimiter */ next_context = delim_ptr+1; retval = strToken; TRACE("found delimiter; next token will be %p\n",next_context); } if ((ret = pthread_setspecific(wcstokKey, next_context)) != 0) { ERROR("pthread_setspecific() failed error:%d (%s)\n", ret, strerror(ret)); retval = NULL; } done: LOGEXIT("wcstok() returns %p (%S)\n", retval?retval:W16_NULLSTRING, retval?retval:W16_NULLSTRING); return(retval); }
/*++ 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; }
/*++ Function: SetCurrentDirectoryW See MSDN doc. --*/ BOOL PALAPI SetCurrentDirectoryW( IN LPCWSTR lpPathName) { BOOL bRet; DWORD dwLastError = 0; PathCharString dirPathString; int size; size_t length; char * dir; PERF_ENTRY(SetCurrentDirectoryW); ENTRY("SetCurrentDirectoryW(lpPathName=%p (%S))\n", lpPathName?lpPathName:W16_NULLSTRING, lpPathName?lpPathName:W16_NULLSTRING); /*check if the given path is null. If so return FALSE*/ if (lpPathName == NULL ) { ERROR("Invalid path/directory name\n"); dwLastError = ERROR_INVALID_NAME; bRet = FALSE; goto done; } length = (PAL_wcslen(lpPathName)+1) * 3; dir = dirPathString.OpenStringBuffer(length); if (NULL == dir) { dwLastError = ERROR_NOT_ENOUGH_MEMORY; bRet = FALSE; goto done; } size = WideCharToMultiByte( CP_ACP, 0, lpPathName, -1, dir, length, NULL, NULL ); dirPathString.CloseBuffer(size); if( size == 0 ) { dwLastError = GetLastError(); if( dwLastError == ERROR_INSUFFICIENT_BUFFER ) { WARN("lpPathName is larger than MAX_LONGPATH (%d)!\n", MAX_LONGPATH); dwLastError = ERROR_FILENAME_EXCED_RANGE; } else { ASSERT("WideCharToMultiByte failure! error is %d\n", dwLastError); dwLastError = ERROR_INTERNAL_ERROR; } bRet = FALSE; goto done; } bRet = SetCurrentDirectoryA(dir); done: if( dwLastError ) { SetLastError(dwLastError); } LOGEXIT("SetCurrentDirectoryW returns BOOL %d\n", bRet); PERF_EXIT(SetCurrentDirectoryW); return bRet; }
static LPWSTR FMTMSG_ProcessPrintf( wchar_t c , LPWSTR lpPrintfString, LPWSTR lpInsertString) { LPWSTR lpBuffer = NULL; LPWSTR lpBuffer2 = NULL; LPWSTR lpFormat = NULL; #if _DEBUG // small size for _DEBUG to exercise buffer reallocation logic int tmpSize = 4; #else int tmpSize = 64; #endif UINT nFormatLength = 0; int nBufferLength = 0; TRACE( "FMTMSG_ProcessPrintf( %C, %S, %S )\n", c, lpPrintfString, lpInsertString ); switch ( c ) { case 'e' : /* Fall through */ case 'E' : /* Fall through */ case 'f' : /* Fall through */ case 'g' : /* Fall through */ case 'G' : ERROR( "%%%c is not supported by FormatMessage.\n", c ); SetLastError( ERROR_INVALID_PARAMETER ); return NULL; } nFormatLength = PAL_wcslen( lpPrintfString ) + 2; /* Need to count % AND NULL */ lpFormat = (LPWSTR)PAL_malloc( nFormatLength * sizeof( WCHAR ) ); if ( !lpFormat ) { ERROR( "Unable to allocate memory.\n" ); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); return NULL; } /* Create the format string. */ memset( lpFormat, 0, nFormatLength * sizeof(WCHAR) ); *lpFormat = '%'; PAL_wcscat( lpFormat, lpPrintfString ); lpBuffer = (LPWSTR) PAL_malloc(tmpSize*sizeof(WCHAR)); /* try until the buffer is big enough */ while (TRUE) { if (!lpBuffer) { ERROR("Unable to allocate memory\n"); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); PAL_free(lpFormat); return NULL; } nBufferLength = _snwprintf_s( lpBuffer, tmpSize, tmpSize, lpFormat, lpInsertString); if ((nBufferLength >= 0) && (nBufferLength != tmpSize)) { break; /* succeeded */ } else { tmpSize *= 2; lpBuffer2 = static_cast<WCHAR *>( PAL_realloc(lpBuffer, tmpSize*sizeof(WCHAR))); if (lpBuffer2 == NULL) PAL_free(lpBuffer); lpBuffer = lpBuffer2; } } PAL_free( lpFormat ); lpFormat = NULL; return lpBuffer; }
/*++ Function: FormatMessageW See MSDN doc. --*/ DWORD PALAPI FormatMessageW( IN DWORD dwFlags, IN LPCVOID lpSource, IN DWORD dwMessageId, IN DWORD dwLanguageId, OUT LPWSTR lpBuffer, IN DWORD nSize, IN va_list *Arguments) { BOOL bIgnoreInserts = FALSE; BOOL bIsVaList = TRUE; BOOL bIsLocalAlloced = FALSE; LPWSTR lpSourceString = NULL; UINT nCount = 0; LPWSTR lpReturnString = NULL; LPWSTR lpWorkingString = NULL; PERF_ENTRY(FormatMessageW); ENTRY( "FormatMessageW(dwFlags=%#x, lpSource=%p, dwMessageId=%#x, " "dwLanguageId=%#x, lpBuffer=%p, nSize=%u, va_list=%p)\n", dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments); /* Sanity checks. */ if ( dwFlags & FORMAT_MESSAGE_FROM_STRING && !lpSource ) { /* This behavior is different then in Windows. Windows would just crash.*/ ERROR( "lpSource cannot be NULL.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( !(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER ) && !lpBuffer ) { /* This behavior is different then in Windows. Windows would just crash.*/ ERROR( "lpBuffer cannot be NULL, if " " FORMAT_MESSAGE_ALLOCATE_BUFFER is not specified.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( ( dwFlags & FORMAT_MESSAGE_FROM_STRING ) && ( dwFlags & FORMAT_MESSAGE_FROM_SYSTEM ) ) { ERROR( "These flags cannot co-exist. You can either " "specify FORMAT_MESSAGE_FROM_STRING, or " "FORMAT_MESSAGE_FROM_SYSTEM.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( !( dwFlags & FORMAT_MESSAGE_FROM_STRING ) && ( dwLanguageId != 0 #if ENABLE_DOWNLEVEL_FOR_NLS && dwLanguageId != MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ) #endif ) ) { ERROR( "Invalid language indentifier.\n" ); SetLastError( ERROR_RESOURCE_LANG_NOT_FOUND ); goto exit; } /* Parameter processing. */ if ( dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER ) { TRACE( "Allocated %d TCHARs. Don't forget to call LocalFree to " "free the memory when done.\n", nSize ); bIsLocalAlloced = TRUE; } if ( dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS ) { bIgnoreInserts = TRUE; } if ( dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY ) { if ( !Arguments && !bIgnoreInserts ) { ERROR( "The va_list cannot be NULL.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } else { bIsVaList = FALSE; } } if ( dwFlags & FORMAT_MESSAGE_FROM_STRING ) { lpSourceString = (LPWSTR)lpSource; } else if ( dwFlags & FORMAT_MESSAGE_FROM_SYSTEM ) { if ((dwMessageId & 0xFFFF0000) == 0x80070000) { // This message has been produced by HRESULT_FROM_WIN32. Undo its work. dwMessageId &= 0xFFFF; } lpWorkingString = lpReturnString = FMTMSG_GetMessageString( dwMessageId ); if ( !lpWorkingString ) { ERROR( "Unable to find the message %d.\n", dwMessageId ); SetLastError( ERROR_INTERNAL_ERROR ); nCount = 0; goto exit; } nCount = PAL_wcslen( lpWorkingString ); if ( !bIsLocalAlloced && nCount > nSize ) { ERROR( "Insufficient buffer.\n" ); SetLastError( ERROR_INSUFFICIENT_BUFFER ); lpWorkingString = NULL; nCount = 0; goto exit; } if ( !lpWorkingString ) { ERROR( "Invalid error indentifier.\n" ); SetLastError( ERROR_INVALID_ADDRESS ); } goto exit; } else { ERROR( "Unknown flag.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); goto exit; } if ( nSize == 0 && bIsLocalAlloced ) { nSize = 1; } lpWorkingString = static_cast<WCHAR *>( LocalAlloc( LMEM_FIXED, nSize * sizeof( WCHAR ) ) ); if ( !lpWorkingString ) { ERROR( "Unable to allocate memory for the working string.\n" ); SetLastError( ERROR_INSUFFICIENT_BUFFER ); goto exit; } /* Process the string. */ lpReturnString = lpWorkingString; while ( *lpSourceString ) { if ( *lpSourceString == '%' && !bIgnoreInserts ) { lpSourceString++; /* Escape sequences. */ if ( *lpSourceString == '0' ) { /* Terminates a message without a newline character. */ *lpWorkingString = '\0'; goto exit; } else if ( PAL_iswdigit( *lpSourceString ) ) { /* Get the insert number. */ WCHAR Number[] = { '\0', '\0', '\0' }; SIZE_T Index = 0; Number[ 0 ] = *lpSourceString; lpSourceString++; if ( PAL_iswdigit( *lpSourceString ) ) { Number[ 1 ] = *lpSourceString; lpSourceString++; if ( PAL_iswdigit( *lpSourceString ) ) { ERROR( "Invalid insert indentifier.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } } Index = FMTMSG__watoi( Number ); if ( Index == 0 ) { ERROR( "Invalid insert indentifier.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } if ( *lpSourceString == '!' ) { LPWSTR lpInsertString = NULL; LPWSTR lpPrintfString = NULL; LPWSTR lpStartOfFormattedString = NULL; UINT nPrintfLength = 0; LPWSTR lpFormattedString = NULL; UINT nFormattedLength = 0; if ( !bIsVaList ) { lpInsertString = (LPWSTR)Arguments[ Index - 1 ]; } else { va_list TheArgs; va_copy(TheArgs, *Arguments); UINT i = 0; for ( ; i < Index; i++ ) { lpInsertString = va_arg( TheArgs, LPWSTR ); } } /* Calculate the length, and extract the printf string.*/ lpSourceString++; { LPWSTR p = PAL_wcschr( lpSourceString, '!' ); if ( NULL == p ) { nPrintfLength = 0; } else { nPrintfLength = p - lpSourceString; } } lpPrintfString = (LPWSTR)PAL_malloc( ( nPrintfLength + 1 ) * sizeof( WCHAR ) ); if ( !lpPrintfString ) { ERROR( "Unable to allocate memory.\n" ); SetLastError( ERROR_NOT_ENOUGH_MEMORY ); lpWorkingString = NULL; nCount = 0; goto exit; } PAL_wcsncpy( lpPrintfString, lpSourceString, nPrintfLength ); *( lpPrintfString + nPrintfLength ) = '\0'; lpStartOfFormattedString = lpFormattedString = FMTMSG_ProcessPrintf( *lpPrintfString, lpPrintfString, lpInsertString); if ( !lpFormattedString ) { ERROR( "Unable to process the format string.\n" ); /* Function will set the error code. */ PAL_free( lpPrintfString ); lpWorkingString = NULL; goto exit; } nFormattedLength = PAL_wcslen( lpFormattedString ); /* Append the processed printf string into the working string */ while ( *lpFormattedString ) { _CHECKED_ADD_TO_STRING( *lpFormattedString ); lpFormattedString++; } lpSourceString += nPrintfLength + 1; PAL_free( lpPrintfString ); PAL_free( lpStartOfFormattedString ); lpPrintfString = lpFormattedString = NULL; } else { /* The printf format string defaults to 's'.*/ LPWSTR lpInsert = NULL; if ( !bIsVaList ) { lpInsert = (LPWSTR)Arguments[ Index - 1 ]; } else { va_list TheArgs; va_copy(TheArgs, *Arguments); UINT i = 0; for ( ; i < Index; i++ ) { lpInsert = va_arg( TheArgs, LPWSTR ); } } while ( *lpInsert ) { _CHECKED_ADD_TO_STRING( *lpInsert ); lpInsert++; } } } /* Format specifiers. */ else if ( *lpSourceString == '%' ) { _CHECKED_ADD_TO_STRING( '%' ); lpSourceString++; } else if ( *lpSourceString == 'n' ) { /* Hard line break. */ _CHECKED_ADD_TO_STRING( '\n' ); lpSourceString++; } else if ( *lpSourceString == '.' ) { _CHECKED_ADD_TO_STRING( '.' ); lpSourceString++; } else if ( *lpSourceString == '!' ) { _CHECKED_ADD_TO_STRING( '!' ); lpSourceString++; } else if ( !*lpSourceString ) { ERROR( "Invalid parameter.\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } else /* Append the character. */ { _CHECKED_ADD_TO_STRING( *lpSourceString ); lpSourceString++; } }/* END if ( *lpSourceString == '%' ) */ else { /* In Windows if FormatMessage is called with ignore inserts, then FormatMessage strips %1!s! down to %1, since string is the default. */ if ( bIgnoreInserts && *lpSourceString == '!' && *( lpSourceString + 1 ) == 's' ) { LPWSTR lpLastBang = PAL_wcschr( lpSourceString + 1, '!' ); if ( lpLastBang && ( 2 == lpLastBang - lpSourceString ) ) { lpSourceString = lpLastBang + 1; } else { ERROR( "Mal-formed string\n" ); SetLastError( ERROR_INVALID_PARAMETER ); lpWorkingString = NULL; nCount = 0; goto exit; } } else { /* Append to the string. */ _CHECKED_ADD_TO_STRING( *lpSourceString ); lpSourceString++; } } } /* Terminate the message. */ _CHECKED_ADD_TO_STRING( '\0' ); /* NULL does not count. */ nCount--; exit: /* Function clean-up and exit. */ if ( lpWorkingString ) { if ( bIsLocalAlloced ) { TRACE( "Assigning the buffer to the pointer.\n" ); // when FORMAT_MESSAGE_ALLOCATE_BUFFER is specified, nSize // does not specify the size of lpBuffer, rather it specifies // the minimum size of the string // as such we have to blindly assume that lpBuffer has enough space to // store PVOID // might cause a prefast warning, but there is no good way to suppress it yet _ASSERTE(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER); *((LPVOID*)lpBuffer) = (LPVOID)lpReturnString; } else /* Only delete lpReturnString if the caller has their own buffer.*/ { TRACE( "Copying the string into the buffer.\n" ); PAL_wcsncpy( lpBuffer, lpReturnString, nCount + 1 ); LocalFree( lpReturnString ); } } else /* Error, something occured. */ { if ( lpReturnString ) { LocalFree( lpReturnString ); } } LOGEXIT( "FormatMessageW returns %d.\n", nCount ); PERF_EXIT(FormatMessageW); return nCount; }
/*++ Function: FileDosToUnixPathW Abstract: Change a DOS path to a Unix path. Replaces '\' by '/', removes any trailing dots on directory/filenames, and changes '*.*' to be equal to '*' Parameter: IN/OUT lpPath: path to be modified --*/ void FILEDosToUnixPathW( LPWSTR lpPath) { LPWSTR p; LPWSTR pPointAtDot=NULL; WCHAR charBeforeFirstDot='\0'; TRACE("Original DOS path = [%S]\n", lpPath); if (!lpPath) { return; } for (p = lpPath; *p; p++) { /* Make the \\ to / switch first */ if (*p == '\\') { /* Replace \ with / */ *p = '/'; } if (pPointAtDot) { /* If pPointAtDot is not NULL, it is pointing at the first encountered dot. If we encountered a \, that means it could be a trailing dot */ if (*p == '/') { /* If char before the first dot is a '\' or '.' (special case if the dot is the first char in the path) , then we leave it alone, because it is either . or .., otherwise it is a trailing dot pattern and will be truncated */ if (charBeforeFirstDot != '.' && charBeforeFirstDot != '/') { memmove(pPointAtDot,p,((PAL_wcslen(p)+1)*sizeof(WCHAR))); p = pPointAtDot; } pPointAtDot = NULL; /* Need to reset this */ } else if (*p == '*') { /* Check our size before doing anything with our pointers */ if ((p - lpPath) >= 3) { /* At this point, we know that there is 1 or more dots and then a star. AND we know the size of our string at this point is at least 3 (so we can go backwards from our pointer safely AND there could possilby be two characters back) So lets check if there is a '*' and a '.' before, if there is, replace just a '*'. Otherwise, reset pPointAtDot to NULL and do nothing */ if (p[-2] == '*' && p[-1] == '.' && p[0] == '*') { memmove(&(p[-2]),p,(PAL_wcslen(p)*sizeof(WCHAR))); } pPointAtDot = NULL; } } else if (*p != '.') { /* If we are here, that means that this is NOT a trailing dot, some other character is here, so forget our pointer */ pPointAtDot = NULL; } } else { if (*p == '.') { /* If pPointAtDot is NULL, and we encounter a dot, save the pointer */ pPointAtDot = p; if (pPointAtDot != lpPath) { charBeforeFirstDot = p[-1]; } else { charBeforeFirstDot = lpPath[0]; } } } } /* If pPointAtDot still points at anything, then we still have trailing dots. Truncate at pPointAtDot, unless the dots are path specifiers (. or ..) */ if (pPointAtDot) { /* make sure the trailing dots don't follow a '/', and that they aren't the only thing in the name */ if(pPointAtDot != lpPath && *(pPointAtDot-1) != '/') { *pPointAtDot = '\0'; } } TRACE("Resulting Unix path = [%S]\n", lpPath); }