msvfw32: Replace const pointer parameter with correct pointer to const.
[wine/wine-kai.git] / dlls / netapi32 / nbnamecache.c
blob82c10a9013b90f4eb972687270b1347f64c0b831
1 /* Copyright (c) 2003 Juan Lang
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 * This implementation uses a linked list, because I don't have a decent
18 * hash table implementation handy. This is somewhat inefficient, but it's
19 * rather more efficient than not having a name cache at all.
22 #include "config.h"
23 #include "wine/port.h"
25 #include "nbnamecache.h"
27 typedef struct _NBNameCacheNode
29 DWORD expireTime;
30 NBNameCacheEntry *entry;
31 struct _NBNameCacheNode *next;
32 } NBNameCacheNode;
34 struct NBNameCache
36 HANDLE heap;
37 CRITICAL_SECTION cs;
38 DWORD entryExpireTimeMS;
39 NBNameCacheNode *head;
42 /* Unlinks the node pointed to by *prev, and frees any associated memory.
43 * If that node's next pointed to another node, *prev now points to it.
44 * Assumes the caller owns cache's lock.
46 static void NBNameCacheUnlinkNode(struct NBNameCache *cache,
47 NBNameCacheNode **prev)
49 if (cache && prev && *prev)
51 NBNameCacheNode *next = (*prev)->next;
53 HeapFree(cache->heap, 0, (*prev)->entry);
54 HeapFree(cache->heap, 0, *prev);
55 *prev = next;
59 /* Walks the list beginning with cache->head looking for the node with name
60 * name. If the node is found, returns a pointer to the next pointer of the
61 * node _prior_ to the found node (or head if head points to it). Thus, if the
62 * node's all you want, dereference the return value twice. If you want to
63 * modify the list, modify the referent of the return value.
64 * While it's at it, deletes nodes whose time has expired (except the node
65 * you're looking for, of course).
66 * Returns NULL if the node isn't found.
67 * Assumes the caller owns cache's lock.
69 static NBNameCacheNode **NBNameCacheWalk(struct NBNameCache *cache,
70 const char name[NCBNAMSZ])
72 NBNameCacheNode **ret = NULL;
74 if (cache && cache->head)
76 NBNameCacheNode **ptr;
78 ptr = &cache->head;
79 while (ptr && *ptr && (*ptr)->entry)
81 if (!memcmp((*ptr)->entry->name, name, NCBNAMSZ - 1))
82 ret = ptr;
83 else
85 if (GetTickCount() > (*ptr)->expireTime)
86 NBNameCacheUnlinkNode(cache, ptr);
88 if (*ptr)
89 ptr = &(*ptr)->next;
92 return ret;
95 struct NBNameCache *NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS)
97 struct NBNameCache *cache;
100 if (!heap)
101 heap = GetProcessHeap();
102 cache = HeapAlloc(heap, 0, sizeof(struct NBNameCache));
103 if (cache)
105 cache->heap = heap;
106 InitializeCriticalSection(&cache->cs);
107 cache->entryExpireTimeMS = entryExpireTimeMS;
108 cache->head = NULL;
110 return cache;
113 BOOL NBNameCacheAddEntry(struct NBNameCache *cache, NBNameCacheEntry *entry)
115 BOOL ret;
117 if (cache && entry)
119 NBNameCacheNode **node;
121 EnterCriticalSection(&cache->cs);
122 node = NBNameCacheWalk(cache, (char*)entry->name);
123 if (node)
125 (*node)->expireTime = GetTickCount() +
126 cache->entryExpireTimeMS;
127 HeapFree(cache->heap, 0, (*node)->entry);
128 (*node)->entry = entry;
129 ret = TRUE;
131 else
133 NBNameCacheNode *newNode = HeapAlloc(cache->heap, 0, sizeof(NBNameCacheNode));
134 if (newNode)
136 newNode->expireTime = GetTickCount() +
137 cache->entryExpireTimeMS;
138 newNode->entry = entry;
139 newNode->next = cache->head;
140 cache->head = newNode;
141 ret = TRUE;
143 else
144 ret = FALSE;
146 LeaveCriticalSection(&cache->cs);
148 else
149 ret = FALSE;
150 return ret;
153 const NBNameCacheEntry *NBNameCacheFindEntry(struct NBNameCache *cache,
154 const UCHAR name[NCBNAMSZ])
156 const NBNameCacheEntry *ret;
157 UCHAR printName[NCBNAMSZ];
159 memcpy(printName, name, NCBNAMSZ - 1);
160 printName[NCBNAMSZ - 1] = '\0';
161 if (cache)
163 NBNameCacheNode **node;
165 EnterCriticalSection(&cache->cs);
166 node = NBNameCacheWalk(cache, (const char *)name);
167 if (node)
168 ret = (*node)->entry;
169 else
170 ret = NULL;
171 LeaveCriticalSection(&cache->cs);
173 else
174 ret = NULL;
175 return ret;
178 BOOL NBNameCacheUpdateNBName(struct NBNameCache *cache,
179 const UCHAR name[NCBNAMSZ], const UCHAR nbname[NCBNAMSZ])
181 BOOL ret;
183 if (cache)
185 NBNameCacheNode **node;
187 EnterCriticalSection(&cache->cs);
188 node = NBNameCacheWalk(cache, (const char *)name);
189 if (node && *node && (*node)->entry)
191 memcpy((*node)->entry->nbname, nbname, NCBNAMSZ);
192 ret = TRUE;
194 else
195 ret = FALSE;
196 LeaveCriticalSection(&cache->cs);
198 else
199 ret = FALSE;
200 return ret;
203 void NBNameCacheDestroy(struct NBNameCache *cache)
205 if (cache)
207 DeleteCriticalSection(&cache->cs);
208 while (cache->head)
209 NBNameCacheUnlinkNode(cache, &cache->head);
210 HeapFree(cache->heap, 0, cache);