Example #1
0
/*++
Function:
  PAL_HasEntered

Abstract:
  This function can be called to determine if the thread has entered the
  PAL through PAL_Enter or related calls.
--*/
BOOL
PALAPI
PAL_HasEntered()
{
    ENTRY_EXTERNAL("PAL_HasEntered()\n");

    CPalThread *pThread = GetCurrentPalThread();
    if (pThread == NULL)
    {
        ASSERT("PAL_Reenter called on a thread unknown to this PAL\n");
    }

    LOGEXIT("PAL_HasEntered returned\n");
    
    return pThread->IsInPal();
}
Example #2
0
HANDLE
PALAPI
CreateMutexA(
    IN LPSECURITY_ATTRIBUTES lpMutexAttributes,
    IN BOOL bInitialOwner,
    IN LPCSTR lpName)
{
    HANDLE hMutex = NULL;
    CPalThread *pthr = NULL;
    PAL_ERROR palError;
    
    PERF_ENTRY(CreateMutexA);
    ENTRY("CreateMutexA(lpMutexAttr=%p, bInitialOwner=%d, lpName=%p (%s)\n",
          lpMutexAttributes, bInitialOwner, lpName, lpName?lpName:"NULL");

    pthr = InternalGetCurrentThread();
    
    if (lpName != nullptr)
    {
        ASSERT("lpName: Cross-process named objects are not supported in PAL");
        palError = ERROR_NOT_SUPPORTED;
    }
    else
    {
        palError = InternalCreateMutex(
            pthr,
            lpMutexAttributes,
            bInitialOwner,
            NULL,
            &hMutex
            );
    }

    //
    // We always need to set last error, even on success:
    // we need to protect ourselves from the situation
    // where last error is set to ERROR_ALREADY_EXISTS on
    // entry to the function
    //

    pthr->SetLastError(palError);
    
    LOGEXIT("CreateMutexA returns HANDLE %p\n", hMutex);
    PERF_EXIT(CreateMutexA);
    return hMutex;
}
Example #3
0
HANDLE
PALAPI
OpenSemaphoreW(
       IN DWORD dwDesiredAccess,
       IN BOOL bInheritHandle,
       IN LPCWSTR lpName)
{
    HANDLE hSemaphore = NULL;
    PAL_ERROR palError = NO_ERROR;
    CPalThread *pthr = NULL;

    PERF_ENTRY(OpenSemaphoreW);
    ENTRY("OpenSemaphoreW(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%S))\n", 
          dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:W16_NULLSTRING);

    pthr = InternalGetCurrentThread();

    /* validate parameters */
    if (lpName == NULL)
    {
        ERROR("lpName is NULL\n");
        palError = ERROR_INVALID_PARAMETER;
        goto OpenSemaphoreWExit;            
    }

    palError = InternalOpenSemaphore(
        pthr,
        dwDesiredAccess,
        bInheritHandle,
        lpName,
        &hSemaphore
        );

OpenSemaphoreWExit:

    if (NO_ERROR != palError)
    {
        pthr->SetLastError(palError);
    }

    LOGEXIT("OpenSemaphoreW returns HANDLE %p\n", hSemaphore);
    PERF_EXIT(OpenSemaphoreW);

    return hSemaphore;
}
Example #4
0
/*++
Function:
  PAL_Reenter

Abstract:
  This function needs to be called on a thread when it enters
  a region of code that depends on this instance of the PAL
  in the process, and the current thread is already known to
  the PAL.

  NOTE: This function must not modify LastError.
--*/
VOID
PALAPI
PAL_Reenter(PAL_Boundary boundary)
{
    ENTRY_EXTERNAL("PAL_Reenter(boundary=%u)\n", boundary);

    CPalThread *pThread = GetCurrentPalThread();
    if (pThread == NULL)
    {
        ASSERT("PAL_Reenter called on a thread unknown to this PAL\n");
    }

    // We ignore the return code.  This call should only fail on internal
    // error, and we assert at the actual failure.
    pThread->Enter(boundary);

    LOGEXIT("PAL_Reenter returns\n");
}
Example #5
0
PAL_ERROR
AllocatePalThread(CPalThread **ppThread)
{
    CPalThread *pThread = NULL;
    PAL_ERROR palError;

#if !HAVE_MACH_EXCEPTIONS
    // Ensure alternate stack for SIGSEGV handling. Our SIGSEGV handler is set to
    // run on an alternate stack and the stack needs to be allocated per thread.
    if (!EnsureSignalAlternateStack())
    {
        ERROR("Cannot allocate alternate stack for SIGSEGV handler!\n");
        palError = ERROR_NOT_ENOUGH_MEMORY;
        goto exit;
    }
#endif // !HAVE_MACH_EXCEPTIONS

    palError = CreateThreadData(&pThread);
    if (NO_ERROR != palError)
    {
        goto exit;
    }

    HANDLE hThread;
    palError = CreateThreadObject(pThread, pThread, &hThread);
    if (NO_ERROR != palError)
    {
        pthread_setspecific(thObjKey, NULL);
        pThread->ReleaseThreadReference();
        goto exit;
    }
    
    // Like CreateInitialProcessAndThreadObjects, we do not need this 
    // thread handle, since we're not returning it to anyone who will 
    // possibly release it.
    (void)g_pObjectManager->RevokeHandle(pThread, hThread);

    PROCAddThread(pThread, pThread);

exit:
    *ppThread = pThread;
    return palError;
}
Example #6
0
HANDLE
PALAPI
CreateSemaphoreW(
         IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
         IN LONG lInitialCount,
         IN LONG lMaximumCount,
         IN LPCWSTR lpName)
{
    HANDLE hSemaphore = NULL;
    PAL_ERROR palError;
    CPalThread *pthr = NULL;

    PERF_ENTRY(CreateSemaphoreW);
    ENTRY("CreateSemaphoreW(lpSemaphoreAttributes=%p, lInitialCount=%d, "
          "lMaximumCount=%d, lpName=%p (%S))\n",
          lpSemaphoreAttributes, lInitialCount, lMaximumCount, 
          lpName, lpName?lpName:W16_NULLSTRING);

    pthr = InternalGetCurrentThread();

    palError = InternalCreateSemaphore(
        pthr,
        lpSemaphoreAttributes, 
        lInitialCount,
        lMaximumCount,
        lpName,
        &hSemaphore
        );

    //
    // We always need to set last error, even on success:
    // we need to protect ourselves from the situation
    // where last error is set to ERROR_ALREADY_EXISTS on
    // entry to the function
    //

    pthr->SetLastError(palError);

    LOGEXIT("CreateSemaphoreW returns HANDLE %p\n", hSemaphore);
    PERF_EXIT(CreateSemaphoreW);
    return hSemaphore;
}
Example #7
0
/*++
Function:
  Sleep

See MSDN doc.
--*/
VOID
PALAPI
Sleep(IN DWORD dwMilliseconds)
{
    PERF_ENTRY(Sleep);
    ENTRY("Sleep(dwMilliseconds=%u)\n", dwMilliseconds);

    CPalThread * pThread = InternalGetCurrentThread();

    DWORD internalSleepRet = InternalSleepEx(pThread, dwMilliseconds, FALSE);

    if (internalSleepRet != 0)
    {
        ERROR("Sleep(dwMilliseconds=%u) failed [error=%u]\n", dwMilliseconds, internalSleepRet);
        pThread->SetLastError(internalSleepRet);
    }

    LOGEXIT("Sleep returns VOID\n");
    PERF_EXIT(Sleep);
}
Example #8
0
/*++
Function:
  CheckPalThread

Abstract:
  This function is called by the ENTRY macro to validate consistency:
  Whenever a PAL function is called, that thread must have previously
  registered the fact that it is currently executing code that depends
  on this PAL by means of PAL_ReverseEnter or PAL_Enter.
--*/
extern "C" void CheckPalThread()
{
    if (PALIsInitialized())
    {
        CPalThread *pThread = InternalGetCurrentThread();
        if (!pThread)
        {
            ASSERT("PAL function called on a thread unknown to this PAL\n");
        }
        else if (!pThread->IsInPal())
        {
            // There are several outstanding issues where we are not maintaining
            // correct in- vs. out-of-thePAL state. With the advent of 
            // single registration of Mach EH handling per thread, there's no
            // need to actually be in the PAL any more, and so the following
            // is being made into a warning, and we'll deprecate the 
            // entire concept later.
            WARN("PAL function called on a thread external to this PAL\n");
        }
    }
}
Example #9
0
HANDLE
PALAPI
OpenSemaphoreW(
       IN DWORD dwDesiredAccess,
       IN BOOL bInheritHandle,
       IN LPCWSTR lpName)
{
    HANDLE hSemaphore = NULL;
    PAL_ERROR palError = NO_ERROR;
    CPalThread *pthr = NULL;

    PERF_ENTRY(OpenSemaphoreW);
    ENTRY("OpenSemaphoreW(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%S))\n", 
          dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:W16_NULLSTRING);

    pthr = InternalGetCurrentThread();

    /* validate parameters */
    if (lpName == nullptr)
    {
        ERROR("lpName is NULL\n");
        palError = ERROR_INVALID_PARAMETER;
    }
    else
    {
        ASSERT("lpName: Cross-process named objects are not supported in PAL");
        palError = ERROR_NOT_SUPPORTED;
    }

    if (NO_ERROR != palError)
    {
        pthr->SetLastError(palError);
    }

    LOGEXIT("OpenSemaphoreW returns HANDLE %p\n", hSemaphore);
    PERF_EXIT(OpenSemaphoreW);

    return hSemaphore;
}
Example #10
0
HANDLE
PALAPI
CreateMutexW(
    IN LPSECURITY_ATTRIBUTES lpMutexAttributes,
    IN BOOL bInitialOwner,
    IN LPCWSTR lpName)
{
    HANDLE hMutex = NULL;
    PAL_ERROR palError;
    CPalThread *pthr = NULL;

    PERF_ENTRY(CreateMutexW);
    ENTRY("CreateMutexW(lpMutexAttr=%p, bInitialOwner=%d, lpName=%p (%S)\n",
          lpMutexAttributes, bInitialOwner, lpName, lpName?lpName:W16_NULLSTRING);

    pthr = InternalGetCurrentThread();

    palError = InternalCreateMutex(
        pthr,
        lpMutexAttributes,
        bInitialOwner,
        lpName,
        &hMutex
        );

    //
    // We always need to set last error, even on success:
    // we need to protect ourselves from the situation
    // where last error is set to ERROR_ALREADY_EXISTS on
    // entry to the function
    //

    pthr->SetLastError(palError);

    LOGEXIT("CreateMutexW returns HANDLE %p\n", hMutex);
    PERF_EXIT(CreateMutexW);
    return hMutex;
}
Example #11
0
BOOL
PALAPI
ReleaseMutex( IN HANDLE hMutex )
{
    PAL_ERROR palError = NO_ERROR;
    CPalThread *pthr = NULL;
    
    PERF_ENTRY(ReleaseMutex);
    ENTRY("ReleaseMutex(hMutex=%p)\n", hMutex);

    pthr = InternalGetCurrentThread();
    
    palError = InternalReleaseMutex(pthr, hMutex);

    if (NO_ERROR != palError)
    {
        pthr->SetLastError(palError);
    }

    LOGEXIT("ReleaseMutex returns BOOL %d\n", (NO_ERROR == palError));
    PERF_EXIT(ReleaseMutex);
    return (NO_ERROR == palError);
}
Example #12
0
HANDLE
PALAPI
OpenMutexA (
       IN DWORD dwDesiredAccess,
       IN BOOL bInheritHandle,
       IN LPCSTR lpName)
{
    HANDLE hMutex = NULL;
    CPalThread *pthr = NULL;
    PAL_ERROR palError;
    
    PERF_ENTRY(OpenMutexA);
    ENTRY("OpenMutexA(dwDesiredAccess=%#x, bInheritHandle=%d, lpName=%p (%s))\n", 
          dwDesiredAccess, bInheritHandle, lpName, lpName?lpName:"NULL");

    pthr = InternalGetCurrentThread();

    /* validate parameters */
    if (lpName == nullptr)
    {
        ERROR("name is NULL\n");
        palError = ERROR_INVALID_PARAMETER;
        goto OpenMutexAExit;
    }

    palError = InternalOpenMutex(pthr, dwDesiredAccess, bInheritHandle, lpName, &hMutex);

OpenMutexAExit:
    if (NO_ERROR != palError)
    {
        pthr->SetLastError(palError);
    }
        
    LOGEXIT("OpenMutexA returns HANDLE %p\n", hMutex);
    PERF_EXIT(OpenMutexA);
    return hMutex;
}
Example #13
0
/*++
Function:
  GetThreadContext

See MSDN doc.
--*/
BOOL
PALAPI
GetThreadContext(
           IN HANDLE hThread,
           IN OUT LPCONTEXT lpContext)
{
    PAL_ERROR palError;
    CPalThread *pThread;
    CPalThread *pTargetThread;
    IPalObject *pobjThread = NULL;
    BOOL ret = FALSE;
    
    PERF_ENTRY(GetThreadContext);
    ENTRY("GetThreadContext (hThread=%p, lpContext=%p)\n",hThread,lpContext);

    pThread = InternalGetCurrentThread();

    palError = InternalGetThreadDataFromHandle(
        pThread,
        hThread,
        0, // THREAD_GET_CONTEXT
        &pTargetThread,
        &pobjThread
        );

    if (NO_ERROR == palError)
    {
        if (!pTargetThread->IsDummy())
        {
            ret = CONTEXT_GetThreadContext(
                GetCurrentProcessId(),
                pTargetThread->GetPThreadSelf(),
                lpContext
                );
        }
        else
        {
            ASSERT("Dummy thread handle passed to GetThreadContext\n");
            pThread->SetLastError(ERROR_INVALID_HANDLE);
        }
    }
    else
    {
        pThread->SetLastError(palError);
    }

    if (NULL != pobjThread)
    {
        pobjThread->ReleaseReference(pThread);
    }
    
    LOGEXIT("GetThreadContext returns ret:%d\n", ret);
    PERF_EXIT(GetThreadContext);
    return ret;
}
Example #14
0
bool CatchHardwareExceptionHolder::IsEnabled()
{
    CPalThread *pThread = InternalGetCurrentThread();
    return pThread->IsHardwareExceptionsEnabled();
}
Example #15
0
/*++
Function:
    GetComputerNameW

Uses gethostname to get the computer name. See MSDN for functional spec.

--*/
PALIMPORT
BOOL
PALAPI
GetComputerNameW(
    OUT LPWSTR lpBuffer, // address of name buffer
    IN OUT LPDWORD nSize)    // address of size of name buffer
{
    BOOL fRet = FALSE;
    char szHostName[MAXHOSTNAMELEN+1];
    char *pchDot = NULL;
    DWORD cwchLen = 0;
    CPalThread *pPalThread = InternalGetCurrentThread();

    PERF_ENTRY(GetComputerNameW);
    ENTRY("GetComputerNameW(lpBuffer = %p, nSize = %p (%d)\n",
          lpBuffer, nSize, nSize?*nSize:0);

    if (NULL == lpBuffer || NULL == nSize)
    {
        ERROR("lpBuffer == NULL or nSize == NULL");
        pPalThread->SetLastError(ERROR_INVALID_PARAMETER);
        goto done;
    }

    if (0 != gethostname(szHostName, sizeof(szHostName)/sizeof(szHostName[0])))
    {
        ERROR("gethostname failed with error (%d) %s\n", errno, strerror(errno));
        pPalThread->SetLastError(ERROR_INTERNAL_ERROR);
        goto done;
    }

    // Null terminate the string
    szHostName[sizeof(szHostName)/sizeof(szHostName[0])-1] = '\0';

    // some OSes return the hostname with the domain name included.
    // We want to return only the host part of the name (see the spec for
    // more details
    pchDot = strchr(szHostName, '.');
    if (NULL != pchDot)
    {
        *pchDot = '\0'; // remove the domain name info
    }

    // clip the hostname to MAX_COMPUTERNAME_LENGTH
    if (sizeof(szHostName) > MAX_COMPUTERNAME_LENGTH)
    {
        szHostName[MAX_COMPUTERNAME_LENGTH] = '\0';
    }

    // copy the hostname (including NULL character)
    cwchLen = MultiByteToWideChar(CP_ACP, 0, szHostName, -1, lpBuffer, *nSize);
    if (0 == cwchLen) 
    {
        ERROR ("MultiByteToWideChar failed with error %d when trying to convert the hostname "
                "%s to wide char\n", pPalThread->GetLastError(), szHostName);
        if (ERROR_INSUFFICIENT_BUFFER == pPalThread->GetLastError())
        {
            // Find the required size (including NULL)
            cwchLen = MultiByteToWideChar(CP_ACP, 0, szHostName, -1, NULL, 0);
            if (0 == cwchLen)
            {
                ERROR ("MultiByteToWideChar failed with error %d when trying to find the size of "
                       "%s in wide chars\n", pPalThread->GetLastError(), szHostName);
                pPalThread->SetLastError(ERROR_INTERNAL_ERROR);
            }
            else
            {
                // Update the required size
                *nSize = cwchLen - 1; // don't include the NULL
                pPalThread->SetLastError(ERROR_BUFFER_OVERFLOW);
            }
        }
        goto done;
    }

    *nSize = cwchLen - 1; // don't include the NULL
    fRet = TRUE;

done:
    LOGEXIT("GetComputerNameW returning BOOL %d\n", fRet);
    PERF_EXIT(GetComputerNameW);
    return fRet;
}
Example #16
0
/*++
Function:
    GetUserNameW

Uses getpwuid_r to get the user name and if it's not available uses
getpwuid (with the safety of a critical section). See MSDN for functional spec.

--*/
PALIMPORT
BOOL
PALAPI
GetUserNameW(
    OUT LPWSTR lpBuffer, // address of name buffer
    IN OUT LPDWORD nSize )    // address of size of name buffer
{
    BOOL fRet = FALSE;
    struct passwd *pPasswd = NULL;
    char *szUserName = NULL;
    DWORD cwchLen = 0;
    int iEuid = -1;
    int iRet = -1;
    CPalThread *pPalThread = InternalGetCurrentThread();

#if HAVE_GETPWUID_R
    
    char *pchBuffer = NULL;
    DWORD dwBufLen = 0;
    struct passwd sPasswd;
    
#endif // HAVE_GETPWUID_R

    PERF_ENTRY(GetUserNameW);
    ENTRY("GetUserNameW(lpBuffer = %p, nSize = %p (%d)\n",
          lpBuffer, nSize, nSize?*nSize:0);

    iEuid = geteuid();

    if (NULL == lpBuffer || NULL == nSize)
    {
        ERROR("lpBuffer == NULL or nSize == NULL");
        pPalThread->SetLastError(ERROR_INVALID_PARAMETER);
        goto done;
    }

#if HAVE_GETPWUID_R

    dwBufLen = dwInitialPasswdBufferSize;

    while (NULL == pPasswd)
    {
        pchBuffer = (char*) InternalMalloc(pPalThread, sizeof(pchBuffer[0]) * dwBufLen);
        if (NULL == pchBuffer)
        {
            pPalThread->SetLastError(ERROR_OUTOFMEMORY);
            goto done;
        }

        iRet = InternalGetpwuid_r(pPalThread, iEuid, &sPasswd, pchBuffer, dwBufLen, &pPasswd);
        if (0 != iRet)
        {
            WARN("getpwuid_r(%d) returns %d for a buffer size of %d, error string is %s\n", 
                        iEuid, iRet, dwBufLen, strerror(iRet));

            if (ERANGE == iRet) // need a bigger buffer
            {
                InternalFree(pPalThread, pchBuffer);
                pchBuffer = NULL;
                pPasswd = NULL;
                dwBufLen *= 2; // double the buffer
                continue; // try again
            }

            pPalThread->SetLastError(ERROR_INTERNAL_ERROR);
            goto done;
        }

        // Unfortunately, HPUX returns success and result = NULL even when the buffer size is small
        // (instead of returning ERANGE error). But, since we are using either
        // sysconf(_SC_GETPW_R_SIZE_MAX) or the HP recommended value of 1024, buffer should always
        // be big enough for getpwuid_r.

        if (NULL == pPasswd || NULL == pPasswd->pw_name)
        {
            // No matching entry found! something failed somewhere.
            ERROR("getpwuid_r(%d) returned %p with name NULL!\n", iEuid, pPasswd);
            pPalThread->SetLastError(ERROR_INTERNAL_ERROR);
            goto done;
        }
    }

    szUserName = pPasswd->pw_name;

#else // HAVE_GETPWUID_R

    InternalEnterCriticalSection(pPalThread, &identity_critsec);
    pPasswd = getpwuid(iEuid);

    if ((NULL == pPasswd) || (NULL == pPasswd->pw_name))
    {
        InternalLeaveCriticalSection(pPalThread, &identity_critsec);
        ERROR("getpwuid(%d) returned %p with name NULL! error (%d) is %s\n",
                iEuid, pPasswd, errno, strerror(errno));
        pPalThread->SetLastError(ERROR_INTERNAL_ERROR);
        goto done;
    }

    // make a copy so that we can modify it
    szUserName = InternalStrdup(pPalThread, pPasswd->pw_name);
    if (NULL == szUserName)
    {
        InternalLeaveCriticalSection(pPalThread, &identity_critsec);
        pPalThread->SetLastError(ERROR_OUTOFMEMORY);
        goto done;
    }

    InternalLeaveCriticalSection(pPalThread, &identity_critsec);
#endif // HAVE_GETPWUID_R

    // truncate the user name if it exceeds the maximum allowed limit
    if (strlen(szUserName) > UNLEN)
    {
        szUserName[UNLEN] = '\0';
    }

    // Copy from pPasswd->pw_name
    cwchLen = MultiByteToWideChar(CP_ACP, 0, szUserName, -1, lpBuffer, *nSize);
    if (0 == cwchLen)
    {
        ERROR ("MultiByteToWideChar failed with error %d when trying to convert the username "
               "%s to wide char\n", pPalThread->GetLastError(), szUserName);
        if (ERROR_INSUFFICIENT_BUFFER == pPalThread->GetLastError())
        {
            // Find the required size (including NULL)
            cwchLen = MultiByteToWideChar(CP_ACP, 0, szUserName, -1, NULL, 0);
            if (0 == cwchLen)
            {
                ERROR ("MultiByteToWideChar failed with error %d when trying to find the size of "
                       "%s in wide chars\n", pPalThread->GetLastError(), szUserName);
                pPalThread->SetLastError(ERROR_INTERNAL_ERROR);
            }
            else
            {
                // Update the required size
                *nSize = cwchLen;
                pPalThread->SetLastError(ERROR_MORE_DATA);
            }
        }
        goto done;
    }

    *nSize = cwchLen;
    fRet = TRUE;

done:
#if HAVE_GETPWUID_R
    if (NULL != pchBuffer)
    {
        InternalFree(pPalThread, pchBuffer);
    }
#else // HAVE_GETPWUID_R
    if (NULL != szUserName)
    {
        InternalFree(pPalThread, szUserName);
    }
#endif // HAVE_GETPWUID_R

    LOGEXIT("GetUserNameW returning BOOL %d\n", fRet);
    PERF_EXIT(GetUserNameW);
    return fRet;
}
Example #17
0
HANDLE
PALAPI
CreateSemaphoreA(
         IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
         IN LONG lInitialCount,
         IN LONG lMaximumCount,
         IN LPCSTR lpName)
{
    HANDLE hSemaphore = NULL;
    WCHAR pwName[c_cchMaxSemaphore];
    CPalThread *pthr = NULL;
    PAL_ERROR palError;

    PERF_ENTRY(CreateSemaphoreA);
    ENTRY("CreateSemaphoreA(lpSemaphoreAttributes=%p, lInitialCount=%d, "
          "lMaximumCount=%d, lpName=%p (%s))\n",
          lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName, lpName?lpName:"NULL");

    pthr = InternalGetCurrentThread();
    
    if (lpName != NULL)
    {
        palError = InternalWszNameFromSzName(
            pthr,
            lpName,
            pwName,
            sizeof(pwName) / sizeof(pwName[0])
            );

        if (NO_ERROR != palError)
        {
            goto CreateSemaphoreAExit;
        }

        palError = InternalCreateSemaphore(
            pthr,
            lpSemaphoreAttributes,
            lInitialCount,
            lMaximumCount,
            pwName,
            &hSemaphore
            );
    }
    else
    {
        palError = InternalCreateSemaphore(
            pthr,
            lpSemaphoreAttributes,
            lInitialCount,
            lMaximumCount,
            NULL,
            &hSemaphore
            );
    }

CreateSemaphoreAExit:
    
    //
    // We always need to set last error, even on success:
    // we need to protect ourselves from the situation
    // where last error is set to ERROR_ALREADY_EXISTS on
    // entry to the function
    //

    pthr->SetLastError(palError);
    
    LOGEXIT("CreateSemaphoreA returns HANDLE %p\n", hSemaphore);
    PERF_EXIT(CreateSemaphoreA);
    return hSemaphore;
}
Example #18
0
DWORD
PAL_DeleteExecWatchpoint(
    HANDLE hThread,
    PVOID pvInstruction
    )
{
    PERF_ENTRY(PAL_DeleteExecWatchpoint);
    ENTRY("PAL_DeleteExecWatchpoint (hThread=%p, pvInstruction=%p)\n", hThread, pvInstruction);

    DWORD dwError = ERROR_NOT_SUPPORTED;

#if HAVE_PRWATCH_T

    CPalThread *pThread = NULL;
    CPalThread *pTargetThread = NULL;
    IPalObject *pobjThread = NULL;
    int fd = -1;
    char ctlPath[50];

    struct
    {
        long ctlCode;
        prwatch_t prwatch;
    } ctlStruct;


    pThread = InternalGetCurrentThread();

    dwError = InternalGetThreadDataFromHandle(
        pThread,
        hThread,
        0, // THREAD_SET_CONTEXT
        &pTargetThread,
        &pobjThread
        );

    if (NO_ERROR != dwError)
    {
        goto PAL_DeleteExecWatchpointExit;
    }

    snprintf(ctlPath, sizeof(ctlPath), "/proc/%u/lwp/%u/lwpctl", getpid(), pTargetThread->GetLwpId());

    fd = InternalOpen(pThread, ctlPath, O_WRONLY);
    if (-1 == fd)
    {
        ERROR("Failed to open %s\n", ctlPath);
        dwError = ERROR_INVALID_ACCESS;
        goto PAL_DeleteExecWatchpointExit;
    }

    ctlStruct.ctlCode = PCWATCH;
    ctlStruct.prwatch.pr_vaddr = (uintptr_t) pvInstruction;
    ctlStruct.prwatch.pr_size = sizeof(DWORD);
    ctlStruct.prwatch.pr_wflags = 0;

    if (write(fd, (void*) &ctlStruct, sizeof(ctlStruct)) != sizeof(ctlStruct))
    {
        ERROR("Failure writing control structure (errno = %u)\n", errno);
        dwError = ERROR_INTERNAL_ERROR;
        goto PAL_DeleteExecWatchpointExit;
    }

    dwError = ERROR_SUCCESS;
    
PAL_DeleteExecWatchpointExit:

    if (NULL != pobjThread)
    {
        pobjThread->ReleaseReference(pThread);
    }

    if (-1 != fd)
    {
        close(fd);
    }

#endif // HAVE_PRWATCH_T    
    
    LOGEXIT("PAL_DeleteExecWatchpoint returns ret:%d\n", dwError);
    PERF_EXIT(PAL_DeleteExecWatchpoint);
    return dwError;
}
Example #19
0
/*++
Function:
  PALCommonCleanup

Utility function to free any resource used by the PAL. 

Parameters :
    step: selects the desired cleanup step
    full_cleanup:  FALSE: cleanup only what's needed and leave the rest 
                          to the OS process cleanup
                   TRUE:  full cleanup 
--*/
void 
PALCommonCleanup(PALCLEANUP_STEP step, BOOL full_cleanup)
{
    CPalThread *pThread = InternalGetCurrentThread();
    static int step_done[PALCLEANUP_STEP_INVALID] = { 0 };

    switch (step)
    {
    case PALCLEANUP_ALL_STEPS:
    case PALCLEANUP_STEP_ONE:
        /* Note: in order to work correctly, this step should be executed with 
           init_count > 0
         */
        if (!step_done[PALCLEANUP_STEP_ONE])
        {
            step_done[PALCLEANUP_STEP_ONE] = 1;

            PALSetShutdownIntent();

            //
            // Let the synchronization manager know we're about to shutdown
            //

            CPalSynchMgrController::PrepareForShutdown();

#ifdef _DEBUG
            PROCDumpThreadList();
#endif

            TRACE("About to suspend every other thread\n");

            /* prevent other threads from acquiring signaled objects */
            PROCCondemnOtherThreads();
            /* prevent other threads from using services we're shutting down */
            PROCSuspendOtherThreads();

            TRACE("Every other thread suspended until exit\n");
        }

        /* Fall down for PALCLEANUP_ALL_STEPS */
        if (PALCLEANUP_ALL_STEPS != step)
            break;

    case PALCLEANUP_STEP_TWO:
        if (!step_done[PALCLEANUP_STEP_TWO])
        {
            step_done[PALCLEANUP_STEP_TWO] = 1;

            /* LOADFreeeModules needs to be called before unitializing the rest
               of the PAL since it could result in calling DllMain for loaded
               libraries. For the user DllMain, all PAL APIs should still be
               functional. */
            LOADFreeModules(FALSE);

#ifdef PAL_PERF
            PERFDisableProcessProfile();
            PERFDisableThreadProfile(FALSE);
            PERFTerminate();  
#endif

            if (full_cleanup)
            {
                /* close primary handles of standard file objects */
                FILECleanupStdHandles();
                /* This unloads the palrt so, during its unloading, they
                   can call any number of APIs, so we have to be active for it to work. */
                FMTMSG_FormatMessageCleanUp();
                VIRTUALCleanup();
                /* SEH requires information from the process structure to work;
                   LOADFreeModules requires SEH to be functional when calling DllMain.
                   Therefore SEHCleanup must go between LOADFreeModules and
                   PROCCleanupInitialProcess */
                SEHCleanup();
                PROCCleanupInitialProcess();
            }

            // Object manager shutdown may cause all CPalThread objects
            // to be deleted. Since the CPalThread of the shutdown thread
            // needs to be available for reference by the thread suspension unsafe
            // operations, the reference of CPalThread is incremented here
            // to keep it alive until PAL finishes cleanup.
            pThread->AddThreadReference();

            //
            // Shutdown object manager -- this needs to happen before the
            // synch manager shutdown since it will call into the synch
            // manager to free object synch data
            // 
            static_cast<CSharedMemoryObjectManager*>(g_pObjectManager)->Shutdown(pThread);

            //
            // Final synch manager shutdown
            //
            CPalSynchMgrController::Shutdown(pThread, full_cleanup);

            if (full_cleanup)
            {
                /* It needs to be done after stopping the handle manager, because
                   the cleanup will delete the critical section which is used
                   when closing the handle of a file mapping */
                MAPCleanup();
                // MutexCleanup();

                MiscCleanup();

                TLSCleanup();
            }

            // The thread object will no longer be available after the shutdown thread
            // releases the thread reference.
            g_fThreadDataAvailable = FALSE;
            pThread->ReleaseThreadReference();
            pthread_setspecific(thObjKey, NULL); // Make sure any TLS entry is removed.

            // Since thread object is no longer available here,
            // the code path from here should stop using any functions
            // that reference thread object.
            SHMCleanup();

            TRACE("PAL Terminated.\n");
        }
        break;

    default:
        ASSERT("Unknown final cleanup step %d", step);
        break;
    }
}
Example #20
0
void LOADCallDllMain(DWORD dwReason, LPVOID lpReserved)
{
    MODSTRUCT *module = NULL;
    BOOL InLoadOrder = TRUE; /* true if in load order, false for reverse */
    CPalThread *pThread;
    
    pThread = InternalGetCurrentThread();
    if (UserCreatedThread != pThread->GetThreadType())
    {
        return;
    }

    /* Validate dwReason */
    switch(dwReason)
    {
    case DLL_PROCESS_ATTACH: 
        ASSERT("got called with DLL_PROCESS_ATTACH parameter! Why?\n");
        break;
    case DLL_PROCESS_DETACH:
        ASSERT("got called with DLL_PROCESS_DETACH parameter! Why?\n");
        InLoadOrder = FALSE;
        break;
    case DLL_THREAD_ATTACH:
        TRACE("Calling DllMain(DLL_THREAD_ATTACH) on all known modules.\n");
        break;
    case DLL_THREAD_DETACH:
        TRACE("Calling DllMain(DLL_THREAD_DETACH) on all known modules.\n");
        InLoadOrder = FALSE;
        break;
    default:
        ASSERT("LOADCallDllMain called with unknown parameter %d!\n", dwReason);
        return;
    }

    LockModuleList();

    module = &exe_module;
    do {
        if (!InLoadOrder)
            module = module->prev;

        if (module->threadLibCalls)
        {
            if (module->pDllMain)
            {
#if !_NO_DEBUG_MESSAGES_
                /* reset ENTRY nesting level back to zero while inside the callback... */
                int old_level;
                old_level = DBG_change_entrylevel(0);
#endif /* !_NO_DEBUG_MESSAGES_ */

                {
                    // This module may be foreign to our PAL, so leave our PAL.
                    // If it depends on us, it will re-enter.
                    PAL_LeaveHolder holder;
                    module->pDllMain(module->hinstance, dwReason, lpReserved);
                }

#if !_NO_DEBUG_MESSAGES_
                /* ...and set nesting level back to what it was */
                DBG_change_entrylevel(old_level);
#endif /* !_NO_DEBUG_MESSAGES_ */
            }
        }

        if (InLoadOrder)
            module = module->next;
    } while (module != &exe_module);

    UnlockModuleList();
}
Example #21
0
DWORD
PAL_CreateExecWatchpoint(
    HANDLE hThread,
    PVOID pvInstruction
    )
{
    PERF_ENTRY(PAL_CreateExecWatchpoint);
    ENTRY("PAL_CreateExecWatchpoint (hThread=%p, pvInstruction=%p)\n", hThread, pvInstruction);

    DWORD dwError = ERROR_NOT_SUPPORTED;

#if HAVE_PRWATCH_T

    CPalThread *pThread = NULL;
    CPalThread *pTargetThread = NULL;
    IPalObject *pobjThread = NULL;
    int fd = -1;
    char ctlPath[50];

    struct
    {
        long ctlCode;
        prwatch_t prwatch;
    } ctlStruct;

    //
    // We must never set a watchpoint on an instruction that enters a syscall;
    // if such a request comes in we succeed it w/o actually creating the
    // watchpoint. This mirrors the behavior of setting the single-step flag
    // in a thread context when the thread is w/in a system service -- the
    // flag is ignored and will not be present when the thread returns
    // to user mode.
    //

#if defined(_SPARC_)
    if (*(DWORD*)pvInstruction == 0x91d02008) // ta 8
    {
        TRACE("Watchpoint requested on sysenter instruction -- ignoring");
        dwError = ERROR_SUCCESS;
        goto PAL_CreateExecWatchpointExit;        
    }
#else
#error Need syscall instruction for this platform
#endif // _SPARC_

    pThread = InternalGetCurrentThread();

    dwError = InternalGetThreadDataFromHandle(
        pThread,
        hThread,
        0, // THREAD_SET_CONTEXT
        &pTargetThread,
        &pobjThread
        );

    if (NO_ERROR != dwError)
    {
        goto PAL_CreateExecWatchpointExit;
    }

    snprintf(ctlPath, sizeof(ctlPath), "/proc/%u/lwp/%u/lwpctl", getpid(), pTargetThread->GetLwpId());

    fd = InternalOpen(pThread, ctlPath, O_WRONLY);
    if (-1 == fd)
    {
        ERROR("Failed to open %s\n", ctlPath);
        dwError = ERROR_INVALID_ACCESS;
        goto PAL_CreateExecWatchpointExit;
    }

    ctlStruct.ctlCode = PCWATCH;
    ctlStruct.prwatch.pr_vaddr = (uintptr_t) pvInstruction;
    ctlStruct.prwatch.pr_size = sizeof(DWORD);
    ctlStruct.prwatch.pr_wflags = WA_EXEC | WA_TRAPAFTER;

    if (write(fd, (void*) &ctlStruct, sizeof(ctlStruct)) != sizeof(ctlStruct))
    {
        ERROR("Failure writing control structure (errno = %u)\n", errno);
        dwError = ERROR_INTERNAL_ERROR;
        goto PAL_CreateExecWatchpointExit;
    }

    dwError = ERROR_SUCCESS;
    
PAL_CreateExecWatchpointExit:

    if (NULL != pobjThread)
    {
        pobjThread->ReleaseReference(pThread);
    }

    if (-1 != fd)
    {
        close(fd);
    }

#endif // HAVE_PRWATCH_T     
    
    LOGEXIT("PAL_CreateExecWatchpoint returns ret:%d\n", dwError);
    PERF_EXIT(PAL_CreateExecWatchpoint);
    return dwError;
}
Example #22
0
HANDLE
PALAPI
CreateMutexA (
    IN LPSECURITY_ATTRIBUTES lpMutexAttributes,
    IN BOOL bInitialOwner,
    IN LPCSTR lpName)
{
    HANDLE hMutex = NULL;
    WCHAR pwName[c_cchMaxMutex];
    CPalThread *pthr = NULL;
    PAL_ERROR palError;
    
    PERF_ENTRY(CreateMutexA);
    ENTRY("CreateMutexA(lpMutexAttr=%p, bInitialOwner=%d, lpName=%p (%s)\n",
          lpMutexAttributes, bInitialOwner, lpName, lpName?lpName:"NULL");

    pthr = InternalGetCurrentThread();
    
    if (lpName != NULL)
    {
        palError = InternalWszNameFromSzName(
            pthr,
            lpName,
            pwName,
            sizeof(pwName) / sizeof(pwName[0])
            );

        if (NO_ERROR != palError)
        {
            goto CreateMutexAExit;
        }

        palError = InternalCreateMutex(
            pthr,
            lpMutexAttributes,
            bInitialOwner,
            pwName,
            &hMutex
            );
    }
    else
    {
        palError = InternalCreateMutex(
            pthr,
            lpMutexAttributes,
            bInitialOwner,
            NULL,
            &hMutex
            );
    }

CreateMutexAExit:
    
    //
    // We always need to set last error, even on success:
    // we need to protect ourselves from the situation
    // where last error is set to ERROR_ALREADY_EXISTS on
    // entry to the function
    //

    pthr->SetLastError(palError);
    
    LOGEXIT("CreateMutexA returns HANDLE %p\n", hMutex);
    PERF_EXIT(CreateMutexA);
    return hMutex;
}