summaryrefslogtreecommitdiff
path: root/src/pal/tests/palsuite/threading/DisableThreadLibraryCalls/test1/test1.c
blob: b64fd0c7d238c26c761e9be694c7dd1445271d5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

/*=====================================================================
**
** Source:  test1.c
**
** Purpose: Tests that DisableThreadLibraryCalls actually stops thread 
**          attach/detach notifications to a library.  Also tests how it
**          handles an invalid module handle.
**
**
**===================================================================*/

#include <palsuite.h>


/* SHLEXT is defined only for Unix variants */

#if defined(SHLEXT)
#define LibName  "testlib"SHLEXT
#define GETCALLCOUNT "GetCallCount"
#else
#define LibName  "testlib"
#define GETCALLCOUNT "_GetCallCount@0"
#endif

DWORD __stdcall ThreadFunc(LPVOID lpParam);
int RunTest(int DisableThreadCalls);

int __cdecl main(int argc, char **argv)
{    
    int ret;

    if ((PAL_Initialize(argc,argv)) != 0)
    {
        return (FAIL);
    }


    /* 
     * Although MSDN says that DisableThreadLibraryCalls will fail if passed 
     * an invalid handle, it actually returns success!
     */
    ret = DisableThreadLibraryCalls(NULL);
    if (!ret)
    {
        Fail("DisableThreadLibraryCalls failed on an invalid module "
            "handle (it actually should pass)!\n");
    }
    

    /*
     * Test once without calling DisableThreadLibraryCalls and make sure we 
     * get expected results.
     */
    ret = RunTest(0);
    if (ret != 2)
    {
        Fail("Expected to get 2 thread library calls, got %d!\n", ret);
    }
    

    /*
     * Test again, this time calling DisableThreadLibraryCalls.
     */
    ret = RunTest(1);
    if (ret != 0)
    {
        Fail("Expected to get 0 thread library calls, got %d!\n", ret);
    }

    PAL_Terminate();
    return PASS;
}

/*
 * Thread entry point.  Doesn't do anything.
 */
DWORD __stdcall ThreadFunc(LPVOID lpParam)
{
    return 0;
}


int RunTest(int DisableThreadCalls)
{
    HMODULE LibMod;
    HANDLE hThread;
    DWORD threadID;
    DWORD WaitRet;
    int (*GetCallCount)();
    int count;

    LibMod = LoadLibrary(LibName);
    if (LibMod == NULL)
    {
        Fail("Unable to load test library!\nGetLastError returned %d\n", 
            GetLastError());
    }

    GetCallCount = (int(*)())GetProcAddress(LibMod, GETCALLCOUNT);
    if (GetCallCount == NULL)
    {
        Fail("Unable to get function GetCallCount from library!\n"
            "GetLastError returned %d\n", GetLastError());
    }

    if (DisableThreadCalls)
    {
        if (!DisableThreadLibraryCalls(LibMod))
        {
            Fail("DisabledThreadLibraryCalls failed!\n"
                "GetLastError returned %d!\n", GetLastError());
        }
    }

    hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunc,
        NULL, 0, &threadID);

    if (hThread == NULL)
    {
        Fail("Unable to create a thread!\n");
    }

    WaitRet = WaitForSingleObject(hThread, INFINITE);
    if (WaitRet == WAIT_FAILED)
    {
        Fail("Unable to wait on thread!\nGetLastError returned %d\n", 
            GetLastError());
    }

    count = GetCallCount();

    CloseHandle(hThread);

    if (!FreeLibrary(LibMod))
    {
        Fail("Failed freeing library!\nGetLastError returned %d\n",
            GetLastError());
    }
    
    return count;
}