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
= HeapAlloc(heap
, 0, sizeof(struct NBNameCache
));
109 InitializeCriticalSection(&cache
->cs
);
110 cache
->entryExpireTimeMS
= entryExpireTimeMS
;
116 BOOL
NBNameCacheAddEntry(struct NBNameCache
*cache
, NBNameCacheEntry
*entry
)
122 NBNameCacheNode
**node
;
124 EnterCriticalSection(&cache
->cs
);
125 node
= NBNameCacheWalk(cache
, entry
->name
);
128 (*node
)->expireTime
= GetTickCount() +
129 cache
->entryExpireTimeMS
;
130 HeapFree(cache
->heap
, 0, (*node
)->entry
);
131 (*node
)->entry
= entry
;
136 NBNameCacheNode
*newNode
= HeapAlloc(cache
->heap
, 0, sizeof(NBNameCacheNode
));
139 newNode
->expireTime
= GetTickCount() +
140 cache
->entryExpireTimeMS
;
141 newNode
->entry
= entry
;
142 newNode
->next
= cache
->head
;
143 cache
->head
= newNode
;
149 LeaveCriticalSection(&cache
->cs
);
156 const NBNameCacheEntry
*NBNameCacheFindEntry(struct NBNameCache
*cache
,
157 const UCHAR name
[NCBNAMSZ
])
159 const NBNameCacheEntry
*ret
;
160 UCHAR printName
[NCBNAMSZ
];
162 memcpy(printName
, name
, NCBNAMSZ
- 1);
163 printName
[NCBNAMSZ
- 1] = '\0';
166 NBNameCacheNode
**node
;
168 EnterCriticalSection(&cache
->cs
);
169 node
= NBNameCacheWalk(cache
, name
);
171 ret
= (*node
)->entry
;
174 LeaveCriticalSection(&cache
->cs
);
181 BOOL
NBNameCacheUpdateNBName(struct NBNameCache
*cache
,
182 const UCHAR name
[NCBNAMSZ
], const UCHAR nbname
[NCBNAMSZ
])
188 NBNameCacheNode
**node
;
190 EnterCriticalSection(&cache
->cs
);
191 node
= NBNameCacheWalk(cache
, name
);
192 if (node
&& *node
&& (*node
)->entry
)
194 memcpy((*node
)->entry
->nbname
, nbname
, NCBNAMSZ
);
199 LeaveCriticalSection(&cache
->cs
);
206 void NBNameCacheDestroy(struct NBNameCache
*cache
)
210 DeleteCriticalSection(&cache
->cs
);
212 NBNameCacheUnlinkNode(cache
, &cache
->head
);
213 HeapFree(cache
->heap
, 0, cache
);