home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / software / pelne / optionp / iis4_07.cab / CACHE.C < prev    next >
Text File  |  1997-10-25  |  8KB  |  390 lines

  1. /*++
  2.  
  3. Copyright (c) 1996  Microsoft Corporation
  4.  
  5. This program is released into the public domain for any purpose.
  6.  
  7.  
  8. Module Name:
  9.  
  10.     cache.c
  11.  
  12. Abstract:
  13.  
  14.     This module implements a simple user cache.  The cached users are kept
  15.     in an LRU sorted list.  If there will be a large number of simultaneous
  16.     users, then a sorted array would be more appropriate.
  17.  
  18. --*/
  19.  
  20. #include <windows.h>
  21. #include <httpfilt.h>
  22. #include "authfilt.h"
  23.  
  24. //
  25. // Constants
  26. //
  27.  
  28. //
  29. //  The maximum number of users we will cache.  If there will be a large number
  30. //  of simultaneous users, bump this value
  31. //
  32.  
  33. #define MAX_CACHED_USERS        100
  34.  
  35. //
  36. //  The position after which we'll move a cache entry to the front of the list
  37. //
  38.  
  39. #define LIST_REORDER_THRESHOLD  6
  40.  
  41. //
  42. //  Cached user structure
  43. //
  44.  
  45. typedef struct _USER_INFO
  46. {
  47.     LIST_ENTRY  ListEntry;  // Double linked list entry
  48.  
  49.     CHAR  achUserName[SF_MAX_USERNAME];   // External username and password
  50.     CHAR  achPassword[SF_MAX_PASSWORD];
  51.  
  52.     CHAR  achNTUserName[SF_MAX_USERNAME]; // NT account and password to map user to
  53.     CHAR  achNTUserPassword[SF_MAX_PASSWORD];
  54.  
  55. } USER_INFO, *PUSER_INFO;
  56.  
  57.  
  58. //
  59. //  Globals
  60. //
  61.  
  62. //
  63. //  Circular double linked list of cached users
  64. //
  65.  
  66. LIST_ENTRY CacheListHead;
  67.  
  68. //
  69. //  Critical section protects cache list
  70. //
  71.  
  72. CRITICAL_SECTION csCacheLock;
  73.  
  74. //
  75. //  Indicates whether we are initialized
  76. //
  77.  
  78. BOOL fCacheInitialized = FALSE;
  79.  
  80. //
  81. //  Number of items in the cache
  82. //
  83.  
  84. DWORD cCacheItems = 0;
  85.  
  86.  
  87. BOOL
  88. InitializeCache(
  89.     VOID
  90.     )
  91. /*++
  92.  
  93. Routine Description:
  94.  
  95.     Initializes the cache module
  96.  
  97. Return Value:
  98.  
  99.     TRUE if initialized successfully, FALSE on error
  100.  
  101. --*/
  102. {
  103.     if ( fCacheInitialized )
  104.         return TRUE;
  105.  
  106.     InitializeCriticalSection( &csCacheLock );
  107.     CacheListHead.Blink = CacheListHead.Flink = &CacheListHead;
  108.  
  109.     fCacheInitialized = TRUE;
  110.  
  111.     return TRUE;
  112. }
  113.  
  114.  
  115. BOOL
  116. LookupUserInCache(
  117.     CHAR * pszUserName,
  118.     BOOL * pfFound,
  119.     CHAR * pszPassword,
  120.     CHAR * pszNTUser,
  121.     CHAR * pszNTUserPassword
  122.     )
  123. /*++
  124.  
  125. Routine Description:
  126.  
  127.     Checks to see if a user is in the cache and returns the user properties
  128.     if found
  129.  
  130. Arguments:
  131.  
  132.     pszUserName - Case insensitive username to find
  133.     pfFound     - Set to TRUE if the specified user was found
  134.     pszPassword - Receives password for specified user if found
  135.     pszNTUser   - Receives the NT Username to map this user to
  136.     pszNTUserPassword - Receives the NT Password for pszNTUser
  137.  
  138.     Note: pszPassword and pszNTUserPassword must be at least SF_MAX_PASSWORD
  139.     characters.  pszNTUser must be at least SF_MAX_USERNAME characters.
  140.  
  141. Return Value:
  142.  
  143.     TRUE if no errors occurred.
  144.  
  145. --*/
  146. {
  147.     LIST_ENTRY * pEntry;
  148.     USER_INFO *  pUser;
  149.     DWORD        cPosition = 0;
  150.  
  151.     //
  152.     //  Search the cache for the specified user
  153.     //
  154.  
  155.     EnterCriticalSection( &csCacheLock );
  156.  
  157.     for ( pEntry  = CacheListHead.Flink;
  158.           pEntry != &CacheListHead;
  159.           pEntry = pEntry->Flink )
  160.     {
  161.         pUser = CONTAINING_RECORD( pEntry, USER_INFO, ListEntry );
  162.  
  163.         if ( !stricmp( pszUserName, pUser->achUserName ))
  164.         {
  165.             goto Found;
  166.         }
  167.  
  168.         cPosition++;
  169.     }
  170.  
  171.     LeaveCriticalSection( &csCacheLock );
  172.  
  173.     //
  174.     //  Not Found
  175.     //
  176.  
  177.     *pfFound = FALSE;
  178.     return TRUE;
  179.  
  180. Found:
  181.  
  182.     //
  183.     //  Copy out the user properties
  184.     //
  185.  
  186.     strcpy( pszPassword,       pUser->achPassword );
  187.     strcpy( pszNTUser,         pUser->achNTUserName );
  188.     strcpy( pszNTUserPassword, pUser->achNTUserPassword );
  189.  
  190.     //
  191.     //  Move this user entry to the front of the list as we're probably going
  192.     //  to get subsequent requests for this user.  Note we only move it
  193.     //  if it's not already near the front
  194.     //
  195.  
  196.     if ( cPosition > LIST_REORDER_THRESHOLD )
  197.     {
  198.         //
  199.         //  Remove from the old position...
  200.         //
  201.  
  202.         pEntry->Blink->Flink = pEntry->Flink;
  203.         pEntry->Flink->Blink = pEntry->Blink;
  204.  
  205.         //
  206.         // ...and insert it at the beginning of the list
  207.         //
  208.  
  209.         pEntry->Blink = &CacheListHead;
  210.         pEntry->Flink = CacheListHead.Flink;
  211.  
  212.         CacheListHead.Flink->Blink = pEntry;
  213.         CacheListHead.Flink        = pEntry;
  214.     }
  215.  
  216.     LeaveCriticalSection( &csCacheLock );
  217.  
  218.     *pfFound = TRUE;
  219.  
  220.     return TRUE;
  221. }
  222.  
  223. BOOL
  224. AddUserToCache(
  225.     CHAR * pszUserName,
  226.     CHAR * pszPassword,
  227.     CHAR * pszNTUser,
  228.     CHAR * pszNTUserPassword
  229.     )
  230. /*++
  231.  
  232. Routine Description:
  233.  
  234.     Adds the specified user to the cache
  235.  
  236. Arguments:
  237.  
  238.     pszUserName - Username to add
  239.     pszPassword - Contains the external password for this user
  240.     pszNTUser   - Contains the NT user name to use for this user
  241.     pszNTUserPassword - Contains the password for NTUser
  242.  
  243. Return Value:
  244.  
  245.     TRUE if no errors occurred.
  246.  
  247. --*/
  248. {
  249.     LIST_ENTRY * pEntry;
  250.     USER_INFO *  pUser;
  251.  
  252.     //
  253.     //  Check our parameters before adding them to the cache
  254.     //
  255.  
  256.     if ( strlen( pszUserName ) > SF_MAX_USERNAME ||
  257.          strlen( pszPassword ) > SF_MAX_PASSWORD ||
  258.          strlen( pszNTUser   ) > SF_MAX_USERNAME ||
  259.          strlen( pszNTUserPassword ) > SF_MAX_PASSWORD )
  260.     {
  261.         SetLastError( ERROR_INVALID_PARAMETER );
  262.         return FALSE;
  263.     }
  264.  
  265.     //
  266.     //  Search the cache for the specified user to make sure there are no
  267.     //  duplicates
  268.     //
  269.  
  270.     EnterCriticalSection( &csCacheLock );
  271.  
  272.     for ( pEntry  = CacheListHead.Flink;
  273.           pEntry != &CacheListHead;
  274.           pEntry = pEntry->Flink )
  275.     {
  276.         pUser = CONTAINING_RECORD( pEntry, USER_INFO, ListEntry );
  277.  
  278.         if ( !stricmp( pszUserName, pUser->achUserName ))
  279.         {
  280.             goto Found;
  281.         }
  282.     }
  283.  
  284.     //
  285.     //  Allocate a new cache item and put it at the head of the list
  286.     //
  287.  
  288.     pUser = (USER_INFO *) LocalAlloc( LPTR, sizeof( USER_INFO ));
  289.  
  290.     if ( !pUser )
  291.     {
  292.         LeaveCriticalSection( &csCacheLock );
  293.  
  294.         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  295.         return FALSE;
  296.     }
  297.  
  298.     pUser->ListEntry.Flink = CacheListHead.Flink;
  299.     pUser->ListEntry.Blink = &CacheListHead;
  300.  
  301.     CacheListHead.Flink->Blink = &pUser->ListEntry;
  302.     CacheListHead.Flink = &pUser->ListEntry;
  303.  
  304. Found:
  305.  
  306.     //
  307.     //  Set the various fields
  308.     //
  309.  
  310.     strcpy( pUser->achUserName,       pszUserName );
  311.     strcpy( pUser->achPassword,       pszPassword );
  312.     strcpy( pUser->achNTUserName,     pszNTUser );
  313.     strcpy( pUser->achNTUserPassword, pszNTUserPassword );
  314.  
  315.     cCacheItems++;
  316.  
  317.     //
  318.     //  If there are too many cached users, remove the least recently
  319.     //  used one now
  320.     //
  321.  
  322.     if ( cCacheItems > MAX_CACHED_USERS )
  323.     {
  324.         pEntry = CacheListHead.Blink;
  325.  
  326.         pEntry->Blink->Flink = &CacheListHead;
  327.         CacheListHead.Blink  = pEntry->Blink;
  328.  
  329.         LocalFree( CONTAINING_RECORD( pEntry, USER_INFO, ListEntry ));
  330.  
  331.         cCacheItems--;
  332.     }
  333.  
  334.     LeaveCriticalSection( &csCacheLock );
  335.  
  336.     return TRUE;
  337. }
  338.  
  339. VOID
  340. TerminateCache(
  341.     VOID
  342.     )
  343. /*++
  344.  
  345. Routine Description:
  346.  
  347.     Terminates the cache module and frees any allocated memory
  348.  
  349. --*/
  350. {
  351.     LIST_ENTRY * pEntry;
  352.     LIST_ENTRY * pEntryNext;
  353.     USER_INFO *  pUser;
  354.  
  355.     if ( !fCacheInitialized )
  356.         return;
  357.  
  358.     EnterCriticalSection( &csCacheLock );
  359.  
  360.     //
  361.     //  Free all of the cache entries
  362.     //
  363.  
  364.     for ( pEntry  = CacheListHead.Flink;
  365.           pEntry != &CacheListHead;
  366.           pEntry  = pEntryNext )
  367.  
  368.     {
  369.         pUser = CONTAINING_RECORD( pEntry, USER_INFO, ListEntry );
  370.  
  371.         pEntryNext = pEntry->Flink;
  372.  
  373.         //
  374.         //  Remove this entry from the list and free it
  375.         //
  376.  
  377.         pEntry->Blink->Flink = pEntry->Flink;
  378.         pEntry->Flink->Blink = pEntry->Blink;
  379.  
  380.         LocalFree( pUser );
  381.     }
  382.  
  383.     cCacheItems = 0;
  384.     LeaveCriticalSection( &csCacheLock );
  385.  
  386.     DeleteCriticalSection( &csCacheLock );
  387.  
  388.     fCacheInitialized = FALSE;
  389. }
  390.