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.

1393 lines
45 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. server.c
  5. Abstract:
  6. This module contains server global data and server init code.
  7. This is used by the admin interface to start-off the server.
  8. Author:
  9. Jameel Hyder (microsoft!jameelh)
  10. Revision History:
  11. 25 Apr 1992 Initial Version
  12. Notes: Tab stop: 4
  13. --*/
  14. #define _GLOBALS_
  15. #define SERVER_LOCALS
  16. #define FILENUM FILE_SERVER
  17. #include <seposix.h>
  18. #include <afp.h>
  19. #include <afpadmin.h>
  20. #include <access.h>
  21. #include <client.h>
  22. #include <tcp.h>
  23. #ifdef ALLOC_PRAGMA
  24. #pragma alloc_text( INIT, AfpInitializeDataAndSubsystems)
  25. #pragma alloc_text( PAGE, AfpDeinitializeSubsystems)
  26. #pragma alloc_text( PAGE, AfpAdmSystemShutdown)
  27. #pragma alloc_text( PAGE, AfpCreateNewThread)
  28. #pragma alloc_text( PAGE_AFP, AfpAdmWServerSetInfo)
  29. //#pragma alloc_text( PAGE_AFP, AfpSetServerStatus)
  30. #endif
  31. // This is the device handle to the stack.
  32. BOOLEAN afpSpNameRegistered = False;
  33. HANDLE afpSpAddressHandle = NULL;
  34. PDEVICE_OBJECT afpSpAppleTalkDeviceObject = NULL;
  35. PFILE_OBJECT afpSpAddressObject = NULL;
  36. LONG afpSpNumOutstandingReplies = 0;
  37. /*** AfpInitializeDataAndSubsystems
  38. *
  39. * Initialize Server Data and all subsystems.
  40. */
  41. NTSTATUS
  42. AfpInitializeDataAndSubsystems(
  43. VOID
  44. )
  45. {
  46. NTSTATUS Status;
  47. PBYTE pBuffer;
  48. PBYTE pDest;
  49. LONG i, j;
  50. // Initialize various global locks
  51. INITIALIZE_SPIN_LOCK(&AfpServerGlobalLock);
  52. INITIALIZE_SPIN_LOCK(&AfpSwmrLock);
  53. INITIALIZE_SPIN_LOCK(&AfpStatisticsLock);
  54. #if DBG
  55. INITIALIZE_SPIN_LOCK(&AfpDebugSpinLock);
  56. InitializeListHead(&AfpDebugDelAllocHead);
  57. #endif
  58. KeInitializeEvent(&AfpStopConfirmEvent, NotificationEvent, False);
  59. KeInitializeMutex(&AfpPgLkMutex, 0xFFFF);
  60. AfpInitializeWorkItem(&AfpTerminateThreadWI, NULL, NULL);
  61. // The default security quality of service
  62. AfpSecurityQOS.Length = sizeof(AfpSecurityQOS);
  63. AfpSecurityQOS.ImpersonationLevel = SecurityImpersonation;
  64. AfpSecurityQOS.ContextTrackingMode = SECURITY_STATIC_TRACKING;
  65. AfpSecurityQOS.EffectiveOnly = False;
  66. // Timeout(s) value used by AfpIoWait
  67. FiveSecTimeOut.QuadPart = (-5*NUM_100ns_PER_SECOND);
  68. ThreeSecTimeOut.QuadPart = (-3*NUM_100ns_PER_SECOND);
  69. TwoSecTimeOut.QuadPart = (-2*NUM_100ns_PER_SECOND);
  70. OneSecTimeOut.QuadPart = (-1*NUM_100ns_PER_SECOND);
  71. // Default Type Creator. Careful with the initialization here.This has
  72. // to be processor independent
  73. AfpSwmrInitSwmr(&AfpEtcMapLock);
  74. PUTBYTE42BYTE4(&AfpDefaultEtcMap.etc_type, AFP_DEFAULT_ETC_TYPE);
  75. PUTBYTE42BYTE4(&AfpDefaultEtcMap.etc_creator, AFP_DEFAULT_ETC_CREATOR);
  76. PUTBYTE42BYTE4(&AfpDefaultEtcMap.etc_extension, AFP_DEFAULT_ETC_EXT);
  77. // Determine if the machine is little or big endian. This is not currently used
  78. // at all. The idea is to maintain all on-disk databases in little-endian
  79. // format and on big-endian machines, convert on the way-in and out.
  80. i = 0x01020304;
  81. AfpIsMachineLittleEndian = (*(BYTE *)(&i) == 0x04);
  82. AfpServerState = AFP_STATE_IDLE;
  83. AfpServerOptions = AFP_SRVROPT_NONE;
  84. AfpServerMaxSessions = AFP_MAXSESSIONS;
  85. // Check if server needs the Greek fix
  86. {
  87. UNICODE_STRING valueName;
  88. UNICODE_STRING regPath;
  89. HANDLE ParametersHandle = NULL;
  90. PBYTE Storage = NULL;
  91. PKEY_VALUE_FULL_INFORMATION Info = NULL;
  92. ULONG bytesWritten;
  93. PDWORD Value;
  94. OBJECT_ATTRIBUTES ObjectAttributes;
  95. NTSTATUS status;
  96. AfpServerIsGreek = FALSE;
  97. RtlInitUnicodeString (&regPath,
  98. AFP_KEYPATH_SERVER_PARAMS_GREEK);
  99. InitializeObjectAttributes(&ObjectAttributes,
  100. &regPath,
  101. OBJ_CASE_INSENSITIVE,
  102. NULL,
  103. NULL);
  104. status = ZwOpenKey(&ParametersHandle,
  105. KEY_READ,
  106. &ObjectAttributes);
  107. if (NT_SUCCESS(status))
  108. {
  109. RtlInitUnicodeString (&valueName,
  110. AFPREG_VALNAME_GreekServer);
  111. status = ZwQueryValueKey(ParametersHandle,
  112. &valueName,
  113. KeyValueFullInformation,
  114. NULL,
  115. 0,
  116. &bytesWritten);
  117. if (status == STATUS_BUFFER_TOO_SMALL)
  118. {
  119. Storage = (PBYTE)AfpAllocNonPagedMemory (bytesWritten);
  120. Info = (PKEY_VALUE_FULL_INFORMATION)Storage;
  121. status = ZwQueryValueKey(ParametersHandle,
  122. &valueName,
  123. KeyValueFullInformation,
  124. Info,
  125. Storage?bytesWritten:0,
  126. &bytesWritten);
  127. if (NT_SUCCESS(status))
  128. {
  129. if (Info->Type != REG_DWORD)
  130. {
  131. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  132. ("AfpInitializeDataAndSubsystems: Invalid value type=(%ld) expected=(%ld)\n",
  133. Info->Type, REG_DWORD));
  134. }
  135. else
  136. {
  137. Value = (PDWORD)((PBYTE)Info + Info->DataOffset);
  138. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  139. ("AfpInitializeDataAndSubsystems: Read in value for Greek key (%ld)\n",
  140. *Value));
  141. if (*Value == TRUE)
  142. {
  143. AfpServerIsGreek = TRUE;
  144. }
  145. }
  146. }
  147. else
  148. {
  149. AfpServerIsGreek = FALSE;
  150. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  151. ("AfpInitializeDataAndSubsystems: ZwQueryValueKey 2 failed with error (%0lx), Storagesize=(%ld), BytesNeeded=(%ld)\n",
  152. status, sizeof(Storage), bytesWritten));
  153. }
  154. }
  155. else
  156. {
  157. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  158. ("AfpInitializeDataAndSubsystems: ZwQueryValueKey 1 failed with error (%0lx), Storagesize=(%ld), BytesNeeded=(%ld)\n",
  159. status, sizeof(Storage), bytesWritten));
  160. }
  161. }
  162. else
  163. {
  164. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  165. ("AfpInitializeDataAndSubsystems: ZwOpenKey failed with error (%0lx)\n",
  166. status));
  167. }
  168. if (ParametersHandle != NULL)
  169. {
  170. ZwClose(ParametersHandle);
  171. }
  172. if (Storage != NULL)
  173. {
  174. AfpFreeMemory (Storage);
  175. }
  176. status = STATUS_SUCCESS;
  177. }
  178. AfpGetCurrentTimeInMacFormat((PAFPTIME)&AfpServerStatistics.stat_TimeStamp);
  179. //AfpGetCurrentTimeInMacFormat(&AfpSrvrNotifSentTime);
  180. // generate a "unique" signature for our server
  181. pDest = &AfpServerSignature[0];
  182. for (i=0; i<2; i++)
  183. {
  184. pBuffer = AfpGetChallenge();
  185. if (pBuffer)
  186. {
  187. RtlCopyMemory(pDest, pBuffer, MSV1_0_CHALLENGE_LENGTH);
  188. pDest += MSV1_0_CHALLENGE_LENGTH;
  189. AfpFreeMemory(pBuffer);
  190. }
  191. }
  192. #ifdef PROFILING
  193. // Allocate this directly since AfpAllocMemory() uses AfpServerProfile !!!
  194. if ((AfpServerProfile = (PAFP_PROFILE_INFO)ExAllocatePoolWithTag(NonPagedPool,
  195. sizeof(AFP_PROFILE_INFO),
  196. AFP_TAG)) == NULL)
  197. return STATUS_INSUFFICIENT_RESOURCES;
  198. RtlZeroMemory(AfpServerProfile, sizeof(AFP_PROFILE_INFO));
  199. KeQueryPerformanceCounter(&AfpServerProfile->perf_PerfFreq);
  200. #endif
  201. AfpInitStrings();
  202. // Initialize the sub-systems
  203. for (i = 0; i < NUM_INIT_SYSTEMS; i++)
  204. {
  205. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  206. ("AfpInitializeDataAndSubsystems: Initializing s\n",
  207. AfpInitSubSystems[i].InitRoutineName));
  208. if (AfpInitSubSystems[i].InitRoutine != NULL)
  209. {
  210. Status = (*AfpInitSubSystems[i].InitRoutine)();
  211. if (!NT_SUCCESS(Status))
  212. {
  213. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  214. ("AfpInitializeDataAndSubsystems: %s failed %lx\n",
  215. AfpInitSubSystems[i].InitRoutineName, Status));
  216. // One of the subsystems failed to initialize. Deinitialize all
  217. // of them which succeeded.
  218. for (j = 0; j < i; j++)
  219. {
  220. if (AfpInitSubSystems[j].DeInitRoutine != NULL)
  221. {
  222. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  223. ("AfpInitializeDataAndSubsystems: Deinitializing %s\n",
  224. AfpInitSubSystems[j].DeInitRoutineName));
  225. (*AfpInitSubSystems[j].DeInitRoutine)();
  226. }
  227. #if DBG
  228. AfpInitSubSystems[j].Deinitialized = True;
  229. #endif
  230. }
  231. return Status;
  232. }
  233. #if DBG
  234. AfpInitSubSystems[i].Initialized = True;
  235. #endif
  236. }
  237. }
  238. return STATUS_SUCCESS;
  239. }
  240. /*** AfpDeinitializeSubsystems
  241. *
  242. * De-initialize all subsystems.
  243. */
  244. VOID
  245. AfpDeinitializeSubsystems(
  246. VOID
  247. )
  248. {
  249. LONG i;
  250. PAGED_CODE( );
  251. // De-initialize the sub-systems
  252. for (i = 0; i < NUM_INIT_SYSTEMS; i++)
  253. {
  254. if (AfpInitSubSystems[i].DeInitRoutine != NULL)
  255. {
  256. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  257. ("AfpDeinitializeDataAndSubsystems: Deinitializing %s\n",
  258. AfpInitSubSystems[i].DeInitRoutineName));
  259. (*AfpInitSubSystems[i].DeInitRoutine)();
  260. }
  261. #if DBG
  262. AfpInitSubSystems[i].Deinitialized = True;
  263. #endif
  264. }
  265. }
  266. /*** AfpSetServerStatus
  267. *
  268. * Set the Server status block via afpSpSetStatus. This is called in once at
  269. * server startup and anytime a change in server status makes this necessary.
  270. * By now, ServerSetInfo() has happened and it has been validated that all
  271. * paramters are kosher.
  272. *
  273. * LOCKS: AfpServerGlobalLock (SPIN)
  274. */
  275. AFPSTATUS
  276. AfpSetServerStatus(
  277. IN VOID
  278. )
  279. {
  280. KIRQL OldIrql;
  281. AFPSTATUS Status=STATUS_SUCCESS;
  282. AFPSTATUS Status2;
  283. struct _StatusHeader
  284. {
  285. BYTE _MachineString[2]; // These are offsets relative to the struct
  286. BYTE _AfpVersions[2]; // ---------- do ------------
  287. BYTE _UAMs[2]; // ---------- do ------------
  288. BYTE _VolumeIcon[2]; // ---------- do ------------
  289. BYTE _Flags[2]; // Server Flags
  290. // The actual strings start here
  291. } *pStatusHeader;
  292. PASCALSTR pStr;
  293. PBYTE pNumUamPtr;
  294. LONG Size;
  295. USHORT Flags;
  296. BOOLEAN GuestAllowed = False,
  297. ClearTextAllowed = False,
  298. NativeAppleUamSupported = False,
  299. MicrosoftUamSupported = False,
  300. AllowSavePass = False;
  301. BYTE CountOfUams;
  302. PBYTE pSignOffset;
  303. PBYTE pNetAddrOffset;
  304. DWORD IpAddrCount=0;
  305. PBYTE IpAddrBlob=NULL;
  306. NTSTATUS ntStatus;
  307. // Assert that all the info that we can possibly stuff in can indeed fit
  308. // in the buffer that we'll allocate
  309. // Allocate a buffer to fill the status information in. This will be
  310. // freed by AfpSpSetStatus(), this can be freed. We do not know up front
  311. // how much we'll need. Err on the safe side
  312. if ((pStatusHeader = (struct _StatusHeader *)
  313. AfpAllocZeroedNonPagedMemory(ASP_MAX_STATUS_BUF)) == NULL)
  314. {
  315. return STATUS_INSUFFICIENT_RESOURCES;
  316. }
  317. //
  318. // first, find out if we have any TCPIP addresses
  319. //
  320. ntStatus = DsiGetIpAddrBlob(&IpAddrCount, &IpAddrBlob);
  321. if (!NT_SUCCESS(ntStatus))
  322. {
  323. AfpFreeMemory(pStatusHeader);
  324. DBGPRINT(DBG_COMP_STACKIF, DBG_LEVEL_ERR,
  325. ("AfpSetServerStatus: DsiGetIpAddrBlob failed %lx\n",ntStatus));
  326. return STATUS_INSUFFICIENT_RESOURCES;
  327. }
  328. ACQUIRE_SPIN_LOCK(&AfpServerGlobalLock, &OldIrql);
  329. GuestAllowed = (AfpServerOptions & AFP_SRVROPT_GUESTLOGONALLOWED) ?
  330. True : False;
  331. ClearTextAllowed = (AfpServerOptions & AFP_SRVROPT_CLEARTEXTLOGONALLOWED) ?
  332. True : False;
  333. MicrosoftUamSupported = (AfpServerOptions & AFP_SRVROPT_MICROSOFT_UAM)?
  334. True : False;
  335. NativeAppleUamSupported = (AfpServerOptions & AFP_SRVROPT_NATIVEAPPLEUAM) ?
  336. True : False;
  337. if (!ClearTextAllowed && !MicrosoftUamSupported && !NativeAppleUamSupported)
  338. {
  339. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  340. ("AfpSetServerStatus: got to enable at least one UAM! Failing request\n"));
  341. RELEASE_SPIN_LOCK(&AfpServerGlobalLock, OldIrql);
  342. AfpFreeMemory(pStatusHeader);
  343. if (IpAddrBlob)
  344. {
  345. AfpFreeMemory(IpAddrBlob);
  346. }
  347. return(STATUS_INVALID_PARAMETER);
  348. }
  349. Size = sizeof(struct _StatusHeader) + // Status header
  350. AfpServerName.Length + 1 + // Server Name
  351. AFP_MACHINE_TYPE_LEN + 1 + // Machine String
  352. AfpVersion20.Length + 1 + // Afp Versions
  353. AfpVersion21.Length + 1 +
  354. ICONSIZE_ICN; // Volume Icon & Mask
  355. ASSERT(Size <= ASP_MAX_STATUS_BUF);
  356. // Specify our capabilities
  357. Flags = SRVRINFO_SUPPORTS_COPYFILE |
  358. SRVRINFO_SUPPORTS_CHGPASSWD |
  359. SRVRINFO_SUPPORTS_SERVERMSG |
  360. SRVRINFO_SUPPORTS_SRVSIGN |
  361. SRVRINFO_SUPPORTS_SRVNOTIFY |
  362. #ifdef CLIENT36
  363. SRVRINFO_SUPPORTS_MGETREQS |
  364. #endif
  365. ((AfpServerOptions & AFP_SRVROPT_ALLOWSAVEDPASSWORD) ?
  366. 0: SRVRINFO_DISALLOW_SAVEPASS);
  367. // do we have any ipaddresses?
  368. if (IpAddrCount > 0)
  369. {
  370. Flags |= SRVRINFO_SUPPORTS_TCPIP;
  371. }
  372. PUTSHORT2SHORT(&pStatusHeader->_Flags, Flags);
  373. // Copy the Server Name
  374. pStr = (PASCALSTR)((PBYTE)pStatusHeader + sizeof(struct _StatusHeader));
  375. pStr->ps_Length = (BYTE)(AfpServerName.Length);
  376. RtlCopyMemory(pStr->ps_String, AfpServerName.Buffer, AfpServerName.Length);
  377. (PBYTE)pStr += AfpServerName.Length + 1;
  378. // do we need a pad byte?
  379. if (((PBYTE)pStr - (PBYTE)pStatusHeader) % 2 == 1)
  380. {
  381. *(PBYTE)pStr = 0;
  382. ((PBYTE)pStr)++;
  383. }
  384. // skip past the Signature Offset field: we'll store the value later
  385. pSignOffset = (PBYTE)pStr;
  386. ((PBYTE)pStr) += 2;
  387. if ((IpAddrCount > 0) || (AfpServerBoundToAsp))
  388. {
  389. // skip past the Network Address Count Offset: we'll store the value later
  390. pNetAddrOffset = (PBYTE)pStr;
  391. ((PBYTE)pStr) += 2;
  392. }
  393. else
  394. {
  395. DBGPRINT(DBG_COMP_STACKIF, DBG_LEVEL_ERR,
  396. ("AfpSetServerStatus: Neither TCP nor Appletalk is active!!\n"));
  397. }
  398. PUTSHORT2SHORT(pStatusHeader->_MachineString,
  399. (USHORT)((PBYTE)pStr - (PBYTE)pStatusHeader));
  400. // Copy the machine name string
  401. pStr->ps_Length = (BYTE) AFP_MACHINE_TYPE_LEN;
  402. RtlCopyMemory(pStr->ps_String, AFP_MACHINE_TYPE_STR, AFP_MACHINE_TYPE_LEN);
  403. (PBYTE)pStr += AFP_MACHINE_TYPE_LEN + 1;
  404. // Copy the Afp Version Strings
  405. PUTSHORT2SHORT(pStatusHeader->_AfpVersions,
  406. (USHORT)((PBYTE)pStr - (PBYTE)pStatusHeader));
  407. *((PBYTE)pStr)++ = AFP_NUM_VERSIONS;
  408. pStr->ps_Length = (BYTE)AfpVersion20.Length;
  409. RtlCopyMemory(pStr->ps_String, AfpVersion20.Buffer, AfpVersion20.Length);
  410. (PBYTE)pStr += AfpVersion20.Length + 1;
  411. pStr->ps_Length = (BYTE)AfpVersion21.Length;
  412. RtlCopyMemory(pStr->ps_String, AfpVersion21.Buffer, AfpVersion21.Length);
  413. (PBYTE)pStr += AfpVersion21.Length + 1;
  414. pStr->ps_Length = (BYTE)AfpVersion22.Length;
  415. RtlCopyMemory(pStr->ps_String, AfpVersion22.Buffer, AfpVersion22.Length);
  416. (PBYTE)pStr += AfpVersion22.Length + 1;
  417. // We always support at least one UAM!
  418. PUTSHORT2SHORT(pStatusHeader->_UAMs, (USHORT)((PBYTE)pStr - (PBYTE)pStatusHeader));
  419. pNumUamPtr = (PBYTE)pStr;
  420. ((PBYTE)pStr)++;
  421. CountOfUams = 0;
  422. if (GuestAllowed)
  423. {
  424. pStr->ps_Length = (BYTE)AfpUamGuest.Length;
  425. RtlCopyMemory(pStr->ps_String, AfpUamGuest.Buffer,
  426. AfpUamGuest.Length);
  427. (PBYTE)pStr += AfpUamGuest.Length + 1;
  428. CountOfUams++;
  429. Size += (AfpUamGuest.Length + 1);
  430. }
  431. else
  432. {
  433. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  434. ("AfpSetServerStatus: Guest is disabled\n"));
  435. }
  436. if (ClearTextAllowed)
  437. {
  438. pStr->ps_Length = (BYTE)AfpUamClearText.Length;
  439. RtlCopyMemory(pStr->ps_String, AfpUamClearText.Buffer,
  440. AfpUamClearText.Length);
  441. (PBYTE)pStr += AfpUamClearText.Length + 1;
  442. CountOfUams++;
  443. Size += (AfpUamClearText.Length + 1);
  444. }
  445. else
  446. {
  447. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  448. ("AfpSetServerStatus: ClearText UAM is NOT configured\n"));
  449. }
  450. if (MicrosoftUamSupported)
  451. {
  452. // copy in "Microsoft V1.0" string
  453. pStr->ps_Length = (BYTE)AfpUamCustomV1.Length;
  454. RtlCopyMemory(pStr->ps_String, AfpUamCustomV1.Buffer, AfpUamCustomV1.Length);
  455. (PBYTE)pStr += AfpUamCustomV1.Length + 1;
  456. CountOfUams++;
  457. Size += (AfpUamCustomV1.Length + 1 + 1);
  458. // copy in "Microsoft V2.0" string
  459. pStr->ps_Length = (BYTE)AfpUamCustomV2.Length;
  460. RtlCopyMemory(pStr->ps_String, AfpUamCustomV2.Buffer, AfpUamCustomV2.Length);
  461. (PBYTE)pStr += AfpUamCustomV2.Length + 1;
  462. CountOfUams++;
  463. Size += (AfpUamCustomV2.Length + 1 + 1);
  464. // copy in "Microsoft V3.0" string
  465. pStr->ps_Length = (BYTE)AfpUamCustomV3.Length;
  466. RtlCopyMemory(pStr->ps_String, AfpUamCustomV3.Buffer, AfpUamCustomV3.Length);
  467. (PBYTE)pStr += AfpUamCustomV3.Length + 1;
  468. CountOfUams++;
  469. Size += (AfpUamCustomV3.Length + 1 + 1);
  470. }
  471. else
  472. {
  473. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  474. ("AfpSetServerStatus: Microsoft UAM is NOT configured\n"));
  475. }
  476. if (NativeAppleUamSupported)
  477. {
  478. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  479. ("AfpSetServerStatus: Apple's native UAM is configured\n"));
  480. pStr->ps_Length = (BYTE)AfpUamApple.Length;
  481. RtlCopyMemory(pStr->ps_String, AfpUamApple.Buffer, AfpUamApple.Length);
  482. (PBYTE)pStr += AfpUamApple.Length + 1;
  483. CountOfUams++;
  484. Size += (AfpUamApple.Length + 1 + 1);
  485. // 2-way not included for now
  486. #if ALLOW_2WAY_ASWELL
  487. pStr->ps_Length = (BYTE)AfpUamApple2Way.Length;
  488. RtlCopyMemory(pStr->ps_String, AfpUamApple2Way.Buffer, AfpUamApple2Way.Length);
  489. (PBYTE)pStr += AfpUamApple2Way.Length + 1;
  490. CountOfUams++;
  491. Size += (AfpUamApple2Way.Length + 1 + 1);
  492. #endif
  493. }
  494. // how many UAM's are we telling the client we support
  495. *pNumUamPtr = CountOfUams;
  496. // now we know where Server signature goes: write the offset
  497. PUTSHORT2SHORT(pSignOffset,(USHORT)((PBYTE)pStr - (PBYTE)pStatusHeader));
  498. // copy the Server signature
  499. RtlCopyMemory((PBYTE)pStr, AfpServerSignature, 16);
  500. ((PBYTE)pStr) += 16;
  501. //
  502. // if we have network address(es), send that info over!
  503. //
  504. if ((IpAddrCount > 0) || (AfpServerBoundToAsp))
  505. {
  506. // now we know where Network Address Count Offset goes: write the offset
  507. PUTSHORT2SHORT(pNetAddrOffset,(USHORT)((PBYTE)pStr - (PBYTE)pStatusHeader));
  508. // how many addresses are we returning?
  509. *(PBYTE)pStr = ((BYTE)IpAddrCount) + ((AfpServerBoundToAsp) ? 1 : 0);
  510. ((PBYTE)pStr)++;
  511. // copy the ipaddresses, if bound
  512. if (IpAddrCount > 0)
  513. {
  514. // copy the blob containing the Length, Tag and Ipaddress info
  515. RtlCopyMemory((PBYTE)pStr, IpAddrBlob, IpAddrCount*DSI_NETWORK_ADDR_LEN);
  516. ((PBYTE)pStr) += (IpAddrCount*DSI_NETWORK_ADDR_LEN);
  517. }
  518. // now copy the appletalk addres, if bound
  519. if (AfpServerBoundToAsp)
  520. {
  521. *(PBYTE)pStr = DSI_NETWORK_ADDR_LEN;
  522. ((PBYTE)pStr)++;
  523. *(PBYTE)pStr = ATALK_NETWORK_ADDR_ATKTAG;
  524. ((PBYTE)pStr)++;
  525. PUTDWORD2DWORD((PBYTE)pStr, AfpAspEntries.asp_AtalkAddr.Address);
  526. ((PBYTE)pStr) += sizeof(DWORD);
  527. }
  528. }
  529. // Now get the volume icon, if any
  530. if (AfpServerIcon != NULL)
  531. {
  532. RtlCopyMemory((PBYTE)pStr, AfpServerIcon, ICONSIZE_ICN);
  533. PUTSHORT2SHORT(pStatusHeader->_VolumeIcon,
  534. (USHORT)((PBYTE)pStr - (PBYTE)pStatusHeader));
  535. }
  536. else PUTSHORT2SHORT(pStatusHeader->_VolumeIcon, 0);
  537. RELEASE_SPIN_LOCK(&AfpServerGlobalLock, OldIrql);
  538. if (AfpServerBoundToAsp)
  539. {
  540. Status = AfpSpSetAspStatus((PBYTE)pStatusHeader, Size);
  541. }
  542. if (AfpServerBoundToTcp)
  543. {
  544. Status2 = AfpSpSetDsiStatus((PBYTE)pStatusHeader, Size);
  545. // as long as one succeeds, we want the call to succeed
  546. if (!NT_SUCCESS(Status))
  547. {
  548. Status = Status2;
  549. }
  550. }
  551. AfpFreeMemory(pStatusHeader);
  552. if (IpAddrBlob)
  553. {
  554. AfpFreeMemory(IpAddrBlob);
  555. }
  556. return Status;
  557. }
  558. /*** AfpAdmWServerSetInfo
  559. *
  560. * This routine sets various server globals with data supplied by the admin. The
  561. * following server globals are set by this routine:
  562. *
  563. * - Server Name
  564. * - Maximum Sessions (valid values are 1 through AFP_MAXSESSIONS)
  565. * - Server Options (i.e. guest logon allowed, etc.)
  566. * - Server Login Message
  567. * - Maximum paged and non-paged memory limits
  568. * - Macintosh Code Page File
  569. *
  570. * The server name and memory limits can only be changed while the server
  571. * is stopped. The Macintosh Code Page File may only be set ONE time after
  572. * the AFP server driver is loaded. i.e. if you want to reset the codepage,
  573. * the service must unload the AFP server, then reload it.
  574. *
  575. * This routine must execute in the context of the worker thread, since we
  576. * need to map the Macintosh CodePage into the server's virtual memory
  577. * space, not the client's.
  578. *
  579. * LOCKS: AfpServerGlobalLock (SPIN)
  580. */
  581. AFPSTATUS
  582. AfpAdmWServerSetInfo(
  583. IN OUT PVOID InBuf OPTIONAL,
  584. IN LONG OutBufLen OPTIONAL,
  585. OUT PVOID OutBuf OPTIONAL
  586. )
  587. {
  588. KIRQL OldIrql;
  589. AFPSTATUS rc;
  590. ANSI_STRING amsg, aname;
  591. UNICODE_STRING uname, umsg, oldloginmsgU;
  592. DWORD parmflags = ((PSETINFOREQPKT)InBuf)->sirqp_parmnum;
  593. PAFP_SERVER_INFO pSvrInfo = (PAFP_SERVER_INFO)((PCHAR)InBuf+sizeof(SETINFOREQPKT));
  594. BOOLEAN setstatus = False;
  595. BOOLEAN locktaken = False;
  596. BOOLEAN servernameexists = False;
  597. amsg.Length = 0;
  598. amsg.MaximumLength = 0;
  599. amsg.Buffer = NULL;
  600. aname.Length = 0;
  601. aname.MaximumLength = 0;
  602. aname.Buffer = NULL;
  603. AfpSetEmptyUnicodeString(&umsg, 0, NULL);
  604. AfpSetEmptyUnicodeString(&oldloginmsgU, 0, NULL);
  605. /* Validate all limits */
  606. if ((parmflags & ~AFP_SERVER_PARMNUM_ALL) ||
  607. ((parmflags & AFP_SERVER_PARMNUM_OPTIONS) &&
  608. (pSvrInfo->afpsrv_options & ~AFP_SRVROPT_ALL)) ||
  609. ((parmflags & AFP_SERVER_PARMNUM_MAX_SESSIONS) &&
  610. ((pSvrInfo->afpsrv_max_sessions > AFP_MAXSESSIONS) ||
  611. (pSvrInfo->afpsrv_max_sessions == 0))))
  612. {
  613. DBGPRINT(DBG_COMP_ADMINAPI_SRV, DBG_LEVEL_ERR,
  614. ("AfpAdmWServerSetInfo: invalid parm!\n"));
  615. return AFPERR_InvalidParms_MaxSessions;
  616. }
  617. if (parmflags == AFP_SERVER_GUEST_ACCT_NOTIFY)
  618. {
  619. AfpServerOptions ^= AFP_SRVROPT_GUESTLOGONALLOWED;
  620. DBGPRINT(DBG_COMP_ADMINAPI_SRV, DBG_LEVEL_ERR,
  621. ("AfpAdmWServerSetInfo: Guest account is now %s\n",
  622. (AfpServerOptions & AFP_SRVROPT_GUESTLOGONALLOWED)? "enabled":"disabled"));
  623. AfpSetServerStatus();
  624. return(STATUS_SUCCESS);
  625. }
  626. if (parmflags & AFP_SERVER_PARMNUM_CODEPAGE)
  627. {
  628. // You may only set the Macintosh CodePage once
  629. if (AfpMacCPBaseAddress != NULL)
  630. return AFPERR_InvalidServerState;
  631. else
  632. {
  633. rc = AfpGetMacCodePage(pSvrInfo->afpsrv_codepage);
  634. if (!NT_SUCCESS(rc))
  635. {
  636. return AFPERR_CodePage;
  637. }
  638. }
  639. }
  640. if (parmflags & AFP_SERVER_PARMNUM_LOGINMSG)
  641. {
  642. RtlInitUnicodeString(&umsg, pSvrInfo->afpsrv_login_msg);
  643. if (umsg.Length == 0)
  644. {
  645. umsg.Buffer = NULL;
  646. }
  647. amsg.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(&umsg);
  648. amsg.Length = amsg.MaximumLength - 1;
  649. if (amsg.Length > AFP_MESSAGE_LEN)
  650. {
  651. return AFPERR_InvalidParms_LoginMsg;
  652. }
  653. if (amsg.Length != 0)
  654. {
  655. if ((umsg.Buffer =
  656. (LPWSTR)AfpAllocPagedMemory(umsg.Length+1)) == NULL)
  657. {
  658. return STATUS_INSUFFICIENT_RESOURCES;
  659. }
  660. if ((amsg.Buffer =
  661. (PCHAR)AfpAllocNonPagedMemory(amsg.MaximumLength)) == NULL)
  662. {
  663. AfpFreeMemory(umsg.Buffer);
  664. return STATUS_INSUFFICIENT_RESOURCES;
  665. }
  666. RtlCopyMemory(umsg.Buffer, pSvrInfo->afpsrv_login_msg, umsg.Length);
  667. rc = RtlUnicodeStringToAnsiString(&amsg, &umsg, False);
  668. if (!NT_SUCCESS(rc))
  669. {
  670. AfpFreeMemory(amsg.Buffer);
  671. AfpFreeMemory(umsg.Buffer);
  672. return AFPERR_InvalidParms;
  673. }
  674. else AfpConvertHostAnsiToMacAnsi(&amsg);
  675. }
  676. }
  677. do
  678. {
  679. if (parmflags & AFP_SERVER_PARMNUM_NAME)
  680. {
  681. RtlInitUnicodeString(&uname,pSvrInfo->afpsrv_name);
  682. aname.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(&uname);
  683. aname.Length = aname.MaximumLength - 1;
  684. if ((aname.Length == 0) || (aname.Length > AFP_SERVERNAME_LEN))
  685. {
  686. DBGPRINT(DBG_COMP_ADMINAPI_SRV, DBG_LEVEL_ERR,
  687. ("AfpAdmWServerSetInfo: bad name length %d, rejecting\n,aname.Length"));
  688. rc = AFPERR_InvalidServerName_Length;
  689. break;
  690. }
  691. if ((aname.Buffer = AfpAllocNonPagedMemory(aname.MaximumLength)) == NULL)
  692. {
  693. DBGPRINT(DBG_COMP_ADMINAPI_SRV, DBG_LEVEL_ERR,
  694. ("AfpAdmWServerSetInfo: malloc failed on name change\n"));
  695. rc = STATUS_INSUFFICIENT_RESOURCES;
  696. break;
  697. }
  698. rc = AfpConvertStringToAnsi(&uname, &aname);
  699. if (!NT_SUCCESS(rc))
  700. {
  701. rc = AFPERR_InvalidServerName;
  702. DBGPRINT(DBG_COMP_ADMINAPI_SRV, DBG_LEVEL_ERR,
  703. ("AfpAdmWServerSetInfo: AfpConvertStringToAnsi failed %lx\n",rc));
  704. break;
  705. }
  706. }
  707. rc = STATUS_SUCCESS;
  708. //
  709. // take the global data lock and set the new information
  710. //
  711. ACQUIRE_SPIN_LOCK(&AfpServerGlobalLock, &OldIrql);
  712. locktaken = True;
  713. // Validate if we are in the right state to receive some of the
  714. // parameters
  715. if ((AfpServerState != AFP_STATE_IDLE) &&
  716. (parmflags & (AFP_SERVER_PARMNUM_PAGEMEMLIM |
  717. AFP_SERVER_PARMNUM_NONPAGEMEMLIM)))
  718. {
  719. DBGPRINT(DBG_COMP_ADMINAPI_SRV, DBG_LEVEL_ERR,
  720. ("AfpAdmWServerSetInfo: failure at 1\n"));
  721. rc = AFPERR_InvalidServerState;
  722. break;
  723. }
  724. else if ((AfpServerState == AFP_STATE_IDLE) &&
  725. (parmflags & (AFP_SERVER_PARMNUM_NAME |
  726. AFP_SERVER_PARMNUM_PAGEMEMLIM |
  727. AFP_SERVER_PARMNUM_NONPAGEMEMLIM)) !=
  728. (DWORD)(AFP_SERVER_PARMNUM_NAME |
  729. AFP_SERVER_PARMNUM_PAGEMEMLIM |
  730. AFP_SERVER_PARMNUM_NONPAGEMEMLIM))
  731. {
  732. DBGPRINT(DBG_COMP_ADMINAPI_SRV, DBG_LEVEL_ERR,
  733. ("AfpAdmWServerSetInfo: failure at 2\n"));
  734. rc = AFPERR_InvalidParms;
  735. break;
  736. }
  737. if (parmflags & (AFP_SERVER_PARMNUM_PAGEMEMLIM |
  738. AFP_SERVER_PARMNUM_NONPAGEMEMLIM))
  739. {
  740. AfpPagedPoolLimit = pSvrInfo->afpsrv_max_paged_mem * 1024;
  741. AfpNonPagedPoolLimit = pSvrInfo->afpsrv_max_nonpaged_mem * 1024;
  742. }
  743. if (parmflags & AFP_SERVER_PARMNUM_NAME)
  744. {
  745. setstatus = ((AfpServerState == AFP_STATE_RUNNING) ||
  746. (AfpServerState == AFP_STATE_START_PENDING));
  747. rc = STATUS_SUCCESS;
  748. if (AfpServerName.Buffer == NULL)
  749. {
  750. AfpServerName = aname;
  751. }
  752. else
  753. {
  754. servernameexists = True;
  755. }
  756. // Re-register the name only if the service up and running
  757. // No point registering the name on a service not functioning.
  758. // This causes problems as we falsely advertise
  759. // the AFP server in the browser when it is not really available.
  760. if (setstatus)
  761. {
  762. // deregister the old name, if one exists
  763. if ((AfpServerBoundToAsp) && (servernameexists))
  764. {
  765. RELEASE_SPIN_LOCK(&AfpServerGlobalLock,OldIrql);
  766. rc = AfpSpRegisterName(&AfpServerName, False);
  767. ACQUIRE_SPIN_LOCK(&AfpServerGlobalLock, &OldIrql);
  768. AfpFreeMemory(AfpServerName.Buffer);
  769. }
  770. AfpServerName = aname;
  771. // if deregister succeeded, register the new name
  772. if ((NT_SUCCESS(rc)) && (AfpServerBoundToAsp))
  773. {
  774. RELEASE_SPIN_LOCK(&AfpServerGlobalLock,OldIrql);
  775. rc = AfpSpRegisterName(&AfpServerName, True);
  776. ACQUIRE_SPIN_LOCK(&AfpServerGlobalLock, &OldIrql);
  777. }
  778. }
  779. }
  780. if (parmflags & AFP_SERVER_PARMNUM_OPTIONS)
  781. {
  782. if (pSvrInfo->afpsrv_options & AFP_SRVROPT_STANDALONE)
  783. {
  784. // Server is NtProductServer or NtProductWinNt
  785. AfpServerIsStandalone = True;
  786. if (AfpSidNone == NULL)
  787. {
  788. // If we didn't initialize the AfpSidNone during
  789. // AfpInitSidOffsets then the service either sent
  790. // us bogus offsets, or this bit is bogus
  791. rc = AFPERR_InvalidParms;
  792. break;
  793. }
  794. pSvrInfo->afpsrv_options &= ~AFP_SRVROPT_STANDALONE;
  795. }
  796. if (!setstatus)
  797. {
  798. setstatus =
  799. (AfpServerOptions ^ pSvrInfo->afpsrv_options) ? True : False;
  800. setstatus = setstatus &&
  801. ((AfpServerState == AFP_STATE_RUNNING) ||
  802. (AfpServerState == AFP_STATE_START_PENDING));
  803. }
  804. AfpServerOptions = pSvrInfo->afpsrv_options;
  805. }
  806. if (parmflags & AFP_SERVER_PARMNUM_LOGINMSG)
  807. {
  808. if (AfpLoginMsg.Buffer != NULL)
  809. {
  810. AfpFreeMemory(AfpLoginMsg.Buffer);
  811. }
  812. AfpLoginMsg = amsg;
  813. oldloginmsgU = AfpLoginMsgU;
  814. AfpLoginMsgU = umsg;
  815. }
  816. if (parmflags & AFP_SERVER_PARMNUM_MAX_SESSIONS)
  817. {
  818. if (AfpServerMaxSessions != pSvrInfo->afpsrv_max_sessions)
  819. {
  820. BOOLEAN KillSome;
  821. KillSome = (AfpServerMaxSessions > pSvrInfo->afpsrv_max_sessions);
  822. AfpServerMaxSessions = pSvrInfo->afpsrv_max_sessions;
  823. RELEASE_SPIN_LOCK(&AfpServerGlobalLock,OldIrql);
  824. locktaken = False;
  825. }
  826. }
  827. } while (False);
  828. if (locktaken)
  829. {
  830. RELEASE_SPIN_LOCK(&AfpServerGlobalLock,OldIrql);
  831. }
  832. if (!NT_SUCCESS(rc))
  833. {
  834. DBGPRINT(DBG_COMP_ADMINAPI_SRV, DBG_LEVEL_ERR,
  835. ("AfpAdmWServerSetInfo: returning %lx\n",rc));
  836. if (amsg.Buffer != NULL)
  837. {
  838. AfpFreeMemory(amsg.Buffer);
  839. }
  840. if (aname.Buffer != NULL)
  841. {
  842. if (AfpServerName.Buffer == aname.Buffer)
  843. {
  844. AfpServerName.Buffer = NULL;
  845. AfpServerName.MaximumLength = 0;
  846. AfpServerName.Length = 0;
  847. }
  848. AfpFreeMemory(aname.Buffer);
  849. }
  850. }
  851. else if (setstatus)
  852. {
  853. return (AfpSetServerStatus());
  854. }
  855. if (oldloginmsgU.Buffer != NULL)
  856. AfpFreeMemory(oldloginmsgU.Buffer);
  857. return rc;
  858. }
  859. /*** AfpCreateNewThread
  860. *
  861. * Create either an admin or a worker thread.
  862. */
  863. NTSTATUS FASTCALL
  864. AfpCreateNewThread(
  865. IN VOID (*ThreadFunc)(IN PVOID pContext),
  866. IN LONG ThreadNum
  867. )
  868. {
  869. NTSTATUS Status;
  870. HANDLE FspThread;
  871. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  872. ("AfpCreateNewThread: Creating thread %lx\n", ThreadFunc));
  873. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  874. ASSERT ((AfpServerState == AFP_STATE_IDLE) ||
  875. (ThreadNum < AFP_MAX_THREADS) && (AfpNumThreads >= AFP_MIN_THREADS));
  876. Status = PsCreateSystemThread(&FspThread,
  877. THREAD_ALL_ACCESS,
  878. NULL,
  879. NtCurrentProcess(),
  880. NULL,
  881. ThreadFunc,
  882. (PVOID)((ULONG_PTR)ThreadNum));
  883. if (!NT_SUCCESS(Status))
  884. {
  885. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  886. ("AfpCreateNewThread: Cannot create threads %lx\n", Status));
  887. AFPLOG_DDERROR(AFPSRVMSG_CREATE_THREAD, Status, NULL, 0, NULL);
  888. }
  889. else
  890. {
  891. // Close the handle to the thread so that it goes away when the
  892. // thread terminates
  893. NtClose(FspThread);
  894. }
  895. return Status;
  896. }
  897. /*** AfpQueueWorkItem
  898. *
  899. * Queue a work item to the worker thread.
  900. *
  901. * LOCKS: AfpStatisticsLock
  902. */
  903. VOID FASTCALL
  904. AfpQueueWorkItem(
  905. IN PWORK_ITEM pWI
  906. )
  907. {
  908. KIRQL OldIrql;
  909. ACQUIRE_SPIN_LOCK(&AfpStatisticsLock, &OldIrql);
  910. AfpServerStatistics.stat_CurrQueueLength ++;
  911. #ifdef PROFILING
  912. AfpServerProfile->perf_QueueCount ++;
  913. #endif
  914. if (AfpServerStatistics.stat_CurrQueueLength > AfpServerStatistics.stat_MaxQueueLength)
  915. AfpServerStatistics.stat_MaxQueueLength++;
  916. RELEASE_SPIN_LOCK(&AfpStatisticsLock, OldIrql);
  917. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  918. ("AfpQueueWorkItem: Queueing %lx (%lx)\n",
  919. pWI->wi_Worker, pWI->wi_Context));
  920. INTERLOCKED_ADD_ULONG(&AfpWorkerRequests, 1, &AfpServerGlobalLock);
  921. // Insert work item in worker queue
  922. KeInsertQueue(&AfpWorkerQueue, &pWI->wi_List);
  923. }
  924. /*** AfpWorkerThread
  925. *
  926. * This thread is used to do all the work that is queued to the FSP.
  927. *
  928. * We want to dynamically create and destroy threads so that we can
  929. * optimize the number of threads used. The number of threads range
  930. * from AFP_MIN_THREADS - AFP_MAX_THREADS.
  931. * A new thread is created if the number of entries in the queue
  932. * exceeds AFP_THREAD_THRESHOLD_REQ. A thread is terminated if the request count
  933. * drops below AFP_THREAD_THRESHOLD_IDLE.
  934. */
  935. VOID
  936. AfpWorkerThread(
  937. IN PVOID pContext
  938. )
  939. {
  940. NTSTATUS Status;
  941. PLIST_ENTRY pList;
  942. PWORK_ITEM pWI;
  943. LONG IdleCount = 0;
  944. LONG ThreadNum, CreateId;
  945. ULONG BasePriority = THREAD_BASE_PRIORITY_MAX;
  946. KIRQL OldIrql;
  947. BOOLEAN Release = False;
  948. BOOLEAN ReasonToLive = True;
  949. ThreadNum = (LONG)(LONG_PTR)pContext;
  950. ASSERT (AfpThreadState[ThreadNum] == AFP_THREAD_STARTED);
  951. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  952. ("AfpWorkerThread: Thread %ld Starting. NumThreads %ld\n",
  953. ThreadNum, AfpNumThreads));
  954. // Update the thread statistics.
  955. ACQUIRE_SPIN_LOCK(&AfpStatisticsLock, &OldIrql);
  956. AfpServerStatistics.stat_CurrThreadCount ++;
  957. if (AfpServerStatistics.stat_CurrThreadCount > AfpServerStatistics.stat_MaxThreadCount)
  958. AfpServerStatistics.stat_MaxThreadCount = AfpServerStatistics.stat_CurrThreadCount;
  959. RELEASE_SPIN_LOCK(&AfpStatisticsLock, OldIrql);
  960. // Set the thread base priority to 'foreground'
  961. NtSetInformationThread( NtCurrentThread(),
  962. ThreadBasePriority,
  963. &BasePriority,
  964. sizeof(BasePriority));
  965. // Disable hard-error pop-ups for this thread
  966. IoSetThreadHardErrorMode( FALSE );
  967. AfpThreadPtrsW[ThreadNum] = PsGetCurrentThread();
  968. do
  969. {
  970. AfpThreadState[ThreadNum] = AFP_THREAD_WAITING;
  971. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  972. ("AfpWorkerThread: About to block\n"));
  973. // DELALLOCQUEUE: unrem the #if 0 part
  974. #if 0
  975. //
  976. // first check if there is someone waiting to get buffer allocation:
  977. // let's deal with them first, so some connection doesn't get "blocked"
  978. // because transport underneath doesn't have buffer
  979. //
  980. pList = KeRemoveQueue(&AfpDelAllocQueue, KernelMode, NULL);
  981. if (pList != NULL)
  982. {
  983. AfpThreadState[ThreadNum] = AFP_THREAD_BUSY;
  984. pWI = CONTAINING_RECORD(pList, WORK_ITEM, wi_List);
  985. // Call the worker
  986. (pWI->wi_Worker)(pWI->wi_Context);
  987. IdleCount = 0;
  988. continue;
  989. }
  990. #endif
  991. pList = KeRemoveQueue(&AfpWorkerQueue, KernelMode, &ThreeSecTimeOut);
  992. Status = STATUS_SUCCESS;
  993. if ((NTSTATUS)((ULONG_PTR)pList) == STATUS_TIMEOUT)
  994. Status = STATUS_TIMEOUT;
  995. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  996. ("AfpWorkerThread: %s\n",
  997. (Status == STATUS_SUCCESS) ? "Another Work item" : "Timer - check"));
  998. if (Status == STATUS_SUCCESS)
  999. {
  1000. pWI = CONTAINING_RECORD(pList, WORK_ITEM, wi_List);
  1001. if (pWI == &AfpTerminateThreadWI)
  1002. {
  1003. BOOLEAN Requeue;
  1004. ReasonToLive = False;
  1005. ACQUIRE_SPIN_LOCK(&AfpServerGlobalLock, &OldIrql);
  1006. AfpNumThreads --;
  1007. Requeue = (AfpNumThreads != 0);
  1008. RELEASE_SPIN_LOCK(&AfpServerGlobalLock, OldIrql);
  1009. AfpThreadState[ThreadNum] = AFP_THREAD_DEAD;
  1010. if (!Requeue)
  1011. {
  1012. ASSERT((AfpServerState == AFP_STATE_STOPPED) ||
  1013. (AfpServerState == AFP_STATE_IDLE));
  1014. Release = True;
  1015. }
  1016. else
  1017. {
  1018. // Re-queue this work-item so that other threads can die too !!!
  1019. KeInsertQueue(&AfpWorkerQueue, &AfpTerminateThreadWI.wi_List);
  1020. }
  1021. break;
  1022. }
  1023. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  1024. ("AfpWorkerThread: Dispatching %lx (%lx)\n",
  1025. pWI->wi_Worker, pWI->wi_Context));
  1026. AfpThreadState[ThreadNum] = AFP_THREAD_BUSY;
  1027. #if DBG
  1028. AfpThreadDispCount[ThreadNum] ++;
  1029. #endif
  1030. // Call the worker
  1031. (pWI->wi_Worker)(pWI->wi_Context);
  1032. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  1033. INTERLOCKED_ADD_ULONG((PLONG)(&AfpServerStatistics.stat_CurrQueueLength),
  1034. (ULONG)-1,
  1035. &AfpStatisticsLock);
  1036. INTERLOCKED_ADD_ULONG(&AfpWorkerRequests, (ULONG)-1, &AfpServerGlobalLock);
  1037. IdleCount = 0;
  1038. }
  1039. else
  1040. {
  1041. IdleCount ++;
  1042. }
  1043. ACQUIRE_SPIN_LOCK(&AfpServerGlobalLock, &OldIrql);
  1044. if (((AfpWorkerRequests - AfpNumThreads) > AFP_THREAD_THRESHOLD_REQS) &&
  1045. (AfpNumThreads < AFP_MAX_THREADS))
  1046. {
  1047. for (CreateId = 0; CreateId < AFP_MAX_THREADS; CreateId++)
  1048. {
  1049. if (AfpThreadState[CreateId] == AFP_THREAD_DEAD)
  1050. {
  1051. AfpThreadState[CreateId] = AFP_THREAD_STARTED;
  1052. break;
  1053. }
  1054. }
  1055. if (CreateId < AFP_MAX_THREADS)
  1056. {
  1057. AfpNumThreads++;
  1058. ASSERT (CreateId < AFP_MAX_THREADS);
  1059. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  1060. ("AfpWorkerThread: Creating New Thread %ld\n", CreateId));
  1061. RELEASE_SPIN_LOCK(&AfpServerGlobalLock, OldIrql);
  1062. Status = AfpCreateNewThread(AfpWorkerThread, CreateId);
  1063. ACQUIRE_SPIN_LOCK(&AfpServerGlobalLock, &OldIrql);
  1064. if (!NT_SUCCESS(Status))
  1065. {
  1066. ASSERT(AfpThreadState[CreateId] == AFP_THREAD_STARTED);
  1067. AfpThreadState[CreateId] = AFP_THREAD_DEAD;
  1068. AfpNumThreads --;
  1069. }
  1070. }
  1071. }
  1072. else if ((AfpNumThreads > AFP_MIN_THREADS) &&
  1073. (IdleCount >= AFP_THREAD_THRESHOLD_IDLE))
  1074. {
  1075. ReasonToLive = False;
  1076. AfpThreadState[ThreadNum] = AFP_THREAD_DEAD;
  1077. AfpNumThreads --;
  1078. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  1079. ("AfpWorkerThread: Thread %ld About to commit suicide, NumThreads %ld\n",
  1080. ThreadNum, AfpNumThreads));
  1081. }
  1082. RELEASE_SPIN_LOCK(&AfpServerGlobalLock, OldIrql);
  1083. } while (ReasonToLive);
  1084. AfpThreadPtrsW[ThreadNum] = NULL;
  1085. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_WARN,
  1086. ("AfpWorkerThread: Thread %ld Quitting\n", ThreadNum));
  1087. INTERLOCKED_ADD_ULONG((PLONG)&AfpServerStatistics.stat_CurrThreadCount,
  1088. (ULONG)-1,
  1089. &AfpStatisticsLock);
  1090. // if this is the last thread in the system, set things up so that unload code
  1091. // can wait on the pointer and know when this thread has really died and not just
  1092. // when KeSetEvent is called
  1093. if (Release)
  1094. {
  1095. AfpThreadPtrsW[ThreadNum] = PsGetCurrentThread();
  1096. ObReferenceObject(AfpThreadPtrsW[ThreadNum]);
  1097. KeSetEvent(&AfpStopConfirmEvent, IO_NETWORK_INCREMENT, False);
  1098. }
  1099. }
  1100. /*** AfpInitStrings
  1101. *
  1102. * Initializes all the strings
  1103. */
  1104. VOID FASTCALL
  1105. AfpInitStrings(
  1106. IN VOID
  1107. )
  1108. {
  1109. // Initialize UAM Strings
  1110. RtlInitString(&AfpUamGuest, NO_USER_AUTHENT_NAME);
  1111. RtlInitString(&AfpUamClearText, CLEAR_TEXT_AUTHENT_NAME);
  1112. RtlInitString(&AfpUamCustomV1, CUSTOM_UAM_NAME_V1);
  1113. RtlInitString(&AfpUamCustomV2, CUSTOM_UAM_NAME_V2);
  1114. RtlInitString(&AfpUamCustomV3, CUSTOM_UAM_NAME_V3);
  1115. RtlInitString(&AfpUamApple, RANDNUM_EXCHANGE_NAME);
  1116. RtlInitString(&AfpUamApple2Way, TWOWAY_EXCHANGE_NAME);
  1117. // Initialize AFP Versions
  1118. RtlInitString(&AfpVersion20, AFP_VER_20_NAME);
  1119. RtlInitString(&AfpVersion21, AFP_VER_21_NAME);
  1120. RtlInitString(&AfpVersion22, AFP_VER_22_NAME);
  1121. // Default Workstation name
  1122. RtlInitUnicodeString(&AfpDefaultWksta, AFP_DEFAULT_WORKSTATION);
  1123. RtlInitUnicodeString(&AfpNetworkTrashNameU, AFP_NWTRASH_NAME_U);
  1124. }
  1125. /*** AfpAdmSystemShutdown
  1126. *
  1127. * Called during system shutdown. Simply close all active sessions and stop the volumes.
  1128. */
  1129. AFPSTATUS
  1130. AfpAdmSystemShutdown(
  1131. IN OUT PVOID Inbuf OPTIONAL,
  1132. IN LONG OutBufLen OPTIONAL,
  1133. OUT PVOID Outbuf OPTIONAL
  1134. )
  1135. {
  1136. AFP_SESSION_INFO SessInfo;
  1137. NTSTATUS Status;
  1138. if ((AfpServerState & ( AFP_STATE_STOPPED |
  1139. AFP_STATE_STOP_PENDING |
  1140. AFP_STATE_SHUTTINGDOWN)) == 0)
  1141. {
  1142. AfpServerState = AFP_STATE_SHUTTINGDOWN;
  1143. DBGPRINT(DBG_COMP_ADMINAPI_SC, DBG_LEVEL_ERR,
  1144. ("AfpAdmSystemShutdown: Shutting down server\n"));
  1145. // Disable listens now that we are about to stop
  1146. AfpSpDisableListens();
  1147. SessInfo.afpsess_id = 0; // Shutdown all sessions
  1148. AfpAdmWSessionClose(&SessInfo, 0, NULL);
  1149. // Wait for the sessions to complete, if there were active sessions
  1150. if (AfpNumSessions > 0) do
  1151. {
  1152. Status = AfpIoWait(&AfpStopConfirmEvent, &FiveSecTimeOut);
  1153. if (Status == STATUS_TIMEOUT)
  1154. {
  1155. DBGPRINT(DBG_COMP_ADMINAPI_SC, DBG_LEVEL_ERR,
  1156. ("AfpAdmSystemShutdown: Timeout Waiting for %ld sessions to die, re-waiting\n",
  1157. AfpNumSessions));
  1158. }
  1159. } while (Status == STATUS_TIMEOUT);
  1160. // bring down the DSI-TCP interface
  1161. DsiDestroyAdapter();
  1162. // wait until DSI cleans up its interface with TCP
  1163. AfpIoWait(&DsiShutdownEvent, NULL);
  1164. // Set the flag to indicate that server is shutting down
  1165. fAfpServerShutdownEvent = TRUE;
  1166. // Now tell each of the volume scavengers to shut-down
  1167. AfpVolumeStopAllVolumes();
  1168. }
  1169. return AFP_ERR_NONE;
  1170. }