Example #1
0
/*++
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;
}
Example #2
0
 void
 SetString(
     const WCHAR *pwsz
     )
 {
     SetStringWithLength(pwsz, PAL_wcslen(pwsz));
 };
Example #3
0
File: pal.c Project: ArildF/masters
/*++
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;
}
Example #4
0
/*++
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;
}
Example #5
0
/*++
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;
}
Example #6
0
__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;
}
Example #7
0
__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;
}
Example #8
0
__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;
}
Example #9
0
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;
}
Example #10
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;
}
Example #11
0
/*++
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;
    }
}
Example #12
0
/*++

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;
}
Example #13
0
__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);
}
Example #14
0
/*++
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;
}
Example #15
0
/*++
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;
}
Example #16
0
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;
}
Example #17
0
/*++
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;
}
Example #18
0
/*++
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);
}