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.

671 lines
9.3 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. AtkUtils.c
  5. Abstract:
  6. This module contains miscellaneous support routines
  7. Author:
  8. Jameel Hyder (jameelh@microsoft.com)
  9. Nikhil Kamkolkar (nikhilk@microsoft.com)
  10. Revision History:
  11. 25 Feb 1993 Initial Version
  12. Notes: Tab stop: 4
  13. --*/
  14. #include <atalk.h>
  15. #pragma hdrstop
  16. #define FILENUM ATKUTILS
  17. #define ONE_MS_IN_100ns -10000L // 1ms in 100ns units
  18. extern BYTE AtalkUpCaseTable[256];
  19. VOID
  20. AtalkUpCase(
  21. IN PBYTE pSrc,
  22. IN BYTE SrcLen,
  23. OUT PBYTE pDst
  24. )
  25. /*++
  26. Routine Description:
  27. Arguments:
  28. Return Value:
  29. --*/
  30. {
  31. while (SrcLen --)
  32. {
  33. *pDst++ = AtalkUpCaseTable[*pSrc++];
  34. }
  35. }
  36. BOOLEAN
  37. AtalkCompareCaseInsensitive(
  38. IN PBYTE s1,
  39. IN PBYTE s2
  40. )
  41. /*++
  42. Routine Description:
  43. Arguments:
  44. Return Value:
  45. --*/
  46. {
  47. BYTE c1, c2;
  48. while (((c1 = *s1++) != 0) && ((c2 = *s2++) != 0))
  49. {
  50. if (AtalkUpCaseTable[c1] != AtalkUpCaseTable[c2])
  51. return(FALSE);
  52. }
  53. return (c2 == 0);
  54. }
  55. int
  56. AtalkOrderCaseInsensitive(
  57. IN PBYTE s1,
  58. IN PBYTE s2
  59. )
  60. /*++
  61. Routine Description:
  62. Arguments:
  63. Return Value:
  64. --*/
  65. {
  66. BYTE c1, c2;
  67. while (((c1 = *s1++) != 0) && ((c2 = *s2++) != 0))
  68. {
  69. c1 = AtalkUpCaseTable[c1];
  70. c2 = AtalkUpCaseTable[c2];
  71. if (c1 != c2)
  72. return (c1 - c2);
  73. }
  74. if (c2 == 0)
  75. return 0;
  76. return (-1);
  77. }
  78. BOOLEAN
  79. AtalkCompareFixedCaseInsensitive(
  80. IN PBYTE s1,
  81. IN PBYTE s2,
  82. IN int len
  83. )
  84. /*++
  85. Routine Description:
  86. Arguments:
  87. Return Value:
  88. --*/
  89. {
  90. while(len--)
  91. {
  92. if (AtalkUpCaseTable[*s1++] != AtalkUpCaseTable[*s2++])
  93. return(FALSE);
  94. }
  95. return(TRUE);
  96. }
  97. PBYTE
  98. AtalkSearchBuf(
  99. IN PBYTE pBuf,
  100. IN BYTE BufLen,
  101. IN BYTE SearchChar
  102. )
  103. /*++
  104. Routine Description:
  105. Arguments:
  106. Return Value:
  107. --*/
  108. {
  109. for (NOTHING;
  110. (BufLen != 0);
  111. BufLen--, pBuf++)
  112. {
  113. if (*pBuf == SearchChar)
  114. {
  115. break;
  116. }
  117. }
  118. return ((BufLen == 0) ? NULL : pBuf);
  119. }
  120. int
  121. GetTokenLen(
  122. IN PBYTE pTokStr,
  123. IN int WildStringLen,
  124. IN BYTE SearchChar
  125. )
  126. /*++
  127. Routine Description:
  128. Find the substring between start of the given string and the first
  129. wildchar after that, and return the length of the substring
  130. --*/
  131. {
  132. int len;
  133. len = 0;
  134. while (len < WildStringLen)
  135. {
  136. if (pTokStr[len] == SearchChar)
  137. {
  138. break;
  139. }
  140. len++;
  141. }
  142. return (len);
  143. }
  144. BOOLEAN
  145. SubStringMatch(
  146. IN PBYTE pTarget,
  147. IN PBYTE pTokStr,
  148. IN int StringLen,
  149. IN int TokStrLen
  150. )
  151. /*++
  152. Routine Description:
  153. Search pTarget string to see if the substring pTokStr can be
  154. found in it.
  155. --*/
  156. {
  157. int i;
  158. if (TokStrLen > StringLen)
  159. {
  160. return (FALSE);
  161. }
  162. // if the pTarget string is "FooBarString" and if the substring is
  163. // BarStr
  164. for (i=(StringLen-TokStrLen); i>=0; i--)
  165. {
  166. if ( AtalkFixedCompareCaseInsensitive( pTarget+i,
  167. TokStrLen,
  168. pTokStr,
  169. TokStrLen) )
  170. {
  171. return( TRUE );
  172. }
  173. }
  174. return (FALSE);
  175. }
  176. BOOLEAN
  177. AtalkCheckNetworkRange(
  178. IN PATALK_NETWORKRANGE Range
  179. )
  180. /*++
  181. Routine Description:
  182. Arguments:
  183. Return Value:
  184. --*/
  185. {
  186. if ((Range->anr_FirstNetwork < FIRST_VALID_NETWORK) ||
  187. (Range->anr_FirstNetwork > LAST_VALID_NETWORK) ||
  188. (Range->anr_LastNetwork < FIRST_VALID_NETWORK) ||
  189. (Range->anr_LastNetwork > LAST_VALID_NETWORK) ||
  190. (Range->anr_LastNetwork < Range->anr_FirstNetwork) ||
  191. (Range->anr_FirstNetwork >= FIRST_STARTUP_NETWORK))
  192. {
  193. return(FALSE);
  194. }
  195. return(TRUE);
  196. }
  197. BOOLEAN
  198. AtalkIsPrime(
  199. long Step
  200. )
  201. /*++
  202. Routine Description:
  203. Arguments:
  204. Return Value:
  205. --*/
  206. {
  207. // We assume "step" is odd.
  208. long i, j;
  209. // All odds, seven and below, are prime.
  210. if (Step <= 7)
  211. return (TRUE);
  212. // Do a little divisibility checking. The "/3" is a reasonably good
  213. // shot at sqrt() because the smallest odd to come through here will be
  214. // 9.
  215. j = Step/3;
  216. for (i = 3; i <= j; i++)
  217. if (Step % i == 0)
  218. return(FALSE);
  219. return(TRUE);
  220. }
  221. LONG
  222. AtalkRandomNumber(
  223. VOID
  224. )
  225. /*++
  226. Routine Description:
  227. Arguments:
  228. Return Value:
  229. --*/
  230. {
  231. LARGE_INTEGER Li;
  232. static LONG seed = 0;
  233. // Return a positive pseudo-random number; simple linear congruential
  234. // algorithm. ANSI C "rand()" function.
  235. if (seed == 0)
  236. {
  237. KeQuerySystemTime(&Li);
  238. seed = Li.LowPart;
  239. }
  240. seed *= (0x41C64E6D + 0x3039);
  241. return (seed & 0x7FFFFFFF);
  242. }
  243. BOOLEAN
  244. AtalkWaitTE(
  245. IN PKEVENT pEvent,
  246. IN ULONG TimeInMs
  247. )
  248. /*++
  249. Routine Description:
  250. Wait for an event to get signalled or a time to elapse
  251. Arguments:
  252. Return Value:
  253. --*/
  254. {
  255. TIME Time;
  256. NTSTATUS Status;
  257. // Make sure we can indeed wait
  258. ASSERT (KeGetCurrentIrql() == LOW_LEVEL);
  259. // Initialize the event
  260. KeInitializeEvent(pEvent, NotificationEvent, FALSE);
  261. Time.QuadPart = Int32x32To64((LONG)TimeInMs, ONE_MS_IN_100ns);
  262. Status = KeWaitForSingleObject(pEvent, Executive, KernelMode, FALSE, &Time);
  263. return (Status != STATUS_TIMEOUT);
  264. }
  265. VOID
  266. AtalkSleep(
  267. IN ULONG TimeInMs
  268. )
  269. /*++
  270. Routine Description:
  271. Arguments:
  272. Return Value:
  273. --*/
  274. {
  275. KTIMER SleepTimer;
  276. LARGE_INTEGER TimerValue;
  277. ASSERT (KeGetCurrentIrql() == LOW_LEVEL);
  278. KeInitializeTimer(&SleepTimer);
  279. TimerValue.QuadPart = Int32x32To64(TimeInMs, ONE_MS_IN_100ns);
  280. KeSetTimer(&SleepTimer,
  281. TimerValue,
  282. NULL);
  283. KeWaitForSingleObject(&SleepTimer, UserRequest, KernelMode, FALSE, NULL);
  284. }
  285. NTSTATUS
  286. AtalkGetProtocolSocketType(
  287. PATALK_DEV_CTX Context,
  288. PUNICODE_STRING RemainingFileName,
  289. PBYTE ProtocolType,
  290. PBYTE SocketType
  291. )
  292. /*++
  293. Routine Description:
  294. Arguments:
  295. Return Value:
  296. --*/
  297. {
  298. NTSTATUS status = STATUS_SUCCESS;
  299. ULONG protocolType;
  300. UNICODE_STRING typeString;
  301. *ProtocolType = PROTOCOL_TYPE_UNDEFINED;
  302. *SocketType = SOCKET_TYPE_UNDEFINED;
  303. switch (Context->adc_DevType)
  304. {
  305. case ATALK_DEV_DDP :
  306. if ((UINT)RemainingFileName->Length <= (sizeof(PROTOCOLTYPE_PREFIX) - sizeof(WCHAR)))
  307. {
  308. status = STATUS_NO_SUCH_DEVICE;
  309. break;
  310. }
  311. RtlInitUnicodeString(&typeString,
  312. (PWCHAR)((PCHAR)RemainingFileName->Buffer +
  313. sizeof(PROTOCOLTYPE_PREFIX) - sizeof(WCHAR)));
  314. status = RtlUnicodeStringToInteger(&typeString,
  315. DECIMAL_BASE,
  316. &protocolType);
  317. if (NT_SUCCESS(status))
  318. {
  319. DBGPRINT(DBG_COMP_CREATE, DBG_LEVEL_INFO,
  320. ("AtalkGetProtocolType: protocol type is %lx\n", protocolType));
  321. if ((protocolType > DDPPROTO_DDP) && (protocolType <= DDPPROTO_MAX))
  322. {
  323. *ProtocolType = (BYTE)protocolType;
  324. }
  325. else
  326. {
  327. status = STATUS_NO_SUCH_DEVICE;
  328. }
  329. }
  330. break;
  331. case ATALK_DEV_ADSP :
  332. // Check for the socket type
  333. if (RemainingFileName->Length == 0)
  334. {
  335. *SocketType = SOCKET_TYPE_RDM;
  336. break;
  337. }
  338. if ((UINT)RemainingFileName->Length != (sizeof(SOCKETSTREAM_SUFFIX) - sizeof(WCHAR)))
  339. {
  340. status = STATUS_NO_SUCH_DEVICE;
  341. break;
  342. }
  343. RtlInitUnicodeString(&typeString, SOCKETSTREAM_SUFFIX);
  344. // Case insensitive compare
  345. if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE))
  346. {
  347. *SocketType = SOCKET_TYPE_STREAM;
  348. break;
  349. }
  350. else
  351. {
  352. status = STATUS_NO_SUCH_DEVICE;
  353. break;
  354. }
  355. case ATALK_DEV_ASPC:
  356. case ATALK_DEV_ASP :
  357. case ATALK_DEV_PAP :
  358. break;
  359. default:
  360. status = STATUS_NO_SUCH_DEVICE;
  361. break;
  362. }
  363. return(status);
  364. }
  365. INT
  366. AtalkIrpGetEaCreateType(
  367. IN PIRP Irp
  368. )
  369. /*++
  370. Routine Description:
  371. Checks the EA name and returns the appropriate open type.
  372. Arguments:
  373. Irp - the irp for the create request, the EA value is stored in the
  374. SystemBuffer
  375. Return Value:
  376. TDI_TRANSPORT_ADDRESS_FILE: Create irp was for a transport address
  377. TDI_CONNECTION_FILE: Create irp was for a connection object
  378. ATALK_FILE_TYPE_CONTROL: Create irp was for a control channel (ea = NULL)
  379. --*/
  380. {
  381. PFILE_FULL_EA_INFORMATION openType;
  382. BOOLEAN found;
  383. INT returnType=0; // not a valid type
  384. USHORT i;
  385. openType = (PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
  386. if (openType != NULL)
  387. {
  388. do
  389. {
  390. found = TRUE;
  391. for (i=0;
  392. (i<(USHORT)openType->EaNameLength) && (i < sizeof(TdiTransportAddress));
  393. i++)
  394. {
  395. if (openType->EaName[i] == TdiTransportAddress[i])
  396. {
  397. continue;
  398. }
  399. else
  400. {
  401. found = FALSE;
  402. break;
  403. }
  404. }
  405. if (found)
  406. {
  407. returnType = TDI_TRANSPORT_ADDRESS_FILE;
  408. break;
  409. }
  410. //
  411. // Is this a connection object?
  412. //
  413. found = TRUE;
  414. for (i=0;
  415. (i<(USHORT)openType->EaNameLength) && (i < sizeof(TdiConnectionContext));
  416. i++)
  417. {
  418. if (openType->EaName[i] == TdiConnectionContext[i])
  419. {
  420. continue;
  421. }
  422. else
  423. {
  424. found = FALSE;
  425. break;
  426. }
  427. }
  428. if (found)
  429. {
  430. returnType = TDI_CONNECTION_FILE;
  431. break;
  432. }
  433. } while ( FALSE );
  434. }
  435. else
  436. {
  437. returnType = TDI_CONTROL_CHANNEL_FILE;
  438. }
  439. return(returnType);
  440. }
  441. #if DBG
  442. VOID
  443. AtalkDbgIncCount(
  444. IN DWORD *Value
  445. )
  446. {
  447. KIRQL OldIrql;
  448. ACQUIRE_SPIN_LOCK(&AtalkDebugSpinLock, &OldIrql);
  449. (*Value)++;
  450. RELEASE_SPIN_LOCK(&AtalkDebugSpinLock, OldIrql);
  451. }
  452. VOID
  453. AtalkDbgDecCount(
  454. IN DWORD *Value
  455. )
  456. {
  457. KIRQL OldIrql;
  458. ACQUIRE_SPIN_LOCK(&AtalkDebugSpinLock, &OldIrql);
  459. ASSERT((*Value) > 0);
  460. (*Value)--;
  461. RELEASE_SPIN_LOCK(&AtalkDebugSpinLock, OldIrql);
  462. }
  463. #endif
  464. 
  465.