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
;
57 HeapFree(cache
->heap
, 0, (*prev
)->entry
);
58 HeapFree(cache
->heap
, 0, *prev
);
63 /* Walks the list beginning with cache->head looking for the node with name
64 * name. If the node is found, returns a pointer to the next pointer of the
65 * node _prior_ to the found node (or head if head points to it). Thus, if the
66 * node's all you want, dereference the return value twice. If you want to
67 * modify the list, modify the referent of the return value.
68 * While it's at it, deletes nodes whose time has expired (except the node
69 * you're looking for, of course).
70 * Returns NULL if the node isn't found.
71 * Assumes the caller owns cache's lock.
73 static NBNameCacheNode
**NBNameCacheWalk(struct NBNameCache
*cache
,
74 const char name
[NCBNAMSZ
])
76 NBNameCacheNode
**ret
= NULL
;
78 if (cache
&& cache
->head
)
80 NBNameCacheNode
**ptr
;
83 while (ptr
&& *ptr
&& (*ptr
)->entry
)
85 if (!memcmp((*ptr
)->entry
->name
, name
, NCBNAMSZ
- 1))
89 if (GetTickCount() > (*ptr
)->expireTime
)
90 NBNameCacheUnlinkNode(cache
, ptr
);
99 struct NBNameCache
*NBNameCacheCreate(HANDLE heap
, DWORD entryExpireTimeMS
)
101 struct NBNameCache
*cache
;
105 heap
= GetProcessHeap();
106 cache
= (struct NBNameCache
*)HeapAlloc(heap
, 0,
107 sizeof(struct NBNameCache
));
111 InitializeCriticalSection(&cache
->cs
);
112 cache
->entryExpireTimeMS
= entryExpireTimeMS
;
118 BOOL
NBNameCacheAddEntry(struct NBNameCache
*cache
, NBNameCacheEntry
*entry
)
124 NBNameCacheNode
**node
;
126 EnterCriticalSection(&cache
->cs
);
127 node
= NBNameCacheWalk(cache
, entry
->name
);
130 (*node
)->expireTime
= GetTickCount() +
131 cache
->entryExpireTimeMS
;
132 HeapFree(cache
->heap
, 0, (*node
)->entry
);
133 (*node
)->entry
= entry
;
138 NBNameCacheNode
*newNode
= (NBNameCacheNode
*)HeapAlloc(
139 cache
->heap
, 0, sizeof(NBNameCacheNode
));
142 newNode
->expireTime
= GetTickCount() +
143 cache
->entryExpireTimeMS
;
144 newNode
->entry
= entry
;
145 newNode
->next
= cache
->head
;
146 cache
->head
= newNode
;
152 LeaveCriticalSection(&cache
->cs
);
159 const NBNameCacheEntry
*NBNameCacheFindEntry(struct NBNameCache
*cache
,
160 const UCHAR name
[NCBNAMSZ
])
162 const NBNameCacheEntry
*ret
;
163 UCHAR printName
[NCBNAMSZ
];
165 memcpy(printName
, name
, NCBNAMSZ
- 1);
166 printName
[NCBNAMSZ
- 1] = '\0';
169 NBNameCacheNode
**node
;
171 EnterCriticalSection(&cache
->cs
);
172 node
= NBNameCacheWalk(cache
, name
);
174 ret
= (*node
)->entry
;
177 LeaveCriticalSection(&cache
->cs
);
184 BOOL
NBNameCacheUpdateNBName(struct NBNameCache
*cache
,
185 const UCHAR name
[NCBNAMSZ
], const UCHAR nbname
[NCBNAMSZ
])
191 NBNameCacheNode
**node
;
193 EnterCriticalSection(&cache
->cs
);
194 node
= NBNameCacheWalk(cache
, name
);
195 if (node
&& *node
&& (*node
)->entry
)
197 memcpy((*node
)->entry
->nbname
, nbname
, NCBNAMSZ
);
202 LeaveCriticalSection(&cache
->cs
);
209 void NBNameCacheDestroy(struct NBNameCache
*cache
)
213 DeleteCriticalSection(&cache
->cs
);
215 NBNameCacheUnlinkNode(cache
, &cache
->head
);
216 HeapFree(cache
->heap
, 0, cache
);