xref: /reactos/win32ss/gdi/gdi32/objects/clientobj.c (revision 8a978a17)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS WIN32 subsystem
4  * PURPOSE:         Support functions for GDI client objects
5  * PROGRAMMER:      Timo Kreuzer (timo.kreuzer@reactos.org)
6  */
7 
8 #include <precomp.h>
9 
10 CRITICAL_SECTION gcsClientObjLinks;
11 ULONG gcClientObj;
12 
13 typedef struct _CLIENTOBJLINK
14 {
15     struct _CLIENTOBJLINK *pcolNext;
16     HGDIOBJ hobj;
17     PVOID pvObj;
18 } CLIENTOBJLINK, *PCLIENTOBJLINK;
19 
20 PCLIENTOBJLINK gapcolHashTable[127];
21 
22 BOOL
23 WINAPI
24 GdiCreateClientObjLink(
25     _In_ HGDIOBJ hobj,
26     _In_ PVOID pvObject)
27 {
28     PCLIENTOBJLINK pcol;
29     ULONG iHashIndex;
30 
31     /* Allocate a link structure */
32     pcol = HeapAlloc(GetProcessHeap(), 0, sizeof(*pcol));
33     if (pcol == NULL)
34     {
35         return FALSE;
36     }
37 
38     /* Setup the link structure */
39     pcol->hobj = hobj;
40     pcol->pvObj = pvObject;
41 
42     /* Calculate the hash index */
43     iHashIndex = (ULONG_PTR)hobj % _countof(gapcolHashTable);
44 
45     /* Enter the critical section */
46     EnterCriticalSection(&gcsClientObjLinks);
47 
48     /* Insert the link structure */
49     pcol->pcolNext = gapcolHashTable[iHashIndex];
50     gapcolHashTable[iHashIndex] = pcol;
51     gcClientObj++;
52 
53     /* Leave the critical section */
54     LeaveCriticalSection(&gcsClientObjLinks);
55 
56     return TRUE;
57 }
58 
59 PVOID
60 WINAPI
61 GdiGetClientObjLink(
62     _In_ HGDIOBJ hobj)
63 {
64     ULONG iHashIndex;
65     PCLIENTOBJLINK pcol;
66     PVOID pvObject = NULL;
67 
68     /* Calculate the hash index */
69     iHashIndex = (ULONG_PTR)hobj % _countof(gapcolHashTable);
70 
71     /* Enter the critical section */
72     EnterCriticalSection(&gcsClientObjLinks);
73 
74     /* Loop the link entries in this hash bucket */
75     pcol = gapcolHashTable[iHashIndex];
76     while (pcol != NULL)
77     {
78         /* Check if this is the object we want */
79         if (pcol->hobj == hobj)
80         {
81             /* Get the object pointer and bail out */
82             pvObject = pcol->pvObj;
83             break;
84         }
85 
86         /* Go to the next entry */
87         pcol = pcol->pcolNext;
88     }
89 
90     /* Leave the critical section */
91     LeaveCriticalSection(&gcsClientObjLinks);
92 
93     return pvObject;
94 }
95 
96 PVOID
97 WINAPI
98 GdiRemoveClientObjLink(
99     _In_ HGDIOBJ hobj)
100 {
101     PCLIENTOBJLINK pcol, *ppcol;
102     ULONG iHashIndex;
103     PVOID pvObject = NULL;
104 
105     /* Calculate the hash index */
106     iHashIndex = (ULONG_PTR)hobj % _countof(gapcolHashTable);
107 
108     /* Enter the critical section */
109     EnterCriticalSection(&gcsClientObjLinks);
110 
111     /* Loop the link entries in this hash bucket */
112     ppcol = &gapcolHashTable[iHashIndex];
113     while (*ppcol != NULL)
114     {
115         /* Get the current client object link */
116         pcol = *ppcol;
117 
118         /* Check if this is the one we want */
119         if (pcol->hobj == hobj)
120         {
121             /* Update the link pointer, removing this link */
122             *ppcol = pcol->pcolNext;
123             gcClientObj--;
124 
125             /* Get the object pointer */
126             pvObject = pcol->pvObj;
127 
128             /* Free the link structure */
129             HeapFree(GetProcessHeap(), 0, pcol);
130 
131             /* We're done */
132             break;
133         }
134 
135         /* Go to the next link pointer */
136         ppcol = &(pcol->pcolNext);
137     }
138 
139     /* Leave the critical section */
140     LeaveCriticalSection(&gcsClientObjLinks);
141 
142     /* Return the object pointer, or NULL if we did not find it */
143     return pvObject;
144 }
145 
146 HGDIOBJ
147 WINAPI
148 GdiCreateClientObj(
149     _In_ PVOID pvObject,
150     _In_ GDILOOBJTYPE eObjType)
151 {
152     HGDIOBJ hobj;
153 
154     /* Call win32k to create a client object handle */
155     hobj = NtGdiCreateClientObj(eObjType);
156     if (hobj == NULL)
157     {
158         return NULL;
159     }
160 
161     /* Create the client object link */
162     if (!GdiCreateClientObjLink(hobj, pvObject))
163     {
164         NtGdiDeleteClientObj(hobj);
165         return NULL;
166     }
167 
168     return hobj;
169 }
170 
171 PVOID
172 WINAPI
173 GdiDeleteClientObj(
174     _In_ HGDIOBJ hobj)
175 {
176     PVOID pvObject;
177 
178     /* Remove the client object link */
179     pvObject = GdiRemoveClientObjLink(hobj);
180     if (pvObject == NULL)
181     {
182         return NULL;
183     }
184 
185     /* Call win32k to delete the handle */
186     if (!NtGdiDeleteClientObj(hobj))
187     {
188         ASSERT(FALSE);
189     }
190 
191     return pvObject;
192 }
193