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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
23 #include "wine/port.h"
24 #include "wine/debug.h"
26 #include "nbnamecache.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(netbios);
30 typedef struct _NBNameCacheNode
33 NBNameCacheEntry *entry;
34 struct _NBNameCacheNode *next;
41 DWORD entryExpireTimeMS;
42 NBNameCacheNode *head;
45 /* Unlinks the node pointed to by *prev, and frees any associated memory.
46 * If that node's next pointed to another node, *prev now points to it.
47 * Assumes the caller owns cache's lock.
49 static void NBNameCacheUnlinkNode(struct NBNameCache *cache,
50 NBNameCacheNode **prev)
52 if (cache && prev && *prev)
54 NBNameCacheNode *next = (*prev)->next;
56 HeapFree(cache->heap, 0, (*prev)->entry);
57 HeapFree(cache->heap, 0, *prev);
62 /* Walks the list beginning with cache->head looking for the node with name
63 * name. If the node is found, returns a pointer to the next pointer of the
64 * node _prior_ to the found node (or head if head points to it). Thus, if the
65 * node's all you want, dereference the return value twice. If you want to
66 * modify the list, modify the referent of the return value.
67 * While it's at it, deletes nodes whose time has expired (except the node
68 * you're looking for, of course).
69 * Returns NULL if the node isn't found.
70 * Assumes the caller owns cache's lock.
72 static NBNameCacheNode **NBNameCacheWalk(struct NBNameCache *cache,
73 const char name[NCBNAMSZ])
75 NBNameCacheNode **ret = NULL;
77 if (cache && cache->head)
79 NBNameCacheNode **ptr;
82 while (ptr && *ptr && (*ptr)->entry)
84 if (!memcmp((*ptr)->entry->name, name, NCBNAMSZ - 1))
88 if (GetTickCount() > (*ptr)->expireTime)
89 NBNameCacheUnlinkNode(cache, ptr);
98 struct NBNameCache *NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS)
100 struct NBNameCache *cache;
104 heap = GetProcessHeap();
105 cache = (struct NBNameCache *)HeapAlloc(heap, 0,
106 sizeof(struct NBNameCache));
110 InitializeCriticalSection(&cache->cs);
111 cache->entryExpireTimeMS = entryExpireTimeMS;
117 BOOL NBNameCacheAddEntry(struct NBNameCache *cache, NBNameCacheEntry *entry)
123 NBNameCacheNode **node;
125 EnterCriticalSection(&cache->cs);
126 node = NBNameCacheWalk(cache, entry->name);
129 (*node)->expireTime = GetTickCount() +
130 cache->entryExpireTimeMS;
131 HeapFree(cache->heap, 0, (*node)->entry);
132 (*node)->entry = entry;
137 NBNameCacheNode *newNode = (NBNameCacheNode *)HeapAlloc(
138 cache->heap, 0, sizeof(NBNameCacheNode));
141 newNode->expireTime = GetTickCount() +
142 cache->entryExpireTimeMS;
143 newNode->entry = entry;
144 newNode->next = cache->head;
145 cache->head = newNode;
151 LeaveCriticalSection(&cache->cs);
158 const NBNameCacheEntry *NBNameCacheFindEntry(struct NBNameCache *cache,
159 const UCHAR name[NCBNAMSZ])
161 const NBNameCacheEntry *ret;
162 UCHAR printName[NCBNAMSZ];
164 memcpy(printName, name, NCBNAMSZ - 1);
165 printName[NCBNAMSZ - 1] = '\0';
168 NBNameCacheNode **node;
170 EnterCriticalSection(&cache->cs);
171 node = NBNameCacheWalk(cache, name);
173 ret = (*node)->entry;
176 LeaveCriticalSection(&cache->cs);
183 BOOL NBNameCacheUpdateNBName(struct NBNameCache *cache,
184 const UCHAR name[NCBNAMSZ], const UCHAR nbname[NCBNAMSZ])
190 NBNameCacheNode **node;
192 EnterCriticalSection(&cache->cs);
193 node = NBNameCacheWalk(cache, name);
194 if (node && *node && (*node)->entry)
196 memcpy((*node)->entry->nbname, nbname, NCBNAMSZ);
201 LeaveCriticalSection(&cache->cs);
208 void NBNameCacheDestroy(struct NBNameCache *cache)
212 DeleteCriticalSection(&cache->cs);
214 NBNameCacheUnlinkNode(cache, &cache->head);
215 HeapFree(cache->heap, 0, cache);