Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

10808 lines
242 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. ism.cxx
  5. Abstract:
  6. HTML administrator for Internet services as a BGI DLL
  7. Author:
  8. Philippe Choquier (phillich) 10-january-1996
  9. --*/
  10. #include <windows.h>
  11. #include <stdio.h>
  12. #include <stdarg.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <ctype.h>
  16. #include <limits.h>
  17. #include <time.h>
  18. #include <lmaccess.h>
  19. #include <winsock2.h>
  20. #include "iis64.h"
  21. #include "iisext.h"
  22. #include "inetinfo.h"
  23. #include "apiutil.h"
  24. #include <mbstring.h>
  25. #include <pudebug.h>
  26. typedef
  27. BOOL
  28. (*GET_DEFAULT_DOMAIN_NAME_FN)(PCHAR,DWORD);
  29. #if defined(IISv1)
  30. #define GENERATE_AUTH_HEADERS
  31. #endif
  32. //#define _CHECK_NEW_BALANCED
  33. #if defined(_CHECK_NEW_BALANCED)
  34. unsigned int g_cA = 0;
  35. void* __cdecl operator new( unsigned int nb )
  36. {
  37. LPVOID p;
  38. ++g_cA;
  39. if ( p = VirtualAlloc( NULL, 4096 + nb, MEM_RESERVE, PAGE_READWRITE) )
  40. {
  41. if ( VirtualAlloc( p, nb, MEM_COMMIT, PAGE_READWRITE ) )
  42. {
  43. return p;
  44. }
  45. }
  46. else
  47. {
  48. }
  49. return NULL;
  50. }
  51. void __cdecl operator delete( void* p )
  52. {
  53. --g_cA;
  54. VirtualFree( p, 0, MEM_RELEASE );
  55. }
  56. #endif
  57. #define _ENABLE_KEEP_ALIVE
  58. #include "ism.hxx"
  59. #include "htmlarc.h"
  60. // This BGI DLL presents HTTP requests to an extended syntax HTML
  61. // file. Extensions includes variables ( mostly used to interface
  62. // use the structures defined by the admin RPC layer ), flow control
  63. // ( if, goto, onerror ), HTTP redirection control, calls to C++ functions,
  64. // iterated construct access ( begin/end iteration ).
  65. // These files are stored with an .htr extension
  66. //
  67. // The HTTP request is composed of 2 parts :
  68. // - the query string, of the form <service_name>/<script_path>+<param>
  69. // where <service_name> is the name of the service to access
  70. // ( http, ftp, gopher )
  71. // <script_path> defines the name of the .htr file to use. The .htr
  72. // extension is appended automatically.
  73. // <param> is made available to the .htr script through the <%urlparam%>
  74. // variable, and is typically used to pass back a reference to an
  75. // element to the script ( i.e. some unique ID referencing an element
  76. // to update / delete, such as an IP security entry ).
  77. // - the request body ( optional ), which must contains the result of
  78. // an HTML FORM to be processed by the !Update function.
  79. // This is to be present only for information update ( see below )
  80. //
  81. // Settings are accessed using variables ( via the '<%' varname '%>'
  82. // construct ). Most variables map directly to a member variable of
  83. // one the structures defined by the admin RPC layer, but some are
  84. // defined onl to easily map with UI objects ( i.e. settings stored in
  85. // a DWORD bitmask are exposed as multiple independant variables ).
  86. //
  87. // Variables are defined in the g_InetInfoConfigInfoMap array. A variable is
  88. // defined by its name ( referenced using '<%' varname '%>' in a .htr file ),
  89. // its type ( cf INET_ELEM_TYPE, this is also used to define the input and
  90. // and output format ), a GET function ( update a pointer allowing get/set access
  91. // to the variable, i.e. a LP(W)STR* for strings, DWORD* for numeric, LPBYTE* for IP
  92. // addresses, LPWSTR for array of WCHAR. This function returns FALSE is the access
  93. // is invalid ( e.g. RPC call to retrieve settings failed )
  94. // and an UPDATE function ( a place to validate the new value ) to be called
  95. // after updating the variable. This will returns FALSE if validation fails,
  96. // or if the variable is inaccessible ( same as for GET : RPC failed, ... )
  97. //
  98. // A transaction ( seeing and modifying an internet server setting )
  99. // is typically composed of 2 parts :
  100. // - information display
  101. // Using variables.
  102. // - information update
  103. // Some settings resides in iterated constructs ( e.g. IP security entries )
  104. // accessing these settings is a 2 part process :
  105. // - positionning
  106. // To set the position on an existing instance of an iterated
  107. // settings the HTTP request must includes a setting specific
  108. // unique ID in the <param> part of the URL ( see above ).
  109. // This ID is used by a positionning function ( such as PosVirtDir )
  110. // to access the correct element. Deletion uses the same basic mechanism
  111. // but requires a specific delete function to position and delete the
  112. // element. This ID is available as a variable ( e.g. ipdenyref ) and is
  113. // typically used to build the <param> field of an URL.
  114. // To add an instance of an iterated settings, add functions are defined
  115. // on a per iterated construct basis.
  116. // - updating : same as a non iterated field.
  117. //
  118. // The settings are updated from the request body by the !Update
  119. // function. The names in the HTML FORM construct must be the same
  120. // as the one defined in the g_InetInfoConfigInfoMap array.
  121. //
  122. // As RPC structures are updated, so are the relevant FieldControl variables
  123. // so that only the minimal amount of updating is done by the RPC server.
  124. //
  125. // In addition to functions to position, add, delete, set default, update
  126. // variables there is a !Clear function to set to 0 a DWORD variable.
  127. // This is necessary because a web browser doesn't send back information
  128. // for a checkbox item if not checked, so te update script has to clear
  129. // the relevant variable before calling the !Update function.
  130. //
  131. // As an error occurs, the error code is stored in reqstatus. If the error
  132. // involves an RPC call the rpcstatus variable is also updated.
  133. // This is typically used with the onerror statement to branch on error.
  134. //
  135. // Special note for IP security lists : there are 2 of them, the deny list
  136. // and the grat list. If the grant list is empty, the default is assumed
  137. // to be grant access. If the grant list is not empty, the default is deny access.
  138. // To signal a default set to deny access when the grant list is empty, as is
  139. // the case initially when a user modify the default to deny, a dummy entry
  140. // is created by the windows based admin tool ( cf. g_achIPNullAddr ).
  141. // This tool uses instead the IP HOST address for the current request,
  142. // to allow the administrator access to the web server after switching the
  143. // default to deny.
  144. //
  145. // The implementation of the current admin tools uses 2 types of .htr :
  146. // - display .htr, which includes HTML FORMs and do not call update functions
  147. // - update .htr, which calls update functions and typically only display
  148. // something in case of error. If no error, they use a redirect construct
  149. // to branch to a display .htr
  150. // This distinction is a UI design conveniance : nothing in the design
  151. // of this DLL enforce this.
  152. // The .htr are typically common to all services ( http, ftp, gopher ).
  153. // Service specific behaviour is possible by testing the servid variable.
  154. // Hierarchy of the current implementation ( update .htr between parenthesis ) :
  155. //
  156. // HTMLA.HTM Top level menu to select service
  157. // SERV.HTR "Service"
  158. // ( SERVU.HTR )
  159. // CONN.HTR Current connections ( FTP Only )
  160. // ( DISC.HTR ) Disconnect a user
  161. // ( DISCA.HTR ) Disconnect all users
  162. // DIR.HTR "Diretories"
  163. // ( DIRU.HTR )
  164. // ( DIRDEL.HTR ) Delete a directory
  165. // DIRADD.HTR Add a directory
  166. // ( DIRADDU.HTR )
  167. // DIREDT.HTR Edit a directory
  168. // ( DIREDTU.HTR )
  169. // LOG.HTR "Logging"
  170. // ( LOGU.HTR )
  171. // ADV.HTR "Advanced"
  172. // ( ADVU.HTR )
  173. // ADVDENY.HTR Ask is set default to deny
  174. // ( ADVDENY2.HTR ) Set default to deny
  175. // ( ADVGRANT.HTR ) Set default to grant
  176. // ( ADVDED.HTR ) Delete a denied access entry
  177. // ADVADDD.HTR Add a denied access entry
  178. // ( ADVADDDU.HTR )
  179. // ADVEDD.HTR Edit a denied access entry
  180. // ( ADVEDDU.HTR )
  181. // ( ADVDEG.HTR ) Delete a granted access entry
  182. // ADVADDG.HTR Add a granted access entry
  183. // ( ADVADDGU.HTR )
  184. // ADVEDG.HTR Edit a granted access entry
  185. // ( ADVEDGU.HTR )
  186. // MSG.HTR "Messages" ( FTP Only )
  187. // ( MSGU.HTR )
  188. // If defined, enable DEBUG_TR() function. DEBUG_LEVEL value enables
  189. // calls to DEBUG_TR up to this level ( as specified in the 1st param of
  190. // DEBUG_TR(), the rest being equivalent to printf() )
  191. #define DEBUG_LEVEL 0
  192. // Separator used in a reference ( i.e. IP addr ref and virtdir ref )
  193. #define REF_SEP '|'
  194. #define REF_SEP_STR "|"
  195. // Expire header insuring that the returned document will always be considered
  196. // expired, so that it will not be cached.
  197. #define ALWAYS_EXPIRE "Expires: Tue, 01 Jan 1980 00:00:00 GMT\r\n\r\n"
  198. #if defined(GENERATE_AUTH_HEADERS)
  199. char WWW_AUTHENTICATE_HEADER[] = "WWW-Authenticate: ";
  200. #define W3SVC_REGISTRY_NTAUTHENTICATIONPROVIDERS "NtAuthenticationProviders"
  201. #define W3SVC_REGISTRY_AUTHENTICATION "Authorization"
  202. #endif
  203. #define W3SVC_REGISTRY_PATH "SYSTEM\\CurrentControlSet\\Services\\W3SVC\\Parameters"
  204. #define W3SVC_REGISTRY_HTMLAPATH "HtmlaPath"
  205. // tokens used to extend the HTML syntax. Extended tokens are inclosed
  206. // in a '<%' '%>' construct.
  207. BYTE TOKEN_BEGIN_ITERATION[]="beginiteration";
  208. BYTE TOKEN_END_ITERATION[]="enditeration";
  209. BYTE TOKEN_IF[]="if ";
  210. BYTE TOKEN_ELSE[]="else";
  211. BYTE TOKEN_ENDIF[]="endif";
  212. BYTE TOKEN_ELIF[]="elif ";
  213. BYTE TOKEN_REDIRECT[]="redirect";
  214. BYTE TOKEN_END_REDIRECT[]="/redirect";
  215. BYTE TOKEN_REDIRECTH[]="redirecthttp";
  216. BYTE TOKEN_END_REDIRECTH[]="/redirecthttp";
  217. BYTE TOKEN_GOTO[]="goto ";
  218. BYTE TOKEN_LABEL[]="label ";
  219. BYTE TOKEN_ONERROR[]="onerror ";
  220. BYTE TOKEN_POST[]="post";
  221. BYTE TOKEN_END_POST[]="/post";
  222. // null IP address used by the RPC admin layer to indicates a non-empty
  223. // IP security list
  224. char g_achIPNullAddr[]="0.0.0.0" REF_SEP_STR "255.255.255.255";
  225. LPSTR g_pszIPNullAddr = g_achIPNullAddr;
  226. // Instance handle of this DLL
  227. HINSTANCE g_hModule = (HINSTANCE)INVALID_HANDLE_VALUE;
  228. // Used to return a zero or one value when accessing an invalid DWORD variable
  229. DWORD g_dwZero = 0;
  230. DWORD g_dwOne = 1;
  231. // TRUE if invoked from a test shell ( i.e. not from the web server )
  232. BOOL g_fFakeServer = FALSE;
  233. #if defined(GENERATE_AUTH_HEADERS)
  234. CAuthenticationReqs g_AuthReqs;
  235. #endif
  236. BOOL g_InitDone = FALSE;
  237. PSTR g_pszDefaultHostName = NULL;
  238. CHAR g_achHtmlaPath[MAX_PATH + 1];
  239. CHAR g_achW3Version[128];
  240. CHAR g_achAccessDenied[128];
  241. CHAR g_achAccessDeniedBody[256];
  242. CHAR g_achInternalError[128];
  243. CHAR g_achNotFound[128];
  244. CHAR g_achNotFoundBody[256];
  245. #if defined(IISv1)
  246. OSVERSIONINFO g_OSVersion;
  247. DWORD g_dwCap1Flag = 0x0000003f;
  248. DWORD g_dwCap1Mask = 0x0000003f;
  249. #endif
  250. HINSTANCE g_hLonsi = NULL;
  251. GET_DEFAULT_DOMAIN_NAME_FN g_pfnGetDefaultDomainName = NULL;
  252. ////////// Directory lists management
  253. char g_achSysDir[MAX_PATH] = "";
  254. CDriveView::CDriveView(
  255. VOID )
  256. {
  257. }
  258. CDriveView::~CDriveView(
  259. VOID )
  260. {
  261. }
  262. BOOL
  263. CDriveView::Init(
  264. CInetInfoConfigInfoMapper* pM )
  265. {
  266. m_pMapper = pM;
  267. m_dsDriveName.Reset();
  268. m_dsDriveLabel.Reset();
  269. m_dsDriveType.Reset();
  270. m_dwCachedDrive = 0;
  271. m_tmCacheExpire = 0;
  272. m_cDrives = 0;
  273. if ( g_achSysDir[0] == '\0' )
  274. {
  275. if ( !GetSystemDirectory( g_achSysDir, sizeof(g_achSysDir) ) )
  276. {
  277. strcpy( g_achSysDir, "c:\\*.*" );
  278. }
  279. else
  280. {
  281. strcpy( g_achSysDir + 2, "\\*.*" );
  282. }
  283. }
  284. return TRUE;
  285. }
  286. BOOL
  287. CDriveView::Reset(
  288. VOID )
  289. {
  290. m_dsDirs.Reset();
  291. m_dsComp.Reset();
  292. m_dsFComp.Reset();
  293. m_cDirs = 0;
  294. m_cComp = 0;
  295. return TRUE;
  296. }
  297. BOOL
  298. CDriveView::Entry(
  299. UINT i,
  300. UINT cMax,
  301. CDStr &dsList,
  302. PVOID pRes )
  303. /*++
  304. Routine Description:
  305. Returns the ith entry ( base 0 ) in a CDStr considered
  306. as a collection of sz strings.
  307. Arguments:
  308. i - index of entry to return
  309. cMax - # of entries in the list
  310. dsList - CDStr as collection of sz string entries
  311. pRes - points to a LPSTR update with address of entry
  312. Returns:
  313. TRUE on success, FALSE on failure
  314. --*/
  315. {
  316. LPSTR pList = dsList.GetString();
  317. if ( i < cMax )
  318. {
  319. while ( i-- )
  320. {
  321. pList += strlen( pList ) + 1;
  322. }
  323. *(LPSTR*)pRes = pList;
  324. return TRUE;
  325. }
  326. return FALSE;
  327. }
  328. BOOL
  329. CDriveView::ValidateDir(
  330. LPSTR pDir )
  331. /*++
  332. Routine Description:
  333. Validate a directory path, set reqstatus HTR_VALIDATION_FAILED
  334. if path invalid.
  335. Arguments:
  336. pDir - directory path to validate
  337. Returns:
  338. TRUE on success, FALSE on failure
  339. updates reqstatus
  340. --*/
  341. {
  342. DWORD dwS;
  343. if ( (dwS = GetFileAttributes( pDir )) == 0xffffffff
  344. || !(dwS & FILE_ATTRIBUTE_DIRECTORY) )
  345. {
  346. m_pMapper->SetRequestStatus( HTR_VALIDATION_FAILED );
  347. }
  348. return TRUE;
  349. }
  350. BOOL
  351. CDriveView::CreateDir(
  352. LPSTR pPath,
  353. LPSTR pNewDir )
  354. /*++
  355. Routine Description:
  356. Create a new directory path from an existing path and
  357. a directory name to be created.
  358. set reqstatus HTR_VALIDATION_FAILED if creation fails
  359. Arguments:
  360. pPath - directory path inn which to create the new directory
  361. pNewDir - directory to create
  362. Returns:
  363. TRUE on success, FALSE on failure
  364. updates reqstatus
  365. --*/
  366. {
  367. BOOL fSt = FALSE;
  368. // Create path : insert '\\'\ between path and NewDir if
  369. // necessary
  370. int cP = strlen( pPath );
  371. LPSTR pDir = new char[cP + 1 + strlen(pNewDir) + 1];
  372. if ( pDir == NULL )
  373. {
  374. return FALSE;
  375. }
  376. memcpy( pDir, pPath, cP );
  377. if ( cP > 0
  378. && &pPath[cP-1] != (LPSTR)_mbsrchr((LPBYTE)pPath,'\\')
  379. && pPath[cP-1] != '/'
  380. && *pNewDir != '\\'
  381. && *pNewDir != '/' )
  382. {
  383. pDir[cP++] = '\\';
  384. }
  385. strcpy( pDir + cP, pNewDir );
  386. if ( !CreateDirectory( pDir, NULL ) )
  387. {
  388. m_pMapper->SetRequestStatus( HTR_VALIDATION_FAILED );
  389. }
  390. delete [] pDir;
  391. return TRUE;
  392. }
  393. extern "C" int __cdecl
  394. QsortStrCmp(
  395. const void *pA,
  396. const void *pB )
  397. {
  398. return _stricmp( *(LPSTR*)pA, *(LPSTR*)pB );
  399. }
  400. /* #pragma INTRINSA suppress=null_pointers */
  401. BOOL
  402. CDriveView::GenerateDirList(
  403. LPSTR pDrive )
  404. /*++
  405. Routine Description:
  406. Generate all directory lists and related values :
  407. m_achRootDir - path actually used in the search
  408. always contains a drive designation,
  409. ends with a '\'
  410. m_achBaseDir - as m_achRootDir but without trailing '\'
  411. m_dsComp - list of all the directory components of the path
  412. m_dsFComp - list of all the directory components of the path
  413. as an absolute path
  414. m_dsDirs - list of all sub-directory of the path
  415. m_dsDriveName - list of all drive names ( i.e "c:" )
  416. m_dsDriveLabel - list of all drive labels
  417. m_dsDriveType - list of all drive types ( as DRIVE_* )
  418. Arguments:
  419. pDrive - path where directory browsing is to take place.
  420. Returns:
  421. TRUE on success, FALSE on failure
  422. updates reqstatus
  423. --*/
  424. {
  425. WIN32_FIND_DATA fdF;
  426. NETRESOURCE *pNetResource;
  427. LPSTR pAdd;
  428. LPSTR pPath;
  429. BOOL fSt = TRUE;
  430. DWORD dwSize;
  431. DWORD cbBuffer;
  432. DWORD dwResult;
  433. HANDLE hEnum;
  434. DWORD cEntries;
  435. DWORD dwD;
  436. UINT i;
  437. int x;
  438. Reset();
  439. // replace all '/' with '\\'
  440. for ( pPath = pDrive ; pPath = strchr( pPath, '/' ) ; ++pPath )
  441. *pPath = '\\';
  442. // Normalize pPath from pDrive : must end with '\*.*'
  443. int cP = strlen( pDrive );
  444. if ( cP > 0 && &pDrive[cP-1] == (LPSTR)_mbsrchr((LPBYTE)pDrive,'\\') )
  445. {
  446. pAdd = "*.*";
  447. }
  448. else
  449. {
  450. if ( cP == 0 )
  451. {
  452. pAdd = g_achSysDir;
  453. }
  454. else
  455. {
  456. pAdd = "\\*.*";
  457. }
  458. }
  459. pPath = m_achRootDir;
  460. memcpy( pPath, pDrive, cP );
  461. strcpy( pPath + cP, pAdd );
  462. // check directory path valid, if not use default value
  463. HANDLE hF = FindFirstFile( pPath, &fdF) ;
  464. if ( hF == INVALID_HANDLE_VALUE )
  465. {
  466. strcpy( pPath, g_achSysDir );
  467. hF = FindFirstFile( pPath, &fdF) ;
  468. }
  469. if ( hF != INVALID_HANDLE_VALUE )
  470. {
  471. // build path component list
  472. m_cComp = 0;
  473. LPSTR pND, pCD = pPath;
  474. for ( ; pND = (LPSTR)_mbschr( (LPBYTE)pCD, '\\' ) ; pCD = pND + 1 )
  475. {
  476. // copy subdir, or drive letter + ':' + '\\' for root
  477. m_dsComp.AddRange( pCD, DIFF(pND - pCD) + (m_cComp == 0 ? 1 : 0) );
  478. m_dsComp.AddRange( "", sizeof("") );
  479. m_dsFComp.AddRange( pPath, DIFF(pND - pPath) + (m_cComp == 0 ? 1 : 0) );
  480. m_dsFComp.AddRange( "", sizeof("") );
  481. ++m_cComp;
  482. }
  483. CDStr dsTempDir;
  484. CDStr dsTempPtr;
  485. DWORD dwI;
  486. // build sub-directory list
  487. do {
  488. if ( fdF.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  489. {
  490. if ( strcmp( fdF.cFileName, "." ) && strcmp( fdF.cFileName, ".." ) )
  491. {
  492. dwI = dsTempDir.GetLen();
  493. dsTempDir.Add( fdF.cFileName );
  494. dsTempDir.AddRange( "", sizeof("") );
  495. dsTempPtr.AddRange( (LPSTR)&dwI, sizeof(DWORD) );
  496. ++m_cDirs;
  497. }
  498. }
  499. } while ( FindNextFile( hF, &fdF ) );
  500. if ( m_cDirs )
  501. {
  502. // adjust TempPtr from offset to ptr
  503. LPSTR *pA = (LPSTR*)dsTempPtr.GetString();
  504. for ( i = 0 ; i < m_cDirs ; ++i )
  505. {
  506. pA[i] = dsTempDir.GetString() + (ULONG_PTR)pA[i];
  507. }
  508. // sort
  509. qsort( pA, m_cDirs, sizeof(LPSTR), QsortStrCmp );
  510. // build sorted list
  511. for ( i = 0 ; i < m_cDirs ; ++ i )
  512. {
  513. m_dsDirs.AddRange( pA[i], strlen(pA[i]) + 1 );
  514. }
  515. }
  516. FindClose( hF );
  517. }
  518. else
  519. {
  520. if ( GetLastError() == ERROR_ACCESS_DENIED )
  521. {
  522. m_pMapper->SetRequestStatus( HTR_ACCESS_DENIED );
  523. }
  524. else
  525. {
  526. m_pMapper->SetRequestStatus( HTR_VALIDATION_FAILED );
  527. }
  528. }
  529. // build drive list
  530. dwD = GetLogicalDrives();
  531. if ( dwD == m_dwCachedDrive
  532. && time(NULL) < m_tmCacheExpire )
  533. {
  534. // use cache
  535. }
  536. else
  537. {
  538. // build list of name for network drives
  539. pNetResource = NULL;
  540. dwResult = WNetOpenEnum( RESOURCE_REMEMBERED, RESOURCETYPE_DISK,
  541. 0, NULL, &hEnum );
  542. if ( dwResult == NO_ERROR )
  543. {
  544. // start with a reasonable buffer size
  545. cbBuffer = 100 * sizeof( NETRESOURCE );
  546. pNetResource = (NETRESOURCE*) new BYTE[cbBuffer];
  547. while ( TRUE )
  548. {
  549. dwSize = cbBuffer,
  550. cEntries = 0xffffffff;
  551. dwResult = WNetEnumResource( hEnum, &cEntries, pNetResource,
  552. &dwSize );
  553. if ( dwResult == ERROR_MORE_DATA )
  554. {
  555. // the buffer was too small, enlarge
  556. cbBuffer = dwSize;
  557. delete [] pNetResource;
  558. pNetResource = (NETRESOURCE*) new BYTE[cbBuffer];
  559. continue;
  560. }
  561. if ( dwResult != NO_ERROR )
  562. {
  563. delete [] pNetResource;
  564. pNetResource = NULL;
  565. cEntries = 0;
  566. break;
  567. }
  568. break;
  569. }
  570. WNetCloseEnum( hEnum );
  571. }
  572. else
  573. {
  574. cEntries = 0;
  575. }
  576. // because of x86 compiler bug
  577. if ( pNetResource == NULL )
  578. {
  579. cEntries = 0;
  580. }
  581. m_dsDriveName.Reset();
  582. m_dsDriveLabel.Reset();
  583. m_dsDriveType.Reset();
  584. m_cDrives = 0;
  585. // iterate for all possible drive names
  586. for ( x = 0 ; x < 'Z'-'A'+1 ; ++x )
  587. {
  588. char achD[4];
  589. // check drive present and visible by this process
  590. if ( dwD & (1<<x) )
  591. {
  592. strcpy( achD + 1, ":\\" );
  593. achD[0] = 'A' + x;
  594. UINT iT = GetDriveType( achD );
  595. if ( iT > 1 )
  596. {
  597. DWORD dwI = iT;
  598. char achVolName[80];
  599. DWORD dwSerNum;
  600. DWORD dwCompLen;
  601. DWORD dwSysFlg;
  602. BOOL fInf = FALSE;
  603. // get volume information for non-removable
  604. // & non cd-rom ( too slow to get info )
  605. if ( iT == DRIVE_FIXED )
  606. {
  607. if ( GetVolumeInformation( achD,
  608. achVolName,
  609. sizeof(achVolName),
  610. &dwSerNum,
  611. &dwCompLen,
  612. &dwSysFlg,
  613. NULL,
  614. 0 ) )
  615. {
  616. m_dsDriveLabel.Add( achVolName );
  617. fInf = TRUE;
  618. }
  619. }
  620. else if ( iT == DRIVE_REMOTE )
  621. {
  622. if ( cEntries != 0 )
  623. {
  624. // search for the specified drive letter
  625. for ( i = 0; i < (int) cEntries; i++ )
  626. {
  627. if ( pNetResource[i].lpLocalName &&
  628. achD[0] == toupper(pNetResource[i]
  629. .lpLocalName[0]) )
  630. {
  631. m_dsDriveLabel.Add( pNetResource[i]
  632. .lpRemoteName );
  633. fInf = TRUE;
  634. }
  635. }
  636. }
  637. else
  638. {
  639. dwCompLen = sizeof( achVolName );
  640. achD[2] = '\0';
  641. if ( WNetGetConnection( achD, achVolName,
  642. &dwCompLen ) == NO_ERROR )
  643. {
  644. m_dsDriveLabel.Add( achVolName );
  645. fInf = TRUE;
  646. }
  647. }
  648. }
  649. if ( fInf )
  650. {
  651. m_dsDriveType.AddRange( (LPSTR)&dwI, sizeof(DWORD) );
  652. m_dsDriveName.AddRange( achD, 2 );
  653. m_dsDriveName.AddRange( "", sizeof("") );
  654. m_dsDriveLabel.AddRange( "", sizeof("") );
  655. }
  656. ++m_cDrives;
  657. }
  658. }
  659. }
  660. m_dwCachedDrive = dwD;
  661. if ( pNetResource != NULL )
  662. {
  663. delete [] pNetResource ;
  664. }
  665. }
  666. m_tmCacheExpire = time(NULL) + DRIVE_CACHE_EXPIRE;
  667. // delimit RootDir after last '\\'
  668. LPSTR pL = pPath + strlen(pPath);
  669. BOOL fAddedSep;
  670. pL = (LPSTR)_mbsrchr((LPBYTE)pPath, '\\');
  671. if (pL == NULL) pL = pPath;
  672. if ( pL == (LPSTR)_mbschr( (LPBYTE)pPath, '\\' ) )
  673. {
  674. fAddedSep = TRUE;
  675. ++pL;
  676. }
  677. else
  678. {
  679. fAddedSep = FALSE;
  680. }
  681. if ( pL != pPath )
  682. {
  683. *pL = '\0';
  684. }
  685. strcpy( m_achBaseDir, pPath );
  686. if ( fAddedSep )
  687. {
  688. *_mbschr( (LPBYTE)m_achBaseDir, '\\' ) = '\0';
  689. }
  690. return fSt;
  691. }
  692. // DEBUG handling
  693. #if defined(DEBUG_LEVEL)
  694. CInetInfoRequest *g_pReq;
  695. #endif
  696. void
  697. TR_DEBUG(
  698. int iLev,
  699. LPSTR pFormat,
  700. ... )
  701. {
  702. #if defined(DEBUG_LEVEL)
  703. if ( iLev <= DEBUG_LEVEL )
  704. {
  705. char achBuf[1024];
  706. va_list arglist;
  707. va_start( arglist, pFormat );
  708. UINT cL = (UINT)wvsprintf( achBuf, pFormat, arglist );
  709. g_pReq->GetBuffer()->CopyBuff( (LPBYTE)achBuf, cL );
  710. }
  711. #endif
  712. }
  713. // Global helper functions
  714. void
  715. DelimStrcpyN(
  716. LPSTR pDest,
  717. LPSTR pSrc,
  718. int cLen )
  719. {
  720. memcpy( pDest, pSrc, cLen );
  721. pDest[ cLen ] = '\0';
  722. }
  723. // Convert a Multi-byte string to a DWORD
  724. DWORD
  725. MultiByteToDWORD(
  726. LPSTR pSet )
  727. {
  728. DWORD dwV = 0;
  729. int c;
  730. while ( (c=*pSet) != '\0' && c==' ' )
  731. {
  732. ++pSet;
  733. }
  734. while ( (c=*pSet++) != '\0' && ((c>='0' && c<='9') || c==',') )
  735. {
  736. if ( c != ',' )
  737. {
  738. dwV = dwV*10 + c-'0';
  739. }
  740. }
  741. return dwV;
  742. }
  743. // Convert a DWORD to a Multi-byte string
  744. void
  745. DWORDToMultiByte(
  746. DWORD dwV,
  747. LPSTR pS )
  748. {
  749. LPSTR pF = pS;
  750. if ( dwV == 0 )
  751. {
  752. *pS++ = '0';
  753. }
  754. else for ( ; dwV ; dwV/=10 )
  755. {
  756. *pS++ = '0' + (int)(dwV%10);
  757. }
  758. *pS-- = '\0';
  759. while ( pF < pS )
  760. {
  761. int c = *pF;
  762. *pF++ = *pS;
  763. *pS-- = (CHAR)c;
  764. }
  765. }
  766. // convert ASCII Hex digit to UINT
  767. UINT
  768. HexCharToUINT(
  769. UINT cH )
  770. {
  771. if ( cH>='0' && cH<='9' )
  772. {
  773. return cH-'0';
  774. }
  775. else if ( cH>='a' && cH<='f' )
  776. {
  777. return cH-'a'+10;
  778. }
  779. else if ( cH>='A' && cH<='F' )
  780. {
  781. return cH-'A'+10;
  782. }
  783. return 0;
  784. }
  785. ///////////// Variable list
  786. // to be accessed by the '<%' varname '%>'construct, and by various tokens
  787. //
  788. // Most of these variables map directly to a member variable of one of the
  789. // structures defined bu the RPC admin layer ( cf. inetcom.h & inetinfo.h )
  790. //
  791. // Variables in iterated costructs ( e.g. virtual roots ) are to be used
  792. // in a beginiteration ... enditeration construct. The element being accessed
  793. // will be designated by the value of the CInetInfoConfigInfoMapper::m_iIter
  794. // variable.
  795. //
  796. // Some of these variables are "virtual" : they do not map to a RPC struct,
  797. // either because they are linked to the current BGI request ( e.g. reqstatus )
  798. // or because the UI need to access info in a different way that what the RPC
  799. // struct define ( e.g. we need to expose different variables to set/reset
  800. // authentication method even if they are stored in one DWORD bitmask in the
  801. // RPC struct ).
  802. CInetInfoMap g_InetInfoConfigInfoMap[] = {
  803. // request variables ( linked to the current BGI request )
  804. { "reqstatus", ITYPE_DWORD, &CInetInfoConfigInfoMapper::RequestStatus,
  805. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  806. },
  807. { "rpcstatus", ITYPE_DWORD, &CInetInfoConfigInfoMapper::RPCStatus,
  808. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  809. },
  810. { "rpcstatusstring", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::RPCStatusString,
  811. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  812. },
  813. { "iter", ITYPE_DWORD, &CInetInfoConfigInfoMapper::Iter,
  814. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  815. },
  816. { "httpstatus", ITYPE_DWORD, &CInetInfoConfigInfoMapper::HttpStatus,
  817. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  818. },
  819. { "ftpstatus", ITYPE_DWORD, &CInetInfoConfigInfoMapper::FtpStatus,
  820. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  821. },
  822. { "gopherstatus", ITYPE_DWORD, &CInetInfoConfigInfoMapper::GopherStatus,
  823. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  824. },
  825. // version information
  826. { "osmajorversion", ITYPE_DWORD, &CInetInfoConfigInfoMapper::OSMajorVersion,
  827. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  828. },
  829. { "osminorversion", ITYPE_DWORD, &CInetInfoConfigInfoMapper::OSMinorVersion,
  830. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  831. },
  832. { "osbuildnumber", ITYPE_DWORD, &CInetInfoConfigInfoMapper::OSBuildNumber,
  833. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  834. },
  835. { "majorversion", ITYPE_DWORD, &CInetInfoConfigInfoMapper::MajorVersion,
  836. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  837. },
  838. { "minorversion", ITYPE_DWORD, &CInetInfoConfigInfoMapper::MinorVersion,
  839. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  840. },
  841. { "w3version", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::W3Version,
  842. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  843. },
  844. { "platformtype", ITYPE_DWORD, &CInetInfoConfigInfoMapper::PlatformType,
  845. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  846. },
  847. { "cap1flag", ITYPE_DWORD, &CInetInfoConfigInfoMapper::Cap1Flag,
  848. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  849. },
  850. { "cap1mask", ITYPE_DWORD, &CInetInfoConfigInfoMapper::Cap1Mask,
  851. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  852. },
  853. { "userflags", ITYPE_DWORD, &CInetInfoConfigInfoMapper::UserFlags,
  854. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  855. },
  856. { "urlparam", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::URLParam,
  857. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  858. },
  859. { "servname", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::ServName,
  860. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  861. },
  862. { "servid", ITYPE_DWORD, &CInetInfoConfigInfoMapper::ServIdx,
  863. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  864. },
  865. { "reqparam", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::ReqParam,
  866. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  867. },
  868. { "remoteaddr", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::RemoteAddr,
  869. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  870. },
  871. { "ipnulladdr", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::IPNullAddr,
  872. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  873. },
  874. { "hostname", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::HostName,
  875. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  876. },
  877. { "htmlapath", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::HtmlaPath,
  878. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  879. },
  880. { "iter", ITYPE_DWORD, &CInetInfoConfigInfoMapper::Iter,
  881. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  882. },
  883. // INET_COM_CONFIG_INFO ( same name, different values for each service )
  884. { "comconntimeout", ITYPE_SHORTDW, &CInetInfoConfigInfoMapper::CommTimeout,
  885. &CInetInfoConfigInfoMapper::UpdateCommTimeout, 0
  886. },
  887. { "commaxconn", ITYPE_DWORD, &CInetInfoConfigInfoMapper::MaxConn,
  888. &CInetInfoConfigInfoMapper::UpdateMaxConn, 0
  889. },
  890. { "comadminname", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::AdminName,
  891. &CInetInfoConfigInfoMapper::UpdateAdminName, 0
  892. },
  893. { "comadminemail", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::AdminEmail,
  894. &CInetInfoConfigInfoMapper::UpdateAdminEmail, 0
  895. },
  896. { "comservercomment", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::ServerComment,
  897. &CInetInfoConfigInfoMapper::UpdateServerComment, 0
  898. },
  899. // INET_LOG_CONFIGURATION
  900. { "enablelog", ITYPE_BOOL, &CInetInfoConfigInfoMapper::EnableLog,
  901. &CInetInfoConfigInfoMapper::UpdateLog, 0
  902. } , // log type
  903. { "logtype", ITYPE_DWORD, &CInetInfoConfigInfoMapper::LogType,
  904. &CInetInfoConfigInfoMapper::UpdateLogType, 0
  905. },
  906. { "enablenewlog", ITYPE_BOOL, &CInetInfoConfigInfoMapper::EnableNewLog,
  907. &CInetInfoConfigInfoMapper::UpdateNewLog, 0
  908. } ,
  909. { "logperiod", ITYPE_DWORD, &CInetInfoConfigInfoMapper::LogPeriod,
  910. &CInetInfoConfigInfoMapper::UpdateLogPeriod, 0
  911. }, // log period
  912. { "logformat", ITYPE_DWORD, &CInetInfoConfigInfoMapper::LogFormat,
  913. &CInetInfoConfigInfoMapper::UpdateLogFormat, 0
  914. },
  915. { "logdir", ITYPE_AWCHAR, &CInetInfoConfigInfoMapper::LogDir,
  916. &CInetInfoConfigInfoMapper::UpdateLogFileInfo, MAX_PATH
  917. },
  918. { "logsize", ITYPE_1M, &CInetInfoConfigInfoMapper::LogSize,
  919. &CInetInfoConfigInfoMapper::UpdateLogSize, 0
  920. },
  921. { "logsrc", ITYPE_AWCHAR, &CInetInfoConfigInfoMapper::LogSrc,
  922. &CInetInfoConfigInfoMapper::UpdateLogODBCInfo, MAX_PATH // sizeof(INET_LOG_CONFIGURATION.rgchDataSource)
  923. },
  924. { "logname", ITYPE_AWCHAR, &CInetInfoConfigInfoMapper::LogName,
  925. &CInetInfoConfigInfoMapper::UpdateLogODBCInfo, MAX_TABLE_NAME_LEN // sizeof(INET_LOG_CONFIGURATION.rgchTableName)
  926. },
  927. { "loguser", ITYPE_AWCHAR, &CInetInfoConfigInfoMapper::LogUser,
  928. &CInetInfoConfigInfoMapper::UpdateLogODBCInfo, MAX_USER_NAME_LEN // sizeof(INET_LOG_CONFIGURATION.rgchUserName)
  929. },
  930. { "logpw", ITYPE_AWCHAR, &CInetInfoConfigInfoMapper::LogPw,
  931. &CInetInfoConfigInfoMapper::UpdateLogODBCInfo, MAX_PASSWORD_LEN // sizeof(INET_LOG_CONFIGURATION.rgchPassword)
  932. },
  933. { "invalidlogupdate", ITYPE_BOOL, &CInetInfoConfigInfoMapper::InvalidLogUpdate,
  934. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  935. },
  936. // INET_INFO_CONFIG_INFO
  937. { "loganon", ITYPE_BOOL, &CInetInfoConfigInfoMapper::LogAnonymous,
  938. &CInetInfoConfigInfoMapper::UpdateLogAnonymous, 0
  939. },
  940. { "lognona", ITYPE_BOOL, &CInetInfoConfigInfoMapper::LogNonAnonymous,
  941. &CInetInfoConfigInfoMapper::UpdateLogNonAnonymous, 0
  942. },
  943. { "anonun", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::AnonUserName,
  944. &CInetInfoConfigInfoMapper::UpdateAnonUserName, 0
  945. },
  946. { "anonpw", ITYPE_AWCHAR, &CInetInfoConfigInfoMapper::AnonUserPw,
  947. &CInetInfoConfigInfoMapper::UpdateAnonUserPw, PWLEN+1, // sizeof(INET_INFO_CONFIG_INFO.szAnonPassword)
  948. },
  949. { "authanon", ITYPE_BOOL, &CInetInfoConfigInfoMapper::AuthAnon,
  950. &CInetInfoConfigInfoMapper::UpdateAuth, 0
  951. },
  952. { "authbasic", ITYPE_BOOL, &CInetInfoConfigInfoMapper::AuthBasic,
  953. &CInetInfoConfigInfoMapper::UpdateAuth, 0
  954. },
  955. { "authnt", ITYPE_BOOL, &CInetInfoConfigInfoMapper::AuthNT,
  956. &CInetInfoConfigInfoMapper::UpdateAuth, 0
  957. },
  958. { "sport", ITYPE_SHORT, &CInetInfoConfigInfoMapper::SPort,
  959. &CInetInfoConfigInfoMapper::UpdateSPort, 0
  960. },
  961. // Deny IP list
  962. { "denyipcount", ITYPE_DWORD, &CInetInfoConfigInfoMapper::DenyIPCount,
  963. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  964. },
  965. { "denyisipsingle", ITYPE_BOOL, &CInetInfoConfigInfoMapper::DenyIsIPSingle,
  966. &CInetInfoConfigInfoMapper::UpdateDenyIsIPSingle, 0
  967. },
  968. { "denyipaddr", ITYPE_IP_ADDR, &CInetInfoConfigInfoMapper::DenyIPAddr,
  969. &CInetInfoConfigInfoMapper::UpdateIP, 0
  970. },
  971. { "denyipmask", ITYPE_IP_MASK, &CInetInfoConfigInfoMapper::DenyIPMask,
  972. &CInetInfoConfigInfoMapper::UpdateDenyIsIPSingle, 0
  973. },
  974. // Grant IP list
  975. { "grantipcount", ITYPE_DWORD, &CInetInfoConfigInfoMapper::GrantIPCount,
  976. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  977. },
  978. { "grantisipsingle", ITYPE_BOOL, &CInetInfoConfigInfoMapper::GrantIsIPSingle,
  979. &CInetInfoConfigInfoMapper::UpdateGrantIsIPSingle, 0
  980. },
  981. { "grantipaddr", ITYPE_IP_ADDR, &CInetInfoConfigInfoMapper::GrantIPAddr,
  982. &CInetInfoConfigInfoMapper::UpdateIP, 0
  983. },
  984. { "grantipmask", ITYPE_IP_MASK, &CInetInfoConfigInfoMapper::GrantIPMask,
  985. &CInetInfoConfigInfoMapper::UpdateGrantIsIPSingle, 0
  986. },
  987. // IP reference
  988. { "ipdenyref", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::IPDenyRef,
  989. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  990. },
  991. { "ipgrantref", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::IPGrantRef,
  992. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  993. },
  994. // Virtual root
  995. { "rootcount", ITYPE_DWORD, &CInetInfoConfigInfoMapper::RootCount,
  996. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  997. },
  998. { "rootname", ITYPE_VIRT_DIR_LPWSTR, &CInetInfoConfigInfoMapper::RootName,
  999. &CInetInfoConfigInfoMapper::UpdateRootName, 0
  1000. },
  1001. { "rootaddr", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::RootAddr,
  1002. &CInetInfoConfigInfoMapper::UpdateRoot, 0
  1003. },
  1004. { "rootdir", ITYPE_PATH_LPWSTR, &CInetInfoConfigInfoMapper::RootDir,
  1005. &CInetInfoConfigInfoMapper::UpdateRoot, 0
  1006. },
  1007. { "rootishome", ITYPE_BOOL, &CInetInfoConfigInfoMapper::RootIsHome,
  1008. &CInetInfoConfigInfoMapper::UpdateRoot, 0
  1009. },
  1010. { "rootisread", ITYPE_BOOL, &CInetInfoConfigInfoMapper::RootIsRead,
  1011. &CInetInfoConfigInfoMapper::UpdateRootMask, 0
  1012. },
  1013. { "rootiswrite", ITYPE_BOOL, &CInetInfoConfigInfoMapper::RootIsWrite,
  1014. &CInetInfoConfigInfoMapper::UpdateRootMask, 0
  1015. },
  1016. { "rootisexec", ITYPE_BOOL, &CInetInfoConfigInfoMapper::RootIsExec,
  1017. &CInetInfoConfigInfoMapper::UpdateRootMask, 0
  1018. },
  1019. { "rootisssl", ITYPE_BOOL, &CInetInfoConfigInfoMapper::RootIsSSL,
  1020. &CInetInfoConfigInfoMapper::UpdateRootMask, 0
  1021. },
  1022. { "rootacctname", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::RootAcctName,
  1023. &CInetInfoConfigInfoMapper::UpdateRoot, 0
  1024. },
  1025. { "rootacctpw", ITYPE_AWCHAR, &CInetInfoConfigInfoMapper::RootAcctPw,
  1026. &CInetInfoConfigInfoMapper::UpdateRoot, PWLEN +1 // sizeof(INET_INFO_VIRTUAL_ROOT_ENTRY.AccountPassword)
  1027. },
  1028. { "rooterror", ITYPE_DWORD, &CInetInfoConfigInfoMapper::RootError,
  1029. &CInetInfoConfigInfoMapper::UpdateRoot, 0
  1030. },
  1031. // Virtual Root reference
  1032. { "rootref", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::RootRef,
  1033. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1034. },
  1035. // W3
  1036. { "w3dirbrowseenabled", ITYPE_BOOL, &CInetInfoConfigInfoMapper::DirBrowseEnab,
  1037. &CInetInfoConfigInfoMapper::UpdateDirControl, 0
  1038. },
  1039. { "w3defaultfileenabled", ITYPE_BOOL, &CInetInfoConfigInfoMapper::DefFileEnab,
  1040. &CInetInfoConfigInfoMapper::UpdateDirControl, 0
  1041. },
  1042. { "w3defaultfile", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::DefFile,
  1043. &CInetInfoConfigInfoMapper::UpdateDefFile, 0
  1044. },
  1045. { "w3ssienabled", ITYPE_BOOL, &CInetInfoConfigInfoMapper::SSIEnabled,
  1046. &CInetInfoConfigInfoMapper::UpdateSSIEnabled, 0
  1047. },
  1048. { "w3ssiext", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::SSIExt,
  1049. &CInetInfoConfigInfoMapper::UpdateSSIExt, 0
  1050. },
  1051. { "w3cryptcapable", ITYPE_DWORD, &CInetInfoConfigInfoMapper::CryptCapable,
  1052. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1053. },
  1054. // Gopher
  1055. { "gophersite", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::GopherSite,
  1056. &CInetInfoConfigInfoMapper::UpdateGopherSite, 0
  1057. },
  1058. { "gopherorg", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::GopherOrg,
  1059. &CInetInfoConfigInfoMapper::UpdateGopherOrg, 0
  1060. },
  1061. { "gopherloc", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::GopherLoc,
  1062. &CInetInfoConfigInfoMapper::UpdateGopherLoc, 0
  1063. },
  1064. { "gophergeo", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::GopherGeo,
  1065. &CInetInfoConfigInfoMapper::UpdateGopherGeo, 0
  1066. },
  1067. { "gopherlang", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::GopherLang,
  1068. &CInetInfoConfigInfoMapper::UpdateGopherLang, 0
  1069. },
  1070. // FTP
  1071. { "ftpallowanon", ITYPE_BOOL, &CInetInfoConfigInfoMapper::FTPIsAnon,
  1072. &CInetInfoConfigInfoMapper::UpdateFTPIsAnon, 0
  1073. },
  1074. { "ftpallowguest", ITYPE_BOOL, &CInetInfoConfigInfoMapper::FTPIsGuest,
  1075. &CInetInfoConfigInfoMapper::UpdateFTPIsGuest, 0
  1076. },
  1077. { "ftpannotdir", ITYPE_BOOL, &CInetInfoConfigInfoMapper::FTPIsAnotDir,
  1078. &CInetInfoConfigInfoMapper::UpdateFTPIsAnotDir, 0
  1079. },
  1080. { "ftpanononly", ITYPE_BOOL, &CInetInfoConfigInfoMapper::FTPIsAnonOnly,
  1081. &CInetInfoConfigInfoMapper::UpdateFTPIsAnonOnly, 0
  1082. },
  1083. { "ftpexitmsg", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::FTPExitMsg,
  1084. &CInetInfoConfigInfoMapper::UpdateFTPExitMsg, 0
  1085. },
  1086. { "ftpgreetmsg", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::FTPGreetMsg,
  1087. &CInetInfoConfigInfoMapper::UpdateFTPGreetMsg, 0
  1088. },
  1089. { "ftphomedir", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::FTPHomeDir,
  1090. &CInetInfoConfigInfoMapper::UpdateFTPHomeDir, 0
  1091. },
  1092. { "ftmaxclmsg", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::FTPMaxClMsg,
  1093. &CInetInfoConfigInfoMapper::UpdateFTPMaxClMsg, 0
  1094. },
  1095. { "ftpmsdosdirout", ITYPE_BOOL, &CInetInfoConfigInfoMapper::FTPIsMsdos,
  1096. &CInetInfoConfigInfoMapper::UpdateFTPIsMsdos, 0
  1097. },
  1098. // User enumeration
  1099. { "enumusercount", ITYPE_DWORD, &CInetInfoConfigInfoMapper::UCount,
  1100. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1101. },
  1102. { "enumusername", ITYPE_LPWSTR, &CInetInfoConfigInfoMapper::UName,
  1103. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1104. },
  1105. { "enumuseranon", ITYPE_BOOL, &CInetInfoConfigInfoMapper::UAnonymous,
  1106. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1107. },
  1108. { "enumuseraddr", ITYPE_IP_ADDR, &CInetInfoConfigInfoMapper::UAddr,
  1109. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1110. },
  1111. { "enumusertime", ITYPE_TIME, &CInetInfoConfigInfoMapper::UTime,
  1112. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1113. },
  1114. { "enumuserid", ITYPE_DWORD, &CInetInfoConfigInfoMapper::UID,
  1115. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1116. },
  1117. // Global
  1118. { "globalisbandwidthlimited", ITYPE_DWORD, &CInetInfoConfigInfoMapper::GlobalIsBandwidthLimited,
  1119. &CInetInfoConfigInfoMapper::UpdateGlobalIsBandwidthLimited, 0
  1120. },
  1121. { "globalbandwidth", ITYPE_1K, &CInetInfoConfigInfoMapper::GlobalBandwidth,
  1122. &CInetInfoConfigInfoMapper::UpdateGlobalBandwidth, 0
  1123. },
  1124. { "globalcache", ITYPE_DWORD, &CInetInfoConfigInfoMapper::GlobalCache,
  1125. &CInetInfoConfigInfoMapper::UpdateGlobal, 0
  1126. },
  1127. } ;
  1128. CInetInfoMap g_InetInfoDirInfoMap[] = {
  1129. // request variables ( linked to the current BGI request )
  1130. { "reqstatus", ITYPE_DWORD, &CInetInfoConfigInfoMapper::RequestStatus,
  1131. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1132. },
  1133. { "rpcstatus", ITYPE_DWORD, &CInetInfoConfigInfoMapper::RPCStatus,
  1134. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1135. },
  1136. { "rpcstatusstring", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::RPCStatusString,
  1137. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1138. },
  1139. { "iter", ITYPE_DWORD, &CInetInfoConfigInfoMapper::Iter,
  1140. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  1141. },
  1142. { "userflags", ITYPE_DWORD, &CInetInfoConfigInfoMapper::UserFlags,
  1143. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1144. },
  1145. { "urlparam", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::URLParam,
  1146. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  1147. },
  1148. { "reqparam", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::ReqParam,
  1149. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  1150. },
  1151. { "remoteaddr", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::RemoteAddr,
  1152. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  1153. },
  1154. { "hostname", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::HostName,
  1155. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  1156. },
  1157. { "htmlapath", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::HtmlaPath,
  1158. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  1159. },
  1160. { "arg1", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::Arg1,
  1161. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  1162. },
  1163. { "arg2", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::Arg2,
  1164. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  1165. },
  1166. { "arg3", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::Arg3,
  1167. &CInetInfoConfigInfoMapper::DenyUpdate , 0
  1168. },
  1169. // version information
  1170. { "w3version", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::W3Version,
  1171. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1172. },
  1173. { "platformtype", ITYPE_DWORD, &CInetInfoConfigInfoMapper::PlatformType,
  1174. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1175. },
  1176. { "w3cryptcapable", ITYPE_DWORD, &CInetInfoConfigInfoMapper::CryptCapable,
  1177. &CInetInfoConfigInfoMapper::DenyUpdate, 0
  1178. },
  1179. { "rootdir", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::DirRootDir,
  1180. &CInetInfoConfigInfoMapper::IgnoreUpdate , 0
  1181. },
  1182. { "basedir", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::DirBaseDir,
  1183. &CInetInfoConfigInfoMapper::IgnoreUpdate, 0
  1184. },
  1185. { "dircount", ITYPE_DWORD, &CInetInfoConfigInfoMapper::DirCount,
  1186. &CInetInfoConfigInfoMapper::IgnoreUpdate , 0
  1187. },
  1188. { "direntry", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::DirEntry,
  1189. &CInetInfoConfigInfoMapper::IgnoreUpdate , 0
  1190. },
  1191. { "dircompcount", ITYPE_DWORD, &CInetInfoConfigInfoMapper::DirCompCount,
  1192. &CInetInfoConfigInfoMapper::IgnoreUpdate , 0
  1193. },
  1194. { "dircompentry", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::DirCompEntry,
  1195. &CInetInfoConfigInfoMapper::IgnoreUpdate , 0
  1196. },
  1197. { "dirfcompentry", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::DirFCompEntry,
  1198. &CInetInfoConfigInfoMapper::IgnoreUpdate , 0
  1199. },
  1200. { "drivecount", ITYPE_DWORD, &CInetInfoConfigInfoMapper::DriveCount,
  1201. &CInetInfoConfigInfoMapper::IgnoreUpdate , 0
  1202. },
  1203. { "drivenameentry", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::DriveNameEntry,
  1204. &CInetInfoConfigInfoMapper::IgnoreUpdate , 0
  1205. },
  1206. { "drivelabelentry", ITYPE_LPSTR, &CInetInfoConfigInfoMapper::DriveLabelEntry,
  1207. &CInetInfoConfigInfoMapper::IgnoreUpdate , 0
  1208. },
  1209. { "drivetypeentry", ITYPE_DWORD, &CInetInfoConfigInfoMapper::DriveTypeEntry,
  1210. &CInetInfoConfigInfoMapper::IgnoreUpdate , 0
  1211. },
  1212. } ;
  1213. ///////////// User enumeration
  1214. // Generic for all services. This structure is bound to
  1215. // a CInetInfoConfigInfoMapper object, which will provide service type.
  1216. // Gives access to the list of currently connected users for this service.
  1217. CUserEnum::CUserEnum(
  1218. VOID )
  1219. {
  1220. }
  1221. CUserEnum::~CUserEnum(
  1222. VOID )
  1223. {
  1224. }
  1225. BOOL
  1226. CUserEnum::Init(
  1227. CInetInfoConfigInfoMapper* pM )
  1228. {
  1229. m_pMapper = pM;
  1230. m_pUsers = NULL;
  1231. Reset();
  1232. return TRUE;
  1233. }
  1234. // Unbind object with user list
  1235. void
  1236. CUserEnum::Reset(
  1237. VOID )
  1238. {
  1239. if ( m_pUsers != NULL )
  1240. {
  1241. MIDL_user_free( m_pUsers );
  1242. m_pUsers = NULL;
  1243. }
  1244. m_dwCount = 0;
  1245. }
  1246. // Insure list loaded. This allow usage on a "load on demand" basis
  1247. BOOL
  1248. CUserEnum::InsureLoaded(
  1249. VOID )
  1250. {
  1251. NET_API_STATUS is = 0;
  1252. if ( m_pUsers == NULL )
  1253. {
  1254. // get list relevant to current service
  1255. __try {
  1256. switch ( m_pMapper->GetType() )
  1257. {
  1258. case INET_HTTP_SVC_ID:
  1259. is = W3EnumerateUsers( m_pMapper->GetComputerName(),
  1260. &m_dwCount, &m_pUsers );
  1261. break;
  1262. case INET_FTP_SVC_ID:
  1263. is = I_FtpEnumerateUsers( m_pMapper->GetComputerName(),
  1264. &m_dwCount, (LPFTP_USER_INFO*)&m_pUsers );
  1265. break;
  1266. default:
  1267. // no list : error
  1268. is = (NET_API_STATUS)~0;
  1269. break;
  1270. }
  1271. }
  1272. __except( EXCEPTION_EXECUTE_HANDLER )
  1273. {
  1274. if ( m_pUsers != NULL )
  1275. {
  1276. MIDL_user_free( m_pUsers );
  1277. }
  1278. is = (NET_API_STATUS)~0;
  1279. }
  1280. if ( is != 0 )
  1281. {
  1282. m_pMapper->SetRequestStatus( HTR_USER_ENUM_ACCESS_ERROR );
  1283. }
  1284. }
  1285. return is == 0 ? TRUE : FALSE;
  1286. }
  1287. // User count
  1288. BOOL
  1289. CUserEnum::GetCount(
  1290. LPVOID* pV )
  1291. {
  1292. if ( InsureLoaded() )
  1293. {
  1294. *pV = (LPVOID)&m_dwCount;
  1295. return TRUE;
  1296. }
  1297. return FALSE;
  1298. }
  1299. // User Name
  1300. BOOL
  1301. CUserEnum::GetName(
  1302. LPVOID* pV )
  1303. {
  1304. DWORD dwI = m_pMapper->GetIter();
  1305. if ( InsureLoaded() && dwI < m_dwCount )
  1306. {
  1307. *pV = (LPVOID)&m_pUsers[dwI].pszUser;
  1308. return TRUE;
  1309. }
  1310. return FALSE;
  1311. }
  1312. // Is user logged-in as anonymous ?
  1313. BOOL
  1314. CUserEnum::GetAnonymous(
  1315. LPVOID* pV )
  1316. {
  1317. DWORD dwI = m_pMapper->GetIter();
  1318. if ( InsureLoaded() && dwI < m_dwCount )
  1319. {
  1320. *pV = (LPVOID)&m_pUsers[dwI].fAnonymous;
  1321. return TRUE;
  1322. }
  1323. return FALSE;
  1324. }
  1325. // User IP address
  1326. BOOL
  1327. CUserEnum::GetAddr(
  1328. LPVOID* pV )
  1329. {
  1330. DWORD dwI = m_pMapper->GetIter();
  1331. if ( InsureLoaded() && dwI < m_dwCount )
  1332. {
  1333. *pV = (LPVOID)&m_pUsers[dwI].inetHost;
  1334. return TRUE;
  1335. }
  1336. return FALSE;
  1337. }
  1338. BOOL
  1339. CUserEnum::GetCountAsDWORD(
  1340. LPDWORD pDW )
  1341. {
  1342. if ( InsureLoaded() )
  1343. {
  1344. *pDW = m_dwCount;
  1345. return TRUE;
  1346. }
  1347. return FALSE;
  1348. }
  1349. BOOL
  1350. CUserEnum::GetIDAsDWORD(
  1351. LPDWORD pDW )
  1352. {
  1353. DWORD dwI = m_pMapper->GetIter();
  1354. if ( InsureLoaded() && dwI < m_dwCount )
  1355. {
  1356. *pDW = m_pUsers[dwI].idUser;
  1357. return TRUE;
  1358. }
  1359. return FALSE;
  1360. }
  1361. // User connection time
  1362. BOOL
  1363. CUserEnum::GetTime(
  1364. LPVOID* pV )
  1365. {
  1366. DWORD dwI = m_pMapper->GetIter();
  1367. if ( InsureLoaded() && dwI < m_dwCount )
  1368. {
  1369. *pV = (LPVOID)&m_pUsers[dwI].tConnect;
  1370. return TRUE;
  1371. }
  1372. return FALSE;
  1373. }
  1374. // User ID
  1375. BOOL
  1376. CUserEnum::GetID(
  1377. LPVOID* pV )
  1378. {
  1379. DWORD dwI = m_pMapper->GetIter();
  1380. if ( InsureLoaded() && dwI < m_dwCount )
  1381. {
  1382. *pV = (LPVOID)&m_pUsers[dwI].idUser;
  1383. return TRUE;
  1384. }
  1385. return FALSE;
  1386. }
  1387. ///////////// Dynamic string class
  1388. CDStr::CDStr(
  1389. VOID )
  1390. {
  1391. Init();
  1392. }
  1393. CDStr::~CDStr(
  1394. VOID )
  1395. {
  1396. if ( m_pStr != NULL )
  1397. {
  1398. delete [] m_pStr;
  1399. }
  1400. }
  1401. void
  1402. CDStr::Reset(
  1403. VOID )
  1404. {
  1405. if ( m_pStr != NULL )
  1406. {
  1407. delete [] m_pStr;
  1408. }
  1409. Init();
  1410. }
  1411. BOOL
  1412. CDStr::Init(
  1413. VOID )
  1414. {
  1415. m_pStr = NULL;
  1416. m_dwAlloc = m_dwLen = 0;
  1417. return TRUE;
  1418. }
  1419. LPSTR
  1420. CDStr::GetString(
  1421. VOID )
  1422. {
  1423. return m_pStr;
  1424. }
  1425. BOOL
  1426. CDStr::Add(
  1427. LPSTR pS )
  1428. /*++
  1429. Routine Description:
  1430. Add a sz string to a dynamic string
  1431. Arguments:
  1432. pS - string to add at the end of the dynamic string
  1433. Returns:
  1434. TRUE on success, FALSE on failure
  1435. --*/
  1436. {
  1437. return AddRange( pS, lstrlen( pS ) );
  1438. }
  1439. BOOL
  1440. CDStr::AddRange(
  1441. LPSTR pS,
  1442. DWORD dwL )
  1443. /*++
  1444. Routine Description:
  1445. Add a character range to a dynamic string
  1446. Arguments:
  1447. pS - character range to add at the end of the dynamic string
  1448. dwL - # of characters to add
  1449. Returns:
  1450. TRUE on success, FALSE on failure
  1451. --*/
  1452. {
  1453. if ( m_dwLen + dwL + 1 > m_dwAlloc )
  1454. {
  1455. DWORD dwN = ( ( m_dwLen + dwL + 1 + 128 ) / 128 ) * 128;
  1456. LPSTR pN = new char[dwN];
  1457. if ( pN == NULL )
  1458. {
  1459. return FALSE;
  1460. }
  1461. if ( m_pStr != NULL )
  1462. {
  1463. memcpy( pN, m_pStr, m_dwLen );
  1464. delete [] m_pStr;
  1465. }
  1466. m_pStr = pN;
  1467. m_dwAlloc = dwN;
  1468. }
  1469. memcpy( m_pStr + m_dwLen, pS, dwL );
  1470. m_dwLen += dwL;
  1471. m_pStr[ m_dwLen ] = '\0';
  1472. return TRUE;
  1473. }
  1474. #if defined(GENERATE_AUTH_HEADERS)
  1475. //
  1476. // This class handles the generation of the authentication sequence
  1477. // as a list of supported WWW-Authenticate scheme.
  1478. // This is necessary for IIS/1.0, not for IIS/1.1+
  1479. //
  1480. CAuthenticationReqs::CAuthenticationReqs(
  1481. VOID )
  1482. {
  1483. }
  1484. CAuthenticationReqs::~CAuthenticationReqs(
  1485. VOID )
  1486. {
  1487. }
  1488. DWORD
  1489. WINAPI AuthUpdateIndication(
  1490. LPVOID pV )
  1491. {
  1492. return ((CAuthenticationReqs*)pV)->UpdateIndication();
  1493. }
  1494. BOOL
  1495. CAuthenticationReqs::Init(
  1496. VOID )
  1497. /*++
  1498. Routine Description:
  1499. Initialize the authentication package, which provides a way
  1500. for an ISAPI app to retrieve the list of supported authentication
  1501. methods as a list of HTTP WWW-Authenticate headers.
  1502. build the initial authentication list, create a registry update
  1503. monitor thread to check for changes in supported authentication
  1504. methods.
  1505. Arguments:
  1506. None
  1507. Returns:
  1508. TRUE on success, FALSE on failure
  1509. --*/
  1510. {
  1511. m_dsH.Init();
  1512. m_pszProviders = NULL;
  1513. INITIALIZE_CRITICAL_SECTION( &m_csR );
  1514. m_hNotifyEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  1515. m_fRequestTerminate = FALSE;
  1516. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1517. W3SVC_REGISTRY_PATH,
  1518. 0,
  1519. KEY_READ,
  1520. &m_hKey ) == ERROR_SUCCESS )
  1521. {
  1522. // retrieve methods
  1523. UpdateMethodsIndication();
  1524. // retrieve NT list
  1525. UpdateNTAuthenticationProvidersIndication();
  1526. // create registry monitoring thread
  1527. DWORD dwID;
  1528. if ( (m_hThread = CreateThread( NULL,
  1529. 0,
  1530. (LPTHREAD_START_ROUTINE)::AuthUpdateIndication,
  1531. (LPVOID)this,
  1532. 0,
  1533. &dwID )) == NULL )
  1534. {
  1535. return FALSE;
  1536. }
  1537. return BuildListHeader();
  1538. }
  1539. else
  1540. {
  1541. m_hKey = NULL;
  1542. }
  1543. return FALSE;
  1544. }
  1545. //
  1546. // wait for an update notification from the registry
  1547. //
  1548. DWORD
  1549. CAuthenticationReqs::UpdateIndication(
  1550. VOID )
  1551. /*++
  1552. Routine Description:
  1553. Thread monitoring authentication methods update in registry
  1554. Arguments:
  1555. None
  1556. Returns:
  1557. NT error
  1558. --*/
  1559. {
  1560. for ( ;; )
  1561. {
  1562. if ( RegNotifyChangeKeyValue( m_hKey,
  1563. FALSE,
  1564. REG_NOTIFY_CHANGE_LAST_SET,
  1565. m_hNotifyEvent,
  1566. TRUE ) != ERROR_SUCCESS )
  1567. {
  1568. break;
  1569. }
  1570. if ( WaitForSingleObject( m_hNotifyEvent, INFINITE)
  1571. != WAIT_OBJECT_0 )
  1572. {
  1573. break;
  1574. }
  1575. if ( m_fRequestTerminate )
  1576. {
  1577. break;
  1578. }
  1579. UpdateMethodsIndication();
  1580. UpdateNTAuthenticationProvidersIndication();
  1581. BuildListHeader();
  1582. }
  1583. return 0;
  1584. }
  1585. BOOL
  1586. CAuthenticationReqs::Terminate(
  1587. VOID )
  1588. /*++
  1589. Routine Description:
  1590. Request the monitoring thread to terminate
  1591. Arguments:
  1592. None
  1593. Returns:
  1594. TRUE if thread successfully terminated, else FALSE
  1595. --*/
  1596. {
  1597. // request thread kill
  1598. m_fRequestTerminate = TRUE;
  1599. SetEvent( m_hNotifyEvent );
  1600. if ( m_hThread != NULL && WaitForSingleObject( m_hThread, 1000 * 3 )
  1601. == WAIT_OBJECT_0 )
  1602. {
  1603. CloseHandle( m_hThread );
  1604. m_hThread = NULL;
  1605. DeleteCriticalSection( &m_csR );
  1606. if ( m_pszProviders != NULL )
  1607. {
  1608. delete [] m_pszProviders;
  1609. }
  1610. if ( m_hKey != NULL )
  1611. {
  1612. RegCloseKey( m_hKey );
  1613. }
  1614. if ( m_hNotifyEvent != NULL )
  1615. {
  1616. CloseHandle( m_hNotifyEvent );
  1617. }
  1618. if ( m_hThread != NULL )
  1619. {
  1620. CloseHandle( m_hThread );
  1621. }
  1622. return TRUE;
  1623. }
  1624. return FALSE;
  1625. }
  1626. BOOL
  1627. CAuthenticationReqs::UpdateMethodsIndication(
  1628. VOID )
  1629. /*++
  1630. Routine Description:
  1631. Update bitmap of supported authentication methods
  1632. Arguments:
  1633. None
  1634. Returns:
  1635. TRUE on success, else FALSE
  1636. --*/
  1637. {
  1638. BOOL fSt = FALSE;
  1639. Lock();
  1640. // access registry
  1641. DWORD dwType;
  1642. DWORD dwM;
  1643. DWORD cData = sizeof( dwM );
  1644. if ( RegQueryValueEx( m_hKey, W3SVC_REGISTRY_AUTHENTICATION,
  1645. NULL, &dwType, (PBYTE)&dwM, &cData ) == ERROR_SUCCESS
  1646. && dwType == REG_DWORD )
  1647. {
  1648. fSt = TRUE;
  1649. m_dwMethods = dwM;
  1650. }
  1651. UnLock();
  1652. return fSt;
  1653. }
  1654. BOOL
  1655. CAuthenticationReqs::BuildListHeader(
  1656. VOID )
  1657. /*++
  1658. Routine Description:
  1659. Build a list of HTTP headers specifying all authentication methods
  1660. supported by the local HTTP server in m_dsH
  1661. Arguments:
  1662. None
  1663. Returns:
  1664. TRUE on success, FALSE on failure
  1665. --*/
  1666. {
  1667. BOOL fAdded = FALSE;
  1668. Lock();
  1669. m_dsH.Reset();
  1670. if ( m_dwMethods & INET_INFO_AUTH_CLEARTEXT )
  1671. {
  1672. m_dsH.Add( WWW_AUTHENTICATE_HEADER );
  1673. m_dsH.Add( "Basic realm=\"NTSRV\"\r\n" );
  1674. fAdded = TRUE;
  1675. }
  1676. if ( (m_dwMethods & INET_INFO_AUTH_NT_AUTH)
  1677. && m_pszProviders != NULL )
  1678. {
  1679. LPSTR pS, pT;
  1680. // iterate through comma-separated list
  1681. for ( pS = m_pszProviders ; *pS ; )
  1682. {
  1683. if ( (pT = strchr( pS, ',' )) == NULL )
  1684. {
  1685. pT = pS + lstrlen( pS );
  1686. }
  1687. m_dsH.Add( WWW_AUTHENTICATE_HEADER );
  1688. m_dsH.AddRange( pS, pT - pS );
  1689. m_dsH.Add( "\r\n" );
  1690. pS = *pT ? pT + 1 : pT;
  1691. fAdded = TRUE;
  1692. }
  1693. }
  1694. if ( fAdded )
  1695. {
  1696. m_dsH.Add( "\r\n" );
  1697. }
  1698. UnLock();
  1699. return TRUE;
  1700. }
  1701. BOOL
  1702. CAuthenticationReqs::UpdateNTAuthenticationProvidersIndication(
  1703. VOID )
  1704. /*++
  1705. Routine Description:
  1706. Update list of supported SSPI authentication methods
  1707. Arguments:
  1708. None
  1709. Returns:
  1710. TRUE on success, FALSE on failure
  1711. --*/
  1712. {
  1713. BOOL fSt = FALSE;
  1714. Lock();
  1715. if ( m_pszProviders != NULL )
  1716. {
  1717. delete [] m_pszProviders;
  1718. m_pszProviders = NULL;
  1719. }
  1720. // access registry
  1721. DWORD cData = 256;
  1722. DWORD dwType;
  1723. if ( (m_pszProviders = new char[cData]) != NULL )
  1724. {
  1725. if ( RegQueryValueEx( m_hKey,
  1726. W3SVC_REGISTRY_NTAUTHENTICATIONPROVIDERS,
  1727. NULL,
  1728. &dwType,
  1729. (PBYTE)m_pszProviders,
  1730. &cData ) == ERROR_SUCCESS
  1731. && dwType == REG_SZ )
  1732. {
  1733. fSt = TRUE;
  1734. }
  1735. else
  1736. {
  1737. delete [] m_pszProviders;
  1738. m_pszProviders = NULL;
  1739. }
  1740. }
  1741. UnLock();
  1742. return fSt;
  1743. }
  1744. LPSTR
  1745. CAuthenticationReqs::GetAuthenticationListHeader(
  1746. VOID )
  1747. /*++
  1748. Routine Description:
  1749. Return the list of supported authentication
  1750. methods as a list of HTTP WWW-Authenticate headers.
  1751. The returned string is either empty or terminated by
  1752. a blank line.
  1753. Arguments:
  1754. None
  1755. Returns:
  1756. TRUE on success, FALSE on failure
  1757. --*/
  1758. {
  1759. return m_dsH.GetString();
  1760. }
  1761. #endif
  1762. ///////////// Mapper
  1763. CInetInfoConfigInfoMapper::CInetInfoConfigInfoMapper(
  1764. VOID )
  1765. {
  1766. }
  1767. CInetInfoConfigInfoMapper::~CInetInfoConfigInfoMapper(
  1768. VOID )
  1769. {
  1770. #if !defined(IISv1)
  1771. if ( m_pServerCaps != NULL )
  1772. {
  1773. MIDL_user_free( m_pServerCaps );
  1774. }
  1775. #endif
  1776. DeleteCriticalSection( &m_csLock );
  1777. }
  1778. BOOL
  1779. CInetInfoConfigInfoMapper::Init(
  1780. CInetInfoMap* pMap,
  1781. int cNbMap,
  1782. DWORD dwS )
  1783. {
  1784. INITIALIZE_CRITICAL_SECTION( &m_csLock );
  1785. m_pMap = pMap;
  1786. m_cNbMap = cNbMap;
  1787. m_dwCurrentServerType = dwS;
  1788. m_pGlobalConfig = NULL;
  1789. m_pConfig = NULL;
  1790. m_pServerCaps = NULL;
  1791. m_pW3Config = NULL;
  1792. m_pFtpConfig = NULL;
  1793. m_pGdConfig = NULL;
  1794. m_pFirstAlloc = m_pLastAlloc = NULL;
  1795. m_fGotServerCapsAndVersion = FALSE;
  1796. m_pszHtmlaPath = g_achHtmlaPath;
  1797. m_pszHostName = m_achHostName;
  1798. m_pszW3Version = g_achW3Version;
  1799. m_pszRPCStatusString = NULL;
  1800. m_fAllocatedRPCStatusString = FALSE;
  1801. m_Users.Init( this );
  1802. m_Drive.Init( this );
  1803. return TRUE;
  1804. }
  1805. // variables access
  1806. BOOL
  1807. CInetInfoConfigInfoMapper::GlobalIsBandwidthLimited(
  1808. LPVOID* pV )
  1809. /*++
  1810. Routine Description:
  1811. Update a pointer to the virtual variable exposing the
  1812. "global bandwidth is limited" setting.
  1813. HTMLA var: "globalisbandwidthlimited"
  1814. Arguments:
  1815. None
  1816. Returns:
  1817. TRUE on success, FALSE on failure
  1818. --*/
  1819. {
  1820. if ( m_pGlobalConfig != NULL )
  1821. {
  1822. m_dwIsBandwidthLimited = m_pGlobalConfig->BandwidthLevel
  1823. != DWORD(-1) ? TRUE : FALSE;
  1824. *pV = (LPVOID)&m_dwIsBandwidthLimited;
  1825. return TRUE;
  1826. }
  1827. return FALSE;
  1828. }
  1829. void
  1830. CInetInfoConfigInfoMapper::AdjustFromIPSingle(
  1831. LPBYTE pMsk )
  1832. /*++
  1833. Routine Description:
  1834. Adjust network mask to be consistent
  1835. with the virtual var controlling if this entry is for
  1836. a single address or not.
  1837. If single address the mask if set to all 1 ( i.e. the whole
  1838. network address is significant ).
  1839. Arguments:
  1840. None
  1841. Returns:
  1842. None
  1843. --*/
  1844. {
  1845. if ( m_dwIsIPSingle == 1 )
  1846. {
  1847. memset( pMsk, 0xff, IP_ADDR_BYTE_SIZE );
  1848. }
  1849. }
  1850. void
  1851. CInetInfoConfigInfoMapper::AdjustIPSingle(
  1852. LPBYTE pMsk )
  1853. /*++
  1854. Routine Description:
  1855. Determine if the mask describes a single IP address ( i.e. is all 1 )
  1856. and updates the virtual var controlling 'singleness' accordingly
  1857. Arguments:
  1858. None
  1859. Returns:
  1860. None
  1861. --*/
  1862. {
  1863. m_dwIsIPSingle = 0;
  1864. for ( int x = 0 ; x < IP_ADDR_BYTE_SIZE ; ++x )
  1865. {
  1866. if ( pMsk[x] != 0xff )
  1867. {
  1868. return;
  1869. }
  1870. }
  1871. m_dwIsIPSingle = 1;
  1872. }
  1873. BOOL
  1874. CInetInfoConfigInfoMapper::DenyIsIPSingle(
  1875. LPVOID* pV )
  1876. /*++
  1877. Routine Description:
  1878. Adjust the virtual variable to be TRUE if the current entry
  1879. in the IP deny access list is a single address, otherwise FALSE.
  1880. Update a pointer to this virtual variable on exit.
  1881. HTMLA var: "denyisipsingle"
  1882. Arguments:
  1883. None
  1884. Returns:
  1885. TRUE on success, FALSE on failure
  1886. --*/
  1887. {
  1888. if ( m_pConfig!=NULL && m_pConfig->DenyIPList
  1889. && m_iIter < m_pConfig->DenyIPList->cEntries )
  1890. {
  1891. AdjustIPSingle( (LPBYTE)&m_pConfig->DenyIPList
  1892. ->aIPSecEntry[m_iIter].dwMask );
  1893. *pV = (LPVOID)&m_dwIsIPSingle;
  1894. return TRUE;
  1895. }
  1896. return FALSE;
  1897. }
  1898. BOOL
  1899. CInetInfoConfigInfoMapper::GrantIsIPSingle(
  1900. LPVOID* pV )
  1901. /*++
  1902. Routine Description:
  1903. Adjust the virtual variable to be TRUE if the current entry
  1904. in the IP grant access list is a single address, otherwise FALSE.
  1905. Update a pointer to this virtual variable on exit.
  1906. HTMLA var: "grantisipsingle"
  1907. Arguments:
  1908. None
  1909. Returns:
  1910. TRUE on success, FALSE on failure
  1911. --*/
  1912. {
  1913. if ( m_pConfig!=NULL && m_pConfig->GrantIPList
  1914. && m_iIter < m_pConfig->GrantIPList->cEntries )
  1915. {
  1916. AdjustIPSingle( (LPBYTE)&m_pConfig->GrantIPList
  1917. ->aIPSecEntry[m_iIter].dwMask );
  1918. *pV = (LPVOID)&m_dwIsIPSingle;
  1919. return TRUE;
  1920. }
  1921. return FALSE;
  1922. }
  1923. BOOL
  1924. CInetInfoConfigInfoMapper::DirBrowseEnab(
  1925. LPVOID *pV )
  1926. /*++
  1927. Routine Description:
  1928. Update a pointer to the virtual variable exposing the
  1929. "directory browsing enabled" setting.
  1930. HTMLA var: "w3dirbrowseenabled"
  1931. Arguments:
  1932. None
  1933. Returns:
  1934. TRUE on success, FALSE on failure
  1935. --*/
  1936. {
  1937. if ( m_pW3Config != NULL )
  1938. {
  1939. m_DirBrowseEnab = (m_pW3Config->dwDirBrowseControl&DIRBROW_ENABLED)
  1940. ? TRUE : FALSE;
  1941. *pV = &m_DirBrowseEnab;
  1942. return TRUE;
  1943. }
  1944. return FALSE;
  1945. }
  1946. BOOL
  1947. CInetInfoConfigInfoMapper::DefFileEnab(
  1948. LPVOID *pV )
  1949. /*++
  1950. Routine Description:
  1951. Update a pointer to the virtual variable exposing the
  1952. "default file enabled" setting.
  1953. HTMLA var: "w3defaultfileenabled"
  1954. Arguments:
  1955. None
  1956. Returns:
  1957. TRUE on success, FALSE on failure
  1958. --*/
  1959. {
  1960. if ( m_pW3Config != NULL )
  1961. {
  1962. m_DefFileEnab = (m_pW3Config->dwDirBrowseControl&DIRBROW_LOADDEFAULT)
  1963. ? TRUE : FALSE;
  1964. *pV = &m_DefFileEnab;
  1965. return TRUE;
  1966. }
  1967. return FALSE;
  1968. }
  1969. BOOL
  1970. CInetInfoConfigInfoMapper::SetRootEntryVars(
  1971. VOID )
  1972. /*++
  1973. Routine Description:
  1974. Set virtual vars exposing various properties of the current
  1975. virtual root entry :
  1976. Home status, read, write, exec, SSL required
  1977. Arguments:
  1978. None
  1979. Returns:
  1980. TRUE on success, FALSE on failure
  1981. --*/
  1982. {
  1983. if ( m_fInvEntry )
  1984. {
  1985. if ( m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter].pszRoot
  1986. != NULL )
  1987. {
  1988. m_fRootIsHome = !wcscmp(
  1989. m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter].pszRoot,
  1990. HOME_DIR_PATH ) ? TRUE : FALSE;
  1991. }
  1992. else
  1993. {
  1994. m_fRootIsHome = FALSE;
  1995. }
  1996. m_fRootIsRead =
  1997. (m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter].dwMask
  1998. & VROOT_MASK_READ) ? TRUE : FALSE;
  1999. m_fRootIsWrite =
  2000. (m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter].dwMask
  2001. & VROOT_MASK_WRITE) ? TRUE : FALSE;
  2002. m_fRootIsExec =
  2003. (m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter].dwMask
  2004. & VROOT_MASK_EXECUTE) ? TRUE : FALSE;
  2005. m_fRootIsSSL =
  2006. (m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter].dwMask
  2007. & VROOT_MASK_SSL) ? TRUE : FALSE;
  2008. m_fInvEntry = TRUE;
  2009. }
  2010. return TRUE;
  2011. }
  2012. BOOL
  2013. CInetInfoConfigInfoMapper::RootIsHome(
  2014. LPVOID *pV )
  2015. /*++
  2016. Routine Description:
  2017. Update a pointer to the virtual variable exposing the
  2018. "current virtual root is home" setting.
  2019. HTMLA var: rootishome
  2020. Arguments:
  2021. None
  2022. Returns:
  2023. TRUE on success, FALSE on failure
  2024. --*/
  2025. {
  2026. if ( m_pConfig != NULL && m_pConfig->VirtualRoots
  2027. && m_iIter < m_pConfig->VirtualRoots->cEntries )
  2028. {
  2029. // must call set vars, cannot make any assumptions about
  2030. // current virtual root entry
  2031. SetRootEntryVars();
  2032. *pV = &m_fRootIsHome;
  2033. return TRUE;
  2034. }
  2035. return FALSE;
  2036. }
  2037. BOOL
  2038. CInetInfoConfigInfoMapper::RootName(
  2039. LPVOID *pV )
  2040. /*++
  2041. Routine Description:
  2042. Update a pointer to the name of the current virtual root entry
  2043. HTMLA var: "rootname"
  2044. Arguments:
  2045. None
  2046. Returns:
  2047. TRUE on success, FALSE on failure
  2048. --*/
  2049. {
  2050. if ( m_pConfig!=NULL && m_pConfig->VirtualRoots
  2051. && m_iIter < m_pConfig->VirtualRoots->cEntries )
  2052. {
  2053. *pV = (LPVOID)&m_pConfig->VirtualRoots
  2054. ->aVirtRootEntry[m_iIter].pszRoot;
  2055. return TRUE;
  2056. }
  2057. else
  2058. {
  2059. return FALSE;
  2060. }
  2061. }
  2062. BOOL
  2063. CInetInfoConfigInfoMapper::RootIsRead(
  2064. LPVOID *pV )
  2065. /*++
  2066. Routine Description:
  2067. Update a pointer to the virtual variable exposing the
  2068. "current virtual root has read access" setting.
  2069. HTMLA var: "rootisread"
  2070. Arguments:
  2071. None
  2072. Returns:
  2073. TRUE on success, FALSE on failure
  2074. --*/
  2075. {
  2076. if ( m_pConfig != NULL
  2077. && m_pConfig->VirtualRoots
  2078. && m_iIter < m_pConfig->VirtualRoots->cEntries )
  2079. {
  2080. // must call set vars, cannot make any assumptions about
  2081. // current virtual root entry
  2082. SetRootEntryVars();
  2083. *pV = &m_fRootIsRead;
  2084. return TRUE;
  2085. }
  2086. return FALSE;
  2087. }
  2088. BOOL
  2089. CInetInfoConfigInfoMapper::RootIsWrite(
  2090. LPVOID *pV )
  2091. /*++
  2092. Routine Description:
  2093. Update a pointer to the virtual variable exposing the
  2094. "current virtual root has write access" setting.
  2095. HTMLA var: "rootiswrite"
  2096. Arguments:
  2097. None
  2098. Returns:
  2099. TRUE on success, FALSE on failure
  2100. --*/
  2101. {
  2102. if ( m_pConfig != NULL
  2103. && m_pConfig->VirtualRoots
  2104. && m_iIter < m_pConfig->VirtualRoots->cEntries )
  2105. {
  2106. // must call set vars, cannot make any assumptions about
  2107. // current virtual root entry
  2108. SetRootEntryVars();
  2109. *pV = &m_fRootIsWrite;
  2110. return TRUE;
  2111. }
  2112. return FALSE;
  2113. }
  2114. BOOL
  2115. CInetInfoConfigInfoMapper::RootIsExec(
  2116. LPVOID *pV )
  2117. /*++
  2118. Routine Description:
  2119. Update a pointer to the virtual variable exposing the
  2120. "current virtual root has execute access" setting.
  2121. HTMLA var: "rootisexec"
  2122. Arguments:
  2123. None
  2124. Returns:
  2125. TRUE on success, FALSE on failure
  2126. --*/
  2127. {
  2128. if ( m_pConfig != NULL
  2129. && m_pConfig->VirtualRoots
  2130. && m_iIter < m_pConfig->VirtualRoots->cEntries )
  2131. {
  2132. // must call set vars, cannot make any assumptions about
  2133. // current virtual root entry
  2134. SetRootEntryVars();
  2135. *pV = &m_fRootIsExec;
  2136. return TRUE;
  2137. }
  2138. return FALSE;
  2139. }
  2140. BOOL
  2141. CInetInfoConfigInfoMapper::RootIsSSL(
  2142. LPVOID *pV )
  2143. /*++
  2144. Routine Description:
  2145. Update a pointer to the virtual variable exposing the
  2146. "current virtual root requires SSL access" setting.
  2147. HTMLA var: "rootisssl"
  2148. Arguments:
  2149. None
  2150. Returns:
  2151. TRUE on success, FALSE on failure
  2152. --*/
  2153. {
  2154. if ( m_pConfig != NULL
  2155. && m_pConfig->VirtualRoots
  2156. && m_iIter < m_pConfig->VirtualRoots->cEntries )
  2157. {
  2158. // must call set vars, cannot make any assumptions about
  2159. // current virtual root entry
  2160. SetRootEntryVars();
  2161. *pV = &m_fRootIsSSL;
  2162. return TRUE;
  2163. }
  2164. return FALSE;
  2165. }
  2166. BOOL
  2167. CInetInfoConfigInfoMapper::AuthAnon(
  2168. LPVOID *pV )
  2169. /*++
  2170. Routine Description:
  2171. Update a pointer to the virtual variable exposing the
  2172. enable anonymous access setting.
  2173. HTMLA var: "authanon"
  2174. Arguments:
  2175. None
  2176. Returns:
  2177. TRUE on success, FALSE on failure
  2178. --*/
  2179. {
  2180. if ( m_pConfig != NULL )
  2181. {
  2182. m_fAuthAnon = m_pConfig->dwAuthentication&INET_INFO_AUTH_ANONYMOUS
  2183. ? TRUE : FALSE;
  2184. *pV = &m_fAuthAnon;
  2185. return TRUE;
  2186. }
  2187. return FALSE;
  2188. }
  2189. BOOL
  2190. CInetInfoConfigInfoMapper::AuthBasic(
  2191. LPVOID *pV )
  2192. /*++
  2193. Routine Description:
  2194. Update a pointer to the virtual variable exposing the
  2195. enable basic ( clear text password ) access setting.
  2196. HTMLA var: "authbasic"
  2197. Arguments:
  2198. None
  2199. Returns:
  2200. TRUE on success, FALSE on failure
  2201. --*/
  2202. {
  2203. if ( m_pConfig != NULL )
  2204. {
  2205. m_fAuthBasic = m_pConfig->dwAuthentication&INET_INFO_AUTH_CLEARTEXT
  2206. ? TRUE : FALSE;
  2207. *pV = &m_fAuthBasic;
  2208. return TRUE;
  2209. }
  2210. return FALSE;
  2211. }
  2212. BOOL
  2213. CInetInfoConfigInfoMapper::AuthNT(
  2214. LPVOID *pV )
  2215. /*++
  2216. Routine Description:
  2217. Update a pointer to the virtual variable exposing the
  2218. enable NTLM based authentication access setting.
  2219. HTMLA var: "authnt"
  2220. Arguments:
  2221. None
  2222. Returns:
  2223. TRUE on success, FALSE on failure
  2224. --*/
  2225. {
  2226. if ( m_pConfig != NULL )
  2227. {
  2228. m_fAuthNT = m_pConfig->dwAuthentication&INET_INFO_AUTH_NT_AUTH
  2229. ? TRUE : FALSE;
  2230. *pV = &m_fAuthNT;
  2231. return TRUE;
  2232. }
  2233. return FALSE;
  2234. }
  2235. BOOL
  2236. CInetInfoConfigInfoMapper::EnableLog(
  2237. LPVOID *pV )
  2238. /*++
  2239. Routine Description:
  2240. Update a pointer to the virtual variable exposing the
  2241. enable log setting.
  2242. HTMLA var: "enablelog"
  2243. Arguments:
  2244. None
  2245. Returns:
  2246. TRUE on success, FALSE on failure
  2247. --*/
  2248. {
  2249. if ( m_pConfig != NULL )
  2250. {
  2251. m_fEnableLog = m_pConfig->lpLogConfig->inetLogType
  2252. ? TRUE : FALSE;
  2253. *pV = &m_fEnableLog;
  2254. return TRUE;
  2255. }
  2256. return FALSE;
  2257. }
  2258. BOOL
  2259. CInetInfoConfigInfoMapper::EnableNewLog(
  2260. LPVOID *pV )
  2261. /*++
  2262. Routine Description:
  2263. Update a pointer to the virtual variable exposing the
  2264. enable new log file creation setting.
  2265. HTMLA var: "enablenewlog"
  2266. Arguments:
  2267. None
  2268. Returns:
  2269. TRUE on success, FALSE on failure
  2270. --*/
  2271. {
  2272. if ( m_pConfig != NULL )
  2273. {
  2274. m_fEnableNewLog = m_dwLogPeriod ? TRUE : FALSE;
  2275. *pV = &m_fEnableNewLog;
  2276. return TRUE;
  2277. }
  2278. return FALSE;
  2279. }
  2280. //
  2281. // Update indication for variables
  2282. // These functions are called AFTER the script updated the
  2283. // corresponding variable.
  2284. //
  2285. BOOL
  2286. CInetInfoConfigInfoMapper::UpdateGlobalIsBandwidthLimited(
  2287. VOID )
  2288. /*++
  2289. Routine Description:
  2290. Adjust bandwidth limit to be consistent
  2291. with setting controlling whether bandwidth is limited.
  2292. HTMLA var: "globalisbandwidthlimited"
  2293. Arguments:
  2294. None
  2295. Returns:
  2296. TRUE on success, FALSE on failure
  2297. --*/
  2298. {
  2299. if ( m_pGlobalConfig != NULL )
  2300. {
  2301. if ( m_dwIsBandwidthLimited == 0 )
  2302. m_pGlobalConfig->BandwidthLevel = DWORD(-1);
  2303. SetField( m_pGlobalConfig->FieldControl, FC_GINET_INFO_ALL );
  2304. return TRUE;
  2305. }
  2306. return FALSE;
  2307. }
  2308. BOOL
  2309. CInetInfoConfigInfoMapper::UpdateGlobalBandwidth(
  2310. VOID )
  2311. /*++
  2312. Routine Description:
  2313. Adjust bandwidth limit to be consistent
  2314. with the virtual var controlling whether bandwidth is limited.
  2315. This assumes that the virtual var "globalisbandwidthlimited" appears
  2316. BEFORE the "globalbandwidth" variable.
  2317. HTMLA var: "globalbandwidth"
  2318. Arguments:
  2319. None
  2320. Returns:
  2321. TRUE on success, FALSE on failure
  2322. --*/
  2323. {
  2324. if ( m_pGlobalConfig != NULL )
  2325. {
  2326. if ( m_dwIsBandwidthLimited == 0 )
  2327. {
  2328. m_pGlobalConfig->BandwidthLevel = DWORD(-1);
  2329. }
  2330. SetField( m_pGlobalConfig->FieldControl, FC_GINET_INFO_ALL );
  2331. return TRUE;
  2332. }
  2333. return FALSE;
  2334. }
  2335. BOOL
  2336. CInetInfoConfigInfoMapper::UpdateDenyIsIPSingle(
  2337. VOID )
  2338. /*++
  2339. Routine Description:
  2340. Adjust network mask for Deny IP access list to be consistent
  2341. with the virtual var controlling if this entry is for
  2342. a single address or not.
  2343. This assumes that the virtual var "denyisipsingle" appears
  2344. BEFORE the "denyipmask" variable.
  2345. HTMLA var: "denyisipsingle"
  2346. Arguments:
  2347. None
  2348. Returns:
  2349. TRUE on success, FALSE on failure
  2350. --*/
  2351. {
  2352. if ( m_pConfig!=NULL
  2353. && m_pConfig->DenyIPList
  2354. && m_iIter < m_pConfig->DenyIPList->cEntries )
  2355. {
  2356. AdjustFromIPSingle( (LPBYTE)&m_pConfig->DenyIPList
  2357. ->aIPSecEntry[m_iIter].dwMask );
  2358. UpdateIP();
  2359. return TRUE;
  2360. }
  2361. return FALSE;
  2362. }
  2363. BOOL
  2364. CInetInfoConfigInfoMapper::UpdateGrantIsIPSingle(
  2365. VOID )
  2366. /*++
  2367. Routine Description:
  2368. Adjust network mask for Grant IP access list to be consistent
  2369. with the virtual var controlling if this entry is for
  2370. a single address or not.
  2371. This assumes that the virtual var "grantisipsingle" appears
  2372. BEFORE the "grantipmask" variable.
  2373. HTMLA var: "grantisipsingle"
  2374. Arguments:
  2375. None
  2376. Returns:
  2377. TRUE on success, FALSE on failure
  2378. --*/
  2379. {
  2380. if ( m_pConfig!=NULL
  2381. && m_pConfig->GrantIPList
  2382. && m_iIter < m_pConfig->GrantIPList->cEntries )
  2383. {
  2384. AdjustFromIPSingle( (LPBYTE)&m_pConfig->GrantIPList
  2385. ->aIPSecEntry[m_iIter].dwMask );
  2386. UpdateIP();
  2387. return TRUE;
  2388. }
  2389. return FALSE;
  2390. }
  2391. BOOL
  2392. CInetInfoConfigInfoMapper::UpdateDirControl(
  2393. VOID )
  2394. /*++
  2395. Routine Description:
  2396. Synchronize virtual vars updated by the user request
  2397. for directory attributes ( browsing, use default file )
  2398. and RPC structures.
  2399. Arguments:
  2400. None
  2401. Returns:
  2402. TRUE on success, FALSE on failure
  2403. --*/
  2404. {
  2405. if ( m_DirBrowseEnab )
  2406. {
  2407. m_pW3Config->dwDirBrowseControl |= DIRBROW_ENABLED;
  2408. }
  2409. else
  2410. {
  2411. m_pW3Config->dwDirBrowseControl &= ~DIRBROW_ENABLED;
  2412. }
  2413. if ( m_DefFileEnab )
  2414. {
  2415. m_pW3Config->dwDirBrowseControl |= DIRBROW_LOADDEFAULT;
  2416. }
  2417. else
  2418. {
  2419. m_pW3Config->dwDirBrowseControl &= ~DIRBROW_LOADDEFAULT;
  2420. }
  2421. SetField( m_pW3Config->FieldControl, FC_W3_DIR_BROWSE_CONTROL );
  2422. return TRUE;
  2423. }
  2424. BOOL
  2425. CInetInfoConfigInfoMapper::UpdateRootName(
  2426. VOID )
  2427. /*++
  2428. Routine Description:
  2429. Synchronize virtual vars updated by the user request
  2430. for virtual root name ( name, home directory or not )
  2431. and RPC structures.
  2432. It assumes that the 'homeness' status of this virtual root
  2433. is determined BEFORE the name, i.e. that the 'home' setting
  2434. appears before the virtual root name in the HTMLA form
  2435. The user setting will be overidden if the virtual root is home
  2436. In this case, the virtual root name will be set to HOME_DIR_PATH
  2437. HTMLA var: "rootname"
  2438. Arguments:
  2439. None
  2440. Returns:
  2441. TRUE on success, FALSE on failure
  2442. --*/
  2443. {
  2444. BOOL fSt = TRUE;
  2445. if ( UpdateRoot() )
  2446. {
  2447. if ( m_fRootIsHome )
  2448. {
  2449. LPWSTR pszRoot = (LPWSTR)Alloc( (wcslen( HOME_DIR_PATH ) + 1)
  2450. * sizeof(WCHAR) );
  2451. if ( pszRoot == NULL )
  2452. {
  2453. fSt = FALSE;
  2454. }
  2455. else
  2456. {
  2457. wcscpy( pszRoot, HOME_DIR_PATH );
  2458. m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter]
  2459. .pszRoot = pszRoot;
  2460. }
  2461. }
  2462. else
  2463. {
  2464. LPWSTR pszR = m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter].pszRoot;
  2465. if ( pszR[0] == L'\0' || !wcscmp( L"/", pszR ) )
  2466. {
  2467. // no name was specified, auto-alias
  2468. fSt = AliasVirtDir( m_pConfig->VirtualRoots
  2469. ->aVirtRootEntry + m_iIter );
  2470. }
  2471. }
  2472. }
  2473. else
  2474. {
  2475. fSt = FALSE;
  2476. }
  2477. return fSt;
  2478. }
  2479. BOOL
  2480. CInetInfoConfigInfoMapper::UpdateRootMask(
  2481. VOID )
  2482. /*++
  2483. Routine Description:
  2484. Synchronize virtual vars updated by the user request
  2485. for directory attributes ( read, execute, SSL required )
  2486. and RPC structures.
  2487. Arguments:
  2488. None
  2489. Returns:
  2490. TRUE on success, FALSE on failure
  2491. --*/
  2492. {
  2493. if ( m_pConfig != NULL && m_iIter < m_pConfig->VirtualRoots->cEntries )
  2494. {
  2495. DWORD dwMsk = m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter].dwMask;
  2496. if ( m_fRootIsRead )
  2497. {
  2498. dwMsk |= VROOT_MASK_READ;
  2499. }
  2500. else
  2501. {
  2502. dwMsk &= ~VROOT_MASK_READ;
  2503. }
  2504. if ( m_fRootIsWrite )
  2505. {
  2506. dwMsk |= VROOT_MASK_WRITE;
  2507. }
  2508. else
  2509. {
  2510. dwMsk &= ~VROOT_MASK_WRITE;
  2511. }
  2512. if ( m_fRootIsExec )
  2513. {
  2514. dwMsk |= VROOT_MASK_EXECUTE;
  2515. }
  2516. else
  2517. {
  2518. dwMsk &= ~VROOT_MASK_EXECUTE;
  2519. }
  2520. if ( m_fRootIsSSL )
  2521. {
  2522. dwMsk |= VROOT_MASK_SSL;
  2523. }
  2524. else
  2525. {
  2526. dwMsk &= ~VROOT_MASK_SSL;
  2527. }
  2528. m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter].dwMask = dwMsk;
  2529. SetField( m_pConfig->FieldControl, FC_INET_INFO_VIRTUAL_ROOTS );
  2530. return TRUE;
  2531. }
  2532. return FALSE;
  2533. }
  2534. BOOL
  2535. CInetInfoConfigInfoMapper::UpdateAuth(
  2536. VOID )
  2537. /*++
  2538. Routine Description:
  2539. Synchronize virtual vars updated by the user request
  2540. for supported authetication methods ( anon, clear text, NTLMSSP )
  2541. and RPC structures.
  2542. Arguments:
  2543. None
  2544. Returns:
  2545. TRUE on success, FALSE on failure
  2546. --*/
  2547. {
  2548. if ( m_pConfig != NULL )
  2549. {
  2550. DWORD dwMsk = m_pConfig->dwAuthentication;
  2551. if ( m_fAuthAnon )
  2552. {
  2553. dwMsk |= INET_INFO_AUTH_ANONYMOUS;
  2554. }
  2555. else
  2556. {
  2557. dwMsk &= ~INET_INFO_AUTH_ANONYMOUS;
  2558. }
  2559. if ( m_fAuthBasic )
  2560. {
  2561. dwMsk |= INET_INFO_AUTH_CLEARTEXT;
  2562. }
  2563. else
  2564. {
  2565. dwMsk &= ~INET_INFO_AUTH_CLEARTEXT;
  2566. }
  2567. if ( m_fAuthNT )
  2568. {
  2569. dwMsk |= INET_INFO_AUTH_NT_AUTH;
  2570. }
  2571. else
  2572. {
  2573. dwMsk &= ~INET_INFO_AUTH_NT_AUTH;
  2574. }
  2575. m_pConfig->dwAuthentication = dwMsk;
  2576. SetField( m_pConfig->FieldControl, FC_INET_INFO_AUTHENTICATION );
  2577. return TRUE;
  2578. }
  2579. return FALSE;
  2580. }
  2581. BOOL
  2582. CInetInfoConfigInfoMapper::UpdateLog(
  2583. VOID )
  2584. /*++
  2585. Routine Description:
  2586. Acknowledge update to log settings
  2587. ( dummy entry, no action for now )
  2588. HTMLA var: "enablelog"
  2589. Arguments:
  2590. None
  2591. Returns:
  2592. TRUE
  2593. --*/
  2594. {
  2595. return TRUE;
  2596. }
  2597. BOOL
  2598. CInetInfoConfigInfoMapper::UpdateNewLog(
  2599. VOID )
  2600. /*++
  2601. Routine Description:
  2602. Insure consistency between user request ( new log enabled,
  2603. log period ) and RPC structures.
  2604. This assumes that enable new Log type is updated BEFORE the log period
  2605. setting, i.e. it appears before this setting in the
  2606. HTMLA form.
  2607. HTMLA var: "enablenewlog"
  2608. Arguments:
  2609. None
  2610. Returns:
  2611. TRUE on success, FALSE on failure
  2612. --*/
  2613. {
  2614. if ( m_pConfig != NULL )
  2615. {
  2616. if ( !m_fEnableNewLog )
  2617. {
  2618. if ( INET_LOG_PERIOD_NONE
  2619. != m_pConfig->lpLogConfig->ilPeriod )
  2620. {
  2621. m_dwLogPeriod
  2622. = m_pConfig->lpLogConfig->ilPeriod
  2623. = INET_LOG_PERIOD_NONE;
  2624. }
  2625. }
  2626. return TRUE;
  2627. }
  2628. return FALSE;
  2629. }
  2630. BOOL
  2631. CInetInfoConfigInfoMapper::UpdateLogType(
  2632. VOID )
  2633. /*++
  2634. Routine Description:
  2635. Insure consistency between user request ( log enabled,
  2636. log type ) and RPC structures.
  2637. This assumes that Log type is updated AFTER the log enabled
  2638. setting, i.e. it appears after this setting in the
  2639. HTMLA form.
  2640. HTMLA var : "logtype"
  2641. Arguments:
  2642. None
  2643. Returns:
  2644. TRUE on success, FALSE on failure
  2645. --*/
  2646. {
  2647. if ( m_pConfig != NULL )
  2648. {
  2649. if ( !m_fEnableLog )
  2650. {
  2651. m_pConfig->lpLogConfig->inetLogType
  2652. = INET_LOG_DISABLED;
  2653. }
  2654. if ( m_dwWasLogType != m_pConfig->lpLogConfig->inetLogType )
  2655. {
  2656. SetField( m_pConfig->FieldControl, FC_INET_INFO_LOG_CONFIG );
  2657. }
  2658. return TRUE;
  2659. }
  2660. return FALSE;
  2661. }
  2662. BOOL
  2663. CInetInfoConfigInfoMapper::SetLogEntryVars(
  2664. VOID )
  2665. /*++
  2666. Routine Description:
  2667. Update virtual vars needed by the log settings, such as
  2668. the log period. Virtual vars are needed to expose the log type
  2669. as a single value, in contrast with the RPC struct definition
  2670. where multiple variables are used to encode this information
  2671. Arguments:
  2672. None
  2673. Returns:
  2674. TRUE on success, FALSE on failure
  2675. --*/
  2676. {
  2677. m_dwLogPeriod = m_pConfig->lpLogConfig->ilPeriod;
  2678. m_dwLogFormat = *((DWORD UNALIGNED *)&(m_pConfig->lpLogConfig->rgchDataSource[MAX_PATH-sizeof(DWORD)]));
  2679. if ( m_pConfig->lpLogConfig->inetLogType
  2680. && m_dwLogPeriod == INET_LOG_PERIOD_NONE
  2681. && m_pConfig->lpLogConfig->cbSizeForTruncation
  2682. != (DWORD)-1 )
  2683. {
  2684. m_dwLogPeriod = INET_LOG_PERIOD_ON_SIZE;
  2685. }
  2686. m_dwInvalidLogUpdate = 0;
  2687. return TRUE;
  2688. }
  2689. BOOL
  2690. CInetInfoConfigInfoMapper::LogPeriod(
  2691. LPVOID *pV )
  2692. /*++
  2693. Routine Description:
  2694. Update a pointer to the virtual variable exposing the
  2695. log period. In addition to the RPC definition for log period
  2696. we support a new log period defined as "create new log when size
  2697. reaches xxx"
  2698. HTMLA var: "logperiod"
  2699. Arguments:
  2700. None
  2701. Returns:
  2702. TRUE on success, FALSE on failure
  2703. --*/
  2704. {
  2705. if ( m_pConfig!= NULL )
  2706. {
  2707. *pV = &m_dwLogPeriod;
  2708. return TRUE;
  2709. }
  2710. return FALSE;
  2711. }
  2712. BOOL
  2713. CInetInfoConfigInfoMapper::LogFormat(
  2714. LPVOID *pV )
  2715. /*++
  2716. Routine Description:
  2717. Update a pointer to the virtual variable exposing the
  2718. log format.
  2719. HTMLA var: "logformat"
  2720. Arguments:
  2721. None
  2722. Returns:
  2723. TRUE on success, FALSE on failure
  2724. --*/
  2725. {
  2726. if ( m_pConfig!= NULL )
  2727. {
  2728. *pV = &m_dwLogFormat;
  2729. return TRUE;
  2730. }
  2731. return FALSE;
  2732. }
  2733. BOOL
  2734. CInetInfoConfigInfoMapper::UpdateLogPeriod(
  2735. VOID )
  2736. /*++
  2737. Routine Description:
  2738. Insure consistency between user request ( log enabled, new log
  2739. enabled, create new log based on size, log period ) and
  2740. RPC structures.
  2741. This assumes that Log period is updated AFTER the log enabled & new
  2742. log enabled settings, i.e. it appears after these settings in the
  2743. HTMLA form.
  2744. HTMLA var: "logperiod"
  2745. Arguments:
  2746. None
  2747. Returns:
  2748. TRUE on success, FALSE on failure
  2749. --*/
  2750. {
  2751. BOOL fUp = FALSE;
  2752. if ( m_pConfig != NULL )
  2753. {
  2754. DWORD dwN;
  2755. // check disabled or set to open on file size
  2756. if ( !m_fEnableLog
  2757. || !m_fEnableNewLog
  2758. || m_dwLogPeriod == INET_LOG_PERIOD_ON_SIZE )
  2759. {
  2760. dwN = INET_LOG_PERIOD_NONE;
  2761. }
  2762. else
  2763. {
  2764. if ( 0 == (dwN = m_dwLogPeriod) )
  2765. {
  2766. if ( m_fEnableLog && m_fEnableNewLog )
  2767. {
  2768. return FALSE;
  2769. }
  2770. }
  2771. m_pConfig->lpLogConfig->cbSizeForTruncation
  2772. = 0;
  2773. }
  2774. if ( dwN != m_pConfig->lpLogConfig->ilPeriod )
  2775. {
  2776. m_pConfig->lpLogConfig->ilPeriod = dwN;
  2777. }
  2778. return TRUE;
  2779. }
  2780. return FALSE;
  2781. }
  2782. BOOL
  2783. CInetInfoConfigInfoMapper::UpdateLogFormat(
  2784. VOID )
  2785. /*++
  2786. Routine Description:
  2787. Insure consistency between user request ( log enabled, new log
  2788. enabled, create new log based on size, log period ) and
  2789. RPC structures.
  2790. HTMLA var: "logformat"
  2791. Arguments:
  2792. None
  2793. Returns:
  2794. TRUE on success, FALSE on failure
  2795. --*/
  2796. {
  2797. BOOL fUp = FALSE;
  2798. if ( m_pConfig != NULL )
  2799. {
  2800. if ((*(DWORD UNALIGNED*)&(m_pConfig->lpLogConfig->rgchDataSource[MAX_PATH-sizeof(DWORD)])) != m_dwLogFormat )
  2801. {
  2802. (*(DWORD UNALIGNED*)&(m_pConfig->lpLogConfig->rgchDataSource[MAX_PATH-sizeof(DWORD)])) = m_dwLogFormat;
  2803. UpdateLogFileInfo();
  2804. }
  2805. return TRUE;
  2806. }
  2807. return FALSE;
  2808. }
  2809. BOOL
  2810. CInetInfoConfigInfoMapper::UpdateLogSize(
  2811. VOID )
  2812. /*++
  2813. Routine Description:
  2814. Insure consistency between user request ( log enabled, new log
  2815. enabled, create new log based on size, log size ) and
  2816. RPC structures.
  2817. This assumes that Log size is updated AFTER the log enabled, new
  2818. log enabled & log period settings, i.e. it appears after these
  2819. settings in the HTMLA form.
  2820. HTMLA var: "logsize"
  2821. Arguments:
  2822. None
  2823. Returns:
  2824. TRUE on success, FALSE on failure
  2825. --*/
  2826. {
  2827. if ( m_pConfig != NULL )
  2828. {
  2829. if ( !m_fEnableNewLog )
  2830. {
  2831. m_pConfig->lpLogConfig->cbSizeForTruncation
  2832. = (DWORD)-1;
  2833. return TRUE;
  2834. }
  2835. else if ( m_dwLogPeriod != INET_LOG_PERIOD_ON_SIZE )
  2836. {
  2837. // restore original log size if not currently creating
  2838. // new file on size
  2839. if ( m_pConfig->lpLogConfig->cbSizeForTruncation
  2840. != m_dwWasSizeForTruncation
  2841. && m_pConfig->lpLogConfig->cbSizeForTruncation
  2842. != 0 )
  2843. {
  2844. m_pConfig->lpLogConfig->cbSizeForTruncation
  2845. = m_dwWasSizeForTruncation;
  2846. m_dwInvalidLogUpdate = INET_LOG_INVALID_TO_FILE;
  2847. }
  2848. else
  2849. {
  2850. m_pConfig->lpLogConfig->cbSizeForTruncation
  2851. = m_dwWasSizeForTruncation;
  2852. }
  2853. }
  2854. else if ( (int)m_pConfig->lpLogConfig->cbSizeForTruncation
  2855. < 1
  2856. && m_pConfig->lpLogConfig->inetLogType
  2857. == INET_LOG_TO_FILE )
  2858. {
  2859. return FALSE;
  2860. }
  2861. else
  2862. {
  2863. UpdateLogInfo();
  2864. }
  2865. return TRUE;
  2866. }
  2867. return FALSE;
  2868. }
  2869. BOOL
  2870. CInetInfoConfigInfoMapper::InvalidLogUpdate(
  2871. LPVOID *pV )
  2872. /*++
  2873. Routine Description:
  2874. Check for invalid changes requested by user to the log settings
  2875. and returns a numeric value indicating what invalid change was made
  2876. Arguments:
  2877. pV - pointer to DWORD where to put invalid change status
  2878. can be updated with INET_LOG_TO_FILE if invalid change made
  2879. to the file log settings, INET_LOG_TO_SQL if invalid changes
  2880. to the ODBC log settings, or 0 if no invalid change.
  2881. Returns:
  2882. TRUE on success, FALSE on failure
  2883. --*/
  2884. {
  2885. if ( m_pConfig->lpLogConfig->ilPeriod != m_dwWasLogPeriod
  2886. || (m_pConfig->lpLogConfig->cbSizeForTruncation
  2887. != m_dwWasSizeForTruncation
  2888. && (m_pConfig->lpLogConfig->ilPeriod
  2889. != INET_LOG_PERIOD_NONE || m_pConfig->lpLogConfig->cbSizeForTruncation==(DWORD)-1)) )
  2890. {
  2891. if ( m_pConfig->lpLogConfig->cbSizeForTruncation
  2892. == (DWORD)-1 && m_dwWasSizeForTruncation == 0)
  2893. {
  2894. // does not consider it as invalid log to file
  2895. // if in ODBC mode
  2896. UpdateLogInfo();
  2897. }
  2898. else
  2899. {
  2900. UpdateLogFileInfo();
  2901. }
  2902. }
  2903. if ( !m_fEnableLog
  2904. && !m_dwWasLogType
  2905. && (m_fLogFileUpdate || m_fLogODBCUpdate ) )
  2906. {
  2907. m_dwInvalidLogUpdate = INET_LOG_INVALID_TO_FILE;
  2908. }
  2909. if ( m_pConfig->lpLogConfig->inetLogType
  2910. == INET_LOG_TO_SQL
  2911. && m_fLogFileUpdate )
  2912. {
  2913. m_dwInvalidLogUpdate = INET_LOG_TO_FILE;
  2914. }
  2915. else if ( m_pConfig->lpLogConfig->inetLogType
  2916. == INET_LOG_TO_FILE
  2917. && m_fLogODBCUpdate )
  2918. {
  2919. m_dwInvalidLogUpdate = INET_LOG_TO_SQL;
  2920. }
  2921. *pV = (LPVOID)&m_dwInvalidLogUpdate;
  2922. return TRUE;
  2923. }
  2924. BOOL
  2925. CInetInfoConfigInfoMapper::UpdateLogFileInfo(
  2926. VOID )
  2927. /*++
  2928. Routine Description:
  2929. Mark the log to file settings as updated by the user
  2930. This will be used to check for invalid log updates
  2931. Arguments:
  2932. None
  2933. Returns:
  2934. TRUE on success, FALSE on failure
  2935. --*/
  2936. {
  2937. m_fLogFileUpdate = TRUE;
  2938. return UpdateLogInfo();
  2939. }
  2940. BOOL
  2941. CInetInfoConfigInfoMapper::UpdateLogODBCInfo(
  2942. VOID )
  2943. /*++
  2944. Routine Description:
  2945. Mark the log to ODBC settings as updated by the user
  2946. This will be used to check for invalid log updates
  2947. Arguments:
  2948. None
  2949. Returns:
  2950. TRUE on success, FALSE on failure
  2951. --*/
  2952. {
  2953. m_fLogODBCUpdate = TRUE;
  2954. return UpdateLogInfo();
  2955. }
  2956. BOOL
  2957. CInetInfoConfigInfoMapper::IPDenyRef(
  2958. LPVOID *pV )
  2959. /*++
  2960. Routine Description:
  2961. Builds a reference to the current IP element in the deny access list
  2962. Arguments:
  2963. pV - LPSTR** to be updated with the address of the LPSTR that will
  2964. contains the reference as a sz string
  2965. HTMLA var: "ipdenyref"
  2966. Returns:
  2967. TRUE on success, FALSE on failure
  2968. --*/
  2969. {
  2970. return IPRef( pV, m_pConfig->DenyIPList, &m_pDenyRef );
  2971. }
  2972. BOOL
  2973. CInetInfoConfigInfoMapper::IPGrantRef(
  2974. LPVOID *pV )
  2975. /*++
  2976. Routine Description:
  2977. Builds a reference to the current IP element in the grant access list
  2978. Arguments:
  2979. pV - LPSTR** to be updated with the address of the LPSTR that will
  2980. contains the reference as a sz string
  2981. HTMLA var: "ipgrantref"
  2982. Returns:
  2983. TRUE on success, FALSE on failure
  2984. --*/
  2985. {
  2986. return IPRef( pV, m_pConfig->GrantIPList, &m_pGrantRef );
  2987. }
  2988. BOOL
  2989. CInetInfoConfigInfoMapper::IPRef(
  2990. LPVOID *pV,
  2991. INET_INFO_IP_SEC_LIST* pL,
  2992. LPSTR* pS )
  2993. /*++
  2994. Routine Description:
  2995. build a reference to the current IP element in the specified list
  2996. Arguments:
  2997. pV - LPSTR** to be updated with the address of the LPSTR that will
  2998. contains the reference as a sz string
  2999. pL - pointer to the a IP access list, to be indexed with the current
  3000. value of the <%beginiteration%> construct : m_iIter
  3001. pS - LPSTR* updated with the address of the generated
  3002. reference
  3003. WARNING:
  3004. Must be in sync with BuildIPUniqueID()
  3005. Returns:
  3006. TRUE on success, FALSE on failure
  3007. --*/
  3008. {
  3009. if ( m_pConfig != NULL && pL && m_iIter < pL->cEntries )
  3010. {
  3011. // get ASCII format of IP address & mask
  3012. LPSTR pN = IPToMultiByte(
  3013. (LPBYTE)&pL->aIPSecEntry[m_iIter].dwNetwork );
  3014. LPSTR pM = IPToMultiByte(
  3015. (LPBYTE)&pL->aIPSecEntry[m_iIter].dwMask );
  3016. if ( pN == NULL || pM == NULL )
  3017. {
  3018. SetRequestStatus( HTR_OUT_OF_RESOURCE );
  3019. return FALSE;
  3020. }
  3021. // build IP ref string
  3022. LPSTR pR = (LPSTR)Alloc( lstrlen(pN)
  3023. + sizeof(REF_SEP_STR)-1
  3024. + lstrlen(pM)
  3025. + 1 );
  3026. if ( pR == NULL )
  3027. {
  3028. return FALSE;
  3029. }
  3030. lstrcpy( pR, pN );
  3031. lstrcat( pR, REF_SEP_STR );
  3032. lstrcat( pR, pM );
  3033. *pS = pR;
  3034. *pV = (LPVOID*)pS;
  3035. return TRUE;
  3036. }
  3037. return FALSE;
  3038. }
  3039. BOOL
  3040. CInetInfoConfigInfoMapper::RootRef(
  3041. LPVOID *pV )
  3042. /*++
  3043. Routine Description:
  3044. build a reference to the current virtual root element
  3045. HTMLA var: "rootref"
  3046. Arguments:
  3047. pV - LPSTR** to be updated with the address of the LPSTR that will
  3048. contains the reference as a sz string
  3049. WARNING:
  3050. must be in sync with BuildVirtDirUniqueID()
  3051. Returns:
  3052. TRUE on success, FALSE on failure
  3053. --*/
  3054. {
  3055. if ( m_pConfig != NULL && m_pConfig->VirtualRoots && m_iIter < m_pConfig->VirtualRoots->cEntries )
  3056. {
  3057. INET_INFO_VIRTUAL_ROOT_ENTRY* pE
  3058. = &m_pConfig->VirtualRoots->aVirtRootEntry[m_iIter];
  3059. size_t lR = wcslen( pE->pszRoot );
  3060. size_t lD = wcslen( pE->pszDirectory );
  3061. size_t lA = wcslen( pE->pszAddress );
  3062. LPSTR pR = (LPSTR)Alloc( lR*2 + 1 + lD*2 +1 + lA*2 + 1);
  3063. if ( pR == NULL )
  3064. {
  3065. return FALSE;
  3066. }
  3067. DWORD dwLr, dwLd, dwLa;
  3068. // contains Root SEP Directory SEP Address
  3069. if ( (dwLr=lR)==0 || (dwLr = WideCharToMultiByte( CP_ACP,
  3070. 0,
  3071. pE->pszRoot,
  3072. lR,
  3073. pR,
  3074. lR*2,
  3075. NULL,
  3076. NULL )) != 0 )
  3077. {
  3078. pR[dwLr] = REF_SEP;
  3079. if ( (dwLd=lD)==0 || (dwLd = WideCharToMultiByte( CP_ACP,
  3080. 0,
  3081. pE->pszDirectory,
  3082. lD,
  3083. pR+dwLr+1,
  3084. lD*2,
  3085. NULL,
  3086. NULL )) != 0 )
  3087. {
  3088. pR[dwLr+1+dwLd] = REF_SEP;
  3089. if ( (dwLa=lA)==0 || (dwLa = WideCharToMultiByte( CP_ACP,
  3090. 0,
  3091. pE->pszAddress,
  3092. lA,
  3093. pR+dwLr+1+dwLd+1,
  3094. lA*2,
  3095. NULL,
  3096. NULL )) != 0 )
  3097. {
  3098. pR[dwLr+1+dwLd+1+dwLa] = '\0';
  3099. m_pRootRef = pR;
  3100. *pV = (LPVOID*)&m_pRootRef;
  3101. return TRUE;
  3102. }
  3103. }
  3104. }
  3105. }
  3106. return FALSE;
  3107. }
  3108. BOOL
  3109. CInetInfoConfigInfoMapper::CryptCapable(
  3110. LPVOID *pV
  3111. )
  3112. /*++
  3113. Routine Description:
  3114. Return status on availability of encryption capability for
  3115. the W3 service only.
  3116. HTMLA var: "w3cryptcapable"
  3117. Arguments:
  3118. pV - DWORD** to be updated with the address of a DWORD that
  3119. will be non zero if encryption capability available
  3120. Returns:
  3121. TRUE on success, FALSE on failure
  3122. --*/
  3123. {
  3124. if ( m_pW3Config != NULL )
  3125. {
  3126. m_dwCryptCapable = (m_pW3Config->dwEncCaps
  3127. & (ENC_CAPS_NOT_INSTALLED|ENC_CAPS_DISABLED))
  3128. ? 0 : (m_pW3Config->dwEncCaps & ENC_CAPS_TYPE_MASK);
  3129. }
  3130. else
  3131. {
  3132. char achEncCaps[32];
  3133. DWORD dwEncCaps = sizeof( achEncCaps );
  3134. EXTENSION_CONTROL_BLOCK* pECB = m_piiR->GetECB();
  3135. if ( pECB->GetServerVariable( (HCONN)pECB->ConnID,
  3136. "HTTP_CFG_ENC_CAPS", achEncCaps, &dwEncCaps ) )
  3137. {
  3138. m_dwCryptCapable = (DWORD)atol( achEncCaps );
  3139. m_dwCryptCapable = (m_dwCryptCapable
  3140. & (ENC_CAPS_NOT_INSTALLED|ENC_CAPS_DISABLED))
  3141. ? 0 : (m_dwCryptCapable & ENC_CAPS_TYPE_MASK);
  3142. }
  3143. else
  3144. {
  3145. m_dwCryptCapable = 0;
  3146. }
  3147. }
  3148. *pV = &m_dwCryptCapable;
  3149. return TRUE;
  3150. }
  3151. //
  3152. // array of services descriptor mapping name to service type
  3153. //
  3154. CServType g_aServTypes[] = {
  3155. { "http", INET_HTTP_SVC_ID },
  3156. { "ftp", INET_FTP_SVC_ID },
  3157. { "gopher", INET_GOPHER_SVC_ID },
  3158. { "dns", INET_DNS_SVC_ID },
  3159. { "dir", INET_DIR },
  3160. } ;
  3161. CServTypeEnum g_ServTypeEnum;
  3162. CServType*
  3163. CServTypeEnum::GetServByName(
  3164. LPSTR pName )
  3165. /*++
  3166. Routine Description:
  3167. Map a service name to a service descriptor entry
  3168. Arguments:
  3169. pName - Service name, i.e. http, ftp, ...
  3170. Returns:
  3171. pointer to service descriptor or NULL if service name not found
  3172. --*/
  3173. {
  3174. for ( int x = 0 ; x < sizeof(g_aServTypes)/sizeof(CServType) ; ++x )
  3175. {
  3176. if ( !strcmp( g_aServTypes[x].GetName(), pName ) )
  3177. {
  3178. return g_aServTypes+x;
  3179. }
  3180. }
  3181. return NULL;
  3182. }
  3183. CServType*
  3184. CServTypeEnum::GetServByType(
  3185. DWORD dwT )
  3186. /*++
  3187. Routine Description:
  3188. Map a service type to a service descriptor entry
  3189. Arguments:
  3190. dwT - Service type, i.e. INET_HTTP, ...
  3191. Returns:
  3192. pointer to service descriptor or NULL if service type not found
  3193. --*/
  3194. {
  3195. for ( int x = 0 ; x < sizeof(g_aServTypes)/sizeof(CServType) ; ++x )
  3196. {
  3197. if ( g_aServTypes[x].GetType() == dwT )
  3198. {
  3199. return g_aServTypes+x;
  3200. }
  3201. }
  3202. return NULL;
  3203. }
  3204. //////
  3205. BOOL
  3206. CInetInfoConfigInfoMapper::ServName(
  3207. LPVOID *pV )
  3208. /*++
  3209. Routine Description:
  3210. Map the service type associated with this object to a string
  3211. representation ( i.e http, ftp, ... )
  3212. Arguments:
  3213. pV - LPSTR** updated with address of string representation of
  3214. service name
  3215. Returns:
  3216. TRUE if success, else FALSE
  3217. --*/
  3218. {
  3219. CServType *pS = g_ServTypeEnum.GetServByType( m_dwCurrentServerType );
  3220. if ( pS != NULL )
  3221. {
  3222. m_pszVarServName = pS->GetName();
  3223. *pV = (LPVOID)&m_pszVarServName;
  3224. return TRUE;
  3225. }
  3226. return FALSE;
  3227. }
  3228. void
  3229. CInetInfoConfigInfoMapper::Lock(
  3230. VOID )
  3231. /*++
  3232. Routine Description:
  3233. Lock access to this mapper object
  3234. Arguments:
  3235. None
  3236. Returns:
  3237. None
  3238. --*/
  3239. {
  3240. EnterCriticalSection( &m_csLock );
  3241. }
  3242. void
  3243. CInetInfoConfigInfoMapper::UnLock(
  3244. VOID )
  3245. /*++
  3246. Routine Description:
  3247. Unlock access to this mapper object
  3248. Arguments:
  3249. None
  3250. Returns:
  3251. None
  3252. --*/
  3253. {
  3254. LeaveCriticalSection( &m_csLock );
  3255. }
  3256. LPVOID
  3257. CInetInfoConfigInfoMapper::Alloc(
  3258. DWORD dwL )
  3259. /*++
  3260. Routine Description:
  3261. Allocate a block of memory which will automatically de-allocated
  3262. by calling FreeInfo()
  3263. Arguments:
  3264. dwL - size of memory block to allocate
  3265. Returns:
  3266. pointer to allocated block or NULL if failure
  3267. updates reqstatus if failure
  3268. --*/
  3269. {
  3270. CAllocNode *pA = new CAllocNode( dwL );
  3271. if ( pA == NULL )
  3272. {
  3273. SetRequestStatus( HTR_OUT_OF_RESOURCE );
  3274. return NULL;
  3275. }
  3276. if ( m_pFirstAlloc == NULL )
  3277. {
  3278. m_pFirstAlloc = pA;
  3279. }
  3280. else
  3281. {
  3282. m_pLastAlloc->SetNext( pA );
  3283. }
  3284. m_pLastAlloc = pA;
  3285. return pA->GetBuff();
  3286. }
  3287. LPSTR
  3288. CInetInfoConfigInfoMapper::IPToMultiByte(
  3289. LPBYTE pB )
  3290. /*++
  3291. Routine Description:
  3292. Returns a created string buffer containing the ASCII
  3293. representation of an IP address
  3294. Arguments:
  3295. pB - pointer to IP address as a byte sequence
  3296. length is given by IP_ADDR_BYTE_SIZE
  3297. Returns:
  3298. pointer to allocated string or NULL if failure
  3299. string is of auto-deallocate type
  3300. --*/
  3301. {
  3302. LPSTR pF,pS;
  3303. pF = pS = (char*)Alloc( IP_ADDR_BYTE_SIZE*4+1 );
  3304. if ( pS == NULL )
  3305. {
  3306. return NULL;
  3307. }
  3308. for ( int y = 0 ; y < IP_ADDR_BYTE_SIZE ; ++y )
  3309. {
  3310. DWORDToMultiByte( (DWORD)*pB++, pS );
  3311. pS += lstrlen( pS );
  3312. if ( y != IP_ADDR_BYTE_SIZE-1 )
  3313. {
  3314. *pS ++ = '.';
  3315. }
  3316. }
  3317. *pS = '\0';
  3318. return pF;
  3319. }
  3320. BOOL
  3321. CInetInfoConfigInfoMapper::MultiByteToIP(
  3322. LPSTR *ppS,
  3323. LPBYTE pB )
  3324. /*++
  3325. Routine Description:
  3326. Convert the ASCII representation of an IP address
  3327. to a sequence of byte
  3328. Arguments:
  3329. ppS - pointer to string containing ASCII representation
  3330. of IP address. Does not have to be zero delimited.
  3331. pB - pointer to IP address as a byte sequence
  3332. length will be IP_ADDR_BYTE_SIZE
  3333. Returns:
  3334. TRUE if success, FALSE if failure
  3335. --*/
  3336. {
  3337. LPSTR pS = *ppS;
  3338. for ( int y = 0 ; y < IP_ADDR_BYTE_SIZE ; ++y )
  3339. {
  3340. int c;
  3341. UINT v;
  3342. for ( v = 0 ; (c=*pS)>='0' && c<='9' ; ++pS )
  3343. {
  3344. v = v * 10 + *pS-'0';
  3345. }
  3346. if ( v > 255 )
  3347. {
  3348. return FALSE;
  3349. }
  3350. *pB++ = (BYTE)v;
  3351. if ( y != IP_ADDR_BYTE_SIZE-1 && *pS++ != '.' )
  3352. {
  3353. return FALSE;
  3354. }
  3355. }
  3356. *ppS = pS;
  3357. return TRUE;
  3358. }
  3359. extern "C" int __cdecl
  3360. QsortVirtDirCmp(
  3361. const void *pA,
  3362. const void *pB )
  3363. /*++
  3364. Routine Description:
  3365. Compare two Virtual root entries for sorting order
  3366. 1st key is the address field, then the name
  3367. Arguments:
  3368. pA - pointer to the 1st virtual root entry
  3369. pB - pointer to the 2nd virtual root entry
  3370. Returns:
  3371. -1 if 1st entry to be placed 1st as defined by the
  3372. sort order, 0 if same rank, 1 if 2nd entry is to
  3373. be placed first
  3374. --*/
  3375. {
  3376. LPWSTR pNameA = ((INET_INFO_VIRTUAL_ROOT_ENTRY*)pA)->pszRoot;
  3377. LPWSTR pNameB = ((INET_INFO_VIRTUAL_ROOT_ENTRY*)pB)->pszRoot;
  3378. LPWSTR pAddrA = ((INET_INFO_VIRTUAL_ROOT_ENTRY*)pA)->pszAddress;
  3379. LPWSTR pAddrB = ((INET_INFO_VIRTUAL_ROOT_ENTRY*)pB)->pszAddress;
  3380. int iCmp;
  3381. //
  3382. // sort on Addr, then Name
  3383. //
  3384. if ( pAddrA && pAddrB )
  3385. {
  3386. iCmp = _wcsicmp( pAddrA, pAddrB );
  3387. }
  3388. else
  3389. {
  3390. iCmp = 0;
  3391. }
  3392. if ( iCmp == 0 && pNameA && pNameB )
  3393. {
  3394. iCmp = _wcsicmp( pNameA, pNameB );
  3395. }
  3396. return iCmp;
  3397. }
  3398. extern "C" int __cdecl
  3399. QsortIpSecCmp(
  3400. const void *pA,
  3401. const void *pB )
  3402. /*++
  3403. Routine Description:
  3404. Compare two IP access entries for sorting order
  3405. Uses the network address as the compare field
  3406. Arguments:
  3407. pA - pointer to the 1st IP access entry
  3408. pB - pointer to the 2nd IP access entry
  3409. Returns:
  3410. -1 if 1st entry to be placed 1st as defined by the
  3411. sort order, 0 if same rank, 1 if 2nd entry is to
  3412. be placed first
  3413. --*/
  3414. {
  3415. //
  3416. // sort on network address
  3417. //
  3418. return memcmp( &((INET_INFO_IP_SEC_ENTRY*)pA)->dwNetwork,
  3419. &((INET_INFO_IP_SEC_ENTRY*)pB)->dwNetwork,
  3420. IP_ADDR_BYTE_SIZE );
  3421. }
  3422. BOOL SortVirtualRoots(
  3423. LPINET_INFO_VIRTUAL_ROOT_LIST pL )
  3424. /*++
  3425. Routine Description:
  3426. Sort a virtual root list for display
  3427. Arguments:
  3428. pL - pointer to a virtual root list
  3429. Returns:
  3430. TRUE
  3431. --*/
  3432. {
  3433. if ( pL != NULL && pL->cEntries )
  3434. {
  3435. qsort( pL->aVirtRootEntry,
  3436. pL->cEntries,
  3437. sizeof(INET_INFO_VIRTUAL_ROOT_ENTRY),
  3438. QsortVirtDirCmp );
  3439. }
  3440. return TRUE;
  3441. }
  3442. BOOL SortIpSecList(
  3443. LPINET_INFO_IP_SEC_LIST pL )
  3444. /*++
  3445. Routine Description:
  3446. Sort a IP access list for display
  3447. Arguments:
  3448. pL - pointer to an IP access list
  3449. Returns:
  3450. TRUE
  3451. --*/
  3452. {
  3453. if ( pL != NULL && pL->cEntries )
  3454. {
  3455. qsort( pL->aIPSecEntry,
  3456. pL->cEntries,
  3457. sizeof(INET_INFO_IP_SEC_ENTRY),
  3458. QsortIpSecCmp );
  3459. }
  3460. return TRUE;
  3461. }
  3462. BOOL
  3463. CInetInfoConfigInfoMapper::GetCurrentConfig(
  3464. VOID )
  3465. /*++
  3466. Routine Description:
  3467. Get the current configuration for the service linked
  3468. to this object by calling the IIS RPC layer
  3469. Arguments:
  3470. None
  3471. Returns:
  3472. TRUE on success, FALSE on failure
  3473. updates reqstatus
  3474. --*/
  3475. {
  3476. BOOL fSt = TRUE;
  3477. NET_API_STATUS iStat;
  3478. DWORD dwSize = sizeof(m_achComputerName)-2;
  3479. m_pConfig = NULL;
  3480. m_pW3Config = NULL;
  3481. m_pFtpConfig = NULL;
  3482. m_pGdConfig = NULL;
  3483. m_pGlobalConfig = NULL;
  3484. // free user enumeration
  3485. m_Users.Reset();
  3486. m_Drive.Reset();
  3487. ResetIter();
  3488. m_dwRPCStatus = 0;
  3489. m_dwInvalidLogUpdate = 0;
  3490. m_fLogFileUpdate = FALSE;
  3491. m_fLogODBCUpdate = FALSE;
  3492. if ( !GetComputerNameW( m_achComputerName+2, &dwSize ) )
  3493. {
  3494. m_achComputerName[0] = 0;
  3495. }
  3496. else
  3497. {
  3498. // adjust computer name for reference through Named Pipes
  3499. m_achComputerName[0] = L'\\';
  3500. m_achComputerName[1] = L'\\';
  3501. #if 0
  3502. m_achComputerName[2] = L'.';
  3503. m_achComputerName[3] = L'\0';
  3504. #endif
  3505. }
  3506. if ( m_dwCurrentServerType == INET_DIR )
  3507. {
  3508. // udpate arg1...3 from m_pszURLParam
  3509. m_pszArg1 = (LPSTR)Alloc( strlen( m_pszURLParam ) + 1 );
  3510. m_pszArg2 = m_pszArg3 = NULL;
  3511. if ( m_pszArg1 == NULL )
  3512. {
  3513. return FALSE;
  3514. }
  3515. strcpy( m_pszArg1, m_pszURLParam );
  3516. LPSTR pD = strchr( m_pszArg1, '?' );
  3517. if ( pD != NULL )
  3518. {
  3519. *pD = '\0';
  3520. m_pszArg2 = pD + 1;
  3521. pD = strchr( m_pszArg2, '?' );
  3522. if ( pD != NULL )
  3523. {
  3524. *pD = '\0';
  3525. m_pszArg3 = pD + 1;
  3526. // insure does not end with '\'
  3527. pD = m_pszArg3 + strlen(m_pszArg3);
  3528. if ( pD > m_pszArg3 && &pD[-1] == (LPSTR)_mbsrchr((LPBYTE)m_pszArg3,'\\') )
  3529. {
  3530. pD[-1] = '\0';
  3531. }
  3532. }
  3533. }
  3534. if ( !m_fGotServerCapsAndVersion )
  3535. {
  3536. #if defined(IISv1)
  3537. m_pServerCaps = NULL;
  3538. g_OSVersion.dwOSVersionInfoSize = sizeof(g_OSVersion);
  3539. GetVersionEx( &g_OSVersion );
  3540. m_dwMinorVersion = 0;
  3541. m_dwMajorVersion = 1;
  3542. #else
  3543. if ( InetInfoGetServerCapabilities( m_achComputerName,
  3544. 0,
  3545. &m_pServerCaps ) != NO_ERROR )
  3546. {
  3547. m_pServerCaps = NULL;
  3548. }
  3549. DWORD dwVer;
  3550. if ( InetInfoGetVersion( m_achComputerName,
  3551. 0,
  3552. &dwVer ) != NO_ERROR )
  3553. {
  3554. dwVer = 0;
  3555. }
  3556. m_dwMinorVersion = dwVer >> 16;
  3557. m_dwMajorVersion = (DWORD)(WORD)dwVer;
  3558. #endif
  3559. m_fGotServerCapsAndVersion = TRUE;
  3560. }
  3561. return TRUE;
  3562. }
  3563. __try {
  3564. if ( (iStat = InetInfoGetAdminInformation( m_achComputerName,
  3565. m_dwCurrentServerType,
  3566. &m_pConfig ))
  3567. == NO_ERROR || iStat == 2 )
  3568. {
  3569. m_pConfig->FieldControl = 0;
  3570. SetLogEntryVars();
  3571. m_dwWasLogPeriod = m_pConfig->lpLogConfig->ilPeriod;
  3572. m_dwWasLogType = m_pConfig->lpLogConfig->inetLogType;
  3573. m_dwWasSizeForTruncation = m_pConfig->lpLogConfig->cbSizeForTruncation ;
  3574. }
  3575. else
  3576. {
  3577. SetRequestStatus( HTR_CONFIG_ACCESS_ERROR );
  3578. m_dwRPCStatus = (DWORD)iStat;
  3579. fSt = FALSE;
  3580. m_pConfig = NULL;
  3581. }
  3582. if ( fSt )
  3583. {
  3584. SortVirtualRoots( m_pConfig->VirtualRoots );
  3585. SortIpSecList( m_pConfig->DenyIPList );
  3586. SortIpSecList( m_pConfig->GrantIPList );
  3587. if ( (iStat = InetInfoGetGlobalAdminInformation( m_achComputerName,
  3588. 0,
  3589. &m_pGlobalConfig ))
  3590. == NO_ERROR || iStat == 2 )
  3591. {
  3592. m_pGlobalConfig->FieldControl = 0;
  3593. m_dwIsBandwidthLimited = 2; // undefined
  3594. }
  3595. else
  3596. {
  3597. SetRequestStatus( HTR_COM_CONFIG_ACCESS_ERROR );
  3598. m_dwRPCStatus = (DWORD)iStat;
  3599. fSt = FALSE;
  3600. m_pGlobalConfig = NULL;
  3601. }
  3602. }
  3603. if ( fSt )
  3604. {
  3605. if ( !m_fGotServerCapsAndVersion )
  3606. {
  3607. #if defined(IISv1)
  3608. m_pServerCaps = NULL;
  3609. g_OSVersion.dwOSVersionInfoSize = sizeof(g_OSVersion);
  3610. GetVersionEx( &g_OSVersion );
  3611. m_dwMinorVersion = 0;
  3612. m_dwMajorVersion = 1;
  3613. #else
  3614. if ( InetInfoGetServerCapabilities( m_achComputerName,
  3615. 0,
  3616. &m_pServerCaps ) != NO_ERROR )
  3617. {
  3618. m_pServerCaps = NULL;
  3619. }
  3620. DWORD dwVer;
  3621. if ( InetInfoGetVersion( m_achComputerName,
  3622. 0,
  3623. &dwVer ) != NO_ERROR )
  3624. {
  3625. dwVer = 0;
  3626. }
  3627. m_dwMinorVersion = dwVer >> 16;
  3628. m_dwMajorVersion = (DWORD)(WORD)dwVer;
  3629. #endif
  3630. m_fGotServerCapsAndVersion = TRUE;
  3631. }
  3632. switch ( m_dwCurrentServerType )
  3633. {
  3634. case INET_HTTP_SVC_ID:
  3635. if ( (iStat = W3GetAdminInformation( m_achComputerName, &m_pW3Config )) == NO_ERROR )
  3636. {
  3637. m_pW3Config->FieldControl = 0;
  3638. }
  3639. else
  3640. {
  3641. SetRequestStatus( HTR_W3_CONFIG_ACCESS_ERROR );
  3642. m_dwRPCStatus = (DWORD)iStat;
  3643. fSt = FALSE;
  3644. m_pW3Config = NULL;
  3645. }
  3646. break;
  3647. case INET_FTP_SVC_ID:
  3648. if ( (iStat = FtpGetAdminInformation( m_achComputerName,
  3649. &m_pFtpConfig )) == NO_ERROR )
  3650. {
  3651. m_pFtpConfig->FieldControl = 0;
  3652. }
  3653. else
  3654. {
  3655. SetRequestStatus( HTR_FTP_CONFIG_ACCESS_ERROR );
  3656. m_dwRPCStatus = (DWORD)iStat;
  3657. fSt = FALSE;
  3658. m_pFtpConfig = NULL;
  3659. }
  3660. break;
  3661. #if 0
  3662. case INET_GOPHER_SVC_ID:
  3663. if ( (iStat = GdGetAdminInformation( m_achComputerName,
  3664. &m_pGdConfig )) == NO_ERROR )
  3665. {
  3666. m_pGdConfig->FieldControl = 0;
  3667. }
  3668. else
  3669. {
  3670. SetRequestStatus( HTR_GD_CONFIG_ACCESS_ERROR );
  3671. m_dwRPCStatus = (DWORD)iStat;
  3672. fSt = FALSE;
  3673. m_pGdConfig = NULL;
  3674. }
  3675. break;
  3676. #endif
  3677. }
  3678. }
  3679. }
  3680. __except( EXCEPTION_EXECUTE_HANDLER )
  3681. {
  3682. SetRequestStatus( HTR_CONFIG_ACCESS_ERROR );
  3683. FreeInfo();
  3684. fSt = FALSE;
  3685. }
  3686. switch ( m_dwCurrentServerType )
  3687. {
  3688. case INET_HTTP_SVC_ID:
  3689. m_dwHttpStatus = m_dwRPCStatus; break;
  3690. case INET_FTP_SVC_ID:
  3691. m_dwFtpStatus = m_dwRPCStatus; break;
  3692. case INET_GOPHER_SVC_ID:
  3693. m_dwGopherStatus = m_dwRPCStatus; break;
  3694. }
  3695. return fSt;
  3696. }
  3697. BOOL
  3698. CInetInfoConfigInfoMapper::Update(
  3699. VOID )
  3700. /*++
  3701. Routine Description:
  3702. Update the current configuration for the service linked
  3703. to this object by calling the IIS RPC layer
  3704. Arguments:
  3705. None
  3706. Returns:
  3707. TRUE on success, FALSE on failure
  3708. updates reqstatus
  3709. --*/
  3710. {
  3711. BOOL fSt = TRUE;
  3712. NET_API_STATUS iStat;
  3713. if ( m_dwRequestStatus != HTR_OK )
  3714. {
  3715. return FALSE;
  3716. }
  3717. if ( m_dwCurrentServerType == INET_DIR )
  3718. {
  3719. return TRUE;
  3720. }
  3721. __try {
  3722. if ( m_pConfig != NULL && m_pConfig->FieldControl &&
  3723. (iStat = InetInfoSetAdminInformation( m_achComputerName,
  3724. m_dwCurrentServerType, m_pConfig )) != NO_ERROR )
  3725. {
  3726. SetRequestStatus( HTR_CONFIG_WRITE_ERROR );
  3727. m_dwRPCStatus = (DWORD)iStat;
  3728. fSt = FALSE;
  3729. }
  3730. if ( fSt )
  3731. {
  3732. #if 0
  3733. // update Authentication header if Authentication methods field updated
  3734. // not necessary : done via registry notification thread
  3735. if ( m_pConfig != NULL && (m_pConfig->FieldControl
  3736. & FC_INET_INFO_AUTHENTICATION) )
  3737. g_AuthReqs.UpdateMethodsIndication();
  3738. #endif
  3739. if ( m_pGlobalConfig != NULL && m_pGlobalConfig->FieldControl &&
  3740. (iStat = InetInfoSetGlobalAdminInformation( m_achComputerName,
  3741. 0, m_pGlobalConfig )) != NO_ERROR && iStat != 2 )
  3742. {
  3743. SetRequestStatus( HTR_COM_CONFIG_WRITE_ERROR );
  3744. m_dwRPCStatus = (DWORD)iStat;
  3745. fSt = FALSE;
  3746. }
  3747. }
  3748. if ( fSt )
  3749. {
  3750. switch ( m_dwCurrentServerType )
  3751. {
  3752. case INET_HTTP_SVC_ID:
  3753. if ( m_pW3Config != NULL && m_pW3Config->FieldControl &&
  3754. (iStat = W3SetAdminInformation( m_achComputerName,
  3755. m_pW3Config )) != NO_ERROR )
  3756. {
  3757. SetRequestStatus( HTR_W3_CONFIG_WRITE_ERROR );
  3758. m_dwRPCStatus = (DWORD)iStat;
  3759. fSt = FALSE;
  3760. }
  3761. break;
  3762. case INET_FTP_SVC_ID:
  3763. if ( m_pFtpConfig != NULL && m_pFtpConfig->FieldControl &&
  3764. (iStat = FtpSetAdminInformation( m_achComputerName,
  3765. m_pFtpConfig )) != NO_ERROR )
  3766. {
  3767. SetRequestStatus( HTR_FTP_CONFIG_WRITE_ERROR );
  3768. m_dwRPCStatus = (DWORD)iStat;
  3769. fSt = FALSE;
  3770. }
  3771. break;
  3772. #if 0
  3773. case INET_GOPHER_SVC_ID:
  3774. if ( m_pGdConfig != NULL && m_pGdConfig->FieldControl &&
  3775. (iStat = GdSetAdminInformation( m_achComputerName,
  3776. m_pGdConfig )) != NO_ERROR )
  3777. {
  3778. SetRequestStatus( HTR_GD_CONFIG_WRITE_ERROR );
  3779. m_dwRPCStatus = (DWORD)iStat;
  3780. fSt = FALSE;
  3781. }
  3782. break;
  3783. #endif
  3784. }
  3785. }
  3786. }
  3787. __except( EXCEPTION_EXECUTE_HANDLER )
  3788. {
  3789. SetRequestStatus( HTR_CONFIG_WRITE_ERROR );
  3790. fSt = FALSE;
  3791. }
  3792. return fSt;
  3793. }
  3794. BOOL
  3795. CInetInfoConfigInfoMapper::FreeInfo(
  3796. VOID )
  3797. /*++
  3798. Routine Description:
  3799. Free memory associated with the current map object
  3800. including memory used by the structure used in the IIS RPC calls
  3801. and memory allocated using Alloc()
  3802. Arguments:
  3803. None
  3804. Returns:
  3805. TRUE on success, FALSE on failure
  3806. updates reqstatus
  3807. --*/
  3808. {
  3809. BOOL fSt = TRUE;
  3810. CAllocNode *pAllocNode;
  3811. // free all memory alloced to update RPC structures
  3812. for ( pAllocNode = m_pFirstAlloc ; pAllocNode != NULL ; )
  3813. {
  3814. CAllocNode *pN = pAllocNode->GetNext();
  3815. delete pAllocNode;
  3816. pAllocNode = pN;
  3817. }
  3818. m_pFirstAlloc = m_pLastAlloc = NULL;
  3819. if ( m_pConfig != NULL )
  3820. {
  3821. MIDL_user_free( m_pConfig );
  3822. m_pConfig = NULL;
  3823. }
  3824. if ( m_pGlobalConfig != NULL )
  3825. {
  3826. MIDL_user_free( m_pGlobalConfig );
  3827. m_pGlobalConfig = NULL;
  3828. }
  3829. // free user enumeration
  3830. m_Users.Reset();
  3831. m_Drive.Reset();
  3832. switch ( m_dwCurrentServerType )
  3833. {
  3834. case INET_HTTP_SVC_ID:
  3835. if ( m_pW3Config != NULL )
  3836. {
  3837. MIDL_user_free( m_pW3Config );
  3838. m_pW3Config = NULL;
  3839. }
  3840. break;
  3841. case INET_FTP_SVC_ID:
  3842. if ( m_pFtpConfig != NULL )
  3843. {
  3844. MIDL_user_free( m_pFtpConfig );
  3845. m_pFtpConfig = NULL;
  3846. }
  3847. break;
  3848. case INET_GOPHER_SVC_ID:
  3849. if ( m_pGdConfig != NULL )
  3850. {
  3851. MIDL_user_free( m_pGdConfig );
  3852. m_pGdConfig = NULL;
  3853. }
  3854. break;
  3855. }
  3856. return fSt;
  3857. }
  3858. BOOL
  3859. CInetInfoConfigInfoMapper::Map(
  3860. LPBYTE pName,
  3861. DWORD dwNameLen,
  3862. CInetInfoMap** ppMap )
  3863. /*++
  3864. Routine Description:
  3865. Map a variable name to a variable descriptor structure
  3866. Arguments:
  3867. pName - variable name
  3868. dwNameLen - variable name length
  3869. ppMap - updated with pointer to variable descriptor
  3870. Returns:
  3871. TRUE on success, FALSE if failure ( variable not found )
  3872. --*/
  3873. {
  3874. int x;
  3875. LPBYTE pLN = new BYTE[dwNameLen];
  3876. if ( pLN == NULL )
  3877. {
  3878. SetRequestStatus( HTR_OUT_OF_RESOURCE );
  3879. return FALSE;
  3880. }
  3881. memcpy( pLN, pName, dwNameLen );
  3882. // case insensitive lookup : normalize name to lower case
  3883. for ( x = 0 ; x < (int)dwNameLen ; ++x )
  3884. {
  3885. if ( IsDBCSLeadByte( pLN[x] ) )
  3886. {
  3887. ++x;
  3888. }
  3889. else if ( isupper( (UCHAR)pLN[x] ) )
  3890. {
  3891. pLN[x] = (UINT)_tolower( (int)pLN[x] );
  3892. }
  3893. }
  3894. for ( x = 0 ; x < m_cNbMap ; ++x )
  3895. {
  3896. DWORD l = (DWORD)lstrlen(m_pMap[x].pName);
  3897. if ( l == dwNameLen && !memcmp( m_pMap[x].pName, pLN, l) )
  3898. {
  3899. *ppMap = m_pMap+x;
  3900. delete [] pLN;
  3901. return TRUE;
  3902. }
  3903. }
  3904. delete [] pLN;
  3905. return FALSE;
  3906. }
  3907. BOOL
  3908. CInetInfoConfigInfoMapper::GetFromMsgBody(
  3909. LPSTR pName,
  3910. DWORD dwNameLen,
  3911. LPSTR *pResult,
  3912. DWORD *pdwResLen )
  3913. /*++
  3914. Routine Description:
  3915. Returns the value of the specified variable in the message
  3916. body of the current request
  3917. Arguments:
  3918. pName - variable name
  3919. dwNameLen - variable name length
  3920. pResult - updated with address of string value
  3921. pdwResLen - updated with length of value
  3922. Returns:
  3923. TRUE on success, FALSE if failure ( variable not found )
  3924. --*/
  3925. {
  3926. // Use the raw request body to avoid parsing errors caused
  3927. // by escaped data values.
  3928. LPSTR pV = m_pszReqParamRaw;
  3929. // assume variable name begins with "msgbody."
  3930. pName += sizeof("msgbody.") - 1;
  3931. dwNameLen -= sizeof("msgbody.") - 1;
  3932. for ( ; *pV ; )
  3933. {
  3934. while ( isspace((UCHAR)(*pV)) )
  3935. {
  3936. ++pV;
  3937. }
  3938. // scan for end of variable name
  3939. LPSTR pE = strchr( pV, '=' );
  3940. BOOL fIsLast = FALSE;
  3941. if ( pE != NULL )
  3942. {
  3943. ++pE;
  3944. // scan for end of value
  3945. LPSTR pN = strchr( pE, '&' );
  3946. if ( pN == NULL )
  3947. {
  3948. if ( (pN = strchr( pE, '\r' )) == NULL )
  3949. {
  3950. if ( (pN = strchr( pE, '\n' )) == NULL )
  3951. {
  3952. pN = pE + strlen( pE );
  3953. }
  3954. }
  3955. fIsLast = TRUE;
  3956. }
  3957. // check for matching variable name
  3958. if ( pE - pV - 1 == (int)dwNameLen
  3959. && !memcmp( pV, pName, dwNameLen ) )
  3960. {
  3961. *pdwResLen = DIFF(pN - pE);
  3962. if ( (*pResult = (LPSTR)Alloc( *pdwResLen + 1 )) == NULL )
  3963. {
  3964. return FALSE;
  3965. }
  3966. DelimStrcpyN( *pResult, pE, *pdwResLen );
  3967. // Escape the data
  3968. InlineFromTransparent( (LPBYTE)*pResult, pdwResLen, FALSE );
  3969. (*pResult)[*pdwResLen] = '\0';
  3970. return TRUE;
  3971. }
  3972. if ( fIsLast )
  3973. {
  3974. break;
  3975. }
  3976. pV = pN + 1;
  3977. }
  3978. }
  3979. return FALSE;
  3980. }
  3981. BOOL
  3982. CInetInfoConfigInfoMapper::GetFromServer(
  3983. LPSTR pName,
  3984. DWORD dwNameLen,
  3985. LPSTR *pResult,
  3986. DWORD *pdwResLen )
  3987. /*++
  3988. Routine Description:
  3989. Returns the value of the specified variable from IIS
  3990. Arguments:
  3991. pName - variable name
  3992. dwNameLen - variable name length
  3993. pResult - updated with address of string value
  3994. pdwResLen - updated with length of value
  3995. Returns:
  3996. TRUE on success, FALSE if failure ( variable not found )
  3997. --*/
  3998. {
  3999. LPSTR pN;
  4000. // assume variable name begins with "iis."
  4001. pName += sizeof("iis.") - 1;
  4002. dwNameLen -= sizeof("iis.") - 1;
  4003. DWORD dwLen = 256;
  4004. if ( (*pResult = (LPSTR)Alloc( dwLen )) == NULL ||
  4005. (pN = (LPSTR)Alloc( dwNameLen+1 )) == NULL )
  4006. {
  4007. return FALSE;
  4008. }
  4009. if ( dwNameLen == sizeof("DEFAULT_DOMAIN")-1 &&
  4010. !_memicmp( pName, "DEFAULT_DOMAIN", dwNameLen ) )
  4011. {
  4012. if ( g_pfnGetDefaultDomainName == NULL ||
  4013. !g_pfnGetDefaultDomainName( *pResult, dwLen))
  4014. {
  4015. *pdwResLen = 0;
  4016. }
  4017. else
  4018. {
  4019. *pdwResLen = strlen( *pResult );
  4020. }
  4021. return TRUE;
  4022. }
  4023. memcpy( pN, pName, dwNameLen );
  4024. pN[dwNameLen] = '\0';
  4025. if ( m_piiR->GetECB()->GetServerVariable( (HCONN)m_piiR->GetECB()->ConnID,
  4026. pN,
  4027. *pResult,
  4028. &dwLen ) )
  4029. {
  4030. *pdwResLen = dwLen ? dwLen-1 : 0;
  4031. return TRUE;
  4032. }
  4033. return FALSE;
  4034. }
  4035. BOOL
  4036. CInetInfoConfigInfoMapper::EscapeString(
  4037. LPSTR *pResult,
  4038. LPDWORD pdwResLen,
  4039. BOOL fFreeAfterUse )
  4040. /*++
  4041. Routine Description:
  4042. Escape the specified string in a form suitable for inclusion
  4043. in a URL
  4044. Arguments:
  4045. pResult - updated with address of string value
  4046. pdwResLen - updated with length of value
  4047. fFreeAfterUse - TRUE if input content of pResult needs to be freed
  4048. after usage ( using delete[] )
  4049. Returns:
  4050. TRUE on success, FALSE if failure
  4051. --*/
  4052. {
  4053. LPSTR pIn = *pResult;
  4054. LPSTR pOut;
  4055. LPSTR pEsc;
  4056. LPSTR pScan;
  4057. DWORD dwIn = *pdwResLen;
  4058. DWORD dwOut = 0;
  4059. //
  4060. // allocate output string base on its max length
  4061. //
  4062. if ( (pOut = (LPSTR)Alloc( dwIn * 3 + 1 )) == NULL )
  4063. {
  4064. return FALSE;
  4065. }
  4066. for ( pEsc = pOut, pScan = pIn ; dwIn-- ; )
  4067. {
  4068. int ch = *pScan++;
  4069. if ( (((ch >= 0) && (ch <= 32)) ||
  4070. (ch&0x80)||
  4071. ( ch == '\\') || ( ch == ':' ) ||
  4072. (ch == '%') || (ch == '?') || (ch == '+') || (ch == '&')) &&
  4073. !(ch == TEXT('\n') || ch == TEXT('\r')) )
  4074. {
  4075. *pEsc++ = TEXT('%');
  4076. //
  4077. // Convert the high then the low character to hex
  4078. //
  4079. UINT nDigit = (UINT)(ch >> 4);
  4080. *pEsc++ = HEXDIGIT( nDigit );
  4081. nDigit = (UINT)(ch & 0x0f);
  4082. *pEsc++ = HEXDIGIT( nDigit );
  4083. dwOut += 3;
  4084. }
  4085. else
  4086. {
  4087. *pEsc++ = (char)ch;
  4088. ++dwOut;
  4089. }
  4090. }
  4091. *pResult = pOut;
  4092. *pdwResLen = dwOut;
  4093. if ( fFreeAfterUse )
  4094. {
  4095. delete [] pIn;
  4096. }
  4097. return TRUE;
  4098. }
  4099. BOOL
  4100. CInetInfoConfigInfoMapper::GetString(
  4101. LPBYTE pName,
  4102. DWORD dwNameLen,
  4103. LPSTR *pResult,
  4104. DWORD *pdwResLen,
  4105. BOOL *pfFree )
  4106. /*++
  4107. Routine Description:
  4108. Returns the value of the specified variable as specified
  4109. by its name as a string
  4110. Arguments:
  4111. pName - variable name
  4112. dwNameLen - variable name length
  4113. pResult - updated with address of string value
  4114. pdwResLen - updated with length of value
  4115. pfFree - updated with TRUE if pResult needs to be freed
  4116. after usage ( using delete[] )
  4117. Returns:
  4118. TRUE on success, FALSE if failure ( variable not found )
  4119. --*/
  4120. {
  4121. CInetInfoMap *pMap;
  4122. BOOL fMustEscape;
  4123. BOOL fSt;
  4124. if ( !memcmp( "\"&z\",", pName, sizeof("\"&z\",")-1 ) )
  4125. {
  4126. pName += sizeof("\"&z\",")-1;
  4127. dwNameLen -= sizeof("\"&z\",")-1;
  4128. fMustEscape = TRUE;
  4129. }
  4130. else
  4131. {
  4132. fMustEscape = FALSE;
  4133. }
  4134. if ( !memcmp( "msgbody.", pName, sizeof("msgbody.")-1 ) )
  4135. {
  4136. *pfFree = FALSE;
  4137. fSt = GetFromMsgBody( (LPSTR)pName, dwNameLen, pResult, pdwResLen );
  4138. }
  4139. else if ( !memcmp( "iis.", pName, sizeof("iis.")-1 ) )
  4140. {
  4141. *pfFree = FALSE;
  4142. fSt = GetFromServer( (LPSTR)pName, dwNameLen, pResult, pdwResLen );
  4143. }
  4144. else if ( Map( pName, dwNameLen, &pMap ) )
  4145. {
  4146. fSt = GetString( pMap, pResult, pdwResLen, pfFree );
  4147. }
  4148. else
  4149. {
  4150. fSt = FALSE;
  4151. }
  4152. if ( fSt == FALSE )
  4153. {
  4154. *pfFree = FALSE;
  4155. }
  4156. else if ( fMustEscape )
  4157. {
  4158. if ( fSt = EscapeString( pResult, pdwResLen, *pfFree ) )
  4159. {
  4160. *pfFree = FALSE;
  4161. }
  4162. }
  4163. return fSt;
  4164. }
  4165. BOOL
  4166. CInetInfoConfigInfoMapper::GetString(
  4167. CInetInfoMap *pMap,
  4168. LPSTR *pResult,
  4169. DWORD *pdwResLen,
  4170. BOOL *pfFree )
  4171. /*++
  4172. Routine Description:
  4173. Returns the value of the specified variable as specified
  4174. by its descriptor as a string
  4175. Arguments:
  4176. pMap - variable descriptor
  4177. pResult - updated with address of string value
  4178. pdwResLen - updated with length of value
  4179. pfFree - updated with TRUE if pResult needs to be freed
  4180. after usage ( using delete[] )
  4181. Returns:
  4182. TRUE on success, FALSE if failure
  4183. updates reqstatus
  4184. --*/
  4185. {
  4186. BOOL fSt = FALSE;
  4187. LPVOID *pV;
  4188. *pResult = NULL;
  4189. *pdwResLen = 0;
  4190. *pfFree = FALSE;
  4191. if ( (this->*pMap->GetAddr)( (LPVOID*)&pV ) == FALSE )
  4192. {
  4193. return FALSE;
  4194. }
  4195. LPSTR pR;
  4196. switch ( pMap->iType )
  4197. {
  4198. case ITYPE_LPWSTR:
  4199. case ITYPE_VIRT_DIR_LPWSTR:
  4200. case ITYPE_PATH_LPWSTR:
  4201. if ( pV != NULL )
  4202. {
  4203. pV = (LPVOID*)*(LPWSTR*)pV;
  4204. }
  4205. // fall-through
  4206. // convert from Unicode to ASCII
  4207. case ITYPE_AWCHAR:
  4208. if ( pV != NULL )
  4209. {
  4210. DWORD dwResLen = wcslen((LPWSTR)pV);
  4211. pR = new char[ dwResLen*2 + 1 + 1];
  4212. if ( pR == NULL )
  4213. {
  4214. SetRequestStatus( HTR_OUT_OF_RESOURCE );
  4215. fSt = FALSE;
  4216. }
  4217. else
  4218. {
  4219. if ( dwResLen == 0 ||
  4220. ( dwResLen = WideCharToMultiByte(
  4221. CP_ACP,
  4222. 0,
  4223. (LPWSTR)pV,
  4224. wcslen((LPWSTR)pV),
  4225. pR,
  4226. wcslen( (LPWSTR)pV)*2,
  4227. NULL,
  4228. NULL ) )
  4229. != 0 )
  4230. {
  4231. // if type is path, normalize path
  4232. // so that root directory ends with '\'
  4233. if ( pMap->iType == ITYPE_PATH_LPWSTR
  4234. && dwResLen == 2 && pR[1] == ':' )
  4235. {
  4236. pR[ dwResLen++ ] = L'\\';
  4237. }
  4238. pR[ dwResLen ] = '\0';
  4239. *pdwResLen = dwResLen;
  4240. *pResult = (LPSTR)pR;
  4241. *pfFree = TRUE;
  4242. fSt = TRUE;
  4243. }
  4244. else
  4245. {
  4246. delete [] pR;
  4247. }
  4248. }
  4249. }
  4250. else
  4251. {
  4252. *pdwResLen = 0;
  4253. *pResult = "";
  4254. *pfFree = FALSE;
  4255. fSt = TRUE;
  4256. }
  4257. break;
  4258. case ITYPE_LPSTR:
  4259. if ( pV != NULL )
  4260. {
  4261. pV = (LPVOID*)*(LPSTR*)pV;
  4262. }
  4263. if ( pV != NULL )
  4264. {
  4265. *pdwResLen = lstrlen( (LPSTR)pV );
  4266. *pResult = (LPSTR)pV;
  4267. *pfFree = FALSE;
  4268. fSt = TRUE;
  4269. }
  4270. else
  4271. {
  4272. *pdwResLen = 0;
  4273. *pResult = "";
  4274. *pfFree = FALSE;
  4275. fSt = TRUE;
  4276. }
  4277. break;
  4278. // convert from numeric to string after possible scaling
  4279. case ITYPE_DWORD:
  4280. case ITYPE_BOOL:
  4281. case ITYPE_SHORT:
  4282. case ITYPE_SHORTDW:
  4283. case ITYPE_1K:
  4284. case ITYPE_1M:
  4285. case ITYPE_TIME:
  4286. pR = new char[MAX_SIZE_OF_DWORD_AS_STRING];
  4287. if ( pR == NULL )
  4288. {
  4289. SetRequestStatus( HTR_OUT_OF_RESOURCE );
  4290. fSt = FALSE;
  4291. }
  4292. else
  4293. {
  4294. DWORD dwV = pMap->iType==ITYPE_SHORT
  4295. ? (DWORD)*(unsigned short*)pV : *(DWORD*)pV;
  4296. if ( pMap->iType==ITYPE_1K )
  4297. {
  4298. dwV /= 1024;
  4299. }
  4300. else if ( pMap->iType==ITYPE_1M )
  4301. {
  4302. dwV /= 1024*1024;
  4303. }
  4304. if ( pMap->iType==ITYPE_TIME )
  4305. {
  4306. wsprintf( pR,
  4307. "%d:%02d:%02d",
  4308. dwV/3600,
  4309. (dwV/60)%60,
  4310. dwV%60 );
  4311. }
  4312. else
  4313. {
  4314. DWORDToMultiByte( dwV, pR );
  4315. }
  4316. *pResult = pR;
  4317. *pdwResLen = lstrlen( pR );
  4318. *pfFree = TRUE;
  4319. fSt = TRUE;
  4320. }
  4321. break;
  4322. case ITYPE_IP_ADDR:
  4323. case ITYPE_IP_MASK:
  4324. *pResult = IPToMultiByte( (LPBYTE)pV );
  4325. *pdwResLen = lstrlen( *pResult );
  4326. *pfFree = FALSE;
  4327. fSt = TRUE;
  4328. break;
  4329. default:
  4330. SetRequestStatus( HTR_INVALID_VAR_TYPE );
  4331. break;
  4332. }
  4333. return fSt;
  4334. }
  4335. BOOL
  4336. CInetInfoConfigInfoMapper::PutString(
  4337. CInetInfoMap *pMap,
  4338. LPSTR pSet )
  4339. /*++
  4340. Routine Description:
  4341. update the value of the specified variable as specified
  4342. by its descriptor from a string
  4343. Arguments:
  4344. pMap - variable descriptor
  4345. pSet - string representation of the new value
  4346. Returns:
  4347. TRUE on success, FALSE if failure
  4348. updates reqstatus
  4349. --*/
  4350. {
  4351. BOOL fSt = FALSE;
  4352. BOOL fUp = FALSE;
  4353. LPVOID pV;
  4354. LPWSTR pW;
  4355. LPSTR pS;
  4356. LPSTR pSM = NULL;
  4357. DWORD dwResLen;
  4358. DWORD dwRes;
  4359. int cL = strlen( pSet );
  4360. DWORD dwN;
  4361. DWORD dwC;
  4362. WCHAR *pT;
  4363. // assume variable accessible, as was checked when
  4364. // retrieving the variable descriptor
  4365. (this->*pMap->GetAddr)( (LPVOID*)&pV );
  4366. if ( pV != NULL )
  4367. {
  4368. switch ( pMap->iType )
  4369. {
  4370. case ITYPE_VIRT_DIR_LPWSTR:
  4371. pSM = (LPSTR)Alloc( (cL+2) );
  4372. if ( pSM == NULL )
  4373. {
  4374. break;
  4375. }
  4376. if ( *pSet == '\\' )
  4377. {
  4378. *pSet = '/';
  4379. }
  4380. if ( *pSet != '/' )
  4381. {
  4382. pSM[0] = '/';
  4383. strcpy( pSM + 1, pSet );
  4384. ++cL;
  4385. }
  4386. else
  4387. {
  4388. strcpy( pSM, pSet );
  4389. }
  4390. // fall-through
  4391. case ITYPE_LPWSTR:
  4392. case ITYPE_PATH_LPWSTR:
  4393. pW = (WCHAR*)Alloc( (cL+1)*sizeof(WCHAR) );
  4394. if ( pW == NULL )
  4395. {
  4396. break;
  4397. }
  4398. if ( (dwResLen=cL)==0 || (pW != NULL && (dwResLen
  4399. = MultiByteToWideChar( CP_ACP,
  4400. 0,
  4401. pSM ? pSM : pSet,
  4402. cL,
  4403. pW,
  4404. cL )) != 0) )
  4405. {
  4406. pW[ dwResLen ] = 0;
  4407. *(LPWSTR*)pV = pW;
  4408. fUp = (this->*pMap->UpdateIndication)();
  4409. fSt = TRUE;
  4410. }
  4411. break;
  4412. case ITYPE_AWCHAR:
  4413. pT = new WCHAR[pMap->dwParam];
  4414. if ( pT == NULL )
  4415. {
  4416. SetRequestStatus( HTR_OUT_OF_RESOURCE );
  4417. break;
  4418. }
  4419. dwC = MultiByteToWideChar(
  4420. CP_ACP,
  4421. 0,
  4422. (LPSTR)pSet,
  4423. cL,
  4424. (LPWSTR)pT,
  4425. pMap->dwParam-1 );
  4426. if ( (dwResLen = cL) == 0 || (dwResLen = dwC) != 0 )
  4427. {
  4428. pT[dwResLen++] = 0;
  4429. if ( lstrcmpW( (PWSTR)pV, pT ) )
  4430. {
  4431. memcpy( pV, pT, dwResLen * sizeof(WCHAR) );
  4432. fUp = (this->*pMap->UpdateIndication)();
  4433. }
  4434. else
  4435. {
  4436. fUp = TRUE;
  4437. }
  4438. fSt = TRUE;
  4439. }
  4440. delete [] pT;
  4441. break;
  4442. case ITYPE_LPSTR:
  4443. pS = (char*)Alloc( cL+1 );
  4444. if ( pS != NULL )
  4445. {
  4446. memcpy( pS, pSet, cL+1 );
  4447. fUp = (this->*pMap->UpdateIndication)();
  4448. fSt = TRUE;
  4449. }
  4450. else
  4451. {
  4452. fSt = FALSE;
  4453. }
  4454. break;
  4455. case ITYPE_TIME:
  4456. fSt = FALSE;
  4457. break;
  4458. case ITYPE_1K:
  4459. *(DWORD*)pV = MultiByteToDWORD( pSet ) * 1024;
  4460. goto to_upd;
  4461. case ITYPE_1M:
  4462. *(DWORD*)pV = MultiByteToDWORD( pSet ) * 1024*1024;
  4463. goto to_upd;
  4464. case ITYPE_SHORT:
  4465. case ITYPE_SHORTDW:
  4466. dwRes = MultiByteToDWORD( pSet );
  4467. if ( dwRes > (pMap->iType == ITYPE_SHORT
  4468. ? USHRT_MAX : (DWORD)SHRT_MAX) )
  4469. {
  4470. fUp = FALSE;
  4471. fSt = TRUE;
  4472. break;
  4473. }
  4474. if ( pMap->iType == ITYPE_SHORT )
  4475. {
  4476. *(unsigned short*)pV = (unsigned short)dwRes;
  4477. }
  4478. else
  4479. {
  4480. *(DWORD*)pV = dwRes;
  4481. }
  4482. goto to_upd;
  4483. case ITYPE_DWORD:
  4484. dwN = MultiByteToDWORD( pSet );
  4485. //if ( dwN != *(DWORD*)pV )
  4486. {
  4487. *(DWORD*)pV = dwN;
  4488. goto to_upd;
  4489. }
  4490. fSt = TRUE;
  4491. fUp = TRUE;
  4492. break;
  4493. case ITYPE_BOOL:
  4494. *(BOOL*)pV = MultiByteToDWORD( pSet ) ? TRUE : FALSE;
  4495. to_upd:
  4496. fUp = (this->*pMap->UpdateIndication)();
  4497. fSt = TRUE;
  4498. break;
  4499. case ITYPE_IP_ADDR:
  4500. case ITYPE_IP_MASK:
  4501. if ( isalpha( (UCHAR)(*pSet) ) )
  4502. {
  4503. hostent *pH;
  4504. if( (pH = gethostbyname( pSet )) != NULL
  4505. && pH->h_addr != NULL )
  4506. {
  4507. memcpy( pV, pH->h_addr, IP_ADDR_BYTE_SIZE );
  4508. fUp = (this->*pMap->UpdateIndication)();
  4509. fSt = TRUE;
  4510. }
  4511. }
  4512. else if ( MultiByteToIP( &pSet, (LPBYTE)pV ) )
  4513. {
  4514. fUp = (this->*pMap->UpdateIndication)();
  4515. fSt = TRUE;
  4516. }
  4517. else if ( pMap->iType == ITYPE_IP_MASK && *pSet == '\0' )
  4518. {
  4519. memset( pV, 0xff, IP_ADDR_BYTE_SIZE );
  4520. fUp = (this->*pMap->UpdateIndication)();
  4521. fSt = TRUE;
  4522. }
  4523. else
  4524. {
  4525. SetRequestStatus( HTR_BAD_PARAM );
  4526. fSt = FALSE;
  4527. }
  4528. break;
  4529. default:
  4530. SetRequestStatus( HTR_INVALID_VAR_TYPE );
  4531. fSt = FALSE;
  4532. break;
  4533. }
  4534. if ( fSt == TRUE && fUp == FALSE )
  4535. {
  4536. SetRequestStatus( HTR_VALIDATION_FAILED );
  4537. fSt = FALSE;
  4538. }
  4539. }
  4540. else
  4541. {
  4542. fSt = FALSE;
  4543. }
  4544. return fSt;
  4545. }
  4546. //
  4547. // Disconnect user management
  4548. //
  4549. BOOL
  4550. CInetInfoConfigInfoMapper::DisconnectUser(
  4551. LPSTR pU )
  4552. /*++
  4553. Routine Description:
  4554. Disconnect user from the specified service based on numeric ID as string
  4555. The ID is opaque to HTMLA, only meaningfull to the FTP service
  4556. It is retrieved using user enumeration
  4557. Arguments:
  4558. pU - ASCII representation of the numeric ID
  4559. Returns:
  4560. TRUE on success, FALSE on failure
  4561. updates reqstatus
  4562. --*/
  4563. {
  4564. BOOL fSt = FALSE;
  4565. DWORD dwID = MultiByteToDWORD( pU );
  4566. fSt = I_FtpDisconnectUser( m_achComputerName, dwID ) == NO_ERROR;
  4567. if ( !fSt )
  4568. {
  4569. SetRequestStatus( HTR_USER_DISCONNECT_ERROR );
  4570. }
  4571. return fSt;
  4572. }
  4573. BOOL
  4574. CInetInfoConfigInfoMapper::DisconnectAll(
  4575. VOID )
  4576. /*++
  4577. Routine Description:
  4578. Disconnect all users from the specified service
  4579. Arguments:
  4580. None
  4581. Returns:
  4582. TRUE on success, FALSE on failure
  4583. --*/
  4584. {
  4585. BOOL fSt = FALSE;
  4586. DWORD dwC, dwI, dwCurID;
  4587. if ( m_Users.GetCountAsDWORD( &dwC ) )
  4588. {
  4589. ResetIter();
  4590. for ( dwI = 0 ; dwI < dwC ; ++dwI )
  4591. {
  4592. if ( !m_Users.GetIDAsDWORD( &dwCurID ) )
  4593. {
  4594. break;
  4595. }
  4596. // can't do anything with status at this point,
  4597. // so ignore error
  4598. I_FtpDisconnectUser( m_achComputerName, dwCurID );
  4599. IncIter();
  4600. }
  4601. fSt = TRUE;
  4602. }
  4603. // if error accessing user enum, RequestStatus already set by CUserEnum
  4604. return fSt;
  4605. }
  4606. BOOL
  4607. CInetInfoConfigInfoMapper::AliasVirtDir(
  4608. INET_INFO_VIRTUAL_ROOT_ENTRY *pU )
  4609. /*++
  4610. Routine Description:
  4611. create an alias for the matching virtual root
  4612. by coalescing all alpha-numeric characters
  4613. from the virtual root physical path
  4614. Arguments:
  4615. pU - ptr to virtual root entry
  4616. Returns:
  4617. TRUE on success, FALSE on failure
  4618. --*/
  4619. {
  4620. int lD = wcslen( pU->pszDirectory );
  4621. int lR = 0;
  4622. if ( !(pU->pszRoot = (LPWSTR)Alloc( (lD + 1 + 1)*sizeof(WCHAR) )) )
  4623. {
  4624. return FALSE;
  4625. }
  4626. pU->pszRoot[lR++] = L'/';
  4627. for ( int x = 0 ; x < lD ; ++x )
  4628. {
  4629. if ( iswalpha( pU->pszDirectory[x] )
  4630. || iswdigit( pU->pszDirectory[x] ) )
  4631. {
  4632. pU->pszRoot[lR++] = pU->pszDirectory[x];
  4633. }
  4634. }
  4635. pU->pszRoot[lR] = 0;
  4636. return TRUE;
  4637. }
  4638. BOOL
  4639. CInetInfoConfigInfoMapper::HandleVirtDirRequest(
  4640. LPSTR pszVirt,
  4641. LPSTR pszAddr,
  4642. int iReq )
  4643. /*++
  4644. Routine Description:
  4645. Handle a virtual root command. can be one of :
  4646. _VIRT_DIR_REQ_ALIAS : create an alias for the matching virtual root
  4647. by coalescing all alpha-numeric characters
  4648. from the virtual root physical path
  4649. _VIRT_DIR_REQ_CHECK : check for the existence of the specified
  4650. virtual root, set reqstatus to HTR_DIR_SAME_NAME
  4651. if present
  4652. Arguments:
  4653. pszVirt - name of virtual root
  4654. pszAddr - network address virtual root
  4655. iReq : a _VIRT_DIR_REQ_ command
  4656. Returns:
  4657. TRUE on success, FALSE on failure
  4658. updates reqstatus
  4659. --*/
  4660. {
  4661. LPINET_INFO_VIRTUAL_ROOT_LIST pL = m_pConfig->VirtualRoots;
  4662. INET_INFO_VIRTUAL_ROOT_ENTRY isE;
  4663. BOOL fSt = FALSE;
  4664. CHAR achID[MAX_PATH + 80];
  4665. if ( pL == NULL )
  4666. {
  4667. goto no_match;
  4668. }
  4669. // drive dir part is empty
  4670. strcpy( achID, pszVirt );
  4671. strcat( achID, REF_SEP_STR REF_SEP_STR);
  4672. strcat( achID, pszAddr );
  4673. // parse ID
  4674. if ( BuildVirtDirUniqueID( achID, &isE ) )
  4675. {
  4676. ResetIter();
  4677. // iterate through list
  4678. DWORD dwI;
  4679. for ( dwI = 0 ; dwI < pL->cEntries ; ++dwI )
  4680. {
  4681. if ( VirtDirCmp( pL->aVirtRootEntry + dwI, &isE, FALSE ) )
  4682. {
  4683. break;
  4684. }
  4685. IncIter();
  4686. }
  4687. if ( dwI == pL->cEntries )
  4688. {
  4689. goto no_match;
  4690. }
  4691. else if ( iReq == _VIRT_DIR_REQ_ALIAS )
  4692. {
  4693. // update pszRoot with alphanum chars from pszDirectory
  4694. fSt = AliasVirtDir( pL->aVirtRootEntry + dwI );
  4695. }
  4696. else // check root
  4697. {
  4698. SetRequestStatus( HTR_DIR_SAME_NAME );
  4699. }
  4700. goto ret;
  4701. }
  4702. else
  4703. {
  4704. SetRequestStatus( HTR_BAD_PARAM );
  4705. }
  4706. goto ret;
  4707. no_match:
  4708. if ( iReq != _VIRT_DIR_REQ_CHECK )
  4709. {
  4710. SetRequestStatus( HTR_REF_NOT_FOUND );
  4711. fSt = FALSE;
  4712. }
  4713. else
  4714. {
  4715. fSt = TRUE;
  4716. }
  4717. ret:
  4718. return fSt;
  4719. }
  4720. BOOL
  4721. CInetInfoConfigInfoMapper::GetStatus(
  4722. VOID )
  4723. /*++
  4724. Routine Description:
  4725. Update the status of the IIS services : HTTP, FTP, Gopher
  4726. stored in m_dw*Status
  4727. status is the return code from the RPC InetInfoGetAdminInformation()
  4728. Arguments:
  4729. None
  4730. Returns:
  4731. TRUE on success, FALSE on failure
  4732. --*/
  4733. {
  4734. BOOL fSt = TRUE;
  4735. INET_INFO_CONFIG_INFO *pConfig;
  4736. DWORD dwNeed;
  4737. // check which status are missing :
  4738. // all services except the one linked to this object
  4739. switch ( m_dwCurrentServerType )
  4740. {
  4741. case INET_HTTP_SVC_ID:
  4742. dwNeed = INET_FTP_SVC_ID | INET_GOPHER_SVC_ID; break;
  4743. case INET_FTP_SVC_ID:
  4744. dwNeed = INET_HTTP_SVC_ID | INET_GOPHER_SVC_ID; break;
  4745. case INET_GOPHER_SVC_ID:
  4746. dwNeed = INET_HTTP_SVC_ID | INET_FTP_SVC_ID; break;
  4747. default:
  4748. dwNeed = INET_HTTP_SVC_ID | INET_FTP_SVC_ID | INET_GOPHER_SVC_ID;
  4749. }
  4750. if ( dwNeed & INET_HTTP_SVC_ID )
  4751. {
  4752. pConfig = NULL;
  4753. if ( (m_dwHttpStatus = InetInfoGetAdminInformation(
  4754. m_achComputerName, INET_HTTP_SVC_ID, &pConfig ))
  4755. == NO_ERROR || m_dwHttpStatus == 2 )
  4756. {
  4757. if ( pConfig != NULL )
  4758. {
  4759. MIDL_user_free( pConfig );
  4760. }
  4761. }
  4762. }
  4763. if ( dwNeed & INET_FTP_SVC_ID )
  4764. {
  4765. pConfig = NULL;
  4766. if ( (m_dwFtpStatus = InetInfoGetAdminInformation( m_achComputerName,
  4767. INET_FTP_SVC_ID, &pConfig ))
  4768. == NO_ERROR || m_dwFtpStatus == 2 )
  4769. {
  4770. if ( pConfig != NULL )
  4771. {
  4772. MIDL_user_free( pConfig );
  4773. }
  4774. }
  4775. }
  4776. if ( dwNeed & INET_GOPHER_SVC_ID )
  4777. {
  4778. pConfig = NULL;
  4779. if ( (m_dwGopherStatus = InetInfoGetAdminInformation( m_achComputerName,
  4780. INET_GOPHER_SVC_ID, &pConfig ))
  4781. == NO_ERROR || m_dwGopherStatus == 2 )
  4782. {
  4783. if ( pConfig != NULL )
  4784. {
  4785. MIDL_user_free( pConfig );
  4786. }
  4787. }
  4788. }
  4789. return fSt;
  4790. }
  4791. // IP list management
  4792. BOOL
  4793. CInetInfoConfigInfoMapper::AddIPAccess(
  4794. BOOL fDenyList )
  4795. {
  4796. return CloneIPAccesses( fDenyList, TRUE, FALSE, 0 );
  4797. }
  4798. BOOL
  4799. CInetInfoConfigInfoMapper::DeleteIPAccess(
  4800. BOOL fDenyList,
  4801. LPSTR pID )
  4802. {
  4803. if ( PositionIPAccess( fDenyList, pID ) )
  4804. {
  4805. BOOL fSt = CloneIPAccesses( fDenyList, FALSE, TRUE, m_iIter );
  4806. if ( fSt )
  4807. {
  4808. UpdateIP();
  4809. }
  4810. return TRUE;
  4811. }
  4812. return FALSE;
  4813. }
  4814. BOOL
  4815. CInetInfoConfigInfoMapper::BuildIPUniqueID(
  4816. LPSTR pI,
  4817. INET_INFO_IP_SEC_ENTRY* pE )
  4818. /*++
  4819. Routine Description:
  4820. Decode the ASCII representation of an IP entry reference
  4821. Arguments:
  4822. pI - contains the IP reference
  4823. pE - pointer to a IP entry where dwMask & dwNetwork will be filled
  4824. WARNING:
  4825. Must be in sync with IPRef()
  4826. Returns:
  4827. TRUE on success, FALSE on failure
  4828. --*/
  4829. {
  4830. for ( int x = 0 ; x < 2 ; ++x )
  4831. {
  4832. LPBYTE pB = x ? (LPBYTE)&pE->dwMask : (LPBYTE)&pE->dwNetwork;
  4833. if ( !MultiByteToIP( &pI, pB ) )
  4834. {
  4835. return FALSE;
  4836. }
  4837. if ( x != 1 && *pI++ != REF_SEP )
  4838. {
  4839. return FALSE;
  4840. }
  4841. }
  4842. return TRUE;
  4843. }
  4844. BOOL
  4845. CInetInfoConfigInfoMapper::PositionIPAccess(
  4846. BOOL fDenyList,
  4847. LPSTR pID )
  4848. /*++
  4849. Routine Description:
  4850. Position the iteration counter ( m_iIter ) on the IP entry
  4851. matching the specified IP reference in the specified list
  4852. Arguments:
  4853. fDenyList - TRUE if the list is the deny list, else FALSE
  4854. for the grant list
  4855. pID - pointer to an IP entry reference
  4856. Returns:
  4857. TRUE on success, FALSE on failure
  4858. updates reqstatus, m_iIter
  4859. --*/
  4860. {
  4861. LPINET_INFO_IP_SEC_LIST pL = fDenyList
  4862. ? m_pConfig->DenyIPList : m_pConfig->GrantIPList;
  4863. INET_INFO_IP_SEC_ENTRY isE;
  4864. BOOL fSt = FALSE;
  4865. InvalidateIPSingle();
  4866. if ( pL == NULL )
  4867. {
  4868. SetRequestStatus( HTR_REF_NOT_FOUND );
  4869. return FALSE;
  4870. }
  4871. // parse ID
  4872. if ( BuildIPUniqueID( pID, &isE ) )
  4873. {
  4874. ResetIter();
  4875. // iterate through list
  4876. DWORD dwI;
  4877. for ( dwI = 0 ; dwI < pL->cEntries ; ++dwI )
  4878. {
  4879. if ( !memcmp( pL->aIPSecEntry + dwI, &isE, sizeof(isE) ) )
  4880. {
  4881. fSt = TRUE;
  4882. break;
  4883. }
  4884. IncIter();
  4885. }
  4886. if ( dwI == pL->cEntries )
  4887. {
  4888. SetRequestStatus( HTR_REF_NOT_FOUND );
  4889. }
  4890. }
  4891. else
  4892. {
  4893. SetRequestStatus( HTR_BAD_PARAM );
  4894. }
  4895. return fSt;
  4896. }
  4897. BOOL
  4898. CInetInfoConfigInfoMapper::CloneIPAccesses(
  4899. BOOL fDenyList,
  4900. BOOL fExtend,
  4901. BOOL fDel,
  4902. DWORD dwToDel )
  4903. /*++
  4904. Routine Description:
  4905. Clone the specified IP list with optional extension and/or
  4906. deletion of an entry
  4907. Arguments:
  4908. fDenyList - TRUE if the list is the deny list, else FALSE
  4909. for the grant list
  4910. fExtend - TRUE if list is to be extended by one entry ( added
  4911. at the end of the list, m_iIter will be positioned
  4912. on this new entry )
  4913. fDel - TRUE if the entry specified in dwToDel is to be deleted
  4914. from the list
  4915. dwToDel - specify the entry index ( 0-based ) to delete if fDel
  4916. is TRUE
  4917. Returns:
  4918. TRUE on success, FALSE on failure
  4919. updates reqstatus, m_iIter
  4920. --*/
  4921. {
  4922. LPINET_INFO_IP_SEC_LIST pL;
  4923. DWORD dwNewCount, dwOldCount;
  4924. LPINET_INFO_IP_SEC_LIST pN;
  4925. pL = fDenyList ? m_pConfig->DenyIPList : m_pConfig->GrantIPList;
  4926. dwOldCount = pL ? pL->cEntries : 0;
  4927. dwNewCount = dwOldCount + (fExtend ? 1 : 0) - (fDel ? 1 : 0);
  4928. pN = (LPINET_INFO_IP_SEC_LIST)Alloc(
  4929. sizeof(INET_INFO_IP_SEC_LIST) + dwNewCount
  4930. * sizeof(INET_INFO_IP_SEC_ENTRY));
  4931. if ( pN == NULL )
  4932. {
  4933. // insure m_iIter is invalid ( so update attempts will fail )
  4934. if ( fExtend )
  4935. {
  4936. SetIter( dwOldCount );
  4937. }
  4938. return FALSE;
  4939. }
  4940. pN->cEntries = dwNewCount;
  4941. DWORD dwF;
  4942. DWORD dwT;
  4943. for ( dwF = dwT = 0 ; dwF < dwOldCount ; ++dwF )
  4944. {
  4945. if ( fDel && dwF == dwToDel )
  4946. {
  4947. continue;
  4948. }
  4949. memcpy( pN->aIPSecEntry + dwT,
  4950. pL->aIPSecEntry + dwF,
  4951. sizeof(INET_INFO_IP_SEC_ENTRY) );
  4952. ++dwT;
  4953. }
  4954. if ( fDenyList )
  4955. {
  4956. m_pConfig->DenyIPList = pN;
  4957. }
  4958. else
  4959. {
  4960. m_pConfig->GrantIPList = pN;
  4961. }
  4962. if ( fExtend )
  4963. {
  4964. SetIter( dwNewCount - 1 );
  4965. memset( &pN->aIPSecEntry[dwNewCount-1].dwMask,
  4966. 0xff,
  4967. IP_ADDR_BYTE_SIZE );
  4968. memset( &pN->aIPSecEntry[dwNewCount-1].dwNetwork,
  4969. 0x00,
  4970. IP_ADDR_BYTE_SIZE );
  4971. }
  4972. return TRUE;
  4973. }
  4974. BOOL
  4975. CInetInfoConfigInfoMapper::SetRemoteAddr(
  4976. LPSTR pR )
  4977. /*++
  4978. Routine Description:
  4979. Store the client IP address in binary and ASCII format
  4980. for later use
  4981. Arguments:
  4982. pR - ASCII representation of the client IP address.
  4983. Returns:
  4984. TRUE on success, FALSE on failure
  4985. --*/
  4986. {
  4987. BOOL fSt = FALSE;
  4988. m_pRemoteAddr = (LPBYTE)Alloc( IP_ADDR_BYTE_SIZE );
  4989. m_pszRemoteAddr = (LPSTR)Alloc( lstrlen( pR ) + 1 );
  4990. if ( m_pRemoteAddr != NULL && m_pszRemoteAddr != NULL )
  4991. {
  4992. LPSTR pC = pR;
  4993. if ( MultiByteToIP( &pC, m_pRemoteAddr ) )
  4994. {
  4995. lstrcpy( m_pszRemoteAddr, pR );
  4996. fSt = TRUE;
  4997. }
  4998. else
  4999. {
  5000. SetRequestStatus( HTR_BAD_PARAM );
  5001. }
  5002. }
  5003. return fSt;
  5004. }
  5005. BOOL
  5006. CInetInfoConfigInfoMapper::SetIPAccessDefault(
  5007. BOOL fIsDeny )
  5008. /*++
  5009. Routine Description:
  5010. Set the default action for the IP access check made by the server
  5011. Can be either deny or grant access.
  5012. To signal a 'deny' default condition we set the deny list to be
  5013. empty, and to signal 'grant' we set the grant list to be empty
  5014. If both lists are empty the default is 'grant'
  5015. To set the default to deny with an empty 'grant' list the regular
  5016. admin tool create a dummy entry 0.0.0.0
  5017. As we must provide access to the distant admin after switching the
  5018. default to 'deny', we use the address of the client as the entry
  5019. to store in the 'grant' list in this case.
  5020. Arguments:
  5021. dIsDeny - TRUE if default is to be deny, FALSE for grant
  5022. Returns:
  5023. TRUE on success, FALSE on failure
  5024. --*/
  5025. {
  5026. LPINET_INFO_IP_SEC_LIST *pL;
  5027. BOOL fSt = TRUE;
  5028. if ( fIsDeny )
  5029. {
  5030. m_pConfig->DenyIPList = (LPINET_INFO_IP_SEC_LIST)NULL;
  5031. pL = &m_pConfig->GrantIPList;
  5032. // insert null entry if none exist in exception list
  5033. if ( *pL == NULL || (*pL)->cEntries == 0 )
  5034. {
  5035. fSt = CloneIPAccesses( !fIsDeny, TRUE, FALSE, 0 );
  5036. if ( fSt )
  5037. {
  5038. // set addr to REMOTE_ADDR
  5039. INET_INFO_IP_SEC_ENTRY *pE = &(*pL)->aIPSecEntry[m_iIter];
  5040. memcpy( &pE->dwNetwork, m_pRemoteAddr, IP_ADDR_BYTE_SIZE );
  5041. memset( &pE->dwMask, 0xff, IP_ADDR_BYTE_SIZE );
  5042. }
  5043. }
  5044. }
  5045. else
  5046. {
  5047. m_pConfig->GrantIPList = (LPINET_INFO_IP_SEC_LIST)NULL;
  5048. }
  5049. if ( fSt )
  5050. {
  5051. UpdateIP();
  5052. }
  5053. return fSt;
  5054. }
  5055. // Virtual Directories list management
  5056. BOOL
  5057. CInetInfoConfigInfoMapper::AddVirtDir(
  5058. VOID )
  5059. /*++
  5060. Routine Description:
  5061. Add a virtual root entry in the current list, position
  5062. the iteration counter to point to this new entry.
  5063. Arguments:
  5064. None
  5065. Returns:
  5066. TRUE on success, FALSE on failure
  5067. Updates m_iIter ( iteration counter )
  5068. --*/
  5069. {
  5070. return CloneVirtDirs( TRUE, FALSE, 0 );
  5071. }
  5072. BOOL
  5073. CInetInfoConfigInfoMapper::DeleteVirtDir(
  5074. LPSTR pID )
  5075. /*++
  5076. Routine Description:
  5077. Delete the virtual root entry specified by the reference
  5078. Arguments:
  5079. pID - virtual root reference
  5080. Returns:
  5081. TRUE on success, FALSE on failure ( e.g. inexistant reference )
  5082. --*/
  5083. {
  5084. if ( PositionVirtDir( pID ) )
  5085. {
  5086. BOOL fSt = CloneVirtDirs( FALSE, TRUE, m_iIter );
  5087. if ( fSt )
  5088. {
  5089. UpdateRoot();
  5090. }
  5091. return TRUE;
  5092. }
  5093. return FALSE;
  5094. }
  5095. BOOL
  5096. CInetInfoConfigInfoMapper::BuildVirtDirUniqueID(
  5097. LPSTR pI,
  5098. INET_INFO_VIRTUAL_ROOT_ENTRY* pE )
  5099. /*++
  5100. Routine Description:
  5101. Decode the ASCII representation of a virtual root reference
  5102. Arguments:
  5103. pI - contains the virtual root reference
  5104. pE - pointer to a virtual root entry pszRoot,
  5105. pszDirectory & pszAddress will be filled
  5106. WARNING:
  5107. Must be in sync with RootRef()
  5108. Returns:
  5109. TRUE on success, FALSE on failure
  5110. --*/
  5111. {
  5112. LPSTR p;
  5113. LPSTR pA;
  5114. if ( (p = strchr( pI, REF_SEP )) != NULL )
  5115. {
  5116. if ( (pA = strchr( p+1, REF_SEP )) != NULL )
  5117. {
  5118. int l1, l2, l3;
  5119. DWORD dwL1, dwL2, dwL3;
  5120. pE->pszRoot = (LPWSTR)Alloc( (ULONG)(((l1=DIFF(p-pI))+1)*sizeof(WCHAR)) );
  5121. pE->pszDirectory = (LPWSTR)Alloc( (ULONG)(((l2=DIFF(pA-p)-1)+1)*sizeof(WCHAR)) );
  5122. pE->pszAddress = (LPWSTR)Alloc( ((l3=lstrlen(pI)-l1-l2-2)+1)
  5123. *sizeof(WCHAR) );
  5124. if ( pE->pszRoot == NULL
  5125. || pE->pszDirectory == NULL
  5126. || pE->pszAddress == NULL )
  5127. {
  5128. return FALSE;
  5129. }
  5130. // convert to UNICODE if string non empty
  5131. if ( dwL1 = l1 )
  5132. {
  5133. dwL1 = MultiByteToWideChar( CP_ACP,
  5134. 0,
  5135. pI,
  5136. l1,
  5137. pE->pszRoot,
  5138. l1 );
  5139. }
  5140. if ( dwL2 = l2 )
  5141. {
  5142. dwL2 = MultiByteToWideChar( CP_ACP,
  5143. 0,
  5144. p+1,
  5145. l2,
  5146. pE->pszDirectory,
  5147. l2 );
  5148. }
  5149. if ( dwL3 = l3 )
  5150. {
  5151. dwL3 = MultiByteToWideChar( CP_ACP,
  5152. 0,
  5153. pA+1,
  5154. l3,
  5155. pE->pszAddress,
  5156. l3 );
  5157. }
  5158. pE->pszRoot[ dwL1 ] = '\0';
  5159. pE->pszDirectory[ dwL2 ] = '\0';
  5160. pE->pszAddress[ dwL3 ] = '\0';
  5161. // return OK if empty string or convertion successfull
  5162. // for both components
  5163. return (!l1 || dwL1) && (!l2 || dwL2 ) && (!l3 || dwL3 )
  5164. ? TRUE : FALSE;
  5165. }
  5166. }
  5167. return FALSE;
  5168. }
  5169. BOOL
  5170. CInetInfoConfigInfoMapper::VirtDirCmp(
  5171. INET_INFO_VIRTUAL_ROOT_ENTRY* p1,
  5172. INET_INFO_VIRTUAL_ROOT_ENTRY* p2,
  5173. BOOL fCompareDrive )
  5174. /*++
  5175. Routine Description:
  5176. Test two virtual root entries for identity
  5177. if fCompareDrive is TRUE, pszRoot, pszDirectory & pszAddress
  5178. will be used in the compare operation
  5179. if FALSE, only pszRoot & pszAddress will be used
  5180. Arguments:
  5181. p1 - 1st virtual root entry
  5182. p2 - 2nd virtual root entry
  5183. fCompareDrive - TRUE to enable compare of pszDirectory
  5184. Returns:
  5185. TRUE if identical.
  5186. --*/
  5187. {
  5188. return ( !wcscmp(p1->pszRoot ? p1->pszRoot : L"", p2->pszRoot)
  5189. && (!fCompareDrive || !wcscmp( p1->pszDirectory
  5190. ? p1->pszDirectory : L"", p2->pszDirectory))
  5191. && !wcscmp( p1->pszAddress ? p1->pszAddress : L"",
  5192. p2->pszAddress) )
  5193. ? TRUE : FALSE;
  5194. }
  5195. BOOL
  5196. CInetInfoConfigInfoMapper::PositionVirtDir(
  5197. LPSTR pID )
  5198. /*++
  5199. Routine Description:
  5200. Position the iteration counter ( m_iIter ) on the virtual
  5201. root entry matching the specified virtual root reference
  5202. Arguments:
  5203. pID - pointer to a virutal root reference
  5204. Returns:
  5205. TRUE on success, FALSE on failure
  5206. updates reqstatus, m_iIter
  5207. --*/
  5208. {
  5209. LPINET_INFO_VIRTUAL_ROOT_LIST pL = m_pConfig->VirtualRoots;
  5210. INET_INFO_VIRTUAL_ROOT_ENTRY isE;
  5211. BOOL fSt = FALSE;
  5212. if ( pL == NULL )
  5213. {
  5214. SetRequestStatus( HTR_REF_NOT_FOUND );
  5215. return FALSE;
  5216. }
  5217. // parse ID
  5218. if ( BuildVirtDirUniqueID( pID, &isE ) )
  5219. {
  5220. ResetIter();
  5221. // iterate through list
  5222. DWORD dwI;
  5223. for ( dwI = 0 ; dwI < pL->cEntries ; ++dwI )
  5224. {
  5225. if ( VirtDirCmp( pL->aVirtRootEntry + dwI, &isE, TRUE ) )
  5226. {
  5227. fSt = TRUE;
  5228. break;
  5229. }
  5230. IncIter();
  5231. }
  5232. if ( dwI == pL->cEntries )
  5233. {
  5234. SetRequestStatus( HTR_REF_NOT_FOUND );
  5235. }
  5236. else
  5237. {
  5238. SetRootEntryVars();
  5239. }
  5240. }
  5241. else
  5242. {
  5243. SetRequestStatus( HTR_BAD_PARAM );
  5244. }
  5245. return fSt;
  5246. }
  5247. BOOL
  5248. CInetInfoConfigInfoMapper::CloneVirtDirs(
  5249. BOOL fExtend,
  5250. BOOL fDel,
  5251. DWORD dwToDel )
  5252. /*++
  5253. Routine Description:
  5254. Clone the virtual root list with optional extension and/or
  5255. deletion of an entry
  5256. Arguments:
  5257. fExtend - TRUE if list is to be extended by one entry ( added
  5258. at the end of the list, m_iIter will be positioned
  5259. on this new entry )
  5260. fDel - TRUE if the entry specified in dwToDel is to be deleted
  5261. from the list
  5262. dwToDel - specify the entry index ( 0-based ) to delete if fDel
  5263. is TRUE
  5264. Returns:
  5265. TRUE on success, FALSE on failure
  5266. updates reqstatus, m_iIter
  5267. --*/
  5268. {
  5269. LPINET_INFO_VIRTUAL_ROOT_LIST pL;
  5270. DWORD dwNewCount;
  5271. LPINET_INFO_VIRTUAL_ROOT_LIST pN;
  5272. pL = m_pConfig->VirtualRoots;
  5273. dwNewCount = pL->cEntries + (fExtend ? 1 : 0) - (fDel ? 1 : 0);
  5274. pN = (LPINET_INFO_VIRTUAL_ROOT_LIST)Alloc(
  5275. sizeof(INET_INFO_VIRTUAL_ROOT_LIST) + dwNewCount
  5276. * sizeof(INET_INFO_VIRTUAL_ROOT_ENTRY));
  5277. if ( pN == NULL )
  5278. {
  5279. // insure m_iIter is invalid ( so update attempts will fail )
  5280. if ( fExtend )
  5281. {
  5282. SetIter( pL->cEntries );
  5283. }
  5284. return FALSE;
  5285. }
  5286. pN->cEntries = dwNewCount;
  5287. DWORD dwF;
  5288. DWORD dwT;
  5289. for ( dwF = dwT = 0 ; dwF < pL->cEntries ; ++dwF )
  5290. {
  5291. if ( fDel && dwF == dwToDel )
  5292. {
  5293. continue;
  5294. }
  5295. memcpy( pN->aVirtRootEntry + dwT,
  5296. pL->aVirtRootEntry + dwF,
  5297. sizeof(INET_INFO_VIRTUAL_ROOT_ENTRY) );
  5298. ++dwT;
  5299. }
  5300. m_pConfig->VirtualRoots = pN;
  5301. if ( fExtend )
  5302. {
  5303. SetIter( dwNewCount - 1 );
  5304. LPWSTR pA = (LPWSTR)Alloc( sizeof(WCHAR) );
  5305. if ( pA != NULL )
  5306. {
  5307. pA[0] = L'\0';
  5308. pN->aVirtRootEntry[dwNewCount-1].pszAddress = pA;
  5309. }
  5310. else
  5311. {
  5312. return FALSE;
  5313. }
  5314. }
  5315. return TRUE;
  5316. }
  5317. VOID
  5318. CInetInfoConfigInfoMapper::SetRPCStatusString( DWORD dwS )
  5319. /*++
  5320. Routine Description:
  5321. Set the RPC status string to the system message with code dwS. If no matching
  5322. code is found, set status string to empty string
  5323. Arguments:
  5324. dwS - System message code
  5325. Returns:
  5326. VOID
  5327. --*/
  5328. {
  5329. LPVOID pszMsgBuffer;
  5330. BOOL fFoundMessage = FALSE;
  5331. DWORD result = 0;
  5332. HANDLE hdll;
  5333. DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
  5334. FORMAT_MESSAGE_FROM_SYSTEM |
  5335. FORMAT_MESSAGE_IGNORE_INSERTS;
  5336. //
  5337. //Check whether we can find the error message in the current
  5338. //image
  5339. //
  5340. if ( ! FormatMessage( flags,
  5341. NULL,
  5342. dwS,
  5343. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  5344. (LPTSTR) &pszMsgBuffer,
  5345. 0,
  5346. NULL ))
  5347. {
  5348. //
  5349. //Couldn't find it in current image, check a list of DLLs
  5350. //
  5351. flags = FORMAT_MESSAGE_ALLOCATE_BUFFER
  5352. | FORMAT_MESSAGE_IGNORE_INSERTS
  5353. | FORMAT_MESSAGE_MAX_WIDTH_MASK
  5354. | FORMAT_MESSAGE_FROM_HMODULE;
  5355. for (int i = 0; i < NUM_ERROR_CODE_DLLS; i++)
  5356. {
  5357. hdll = LoadLibraryA(g_apszErrorCodeDlls[i]);
  5358. //
  5359. //Check for error msg in this dll
  5360. //
  5361. if (hdll != NULL)
  5362. {
  5363. result = FormatMessage( flags,
  5364. (LPVOID) hdll,
  5365. (DWORD) dwS,
  5366. 0,
  5367. (LPTSTR)&pszMsgBuffer,
  5368. 0,
  5369. NULL );
  5370. //Done with the lib, unload
  5371. FreeLibrary((HMODULE)hdll);
  5372. //
  5373. //Found an error string
  5374. //
  5375. if (result)
  5376. {
  5377. fFoundMessage = TRUE;
  5378. break;
  5379. }
  5380. } //if (hdll != NULL)
  5381. } //for (int i = 0; ...)
  5382. } //if ( ! FormatMessage...)
  5383. //
  5384. //Found error message in current image
  5385. //
  5386. else
  5387. {
  5388. fFoundMessage = TRUE;
  5389. }
  5390. if (fFoundMessage)
  5391. {
  5392. //deallocate the string if it's been allocated by FormatMessage
  5393. if (m_fAllocatedRPCStatusString)
  5394. {
  5395. LocalFree((HLOCAL) m_pszRPCStatusString);
  5396. }
  5397. m_pszRPCStatusString = (LPTSTR) pszMsgBuffer;
  5398. m_fAllocatedRPCStatusString = TRUE;
  5399. }
  5400. else
  5401. {
  5402. //Couldn't get an error message string, set status string to be the numeric
  5403. //error code
  5404. //free the string if it's been allocated by FormatMessage
  5405. if (m_fAllocatedRPCStatusString)
  5406. {
  5407. LocalFree((HLOCAL) m_pszRPCStatusString);
  5408. }
  5409. m_pszRPCStatusString = (LPTSTR) m_achRPCErrorCodeBuffer;
  5410. wsprintf(m_pszRPCStatusString,"%ld", dwS);
  5411. m_fAllocatedRPCStatusString = FALSE;
  5412. }
  5413. }
  5414. /////////////////// Verb Context
  5415. CVerbContext::CVerbContext(
  5416. VOID )
  5417. {
  5418. m_pszVerbName = NULL;
  5419. m_cNbInfoMap = m_cAllocedInfoMap = 0;
  5420. m_pMaps = NULL;
  5421. }
  5422. CVerbContext::~CVerbContext(
  5423. VOID )
  5424. {
  5425. if ( m_pszVerbName != NULL )
  5426. {
  5427. delete [] m_pszVerbName;
  5428. }
  5429. if ( m_pMaps != NULL )
  5430. {
  5431. delete [] m_pMaps;
  5432. }
  5433. }
  5434. CInetInfoMap*
  5435. CVerbContext::GetInfoMap(
  5436. DWORD dwI )
  5437. /*++
  5438. Routine Description:
  5439. Access the specified entry ( 0-based ) in the parameter list
  5440. of a verb context
  5441. Arguments:
  5442. dwI - index in the array of parameters
  5443. Returns:
  5444. pointer to variable descriptor or NULL if error
  5445. --*/
  5446. {
  5447. if ( dwI < m_cNbInfoMap )
  5448. {
  5449. return m_pMaps[dwI];
  5450. }
  5451. return NULL;
  5452. }
  5453. BOOL
  5454. CVerbContext::AddInfoMap(
  5455. CInetInfoMap* pI )
  5456. /*++
  5457. Routine Description:
  5458. Add a parameter entry in the list of parameters for a verb context
  5459. Arguments:
  5460. pI - pointer to a parameter descriptor
  5461. Returns:
  5462. TRUE on success, FALSE on failure
  5463. --*/
  5464. {
  5465. if ( m_cNbInfoMap == m_cAllocedInfoMap )
  5466. {
  5467. m_cAllocedInfoMap += 4;
  5468. CInetInfoMap **pN = new CInetInfoMap*[m_cAllocedInfoMap];
  5469. if ( pN == NULL )
  5470. {
  5471. return FALSE;
  5472. }
  5473. if ( m_pMaps )
  5474. {
  5475. memcpy( pN, m_pMaps, m_cNbInfoMap * sizeof(CInetInfoMap*) );
  5476. delete [] m_pMaps;
  5477. }
  5478. m_pMaps = pN;
  5479. }
  5480. m_pMaps[m_cNbInfoMap++] = pI;
  5481. return TRUE;
  5482. }
  5483. DWORD
  5484. CVerbContext::Parse(
  5485. CInetInfoConfigInfoMapper *pMapper,
  5486. LPBYTE pS,
  5487. DWORD dwL )
  5488. /*++
  5489. Routine Description:
  5490. Parse a verb command for parameters ( separated with space )
  5491. remember the verb name &
  5492. create an internal array of parameters as variable descriptors
  5493. Arguments:
  5494. pMapper - pointer to object used to map variable names to variable
  5495. descriptors
  5496. pS - verb command to parse
  5497. dwL - maximum # of characters available for parsing
  5498. Returns:
  5499. length of characters used for parsing the verb excluding the "%>"
  5500. delimitor or 0 if error
  5501. --*/
  5502. {
  5503. DWORD dwW = dwL;
  5504. BOOL fIsVerb;
  5505. CInetInfoMap* pM;
  5506. LPSTR pResult;
  5507. DWORD dwResLen;
  5508. for ( fIsVerb = TRUE ; dwL ; fIsVerb = FALSE )
  5509. {
  5510. // skip white space
  5511. while ( dwL && *pS == ' ' )
  5512. {
  5513. ++pS;
  5514. --dwL;
  5515. }
  5516. LPBYTE pW = pS;
  5517. DWORD dwLenTok = 0;
  5518. // get until '%', ' '
  5519. int c = '%';
  5520. while ( dwL && (c=*pS)!='%' && c!=' ' )
  5521. {
  5522. ++dwLenTok;
  5523. ++pS;
  5524. --dwL;
  5525. }
  5526. if ( fIsVerb )
  5527. {
  5528. m_pszVerbName = new char[dwLenTok+1];
  5529. if ( m_pszVerbName == NULL )
  5530. {
  5531. pMapper->SetRequestStatus( HTR_OUT_OF_RESOURCE );
  5532. return 0;
  5533. }
  5534. memcpy( m_pszVerbName, pW, dwLenTok );
  5535. m_pszVerbName[dwLenTok] = '\0';
  5536. }
  5537. else if ( !memcmp( "iis.", pW, sizeof("iis.")-1 ) )
  5538. {
  5539. if ( pMapper->GetFromServer( (LPSTR)pW, dwLenTok, &pResult,
  5540. &dwResLen ) )
  5541. {
  5542. goto alloc_map;
  5543. }
  5544. return 0; // error
  5545. }
  5546. else if ( !memcmp( "msgbody.", pW, sizeof("msgbody.")-1 ) )
  5547. {
  5548. if ( pMapper->GetFromMsgBody( (LPSTR)pW, dwLenTok, &pResult,
  5549. &dwResLen ) )
  5550. {
  5551. alloc_map:
  5552. pM = (CInetInfoMap*)pMapper->Alloc( sizeof(CInetInfoMap) );
  5553. if ( !pM )
  5554. {
  5555. return 0;
  5556. }
  5557. pM->iType = ITYPE_PARAM_LIT_STRING;
  5558. pM->pName = pResult;
  5559. goto add_map;
  5560. }
  5561. return 0; // error
  5562. }
  5563. else if ( *pW == '"' )
  5564. {
  5565. pM = (CInetInfoMap*)pMapper->Alloc( sizeof(CInetInfoMap) );
  5566. if ( !pM )
  5567. {
  5568. return 0;
  5569. }
  5570. pM->iType = ITYPE_PARAM_LIT_STRING;
  5571. if ( !(pM->pName = (LPSTR)pMapper->Alloc( dwLenTok - 1 )) )
  5572. {
  5573. return 0;
  5574. }
  5575. memcpy( pM->pName, pW + 1, dwLenTok - 2 );
  5576. pM->pName[ dwLenTok -2 ] ='\0';
  5577. add_map:
  5578. if ( !AddInfoMap( pM ) )
  5579. {
  5580. pMapper->SetRequestStatus( HTR_OUT_OF_RESOURCE );
  5581. return 0;
  5582. }
  5583. }
  5584. else
  5585. {
  5586. CInetInfoMap *pM;
  5587. if ( pMapper->Map( pW, dwLenTok, &pM ) )
  5588. {
  5589. if ( !AddInfoMap( pM ) )
  5590. {
  5591. pMapper->SetRequestStatus( HTR_OUT_OF_RESOURCE );
  5592. return 0;
  5593. }
  5594. }
  5595. else
  5596. {
  5597. return 0; // error
  5598. }
  5599. }
  5600. if ( c=='%' )
  5601. {
  5602. break;
  5603. }
  5604. }
  5605. return dwW - dwL;
  5606. }
  5607. /////////////////// Request
  5608. // adjust the IF status at the nested IF level
  5609. void
  5610. Adjust(
  5611. int *piIsSkip,
  5612. int iIf )
  5613. {
  5614. if ( iIf )
  5615. {
  5616. *piIsSkip |= HSS_SKIP_IF;
  5617. }
  5618. else
  5619. {
  5620. *piIsSkip &= ~HSS_SKIP_IF;
  5621. }
  5622. }
  5623. //
  5624. // Extensible buffer class
  5625. //
  5626. CExtBuff::CExtBuff(
  5627. VOID )
  5628. {
  5629. m_pB = NULL;
  5630. m_cCurrent = m_cAlloc = 0;
  5631. }
  5632. CExtBuff::~CExtBuff(
  5633. VOID )
  5634. {
  5635. if ( m_pB )
  5636. {
  5637. delete [] m_pB;
  5638. }
  5639. }
  5640. void
  5641. CExtBuff::Reset(
  5642. VOID )
  5643. /*++
  5644. Routine Description:
  5645. Reset a buffer to an empty state
  5646. Arguments:
  5647. None
  5648. Returns:
  5649. VOID
  5650. --*/
  5651. {
  5652. if ( m_pB != NULL )
  5653. {
  5654. delete [] m_pB;
  5655. }
  5656. m_pB = NULL;
  5657. m_cCurrent = m_cAlloc = 0;
  5658. }
  5659. BOOL
  5660. CExtBuff::Extend(
  5661. UINT cReq )
  5662. /*++
  5663. Routine Description:
  5664. Insure buffer at least wide enough for additional
  5665. specified # of bytes
  5666. Arguments:
  5667. cReq - # of characters to add to current buffer length
  5668. Returns:
  5669. TRUE if success, FALSE if failure
  5670. --*/
  5671. {
  5672. BOOL fSt = TRUE;
  5673. if ( m_cAlloc - m_cCurrent < cReq )
  5674. {
  5675. UINT cAlloc = m_cAlloc + EXTBUFF_INCALLOC;
  5676. if ( cAlloc < m_cCurrent + cReq )
  5677. {
  5678. cAlloc = ((cAlloc + cReq + EXTBUFF_INCALLOC)/EXTBUFF_INCALLOC)
  5679. * EXTBUFF_INCALLOC;
  5680. }
  5681. LPBYTE pN = new BYTE[cAlloc];
  5682. if ( pN != NULL )
  5683. {
  5684. if ( m_pB != NULL )
  5685. {
  5686. memcpy( pN, m_pB, m_cCurrent );
  5687. delete [] m_pB;
  5688. }
  5689. m_pB = pN;
  5690. m_cAlloc = cAlloc;
  5691. }
  5692. else
  5693. {
  5694. fSt = FALSE;
  5695. }
  5696. }
  5697. return fSt;
  5698. }
  5699. BOOL
  5700. CExtBuff::CopyBuff(
  5701. LPBYTE pB,
  5702. UINT cB )
  5703. /*++
  5704. Routine Description:
  5705. append bytes at end of buffer
  5706. Arguments:
  5707. pB - pointer to origine bytes
  5708. cB - count of bytes to copy
  5709. Returns:
  5710. TRUE if success, FALSE if failure
  5711. --*/
  5712. {
  5713. if ( !cB )
  5714. {
  5715. return TRUE;
  5716. }
  5717. if ( Extend( cB ) )
  5718. {
  5719. memcpy( m_pB + m_cCurrent, pB, cB );
  5720. m_cCurrent += cB;
  5721. return TRUE;
  5722. }
  5723. return FALSE;
  5724. }
  5725. //
  5726. // Map HTTP status numeric code to ASCII status
  5727. //
  5728. CStatusStringAndCode g_aStatus[] = {
  5729. { HT_OK, IDS_HTRESP_OKANS },
  5730. { HT_REDIRECT, IDS_HTRESP_REDIRECT },
  5731. { HT_SERVER_ERROR, IDS_HTRESP_SERVER_ERROR },
  5732. { HT_BAD_GATEWAY, IDS_HTRESP_BAD_GATEWAY },
  5733. } ;
  5734. //
  5735. // list of recognized verbs
  5736. //
  5737. CInetInfoVerbMap g_aIVerbMap[] = {
  5738. { "AddDenyIpAccess", &CInetInfoRequest::AddDenyIPAccess },
  5739. { "DelDenyIpAccess", &CInetInfoRequest::DeleteDenyIPAccess },
  5740. { "PosDenyIpAccess", &CInetInfoRequest::PositionDenyIPAccess },
  5741. { "SetDefaultIpAccessToDeny", &CInetInfoRequest::DefaultIsDenyIPAccess },
  5742. { "AddGrantIpAccess", &CInetInfoRequest::AddGrantIPAccess },
  5743. { "DelGrantIpAccess", &CInetInfoRequest::DeleteGrantIPAccess },
  5744. { "PosGrantIpAccess", &CInetInfoRequest::PositionGrantIPAccess },
  5745. { "SetDefaultIpAccessToGrant", &CInetInfoRequest::DefaultIsGrantIPAccess },
  5746. { "AddVirtDir", &CInetInfoRequest::AddVirtDir },
  5747. { "DelVirtDir", &CInetInfoRequest::DeleteVirtDir },
  5748. { "PosVirtDir", &CInetInfoRequest::PositionVirtDir },
  5749. { "ChangePassword", &CInetInfoRequest::ChangePassword },
  5750. { "GetUserFlags", &CInetInfoRequest::GetUserFlags },
  5751. { "SetHttpStatus", &CInetInfoRequest::SetHttpStatus },
  5752. { "Update", &CInetInfoRequest::Update },
  5753. { "Clear", &CInetInfoRequest::Clear },
  5754. { "DisconnectUser", &CInetInfoRequest::DisconnectUser },
  5755. { "DisconnectAll", &CInetInfoRequest::DisconnectAll },
  5756. { "GetStatus", &CInetInfoRequest::GetStatus },
  5757. { "ValidateDir", &CInetInfoRequest::ValidateDir },
  5758. { "CreateDir", &CInetInfoRequest::CreateDir },
  5759. { "GenerateDirList", &CInetInfoRequest::GenerateDirList },
  5760. { "CheckForVirtDir", &CInetInfoRequest::CheckForVirtDir },
  5761. { "AliasVirtDir", &CInetInfoRequest::AliasVirtDir },
  5762. } ;
  5763. CInetInfoRequest::CInetInfoRequest(
  5764. EXTENSION_CONTROL_BLOCK*p_ECB,
  5765. CInetInfoConfigInfoMapper* pMapper,
  5766. LPSTR pScr,
  5767. LPSTR pParam )
  5768. {
  5769. m_pECB = p_ECB;
  5770. m_pMapper = pMapper;
  5771. m_pScr = pScr;
  5772. m_pParam = pParam;
  5773. m_pData = NULL;
  5774. m_dwDataLen = 0;
  5775. m_pDataRaw = NULL;
  5776. m_dwDataRawLen = 0;
  5777. m_dwHTTPStatus = HT_OK;
  5778. }
  5779. CInetInfoRequest::~CInetInfoRequest(
  5780. VOID )
  5781. {
  5782. if ( m_pData != NULL )
  5783. {
  5784. delete [] m_pData;
  5785. }
  5786. if( m_pDataRaw != NULL )
  5787. {
  5788. delete [] m_pDataRaw;
  5789. }
  5790. }
  5791. BOOL
  5792. CInetInfoRequest::DoVerb(
  5793. CVerbContext *pC )
  5794. /*++
  5795. Routine Description:
  5796. Invoke an already parsed verb
  5797. Arguments:
  5798. pC - pointer to parsed verb
  5799. Returns:
  5800. TRUE if success, FALSE if failure
  5801. --*/
  5802. {
  5803. m_pVerbContext = pC;
  5804. // find verb, call it
  5805. UINT iH;
  5806. for ( iH = 0 ; iH < sizeof(g_aIVerbMap)/sizeof(CInetInfoVerbMap) ; ++iH )
  5807. {
  5808. if ( !strcmp( g_aIVerbMap[iH].pszName, pC->GetVerbName() ) )
  5809. {
  5810. break;
  5811. }
  5812. }
  5813. if ( iH == sizeof(g_aIVerbMap)/sizeof(CInetInfoVerbMap) )
  5814. {
  5815. return FALSE;
  5816. }
  5817. return (this->*g_aIVerbMap[iH].pHandler)();
  5818. }
  5819. BOOL
  5820. InlineFromTransparent(
  5821. LPBYTE pData,
  5822. DWORD *pdwDataLen,
  5823. BOOL fFilterEscPlus
  5824. )
  5825. /*++
  5826. Routine Description:
  5827. Decode inline a buffer from HTTP character transparency
  5828. Arguments:
  5829. pData - array of characters to decode
  5830. pdwDataLen - # of characters in buffer, updated on output
  5831. fFilterEscPlus - TRUE if "%+" is to be decoded to "+"
  5832. Returns:
  5833. TRUE if success, FALSE if failure
  5834. --*/
  5835. {
  5836. DWORD dwDataLen, dwWas;
  5837. LPBYTE pT, pScan, pWas ;
  5838. int ch;
  5839. dwWas = *pdwDataLen;
  5840. pWas = pData;
  5841. for ( dwDataLen = dwWas, pScan = pWas ;
  5842. dwDataLen-- ; )
  5843. {
  5844. switch ( ch = *pScan++ )
  5845. {
  5846. case '%':
  5847. if ( dwDataLen )
  5848. {
  5849. if ( !fFilterEscPlus && pScan[0] == '%' )
  5850. {
  5851. --dwWas;
  5852. ++pScan;
  5853. --dwDataLen;
  5854. *pData++ = '%';
  5855. }
  5856. else if ( pScan[0] == '+' )
  5857. {
  5858. if ( fFilterEscPlus )
  5859. {
  5860. --dwWas;
  5861. }
  5862. else
  5863. {
  5864. *pData++ = '%';
  5865. }
  5866. *pData++ = '+';
  5867. ++pScan;
  5868. --dwDataLen;
  5869. }
  5870. else if ( !fFilterEscPlus && dwDataLen >= 2 )
  5871. {
  5872. *pData++ = (HexCharToUINT( pScan[0] )<<4)
  5873. + HexCharToUINT( pScan[1] );
  5874. dwWas -= 2;
  5875. pScan += 2;
  5876. dwDataLen -= 2;
  5877. }
  5878. else
  5879. {
  5880. *pData++ = '%';
  5881. }
  5882. }
  5883. else
  5884. {
  5885. *pData++ = '%';
  5886. }
  5887. break;
  5888. case '+':
  5889. if ( !fFilterEscPlus )
  5890. {
  5891. *pData++ = ' ';
  5892. break;
  5893. }
  5894. // fall-through
  5895. default:
  5896. *pData ++ = (char)ch;
  5897. }
  5898. }
  5899. *pdwDataLen = dwWas;
  5900. return TRUE;
  5901. }
  5902. BOOL
  5903. CInetInfoRequest::Init(
  5904. LPSTR pMsg,
  5905. int cMsg )
  5906. /*++
  5907. Routine Description:
  5908. Initialize a HTMLA request from the associated ISAPI object
  5909. Arguments:
  5910. pMsg - message body. If NULL, uses the associated ISAPI
  5911. structure to retrieve message body
  5912. cMsg - message body length if pMsg is non NULL
  5913. Returns:
  5914. TRUE if success, FALSE if failure
  5915. --*/
  5916. {
  5917. BOOL fSt = TRUE;
  5918. BOOL fDoTrp = TRUE;
  5919. int cTotal;
  5920. if ( pMsg == NULL )
  5921. {
  5922. cMsg = m_pECB->cbAvailable;
  5923. cTotal = m_pECB->cbTotalBytes;
  5924. // work-around bug in IIS
  5925. if ( cMsg > cTotal )
  5926. {
  5927. cMsg = cTotal;
  5928. }
  5929. pMsg = (LPSTR)m_pECB->lpbData;
  5930. }
  5931. else
  5932. {
  5933. cTotal = cMsg;
  5934. fDoTrp = FALSE;
  5935. }
  5936. // get request body
  5937. m_pData = new char[cTotal + 1];
  5938. if ( m_pData == NULL )
  5939. {
  5940. return FALSE;
  5941. }
  5942. if ( (m_dwDataLen = cMsg) )
  5943. {
  5944. memcpy( m_pData, pMsg, cMsg );
  5945. }
  5946. if ( cMsg < cTotal )
  5947. {
  5948. DWORD dwRead = cTotal - cMsg;
  5949. if ( m_pECB->ReadClient( (HCONN)m_pECB->ConnID, m_pData + cMsg,
  5950. &dwRead ) )
  5951. {
  5952. m_dwDataLen += dwRead;
  5953. }
  5954. else
  5955. {
  5956. fSt = FALSE;
  5957. }
  5958. }
  5959. // Get the raw version of the entity data
  5960. // Bug NT-3643652
  5961. m_dwDataRawLen = m_dwDataLen;
  5962. m_pDataRaw = new char[m_dwDataRawLen + 1];
  5963. if( m_pDataRaw == NULL )
  5964. {
  5965. return FALSE;
  5966. }
  5967. memcpy( m_pDataRaw, m_pData, m_dwDataRawLen );
  5968. m_pDataRaw[m_dwDataRawLen] = '\0';
  5969. // Generate "Expires" header
  5970. m_pHeader = ALWAYS_EXPIRE;
  5971. // retrieve remote addr
  5972. char achAddr[64];
  5973. DWORD dwAddr = sizeof( achAddr );
  5974. if ( g_fFakeServer
  5975. || !m_pECB->GetServerVariable( (HCONN)m_pECB->ConnID,
  5976. "REMOTE_ADDR",
  5977. achAddr,
  5978. &dwAddr ) )
  5979. {
  5980. achAddr[0] = '\0';
  5981. }
  5982. GetMapper()->SetRemoteAddr( achAddr );
  5983. // set host name
  5984. LPVOID *ppV;
  5985. LPSTR pS;
  5986. if ( GetMapper()->HostName( (LPVOID*)&ppV ) )
  5987. {
  5988. pS = *(LPSTR*)ppV;
  5989. if ( g_pszDefaultHostName != NULL )
  5990. {
  5991. strcpy( pS, g_pszDefaultHostName );
  5992. }
  5993. else
  5994. {
  5995. DWORD dwL = MAX_DOMAIN_LENGTH;
  5996. if ( m_pECB->GetServerVariable( (HCONN)m_pECB->ConnID,
  5997. "SERVER_NAME", pS, &dwL ) == FALSE )
  5998. {
  5999. *pS = '\0';
  6000. }
  6001. }
  6002. }
  6003. // retrieve HTTP server version
  6004. if ( g_achW3Version[0] == '\0' )
  6005. {
  6006. DWORD dwL = sizeof(g_achW3Version);
  6007. if ( m_pECB->GetServerVariable( (HCONN)m_pECB->ConnID,
  6008. "SERVER_SOFTWARE", g_achW3Version, &dwL ) == FALSE )
  6009. {
  6010. g_achW3Version[0] = '\0';
  6011. }
  6012. }
  6013. if ( fDoTrp )
  6014. {
  6015. // Handle request body for transparency
  6016. InlineFromTransparent( (LPBYTE)m_pData, &m_dwDataLen, FALSE );
  6017. m_pData[m_dwDataLen] = '\0';
  6018. }
  6019. // Handle query string for transparency
  6020. DWORD dwLQ = lstrlen( m_pParam );
  6021. InlineFromTransparent( (LPBYTE)m_pParam, &dwLQ, !fDoTrp );
  6022. if ( m_pParam[dwLQ] != '\0' )
  6023. {
  6024. m_pParam[dwLQ] = '\0';
  6025. }
  6026. return fSt;
  6027. }
  6028. LPSTR
  6029. CInetInfoRequest::HTTPStatusStringFromCode(
  6030. VOID )
  6031. {
  6032. for ( int x = 0 ; x < sizeof(g_aStatus)/sizeof(CStatusStringAndCode) ;
  6033. ++x )
  6034. {
  6035. if ( g_aStatus[x].dwStatus == m_dwHTTPStatus )
  6036. {
  6037. return g_aStatus[x].achStatus;
  6038. }
  6039. }
  6040. return "";
  6041. }
  6042. DWORD
  6043. CInetInfoRequest::Done(
  6044. VOID )
  6045. /*++
  6046. Routine Description:
  6047. Send result from HTMLA request to the associated ISAPI object
  6048. Arguments:
  6049. None, uses internal m_dwHTTPStatus & message buffer
  6050. Returns:
  6051. ISAPI status, to be returned by the ExtensionProc
  6052. --*/
  6053. {
  6054. DWORD dwLen = 0;
  6055. DWORD dwS = HSE_STATUS_SUCCESS;
  6056. char achStatus[80];
  6057. if ( g_fFakeServer )
  6058. {
  6059. return FALSE;
  6060. }
  6061. switch ( m_dwHTTPStatus )
  6062. {
  6063. case HT_REPROCESS:
  6064. dwS = HSE_REPROCESS;
  6065. break;
  6066. case HT_REDIRECT:
  6067. //dwLen = m_eb.GetLen();
  6068. if ( !m_pECB->ServerSupportFunction( m_pECB->ConnID,
  6069. HSE_REQ_SEND_URL_REDIRECT_RESP,
  6070. m_eb.GetPtr(),
  6071. 0,
  6072. NULL ) )
  6073. {
  6074. dwS = HSE_STATUS_ERROR;
  6075. }
  6076. break;
  6077. case HT_REDIRECTH:
  6078. if ( !m_pECB->ServerSupportFunction( m_pECB->ConnID,
  6079. HSE_REQ_SEND_URL_REDIRECT_RESP,
  6080. m_eb.GetPtr(),
  6081. 0,
  6082. NULL ) )
  6083. {
  6084. dwS = HSE_STATUS_ERROR;
  6085. }
  6086. break;
  6087. case HT_DENIED:
  6088. #if defined(GENERATE_AUTH_HEADERS)
  6089. g_AuthReqs.Lock();
  6090. LPSTR pszAuthReqs = g_AuthReqs.GetAuthenticationListHeader();
  6091. if ( pszAuthReqs == NULL )
  6092. {
  6093. dwLen = 0;
  6094. }
  6095. else
  6096. {
  6097. dwLen = lstrlen( pszAuthReqs );
  6098. }
  6099. if ( !m_pECB->ServerSupportFunction( m_pECB->ConnID,
  6100. HSE_REQ_SEND_RESPONSE_HEADER,
  6101. g_achAccessDenied,
  6102. &dwLen,
  6103. (LPDWORD)pszAuthReqs ) )
  6104. {
  6105. dwS = HSE_STATUS_ERROR;
  6106. }
  6107. g_AuthReqs.UnLock();
  6108. break;
  6109. #else
  6110. dwLen = strlen(g_achAccessDeniedBody);
  6111. if ( !m_pECB->ServerSupportFunction( m_pECB->ConnID,
  6112. HSE_REQ_SEND_RESPONSE_HEADER,
  6113. g_achAccessDenied,
  6114. &dwLen,
  6115. (LPDWORD)g_achAccessDeniedBody ) )
  6116. {
  6117. dwS = HSE_STATUS_ERROR;
  6118. }
  6119. break;
  6120. #endif
  6121. case HT_NOT_FOUND:
  6122. dwLen = lstrlen( g_achNotFoundBody );
  6123. if ( !m_pECB->ServerSupportFunction( m_pECB->ConnID,
  6124. HSE_REQ_SEND_RESPONSE_HEADER,
  6125. g_achNotFound,
  6126. &dwLen,
  6127. (LPDWORD) g_achNotFoundBody ) )
  6128. {
  6129. dwS = HSE_STATUS_ERROR;
  6130. }
  6131. break;
  6132. default:
  6133. HSE_SEND_HEADER_EX_INFO HSHEI;
  6134. memset( &HSHEI, 0, sizeof( HSHEI ) );
  6135. wsprintf( achStatus, "%d %s", m_dwHTTPStatus,
  6136. HTTPStatusStringFromCode() );
  6137. HSHEI.pszStatus = achStatus;
  6138. HSHEI.cchStatus = 0;
  6139. if ( m_dwHTTPStatus != HT_OK )
  6140. {
  6141. m_eb.Reset();
  6142. }
  6143. #if defined( _ENABLE_KEEP_ALIVE )
  6144. LPSTR pNewH = new char[ lstrlen( m_pHeader ) + 128 ];
  6145. if ( pNewH != NULL )
  6146. {
  6147. BOOL fKeep = FALSE;
  6148. m_pECB->ServerSupportFunction( m_pECB->ConnID,
  6149. HSE_REQ_IS_KEEP_CONN,
  6150. &fKeep,
  6151. 0,
  6152. NULL );
  6153. strcpy( pNewH, m_pHeader );
  6154. wsprintf( pNewH + lstrlen(pNewH) - 2,
  6155. "%sContent-Length: %lu\r\n\r\n",
  6156. fKeep ? "Connection: keep-alive\r\n" : "",
  6157. m_eb.GetLen() );
  6158. dwLen = lstrlen( pNewH );
  6159. HSHEI.pszHeader = pNewH;
  6160. HSHEI.cchHeader = 0;
  6161. HSHEI.fKeepConn = fKeep;
  6162. if ( m_pECB->ServerSupportFunction( m_pECB->ConnID,
  6163. HSE_REQ_SEND_RESPONSE_HEADER_EX,
  6164. (LPVOID) &HSHEI,
  6165. NULL,
  6166. NULL ) )
  6167. {
  6168. dwS = fKeep
  6169. ? HSE_STATUS_SUCCESS_AND_KEEP_CONN
  6170. : HSE_STATUS_SUCCESS ;
  6171. }
  6172. else
  6173. {
  6174. dwS = HSE_STATUS_ERROR;
  6175. }
  6176. delete [] pNewH;
  6177. }
  6178. else
  6179. #endif
  6180. {
  6181. dwLen = lstrlen( m_pHeader );
  6182. HSHEI.pszHeader = m_pHeader;
  6183. HSHEI.cchHeader = 0;
  6184. if ( !m_pECB->ServerSupportFunction( m_pECB->ConnID,
  6185. HSE_REQ_SEND_RESPONSE_HEADER_EX,
  6186. (LPVOID) &HSHEI,
  6187. NULL,
  6188. NULL ) )
  6189. {
  6190. dwS = HSE_STATUS_ERROR;
  6191. }
  6192. }
  6193. if ( dwS != HSE_STATUS_ERROR )
  6194. {
  6195. dwLen = m_eb.GetLen();
  6196. //
  6197. // If WriteClient fails, nothing useful to do at this point,
  6198. // so ignore return value
  6199. //
  6200. m_pECB->WriteClient( m_pECB->ConnID,
  6201. m_eb.GetPtr(),
  6202. &dwLen,
  6203. 0 );
  6204. }
  6205. }
  6206. return dwS;
  6207. }
  6208. LPSTR
  6209. CInetInfoRequest::GetVarAsString(
  6210. DWORD dwI,
  6211. BOOL *pfF )
  6212. /*++
  6213. Routine Description:
  6214. Access the specified entry ( 0-based ) in the parameter list
  6215. of the associated verb context and returns the result as a string
  6216. Arguments:
  6217. dwI - index in the array of parameters ( 0-based )
  6218. pfF - updated with TRUE if buffer to be freed after usage
  6219. ( using delete[] )
  6220. Returns:
  6221. pointer to string representation of parameter or NULL if error
  6222. --*/
  6223. {
  6224. LPSTR pResult;
  6225. DWORD dwResLen;
  6226. if ( m_pVerbContext->GetNbInfoMap() > dwI )
  6227. {
  6228. CInetInfoMap* pM = m_pVerbContext->GetInfoMap( dwI );
  6229. if ( pM->iType == ITYPE_PARAM_LIT_STRING )
  6230. {
  6231. *pfF = FALSE;
  6232. return pM->pName;
  6233. }
  6234. else if ( GetMapper()->GetString( pM, &pResult, &dwResLen, pfF ) )
  6235. {
  6236. return pResult;
  6237. }
  6238. }
  6239. return NULL;
  6240. }
  6241. //
  6242. // HTMLA Verbs handling. verb is already parsed
  6243. //
  6244. // These functions are basically wrappers around functions in
  6245. // CInetInfoConfigInfoMapper
  6246. //
  6247. // The "HTMLA Arguments:" will indicates arguments for this function
  6248. // in a HTMLA script.
  6249. //
  6250. BOOL
  6251. CInetInfoRequest::AddDenyIPAccess(
  6252. VOID )
  6253. /*++
  6254. Routine Description:
  6255. Add an empty entry in the deny access IP list
  6256. This entry is to be set later by the HTMLA script
  6257. ( the relevant variables will point to the newly created entry )
  6258. Arguments:
  6259. None
  6260. HTMLA Arguments:
  6261. None
  6262. Returns:
  6263. TRUE if success, otherwise FALSE
  6264. updates reqstatus
  6265. --*/
  6266. {
  6267. return GetMapper()->AddIPAccess( TRUE );
  6268. }
  6269. BOOL
  6270. CInetInfoRequest::DeleteDenyIPAccess(
  6271. )
  6272. /*++
  6273. Routine Description:
  6274. Delete an entry in the deny access IP list
  6275. Arguments:
  6276. None
  6277. HTMLA Arguments:
  6278. access list entry reference
  6279. Returns:
  6280. TRUE if success, otherwise FALSE
  6281. updates reqstatus
  6282. --*/
  6283. {
  6284. LPSTR pV;
  6285. BOOL fF;
  6286. BOOL fSt = FALSE;
  6287. if ( (pV = GetVarAsString( 0, &fF )) != NULL )
  6288. {
  6289. fSt = GetMapper()->DeleteIPAccess( TRUE, pV );
  6290. if ( fF )
  6291. {
  6292. delete [] pV;
  6293. }
  6294. }
  6295. return fSt;
  6296. }
  6297. BOOL
  6298. CInetInfoRequest::PositionDenyIPAccess(
  6299. VOID )
  6300. /*++
  6301. Routine Description:
  6302. Set the iteration counter ( m_iIter ) to point to the entry
  6303. matching the specified reference in the deny access list.
  6304. Arguments:
  6305. None
  6306. HTMLA Arguments:
  6307. access list entry reference
  6308. Returns:
  6309. TRUE if success, otherwise FALSE
  6310. updates reqstatus
  6311. --*/
  6312. {
  6313. LPSTR pV;
  6314. BOOL fF;
  6315. BOOL fSt = FALSE;
  6316. if ( (pV = GetVarAsString( 0, &fF )) != NULL )
  6317. {
  6318. if ( GetMapper()->PositionIPAccess( TRUE, pV ) )
  6319. {
  6320. fSt = Update();
  6321. }
  6322. if ( fF )
  6323. {
  6324. delete [] pV;
  6325. }
  6326. }
  6327. return fSt;
  6328. }
  6329. BOOL
  6330. CInetInfoRequest::DefaultIsDenyIPAccess(
  6331. VOID )
  6332. /*++
  6333. Routine Description:
  6334. Set the default condition to be denied access to the service
  6335. if the client address is not in the grant list
  6336. Arguments:
  6337. None
  6338. HTMLA Arguments:
  6339. None
  6340. Returns:
  6341. TRUE if success, otherwise FALSE
  6342. updates reqstatus
  6343. --*/
  6344. {
  6345. return GetMapper()->SetIPAccessDefault( TRUE );
  6346. }
  6347. BOOL
  6348. CInetInfoRequest::AddGrantIPAccess(
  6349. VOID )
  6350. /*++
  6351. Routine Description:
  6352. Add an empty entry in the grant access IP list
  6353. This entry is to be set later by the HTMLA script
  6354. ( the relevant variables will point to the newly created entry )
  6355. Arguments:
  6356. None
  6357. HTMLA Arguments:
  6358. None
  6359. Returns:
  6360. TRUE if success, otherwise FALSE
  6361. updates reqstatus
  6362. --*/
  6363. {
  6364. return GetMapper()->AddIPAccess( FALSE );
  6365. }
  6366. BOOL
  6367. CInetInfoRequest::DeleteGrantIPAccess(
  6368. VOID )
  6369. /*++
  6370. Routine Description:
  6371. Delete an entry in the grant access IP list
  6372. Arguments:
  6373. None
  6374. HTMLA Arguments:
  6375. access list entry reference
  6376. Returns:
  6377. TRUE if success, otherwise FALSE
  6378. updates reqstatus
  6379. --*/
  6380. {
  6381. LPSTR pV;
  6382. BOOL fF;
  6383. BOOL fSt = FALSE;
  6384. if ( (pV = GetVarAsString( 0, &fF )) != NULL )
  6385. {
  6386. fSt = GetMapper()->DeleteIPAccess( FALSE, pV );
  6387. if ( fF )
  6388. {
  6389. delete [] pV;
  6390. }
  6391. }
  6392. return fSt;
  6393. }
  6394. BOOL
  6395. CInetInfoRequest::PositionGrantIPAccess(
  6396. VOID )
  6397. /*++
  6398. Routine Description:
  6399. Set the iteration counter ( m_iIter ) to point to the entry
  6400. matching the specified reference in the grant access list.
  6401. Arguments:
  6402. None
  6403. HTMLA Arguments:
  6404. access list entry reference
  6405. Returns:
  6406. TRUE if success, otherwise FALSE
  6407. updates reqstatus
  6408. --*/
  6409. {
  6410. LPSTR pV;
  6411. BOOL fF;
  6412. BOOL fSt = FALSE;
  6413. if ( (pV = GetVarAsString( 0, &fF )) != NULL )
  6414. {
  6415. if ( GetMapper()->PositionIPAccess( FALSE, pV ) )
  6416. {
  6417. fSt = Update();
  6418. }
  6419. if ( fF )
  6420. {
  6421. delete [] pV;
  6422. }
  6423. }
  6424. return fSt;
  6425. }
  6426. BOOL
  6427. CInetInfoRequest::DefaultIsGrantIPAccess(
  6428. VOID )
  6429. /*++
  6430. Routine Description:
  6431. Set the default condition to be granted access to the service
  6432. if the client address is not in the deny list
  6433. Arguments:
  6434. None
  6435. HTMLA Arguments:
  6436. None
  6437. Returns:
  6438. TRUE if success, otherwise FALSE
  6439. updates reqstatus
  6440. --*/
  6441. {
  6442. return GetMapper()->SetIPAccessDefault( FALSE );
  6443. }
  6444. BOOL
  6445. CInetInfoRequest::AddVirtDir(
  6446. VOID )
  6447. /*++
  6448. Routine Description:
  6449. Add an empty entry in the virtual root list
  6450. This entry is to be set later by the HTMLA script
  6451. ( the relevant variables will point to the newly created entry )
  6452. Arguments:
  6453. None
  6454. HTMLA Arguments:
  6455. None
  6456. Returns:
  6457. TRUE if success, otherwise FALSE
  6458. updates reqstatus
  6459. --*/
  6460. {
  6461. return GetMapper()->AddVirtDir();
  6462. }
  6463. /* INTRINSA suppress=null_pointers, uninitialized */
  6464. BOOL
  6465. CInetInfoRequest::DeleteVirtDir(
  6466. VOID )
  6467. /*++
  6468. Routine Description:
  6469. Delete an entry in the grant access IP list
  6470. Arguments:
  6471. None
  6472. HTMLA Arguments:
  6473. virtual root list entry reference
  6474. Returns:
  6475. TRUE if success, otherwise FALSE
  6476. updates reqstatus
  6477. --*/
  6478. {
  6479. LPSTR pV;
  6480. BOOL fF;
  6481. BOOL fSt = FALSE;
  6482. if ( (pV = GetVarAsString( 0, &fF )) != NULL )
  6483. {
  6484. fSt = GetMapper()->DeleteVirtDir( pV );
  6485. if ( fF )
  6486. {
  6487. delete [] pV;
  6488. }
  6489. }
  6490. return fSt;
  6491. }
  6492. BOOL
  6493. CInetInfoRequest::PositionVirtDir(
  6494. VOID )
  6495. /*++
  6496. Routine Description:
  6497. Set the iteration counter ( m_iIter ) to point to the entry
  6498. matching the specified reference in the virtual root list.
  6499. Arguments:
  6500. None
  6501. HTMLA Arguments:
  6502. virtual root list entry reference
  6503. Returns:
  6504. TRUE if success, otherwise FALSE
  6505. updates reqstatus
  6506. --*/
  6507. {
  6508. LPSTR pV;
  6509. BOOL fF;
  6510. BOOL fSt = FALSE;
  6511. if ( (pV = GetVarAsString( 0, &fF )) != NULL )
  6512. {
  6513. fSt = GetMapper()->PositionVirtDir( pV );
  6514. if ( fF )
  6515. {
  6516. delete [] pV;
  6517. }
  6518. }
  6519. return fSt;
  6520. }
  6521. LPWSTR
  6522. CInetInfoRequest::AnsiToUnicode(
  6523. LPSTR psz
  6524. )
  6525. /*++
  6526. Routine Description:
  6527. Convert ANSI string to UNICODE
  6528. Storage will be automatically released at end of HTMLA request
  6529. Arguments:
  6530. psz - ANSI string
  6531. Returns:
  6532. pointer to UNICODE string or NULL if failure
  6533. updates reqstatus on failure.
  6534. --*/
  6535. {
  6536. UINT cL = strlen( psz );
  6537. LPWSTR pwsz = (LPWSTR)GetMapper()->Alloc( (cL+1)*sizeof(WCHAR) );
  6538. if ( pwsz && cL )
  6539. {
  6540. if ( !(cL = MultiByteToWideChar( CP_ACP, 0, psz, cL, pwsz, cL )) )
  6541. {
  6542. pwsz = NULL;
  6543. GetMapper()->SetRequestStatus( HTR_BAD_PARAM );
  6544. }
  6545. else
  6546. {
  6547. pwsz[cL] = L'\0';
  6548. }
  6549. }
  6550. return pwsz;
  6551. }
  6552. BOOL
  6553. CInetInfoRequest::GetUserFlags(
  6554. VOID
  6555. )
  6556. /*++
  6557. Routine Description:
  6558. Set the userflag variable with up to date info from GetUserInfo
  6559. Arguments:
  6560. None
  6561. HTMLA arguments:
  6562. UserAccout
  6563. Returns:
  6564. TRUE if success, otherwise FALSE
  6565. updates reqstatus, rpcstatus with return from NetUserChangePassword
  6566. --*/
  6567. {
  6568. LPSTR pUser;
  6569. BOOL fUser = FALSE;
  6570. PUSER_INFO_1 pUI1;
  6571. NET_API_STATUS s;
  6572. if ( (pUser = GetVarAsString( 0, &fUser )) )
  6573. {
  6574. //(pU = strchr( pUser, '\\' )) != NULL
  6575. LPWSTR pwszUser = AnsiToUnicode( pUser );
  6576. if ( pwszUser )
  6577. {
  6578. if ( (s = NetUserGetInfo( NULL, pwszUser, 1, (LPBYTE*)&pUI1)) == 0 )
  6579. {
  6580. GetMapper()->SetUserFlags( pUI1->usri1_flags );
  6581. }
  6582. else
  6583. {
  6584. GetMapper()->SetRequestStatus( HTR_VALIDATION_FAILED );
  6585. }
  6586. GetMapper()->SetRPCStatus( s );
  6587. }
  6588. }
  6589. else
  6590. {
  6591. return FALSE;
  6592. }
  6593. if ( fUser )
  6594. {
  6595. delete [] pUser;
  6596. }
  6597. return TRUE;
  6598. }
  6599. BOOL
  6600. CInetInfoRequest::SetHttpStatus(
  6601. VOID
  6602. )
  6603. /*++
  6604. Routine Description:
  6605. Set the HTTP status for the current request
  6606. Arguments:
  6607. None
  6608. HTMLA arguments:
  6609. Numeric status
  6610. Returns:
  6611. TRUE if success, otherwise FALSE
  6612. --*/
  6613. {
  6614. LPSTR pUser;
  6615. BOOL fUser = FALSE;
  6616. PUSER_INFO_1 pUI1;
  6617. NET_API_STATUS s;
  6618. if ( (pUser = GetVarAsString( 0, &fUser )) )
  6619. {
  6620. SetHTTPStatus( atol(pUser) );
  6621. }
  6622. else
  6623. {
  6624. GetMapper()->SetRequestStatus( HTR_BAD_PARAM );
  6625. return FALSE;
  6626. }
  6627. if ( fUser )
  6628. {
  6629. delete [] pUser;
  6630. }
  6631. return TRUE;
  6632. }
  6633. BOOL
  6634. CInetInfoRequest::ChangePassword(
  6635. VOID
  6636. )
  6637. /*++
  6638. Routine Description:
  6639. Change NT account pwd using user name, old pwd, new pwd
  6640. Arguments:
  6641. None
  6642. HTMLA arguments:
  6643. UserAccout OldPwd NewPwd
  6644. Returns:
  6645. TRUE if success, otherwise FALSE
  6646. updates reqstatus, rpcstatus with return from NetUserChangePassword
  6647. --*/
  6648. {
  6649. LPSTR pDomain;
  6650. LPSTR pUser;
  6651. LPSTR pOld;
  6652. LPSTR pNew;
  6653. LPSTR pTmp;
  6654. LPSTR pSep = NULL;
  6655. LPSTR pU = NULL;
  6656. BOOL fDomain = FALSE;
  6657. BOOL fUser = FALSE;
  6658. BOOL fOld = FALSE;
  6659. BOOL fNew = FALSE;
  6660. BOOL fSt = FALSE;
  6661. BOOL fGotAllParams = FALSE;
  6662. CHAR achDefaultDomain[DNLEN + 1];
  6663. NET_API_STATUS s;
  6664. GetMapper()->SetRPCStatus( 0 );
  6665. pDomain = GetVarAsString( 0, &fDomain );
  6666. pUser = GetVarAsString( 1, &fUser );
  6667. pOld = GetVarAsString( 2, &fOld );
  6668. pNew = GetVarAsString( 3, &fNew );
  6669. //
  6670. // We may have the user and domain in the pUser and pDomain fields or
  6671. // we may get both user and domain in the pUser field, in the form
  6672. // DOMAIN\USERNAME. In either case, try to split the information into
  6673. // two variables, pU and pUser, for domain and user name respectively.
  6674. //
  6675. if ( pUser )
  6676. {
  6677. //
  6678. // Got the domain as separate field
  6679. //
  6680. if ( pDomain && *pDomain )
  6681. {
  6682. pU = pDomain;
  6683. }
  6684. //
  6685. // Got domain\user as single field
  6686. //
  6687. else if ( (pU = (LPSTR)_mbschr( (LPBYTE)pUser, '\\' )) != NULL )
  6688. {
  6689. pSep = pU;
  6690. pU[0] = '\0';
  6691. pTmp = pU + 1;
  6692. pU = pUser;
  6693. pUser = pTmp;
  6694. }
  6695. }
  6696. //
  6697. // If we still don't have a logon domain, try to retrieve the default
  6698. //
  6699. if (pU == NULL)
  6700. {
  6701. if ( g_pfnGetDefaultDomainName &&
  6702. g_pfnGetDefaultDomainName((LPSTR) &achDefaultDomain, DNLEN) )
  6703. {
  6704. pU = achDefaultDomain;
  6705. }
  6706. }
  6707. if ( pUser != NULL &&
  6708. pU != NULL &&
  6709. pOld != NULL &&
  6710. pNew != NULL
  6711. )
  6712. {
  6713. LPWSTR pwszDomain = pU ? AnsiToUnicode( pU ) : NULL;
  6714. LPWSTR pwszUser = AnsiToUnicode( pUser );
  6715. LPWSTR pwszOld = AnsiToUnicode( pOld );
  6716. LPWSTR pwszNew = AnsiToUnicode( pNew );
  6717. if ( pwszUser && pwszOld && pwszNew )
  6718. {
  6719. fGotAllParams = TRUE;
  6720. if ( (s = NetUserChangePassword( pwszDomain,
  6721. pwszUser,
  6722. pwszOld,
  6723. pwszNew )) != 0 )
  6724. {
  6725. GetMapper()->SetRPCStatus( s );
  6726. GetMapper()->SetRequestStatus( HTR_VALIDATION_FAILED );
  6727. }
  6728. }
  6729. if ( pSep )
  6730. {
  6731. *pSep = '\\';
  6732. }
  6733. }
  6734. //
  6735. // If we didn't get enough parameters, eg no user name or couldn't convert some of them into
  6736. // the correct format, set error status. We could set more specific error code, eg
  6737. // ERROR_INVALID_PASSWORD, ERROR_BAD_USERNAME, but this would be misleading if more than
  6738. // one of these error conditions happens, so just return generic "bad parameter"
  6739. //
  6740. if (!fGotAllParams)
  6741. {
  6742. GetMapper()->SetRPCStatus( ERROR_INVALID_PARAMETER );
  6743. GetMapper()->SetRequestStatus( HTR_BAD_PARAM );
  6744. }
  6745. if ( fDomain )
  6746. {
  6747. delete [] pDomain;
  6748. }
  6749. if ( fUser )
  6750. {
  6751. delete [] pUser;
  6752. }
  6753. if ( fOld )
  6754. {
  6755. delete [] pOld;
  6756. }
  6757. if ( fNew )
  6758. {
  6759. delete [] pNew;
  6760. }
  6761. return fSt;
  6762. }
  6763. BOOL
  6764. CInetInfoRequest::DisconnectUser(
  6765. VOID )
  6766. /*++
  6767. Routine Description:
  6768. Disconnect the user specified by a numeric ID from the service
  6769. mapped to this request.
  6770. This ID is an opaque numeric value returned by the server
  6771. in one of the RPC structure
  6772. Arguments:
  6773. None
  6774. HTMLA Arguments:
  6775. User numeric ID
  6776. Returns:
  6777. TRUE if success, otherwise FALSE
  6778. updates reqstatus
  6779. --*/
  6780. {
  6781. BOOL fSt = FALSE;
  6782. LPSTR pV;
  6783. BOOL fF;
  6784. if ( (pV = GetVarAsString( 0, &fF )) != NULL )
  6785. {
  6786. fSt = GetMapper()->DisconnectUser( pV );
  6787. if ( fF )
  6788. {
  6789. delete [] pV;
  6790. }
  6791. }
  6792. return fSt;
  6793. }
  6794. BOOL
  6795. CInetInfoRequest::DisconnectAll(
  6796. VOID )
  6797. /*++
  6798. Routine Description:
  6799. Disconnect all users from the service mapped to this request
  6800. Arguments:
  6801. None
  6802. HTMLA Arguments:
  6803. None
  6804. Returns:
  6805. TRUE if success, otherwise FALSE
  6806. updates reqstatus
  6807. --*/
  6808. {
  6809. return GetMapper()->DisconnectAll();
  6810. }
  6811. BOOL
  6812. CInetInfoRequest::GetStatus(
  6813. VOID )
  6814. /*++
  6815. Routine Description:
  6816. Updates the HTMLA variables exposing the status of IP services
  6817. ( HTTP, FTP, Gopher ) so that they can be accessed in the HTMLA
  6818. script.
  6819. Arguments:
  6820. None
  6821. HTMLA Arguments:
  6822. None
  6823. Returns:
  6824. TRUE if success, otherwise FALSE
  6825. updates reqstatus
  6826. --*/
  6827. {
  6828. return GetMapper()->GetStatus();
  6829. }
  6830. BOOL
  6831. CInetInfoRequest::ValidateDir(
  6832. VOID )
  6833. /*++
  6834. Routine Description:
  6835. Validate a directory path ( checks for existence )
  6836. Arguments:
  6837. None
  6838. HTMLA Arguments:
  6839. Directory path to validate
  6840. Returns:
  6841. TRUE if success, otherwise FALSE
  6842. updates reqstatus
  6843. --*/
  6844. {
  6845. BOOL fSt = FALSE;
  6846. LPSTR pV;
  6847. BOOL fF;
  6848. if ( (pV = GetVarAsString( 0, &fF )) != NULL )
  6849. {
  6850. fSt = GetMapper()->ValidateDir( pV );
  6851. if ( fF )
  6852. {
  6853. delete [] pV;
  6854. }
  6855. }
  6856. return fSt;
  6857. }
  6858. BOOL
  6859. CInetInfoRequest::CreateDir(
  6860. VOID )
  6861. /*++
  6862. Routine Description:
  6863. Validate a directory path ( checks for existence )
  6864. Arguments:
  6865. None
  6866. HTMLA Arguments:
  6867. - Directory path where to create directory
  6868. - Directory name to create ( w/o '\' )
  6869. Returns:
  6870. TRUE if success, otherwise FALSE
  6871. updates reqstatus
  6872. --*/
  6873. {
  6874. BOOL fSt = FALSE;
  6875. LPSTR pV1, pV2;
  6876. BOOL fF1 = FALSE, fF2 = FALSE;
  6877. pV1 = GetVarAsString( 0, &fF1 );
  6878. pV2 = GetVarAsString( 1, &fF2 );
  6879. if ( pV1 != NULL && pV2 != NULL )
  6880. {
  6881. fSt = GetMapper()->CreateDir( pV1, pV2 );
  6882. }
  6883. if ( fF1 )
  6884. {
  6885. delete [] pV1;
  6886. }
  6887. if ( fF2 )
  6888. {
  6889. delete [] pV2;
  6890. }
  6891. return fSt;
  6892. }
  6893. BOOL
  6894. CInetInfoRequest::CheckForVirtDir(
  6895. VOID )
  6896. /*++
  6897. Routine Description:
  6898. Handle the _VIRT_DIR_REQ_CHECK command.
  6899. see HandleVirtDirRequest() below
  6900. Arguments:
  6901. None
  6902. Returns:
  6903. TRUE on success, FALSE on failure
  6904. updates reqstatus
  6905. --*/
  6906. {
  6907. return HandleVirtDirRequest( _VIRT_DIR_REQ_CHECK );
  6908. }
  6909. BOOL
  6910. CInetInfoRequest::AliasVirtDir(
  6911. VOID )
  6912. /*++
  6913. Routine Description:
  6914. Handle the _VIRT_DIR_REQ_ALIAS command.
  6915. see HandleVirtDirRequest() below
  6916. Arguments:
  6917. None
  6918. Returns:
  6919. TRUE on success, FALSE on failure
  6920. updates reqstatus
  6921. --*/
  6922. {
  6923. return HandleVirtDirRequest( _VIRT_DIR_REQ_ALIAS );
  6924. }
  6925. BOOL
  6926. CInetInfoRequest::HandleVirtDirRequest(
  6927. int iReq )
  6928. /*++
  6929. Routine Description:
  6930. Handle a virtual root command. can be one of :
  6931. _VIRT_DIR_REQ_ALIAS : create an alias for the matching virtual root
  6932. by coalescing all alpha-numeric characters
  6933. from the virtual root physical path
  6934. _VIRT_DIR_REQ_CHECK : check for the existence of the specified
  6935. virtual root, set reqstatus to HTR_DIR_SAME_NAME
  6936. if present
  6937. Arguments:
  6938. iReq : a _VIRT_DIR_REQ_ command
  6939. HTMLA Arguments:
  6940. - Virtual root name ( e.g. "/scripts" )
  6941. - Virtual root IP address or empty string
  6942. Returns:
  6943. TRUE on success, FALSE on failure
  6944. updates reqstatus
  6945. --*/
  6946. {
  6947. BOOL fSt = FALSE;
  6948. LPSTR pV1, pV2;
  6949. BOOL fF1 = FALSE, fF2 = FALSE;
  6950. pV1 = GetVarAsString( 0, &fF1 );
  6951. pV2 = GetVarAsString( 1, &fF2 );
  6952. if ( pV1 != NULL && pV2 != NULL )
  6953. {
  6954. fSt = GetMapper()->HandleVirtDirRequest( pV1, pV2, iReq );
  6955. }
  6956. if ( fF1 )
  6957. {
  6958. delete [] pV1;
  6959. }
  6960. if ( fF2 )
  6961. {
  6962. delete [] pV2;
  6963. }
  6964. return fSt;
  6965. }
  6966. BOOL
  6967. CInetInfoRequest::GenerateDirList(
  6968. VOID )
  6969. /*++
  6970. Routine Description:
  6971. Generate the vairous lists used by the directory browsing capability
  6972. cf. CDriveView::GenerateDirList()
  6973. Arguments:
  6974. None
  6975. HTMLA Arguments:
  6976. Path of the root of the directory structure to browse
  6977. Returns:
  6978. TRUE if success, otherwise FALSE
  6979. updates reqstatus
  6980. --*/
  6981. {
  6982. BOOL fSt = FALSE;
  6983. LPSTR pV;
  6984. BOOL fF;
  6985. if ( (pV = GetVarAsString( 0, &fF )) != NULL )
  6986. {
  6987. fSt = GetMapper()->GenerateDirList( pV );
  6988. if ( fF )
  6989. {
  6990. delete [] pV;
  6991. }
  6992. }
  6993. return fSt;
  6994. }
  6995. BOOL
  6996. CInetInfoRequest::Clear(
  6997. VOID )
  6998. /*++
  6999. Routine Description:
  7000. Clear ( set to 0 ) a numeric HTMLA script variable
  7001. Used to clear variables used in HTML checkboxes, as an
  7002. unchecked box will not be transmitted in the FORM request
  7003. Arguments:
  7004. None
  7005. HTMLA Arguments:
  7006. HTMLA variable name
  7007. Returns:
  7008. TRUE if success, otherwise FALSE
  7009. updates reqstatus
  7010. --*/
  7011. {
  7012. BOOL fSt = TRUE;
  7013. LPSTR pResult;
  7014. DWORD dwResLen;
  7015. LPVOID pV;
  7016. if ( m_pVerbContext->GetNbInfoMap() > 0 )
  7017. {
  7018. CInetInfoMap *pMap = m_pVerbContext->GetInfoMap(0);
  7019. switch ( pMap->iType )
  7020. {
  7021. case ITYPE_DWORD:
  7022. case ITYPE_SHORTDW:
  7023. case ITYPE_BOOL:
  7024. case ITYPE_1K:
  7025. case ITYPE_1M:
  7026. (GetMapper()->*pMap->GetAddr)( (LPVOID*)&pV );
  7027. *(DWORD*)pV = 0;
  7028. (GetMapper()->*pMap->UpdateIndication)();
  7029. break;
  7030. default:
  7031. GetMapper()->SetRequestStatus( HTR_INVALID_VAR_TYPE );
  7032. fSt = FALSE;
  7033. }
  7034. }
  7035. else
  7036. {
  7037. GetMapper()->SetRequestStatus( HTR_BAD_PARAM );
  7038. fSt = FALSE;
  7039. }
  7040. return fSt;
  7041. }
  7042. BOOL
  7043. CInetInfoRequest::Update(
  7044. VOID )
  7045. /*++
  7046. Routine Description:
  7047. Scan the request message body as a FORM request
  7048. updating HTMLA variables
  7049. If parsing successfull, calls the RPC layer to updates
  7050. the Web Server status.
  7051. Arguments:
  7052. None
  7053. HTMLA Arguments:
  7054. None
  7055. Returns:
  7056. TRUE if success, otherwise FALSE
  7057. updates reqstatus
  7058. --*/
  7059. {
  7060. BOOL fSt = TRUE;
  7061. DWORD dwL;
  7062. LPSTR pV = m_pData; // request body
  7063. for ( ; *pV ; )
  7064. {
  7065. while ( isspace((UCHAR)(*pV)) )
  7066. {
  7067. ++pV;
  7068. }
  7069. LPSTR pE = strchr( pV, '=' );
  7070. BOOL fIsLast = FALSE;
  7071. if ( pE != NULL )
  7072. {
  7073. // find end of value
  7074. LPSTR pN = strchr( pE + 1, '&' );
  7075. if ( pN == NULL )
  7076. {
  7077. if ( (pN = strchr( pE + 1, '\r' )) != NULL )
  7078. {
  7079. *pN = '\0';
  7080. }
  7081. if ( (pN = strchr( pE + 1, '\n' )) != NULL )
  7082. {
  7083. *pN = '\0';
  7084. }
  7085. fIsLast = TRUE;
  7086. }
  7087. else
  7088. {
  7089. *pN = '\0';
  7090. }
  7091. //TR_DEBUG( 0, "Update Mapping %s, value %s<p>", pV, pE+1 );
  7092. CInetInfoMap *pMap;
  7093. if ( GetMapper()->Map( (LPBYTE)pV, DIFF(pE-pV), &pMap ) )
  7094. {
  7095. if ( GetMapper()->PutString( pMap, pE + 1 ) == FALSE )
  7096. {
  7097. GetMapper()->SetRequestStatus( HTR_INVALID_FORM_PARAM );
  7098. fSt = FALSE;
  7099. break;
  7100. }
  7101. }
  7102. if ( fIsLast )
  7103. {
  7104. break;
  7105. }
  7106. pV = pN + 1;
  7107. }
  7108. else
  7109. {
  7110. GetMapper()->SetRequestStatus( HTR_INVALID_FORM_PARAM_NAME );
  7111. fSt = FALSE;
  7112. break;
  7113. }
  7114. }
  7115. // if success, call RPC to update server status
  7116. if ( fSt == TRUE )
  7117. {
  7118. PDWORD pdwI;
  7119. if ( GetMapper()->InvalidLogUpdate( (LPVOID*)&pdwI) && *pdwI )
  7120. {
  7121. GetMapper()->SetRequestStatus( HTR_INVALID_FORM_PARAM );
  7122. fSt = FALSE;
  7123. }
  7124. else
  7125. {
  7126. fSt = GetMapper()->Update();
  7127. }
  7128. }
  7129. return fSt;
  7130. }
  7131. ////////////////////// Merger
  7132. CInetInfoMerger::CInetInfoMerger(
  7133. VOID )
  7134. {
  7135. }
  7136. CInetInfoMerger::~CInetInfoMerger(
  7137. VOID )
  7138. {
  7139. }
  7140. BOOL
  7141. CInetInfoMerger::Init(
  7142. VOID )
  7143. {
  7144. return TRUE;
  7145. }
  7146. CInetInfoMap *
  7147. CInetInfoMerger::GetVarMap(
  7148. CInetInfoConfigInfoMapper *pM,
  7149. LPBYTE pVS,
  7150. DWORD dwSize )
  7151. /*++
  7152. Routine Description:
  7153. Retrieve the variable descriptor from variable name and mapper object
  7154. Arguments:
  7155. pM - pointer to mapper object
  7156. pVS - variable name
  7157. dwSize - size of variable name
  7158. Returns:
  7159. Variable descriptor
  7160. --*/
  7161. {
  7162. CInetInfoMap *pMap;
  7163. LPBYTE pName = (LPBYTE)memchr( pVS, '%', dwSize );
  7164. if ( pName != NULL )
  7165. {
  7166. CInetInfoMap *pMap;
  7167. if ( pM->Map( pVS, (DWORD)(pName - pVS), &pMap ) )
  7168. {
  7169. return pMap;
  7170. }
  7171. }
  7172. return NULL;
  7173. }
  7174. LPSTR
  7175. CInetInfoMerger::AllocDup(
  7176. CInetInfoConfigInfoMapper *pM,
  7177. LPBYTE pDup,
  7178. DWORD dwL )
  7179. /*++
  7180. Routine Description:
  7181. Duplicate a memory block using Alloc()
  7182. Arguments:
  7183. pM - mapper object providing the Alloc() function
  7184. pDup - memory block to duplicate
  7185. dwL - length of emory block to duplicate
  7186. Returns:
  7187. Duplicated memory block, zero-terminated, auto-deallocate
  7188. --*/
  7189. {
  7190. LPSTR pD = (LPSTR)pM->Alloc( dwL + 1 );
  7191. if ( pD == NULL )
  7192. {
  7193. return NULL;
  7194. }
  7195. memcpy( pD, pDup, dwL );
  7196. pD[dwL] = '\0';
  7197. return pD;
  7198. }
  7199. BOOL
  7200. CInetInfoMerger::GetToken(
  7201. LPBYTE pVS,
  7202. DWORD dwSize,
  7203. LPBYTE* pStart,
  7204. DWORD* pdwL )
  7205. /*++
  7206. Routine Description:
  7207. Scan for token, returning its length
  7208. Arguments:
  7209. pVS - pointer to memory block to scan
  7210. dwSize - length of memory block to scan
  7211. pStart - updated with pointer to start of token
  7212. pdwL - updated with token length
  7213. Returns:
  7214. TRUE if succes, FALSE if failure
  7215. --*/
  7216. {
  7217. // skip initial spaces
  7218. while ( dwSize && *pVS == ' ' )
  7219. {
  7220. --dwSize;
  7221. ++pVS;
  7222. }
  7223. *pStart = pVS;
  7224. // get length
  7225. LPBYTE pName = (LPBYTE)memchr( pVS, '%', dwSize );
  7226. if ( pName != NULL )
  7227. {
  7228. *pdwL = DIFF(pName - pVS);
  7229. return TRUE;
  7230. }
  7231. return FALSE;
  7232. }
  7233. BOOL
  7234. CInetInfoMerger::Merge(
  7235. CInetInfoRequest* pR )
  7236. /*++
  7237. Routine Description:
  7238. Merge a template ( .htr ) file with variables as exposed in the
  7239. context of the specified HTMLA request.
  7240. This function opens and closes the file for each request, no caching
  7241. is done. The file is mapped in memory for access.
  7242. Arguments:
  7243. pR - HTMLA request object, linked to a mapper object
  7244. Returns:
  7245. TRUE if succes, FALSE if failure
  7246. --*/
  7247. {
  7248. CInetInfoConfigInfoMapper *pM = pR->GetMapper();
  7249. CExtBuff *pB = pR->GetBuffer();
  7250. DWORD dwE;
  7251. BOOL fSt = TRUE;
  7252. // build filename, open file, map
  7253. HANDLE hFile;
  7254. HANDLE hFileMapping;
  7255. PBYTE pF;
  7256. DWORD dwFileSize;
  7257. char achFileName[MAX_PATH+1];
  7258. DWORD dwL;
  7259. int iIsSkip = HSS_NO_SKIP;
  7260. CExpr v1( pM ), v2( pM );
  7261. CRelop r1;
  7262. UINT cNestedIf = 0;
  7263. int aiNestedIf[MAX_NESTED_IF] = { 0 };
  7264. DWORD dwNewStat, dwOldStat = HTR_OK;
  7265. LPSTR pchGoto = NULL;
  7266. LPSTR pchOnError = NULL;
  7267. LPBYTE pStart;
  7268. BOOL fValid;
  7269. if ( pR->GetScr()[1] == ':' )
  7270. {
  7271. // absolute file name, keep as is
  7272. dwL = 0;
  7273. }
  7274. else
  7275. {
  7276. if ( g_fFakeServer )
  7277. {
  7278. strcpy( achFileName, "\\inetsrv\\scripts\\");
  7279. dwL = lstrlen( achFileName );
  7280. }
  7281. else
  7282. {
  7283. if ( (dwL = GetModuleFileName( g_hModule, achFileName, sizeof(achFileName) )) != 0 )
  7284. {
  7285. // back to last directory marker
  7286. char *p = (LPSTR)_mbsrchr((LPBYTE)achFileName, '\\');
  7287. dwL = (p) ? DIFF(p-achFileName)+1 : 0;
  7288. }
  7289. }
  7290. }
  7291. strncpy( achFileName+dwL, pR->GetScr(), sizeof(achFileName) - dwL - 5 );
  7292. achFileName[ sizeof( achFileName ) - 1 ] = '\0';
  7293. if ( strchr( achFileName, '.' ) == NULL )
  7294. {
  7295. strcat( achFileName, ".htr" );
  7296. }
  7297. if ( (hFile = CreateFile( achFileName, GENERIC_READ, FILE_SHARE_READ,
  7298. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ))
  7299. != INVALID_HANDLE_VALUE )
  7300. {
  7301. if( (hFileMapping = CreateFileMapping( hFile, NULL, PAGE_READONLY,
  7302. 0, 0, NULL )) != NULL )
  7303. {
  7304. dwFileSize = GetFileSize( hFile, NULL );
  7305. if ( dwFileSize != 0xffffffff && (pF = (LPBYTE)MapViewOfFile(
  7306. hFileMapping, FILE_MAP_READ, 0, 0, 0 )) != NULL )
  7307. {
  7308. LPBYTE pS, pOS, pAfter = pF+dwFileSize;
  7309. // remembered position
  7310. LPBYTE pIterS = NULL;
  7311. DWORD dwIterFileSize;
  7312. DWORD dwIter = 0;
  7313. for ( pOS = pS = pF ; dwFileSize; pOS = pS )
  7314. {
  7315. // check for error raised ( only once )
  7316. if ( (dwNewStat = pM->GetRequestStatus()) != dwOldStat )
  7317. {
  7318. if ( dwOldStat == HTR_OK && pchOnError != NULL )
  7319. {
  7320. iIsSkip |= HSS_SKIP_GOTO;
  7321. // copy onerror label to goto target label
  7322. if ( (pchGoto = AllocDup( pM, (LPBYTE)pchOnError,
  7323. strlen(pchOnError) )) == NULL )
  7324. {
  7325. pR->SetHTTPStatus( HT_BAD_GATEWAY );
  7326. fSt = FALSE;
  7327. // can't continue parsing : nested errors
  7328. break;
  7329. }
  7330. }
  7331. dwOldStat = dwNewStat;
  7332. }
  7333. if ( (pS = (LPBYTE)memchr( pOS, '<', (size_t)dwFileSize ))
  7334. == NULL )
  7335. {
  7336. if ( !iIsSkip )
  7337. {
  7338. pB->CopyBuff( pOS, dwFileSize );
  7339. }
  7340. break; // end of file
  7341. }
  7342. // copy up to ( but not including ) '<'
  7343. if ( !iIsSkip )
  7344. {
  7345. pB->CopyBuff( pOS, DIFF(pS - pOS) );
  7346. }
  7347. ++pS;
  7348. dwFileSize = DIFF(pAfter - pS);
  7349. if ( dwFileSize && *pS == '%' )
  7350. {
  7351. LPBYTE pVS = ++pS;
  7352. DWORD dwSize = --dwFileSize;
  7353. // skip to next '>'
  7354. while ( dwFileSize )
  7355. {
  7356. int c = *pS++;
  7357. --dwFileSize;
  7358. if ( c == '>' )
  7359. {
  7360. break;
  7361. }
  7362. }
  7363. if ( dwSize && *pVS == '!' )
  7364. {
  7365. if ( !iIsSkip )
  7366. {
  7367. ++pVS;
  7368. --dwSize;
  7369. // verb : must build CVerbContext
  7370. CVerbContext *pVerb = new CVerbContext();
  7371. if ( pVerb == NULL )
  7372. {
  7373. pR->SetHTTPStatus( HT_BAD_GATEWAY );
  7374. fSt = FALSE;
  7375. break;
  7376. }
  7377. DWORD dwL;
  7378. if ( dwL = pVerb->Parse( pM, pVS, dwSize ) )
  7379. {
  7380. pR->DoVerb( pVerb );
  7381. }
  7382. delete pVerb;
  7383. }
  7384. }
  7385. else if ( dwSize>sizeof(TOKEN_REDIRECT)-1
  7386. && !memcmp( pVS, TOKEN_REDIRECT,
  7387. sizeof(TOKEN_REDIRECT)-1) )
  7388. {
  7389. if ( !iIsSkip )
  7390. {
  7391. pB->Reset();
  7392. }
  7393. }
  7394. else if ( dwSize>sizeof(TOKEN_REDIRECTH)-1
  7395. && !memcmp( pVS, TOKEN_REDIRECTH,
  7396. sizeof(TOKEN_REDIRECTH)-1) )
  7397. {
  7398. if ( !iIsSkip )
  7399. {
  7400. pB->Reset();
  7401. }
  7402. }
  7403. else if ( dwSize>sizeof(TOKEN_END_REDIRECT)-1
  7404. && !memcmp( pVS, TOKEN_END_REDIRECT,
  7405. sizeof(TOKEN_END_REDIRECT)-1) )
  7406. {
  7407. if ( !iIsSkip )
  7408. {
  7409. pB->CopyBuff( (LPBYTE)"", 1 ); // add delimiter
  7410. pR->SetHTTPStatus( HT_REDIRECT );
  7411. break;
  7412. }
  7413. }
  7414. else if ( dwSize>sizeof(TOKEN_END_REDIRECTH)-1
  7415. && !memcmp( pVS, TOKEN_END_REDIRECTH,
  7416. sizeof(TOKEN_END_REDIRECTH)-1) )
  7417. {
  7418. if ( !iIsSkip )
  7419. {
  7420. pB->CopyBuff( (LPBYTE)"", 1 ); // add delimiter
  7421. pR->SetHTTPStatus( HT_REDIRECTH );
  7422. break;
  7423. }
  7424. }
  7425. else if ( dwSize>sizeof(TOKEN_POST)-1
  7426. && !memcmp( pVS, TOKEN_POST,
  7427. sizeof(TOKEN_POST)-1) )
  7428. {
  7429. if ( !iIsSkip )
  7430. {
  7431. pB->Reset();
  7432. }
  7433. }
  7434. else if ( dwSize>sizeof(TOKEN_END_POST)-1
  7435. && !memcmp( pVS, TOKEN_END_POST,
  7436. sizeof(TOKEN_END_POST)-1) )
  7437. {
  7438. if ( !iIsSkip )
  7439. {
  7440. pR->SetHTTPStatus( HT_REPROCESS );
  7441. break;
  7442. }
  7443. }
  7444. else if ( dwSize>sizeof(TOKEN_GOTO)-1
  7445. && !memcmp( pVS, TOKEN_GOTO,
  7446. sizeof(TOKEN_GOTO)-1) )
  7447. {
  7448. if ( !iIsSkip )
  7449. {
  7450. pVS += sizeof(TOKEN_GOTO)-1;
  7451. dwSize -= sizeof(TOKEN_GOTO)-1;
  7452. // ignore all other skip status
  7453. // i.e. cancel If, BeginIteration status
  7454. iIsSkip = HSS_SKIP_GOTO;
  7455. // store goto target
  7456. if ( GetToken( pVS, dwSize, &pStart, &dwL ) )
  7457. {
  7458. if ( (pchGoto = AllocDup( pM, pStart,
  7459. dwL)) == NULL )
  7460. {
  7461. pR->SetHTTPStatus( HT_BAD_GATEWAY );
  7462. fSt = FALSE;
  7463. // can't continue parsing : nested errors
  7464. break;
  7465. }
  7466. }
  7467. else
  7468. {
  7469. pM->SetRequestStatus( HTR_BAD_PARAM );
  7470. }
  7471. }
  7472. }
  7473. else if ( dwSize>sizeof(TOKEN_LABEL)-1
  7474. && !memcmp( pVS, TOKEN_LABEL,
  7475. sizeof(TOKEN_LABEL)-1) )
  7476. {
  7477. if ( iIsSkip&HSS_SKIP_GOTO )
  7478. {
  7479. pVS += sizeof(TOKEN_LABEL)-1;
  7480. dwSize -= sizeof(TOKEN_LABEL)-1;
  7481. if ( GetToken( pVS, dwSize, &pStart, &dwL ) )
  7482. {
  7483. if ( pchGoto && dwL == (DWORD)lstrlen(
  7484. pchGoto)
  7485. && !memcmp( pStart, pchGoto, dwL ) )
  7486. {
  7487. iIsSkip &= ~HSS_SKIP_GOTO;
  7488. }
  7489. }
  7490. else
  7491. {
  7492. pM->SetRequestStatus( HTR_BAD_PARAM );
  7493. }
  7494. }
  7495. }
  7496. else if ( dwSize>sizeof(TOKEN_ONERROR)-1
  7497. && !memcmp( pVS, TOKEN_ONERROR,
  7498. sizeof(TOKEN_ONERROR)-1) )
  7499. {
  7500. if ( !iIsSkip )
  7501. {
  7502. pVS += sizeof(TOKEN_ONERROR)-1;
  7503. dwSize -= sizeof(TOKEN_ONERROR)-1;
  7504. // store onerror target
  7505. if ( GetToken( pVS, dwSize, &pStart, &dwL ) )
  7506. {
  7507. if ( (pchOnError = AllocDup( pM, pStart,
  7508. dwL)) == NULL )
  7509. {
  7510. pR->SetHTTPStatus( HT_BAD_GATEWAY );
  7511. fSt = FALSE;
  7512. // can't continue parsing : no onerror target
  7513. break;
  7514. }
  7515. }
  7516. else
  7517. {
  7518. pM->SetRequestStatus( HTR_BAD_PARAM );
  7519. }
  7520. }
  7521. }
  7522. else if ( dwSize>sizeof(TOKEN_IF)-1
  7523. && !memcmp( pVS, TOKEN_IF,
  7524. sizeof(TOKEN_IF)-1) )
  7525. {
  7526. if ( cNestedIf == MAX_NESTED_IF-1 )
  7527. {
  7528. pM->SetRequestStatus( HTR_TOO_MANY_NESTED_IF );
  7529. continue;
  7530. }
  7531. pVS += sizeof(TOKEN_IF)-1;
  7532. dwSize -= sizeof(TOKEN_IF)-1;
  7533. ++cNestedIf;
  7534. if ( iIsSkip & (HSS_SKIP_IF|HSS_WAIT_ENDIF) )
  7535. {
  7536. aiNestedIf[cNestedIf] = HSS_WAIT_ENDIF;
  7537. }
  7538. else
  7539. {
  7540. aiNestedIf[cNestedIf] = HSS_NO_SKIP;
  7541. //iIsSkip &= ~HSS_SKIP_IF;
  7542. }
  7543. if ( iIsSkip )
  7544. {
  7545. continue;
  7546. }
  7547. as_if_token:
  7548. // get 1st var
  7549. if ( dwL = v1.Get( pVS, dwSize ) )
  7550. {
  7551. pVS += dwL;
  7552. dwSize -= dwL;
  7553. }
  7554. else
  7555. {
  7556. pM->SetRequestStatus( HTR_VAR_NOT_FOUND );
  7557. goto inv_if;
  7558. }
  7559. // get relop
  7560. if ( dwL = r1.Get( pVS, dwSize ) )
  7561. {
  7562. pVS += dwL;
  7563. dwSize -= dwL;
  7564. }
  7565. else
  7566. {
  7567. pM->SetRequestStatus( HTR_BAD_PARAM );
  7568. goto inv_if;
  7569. }
  7570. // get 2nd var
  7571. if ( dwL = v2.Get( pVS, dwSize ) )
  7572. {
  7573. pVS += dwL;
  7574. dwSize -= dwL;
  7575. }
  7576. else
  7577. {
  7578. pM->SetRequestStatus( HTR_VAR_NOT_FOUND );
  7579. goto inv_if;
  7580. }
  7581. if ( !r1.IsTrue( v1, v2, &fValid ) )
  7582. {
  7583. if ( !fValid )
  7584. {
  7585. pM->SetRequestStatus( HTR_INVALID_VAR_TYPE );
  7586. inv_if:
  7587. aiNestedIf[cNestedIf] = HSS_WAIT_ENDIF;
  7588. Adjust( &iIsSkip, aiNestedIf[cNestedIf] );
  7589. }
  7590. else
  7591. {
  7592. aiNestedIf[cNestedIf] = HSS_SKIP_IF;
  7593. Adjust( &iIsSkip, aiNestedIf[cNestedIf] );
  7594. }
  7595. }
  7596. }
  7597. else if ( dwSize>sizeof(TOKEN_ELSE)-1
  7598. && !memcmp( pVS, TOKEN_ELSE,
  7599. sizeof(TOKEN_ELSE)-1) )
  7600. {
  7601. if ( aiNestedIf[cNestedIf] == HSS_SKIP_IF )
  7602. {
  7603. aiNestedIf[cNestedIf] = HSS_NO_SKIP;
  7604. }
  7605. else
  7606. {
  7607. aiNestedIf[cNestedIf] = HSS_WAIT_ENDIF;
  7608. }
  7609. Adjust( &iIsSkip, aiNestedIf[cNestedIf] );
  7610. }
  7611. else if ( dwSize>sizeof(TOKEN_ELIF)-1
  7612. && !memcmp( pVS, TOKEN_ELIF,
  7613. sizeof(TOKEN_ELIF)-1) )
  7614. {
  7615. if ( aiNestedIf[cNestedIf] == HSS_SKIP_IF )
  7616. {
  7617. pVS += sizeof(TOKEN_ELIF)-1;
  7618. dwSize -= sizeof(TOKEN_ELIF)-1;
  7619. aiNestedIf[cNestedIf] = HSS_NO_SKIP;
  7620. Adjust( &iIsSkip, aiNestedIf[cNestedIf] );
  7621. goto as_if_token;
  7622. }
  7623. else
  7624. {
  7625. aiNestedIf[cNestedIf] = HSS_WAIT_ENDIF;
  7626. }
  7627. Adjust( &iIsSkip, aiNestedIf[cNestedIf] );
  7628. }
  7629. else if ( dwSize>sizeof(TOKEN_ENDIF)-1
  7630. && !memcmp( pVS, TOKEN_ENDIF,
  7631. sizeof(TOKEN_ENDIF)-1) )
  7632. {
  7633. if ( cNestedIf )
  7634. {
  7635. --cNestedIf;
  7636. Adjust( &iIsSkip, aiNestedIf[cNestedIf] );
  7637. }
  7638. else
  7639. {
  7640. pM->SetRequestStatus( HTR_IF_UNDERFLOW );
  7641. }
  7642. }
  7643. else if ( dwSize>sizeof(TOKEN_BEGIN_ITERATION)-1
  7644. && !memcmp( pVS, TOKEN_BEGIN_ITERATION,
  7645. sizeof(TOKEN_BEGIN_ITERATION)-1) )
  7646. {
  7647. // get counter
  7648. dwSize -= sizeof(TOKEN_BEGIN_ITERATION)-1;
  7649. pVS += sizeof(TOKEN_BEGIN_ITERATION)-1;
  7650. while ( dwSize && isspace((UCHAR)(*pVS)) )
  7651. {
  7652. --dwSize;
  7653. ++pVS;
  7654. }
  7655. CInetInfoMap *pVar = GetVarMap( pM, pVS, dwSize );
  7656. DWORD *pdwV;
  7657. if ( pVar != NULL && (pVar->iType == ITYPE_DWORD
  7658. || pVar->iType == ITYPE_BOOL) )
  7659. {
  7660. (pM->*pVar->GetAddr)( (LPVOID*)&pdwV );
  7661. dwIter = *pdwV;
  7662. }
  7663. else
  7664. {
  7665. pM->SetRequestStatus( HTR_VAR_NOT_FOUND );
  7666. dwIter = 0;
  7667. continue;
  7668. }
  7669. // remember position to loop on enditeration
  7670. pIterS = pS;
  7671. dwIterFileSize = dwFileSize;
  7672. pM->ResetIter();
  7673. if ( dwIter )
  7674. {
  7675. --dwIter;
  7676. }
  7677. else
  7678. {
  7679. iIsSkip |= HSS_SKIP_ITER;
  7680. }
  7681. }
  7682. else if ( dwSize>sizeof(TOKEN_END_ITERATION)-1
  7683. && !memcmp( pVS, TOKEN_END_ITERATION,
  7684. sizeof(TOKEN_END_ITERATION)-1) )
  7685. {
  7686. pM->IncIter();
  7687. if ( dwIter )
  7688. {
  7689. --dwIter;
  7690. pS = pIterS;
  7691. dwFileSize = dwIterFileSize;
  7692. }
  7693. else
  7694. {
  7695. iIsSkip &= ~HSS_SKIP_ITER;
  7696. }
  7697. }
  7698. else if ( !iIsSkip )
  7699. {
  7700. // is a variable
  7701. LPSTR pRes;
  7702. DWORD dwResLen;
  7703. BOOL fFree;
  7704. LPBYTE pAF = (LPBYTE)memchr( pVS, '%', dwSize );
  7705. if ( pAF && pM->GetString( pVS, DIFF(pAF - pVS),
  7706. &pRes, &dwResLen, &fFree ) )
  7707. {
  7708. pB->CopyBuff( (LPBYTE)pRes, dwResLen );
  7709. if ( fFree )
  7710. {
  7711. delete [] pRes;
  7712. }
  7713. }
  7714. else
  7715. {
  7716. pM->SetRequestStatus( HTR_VAR_NOT_FOUND );
  7717. break;
  7718. }
  7719. }
  7720. }
  7721. else if ( !iIsSkip )
  7722. {
  7723. pB->CopyBuff( (LPBYTE)"<", 1 );
  7724. }
  7725. }
  7726. UnmapViewOfFile( (LPVOID)pF );
  7727. }
  7728. else
  7729. {
  7730. pR->SetHTTPStatus( HT_BAD_GATEWAY );
  7731. fSt = FALSE;
  7732. }
  7733. CloseHandle( hFileMapping );
  7734. }
  7735. else
  7736. {
  7737. pR->SetHTTPStatus( HT_BAD_GATEWAY );
  7738. fSt = FALSE;
  7739. }
  7740. CloseHandle( hFile );
  7741. }
  7742. else
  7743. {
  7744. switch ( GetLastError() )
  7745. {
  7746. case ERROR_FILE_NOT_FOUND :
  7747. pR->SetHTTPStatus( HT_NOT_FOUND );
  7748. break;
  7749. case ERROR_ACCESS_DENIED:
  7750. pR->SetHTTPStatus( HT_DENIED );
  7751. break;
  7752. default:
  7753. pR->SetHTTPStatus( HT_SERVER_ERROR );
  7754. break;
  7755. }
  7756. fSt = FALSE;
  7757. }
  7758. return fSt;
  7759. }
  7760. ////////////// Dispatcher
  7761. CInetInfoRequestMap g_aIReqMap[] = {
  7762. { "display", &CInetInfoDispatcher::HandleDisplay, TRUE }, // all displays
  7763. } ;
  7764. CInetInfoDispatcher::CInetInfoDispatcher(
  7765. VOID )
  7766. {
  7767. }
  7768. CInetInfoDispatcher::~CInetInfoDispatcher(
  7769. VOID )
  7770. {
  7771. }
  7772. // map a service name to a CInetInfoConfigInfoMapper
  7773. CInetInfoConfigInfoMapper*
  7774. CInetInfoDispatcher::GetMapperFromString(
  7775. LPSTR pszServ )
  7776. {
  7777. if ( !strcmp( pszServ, "http" ) )
  7778. {
  7779. return &m_MapperHTTP;
  7780. }
  7781. else if ( !strcmp( pszServ, "ftp" ) )
  7782. {
  7783. return &m_MapperFTP;
  7784. }
  7785. else if ( !strcmp( pszServ, "gopher" ) )
  7786. {
  7787. return &m_MapperGOPHER;
  7788. }
  7789. else if ( !strcmp( pszServ, "dns" ) )
  7790. {
  7791. return &m_MapperDNS;
  7792. }
  7793. else if ( !strcmp( pszServ, "dir" ) )
  7794. {
  7795. return &m_MapperDIR;
  7796. }
  7797. // default is HTTP
  7798. return &m_MapperHTTP;
  7799. }
  7800. BOOL
  7801. CInetInfoDispatcher::HandleDisplay(
  7802. CInetInfoRequest* pR )
  7803. {
  7804. BOOL fSt = FALSE;
  7805. // display screen
  7806. fSt = m_IFMerger.Merge( pR );
  7807. return fSt;
  7808. }
  7809. BOOL
  7810. CInetInfoDispatcher::Init(
  7811. VOID )
  7812. {
  7813. m_apH = g_aIReqMap;
  7814. m_cH = sizeof(g_aIReqMap)/sizeof(CInetInfoRequestMap);
  7815. // initialize mappers
  7816. m_MapperHTTP.Init( g_InetInfoConfigInfoMap,
  7817. sizeof(g_InetInfoConfigInfoMap)/sizeof(CInetInfoMap),
  7818. INET_HTTP_SVC_ID );
  7819. m_MapperFTP.Init( g_InetInfoConfigInfoMap,
  7820. sizeof(g_InetInfoConfigInfoMap)/sizeof(CInetInfoMap),
  7821. INET_FTP_SVC_ID );
  7822. m_MapperGOPHER.Init( g_InetInfoConfigInfoMap,
  7823. sizeof(g_InetInfoConfigInfoMap)/sizeof(CInetInfoMap),
  7824. INET_GOPHER_SVC_ID );
  7825. m_MapperDNS.Init( g_InetInfoConfigInfoMap,
  7826. sizeof(g_InetInfoConfigInfoMap)/sizeof(CInetInfoMap),
  7827. INET_DNS_SVC_ID );
  7828. m_MapperDIR.Init( g_InetInfoDirInfoMap,
  7829. sizeof(g_InetInfoDirInfoMap)/sizeof(CInetInfoMap),
  7830. INET_DIR );
  7831. // initialize merger
  7832. m_IFMerger.Init();
  7833. return TRUE;
  7834. }
  7835. DWORD
  7836. CInetInfoDispatcher::Invoke(
  7837. EXTENSION_CONTROL_BLOCK *pECB )
  7838. /*++
  7839. Routine Description:
  7840. Handle an ISAPI request.
  7841. Arguments:
  7842. pECB - pointer ISAPI object
  7843. Returns:
  7844. ISAPI status
  7845. --*/
  7846. {
  7847. LPSTR pScr;
  7848. CInetInfoConfigInfoMapper *pIFMapper;
  7849. LPSTR pParam;
  7850. LPSTR p;
  7851. DWORD dwS = HSE_STATUS_ERROR;
  7852. LPSTR pMsgBody = NULL;
  7853. int cMsgBody = 0;
  7854. LPSTR pQueryString = NULL;
  7855. #if 0
  7856. // check authentication
  7857. char achRemoteUser[128];
  7858. DWORD dwRemoteUser = sizeof( achRemoteUser );
  7859. if ( !g_fFakeServer )
  7860. {
  7861. if ( pECB->GetServerVariable( (HCONN)pECB->ConnID,
  7862. "REMOTE_USER", achRemoteUser, &dwRemoteUser ) == FALSE
  7863. || achRemoteUser[0] == '\0' )
  7864. {
  7865. // send back authentication required header
  7866. #if defined(GENERATE_AUTH_HEADERS)
  7867. g_AuthReqs.Lock();
  7868. DWORD dwLen;
  7869. LPSTR pszAuthReqs = g_AuthReqs.GetAuthenticationListHeader();
  7870. if ( pszAuthReqs != NULL )
  7871. {
  7872. dwLen = lstrlen( pszAuthReqs );
  7873. pECB->ServerSupportFunction( pECB->ConnID,
  7874. HSE_REQ_SEND_RESPONSE_HEADER,
  7875. g_achAccessDenied,
  7876. &dwLen,
  7877. (LPDWORD)pszAuthReqs );
  7878. }
  7879. else
  7880. {
  7881. #if 0
  7882. dwLen = 0;
  7883. pECB->ServerSupportFunction( pECB->ConnID,
  7884. HSE_REQ_SEND_RESPONSE_HEADER,
  7885. "500 Authentication access failed",
  7886. &dwLen,
  7887. (LPDWORD)NULL );
  7888. #else
  7889. // no authentication method supported by server
  7890. // allow anonymous access ( likely to fail access to RPC,
  7891. // this will set reqstatus and give a chance to the .htr
  7892. // to handle it ).
  7893. g_AuthReqs.UnLock();
  7894. goto allow_in;
  7895. #endif
  7896. }
  7897. g_AuthReqs.UnLock();
  7898. dwS = HSE_STATUS_SUCCESS;
  7899. #else
  7900. DWORD dwLen = strlen(g_achAccessDeniedBody);
  7901. if ( !pECB->ServerSupportFunction( pECB->ConnID,
  7902. HSE_REQ_SEND_RESPONSE_HEADER,
  7903. g_achAccessDenied,
  7904. &dwLen,
  7905. (LPDWORD)g_achAccessDeniedBody ) )
  7906. {
  7907. dwS = HSE_STATUS_ERROR;
  7908. }
  7909. #endif
  7910. return dwS;
  7911. }
  7912. }
  7913. #endif
  7914. if ( pECB->lpszPathTranslated
  7915. && pECB->lpszPathInfo[0]
  7916. && pECB->lpszPathTranslated[0] )
  7917. {
  7918. if ( (pQueryString = new char[sizeof("dir/")
  7919. + strlen( pECB->lpszQueryString ) + 1
  7920. + strlen(pECB->lpszPathTranslated)]) == NULL )
  7921. {
  7922. return HSE_STATUS_ERROR;
  7923. }
  7924. memcpy( pQueryString, "dir/", sizeof("dir/")-1 );
  7925. strcpy( pQueryString + sizeof("dir/")-1, pECB->lpszPathTranslated );
  7926. strcat( pQueryString, "+" );
  7927. strcat( pQueryString, pECB->lpszQueryString );
  7928. }
  7929. allow_in:
  7930. if ( (p = strchr( pQueryString ? pQueryString : pECB->lpszQueryString,
  7931. '/' )) != NULL )
  7932. {
  7933. *p = '\0';
  7934. pIFMapper = GetMapperFromString( pQueryString
  7935. ? pQueryString : pECB->lpszQueryString );
  7936. pScr = p + 1;
  7937. // Look for parameter ( exposed as %urlparam% ) after '+'
  7938. if ( (pParam = strchr( pScr, '+' )) != NULL )
  7939. {
  7940. if ( pParam > pScr && pParam[-1] == '%' )
  7941. {
  7942. pParam[-1] = '\0';
  7943. }
  7944. else
  7945. {
  7946. *pParam = '\0';
  7947. }
  7948. ++pParam;
  7949. }
  7950. else
  7951. {
  7952. pParam = "";
  7953. }
  7954. UINT iH = 0;
  7955. CInetInfoRequest *pR = new CInetInfoRequest( pECB, pIFMapper,
  7956. pScr, pParam );
  7957. #if defined(DEBUG_LEVEL)
  7958. g_pReq = pR;
  7959. #endif
  7960. BOOL fSt = FALSE;
  7961. if ( pR != NULL && pR->Init( pMsgBody, cMsgBody ) )
  7962. {
  7963. // current methods are all Std
  7964. if ( m_apH[iH].fIsStd )
  7965. {
  7966. // Standard shell : retrieve info inside lock
  7967. pIFMapper->Lock();
  7968. pIFMapper->SetRequestStatus( HTR_OK );
  7969. pIFMapper->SetURLParam( pParam );
  7970. pIFMapper->SetReqParam( pR->GetData(), pR, pR->GetDataRaw() );
  7971. pIFMapper->GetCurrentConfig();
  7972. if ( pIFMapper->GetRPCStatus() == ERROR_ACCESS_DENIED )
  7973. {
  7974. pR->SetHTTPStatus( HT_DENIED );
  7975. fSt = TRUE;
  7976. }
  7977. else
  7978. {
  7979. fSt = (this->*m_apH[iH].pHandler)( pR );
  7980. }
  7981. pIFMapper->FreeInfo();
  7982. pIFMapper->UnLock();
  7983. }
  7984. else
  7985. {
  7986. fSt = (this->*m_apH[iH].pHandler)( pR );
  7987. }
  7988. //
  7989. // Always send back the response to the client
  7990. //
  7991. DWORD dwStatus = pR->Done();
  7992. dwS = fSt ? dwStatus : HSE_STATUS_ERROR;
  7993. if ( pMsgBody )
  7994. {
  7995. delete [] pMsgBody;
  7996. }
  7997. if ( pQueryString )
  7998. {
  7999. delete [] pQueryString;
  8000. }
  8001. if ( dwS == HSE_REPROCESS )
  8002. {
  8003. // store msg body, query string
  8004. LPSTR pB = (LPSTR)pR->GetBuffer()->GetPtr();
  8005. LPSTR pD = strchr( pB ? pB : "", '?' );
  8006. if ( pD != NULL )
  8007. {
  8008. cMsgBody = pR->GetBuffer()->GetLen() - DIFF( pD - pB ) - 1;
  8009. pQueryString = new char[ DIFF(pD - pB) + 1 ];
  8010. pMsgBody = new char[ cMsgBody + 1];
  8011. if ( pQueryString == NULL || pMsgBody == NULL )
  8012. goto no_rep;
  8013. DelimStrcpyN( pQueryString, pB, DIFF(pD - pB) );
  8014. DelimStrcpyN( pMsgBody, pB + ( pD - pB ) + 1, cMsgBody++ );
  8015. }
  8016. }
  8017. else
  8018. {
  8019. no_rep:
  8020. pMsgBody = NULL;
  8021. cMsgBody = 0;
  8022. pQueryString = NULL;
  8023. }
  8024. }
  8025. else
  8026. {
  8027. DWORD dwLen = 0;
  8028. pECB->ServerSupportFunction( pECB->ConnID,
  8029. HSE_REQ_SEND_RESPONSE_HEADER,
  8030. g_achInternalError,
  8031. &dwLen,
  8032. NULL );
  8033. dwS = HSE_STATUS_SUCCESS;
  8034. }
  8035. if ( pR != NULL )
  8036. {
  8037. delete pR;
  8038. }
  8039. }
  8040. if ( dwS == HSE_REPROCESS )
  8041. {
  8042. goto allow_in;
  8043. }
  8044. return dwS;
  8045. }
  8046. ///////////// CExpr, CRelop
  8047. // Get an expr, returns length of relop token or 0 if error
  8048. // expr can be either a var reference or an unsigned numeric literal
  8049. DWORD
  8050. CExpr::Get(
  8051. LPBYTE pS,
  8052. DWORD dwL )
  8053. /*++
  8054. Routine Description:
  8055. Parse memory block for expression
  8056. expression can one of :
  8057. - variable name
  8058. - numeric literal
  8059. - string literal ( inside "" )
  8060. Arguments:
  8061. pS - memory block to parse
  8062. dwL - size of memory block to parse
  8063. Returns:
  8064. # of bytes consumed to parse the expression or 0 if error
  8065. --*/
  8066. {
  8067. DWORD dwW = dwL;
  8068. int c;
  8069. // check if this object is re-used from previous call
  8070. if ( m_fMustFree )
  8071. {
  8072. delete [] m_pV;
  8073. m_fMustFree = FALSE;
  8074. }
  8075. // skip white space
  8076. while ( dwL && *pS == ' ' )
  8077. {
  8078. ++pS;
  8079. --dwL;
  8080. }
  8081. LPBYTE pW = pS;
  8082. DWORD dwLenTok = 0;
  8083. DWORD dwRes;
  8084. // get until '%', ' '
  8085. while ( dwL && (c=*pS)!='%' && c!=' ' )
  8086. {
  8087. ++dwLenTok;
  8088. ++pS;
  8089. --dwL;
  8090. }
  8091. if ( dwLenTok )
  8092. {
  8093. if ( *pW>='0' && *pW<='9' )
  8094. {
  8095. // litteral num
  8096. m_dwV = MultiByteToDWORD( (LPSTR)pW );
  8097. m_iType = ITYPE_DWORD;
  8098. return dwW - dwL;
  8099. }
  8100. else if ( *pW == '"' )
  8101. {
  8102. // String literal
  8103. m_pV = new char[ dwLenTok - 1 ];
  8104. if ( m_pV != NULL )
  8105. {
  8106. memcpy( m_pV, pW + 1, dwLenTok - 2 );
  8107. m_pV[ dwLenTok - 2 ] = '\0';
  8108. m_iType = ITYPE_LPSTR;
  8109. m_fMustFree = TRUE;
  8110. return dwW - dwL;
  8111. }
  8112. }
  8113. else
  8114. {
  8115. CInetInfoMap* pMap;
  8116. if ( m_pMap->Map( pW, dwLenTok, &pMap ) )
  8117. {
  8118. if ( pMap->iType == ITYPE_BOOL
  8119. || pMap->iType == ITYPE_DWORD
  8120. || pMap->iType == ITYPE_SHORT
  8121. || pMap->iType == ITYPE_SHORTDW )
  8122. {
  8123. LPVOID pV;
  8124. if ( (m_pMap->*pMap->GetAddr)( (LPVOID*)&pV ) )
  8125. {
  8126. m_dwV = pMap->iType == ITYPE_SHORT
  8127. ? (DWORD)*(unsigned short*)pV : *(DWORD*)pV;
  8128. m_iType = ITYPE_DWORD;
  8129. return dwW - dwL;
  8130. }
  8131. }
  8132. else if ( m_pMap->GetString( pMap,
  8133. &m_pV, &dwLenTok, &m_fMustFree ) )
  8134. {
  8135. m_iType = ITYPE_LPSTR;
  8136. return dwW - dwL;
  8137. }
  8138. }
  8139. else if ( m_pMap->GetString( pW, dwLenTok,
  8140. &m_pV, &dwRes, &m_fMustFree ) )
  8141. {
  8142. m_iType = ITYPE_LPSTR;
  8143. return dwW - dwL;
  8144. }
  8145. }
  8146. }
  8147. return 0; // error
  8148. }
  8149. DWORD
  8150. CExpr::GetAsDWORD(
  8151. )
  8152. /*++
  8153. Routine Description:
  8154. Returns content as a DWORD, converting from string to DWORD
  8155. if type is LPSR
  8156. Arguments:
  8157. None
  8158. Returns:
  8159. Value of object
  8160. --*/
  8161. {
  8162. if ( m_iType == ITYPE_DWORD )
  8163. {
  8164. return m_dwV;
  8165. }
  8166. else if ( m_iType == ITYPE_LPSTR )
  8167. {
  8168. return MultiByteToDWORD( m_pV );
  8169. }
  8170. else
  8171. {
  8172. return 0;
  8173. }
  8174. }
  8175. // relop list. Must be in sync with the RELOP_TYPE enum type.
  8176. LPSTR RELOP_TOKS[] = {
  8177. "~~", // invalid, not used
  8178. "EQ",
  8179. "NE",
  8180. "GT",
  8181. "LT",
  8182. "GE",
  8183. "LE",
  8184. "RF",
  8185. "BA",
  8186. } ;
  8187. DWORD
  8188. CRelop::Get(
  8189. LPBYTE pS,
  8190. DWORD dwL )
  8191. /*++
  8192. Routine Description:
  8193. Parse memory block for relational operator
  8194. as defined in RELOP_TOKS
  8195. Arguments:
  8196. pS - memory block to parse
  8197. dwL - size of memory block to parse
  8198. Returns:
  8199. # of bytes consumed to parse the operator or 0 if error
  8200. --*/
  8201. {
  8202. DWORD dwW = dwL;
  8203. UINT c;
  8204. // skip white space
  8205. while ( dwL && *pS == ' ' )
  8206. {
  8207. ++pS;
  8208. --dwL;
  8209. }
  8210. LPBYTE pW = pS;
  8211. DWORD dwLenTok = 0;
  8212. // get until '%', ' '
  8213. while ( dwL && (c=*pS)!='%' && c!=' ' )
  8214. {
  8215. ++dwLenTok;
  8216. ++pS;
  8217. --dwL;
  8218. }
  8219. if ( dwLenTok == 2 )
  8220. {
  8221. int x;
  8222. for ( x = 1 ; x < sizeof(RELOP_TOKS)/sizeof(LPSTR) ; ++x )
  8223. {
  8224. if ( !memcmp( RELOP_TOKS[x], pW, 2 ) )
  8225. {
  8226. m_iType = (RELOP_TYPE)x;
  8227. return dwW - dwL;
  8228. }
  8229. }
  8230. }
  8231. return 0; // error
  8232. }
  8233. // return TRUE if v1 RELOP v2 is TRUE
  8234. // handle only LPSTR and DWORD types
  8235. BOOL
  8236. CRelop::IsTrue(
  8237. CExpr& v1,
  8238. CExpr& v2,
  8239. BOOL *pfValid )
  8240. /*++
  8241. Routine Description:
  8242. Test the specified expressions with the current relational operator
  8243. Arguments:
  8244. v1 - left expression
  8245. v2 - right expression
  8246. pfValid - updated with FALSE is expression is invalid, else TRUE
  8247. Returns:
  8248. TRUE if v1 relop v2 is TRUE, otherwise FALSE
  8249. --*/
  8250. {
  8251. int iC;
  8252. DWORD num1, num2;
  8253. *pfValid = TRUE;
  8254. if ( v1.GetType() != v2.GetType() )
  8255. {
  8256. if ( (v1.GetType() == ITYPE_DWORD && v2.GetType() == ITYPE_LPSTR)
  8257. || (v1.GetType() == ITYPE_LPSTR && v2.GetType() == ITYPE_DWORD) )
  8258. {
  8259. goto as_dword;
  8260. }
  8261. *pfValid = FALSE;
  8262. return FALSE;
  8263. }
  8264. else if ( v1.GetType() == ITYPE_DWORD )
  8265. {
  8266. as_dword:
  8267. iC = (v1.GetAsDWORD() < v2.GetAsDWORD()) ? -1
  8268. : ((v1.GetAsDWORD() == v2.GetAsDWORD()) ? 0 : 1);
  8269. }
  8270. else if ( v1.GetType() == ITYPE_LPSTR )
  8271. {
  8272. if ( m_iType != RELOP_RF )
  8273. {
  8274. iC = lstrcmp( v1.GetAsStr(), v2.GetAsStr() );
  8275. }
  8276. }
  8277. else
  8278. {
  8279. iC = 0;
  8280. }
  8281. BOOL fR;
  8282. LPSTR pV;
  8283. LPSTR p2;
  8284. DWORD dwL2;
  8285. switch ( m_iType )
  8286. {
  8287. case RELOP_EQ: fR = iC == 0; break;
  8288. case RELOP_NE: fR = iC != 0; break;
  8289. case RELOP_GT: fR = iC > 0; break;
  8290. case RELOP_LT: fR = iC < 0; break;
  8291. case RELOP_GE: fR = iC >= 0; break;
  8292. case RELOP_LE: fR = iC <= 0; break;
  8293. case RELOP_BA: fR = !!(v1.GetAsDWORD() & v2.GetAsDWORD());
  8294. break;
  8295. case RELOP_RF:
  8296. fR = FALSE;
  8297. if ( v1.GetType() == ITYPE_LPSTR )
  8298. {
  8299. // parse v1 for v2
  8300. pV = v1.GetAsStr();
  8301. p2 = v2.GetAsStr();
  8302. dwL2 = lstrlen( p2 );
  8303. for ( ; *pV ; )
  8304. {
  8305. while ( isspace((UCHAR)(*pV)) )
  8306. {
  8307. ++pV;
  8308. }
  8309. LPSTR pE = strchr( pV, '=' );
  8310. BOOL fIsLast = FALSE;
  8311. if ( pE != NULL )
  8312. {
  8313. LPSTR pN = strchr( pE + 1, '&' );
  8314. if ( pN == NULL )
  8315. {
  8316. fIsLast = TRUE;
  8317. }
  8318. //TR_DEBUG( 0, "Update Mapping %s, value %s<p>", pV, pE+1 );
  8319. if ( (DWORD)(pE-pV) == dwL2
  8320. && !memcmp( pV, p2, DIFF(pE-pV) ) )
  8321. {
  8322. fR = TRUE;
  8323. break;
  8324. }
  8325. if ( fIsLast )
  8326. {
  8327. break;
  8328. }
  8329. pV = pN + 1;
  8330. }
  8331. else
  8332. {
  8333. break;
  8334. }
  8335. }
  8336. }
  8337. break;
  8338. default: fR = FALSE; break;
  8339. }
  8340. return fR;
  8341. }
  8342. /////////////
  8343. CInetInfoDispatcher g_InetInfoDispatcher;
  8344. /////////////
  8345. // version information
  8346. extern "C" BOOL WINAPI
  8347. GetExtensionVersion(
  8348. HSE_VERSION_INFO *version
  8349. )
  8350. /*++
  8351. Routine Description:
  8352. ISAPI function : called once to return version #
  8353. Arguments:
  8354. version - updated with version #
  8355. Returns:
  8356. TRUE if initialization success, else FALSE
  8357. --*/
  8358. {
  8359. version->dwExtensionVersion
  8360. = MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR);
  8361. strcpy(version->lpszExtensionDesc, "ism.dll v1.0");
  8362. if ( !g_InitDone )
  8363. {
  8364. g_InetInfoDispatcher.Init();
  8365. #if defined(GENERATE_AUTH_HEADERS)
  8366. g_AuthReqs.Init();
  8367. #endif
  8368. // initialize host name
  8369. char hn[MAX_DOMAIN_LENGTH + 1];
  8370. struct hostent FAR* pH;
  8371. if ( !gethostname( hn, sizeof(hn) )
  8372. && (pH = gethostbyname( hn ))
  8373. && pH->h_name
  8374. && pH->h_addr_list
  8375. && pH->h_addr_list[0]
  8376. )
  8377. {
  8378. g_pszDefaultHostName = new char[strlen( pH->h_name ) + 1];
  8379. if ( g_pszDefaultHostName == NULL )
  8380. {
  8381. return FALSE;
  8382. }
  8383. strcpy( g_pszDefaultHostName, pH->h_name );
  8384. }
  8385. // initialize htmla path
  8386. HKEY hK;
  8387. BOOL fDef = TRUE;
  8388. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  8389. W3SVC_REGISTRY_PATH,
  8390. 0,
  8391. KEY_READ,
  8392. &hK ) == ERROR_SUCCESS )
  8393. {
  8394. DWORD dwType;
  8395. DWORD cData = sizeof( g_achHtmlaPath );
  8396. if ( RegQueryValueEx( hK, W3SVC_REGISTRY_HTMLAPATH,
  8397. NULL, &dwType, (PBYTE)g_achHtmlaPath, &cData )
  8398. == ERROR_SUCCESS && dwType == REG_SZ )
  8399. {
  8400. fDef = FALSE;
  8401. }
  8402. RegCloseKey( hK );
  8403. }
  8404. if ( fDef )
  8405. {
  8406. strcpy( g_achHtmlaPath, "/htmla" );
  8407. }
  8408. //
  8409. // init strings from resources
  8410. //
  8411. if ( LoadString( g_hModule,
  8412. IDS_HTRESPX_DENIED,
  8413. g_achAccessDenied,
  8414. sizeof( g_achAccessDenied ) ) == 0 )
  8415. {
  8416. strcpy( g_achAccessDenied, "401" );
  8417. }
  8418. if ( LoadString( g_hModule,
  8419. IDS_HTRESPX_DENIED_BODY,
  8420. g_achAccessDeniedBody,
  8421. sizeof( g_achAccessDeniedBody ) ) == 0 )
  8422. {
  8423. strcpy( g_achAccessDeniedBody, "<html>Error: access denied</html>" );
  8424. }
  8425. if ( LoadString( g_hModule,
  8426. IDS_HTRESPX_SERVER_ERROR,
  8427. g_achInternalError,
  8428. sizeof( g_achInternalError ) ) == 0 )
  8429. {
  8430. strcpy( g_achInternalError, "500" );
  8431. }
  8432. if ( LoadString( g_hModule,
  8433. IDS_HTRESPX_NOT_FOUND,
  8434. g_achNotFound,
  8435. sizeof( g_achNotFound ) ) == 0 )
  8436. {
  8437. strcpy( g_achNotFound, "404" );
  8438. }
  8439. if ( LoadString( g_hModule,
  8440. IDS_HTRESPX_NOT_FOUND_BODY,
  8441. g_achNotFoundBody,
  8442. sizeof( g_achNotFoundBody ) ) == 0 )
  8443. {
  8444. strcpy( g_achNotFoundBody,
  8445. "<html>Error : The requested file could not be found.</html>" );
  8446. }
  8447. for ( int x = 0 ;
  8448. x < sizeof(g_aStatus)/sizeof(CStatusStringAndCode) ;
  8449. ++x )
  8450. {
  8451. if ( LoadString( g_hModule,
  8452. g_aStatus[x].dwID,
  8453. g_aStatus[x].achStatus,
  8454. sizeof( g_aStatus[x].achStatus ) ) == 0 )
  8455. {
  8456. wsprintf( g_aStatus[x].achStatus,
  8457. "%d",
  8458. g_aStatus[x].dwStatus );
  8459. }
  8460. }
  8461. g_InitDone = TRUE;
  8462. }
  8463. return TRUE;
  8464. }
  8465. extern "C" DWORD WINAPI
  8466. HttpExtensionProc(
  8467. EXTENSION_CONTROL_BLOCK* pEcb
  8468. )
  8469. /*++
  8470. Routine Description:
  8471. ISAPI function : called for each incoming HTTP request
  8472. Arguments:
  8473. pEcb - pointer to ISAPI request object
  8474. Returns:
  8475. ISAPI status
  8476. --*/
  8477. {
  8478. return g_InetInfoDispatcher.Invoke( pEcb );
  8479. }
  8480. extern "C" BOOL WINAPI
  8481. DllMain(
  8482. HANDLE hModule,
  8483. DWORD dwReason,
  8484. LPVOID )
  8485. /*++
  8486. Routine Description:
  8487. DLL init/terminate notification function
  8488. Arguments:
  8489. hModule - DLL handle
  8490. dwReason - notification type
  8491. LPVOID - not used
  8492. Returns:
  8493. TRUE if success, FALSE if failure
  8494. --*/
  8495. {
  8496. switch ( dwReason )
  8497. {
  8498. case DLL_PROCESS_ATTACH:
  8499. // record the module handle to access module info later
  8500. g_hModule = (HINSTANCE)hModule;
  8501. if ( g_hLonsi = LoadLibrary("lonsint.dll") )
  8502. {
  8503. g_pfnGetDefaultDomainName = (GET_DEFAULT_DOMAIN_NAME_FN)
  8504. GetProcAddress( g_hLonsi, "IISGetDefaultDomainName" );
  8505. }
  8506. break;
  8507. case DLL_PROCESS_DETACH:
  8508. #if defined(GENERATE_AUTH_HEADERS)
  8509. g_AuthReqs.Terminate();
  8510. #endif
  8511. if ( g_hLonsi )
  8512. {
  8513. g_pfnGetDefaultDomainName = NULL;
  8514. FreeLibrary( g_hLonsi );
  8515. g_hLonsi = NULL;
  8516. }
  8517. break;
  8518. }
  8519. return TRUE;
  8520. }
  8521. // Test shell. To be used to simulate a BGI call using a console app.
  8522. BYTE achTest[]="rootdir=c:\\inetsrv&rootishome=0&rootname=/w&rootacctname=&rootacctpw=&rootaddr=&rootisread=1";
  8523. void __declspec( dllexport )
  8524. Test(
  8525. VOID )
  8526. {
  8527. HSE_VERSION_INFO hv;
  8528. EXTENSION_CONTROL_BLOCK Ecb;
  8529. Ecb.cbTotalBytes = sizeof(achTest);
  8530. Ecb.cbAvailable = sizeof(achTest);
  8531. Ecb.lpbData = achTest;
  8532. //Ecb.lpszQueryString = "http/w3/advdeny+/-c:\\inetsrv\\wwwroot";
  8533. Ecb.lpszQueryString = "http/w3/serv+/syuyr!/ttt";
  8534. printf( "Nb Handler : %d\n", g_InetInfoDispatcher.GetNbH() );
  8535. GetExtensionVersion( &hv );
  8536. g_fFakeServer = TRUE;
  8537. HttpExtensionProc( &Ecb );
  8538. }