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.

373 lines
14 KiB

  1. // wsnmp_ma.c
  2. //
  3. // WinSNMP Initialization Functions and helpers
  4. // Copyright 1995-1997 ACE*COMM Corp
  5. // Rleased to Microsoft under Contract
  6. // Beta 1 version, 970228
  7. // Bob Natale ([email protected])
  8. //
  9. // 970310 - Free table memory on PROCESS_DETACH
  10. // - Refine snmpAllocTable() code
  11. // 970417 - GetVersionEx added to check for
  12. // - NT vs 95 and adjust code accordingly
  13. //
  14. #include "winsnmp.h"
  15. #include "winsnmpn.h"
  16. // Memory descriptors
  17. SNMPTD SessDescr;
  18. SNMPTD PDUsDescr;
  19. SNMPTD VBLsDescr;
  20. SNMPTD EntsDescr;
  21. SNMPTD CntxDescr;
  22. SNMPTD MsgDescr;
  23. SNMPTD TrapDescr;
  24. SNMPTD AgentDescr;
  25. TASK TaskData;
  26. CRITICAL_SECTION cs_TASK;
  27. CRITICAL_SECTION cs_SESSION;
  28. CRITICAL_SECTION cs_PDU;
  29. CRITICAL_SECTION cs_VBL;
  30. CRITICAL_SECTION cs_ENTITY;
  31. CRITICAL_SECTION cs_CONTEXT;
  32. CRITICAL_SECTION cs_MSG;
  33. CRITICAL_SECTION cs_TRAP;
  34. CRITICAL_SECTION cs_AGENT;
  35. CRITICAL_SECTION cs_XMODE;
  36. //-----------------------------------------------------------------
  37. // snmpAllocTable - This function is used to initialize and to increase
  38. // the size of WinSNMP internal tables. The caller must always ensure
  39. // that this function is executed only within a critical section block
  40. // on the target table's CRITICAL_SECTION object.
  41. //-----------------------------------------------------------------
  42. SNMPAPI_STATUS snmpAllocTable (LPSNMPTD pTableDescr)
  43. {
  44. LPVOID ptr;
  45. DWORD nLen;
  46. SNMPAPI_STATUS lResult = SNMPAPI_FAILURE;
  47. LPSNMPBD pBufDescr;
  48. // allocate a buffer large enough for the SNMPBD header plus the space
  49. // needed to hold 'BlockToAdd' blocks of size 'BlockSize' each.
  50. // the memory is already zero-ed because of the GPTR flag.
  51. pBufDescr = GlobalAlloc(GPTR, sizeof(SNMPBD) + (pTableDescr->BlockSize * pTableDescr->BlocksToAdd));
  52. if (pBufDescr == NULL)
  53. return SNMPAPI_FAILURE;
  54. // see if other buffers are present in the table
  55. if (pTableDescr->Allocated == 0)
  56. {
  57. // no blocks previously allocated => pTableDescr->Buffer = NULL at this point
  58. // pNewBufDescr is the first buffer in the table.
  59. pBufDescr->next = pBufDescr->prev = pBufDescr;
  60. pTableDescr->HeadBuffer = pBufDescr;
  61. }
  62. else
  63. {
  64. // there is at least one other block into the table, so insert the
  65. // new buffer into the circular list, just before the head of the list
  66. pBufDescr->next = pTableDescr->HeadBuffer;
  67. pBufDescr->prev = pTableDescr->HeadBuffer->prev;
  68. pBufDescr->next->prev = pBufDescr;
  69. pBufDescr->prev->next = pBufDescr;
  70. }
  71. // increase 'Allocated' with the additional 'BlocksToAdd' newly allocated entries.
  72. pTableDescr->Allocated += pTableDescr->BlocksToAdd;
  73. return SNMPAPI_SUCCESS;
  74. }
  75. //-----------------------------------------------------------------
  76. // snmpInitTableDescr - initializes the table descriptor with the
  77. // parameters given as arguments. Creates a first chunck of table.
  78. //-----------------------------------------------------------------
  79. SNMPAPI_STATUS snmpInitTableDescr(/*in*/LPSNMPTD pTableDescr, /*in*/DWORD dwBlocksToAdd, /*in*/DWORD dwBlockSize)
  80. {
  81. ZeroMemory (pTableDescr, sizeof(SNMPTD));
  82. pTableDescr->BlocksToAdd = dwBlocksToAdd;
  83. pTableDescr->BlockSize = dwBlockSize;
  84. return snmpAllocTable (pTableDescr);
  85. }
  86. //-----------------------------------------------------------------
  87. // snmpFreeTableDescr - releases any memory allocated for the table.
  88. //-----------------------------------------------------------------
  89. VOID snmpFreeTableDescr(/*in*/LPSNMPTD pTableDescr)
  90. {
  91. // do nothing if the table does not contain any entries
  92. if (pTableDescr->HeadBuffer == NULL)
  93. return;
  94. // break the circular list by setting the 'next' of
  95. // the buffer before the head to NULL
  96. pTableDescr->HeadBuffer->prev->next = NULL;
  97. while (pTableDescr->HeadBuffer != NULL)
  98. {
  99. LPSNMPBD pBufDescr;
  100. pBufDescr = pTableDescr->HeadBuffer;
  101. pTableDescr->HeadBuffer = pBufDescr->next;
  102. GlobalFree(pBufDescr);
  103. }
  104. }
  105. //-----------------------------------------------------------------
  106. // snmpAllocTableEntry - finds an empty slot in the table described
  107. // by pTableDescr, and returns its index. If none could be
  108. // found, table is extended in order to get some new empty slots.
  109. // It is not an API call so it doesn't check its parameters.
  110. //-----------------------------------------------------------------
  111. SNMPAPI_STATUS snmpAllocTableEntry(/*in*/LPSNMPTD pTableDescr, /*out*/LPDWORD pdwIndex)
  112. {
  113. // check if there are any empty entries into the table ..
  114. if (pTableDescr->Allocated == pTableDescr->Used)
  115. {
  116. // .. if not, enlarge the table ..
  117. if (!snmpAllocTable (pTableDescr))
  118. return SNMPAPI_ALLOC_ERROR;
  119. // .. and return the first empty slot
  120. *pdwIndex = pTableDescr->Used;
  121. // don't forget to update the 'Used' fields. The first one markes a new entry in use
  122. // in the buffer, the second one marks a new entry in use in the table as a whole
  123. (pTableDescr->HeadBuffer->prev->Used)++;
  124. pTableDescr->Used++;
  125. }
  126. else
  127. {
  128. DWORD dwBufferIndex, dwInBufferIndex;
  129. LPSNMPBD pBufDescr;
  130. LPBYTE pTblEntry; // cursor on the entries in the table
  131. // scan the list of buffers searching for the buffer that
  132. // holds at least one available entry.
  133. for (pBufDescr = pTableDescr->HeadBuffer, dwBufferIndex=0;
  134. pBufDescr->Used >= pTableDescr->BlocksToAdd;
  135. pBufDescr = pBufDescr->next, dwBufferIndex++)
  136. {
  137. // just a precaution: make sure we are not looping infinitely here
  138. // this shouldn't happen as far as 'Allocated' and 'Used' say there
  139. // are available entries, hence at least a buffer should match
  140. if (pBufDescr->next == pTableDescr->HeadBuffer)
  141. return SNMPAPI_OTHER_ERROR;
  142. }
  143. // now that we have the buffer with available entries,
  144. // search in it for the first one available.
  145. for ( pTblEntry = (LPBYTE)pBufDescr + sizeof(SNMPBD), dwInBufferIndex = 0;
  146. dwInBufferIndex < pTableDescr->BlocksToAdd;
  147. dwInBufferIndex++, pTblEntry += pTableDescr->BlockSize)
  148. {
  149. // an empty slot into the table has the first field = (HSNMP_SESSION)0
  150. if (*(HSNMP_SESSION *)pTblEntry == 0)
  151. break;
  152. }
  153. // make sure the buffer is not corrupted (it is so if 'Used' shows at
  154. // least an entry being available, but none seems to be so)
  155. if (dwInBufferIndex == pTableDescr->BlocksToAdd)
  156. return SNMPAPI_OTHER_ERROR;
  157. // don't forget to update the 'Used' fields. The first one markes a new entry in use
  158. // in the buffer, the second one marks a new entry in use in the table as a whole
  159. pBufDescr->Used++;
  160. pTableDescr->Used++;
  161. // we have the index of the buffer that contains the available entry
  162. // and the index of that entry inside the buffer. So just compute
  163. // the overall index and get out.
  164. (*pdwIndex) = dwBufferIndex * pTableDescr->BlocksToAdd + dwInBufferIndex;
  165. }
  166. return SNMPAPI_SUCCESS;
  167. }
  168. //-----------------------------------------------------------------
  169. // snmpFreeTableEntry - releases the entry at index dwIndex from the
  170. // table described by pTableDescr. It checks the validity of the index
  171. // and returns SNMPAPI_INDEX_INVALID if it is not in the range of the
  172. // allocated entries. It does not actually frees the memory, it cleares
  173. // it up and adjusts internal counters.
  174. //-----------------------------------------------------------------
  175. SNMPAPI_STATUS snmpFreeTableEntry(/*in*/LPSNMPTD pTableDescr, /*out*/DWORD dwIndex)
  176. {
  177. LPSNMPBD pBufDescr;
  178. LPBYTE pTableEntry;
  179. if (dwIndex >= pTableDescr->Allocated)
  180. return SNMPAPI_INDEX_INVALID;
  181. // scan for the buffer that holds the entry at index dwIndex
  182. for (pBufDescr = pTableDescr->HeadBuffer;
  183. dwIndex >= pTableDescr->BlocksToAdd;
  184. pBufDescr = pBufDescr->next, dwIndex -= pTableDescr->BlocksToAdd);
  185. // we have the buffer, get the actual pointer to the entry
  186. pTableEntry = (LPBYTE)pBufDescr + sizeof(SNMPBD);
  187. pTableEntry += dwIndex * pTableDescr->BlockSize;
  188. // zero the entry - having the first HSNMP_SESSION field set to 0
  189. // makes this entry available for further allocations
  190. ZeroMemory (pTableEntry, pTableDescr->BlockSize);
  191. // update the 'Used' fields to show that one entry less is in use
  192. if (pBufDescr->Used > 0)
  193. (pBufDescr->Used)--;
  194. if (pTableDescr->Used > 0)
  195. (pTableDescr->Used)--;
  196. return SNMPAPI_SUCCESS;
  197. }
  198. //-----------------------------------------------------------------
  199. // snmpGetTableEntry - takes as arguments a table description (pTableDescr)
  200. // and the zero based index (dwIndex) of the entry requested from the table
  201. // and returns in pointer to the entry requested.
  202. //-----------------------------------------------------------------
  203. PVOID snmpGetTableEntry(/*in*/LPSNMPTD pTableDescr, /*in*/DWORD dwIndex)
  204. {
  205. LPSNMPBD pBufDescr;
  206. LPBYTE pTableEntry;
  207. // this is an internal API, we make the assumption the index is correct
  208. // scan for the buffer that holds the entry at index dwIndex
  209. for (pBufDescr = pTableDescr->HeadBuffer;
  210. dwIndex >= pTableDescr->BlocksToAdd;
  211. pBufDescr = pBufDescr->next, dwIndex -= pTableDescr->BlocksToAdd);
  212. // we have the buffer, get the actual pointer to the entry
  213. pTableEntry = (LPBYTE)pBufDescr + sizeof(SNMPBD);
  214. pTableEntry += dwIndex * pTableDescr->BlockSize;
  215. // this is it, pTableEntry can be returned to the caller
  216. return pTableEntry;
  217. }
  218. //-----------------------------------------------------------------
  219. // snmpValidTableEntry - returns TRUE or FALSE as the entry at zero
  220. // based index dwIndex from the table described by pTableDescr has
  221. // valid data (is allocated) or not
  222. //-----------------------------------------------------------------
  223. BOOL snmpValidTableEntry(/*in*/LPSNMPTD pTableDescr, /*in*/DWORD dwIndex)
  224. {
  225. return (dwIndex < pTableDescr->Allocated) &&
  226. (*(HSNMP_SESSION *)snmpGetTableEntry(pTableDescr, dwIndex) != 0);
  227. }
  228. // Save error value as session/task/global error and return 0
  229. SNMPAPI_STATUS SaveError(HSNMP_SESSION hSession, SNMPAPI_STATUS nError)
  230. {
  231. TaskData.nLastError = nError;
  232. if (hSession)
  233. {
  234. LPSESSION pSession = snmpGetTableEntry(&SessDescr, HandleToUlong(hSession)-1);
  235. pSession->nLastError = nError;
  236. }
  237. return (SNMPAPI_FAILURE);
  238. }
  239. SNMPAPI_STATUS CheckRange (DWORD index, LPSNMPTD block)
  240. {
  241. if ((!index) || (index > block->Allocated))
  242. return (SNMPAPI_FAILURE);
  243. else
  244. return (SNMPAPI_SUCCESS);
  245. }
  246. int snmpInit (void)
  247. {
  248. // Initialize Tables
  249. if (snmpInitTableDescr(&SessDescr, DEFSESSIONS, sizeof(SESSION)) != SNMPAPI_SUCCESS ||
  250. snmpInitTableDescr(&PDUsDescr, DEFPDUS, sizeof(PDUS)) != SNMPAPI_SUCCESS ||
  251. snmpInitTableDescr(&VBLsDescr, DEFVBLS, sizeof(VBLS)) != SNMPAPI_SUCCESS ||
  252. snmpInitTableDescr(&EntsDescr, DEFENTITIES, sizeof(ENTITY)) != SNMPAPI_SUCCESS ||
  253. snmpInitTableDescr(&CntxDescr, DEFCONTEXTS, sizeof(CTXT)) != SNMPAPI_SUCCESS ||
  254. snmpInitTableDescr(&MsgDescr, DEFMSGS, sizeof(SNMPMSG)) != SNMPAPI_SUCCESS ||
  255. snmpInitTableDescr(&TrapDescr, DEFTRAPS, sizeof(TRAPNOTICE)) != SNMPAPI_SUCCESS ||
  256. snmpInitTableDescr(&AgentDescr, DEFAGENTS, sizeof(AGENT)) != SNMPAPI_SUCCESS)
  257. return (SNMPAPI_FAILURE);
  258. //
  259. return (SNMPAPI_SUCCESS);
  260. } // end_snmpInit()
  261. void snmpFree (void)
  262. {
  263. snmpFreeTableDescr(&SessDescr);
  264. snmpFreeTableDescr(&PDUsDescr);
  265. snmpFreeTableDescr(&VBLsDescr);
  266. snmpFreeTableDescr(&EntsDescr);
  267. snmpFreeTableDescr(&CntxDescr);
  268. snmpFreeTableDescr(&MsgDescr);
  269. snmpFreeTableDescr(&TrapDescr);
  270. snmpFreeTableDescr(&AgentDescr);
  271. } // end_snmpFree()
  272. BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
  273. {
  274. BOOL errCode = FALSE;
  275. LPCRITICAL_SECTION pCSArray[10]; // ten critical sections to initialize (cs_TASK..cs_XMODE)
  276. INT nCS; // counter in pCSArray
  277. pCSArray[0] = &cs_TASK;
  278. pCSArray[1] = &cs_SESSION;
  279. pCSArray[2] = &cs_PDU;
  280. pCSArray[3] = &cs_VBL;
  281. pCSArray[4] = &cs_ENTITY;
  282. pCSArray[5] = &cs_CONTEXT;
  283. pCSArray[6] = &cs_MSG;
  284. pCSArray[7] = &cs_TRAP;
  285. pCSArray[8] = &cs_AGENT;
  286. pCSArray[9] = &cs_XMODE;
  287. switch (dwReason)
  288. {
  289. case DLL_PROCESS_ATTACH:
  290. // Init task-specific data area
  291. ZeroMemory (&TaskData, sizeof(TASK));
  292. // Build tables
  293. __try
  294. {
  295. for (nCS = 0; nCS < 10; nCS++)
  296. InitializeCriticalSection (pCSArray[nCS]);
  297. }
  298. __except(EXCEPTION_EXECUTE_HANDLER)
  299. {
  300. // if an exception was raised, rollback the successfully initialized CS
  301. while (nCS > 0)
  302. DeleteCriticalSection(pCSArray[--nCS]);
  303. break;
  304. }
  305. if (snmpInit() == SNMPAPI_SUCCESS)
  306. errCode = TRUE;
  307. break;
  308. case DLL_THREAD_ATTACH:
  309. // A new thread is being created in the current process.
  310. break;
  311. case DLL_THREAD_DETACH:
  312. // A thread is exiting cleanly.
  313. break;
  314. case DLL_PROCESS_DETACH:
  315. // The calling process is detaching the DLL from its address space.
  316. for (nCS = 0; nCS < 10; nCS++)
  317. DeleteCriticalSection(pCSArray[nCS]);
  318. snmpFree();
  319. errCode = TRUE;
  320. break;
  321. default:
  322. break;
  323. }
  324. return (errCode);
  325. }