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.

1150 lines
29 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. fsd.c
  5. Abstract:
  6. This module implements the File System Driver for the AFP Server. All of
  7. the initialization, admin request handler etc. is here.
  8. Author:
  9. Jameel Hyder (microsoft!jameelh)
  10. Revision History:
  11. 01 Jun 1992 Initial Version
  12. --*/
  13. #define FILENUM FILE_FSD
  14. #include <afp.h>
  15. #define AFPADMIN_LOCALS
  16. #include <afpadmin.h>
  17. #include <client.h>
  18. #include <scavengr.h>
  19. #include <secutil.h>
  20. #ifdef ALLOC_PRAGMA
  21. #pragma alloc_text( INIT, DriverEntry)
  22. #pragma alloc_text( INIT, afpInitServer)
  23. #pragma alloc_text( PAGE, afpFsdDispatchAdminRequest)
  24. #pragma alloc_text( PAGE, afpFsdHandleAdminRequest)
  25. #pragma alloc_text( PAGE, afpHandleQueuedAdminRequest)
  26. #pragma alloc_text( PAGE, afpFsdUnloadServer)
  27. #pragma alloc_text( PAGE, afpAdminThread)
  28. #pragma alloc_text( PAGE, afpFsdHandleShutdownRequest)
  29. #endif
  30. /*** afpFsdDispatchAdminRequest
  31. *
  32. * This is the driver entry point. This is for the sole use by the server
  33. * service which opens the driver for EXCLUSIVE use. The admin request is
  34. * received here as a request packet defined in admin.h.
  35. */
  36. LOCAL NTSTATUS
  37. afpFsdDispatchAdminRequest(
  38. IN PDEVICE_OBJECT pDeviceObject,
  39. IN PIRP pIrp
  40. )
  41. {
  42. PIO_STACK_LOCATION pIrpSp;
  43. NTSTATUS Status;
  44. BOOLEAN LockDown = True;
  45. static DWORD afpOpenCount = 0;
  46. pDeviceObject; // prevent compiler warnings
  47. PAGED_CODE( );
  48. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  49. pIrp->IoStatus.Information = 0;
  50. if ((pIrpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) ||
  51. (pIrpSp->MajorFunction == IRP_MJ_CREATE) ||
  52. (pIrpSp->MajorFunction == IRP_MJ_CLOSE))
  53. {
  54. LockDown = False;
  55. }
  56. else
  57. {
  58. afpStartAdminRequest(pIrp); // Lock admin code
  59. }
  60. switch (pIrpSp->MajorFunction)
  61. {
  62. case IRP_MJ_CREATE:
  63. DBGPRINT(DBG_COMP_ADMINAPI, DBG_LEVEL_INFO,
  64. ("afpFsdDispatchAdminRequest: Open Handle\n"));
  65. INTERLOCKED_INCREMENT_LONG(&afpOpenCount);
  66. // Fall through
  67. case IRP_MJ_CLOSE:
  68. Status = STATUS_SUCCESS;
  69. break;
  70. case IRP_MJ_DEVICE_CONTROL:
  71. Status = afpFsdHandleAdminRequest(pIrp);
  72. break;
  73. case IRP_MJ_FILE_SYSTEM_CONTROL:
  74. Status = AfpSecurityUtilityWorker(pIrp, pIrpSp);
  75. break;
  76. case IRP_MJ_CLEANUP:
  77. Status = STATUS_SUCCESS;
  78. DBGPRINT(DBG_COMP_ADMINAPI, DBG_LEVEL_INFO,
  79. ("afpFsdDispatchAdminRequest: Close Handle\n"));
  80. INTERLOCKED_DECREMENT_LONG(&afpOpenCount);
  81. #if 0
  82. // If the service is closing its handle. Force a service stop
  83. if ((afpOpenCount == 0) &&
  84. (AfpServerState != AFP_STATE_STOPPED))
  85. AfpAdmServiceStop(NULL, 0, NULL);
  86. #endif
  87. break;
  88. case IRP_MJ_SHUTDOWN:
  89. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  90. ("afpFsdDispatchAdminRequest: Received shutdown notification !!\n"));
  91. Status = afpFsdHandleShutdownRequest(pIrp);
  92. break;
  93. default:
  94. Status = STATUS_NOT_IMPLEMENTED;
  95. break;
  96. }
  97. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  98. if (Status != STATUS_PENDING)
  99. {
  100. pIrp->IoStatus.Status = Status;
  101. if (LockDown)
  102. {
  103. afpStopAdminRequest(pIrp); // Unlock admin code (and complete request)
  104. }
  105. else
  106. {
  107. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  108. }
  109. }
  110. return Status;
  111. }
  112. /*** afpFsdHandleAdminRequest
  113. *
  114. * This is the admin request handler. The list of admin requests are defined
  115. * in admin.h. The admin requests must happen in a pre-defined order. The
  116. * service start must happen after atleast the following.
  117. *
  118. * ServerSetInfo
  119. *
  120. * Preferably all VolumeAdds should also happen before server start. This is
  121. * not enforced, obviously since the server can start w/o any volumes defined.
  122. *
  123. */
  124. LOCAL NTSTATUS
  125. afpFsdHandleAdminRequest(
  126. IN PIRP pIrp
  127. )
  128. {
  129. NTSTATUS Status = STATUS_PENDING;
  130. USHORT FuncCode;
  131. USHORT Method;
  132. PVOID pBufIn;
  133. PVOID pBufOut;
  134. LONG i, Off, iBufLen, oBufLen;
  135. LONG NumEntries;
  136. PADMQREQ pAdmQReq;
  137. IN PIO_STACK_LOCATION pIrpSp;
  138. struct _AdminApiDispatchTable *pDispTab;
  139. PAGED_CODE( );
  140. // Initialize the I/O Status block
  141. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  142. iBufLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  143. pBufIn = pIrp->AssociatedIrp.SystemBuffer;
  144. FuncCode = (USHORT)AFP_CC_BASE(pIrpSp->Parameters.DeviceIoControl.IoControlCode);
  145. Method = (USHORT)AFP_CC_METHOD(pIrpSp->Parameters.DeviceIoControl.IoControlCode);
  146. if (Method == METHOD_BUFFERED)
  147. {
  148. // Get the output buffer and its length. Input and Output buffers are
  149. // both pointed to by the SystemBuffer
  150. pBufOut = pBufIn;
  151. oBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  152. }
  153. else if ((Method == METHOD_IN_DIRECT) && (pIrp->MdlAddress != NULL))
  154. {
  155. pBufOut = MmGetSystemAddressForMdlSafe(
  156. pIrp->MdlAddress,
  157. NormalPagePriority);
  158. if (pBufOut == NULL)
  159. {
  160. ASSERT(0);
  161. return STATUS_INSUFFICIENT_RESOURCES;
  162. }
  163. oBufLen = MmGetMdlByteCount(pIrp->MdlAddress);
  164. }
  165. else
  166. {
  167. DBGPRINT(DBG_COMP_ADMINAPI, DBG_LEVEL_ERR,
  168. ("afpFsdHandleAdminRequest: Invalid Request %d/%d\n", FuncCode, Method));
  169. return STATUS_INVALID_PARAMETER;
  170. }
  171. DBGPRINT(DBG_COMP_ADMINAPI, DBG_LEVEL_INFO,
  172. ("afpFsdHandleAdminRequest Entered, Function %d\n", FuncCode));
  173. // Validate the function code
  174. if (FuncCode == 0 || FuncCode >= CC_BASE_MAX)
  175. return STATUS_INVALID_PARAMETER;
  176. pDispTab = &AfpAdminDispatchTable[FuncCode - 1];
  177. if ((pDispTab->_MinBufLen > (SHORT)iBufLen) ||
  178. (pDispTab->_OpCode != pIrpSp->Parameters.DeviceIoControl.IoControlCode))
  179. {
  180. return STATUS_INVALID_PARAMETER;
  181. }
  182. INTERLOCKED_INCREMENT_LONG( &AfpServerStatistics.stat_NumAdminReqs );
  183. if (pDispTab->_CausesChange)
  184. INTERLOCKED_INCREMENT_LONG( &AfpServerStatistics.stat_NumAdminChanges );
  185. // Now validate the DESCRIPTOR of the input buffer
  186. for (i = 0; i < MAX_FIELDS; i++)
  187. {
  188. if (pDispTab->_Fields[i]._FieldDesc == DESC_NONE)
  189. break;
  190. Off = pDispTab->_Fields[i]._FieldOffset;
  191. switch (pDispTab->_Fields[i]._FieldDesc)
  192. {
  193. case DESC_STRING:
  194. ASSERT(pBufIn != NULL);
  195. // Make Sure that the string is pointing to somewhere within
  196. // the buffer and also the end of the buffer is a UNICODE_NULL
  197. if ((*(PLONG)((PBYTE)pBufIn + Off) > iBufLen) ||
  198. (*(LPWSTR)((PBYTE)pBufIn + iBufLen - sizeof(WCHAR)) != UNICODE_NULL))
  199. {
  200. return STATUS_INVALID_PARAMETER;
  201. }
  202. // Convert the offset to a pointer
  203. OFFSET_TO_POINTER(*(PBYTE *)((PBYTE)pBufIn + Off),
  204. (PBYTE)pBufIn + pDispTab->_OffToStruct);
  205. break;
  206. case DESC_ETC:
  207. ASSERT(pBufIn != NULL);
  208. // Make Sure that there are as many etc mappings as the
  209. // structure claims
  210. NumEntries = *(PLONG)((PBYTE)pBufIn + Off);
  211. if ((LONG)(NumEntries * sizeof(ETCMAPINFO) + sizeof(DWORD)) > iBufLen)
  212. {
  213. return STATUS_INVALID_PARAMETER;
  214. }
  215. if (NumEntries > (LONG)((iBufLen/sizeof(ETCMAPINFO)) + 1))
  216. {
  217. return STATUS_INVALID_PARAMETER;
  218. }
  219. break;
  220. case DESC_ICON:
  221. // Validate that the buffer is atleast big enough to hold the
  222. // icon that this purports to.
  223. ASSERT(pBufIn != NULL);
  224. if ((LONG)((*(PLONG)((PBYTE)pBufIn + Off) +
  225. sizeof(SRVICONINFO))) > iBufLen)
  226. {
  227. return STATUS_INVALID_PARAMETER;
  228. }
  229. break;
  230. case DESC_SID:
  231. // Validate that the buffer is big enough to hold the Sid
  232. ASSERT(pBufIn != NULL);
  233. {
  234. LONG Offst, SidSize;
  235. Offst = *(PLONG)((PBYTE)pBufIn + Off);
  236. // If no SID is being sent then we're done
  237. if (Offst == 0)
  238. {
  239. break;
  240. }
  241. if ((Offst > iBufLen) ||
  242. (Offst < (LONG)(sizeof(AFP_DIRECTORY_INFO))) ||
  243. ((Offst + (LONG)sizeof(SID)) > iBufLen))
  244. {
  245. return STATUS_INVALID_PARAMETER;
  246. }
  247. // Convert the offset to a pointer
  248. OFFSET_TO_POINTER(*(PBYTE *)((PBYTE)pBufIn + Off),
  249. (PBYTE)pBufIn + pDispTab->_OffToStruct);
  250. // Finally check if the buffer is big enough for the real
  251. // sid
  252. SidSize = RtlLengthSid(*((PSID *)((PBYTE)pBufIn + Off)));
  253. if ((Off + SidSize) > iBufLen)
  254. {
  255. return STATUS_INVALID_PARAMETER;
  256. }
  257. }
  258. break;
  259. case DESC_SPECIAL:
  260. // Validate that the buffer is big enough to hold all the
  261. // information. The information consists of limits on non-paged
  262. // and paged memory and a list of domain sids and their corres.
  263. // posix offsets
  264. ASSERT(pBufIn != NULL);
  265. {
  266. LONG i;
  267. LONG SizeRemaining;
  268. PAFP_SID_OFFSET pSidOff;
  269. SizeRemaining = iBufLen - (sizeof(AFP_SID_OFFSET_DESC) -
  270. sizeof(AFP_SID_OFFSET));
  271. for (i = 0;
  272. i < (LONG)(((PAFP_SID_OFFSET_DESC)pBufIn)->CountOfSidOffsets);
  273. i++, pSidOff++)
  274. {
  275. pSidOff = &((PAFP_SID_OFFSET_DESC)pBufIn)->SidOffsetPairs[i];
  276. if (SizeRemaining < (sizeof(AFP_SID_OFFSET) + sizeof(SID)))
  277. return STATUS_INVALID_PARAMETER;
  278. OFFSET_TO_POINTER(pSidOff->pSid, pSidOff);
  279. if ((LONG)(((PBYTE)(pSidOff->pSid) - (PBYTE)pBufIn +
  280. RtlLengthSid(pSidOff->pSid))) > iBufLen)
  281. return STATUS_INVALID_PARAMETER;
  282. SizeRemaining -= (RtlLengthSid(pSidOff->pSid) +
  283. sizeof(AFP_SID_OFFSET));
  284. }
  285. }
  286. break;
  287. }
  288. }
  289. // Can this request be handled/validated at this level
  290. if (pDispTab->_AdminApiWorker != NULL)
  291. {
  292. Status = (*pDispTab->_AdminApiWorker)(pBufIn, oBufLen, pBufOut);
  293. if (NT_SUCCESS(Status))
  294. {
  295. if (Method != METHOD_BUFFERED)
  296. pIrp->IoStatus.Information = oBufLen;
  297. }
  298. }
  299. if (Status == STATUS_PENDING)
  300. {
  301. ASSERT (pDispTab->_AdminApiQueuedWorker != NULL);
  302. // Mark this as a pending Irp as we are about to queue it up
  303. IoMarkIrpPending(pIrp);
  304. if ((pAdmQReq =
  305. (PADMQREQ)AfpAllocNonPagedMemory(sizeof(ADMQREQ))) == NULL)
  306. {
  307. Status = STATUS_INSUFFICIENT_RESOURCES;
  308. }
  309. else
  310. {
  311. PWORK_ITEM pWI = &pAdmQReq->aqr_WorkItem;
  312. DBGPRINT(DBG_COMP_ADMINAPI, DBG_LEVEL_INFO,
  313. ("afpFsdHandleAdminRequest: Queuing to worker\n"));
  314. AfpInitializeWorkItem(pWI,
  315. afpHandleQueuedAdminRequest,
  316. pAdmQReq);
  317. pAdmQReq->aqr_AdminApiWorker = pDispTab->_AdminApiQueuedWorker;
  318. pAdmQReq->aqr_pIrp = pIrp;
  319. // Insert item in admin queue
  320. INTERLOCKED_ADD_ULONG(&AfpWorkerRequests, 1, &AfpServerGlobalLock);
  321. KeInsertQueue(&AfpAdminQueue, &pAdmQReq->aqr_WorkItem.wi_List);
  322. }
  323. }
  324. return Status;
  325. }
  326. /*** afpHandleQueuedAdminRequest
  327. *
  328. * This handles queued admin requests. It is called in the context of the
  329. * worker thread.
  330. */
  331. LOCAL VOID FASTCALL
  332. afpHandleQueuedAdminRequest(
  333. IN PADMQREQ pAdmQReq
  334. )
  335. {
  336. PIRP pIrp;
  337. PIO_STACK_LOCATION pIrpSp;
  338. PVOID pBufOut = NULL;
  339. LONG oBufLen = 0;
  340. USHORT Method;
  341. PAGED_CODE( );
  342. DBGPRINT(DBG_COMP_ADMINAPI, DBG_LEVEL_INFO,
  343. ("afpHandleQueuedAdminRequest Entered\n"));
  344. // Get the IRP and the IRP Stack location out of the request
  345. pIrp = pAdmQReq->aqr_pIrp;
  346. ASSERT (pIrp != NULL);
  347. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  348. ASSERT (pIrpSp != NULL);
  349. Method = (USHORT)AFP_CC_METHOD(pIrpSp->Parameters.DeviceIoControl.IoControlCode);
  350. if (Method == METHOD_BUFFERED)
  351. {
  352. // Get the output buffer and its length. Input and Output buffers are
  353. // both pointed to by the SystemBuffer
  354. oBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  355. pBufOut = pIrp->AssociatedIrp.SystemBuffer;
  356. }
  357. else if ((Method == METHOD_IN_DIRECT) && (pIrp->MdlAddress != NULL))
  358. {
  359. pBufOut = MmGetSystemAddressForMdlSafe(
  360. pIrp->MdlAddress,
  361. NormalPagePriority);
  362. if (pBufOut == NULL)
  363. {
  364. ASSERT(0);
  365. pAdmQReq->aqr_pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  366. IoCompleteRequest(pAdmQReq->aqr_pIrp, IO_NETWORK_INCREMENT);
  367. AfpFreeMemory(pAdmQReq);
  368. return;
  369. }
  370. oBufLen = MmGetMdlByteCount(pIrp->MdlAddress);
  371. }
  372. else ASSERTMSG(0, "afpHandleQueuedAdminRequest: Invalid method\n");
  373. // Call the worker and complete the IoRequest
  374. pIrp->IoStatus.Status = (*pAdmQReq->aqr_AdminApiWorker)(pIrp->AssociatedIrp.SystemBuffer,
  375. oBufLen,
  376. pBufOut);
  377. if (NT_SUCCESS(pIrp->IoStatus.Status))
  378. {
  379. if (Method != METHOD_BUFFERED)
  380. pIrp->IoStatus.Information = oBufLen;
  381. }
  382. ASSERT(pIrp->IoStatus.Status != STATUS_PENDING);
  383. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  384. afpStopAdminRequest(pIrp); // Unlock admin code and complete request
  385. AfpFreeMemory(pAdmQReq);
  386. }
  387. /*** afpFsdUnloadServer
  388. *
  389. * This is the unload routine for the Afp Server. The server can ONLY be
  390. * unloaded in its passive state i.e. either before recieving a ServiceStart
  391. * or after recieving a ServiceStop. This is ensured by making the service
  392. * dependent on the server. Also the IO system ensures that there are no open
  393. * handles to our device when this happens.
  394. */
  395. LOCAL VOID
  396. afpFsdUnloadServer(
  397. IN PDRIVER_OBJECT DeviceObject
  398. )
  399. {
  400. NTSTATUS Status;
  401. LONG i;
  402. LONG LastThreadCount = 0;
  403. PETHREAD pLastThrdPtr;
  404. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  405. ("afpFsdUnloadServer Entered\n"));
  406. ASSERT((AfpServerState == AFP_STATE_STOPPED) || (AfpServerState == AFP_STATE_IDLE));
  407. // Stop our threads before unloading
  408. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  409. ("afpFsdUnloadServer: Stopping worker threads\n"));
  410. //
  411. // tell TDI we don't care to know if the stack is going away
  412. //
  413. if (AfpTdiNotificationHandle)
  414. {
  415. Status = TdiDeregisterPnPHandlers(AfpTdiNotificationHandle);
  416. if (!NT_SUCCESS(Status))
  417. {
  418. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  419. ("afpFsdUnloadServer: TdiDeregisterNotificationHandler failed with %lx\n",Status));
  420. }
  421. AfpTdiNotificationHandle = NULL;
  422. }
  423. DsiShutdown();
  424. // Stop the scavenger. This also happens during server stop but we can get here
  425. // another way as well
  426. AfpScavengerFlushAndStop();
  427. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  428. ("afpFsdUnloadServer: Stopping admin thread\n"));
  429. if (AfpNumAdminThreads > 0)
  430. {
  431. KeClearEvent(&AfpStopConfirmEvent);
  432. KeInsertQueue(&AfpAdminQueue, &AfpTerminateThreadWI.wi_List);
  433. do
  434. {
  435. Status = AfpIoWait(&AfpStopConfirmEvent, &FiveSecTimeOut);
  436. if (Status == STATUS_TIMEOUT)
  437. {
  438. DBGPRINT(DBG_COMP_ADMINAPI_SC, DBG_LEVEL_ERR,
  439. ("afpFsdUnloadServer: Timeout Waiting for admin thread, re-waiting\n"));
  440. }
  441. } while (Status == STATUS_TIMEOUT);
  442. }
  443. KeRundownQueue(&AfpAdminQueue);
  444. if (AfpNumNotifyThreads > 0)
  445. {
  446. for (i = 0; i < NUM_NOTIFY_QUEUES; i++)
  447. {
  448. KeClearEvent(&AfpStopConfirmEvent);
  449. KeInsertQueue(&AfpVolumeNotifyQueue[i], &AfpTerminateNotifyThread.vn_List);
  450. do
  451. {
  452. Status = AfpIoWait(&AfpStopConfirmEvent, &FiveSecTimeOut);
  453. if (Status == STATUS_TIMEOUT)
  454. {
  455. DBGPRINT(DBG_COMP_ADMINAPI_SC, DBG_LEVEL_ERR,
  456. ("afpFsdUnloadServer: Timeout Waiting for Notify Thread %d, re-waiting\n", i));
  457. }
  458. } while (Status == STATUS_TIMEOUT);
  459. KeRundownQueue(&AfpVolumeNotifyQueue[i]);
  460. }
  461. }
  462. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  463. // Cleanup virtual memory used by volumes for private notifies
  464. afpFreeNotifyBlockMemory();
  465. // Stop worker threads
  466. if (AfpNumThreads > 0)
  467. {
  468. KeClearEvent(&AfpStopConfirmEvent);
  469. KeInsertQueue(&AfpWorkerQueue, &AfpTerminateThreadWI.wi_List);
  470. do
  471. {
  472. Status = AfpIoWait(&AfpStopConfirmEvent, &FiveSecTimeOut);
  473. if (Status == STATUS_TIMEOUT)
  474. {
  475. DBGPRINT(DBG_COMP_ADMINAPI_SC, DBG_LEVEL_ERR,
  476. ("afpFsdUnloadServer: Timeout Waiting for worker threads, re-waiting\n"));
  477. }
  478. } while (Status == STATUS_TIMEOUT);
  479. }
  480. // See how many threads are around
  481. // Loop around until we have exactly one thread left or if no worker
  482. // thread was started
  483. do
  484. {
  485. pLastThrdPtr = NULL;
  486. LastThreadCount = 0;
  487. for (i=0; i<AFP_MAX_THREADS; i++)
  488. {
  489. if (AfpThreadPtrsW[i] != NULL)
  490. {
  491. pLastThrdPtr = AfpThreadPtrsW[i];
  492. LastThreadCount++;
  493. if (LastThreadCount > 1)
  494. {
  495. Status = AfpIoWait(pLastThrdPtr, &FiveSecTimeOut);
  496. break;
  497. }
  498. }
  499. }
  500. if ((LastThreadCount == 1) || (LastThreadCount == 0))
  501. {
  502. break;
  503. }
  504. } while (TRUE);
  505. // wait on the last thread pointer. When that thread quits, we are signaled. This
  506. // is the surest way of knowing that the thread has really really died
  507. if (pLastThrdPtr)
  508. {
  509. do
  510. {
  511. Status = AfpIoWait(pLastThrdPtr, &FiveSecTimeOut);
  512. if (Status == STATUS_TIMEOUT)
  513. {
  514. DBGPRINT(DBG_COMP_ADMINAPI_SC, DBG_LEVEL_ERR,
  515. ("afpFsdUnloadServer: Timeout Waiting for last threads, re-waiting\n"));
  516. }
  517. } while (Status == STATUS_TIMEOUT);
  518. ObDereferenceObject(pLastThrdPtr);
  519. }
  520. KeRundownQueue(&AfpDelAllocQueue);
  521. KeRundownQueue(&AfpWorkerQueue);
  522. // Close the cloned process token
  523. if (AfpFspToken != NULL)
  524. NtClose(AfpFspToken);
  525. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  526. ("afpFsdUnloadServer: De-initializing sub-systems\n"));
  527. // De-initialize all sub-systems now
  528. AfpDeinitializeSubsystems();
  529. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  530. ("afpFsdUnloadServer: Deleting device\n"));
  531. // Destroy the DeviceObject for our device
  532. IoDeleteDevice(AfpDeviceObject);
  533. #ifdef PROFILING
  534. ASSERT(AfpServerProfile->perf_cAllocatedIrps == 0);
  535. ASSERT(AfpServerProfile->perf_cAllocatedMdls == 0);
  536. ExFreePool(AfpServerProfile);
  537. #endif
  538. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, ("Current Sessions = %ld\n NonPaged usage = %ld\n CurrPagedUsage = %ld \n CurrentFileLocks = %ld \n CurrentFileOpen = %ld \n CurrentInternalOpens = %ld, NotifyBlockCount = %ld, NotifyCount = %d \n",
  539. AfpServerStatistics.stat_CurrentSessions,
  540. AfpServerStatistics.stat_CurrNonPagedUsage,
  541. AfpServerStatistics.stat_CurrPagedUsage,
  542. AfpServerStatistics.stat_CurrentFileLocks,
  543. AfpServerStatistics.stat_CurrentFilesOpen,
  544. AfpServerStatistics.stat_CurrentInternalOpens,
  545. afpNotifyBlockAllocCount,
  546. afpNotifyAllocCount
  547. ));
  548. // Make sure we do not have resource leaks
  549. ASSERT(AfpServerStatistics.stat_CurrentSessions == 0);
  550. ASSERT(AfpServerStatistics.stat_CurrNonPagedUsage == 0);
  551. ASSERT(AfpServerStatistics.stat_CurrPagedUsage == 0);
  552. ASSERT(AfpServerStatistics.stat_CurrentFileLocks == 0);
  553. ASSERT(AfpServerStatistics.stat_CurrentFilesOpen == 0);
  554. ASSERT(AfpServerStatistics.stat_CurrentInternalOpens == 0);
  555. ASSERT (AfpLockCount == 0);
  556. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, ("afpFsdUnloadServer Done\n"));
  557. // Give the worker threads a chance to really, really die
  558. AfpSleepAWhile(1000);
  559. }
  560. /*** afpAdminThread
  561. *
  562. * This thread is used to do all the work of the queued admin threads.
  563. *
  564. * LOCKS: AfpServerGlobalLock (SPIN)
  565. */
  566. LOCAL VOID
  567. afpAdminThread(
  568. IN PVOID pContext
  569. )
  570. {
  571. PLIST_ENTRY pList;
  572. PWORK_ITEM pWI;
  573. ULONG BasePriority;
  574. NTSTATUS Status;
  575. AfpThread = PsGetCurrentThread();
  576. IoSetThreadHardErrorMode( FALSE );
  577. // Boost our priority to just below low realtime.
  578. // The idea is get the work done fast and get out of the way.
  579. BasePriority = LOW_REALTIME_PRIORITY;
  580. Status = NtSetInformationThread(NtCurrentThread(),
  581. ThreadBasePriority,
  582. &BasePriority,
  583. sizeof(BasePriority));
  584. ASSERT(NT_SUCCESS(Status));
  585. do
  586. {
  587. // Wait for admin request to process.
  588. pList = KeRemoveQueue(&AfpAdminQueue,
  589. KernelMode, // Do not let the kernel stack be paged
  590. NULL);
  591. ASSERT(Status == STATUS_SUCCESS);
  592. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  593. pWI = CONTAINING_RECORD(pList, WORK_ITEM, wi_List);
  594. if (pWI == &AfpTerminateThreadWI)
  595. {
  596. break;
  597. }
  598. (*pWI->wi_Worker)(pWI->wi_Context);
  599. INTERLOCKED_ADD_ULONG(&AfpWorkerRequests, (ULONG)-1, &AfpServerGlobalLock);
  600. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  601. } while (True);
  602. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, ("afpAdminThread: Quitting\n"));
  603. KeSetEvent(&AfpStopConfirmEvent, IO_NETWORK_INCREMENT, False);
  604. }
  605. /*** afpStartStopAdminRequest
  606. *
  607. * Called whenever an admin request is started/stopped. The admin code is locked
  608. * or unlocked accordingly.
  609. */
  610. LOCAL VOID
  611. afpStartStopAdminRequest(
  612. IN PIRP pIrp,
  613. IN BOOLEAN Start
  614. )
  615. {
  616. // EnterCriticalSection
  617. AfpIoWait(&AfpPgLkMutex, NULL);
  618. ASSERT (AfpLockHandle != NULL);
  619. if (Start)
  620. {
  621. if (AfpLockCount == 0)
  622. {
  623. MmLockPagableSectionByHandle(AfpLockHandle);
  624. }
  625. AfpLockCount ++;
  626. pIrp->IoStatus.Status = STATUS_PENDING;
  627. }
  628. else
  629. {
  630. ASSERT (AfpLockCount > 0);
  631. AfpLockCount --;
  632. if (AfpLockCount == 0)
  633. {
  634. MmUnlockPagableImageSection(AfpLockHandle);
  635. }
  636. }
  637. // LeaveCriticalSection
  638. KeReleaseMutex(&AfpPgLkMutex, False);
  639. if (!Start)
  640. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  641. }
  642. /*** afpFsdHandleShutdownRequest
  643. *
  644. * This is the shutdown request handler. All sessions are shutdown and volumes
  645. * flushed.
  646. */
  647. LOCAL NTSTATUS
  648. afpFsdHandleShutdownRequest(
  649. IN PIRP pIrp
  650. )
  651. {
  652. PADMQREQ pAdmQReq;
  653. NTSTATUS Status;
  654. if ((pAdmQReq =
  655. (PADMQREQ)AfpAllocNonPagedMemory(sizeof(ADMQREQ))) == NULL)
  656. {
  657. Status = STATUS_INSUFFICIENT_RESOURCES;
  658. }
  659. else
  660. {
  661. PWORK_ITEM pWI = &pAdmQReq->aqr_WorkItem;
  662. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  663. ("afpFsdHandleShutdownRequest: Queuing to worker\n"));
  664. AfpInitializeWorkItem(&pAdmQReq->aqr_WorkItem,
  665. afpHandleQueuedAdminRequest,
  666. pAdmQReq);
  667. pAdmQReq->aqr_AdminApiWorker = AfpAdmSystemShutdown;
  668. pAdmQReq->aqr_pIrp = pIrp;
  669. // Insert item in admin queue
  670. KeInsertQueue(&AfpAdminQueue, &pAdmQReq->aqr_WorkItem.wi_List);
  671. Status = STATUS_PENDING;
  672. }
  673. return Status;
  674. }
  675. /*** DriverEntry
  676. *
  677. * This is the initialization routine for the AFP server file
  678. * system driver. This routine creates the device object for the
  679. * AfpServer device and performs all other driver initialization.
  680. */
  681. NTSTATUS
  682. DriverEntry (
  683. IN PDRIVER_OBJECT DriverObject,
  684. IN PUNICODE_STRING RegistryPath
  685. )
  686. {
  687. UNICODE_STRING DeviceName;
  688. LONG i;
  689. NTSTATUS Status;
  690. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  691. ("AFP Server Fsd initialization started\n"));
  692. //
  693. // Initialize global data event log insertion strings
  694. //
  695. KeInitializeQueue(&AfpDelAllocQueue, 0);
  696. KeInitializeQueue(&AfpWorkerQueue, 0);
  697. KeInitializeQueue(&AfpAdminQueue, 0);
  698. AfpProcessObject = IoGetCurrentProcess();
  699. Status = AfpInitializeDataAndSubsystems();
  700. if (!NT_SUCCESS(Status))
  701. {
  702. return Status;
  703. }
  704. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  705. ("AFP Server Fsd Data initialized %lx\n", Status));
  706. // Create the device object. (IoCreateDevice zeroes the memory
  707. // occupied by the object.)
  708. //
  709. // Should we apply an ACL to the device object ?
  710. RtlInitUnicodeString(&DeviceName, AFPSERVER_DEVICE_NAME);
  711. Status = IoCreateDevice(DriverObject, // DriverObject
  712. 0, // DeviceExtension
  713. &DeviceName, // DeviceName
  714. FILE_DEVICE_NETWORK, // DeviceType
  715. FILE_DEVICE_SECURE_OPEN, // DeviceCharacteristics
  716. False, // Exclusive
  717. &AfpDeviceObject); // DeviceObject
  718. if (!NT_SUCCESS(Status))
  719. {
  720. // Do not errorlog here since logging uses the device object
  721. AfpDeinitializeSubsystems();
  722. return Status;
  723. }
  724. do
  725. {
  726. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  727. ("DriverEntry: Creating Admin Thread\n"));
  728. // Create the Admin thread. This handles all queued operations
  729. Status = AfpCreateNewThread(afpAdminThread, 0);
  730. if (!NT_SUCCESS(Status))
  731. {
  732. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_FATAL,
  733. ("afpInitServer: Admin Thread creation failed %lx\n", Status));
  734. break;
  735. }
  736. AfpNumAdminThreads = 1;
  737. for (i = 0; i < NUM_NOTIFY_QUEUES; i++)
  738. {
  739. // Initialize volume change notify queue
  740. KeInitializeQueue(&AfpVolumeNotifyQueue[i], 0);
  741. // Start a thread to process change notifies
  742. Status = AfpCreateNewThread(AfpChangeNotifyThread, i);
  743. if (!NT_SUCCESS(Status))
  744. {
  745. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_FATAL,
  746. ("afpInitServer: Notify Thread %d, creation failed %lx\n", i+1, Status));
  747. break;
  748. }
  749. }
  750. if (!NT_SUCCESS(Status))
  751. {
  752. for (--i; i >= 0; i--)
  753. {
  754. KeClearEvent(&AfpStopConfirmEvent);
  755. KeInsertQueue(&AfpVolumeNotifyQueue[i], &AfpTerminateNotifyThread.vn_List);
  756. AfpIoWait(&AfpStopConfirmEvent, NULL);
  757. }
  758. break;
  759. }
  760. AfpNumNotifyThreads = NUM_NOTIFY_QUEUES;
  761. for (i = 0; i < AFP_MIN_THREADS; i++)
  762. {
  763. AfpThreadState[i] = AFP_THREAD_STARTED;
  764. Status = AfpCreateNewThread(AfpWorkerThread, i);
  765. if (!NT_SUCCESS(Status))
  766. {
  767. AfpThreadState[i] = AFP_THREAD_DEAD;
  768. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_FATAL,
  769. ("afpInitServer: Thread creation failed %d\n", i+1));
  770. if (i > 0)
  771. {
  772. KeClearEvent(&AfpStopConfirmEvent);
  773. KeInsertQueue(&AfpWorkerQueue, &AfpTerminateThreadWI.wi_List);
  774. AfpIoWait(&AfpStopConfirmEvent, NULL);
  775. }
  776. break;
  777. }
  778. #if DBG
  779. AfpSleepAWhile(50); // Make it so threads do not time out together
  780. // Helps with debugging
  781. #endif
  782. }
  783. AfpNumThreads = AFP_MIN_THREADS;
  784. if (!NT_SUCCESS(Status))
  785. break;
  786. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  787. ("AFP Server Fsd initialization completed %lx\n", Status));
  788. // initialize DSI specific things
  789. DsiInit();
  790. Status = AfpTdiRegister();
  791. if (!NT_SUCCESS(Status))
  792. {
  793. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  794. ("TdiRegisterNotificationHandler failed %lx\n", Status));
  795. break;
  796. }
  797. Status = afpInitServer();
  798. if (NT_SUCCESS(Status))
  799. {
  800. // Initialize the driver object for this file system driver.
  801. DriverObject->DriverUnload = afpFsdUnloadServer;
  802. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
  803. {
  804. DriverObject->MajorFunction[i] = afpFsdDispatchAdminRequest;
  805. }
  806. // Register for shutdown notification. We don't care if this fails.
  807. Status = IoRegisterShutdownNotification(AfpDeviceObject);
  808. if (!NT_SUCCESS(Status))
  809. {
  810. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERR,
  811. ("Afp Server Fsd: IoRegisterShutdownNotification failed %lx\n", Status));
  812. }
  813. Status = STATUS_SUCCESS;
  814. }
  815. } while (False);
  816. if (!NT_SUCCESS(Status))
  817. {
  818. afpFsdUnloadServer(DriverObject);
  819. Status = STATUS_UNSUCCESSFUL;
  820. }
  821. KeClearEvent(&AfpStopConfirmEvent);
  822. return Status;
  823. }
  824. /*** afpInitServer
  825. *
  826. * Initialize the AFP Server. This happens on FSD initialization.
  827. * The initialization consists of the following steps.
  828. *
  829. * - Create a socket on the appletalk stack.
  830. * - Create a token for ourselves.
  831. * - Initialize security
  832. * - Open the Authentication pacakage
  833. *
  834. * Note: Any errorlogging done from here must use AFPLOG_DDERROR since we
  835. * will not have a usermode thread to do our errorlogging if anything
  836. * goes wrong here.
  837. */
  838. NTSTATUS
  839. afpInitServer(
  840. VOID
  841. )
  842. {
  843. NTSTATUS Status;
  844. ANSI_STRING LogonProcessName;
  845. ULONG OldSize;
  846. HANDLE ProcessToken;
  847. TOKEN_PRIVILEGES ProcessPrivileges, PreviousPrivilege;
  848. OBJECT_ATTRIBUTES ObjectAttr;
  849. UNICODE_STRING PackageName;
  850. WCHAR PkgBuf[5];
  851. TimeStamp Expiry; // unused on the server side (i.e. us)
  852. InitSecurityInterface();
  853. do
  854. {
  855. // Open our socket on the ASP Device. Implicitly checks out the
  856. // Appletalk stack
  857. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  858. ("afpInitServer: Initializing Atalk\n"));
  859. DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO,
  860. ("afpInitServer: Creating token\n"));
  861. // Clone the system process token and add the required privilges that
  862. // we need. This token will be used to impersonate when we set permissions
  863. Status = NtOpenProcessToken(NtCurrentProcess(),
  864. TOKEN_ALL_ACCESS,
  865. &ProcessToken);
  866. if (!NT_SUCCESS(Status))
  867. {
  868. AFPLOG_DDERROR(AFPSRVMSG_PROCESS_TOKEN, Status, NULL, 0, NULL);
  869. break;
  870. }
  871. InitializeObjectAttributes(&ObjectAttr, NULL, 0, NULL, NULL);
  872. ObjectAttr.SecurityQualityOfService = &AfpSecurityQOS;
  873. Status = NtDuplicateToken(ProcessToken,
  874. TOKEN_ALL_ACCESS,
  875. &ObjectAttr,
  876. False,
  877. TokenImpersonation,
  878. &AfpFspToken);
  879. NtClose(ProcessToken);
  880. if (!NT_SUCCESS(Status))
  881. {
  882. AFPLOG_DDERROR(AFPSRVMSG_PROCESS_TOKEN, Status, NULL, 0, NULL);
  883. break;
  884. }
  885. ProcessPrivileges.PrivilegeCount = 1L;
  886. ProcessPrivileges.Privileges[0].Attributes =
  887. SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_USED_FOR_ACCESS;
  888. ProcessPrivileges.Privileges[0].Luid = RtlConvertLongToLuid(SE_RESTORE_PRIVILEGE);
  889. Status = NtAdjustPrivilegesToken(AfpFspToken,
  890. False,
  891. &ProcessPrivileges,
  892. sizeof(TOKEN_PRIVILEGES),
  893. &PreviousPrivilege,
  894. &OldSize);
  895. if (!NT_SUCCESS(Status))
  896. {
  897. AFPLOG_DDERROR(AFPSRVMSG_PROCESS_TOKEN, Status, NULL, 0, NULL);
  898. break;
  899. }
  900. PackageName.Length = 8;
  901. PackageName.Buffer = (LPWSTR)PkgBuf;
  902. RtlCopyMemory( PackageName.Buffer, NTLMSP_NAME, 8);
  903. Status = AcquireCredentialsHandle(NULL, // Default principal
  904. (PSECURITY_STRING)&PackageName,
  905. SECPKG_CRED_INBOUND,
  906. NULL,
  907. NULL,
  908. NULL,
  909. (PVOID) NULL,
  910. &AfpSecHandle,
  911. &Expiry);
  912. if(!NT_SUCCESS(Status))
  913. {
  914. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  915. ("AfpInitServer: AcquireCredentialsHandle() failed with %X\n", Status));
  916. ASSERT(0);
  917. if (AfpFspToken != NULL)
  918. {
  919. NtClose(AfpFspToken);
  920. AfpFspToken = NULL;
  921. }
  922. break;
  923. }
  924. // Finally obtain a handle to our conditionally locked section
  925. AfpLockHandle = MmLockPagableCodeSection((PVOID)AfpAdmWServerSetInfo);
  926. MmUnlockPagableImageSection(AfpLockHandle);
  927. } while (False);
  928. return Status;
  929. }
  930.