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.

495 lines
15 KiB

  1. /*++
  2. Copyright (c) 1989 - 1999 Microsoft Corporation
  3. Module Name:
  4. devfcb.c
  5. Abstract:
  6. This module implements the mechanism for deleting an established connection
  7. --*/
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. #include "fsctlbuf.h"
  11. //
  12. // The local debug trace level
  13. //
  14. #define Dbg (DEBUG_TRACE_DEVFCB)
  15. #define FIXED_CONNECT_NAME L"\\;0:\\nulsvr\\share"
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE, NulMRxDevFcbXXXControlFile)
  18. #endif
  19. NTSTATUS
  20. NulMRxDevFcbXXXControlFile (
  21. IN OUT PRX_CONTEXT RxContext
  22. )
  23. /*++
  24. Routine Description:
  25. This routine handles all the device FCB related FSCTL's in the mini rdr
  26. Arguments:
  27. RxContext - Describes the Fsctl and Context.
  28. Return Value:
  29. a valid NTSTATUS code.
  30. Notes:
  31. --*/
  32. {
  33. NTSTATUS Status;
  34. RxCaptureFobx;
  35. UCHAR MajorFunctionCode = RxContext->MajorFunction;
  36. NulMRxGetDeviceExtension(RxContext,pDeviceExtension);
  37. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  38. ULONG ControlCode = 0;
  39. DbgPrint("NulMRxDevFcb\n");
  40. switch (MajorFunctionCode)
  41. {
  42. case IRP_MJ_FILE_SYSTEM_CONTROL:
  43. {
  44. switch (LowIoContext->ParamsFor.FsCtl.MinorFunction)
  45. {
  46. case IRP_MN_USER_FS_REQUEST:
  47. switch (ControlCode) {
  48. default:
  49. Status = STATUS_INVALID_DEVICE_REQUEST;
  50. }
  51. break;
  52. default : //minor function != IRP_MN_USER_FS_REQUEST
  53. Status = STATUS_INVALID_DEVICE_REQUEST;
  54. }
  55. } // FSCTL case
  56. break;
  57. case IRP_MJ_DEVICE_CONTROL:
  58. {
  59. ControlCode = LowIoContext->ParamsFor.IoCtl.IoControlCode;
  60. switch (ControlCode) {
  61. case IOCTL_NULMRX_ADDCONN:
  62. {
  63. Status = NulMRxCreateConnection( RxContext, &RxContext->PostRequest );
  64. }
  65. break;
  66. case IOCTL_NULMRX_DELCONN:
  67. Status = NulMRxDeleteConnection( RxContext, &RxContext->PostRequest );
  68. break;
  69. case IOCTL_NULMRX_GETLIST:
  70. {
  71. ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
  72. PVOID pbOut = LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
  73. if ( cbOut >= 26 )
  74. {
  75. BOOLEAN GotMutex;
  76. GotMutex = ExTryToAcquireFastMutex( &pDeviceExtension->LCMutex );
  77. RtlCopyMemory( pbOut, pDeviceExtension->LocalConnections, 26 );
  78. if ( GotMutex )
  79. {
  80. ExReleaseFastMutex( &pDeviceExtension->LCMutex );
  81. }
  82. RxContext->InformationToReturn = 26;
  83. }
  84. else
  85. {
  86. RxContext->InformationToReturn = 0;
  87. }
  88. Status = STATUS_SUCCESS;
  89. }
  90. break;
  91. case IOCTL_NULMRX_GETCONN:
  92. {
  93. UNICODE_STRING LookupName;
  94. UNICODE_STRING RemainingName;
  95. LOCK_HOLDING_STATE LockHoldingState;
  96. PVOID Container;
  97. ULONG ReturnedSize = 0;
  98. ULONG ConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
  99. PWCHAR ConnectName = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
  100. ULONG RemoteNameLen = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
  101. PULONG RemoteName = LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
  102. PRX_PREFIX_TABLE pRxNetNameTable
  103. = RxContext->RxDeviceObject->pRxNetNameTable;
  104. // insert the local connection name
  105. if ( ConnectNameLen > sizeof( WCHAR ) )
  106. {
  107. PWCHAR pLookupName = ExAllocatePool( PagedPool, sizeof(FIXED_CONNECT_NAME) );
  108. RtlCopyMemory( pLookupName, FIXED_CONNECT_NAME, sizeof( FIXED_CONNECT_NAME ) );
  109. pLookupName[2] = ConnectName[0];
  110. LookupName.Buffer = pLookupName;
  111. LookupName.Length = sizeof(FIXED_CONNECT_NAME);
  112. LookupName.MaximumLength = sizeof(FIXED_CONNECT_NAME);
  113. if ( LookupName.Buffer )
  114. {
  115. LockHoldingState = LHS_SharedLockHeld;
  116. RxAcquirePrefixTableLockShared(pRxNetNameTable, TRUE);
  117. Container = RxPrefixTableLookupName(pRxNetNameTable,
  118. &LookupName, &RemainingName, NULL);
  119. if (Container)
  120. {
  121. switch (NodeType(Container))
  122. {
  123. case RDBSS_NTC_V_NETROOT:
  124. {
  125. PMRX_NET_ROOT pNetRoot = ((PV_NET_ROOT)Container)->pNetRoot;
  126. RtlCopyMemory( RemoteName, pNetRoot->pNetRootName->Buffer, pNetRoot->pNetRootName->Length );
  127. ReturnedSize = pNetRoot->pNetRootName->Length;
  128. RxDereferenceVNetRoot((PV_NET_ROOT)Container, LockHoldingState);
  129. }
  130. break;
  131. case RDBSS_NTC_NETROOT:
  132. {
  133. PNET_ROOT pNetRoot = (PNET_ROOT) Container;
  134. RtlCopyMemory( RemoteName, pNetRoot->pNetRootName->Buffer, pNetRoot->pNetRootName->Length );
  135. ReturnedSize = pNetRoot->pNetRootName->Length;
  136. RxDereferenceNetRoot((PNET_ROOT)Container, LockHoldingState);
  137. }
  138. break;
  139. case RDBSS_NTC_SRVCALL:
  140. RxDereferenceSrvCall((PSRV_CALL)Container, LockHoldingState);
  141. ReturnedSize = 0;
  142. break;
  143. default:
  144. RxDereference((PVOID)Container,LockHoldingState);
  145. ReturnedSize = 0;
  146. break;
  147. }
  148. }
  149. RxReleasePrefixTableLock(pRxNetNameTable);
  150. ExFreePool( LookupName.Buffer );
  151. }
  152. }
  153. if ( ReturnedSize )
  154. {
  155. Status = STATUS_SUCCESS;
  156. }
  157. else
  158. {
  159. Status = STATUS_BAD_NETWORK_NAME;
  160. }
  161. RxContext->InformationToReturn = ReturnedSize;
  162. }
  163. break;
  164. default :
  165. Status = STATUS_INVALID_DEVICE_REQUEST;
  166. }
  167. }
  168. break;
  169. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  170. {
  171. switch (ControlCode) {
  172. default :
  173. Status = STATUS_INVALID_DEVICE_REQUEST;
  174. }
  175. }
  176. break;
  177. default:
  178. ASSERT(!"unimplemented major function");
  179. Status = STATUS_INVALID_DEVICE_REQUEST;
  180. }
  181. DbgPrint("NulMRxDevFcb st,info=%08lx,%08lx\n",
  182. Status,RxContext->InformationToReturn);
  183. return(Status);
  184. }
  185. HANDLE
  186. GetConnectionHandle(
  187. IN PUNICODE_STRING ConnectionName
  188. )
  189. {
  190. NTSTATUS Status;
  191. HANDLE Handle;
  192. IO_STATUS_BLOCK IoStatusBlock;
  193. OBJECT_ATTRIBUTES ObjectAttributes;
  194. UNICODE_STRING FileName;
  195. // Connection name should get checked to be certain our device is in the path
  196. InitializeObjectAttributes(
  197. &ObjectAttributes,
  198. ConnectionName,
  199. OBJ_CASE_INSENSITIVE,
  200. NULL,
  201. NULL);
  202. Status = ZwCreateFile(
  203. &Handle,
  204. SYNCHRONIZE,
  205. &ObjectAttributes,
  206. &IoStatusBlock,
  207. NULL, // Allocation size
  208. FILE_ATTRIBUTE_NORMAL,
  209. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  210. FILE_OPEN_IF,
  211. FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
  212. NULL, // Ptr to EA Buffer
  213. 0); // Length of EA buffer
  214. DbgPrint("ZwCreateFile returned %lx\n",Status);
  215. if ( (STATUS_SUCCESS == Status) && (INVALID_HANDLE_VALUE != Handle) ) {
  216. DbgPrint("ZwCreateFile returned success\n");
  217. }
  218. else
  219. Handle = INVALID_HANDLE_VALUE;
  220. return Handle;
  221. }
  222. NTSTATUS
  223. DoCreateConnection(
  224. IN PRX_CONTEXT RxContext,
  225. ULONG CreateDisposition
  226. )
  227. {
  228. NTSTATUS Status = STATUS_SUCCESS;
  229. HANDLE Handle;
  230. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  231. ULONG ConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
  232. PWCHAR ConnectName = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
  233. UNICODE_STRING FileName;
  234. NulMRxGetDeviceExtension(RxContext,pDeviceExtension);
  235. // The sample code passes in only the filename in the Ioctl data buffer.
  236. // An actual implementation could pass in stuff like EAs, security
  237. // credentials, etc
  238. RxDbgTrace(0, Dbg,("DoCreateConnection"));
  239. FileName.Buffer = ConnectName;
  240. FileName.Length = (USHORT) ConnectNameLen;
  241. FileName.MaximumLength = (USHORT) ConnectNameLen;
  242. Handle = GetConnectionHandle(&FileName);
  243. if ( INVALID_HANDLE_VALUE != Handle )
  244. {
  245. PWCHAR pwcLC;
  246. ULONG i;
  247. DbgPrint("GetConnectionHandle returned success\n");
  248. ZwClose(Handle);
  249. for ( i = 0, pwcLC = (PWCHAR) ConnectName; i < ConnectNameLen && *pwcLC!= L':'; i+=sizeof(WCHAR), pwcLC++ );
  250. if ( i >= sizeof(WCHAR) && i < ConnectNameLen )
  251. {
  252. pwcLC--;
  253. if ( *pwcLC >= L'A' && *pwcLC <= L'Z' )
  254. {
  255. ExAcquireFastMutex( &pDeviceExtension->LCMutex );
  256. pDeviceExtension->LocalConnections[*pwcLC - L'A'] = TRUE;
  257. ExReleaseFastMutex( &pDeviceExtension->LCMutex );
  258. }
  259. }
  260. }
  261. else
  262. {
  263. DbgPrint("GetConnectionHandle returned failure\n");
  264. Status = STATUS_BAD_NETWORK_NAME;
  265. }
  266. return(Status);
  267. }
  268. NTSTATUS
  269. NulMRxCreateConnection (
  270. IN PRX_CONTEXT RxContext,
  271. OUT PBOOLEAN PostToFsp
  272. )
  273. /*++
  274. Routine Description:
  275. Arguments:
  276. IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
  277. Return Value:
  278. RXSTATUS
  279. --*/
  280. {
  281. NTSTATUS Status = STATUS_SUCCESS;
  282. BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
  283. BOOLEAN InFSD = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP);
  284. PAGED_CODE();
  285. DbgPrint("NulMrxCreateConnection called\n");
  286. RxDbgTrace(+1, Dbg, ("NulMRxCreateConnection \n"));
  287. if (!Wait) {
  288. //just post right now!
  289. *PostToFsp = TRUE;
  290. return STATUS_PENDING;
  291. }
  292. Status = DoCreateConnection(RxContext, (ULONG)FILE_OPEN_IF);
  293. return Status;
  294. }
  295. NTSTATUS
  296. DoDeleteConnection(
  297. PUNICODE_STRING FileName
  298. )
  299. {
  300. HANDLE Handle;
  301. NTSTATUS Status = STATUS_INVALID_HANDLE;
  302. PFILE_OBJECT pFileObject;
  303. PNET_ROOT NetRoot;
  304. PV_NET_ROOT VNetRoot;
  305. PFOBX Fobx;
  306. Handle = GetConnectionHandle(FileName);
  307. if ( INVALID_HANDLE_VALUE != Handle ) {
  308. DbgPrint("GetConnectionHandle returned success\n");
  309. Status = ObReferenceObjectByHandle(
  310. Handle,
  311. 0L,
  312. NULL,
  313. KernelMode,
  314. (PVOID *)&pFileObject,
  315. NULL);
  316. DbgPrint("ObReferenceObjectByHandle worked ok\n");
  317. if ( NT_SUCCESS(Status) ) {
  318. // Got the FileObject. Now get an Fobx
  319. Fobx = pFileObject->FsContext2;
  320. if (NodeType(Fobx)==RDBSS_NTC_V_NETROOT) {
  321. VNetRoot = (PV_NET_ROOT)(Fobx);
  322. NetRoot = (PNET_ROOT)VNetRoot->NetRoot;
  323. DbgPrint("Calling RxFinalizeConnection\n");
  324. Status = RxFinalizeConnection(NetRoot,VNetRoot,TRUE);
  325. } else {
  326. ASSERT(FALSE);
  327. Status = STATUS_INVALID_DEVICE_REQUEST;
  328. }
  329. ObDereferenceObject(pFileObject);
  330. }
  331. ZwClose(Handle);
  332. }
  333. return Status;
  334. }
  335. NTSTATUS
  336. NulMRxDeleteConnection (
  337. IN PRX_CONTEXT RxContext,
  338. OUT PBOOLEAN PostToFsp
  339. )
  340. /*++
  341. Routine Description:
  342. This routine deletes a single vnetroot.
  343. Arguments:
  344. IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
  345. Return Value:
  346. RXSTATUS
  347. --*/
  348. {
  349. NTSTATUS Status;
  350. UNICODE_STRING FileName;
  351. BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
  352. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  353. PWCHAR ConnectName = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
  354. ULONG ConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
  355. NulMRxGetDeviceExtension(RxContext,pDeviceExtension);
  356. PAGED_CODE();
  357. //RxDbgTrace(+1, Dbg, ("NulMRxDeleteConnection Fobx %08lx\n", capFobx));
  358. if (!Wait) {
  359. //just post right now!
  360. *PostToFsp = TRUE;
  361. return(STATUS_PENDING);
  362. }
  363. FileName.Buffer = ConnectName;
  364. FileName.Length = (USHORT) ConnectNameLen;
  365. FileName.MaximumLength = (USHORT) ConnectNameLen;
  366. Status = DoDeleteConnection(&FileName);
  367. if ( NT_SUCCESS(Status) ) {
  368. PWCHAR pwcLC;
  369. ULONG i;
  370. for ( i = 0, pwcLC = ConnectName; i < ConnectNameLen && *pwcLC!= L':';
  371. i+=sizeof(WCHAR), pwcLC++ );
  372. if ( i >= sizeof(WCHAR) && i < ConnectNameLen )
  373. {
  374. pwcLC--;
  375. if ( *pwcLC >= L'A' && *pwcLC <= L'Z' )
  376. {
  377. ExAcquireFastMutex( &pDeviceExtension->LCMutex );
  378. pDeviceExtension->LocalConnections[*pwcLC - L'A'] = FALSE;
  379. ExReleaseFastMutex( &pDeviceExtension->LCMutex );
  380. }
  381. }
  382. }
  383. return Status;
  384. }