@@ -17,7 +17,7 @@ Module Name:
1717
1818_Use_decl_annotations_
1919BOOLEAN
20- AddWord (
20+ AddWordEntry (
2121 PDICTIONARY Dictionary ,
2222 PCBYTE Word ,
2323 PCWORD_ENTRY * WordEntryPointer ,
@@ -65,6 +65,7 @@ Return Value:
6565 PBYTE Buffer ;
6666 ULONG Length ;
6767 ULONG EntrySize ;
68+ ULONGLONG StringBytesUsed = 0 ;
6869 PULONG BitmapHash ;
6970 PULONG HistogramHash ;
7071 BOOLEAN NewWordEntry ;
@@ -73,6 +74,7 @@ Return Value:
7374 BOOLEAN NewHistogramEntry ;
7475 BOOLEAN IsNewCurrentLongestWord ;
7576 BOOLEAN IsNewLongestWordAllTime ;
77+ PRTL_AVL_TABLE Avl ;
7678 PALLOCATOR Allocator ;
7779 PALLOCATOR WordAllocator ;
7880 PLONG_STRING String ;
@@ -88,6 +90,7 @@ Return Value:
8890 PCLONG_STRING CurrentLongestWord ;
8991 PCLONG_STRING LongestWordAllTime ;
9092 PTABLE_ENTRY_HEADER TableEntryHeader ;
93+ ULARGE_INTEGER TotalStringBufferAllocSize ;
9194 PRTL_INITIALIZE_GENERIC_TABLE_AVL RtlInitializeGenericTableAvl ;
9295 PRTL_INSERT_ELEMENT_GENERIC_TABLE_AVL RtlInsertElementGenericTableAvl ;
9396
@@ -117,10 +120,6 @@ Return Value:
117120 return FALSE;
118121 }
119122
120- if (!ARGUMENT_PRESENT (EntryCountPointer )) {
121- return FALSE;
122- }
123-
124123 //
125124 // Clear the caller's word entry and entry count pointers up-front.
126125 //
@@ -192,13 +191,6 @@ Return Value:
192191 Context .Dictionary = Dictionary ;
193192 DictionaryTlsSetContext (& Context );
194193
195- //
196- // Acquire the exclusive dictionary lock for the remaining duration of the
197- // routine.
198- //
199-
200- AcquireDictionaryLockExclusive (& Dictionary -> Lock );
201-
202194 //
203195 // Prepare a bitmap table entry for potential insertion into the bitmap
204196 // AVL table.
@@ -273,7 +265,7 @@ Return Value:
273265 }
274266
275267 //
276- // Update the TLS context and initialize the word entry table alias.
268+ // Update the TLS context and initialize the word table alias.
277269 //
278270
279271 Context .HistogramTableEntry = HistogramTableEntry ;
@@ -347,6 +339,19 @@ Return Value:
347339 goto Error ;
348340 }
349341
342+ //
343+ // Update the number of bytes allocated to string buffers in the
344+ // current word table. Because the high and low parts of the count
345+ // are split, we need to do some LARGE_INTEGER juggling.
346+ //
347+
348+ Avl = & WordTable -> Avl ;
349+ TotalStringBufferAllocSize .LowPart = Avl -> BytesAllocatedLowPart ;
350+ TotalStringBufferAllocSize .HighPart = Avl -> BytesAllocatedHighPart ;
351+ TotalStringBufferAllocSize .QuadPart += (Length + 1 );
352+ Avl -> BytesAllocatedLowPart = TotalStringBufferAllocSize .LowPart ;
353+ Avl -> BytesAllocatedHighPart = TotalStringBufferAllocSize .HighPart ;
354+
350355 //
351356 // Copy the buffer, add the trailing NULL, switch the underlying word
352357 // entry's buffer pointer.
@@ -491,7 +496,10 @@ Return Value:
491496 //
492497
493498 * WordEntryPointer = WordEntry ;
494- * EntryCountPointer = WordStats -> EntryCount ;
499+
500+ if (ARGUMENT_PRESENT (EntryCountPointer )) {
501+ * EntryCountPointer = WordStats -> EntryCount ;
502+ }
495503
496504 //
497505 // Indicate success and jump to the end, we're done.
@@ -511,9 +519,74 @@ Return Value:
511519
512520End :
513521
514- ReleaseDictionaryLockExclusive (& Dictionary -> Lock );
522+ return Success ;
523+ }
524+
525+ _Use_decl_annotations_
526+ BOOLEAN
527+ AddWord (
528+ PDICTIONARY Dictionary ,
529+ PCBYTE Word ,
530+ PLONGLONG EntryCountPointer
531+ )
532+ /*++
533+
534+ Routine Description:
535+
536+ Adds a word to a dictionary if it doesn't exist, increments the word's
537+ existing count if it does. Returns the entry count for the word.
538+
539+ N.B. The word may also be registered as the current and all-time longest
540+ word associated with the dictionary.
541+
542+ Arguments:
543+
544+ Dictionary - Supplies a pointer to a DICTIONARY structure to which the
545+ word is to be added.
515546
516- DictionaryTlsSetContext (NULL );
547+ Word - Supplies a NULL-terminated array of bytes to add to the dictionary.
548+ The length of the array must be between the minimum and maximum lengths
549+ configured for the dictionary, otherwise the word will be rejected and
550+ this routine will return FALSE.
551+
552+ EntryCountPointer - Supplies an address to a variable that receives the
553+ current entry count associated with the word at the time that it was
554+ added to the directory. Set to zero on error.
555+
556+ Return Value:
557+
558+ TRUE on success, FALSE on failure.
559+
560+ --*/
561+ {
562+ BOOLEAN Success ;
563+ PWORD_ENTRY WordEntry ;
564+
565+ //
566+ // Validate arguments.
567+ //
568+
569+ if (!ARGUMENT_PRESENT (Dictionary )) {
570+ return FALSE;
571+ }
572+
573+ if (!ARGUMENT_PRESENT (Word )) {
574+ return FALSE;
575+ }
576+
577+ //
578+ // Obtain an exclusive lock on the dictionary.
579+ //
580+
581+ AcquireDictionaryLockExclusive (& Dictionary -> Lock );
582+
583+ Success = AddWordEntry (Dictionary , Word , & WordEntry , EntryCountPointer );
584+
585+ //
586+ // Release the lock and return.
587+ //
588+
589+ ReleaseDictionaryLockExclusive (& Dictionary -> Lock );
517590
518591 return Success ;
519592}
0 commit comments