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.

640 lines
13 KiB

  1. #include "stdafx.h"
  2. #if defined(DBG)
  3. void Debug (LPCWSTR Text)
  4. {
  5. UNICODE_STRING UnicodeString;
  6. ANSI_STRING AnsiString;
  7. NTSTATUS Status;
  8. assert (Text);
  9. if (DebugLevel > 0) {
  10. RtlInitUnicodeString (&UnicodeString, Text);
  11. Status = RtlUnicodeStringToAnsiString (&AnsiString, &UnicodeString, TRUE);
  12. if (NT_SUCCESS (Status)) {
  13. OutputDebugStringA (AnsiString.Buffer);
  14. RtlFreeAnsiString (&AnsiString);
  15. }
  16. }
  17. }
  18. void DebugVa (LPCTSTR Format, va_list VaList)
  19. {
  20. TCHAR Text [0x200];
  21. _vsntprintf (Text, 0x200, Format, VaList);
  22. Debug (Text);
  23. }
  24. void DebugF (LPCTSTR Format, ...)
  25. {
  26. va_list VaList;
  27. va_start (VaList, Format);
  28. DebugVa (Format, VaList);
  29. va_end (VaList);
  30. }
  31. void DumpError (DWORD ErrorCode)
  32. {
  33. TCHAR Text [0x200];
  34. DWORD TextLength;
  35. DWORD MaxLength;
  36. LPTSTR Pos;
  37. _tcscpy (Text, _T("\tError: "));
  38. Pos = Text + _tcslen (Text);
  39. MaxLength = 0x200 - (DWORD)(Pos - Text);
  40. TextLength = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrorCode, LANG_NEUTRAL, Text, 0x200, NULL);
  41. if (!TextLength)
  42. _sntprintf (Pos, MaxLength, _T("Uknown error %08XH %u"), ErrorCode, ErrorCode);
  43. _tcsncat (Text, _T("\n"), MaxLength);
  44. Text [MaxLength - 1] = 0;
  45. Debug (Text);
  46. }
  47. void DebugError (DWORD ErrorCode, LPCTSTR Text)
  48. {
  49. Debug (Text);
  50. DumpError (ErrorCode);
  51. }
  52. void DebugErrorF (DWORD ErrorCode, LPCTSTR Format, ...)
  53. {
  54. va_list VaList;
  55. va_start (VaList, Format);
  56. DebugVa (Format, VaList);
  57. va_end (VaList);
  58. DumpError (ErrorCode);
  59. }
  60. void DebugLastError (LPCTSTR Text)
  61. {
  62. DebugError (GetLastError(), Text);
  63. }
  64. void DebugLastErrorF (LPCTSTR Format, ...)
  65. {
  66. va_list VaList;
  67. DWORD ErrorCode;
  68. ErrorCode = GetLastError();
  69. va_start (VaList, Format);
  70. DebugVa (Format, VaList);
  71. va_end (VaList);
  72. DumpError (ErrorCode);
  73. }
  74. static __inline CHAR ToHexA (UCHAR x)
  75. {
  76. x &= 0xF;
  77. if (x < 10) return x + '0';
  78. return (x - 10) + 'A';
  79. }
  80. void DumpMemory (const UCHAR * Data, ULONG Length)
  81. {
  82. const UCHAR * DataPos; // position within data
  83. const UCHAR * DataEnd; // end of valid data
  84. const UCHAR * RowPos; // position within a row
  85. const UCHAR * RowEnd; // end of single row
  86. CHAR Text [0x100];
  87. LPSTR TextPos;
  88. ULONG RowWidth;
  89. assert (Data);
  90. if (DebugLevel > 1) {
  91. DataPos = Data;
  92. DataEnd = Data + Length;
  93. while (DataPos < DataEnd) {
  94. RowWidth = (DWORD)(DataEnd - DataPos);
  95. if (RowWidth > 16)
  96. RowWidth = 16;
  97. RowEnd = DataPos + RowWidth;
  98. TextPos = Text;
  99. *TextPos++ = '\t';
  100. for (RowPos = DataPos; RowPos < RowEnd; RowPos++) {
  101. *TextPos++ = ToHexA ((*RowPos >> 4) & 0xF);
  102. *TextPos++ = ToHexA (*RowPos & 0xF);
  103. *TextPos++ = ' ';
  104. }
  105. *TextPos++ = '\r';
  106. *TextPos++ = '\n';
  107. *TextPos = 0;
  108. OutputDebugStringA (Text);
  109. assert (RowEnd > DataPos); // make sure we are walking forward
  110. DataPos = RowEnd;
  111. }
  112. }
  113. }
  114. #endif // defined(DBG)
  115. // LIFETIME_CONTROLLER -------------------------------------------------------------------------
  116. LIFETIME_CONTROLLER::LIFETIME_CONTROLLER (SYNC_COUNTER * AssocSyncCounter) {
  117. ReferenceCount = 0L;
  118. AssociatedSyncCounter = AssocSyncCounter;
  119. if (AssociatedSyncCounter)
  120. AssociatedSyncCounter -> Increment ();
  121. #if ENABLE_REFERENCE_HISTORY
  122. InitializeCriticalSection (&ReferenceHistoryLock);
  123. if (AssociatedSyncCounter) {
  124. AssociatedSyncCounter -> Lock ();
  125. InsertTailList (&AssociatedSyncCounter -> ActiveLifetimeControllers, &ListEntry);
  126. AssociatedSyncCounter -> Unlock ();
  127. }
  128. #endif // ENABLE_REFERENCE_HISTORY
  129. }
  130. LIFETIME_CONTROLLER::~LIFETIME_CONTROLLER () {
  131. #if ENABLE_REFERENCE_HISTORY
  132. if (AssociatedSyncCounter) {
  133. AssociatedSyncCounter -> Lock ();
  134. RemoveEntryList(&ListEntry);
  135. AssociatedSyncCounter -> Unlock ();
  136. }
  137. DeleteCriticalSection(&ReferenceHistoryLock);
  138. #endif // ENABLE_REFERENCE_HISTORY
  139. _ASSERTE (ReferenceCount == 0L);
  140. }
  141. void LIFETIME_CONTROLLER::AddRef (void) {
  142. LONG Count;
  143. _ASSERTE (ReferenceCount >= 0L);
  144. Count = InterlockedIncrement (&ReferenceCount);
  145. #if ENABLE_REFERENCE_HISTORY
  146. MAKE_REFERENCE_HISTORY_ENTRY ();
  147. #endif //ENABLE_REFERENCE_HISTORY
  148. }
  149. void LIFETIME_CONTROLLER::Release (void) {
  150. LONG Count;
  151. Count = InterlockedDecrement (&ReferenceCount);
  152. #if ENABLE_REFERENCE_HISTORY
  153. MAKE_REFERENCE_HISTORY_ENTRY ();
  154. #endif // ENABLE_REFERENCE_HISTORY
  155. _ASSERTE (Count >= 0);
  156. if (Count == 0) {
  157. SYNC_COUNTER * LocalAssociatedSyncCounter;
  158. LocalAssociatedSyncCounter = AssociatedSyncCounter;
  159. delete this;
  160. if (LocalAssociatedSyncCounter)
  161. LocalAssociatedSyncCounter -> Decrement ();
  162. }
  163. }
  164. // SYNC_COUNTER -------------------------------------------------------------------------
  165. SYNC_COUNTER::SYNC_COUNTER () {
  166. CounterValue = 0;
  167. ZeroEvent = NULL;
  168. }
  169. SYNC_COUNTER::~SYNC_COUNTER () {
  170. }
  171. HRESULT SYNC_COUNTER::Start (void)
  172. {
  173. HRESULT Result = S_OK;
  174. assert (ZeroEvent == NULL);
  175. CounterValue = 1;
  176. ZeroEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
  177. if (!ZeroEvent) {
  178. Result = GetLastError ();
  179. DebugLastError (_T("SYNC_COUNTER::SYNC_COUNTER: failed to create zero event\n"));
  180. }
  181. #if ENABLE_REFERENCE_HISTORY
  182. Lock ();
  183. InitializeListHead (&ActiveLifetimeControllers);
  184. Unlock ();
  185. #endif // ENABLE_REFERENCE_HISTORY
  186. return Result;
  187. }
  188. void SYNC_COUNTER::Stop () {
  189. if (ZeroEvent) {
  190. CloseHandle (ZeroEvent);
  191. ZeroEvent = NULL;
  192. }
  193. }
  194. DWORD SYNC_COUNTER::Wait (DWORD Timeout)
  195. {
  196. if (!ZeroEvent) {
  197. Debug (_T("SYNC_COUNTER::Wait: cannot wait because zero event could not be created\n"));
  198. return ERROR_GEN_FAILURE;
  199. }
  200. Lock();
  201. assert (CounterValue > 0);
  202. if (--CounterValue == 0) {
  203. if (ZeroEvent)
  204. SetEvent (ZeroEvent);
  205. }
  206. Unlock ();
  207. #if DBG
  208. if (Timeout == INFINITE) {
  209. DWORD Status;
  210. for (;;) {
  211. Status = WaitForSingleObject (ZeroEvent, 5000);
  212. if (Status == WAIT_OBJECT_0)
  213. return ERROR_SUCCESS;
  214. assert (Status == WAIT_TIMEOUT);
  215. DebugF (_T("SYNC_COUNTER::Wait: thread %08XH is taking a long time to wait for sync counter, counter value (%d)\n"),
  216. GetCurrentThreadId(), CounterValue);
  217. }
  218. }
  219. else
  220. return WaitForSingleObject (ZeroEvent, Timeout);
  221. #else
  222. return WaitForSingleObject (ZeroEvent, Timeout);
  223. #endif
  224. }
  225. void SYNC_COUNTER::Increment (void)
  226. {
  227. Lock();
  228. CounterValue++;
  229. Unlock();
  230. }
  231. void SYNC_COUNTER::Decrement (void)
  232. {
  233. Lock();
  234. assert (CounterValue > 0);
  235. if (--CounterValue == 0) {
  236. if (ZeroEvent)
  237. SetEvent (ZeroEvent);
  238. }
  239. Unlock();
  240. }
  241. EXTERN_C void MergeLists (PLIST_ENTRY Result, PLIST_ENTRY Source)
  242. {
  243. PLIST_ENTRY Entry;
  244. // for now, we do a poor algorithm -- remove and insert every single object
  245. AssertListIntegrity (Source);
  246. AssertListIntegrity (Result);
  247. while (!IsListEmpty (Source)) {
  248. Entry = RemoveHeadList (Source);
  249. assert (!IsInList (Result, Entry));
  250. InsertTailList (Result, Entry);
  251. }
  252. }
  253. // check to see if entry is in list
  254. EXTERN_C BOOL IsInList (LIST_ENTRY * List, LIST_ENTRY * Entry)
  255. {
  256. LIST_ENTRY * Pos;
  257. AssertListIntegrity (List);
  258. for (Pos = List -> Flink; Pos != List; Pos = Pos -> Flink)
  259. if (Pos == Entry)
  260. return TRUE;
  261. return FALSE;
  262. }
  263. EXTERN_C void ExtractList (LIST_ENTRY * Destination, LIST_ENTRY * Source)
  264. {
  265. AssertListIntegrity (Source);
  266. InsertTailList (Source, Destination);
  267. RemoveEntryList (Source);
  268. InitializeListHead (Source);
  269. }
  270. EXTERN_C DWORD CountListLength (LIST_ENTRY * ListHead)
  271. {
  272. LIST_ENTRY * ListEntry;
  273. DWORD Count;
  274. assert (ListHead);
  275. AssertListIntegrity (ListHead);
  276. Count = 0;
  277. for (ListEntry = ListHead -> Flink; ListEntry != ListHead; ListEntry++)
  278. Count++;
  279. return Count;
  280. }
  281. void AssertListIntegrity (LIST_ENTRY * list)
  282. {
  283. LIST_ENTRY * entry;
  284. assert (list);
  285. assert (list -> Flink -> Blink == list);
  286. assert (list -> Blink -> Flink == list);
  287. for (entry = list -> Flink; entry != list; entry = entry -> Flink) {
  288. assert (entry);
  289. assert (entry -> Flink -> Blink == entry);
  290. assert (entry -> Blink -> Flink == entry);
  291. }
  292. }
  293. NTSTATUS CopyAnsiString (
  294. IN ANSI_STRING * SourceString,
  295. OUT ANSI_STRING * DestString)
  296. {
  297. // assert (SourceString);
  298. // assert (SourceString -> Buffer);
  299. assert (DestString);
  300. if (SourceString) {
  301. // it's really SourceString -> Length, not * sizeof (CHAR), so don't change it
  302. DestString -> Buffer = (LPSTR) HeapAlloc (GetProcessHeap(), 0, SourceString -> Length);
  303. if (DestString -> Buffer) {
  304. memcpy (DestString -> Buffer, SourceString -> Buffer, SourceString -> Length);
  305. // yes, maxlen = len, not maxlen = maxlen
  306. DestString -> MaximumLength = SourceString -> Length;
  307. DestString -> Length = SourceString -> Length;
  308. return STATUS_SUCCESS;
  309. }
  310. else {
  311. ZeroMemory (DestString, sizeof (ANSI_STRING));
  312. return STATUS_NO_MEMORY;
  313. }
  314. }
  315. else {
  316. DestString -> Buffer = NULL;
  317. DestString -> MaximumLength = 0;
  318. DestString -> Length = 0;
  319. return STATUS_SUCCESS;
  320. }
  321. }
  322. void FreeAnsiString (
  323. IN ANSI_STRING * String)
  324. {
  325. assert (String);
  326. if (String -> Buffer) {
  327. HeapFree (GetProcessHeap(), 0, String -> Buffer);
  328. String -> Buffer = NULL;
  329. }
  330. }
  331. #if DBG
  332. void ExposeTimingWindow (void)
  333. {
  334. #if 0
  335. // this is here mostly to catch bug #393393, a/v on shutdown (race condition) -- arlied
  336. Debug (_T("H323: waiting for 10s to expose race condition... (expect assertion failure on NatHandle)\n"));
  337. DWORD Count;
  338. for (Count = 0; Count < 10; Count++) {
  339. assert (NatHandle);
  340. Sleep (1000);
  341. }
  342. Debug (_T("H323: finished waiting for race condition, looks normal...\n"));
  343. #endif
  344. }
  345. #endif
  346. /*++
  347. Routine Description:
  348. Get the address of the best interface that
  349. will be used to connect to the address specified.
  350. Arguments:
  351. DestinationAddress (IN) - address to be connected to, host order
  352. InterfaceAddress (OUT) - address of the interface that
  353. will be used for connection, host order
  354. Return Values:
  355. Win32 error specifying the outcome of the request
  356. Notes:
  357. Tries to use UDP-connect procedure to find the address of the interface
  358. If the procedure fails, then tries an alternative way of consulting
  359. the routing table, with GetBestInterface.
  360. --*/
  361. ULONG GetBestInterfaceAddress (
  362. IN DWORD DestinationAddress, // host order
  363. OUT DWORD * InterfaceAddress) // host order
  364. {
  365. SOCKET UDP_Socket;
  366. ULONG Error;
  367. SOCKADDR_IN ClientAddress;
  368. SOCKADDR_IN LocalToClientAddress;
  369. INT LocalToClientAddrSize = sizeof (SOCKADDR_IN);
  370. Error = S_OK;
  371. ClientAddress.sin_addr.s_addr = htonl (DestinationAddress);
  372. ClientAddress.sin_port = htons (0);
  373. ClientAddress.sin_family = AF_INET;
  374. UDP_Socket = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  375. if (UDP_Socket == INVALID_SOCKET){
  376. Error = WSAGetLastError ();
  377. DebugLastError (_T("GetBestInterfaceAddress: failed to create UDP socket.\n"));
  378. } else {
  379. if (SOCKET_ERROR != connect (UDP_Socket, (PSOCKADDR)&ClientAddress, sizeof (SOCKADDR_IN))) {
  380. LocalToClientAddrSize = sizeof (SOCKADDR_IN);
  381. if (!getsockname (UDP_Socket, (struct sockaddr *)&LocalToClientAddress, &LocalToClientAddrSize)) {
  382. *InterfaceAddress = ntohl (LocalToClientAddress.sin_addr.s_addr);
  383. Error = ERROR_SUCCESS;
  384. } else {
  385. Error = WSAGetLastError ();
  386. DebugLastError (_T("GetBestInterfaceAddress: failed to get name of UDP socket.\n"));
  387. }
  388. } else {
  389. Error = WSAGetLastError ();
  390. DebugLastError (_T("GetBestInterfaceAddress: failed to connect UDP socket."));
  391. }
  392. closesocket (UDP_Socket);
  393. UDP_Socket = INVALID_SOCKET;
  394. }
  395. return Error;
  396. }
  397. DWORD
  398. H323MapAdapterToAddress (
  399. IN DWORD AdapterIndex
  400. )
  401. /*++
  402. Routine Description:
  403. This routine is invoked to map an adapter index to an IP address.
  404. It does so by obtaining the stack's address table, and then linearly
  405. searching through it trying to find an entry with matching adapter
  406. index. If found, the entry is then used to obtain the IP address
  407. corresponding to the adapter index.
  408. Arguments:
  409. AdapterIndex - Index of a local adapter for which an IP address is requested
  410. Return Value:
  411. DWORD - IP address (in host order)
  412. If the routine succeeds, the return value will be a valid IP address
  413. If the routine fails, the return value will be INADDR_NONE
  414. --*/
  415. {
  416. DWORD Address = htonl (INADDR_NONE);
  417. ULONG Index;
  418. PMIB_IPADDRTABLE Table;
  419. if (AllocateAndGetIpAddrTableFromStack (
  420. &Table, FALSE, GetProcessHeap (), 0
  421. ) == NO_ERROR) {
  422. for (Index = 0; Index < Table -> dwNumEntries; Index++) {
  423. if (Table -> table[Index].dwIndex != AdapterIndex) {
  424. continue;
  425. }
  426. Address = Table -> table [Index].dwAddr;
  427. break;
  428. }
  429. HeapFree (GetProcessHeap (), 0, Table);
  430. }
  431. return ntohl (Address);
  432. } // H323MapAddressToAdapter