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.
22 #include "wine/debug.h"
23 #include "nbnamecache.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(netbios
);
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
;
54 HeapFree(cache
->heap
, 0, (*prev
)->entry
);
55 HeapFree(cache
->heap
, 0, *prev
);
60 /* Walks the list beginning with cache->head looking for the node with name
61 * name. If the node is found, returns a pointer to the next pointer of the
62 * node _prior_ to the found node (or head if head points to it). Thus, if the
63 * node's all you want, dereference the return value twice. If you want to
64 * modify the list, modify the referent of the return value.
65 * While it's at it, deletes nodes whose time has expired (except the node
66 * you're looking for, of course).
67 * Returns NULL if the node isn't found.
68 * Assumes the caller owns cache's lock.
70 static NBNameCacheNode
**NBNameCacheWalk(struct NBNameCache
*cache
,
71 const char name
[NCBNAMSZ
])
73 NBNameCacheNode
**ret
= NULL
;
75 if (cache
&& cache
->head
)
77 NBNameCacheNode
**ptr
;
80 while (ptr
&& *ptr
&& (*ptr
)->entry
)
82 if (!memcmp((*ptr
)->entry
->name
, name
, NCBNAMSZ
- 1))
86 if (GetTickCount() > (*ptr
)->expireTime
)
87 NBNameCacheUnlinkNode(cache
, ptr
);
96 struct NBNameCache
*NBNameCacheCreate(HANDLE heap
, DWORD entryExpireTimeMS
)
98 struct NBNameCache
*cache
;
102 heap
= GetProcessHeap();
103 cache
= (struct NBNameCache
*)HeapAlloc(heap
, 0,
104 sizeof(struct NBNameCache
));
108 InitializeCriticalSection(&cache
->cs
);
109 cache
->entryExpireTimeMS
= entryExpireTimeMS
;
115 BOOL
NBNameCacheAddEntry(struct NBNameCache
*cache
, NBNameCacheEntry
*entry
)
121 NBNameCacheNode
**node
;
123 EnterCriticalSection(&cache
->cs
);
124 node
= NBNameCacheWalk(cache
, entry
->name
);
127 (*node
)->expireTime
= GetTickCount() +
128 cache
->entryExpireTimeMS
;
129 HeapFree(cache
->heap
, 0, (*node
)->entry
);
130 (*node
)->entry
= entry
;
135 NBNameCacheNode
*newNode
= (NBNameCacheNode
*)HeapAlloc(
136 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
);