Leaked source code of windows server 2003
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.

573 lines
15 KiB

  1. /*++
  2. Copyright (c) 1992-1996 Microsoft Corporation
  3. Module Name:
  4. odom_lm.c
  5. Abstract:
  6. This file contains the routines which actually call Lan Manager and
  7. retrieve the contents of the other domains table, including cacheing.
  8. Environment:
  9. User Mode - Win32
  10. Revision History:
  11. 10-May-1996 DonRyan
  12. Removed banner from Technology Dynamics, Inc.
  13. --*/
  14. //--------------------------- WINDOWS DEPENDENCIES --------------------------
  15. //--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----
  16. #ifdef WIN32
  17. #include <windows.h>
  18. #include <lm.h>
  19. #endif
  20. #include <string.h>
  21. #include <search.h>
  22. #include <stdlib.h>
  23. #include <time.h>
  24. //--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
  25. #include "mib.h"
  26. #include "mibfuncs.h"
  27. #include "odom_tbl.h"
  28. #include "lmcache.h"
  29. //--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----
  30. //--------------------------- PUBLIC VARIABLES --(same as in module.h file)--
  31. //--------------------------- PRIVATE CONSTANTS -----------------------------
  32. #define SafeBufferFree(x) if(NULL != x) NetApiBufferFree( x )
  33. #define SafeFree(x) if(NULL != x) SnmpUtilMemFree( x )
  34. //--------------------------- PRIVATE STRUCTS -------------------------------
  35. //--------------------------- PRIVATE VARIABLES -----------------------------
  36. //--------------------------- PRIVATE PROTOTYPES ----------------------------
  37. //--------------------------- PRIVATE PROCEDURES ----------------------------
  38. int __cdecl odom_entry_cmp(
  39. IN const DOM_OTHER_ENTRY *A,
  40. IN const DOM_OTHER_ENTRY *B
  41. ) ;
  42. BOOL build_odom_entry_oids( );
  43. void FreeDomOtherDomainTable();
  44. int chrcount(char *s)
  45. {
  46. char *temp;
  47. int i;
  48. temp = s;
  49. i = 1; // assume one since no terminating space, other code counts tokens
  50. while( NULL != (temp = strchr(temp,' ')) ) {
  51. i++;
  52. }
  53. return i;
  54. }
  55. //--------------------------- PUBLIC PROCEDURES -----------------------------
  56. //
  57. // MIB_odoms_lmset
  58. // Perform the necessary actions to set an entry in the Other Domain Table.
  59. //
  60. // Notes:
  61. //
  62. // Return Codes:
  63. //
  64. // Error Codes:
  65. // None.
  66. //
  67. UINT MIB_odoms_lmset(
  68. IN AsnObjectIdentifier *Index,
  69. IN UINT Field,
  70. IN AsnAny *Value
  71. )
  72. {
  73. LPBYTE bufptr = NULL;
  74. WKSTA_USER_INFO_1101 ODom;
  75. LPBYTE Temp;
  76. UINT Entry;
  77. UINT I;
  78. UINT ErrStat = SNMP_ERRORSTATUS_NOERROR;
  79. #ifdef UNICODE
  80. LPWSTR unitemp ;
  81. #endif
  82. // Must make sure the table is in memory
  83. if ( SNMPAPI_ERROR == MIB_odoms_lmget() )
  84. {
  85. ErrStat = SNMP_ERRORSTATUS_GENERR;
  86. goto Exit;
  87. }
  88. // See if match in table
  89. if ( MIB_TBL_POS_FOUND == MIB_odoms_match(Index, &Entry) )
  90. {
  91. // If empty string then delete entry
  92. if ( Value->asnValue.string.length == 0 )
  93. {
  94. // Alloc memory for buffer
  95. bufptr = SnmpUtilMemAlloc( DNLEN * sizeof(char) *
  96. (MIB_DomOtherDomainTable.Len-1) +
  97. MIB_DomOtherDomainTable.Len-1 );
  98. // prefix #57351
  99. if (bufptr == NULL)
  100. return SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE;
  101. // Create the other domain string
  102. Temp = bufptr;
  103. for ( I=0;I < MIB_DomOtherDomainTable.Len;I++ )
  104. {
  105. if ( I+1 != Entry )
  106. {
  107. if (MIB_DomOtherDomainTable.Table[I].domOtherName.length <= DNLEN)
  108. {
  109. memcpy( Temp,
  110. MIB_DomOtherDomainTable.Table[I].domOtherName.stream,
  111. MIB_DomOtherDomainTable.Table[I].domOtherName.length );
  112. Temp[MIB_DomOtherDomainTable.Table[I].domOtherName.length] = ' ';
  113. Temp += MIB_DomOtherDomainTable.Table[I].domOtherName.length + 1;
  114. }
  115. else
  116. {
  117. memcpy( Temp,
  118. MIB_DomOtherDomainTable.Table[I].domOtherName.stream,
  119. DNLEN );
  120. Temp[DNLEN] = ' ';
  121. Temp += DNLEN + 1;
  122. }
  123. }
  124. }
  125. *(Temp-1) = '\0';
  126. }
  127. else
  128. {
  129. // Cannot modify the domain entries, so bad value
  130. ErrStat = SNMP_ERRORSTATUS_BADVALUE;
  131. goto Exit;
  132. }
  133. }
  134. else
  135. {
  136. // Check for addition of NULL string, bad value
  137. if ( Value->asnValue.string.length == 0 )
  138. {
  139. ErrStat = SNMP_ERRORSTATUS_BADVALUE;
  140. goto Exit;
  141. }
  142. //
  143. // Entry doesn't exist so add it to the list
  144. //
  145. // Alloc memory for buffer
  146. bufptr = SnmpUtilMemAlloc( DNLEN * sizeof(char) *
  147. (MIB_DomOtherDomainTable.Len+1) +
  148. MIB_DomOtherDomainTable.Len+1 );
  149. // prefix #57352
  150. if (bufptr == NULL)
  151. return SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE;
  152. // Create the other domain string
  153. Temp = bufptr;
  154. for ( I=0;I < MIB_DomOtherDomainTable.Len;I++ )
  155. {
  156. if (MIB_DomOtherDomainTable.Table[I].domOtherName.length <= DNLEN)
  157. {
  158. memcpy( Temp, MIB_DomOtherDomainTable.Table[I].domOtherName.stream,
  159. MIB_DomOtherDomainTable.Table[I].domOtherName.length );
  160. Temp[MIB_DomOtherDomainTable.Table[I].domOtherName.length] = ' ';
  161. Temp += MIB_DomOtherDomainTable.Table[I].domOtherName.length + 1;
  162. }
  163. else
  164. {
  165. memcpy( Temp, MIB_DomOtherDomainTable.Table[I].domOtherName.stream,
  166. DNLEN );
  167. Temp[DNLEN] = ' ';
  168. Temp += DNLEN + 1;
  169. }
  170. }
  171. // Add new entry
  172. if (Value->asnValue.string.length <= DNLEN)
  173. {
  174. memcpy( Temp, Value->asnValue.string.stream,
  175. Value->asnValue.string.length );
  176. // Add NULL terminator
  177. Temp[Value->asnValue.string.length] = '\0';
  178. }
  179. else
  180. {
  181. memcpy( Temp, Value->asnValue.string.stream, DNLEN );
  182. // Add NULL terminator
  183. Temp[DNLEN] = '\0';
  184. }
  185. }
  186. // Set table and check return codes
  187. #ifdef UNICODE
  188. if (SnmpUtilUTF8ToUnicode( &unitemp,
  189. bufptr,
  190. TRUE ))
  191. {
  192. // failed
  193. ErrStat = SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE;
  194. goto Exit;
  195. }
  196. ODom.wkui1101_oth_domains = unitemp;
  197. #else
  198. ODom.wkui1101_oth_domains = bufptr;
  199. #endif
  200. #if 0
  201. if ( NERR_Success == NetWkstaUserSetInfo(NULL, 1101, (LPBYTE)&ODom, NULL) )
  202. {
  203. // Make cache be reloaded next time
  204. cache_table[C_ODOM_TABLE].bufptr = NULL;
  205. }
  206. else
  207. {
  208. ErrStat = SNMP_ERRORSTATUS_GENERR;
  209. }
  210. #else
  211. ErrStat = SNMP_ERRORSTATUS_GENERR;
  212. #endif
  213. Exit:
  214. SnmpUtilMemFree( bufptr );
  215. return ErrStat;
  216. } // MIB_odoms_lmset
  217. //
  218. // MIB_odom_lmget
  219. // Retrieve print queue table information from Lan Manager.
  220. // If not cached, sort it and then
  221. // cache it.
  222. //
  223. // Notes:
  224. //
  225. // Return Codes:
  226. // SNMPAPI_NOERROR
  227. // SNMPAPI_ERROR
  228. //
  229. // Error Codes:
  230. // None.
  231. //
  232. SNMPAPI MIB_odoms_lmget(
  233. )
  234. {
  235. DWORD totalentries;
  236. LPBYTE bufptr = NULL;
  237. unsigned lmCode;
  238. WKSTA_USER_INFO_1101 *DataTable;
  239. DOM_OTHER_ENTRY *MIB_DomOtherDomainTableElement ;
  240. char *p;
  241. char *next;
  242. time_t curr_time ;
  243. unsigned i;
  244. SNMPAPI nResult = SNMPAPI_NOERROR;
  245. time(&curr_time); // get the time
  246. //
  247. //
  248. // If cached, return piece of info.
  249. //
  250. //
  251. if((NULL != cache_table[C_ODOM_TABLE].bufptr) &&
  252. (curr_time <
  253. (cache_table[C_ODOM_TABLE].acquisition_time
  254. + cache_expire[C_ODOM_TABLE] ) ) )
  255. { // it has NOT expired!
  256. goto Exit; // the global table is valid
  257. }
  258. //
  259. //
  260. // Do network call to gather information and put it in a nice array
  261. //
  262. //
  263. //
  264. // remember to free the existing data
  265. //
  266. FreeDomOtherDomainTable();
  267. lmCode =
  268. NetWkstaUserGetInfo(
  269. 0, // required
  270. 1101, // level 0,
  271. &bufptr // data structure to return
  272. );
  273. DataTable = (WKSTA_USER_INFO_1101 *) bufptr ;
  274. if((NERR_Success == lmCode) || (ERROR_MORE_DATA == lmCode))
  275. { // valid so process it, otherwise error
  276. if(NULL==DataTable->wkui1101_oth_domains) {
  277. // Prefix #57350
  278. // free all of the lanman data
  279. SafeBufferFree( bufptr ) ;
  280. // Signal error
  281. nResult = SNMPAPI_ERROR;
  282. goto Exit;
  283. } else { // compute it
  284. totalentries = chrcount((char *)DataTable->wkui1101_oth_domains);
  285. if(0 == MIB_DomOtherDomainTable.Len) { // 1st time, alloc the whole table
  286. // alloc the table space
  287. MIB_DomOtherDomainTable.Table = SnmpUtilMemAlloc(totalentries *
  288. sizeof(DOM_OTHER_ENTRY) );
  289. // Prefix #57349
  290. if (MIB_DomOtherDomainTable.Table == NULL)
  291. {
  292. // free all of the lanman data
  293. SafeBufferFree( bufptr ) ;
  294. // Signal error
  295. nResult = SNMPAPI_ERROR;
  296. goto Exit;
  297. }
  298. }
  299. MIB_DomOtherDomainTableElement = MIB_DomOtherDomainTable.Table ;
  300. // make a pointer to the beginning of the string field
  301. #ifdef UNICODE
  302. if (SnmpUtilUnicodeToUTF8(
  303. &p,
  304. DataTable->wkui1101_oth_domains,
  305. TRUE))
  306. {
  307. // free all of the lanman data
  308. SafeBufferFree( bufptr ) ;
  309. // Signal error
  310. nResult = SNMPAPI_ERROR;
  311. goto Exit;
  312. }
  313. #else
  314. p = DataTable->wkui1101_oth_domains ;
  315. #endif
  316. // scan through the field, making an entry for each space
  317. // separated domain
  318. while( (NULL != p ) &&
  319. ('\0' != *p) ) { // once for each entry in the buffer
  320. // find the end of this one
  321. next = strchr(p,' ');
  322. // if more to come, ready next pointer and mark end of this one
  323. if(NULL != next) {
  324. *next='\0' ; // replace space with EOS
  325. next++ ; // point to beginning of next domain
  326. }
  327. MIB_DomOtherDomainTableElement->domOtherName.stream = SnmpUtilMemAlloc (
  328. strlen( p ) ) ;
  329. if (NULL == MIB_DomOtherDomainTableElement->domOtherName.stream)
  330. {
  331. p = next;
  332. continue;
  333. }
  334. MIB_DomOtherDomainTableElement->domOtherName.length =
  335. strlen( p ) ;
  336. MIB_DomOtherDomainTableElement->domOtherName.dynamic = TRUE;
  337. memcpy( MIB_DomOtherDomainTableElement->domOtherName.stream,
  338. p,
  339. strlen( p ) ) ;
  340. // increment the entry number
  341. MIB_DomOtherDomainTable.Len ++;
  342. MIB_DomOtherDomainTableElement ++ ; // and table entry
  343. p = next;
  344. } // while still more to do
  345. } // if there really were entries
  346. } // if data is valid to process
  347. else
  348. {
  349. // Signal error
  350. nResult = SNMPAPI_ERROR;
  351. goto Exit;
  352. }
  353. // free all of the lan man data
  354. SafeBufferFree( bufptr ) ;
  355. // iterate over the table populating the Oid field
  356. if (! build_odom_entry_oids())
  357. {
  358. SNMPDBG((
  359. SNMP_LOG_TRACE,
  360. "SNMP: LMMIB2: build_odom_entry_oids failed\n."));
  361. FreeDomOtherDomainTable();
  362. cache_table[C_ODOM_TABLE].bufptr = NULL;
  363. nResult = SNMPAPI_ERROR;
  364. goto Exit;
  365. }
  366. // Sort the table information using MSC QuickSort routine
  367. qsort( (void *)&MIB_DomOtherDomainTable.Table[0], (size_t)MIB_DomOtherDomainTable.Len,
  368. (size_t)sizeof(DOM_OTHER_ENTRY), odom_entry_cmp );
  369. //
  370. //
  371. // Cache table
  372. //
  373. //
  374. if(0 != MIB_DomOtherDomainTable.Len) {
  375. cache_table[C_ODOM_TABLE].acquisition_time = curr_time ;
  376. cache_table[C_ODOM_TABLE].bufptr = bufptr ;
  377. }
  378. //
  379. //
  380. // Return piece of information requested
  381. //
  382. //
  383. Exit:
  384. return nResult;
  385. } // MIB_odom_get
  386. //
  387. // MIB_odom_cmp
  388. // Routine for sorting the session table.
  389. //
  390. // Notes:
  391. //
  392. // Return Codes:
  393. // SNMPAPI_NOERROR
  394. // SNMPAPI_ERROR
  395. //
  396. // Error Codes:
  397. // None.
  398. //
  399. int __cdecl odom_entry_cmp(
  400. IN const DOM_OTHER_ENTRY *A,
  401. IN const DOM_OTHER_ENTRY *B
  402. )
  403. {
  404. // Compare the OID's
  405. return SnmpUtilOidCmp( (AsnObjectIdentifier *)&A->Oid,
  406. (AsnObjectIdentifier *)&B->Oid );
  407. } // MIB_odom_cmp
  408. //
  409. // None.
  410. //
  411. BOOL build_odom_entry_oids(
  412. )
  413. {
  414. AsnOctetString OSA ;
  415. DOM_OTHER_ENTRY *DomOtherEntry ;
  416. unsigned i;
  417. // start pointer at 1st guy in the table
  418. DomOtherEntry = MIB_DomOtherDomainTable.Table ;
  419. // now iterate over the table, creating an oid for each entry
  420. for( i=0; i<MIB_DomOtherDomainTable.Len ; i++) {
  421. // for each entry in the session table
  422. OSA.stream = DomOtherEntry->domOtherName.stream ;
  423. OSA.length = DomOtherEntry->domOtherName.length ;
  424. OSA.dynamic = FALSE;
  425. // Make the entry's OID from string index
  426. if (! MakeOidFromStr( &OSA, &DomOtherEntry->Oid ))
  427. {
  428. return FALSE;
  429. }
  430. DomOtherEntry++; // point to the next guy in the table
  431. } // for
  432. return TRUE;
  433. } // build_odom_entry_oids
  434. void FreeDomOtherDomainTable()
  435. {
  436. UINT i;
  437. DOM_OTHER_ENTRY *MIB_DomOtherDomainTableElement;
  438. MIB_DomOtherDomainTableElement = MIB_DomOtherDomainTable.Table ;
  439. if (MIB_DomOtherDomainTableElement)
  440. {
  441. // iterate over the whole table
  442. for(i=0; i<MIB_DomOtherDomainTable.Len ;i++)
  443. {
  444. // free any alloc'ed elements of the structure
  445. SnmpUtilOidFree(&(MIB_DomOtherDomainTableElement->Oid));
  446. SnmpUtilMemFree(MIB_DomOtherDomainTableElement->domOtherName.stream);
  447. MIB_DomOtherDomainTableElement ++ ; // increment table entry
  448. }
  449. SnmpUtilMemFree(MIB_DomOtherDomainTable.Table) ; // free the base Table
  450. }
  451. MIB_DomOtherDomainTable.Table = NULL ; // just for safety
  452. MIB_DomOtherDomainTable.Len = 0 ; // just for safety
  453. }
  454. //-------------------------------- END --------------------------------------