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.
23 #include "wine/port.h"
25 #include "nbnamecache.h"
27 typedef struct _NBNameCacheNode
30 NBNameCacheEntry
*entry
;
31 struct _NBNameCacheNode
*next
;
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
);
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
;
79 while (ptr
&& *ptr
&& (*ptr
)->entry
)
81 if (!memcmp((*ptr
)->entry
->name
, name
, NCBNAMSZ
- 1))
85 if (GetTickCount() > (*ptr
)->expireTime
)
86 NBNameCacheUnlinkNode(cache
, ptr
);
95 struct NBNameCache
*NBNameCacheCreate(HANDLE heap
, DWORD entryExpireTimeMS
)
97 struct NBNameCache
*cache
;
101 heap
= GetProcessHeap();
102 cache
= HeapAlloc(heap
, 0, sizeof(struct NBNameCache
));
106 InitializeCriticalSection(&cache
->cs
);
107 cache
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": NBNameCache.cs");
108 cache
->entryExpireTimeMS
= entryExpireTimeMS
;
114 BOOL
NBNameCacheAddEntry(struct NBNameCache
*cache
, NBNameCacheEntry
*entry
)
120 NBNameCacheNode
**node
;
122 EnterCriticalSection(&cache
->cs
);
123 node
= NBNameCacheWalk(cache
, (char*)entry
->name
);
126 (*node
)->expireTime
= GetTickCount() +
127 cache
->entryExpireTimeMS
;
128 HeapFree(cache
->heap
, 0, (*node
)->entry
);
129 (*node
)->entry
= entry
;
134 NBNameCacheNode
*newNode
= HeapAlloc(cache
->heap
, 0, sizeof(NBNameCacheNode
));
137 newNode
->expireTime
= GetTickCount() +
138 cache
->entryExpireTimeMS
;
139 newNode
->entry
= entry
;
140 newNode
->next
= cache
->head
;
141 cache
->head
= newNode
;
147 LeaveCriticalSection(&cache
->cs
);
154 const NBNameCacheEntry
*NBNameCacheFindEntry(struct NBNameCache
*cache
,
155 const UCHAR name
[NCBNAMSZ
])
157 const NBNameCacheEntry
*ret
;
158 UCHAR printName
[NCBNAMSZ
];
160 memcpy(printName
, name
, NCBNAMSZ
- 1);
161 printName
[NCBNAMSZ
- 1] = '\0';
164 NBNameCacheNode
**node
;
166 EnterCriticalSection(&cache
->cs
);
167 node
= NBNameCacheWalk(cache
, (const char *)name
);
169 ret
= (*node
)->entry
;
172 LeaveCriticalSection(&cache
->cs
);
179 void NBNameCacheDestroy(struct NBNameCache
*cache
)
183 cache
->cs
.DebugInfo
->Spare
[0] = 0;
184 DeleteCriticalSection(&cache
->cs
);
186 NBNameCacheUnlinkNode(cache
, &cache
->head
);
187 HeapFree(cache
->heap
, 0, cache
);