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.

722 lines
18 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. NdsApiNT.c
  5. Abstract:
  6. This module implements the NT specific exposed user-mode link to
  7. Netware NDS support in the Netware redirector. For
  8. more comments, see ndslib32.h.
  9. Author:
  10. Cory West [CoryWest] 23-Feb-1995
  11. --*/
  12. #include <procs.h>
  13. NTSTATUS
  14. NwNdsOpenTreeHandle(
  15. IN PUNICODE_STRING puNdsTree,
  16. OUT PHANDLE phNwRdrHandle
  17. ) {
  18. NTSTATUS ntstatus, OpenStatus;
  19. IO_STATUS_BLOCK IoStatusBlock;
  20. OBJECT_ATTRIBUTES ObjectAttributes;
  21. ACCESS_MASK DesiredAccess = SYNCHRONIZE | FILE_LIST_DIRECTORY;
  22. WCHAR DevicePreamble[] = L"\\Device\\Nwrdr\\";
  23. UINT PreambleLength = 14;
  24. WCHAR NameStr[128];
  25. UNICODE_STRING uOpenName;
  26. UINT i;
  27. PNWR_NDS_REQUEST_PACKET Rrp;
  28. BYTE RrpData[1024];
  29. //
  30. // Prepare the open name.
  31. //
  32. uOpenName.MaximumLength = sizeof( NameStr );
  33. if ( puNdsTree->Length > (MAX_NDS_TREE_NAME_LEN * sizeof(WCHAR)))
  34. return STATUS_INVALID_PARAMETER;
  35. for ( i = 0; i < PreambleLength ; i++ )
  36. NameStr[i] = DevicePreamble[i];
  37. try {
  38. for ( i = 0 ; i < ( puNdsTree->Length / sizeof( WCHAR ) ) ; i++ ) {
  39. NameStr[i + PreambleLength] = puNdsTree->Buffer[i];
  40. }
  41. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  42. return STATUS_INVALID_PARAMETER;
  43. }
  44. uOpenName.Length = (USHORT)(( i * sizeof( WCHAR ) ) +
  45. ( PreambleLength * sizeof( WCHAR ) ));
  46. uOpenName.Buffer = NameStr;
  47. //
  48. // Set up the object attributes.
  49. //
  50. InitializeObjectAttributes(
  51. &ObjectAttributes,
  52. &uOpenName,
  53. OBJ_CASE_INSENSITIVE,
  54. NULL,
  55. NULL );
  56. ntstatus = NtOpenFile(
  57. phNwRdrHandle,
  58. DesiredAccess,
  59. &ObjectAttributes,
  60. &IoStatusBlock,
  61. FILE_SHARE_VALID_FLAGS,
  62. FILE_SYNCHRONOUS_IO_NONALERT
  63. );
  64. if ( !NT_SUCCESS(ntstatus) )
  65. return ntstatus;
  66. OpenStatus = IoStatusBlock.Status;
  67. //
  68. // Verify that this is a tree handle, not a server handle.
  69. //
  70. Rrp = (PNWR_NDS_REQUEST_PACKET)RrpData;
  71. Rrp->Version = 0;
  72. RtlCopyMemory( &(Rrp->Parameters).VerifyTree,
  73. puNdsTree,
  74. sizeof( UNICODE_STRING ) );
  75. RtlCopyMemory( (BYTE *)(&(Rrp->Parameters).VerifyTree.NameString),
  76. puNdsTree->Buffer,
  77. puNdsTree->Length );
  78. (Rrp->Parameters).VerifyTree.TreeName.Buffer = (Rrp->Parameters).VerifyTree.NameString;
  79. try {
  80. ntstatus = NtFsControlFile( *phNwRdrHandle,
  81. NULL,
  82. NULL,
  83. NULL,
  84. &IoStatusBlock,
  85. FSCTL_NWR_NDS_VERIFY_TREE,
  86. (PVOID) Rrp,
  87. sizeof( NWR_NDS_REQUEST_PACKET ) + puNdsTree->Length,
  88. NULL,
  89. 0 );
  90. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  91. ntstatus = GetExceptionCode();
  92. goto CloseAndExit;
  93. }
  94. if ( !NT_SUCCESS( ntstatus )) {
  95. goto CloseAndExit;
  96. }
  97. //
  98. // Otherwise, all is well!
  99. //
  100. return OpenStatus;
  101. CloseAndExit:
  102. NtClose( *phNwRdrHandle );
  103. *phNwRdrHandle = NULL;
  104. return ntstatus;
  105. }
  106. NTSTATUS
  107. NwOpenHandleWithSupplementalCredentials(
  108. IN PUNICODE_STRING puResourceName,
  109. IN PUNICODE_STRING puUserName,
  110. IN PUNICODE_STRING puPassword,
  111. OUT LPDWORD lpdwHandleType,
  112. OUT PHANDLE phNwHandle
  113. ) {
  114. NTSTATUS ntstatus, OpenStatus;
  115. IO_STATUS_BLOCK IoStatusBlock;
  116. OBJECT_ATTRIBUTES ObjectAttributes;
  117. ACCESS_MASK DesiredAccess = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
  118. WCHAR DevicePreamble[] = L"\\Device\\Nwrdr\\";
  119. UINT PreambleLength = 14;
  120. WCHAR NameStr[128];
  121. UNICODE_STRING uOpenName;
  122. UINT i;
  123. PFILE_FULL_EA_INFORMATION pEaEntry;
  124. PBYTE EaBuffer;
  125. ULONG EaLength, EaNameLength, EaTotalLength;
  126. ULONG UserNameLen, PasswordLen, TypeLen, CredLen;
  127. PNWR_NDS_REQUEST_PACKET Rrp;
  128. BYTE RrpData[1024];
  129. //
  130. // Prepare the open name.
  131. //
  132. uOpenName.MaximumLength = sizeof( NameStr );
  133. if ( puResourceName->Length > uOpenName.MaximumLength - ( PreambleLength * sizeof(WCHAR) ) )
  134. return STATUS_INVALID_PARAMETER;
  135. for ( i = 0; i < PreambleLength ; i++ )
  136. NameStr[i] = DevicePreamble[i];
  137. try {
  138. for ( i = 0 ; i < ( puResourceName->Length / sizeof( WCHAR ) ) ; i++ ) {
  139. NameStr[i + PreambleLength] = puResourceName->Buffer[i];
  140. }
  141. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  142. return STATUS_INVALID_PARAMETER;
  143. }
  144. uOpenName.Length = (USHORT)(( i * sizeof( WCHAR ) ) +
  145. ( PreambleLength * sizeof( WCHAR ) ));
  146. uOpenName.Buffer = NameStr;
  147. //
  148. // Set up the object attributes.
  149. //
  150. InitializeObjectAttributes(
  151. &ObjectAttributes,
  152. &uOpenName,
  153. OBJ_CASE_INSENSITIVE,
  154. NULL,
  155. NULL );
  156. //
  157. // Allocate the EA buffer - be a little generous.
  158. //
  159. UserNameLen = strlen( EA_NAME_USERNAME );
  160. PasswordLen = strlen( EA_NAME_PASSWORD );
  161. TypeLen = strlen( EA_NAME_TYPE );
  162. CredLen = strlen( EA_NAME_CREDENTIAL_EX );
  163. EaLength = 4 * sizeof( FILE_FULL_EA_INFORMATION );
  164. EaLength += 4 * sizeof( ULONG );
  165. EaLength += ROUNDUP4( UserNameLen );
  166. EaLength += ROUNDUP4( PasswordLen );
  167. EaLength += ROUNDUP4( TypeLen );
  168. EaLength += ROUNDUP4( CredLen );
  169. EaLength += ROUNDUP4( puUserName->Length );
  170. EaLength += ROUNDUP4( puPassword->Length );
  171. EaBuffer = LocalAlloc( LMEM_ZEROINIT, EaLength );
  172. if ( !EaBuffer ) {
  173. return STATUS_INSUFFICIENT_RESOURCES;
  174. }
  175. //
  176. // Pack in the first EA: UserName.
  177. //
  178. pEaEntry = (PFILE_FULL_EA_INFORMATION) EaBuffer;
  179. EaNameLength = UserNameLen + sizeof( CHAR );
  180. pEaEntry->EaNameLength = (UCHAR) EaNameLength;
  181. pEaEntry->EaValueLength = puUserName->Length;
  182. RtlCopyMemory( &(pEaEntry->EaName[0]),
  183. EA_NAME_USERNAME,
  184. EaNameLength );
  185. EaNameLength = ROUNDUP2( EaNameLength + sizeof( CHAR ) );
  186. RtlCopyMemory( &(pEaEntry->EaName[EaNameLength]),
  187. puUserName->Buffer,
  188. puUserName->Length );
  189. EaLength = ( 2 * sizeof( DWORD ) ) +
  190. EaNameLength +
  191. puUserName->Length;
  192. EaLength = ROUNDUP4( EaLength );
  193. EaTotalLength = EaLength;
  194. pEaEntry->NextEntryOffset = EaLength;
  195. //
  196. // Pack in the second EA: Password.
  197. //
  198. pEaEntry = (PFILE_FULL_EA_INFORMATION)
  199. ( ( (PBYTE)pEaEntry ) + pEaEntry->NextEntryOffset );
  200. EaNameLength = PasswordLen + sizeof( CHAR );
  201. pEaEntry->EaNameLength = (UCHAR) EaNameLength;
  202. pEaEntry->EaValueLength = puPassword->Length;
  203. RtlCopyMemory( &(pEaEntry->EaName[0]),
  204. EA_NAME_PASSWORD,
  205. EaNameLength );
  206. EaNameLength = ROUNDUP2( EaNameLength + sizeof( CHAR ) );
  207. RtlCopyMemory( &(pEaEntry->EaName[EaNameLength]),
  208. puPassword->Buffer,
  209. puPassword->Length );
  210. EaLength = ( 2 * sizeof( DWORD ) ) +
  211. EaNameLength +
  212. puPassword->Length;
  213. EaLength = ROUNDUP4( EaLength );
  214. EaTotalLength += EaLength;
  215. pEaEntry->NextEntryOffset = EaLength;
  216. //
  217. // Pack in the third EA: Type.
  218. //
  219. pEaEntry = (PFILE_FULL_EA_INFORMATION)
  220. ( ( (PBYTE)pEaEntry ) + pEaEntry->NextEntryOffset );
  221. EaNameLength = TypeLen + sizeof( CHAR );
  222. pEaEntry->EaNameLength = (UCHAR) EaNameLength;
  223. pEaEntry->EaValueLength = sizeof( ULONG );
  224. RtlCopyMemory( &(pEaEntry->EaName[0]),
  225. EA_NAME_TYPE,
  226. EaNameLength );
  227. EaNameLength = ROUNDUP2( EaNameLength + sizeof( CHAR ) );
  228. EaLength = ( 2 * sizeof( DWORD ) ) +
  229. EaNameLength +
  230. sizeof( ULONG );
  231. EaLength = ROUNDUP4( EaLength );
  232. EaTotalLength += EaLength;
  233. pEaEntry->NextEntryOffset = EaLength;
  234. //
  235. // Pack in the fourth EA: the CredentialEx flag.
  236. //
  237. pEaEntry = (PFILE_FULL_EA_INFORMATION)
  238. ( ( (PBYTE)pEaEntry ) + pEaEntry->NextEntryOffset );
  239. EaNameLength = CredLen + sizeof( CHAR );
  240. pEaEntry->EaNameLength = (UCHAR) EaNameLength;
  241. pEaEntry->EaValueLength = sizeof( ULONG );
  242. RtlCopyMemory( &(pEaEntry->EaName[0]),
  243. EA_NAME_CREDENTIAL_EX,
  244. EaNameLength );
  245. EaNameLength = ROUNDUP2( EaNameLength + sizeof( CHAR ) );
  246. EaLength = ( 2 * sizeof( DWORD ) ) +
  247. EaNameLength +
  248. sizeof( ULONG );
  249. EaLength = ROUNDUP4( EaLength );
  250. EaTotalLength += EaLength;
  251. pEaEntry->NextEntryOffset = 0;
  252. //
  253. // Do the open.
  254. //
  255. ntstatus = NtCreateFile( phNwHandle, // File handle (OUT)
  256. DesiredAccess, // Access mask
  257. &ObjectAttributes, // Object attributes
  258. &IoStatusBlock, // Io status
  259. NULL, // Optional Allocation size
  260. FILE_ATTRIBUTE_NORMAL, // File attributes
  261. FILE_SHARE_VALID_FLAGS, // File share access
  262. FILE_OPEN, // Create disposition
  263. 0, // Create options
  264. (PVOID) EaBuffer, // Our EA buffer
  265. EaTotalLength ); // Ea buffer length
  266. LocalFree( EaBuffer );
  267. if ( !NT_SUCCESS(ntstatus) )
  268. return ntstatus;
  269. OpenStatus = IoStatusBlock.Status;
  270. //
  271. // Check the handle type.
  272. //
  273. Rrp = (PNWR_NDS_REQUEST_PACKET)RrpData;
  274. Rrp->Version = 0;
  275. RtlCopyMemory( &(Rrp->Parameters).VerifyTree,
  276. puResourceName,
  277. sizeof( UNICODE_STRING ) );
  278. RtlCopyMemory( (BYTE *)(&(Rrp->Parameters).VerifyTree) + sizeof( UNICODE_STRING ),
  279. puResourceName->Buffer,
  280. puResourceName->Length );
  281. try {
  282. ntstatus = NtFsControlFile( *phNwHandle,
  283. NULL,
  284. NULL,
  285. NULL,
  286. &IoStatusBlock,
  287. FSCTL_NWR_NDS_VERIFY_TREE,
  288. (PVOID) Rrp,
  289. sizeof( NWR_NDS_REQUEST_PACKET ) + puResourceName->Length,
  290. NULL,
  291. 0 );
  292. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  293. ntstatus = GetExceptionCode();
  294. goto CloseAndExit2;
  295. }
  296. if ( !NT_SUCCESS( ntstatus ))
  297. {
  298. *lpdwHandleType = HANDLE_TYPE_NCP_SERVER;
  299. }
  300. else
  301. {
  302. *lpdwHandleType = HANDLE_TYPE_NDS_TREE;
  303. }
  304. return OpenStatus;
  305. CloseAndExit2:
  306. NtClose( *phNwHandle );
  307. *phNwHandle = NULL;
  308. return ntstatus;
  309. }
  310. NTSTATUS
  311. NwNdsResolveName (
  312. IN HANDLE hNdsTree,
  313. IN PUNICODE_STRING puObjectName,
  314. OUT DWORD *dwObjectId,
  315. OUT PUNICODE_STRING puReferredServer,
  316. OUT PBYTE pbRawResponse,
  317. IN DWORD dwResponseBufferLen
  318. ) {
  319. NTSTATUS ntstatus;
  320. IO_STATUS_BLOCK IoStatusBlock;
  321. PNWR_NDS_REQUEST_PACKET Rrp;
  322. PNDS_RESPONSE_RESOLVE_NAME Rsp;
  323. DWORD dwRspBufferLen, dwNameLen, dwPadding;
  324. BYTE RrpData[1024];
  325. BYTE RspData[256];
  326. Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
  327. RtlZeroMemory( Rrp, 1024 );
  328. //
  329. // NW NDS strings are null terminated, so we make sure we
  330. // report the correct length...
  331. //
  332. dwNameLen = puObjectName->Length + sizeof( WCHAR );
  333. if (dwNameLen > MAX_NDS_NAME_SIZE)
  334. {
  335. return STATUS_INVALID_PARAMETER;
  336. }
  337. Rrp->Version = 0;
  338. Rrp->Parameters.ResolveName.ObjectNameLength = ROUNDUP4( dwNameLen );
  339. Rrp->Parameters.ResolveName.ResolverFlags = RSLV_DEREF_ALIASES |
  340. RSLV_WALK_TREE |
  341. RSLV_WRITABLE;
  342. try {
  343. //
  344. // But don't try to copy more than the user gave us.
  345. //
  346. memcpy( Rrp->Parameters.ResolveName.ObjectName,
  347. puObjectName->Buffer,
  348. puObjectName->Length );
  349. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  350. return STATUS_INVALID_PARAMETER;
  351. }
  352. //
  353. // Send the request to the Redirector FSD.
  354. //
  355. if ( dwResponseBufferLen != 0 &&
  356. pbRawResponse != NULL ) {
  357. Rsp = ( PNDS_RESPONSE_RESOLVE_NAME ) pbRawResponse;
  358. dwRspBufferLen = dwResponseBufferLen;
  359. } else {
  360. Rsp = ( PNDS_RESPONSE_RESOLVE_NAME ) RspData;
  361. dwRspBufferLen = 256;
  362. }
  363. try {
  364. ntstatus = NtFsControlFile( hNdsTree,
  365. NULL,
  366. NULL,
  367. NULL,
  368. &IoStatusBlock,
  369. FSCTL_NWR_NDS_RESOLVE_NAME,
  370. (PVOID) Rrp,
  371. sizeof( NWR_NDS_REQUEST_PACKET ) + Rrp->Parameters.ResolveName.ObjectNameLength,
  372. (PVOID) Rsp,
  373. dwRspBufferLen );
  374. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  375. return GetExceptionCode();
  376. }
  377. //
  378. // Dig out the object id and referred server.
  379. //
  380. if ( NT_SUCCESS( ntstatus ) ) {
  381. try {
  382. *dwObjectId = Rsp->EntryId;
  383. if ( Rsp->ServerNameLength > puReferredServer->MaximumLength ) {
  384. ntstatus = STATUS_BUFFER_TOO_SMALL;
  385. } else {
  386. RtlCopyMemory( puReferredServer->Buffer,
  387. Rsp->ReferredServer,
  388. Rsp->ServerNameLength );
  389. puReferredServer->Length = (USHORT)Rsp->ServerNameLength;
  390. }
  391. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  392. return ntstatus;
  393. }
  394. }
  395. return ntstatus;
  396. }
  397. int
  398. _cdecl
  399. FormatBuf(
  400. char *buf,
  401. int bufLen,
  402. const char *format,
  403. va_list args
  404. );
  405. int
  406. _cdecl
  407. CalculateBuf(
  408. const char *format,
  409. va_list args
  410. );
  411. NTSTATUS
  412. _cdecl
  413. FragExWithWait(
  414. IN HANDLE hNdsServer,
  415. IN DWORD NdsVerb,
  416. IN BYTE *pReplyBuffer,
  417. IN DWORD pReplyBufferLen,
  418. IN OUT DWORD *pdwReplyLen,
  419. IN BYTE *NdsRequestStr,
  420. ...
  421. )
  422. /*
  423. Routine Description:
  424. Exchanges an NDS request in fragments and collects the fragments
  425. of the response and writes them to the reply buffer.
  426. Routine Arguments:
  427. hNdsServer - A handle to the server you want to talk to.
  428. NdsVerb - The verb for that indicates the request.
  429. pReplyBuffer - The reply buffer.
  430. pReplyBufferLen - The length of the reply buffer.
  431. NdsReqestStr - The format string for the arguments to this NDS request.
  432. Arguments - The arguments that satisfy the NDS format string.
  433. Return Value:
  434. NTSTATUS - Status of the exchange, but not the result code in the packet.
  435. */
  436. {
  437. NTSTATUS Status;
  438. IO_STATUS_BLOCK IoStatusBlock;
  439. PNWR_NDS_REQUEST_PACKET RawRequest = NULL;
  440. BYTE *NdsRequestBuf;
  441. DWORD NdsRequestLen;
  442. int bufferSize = 0;
  443. va_list Arguments;
  444. //
  445. // Allocate a request buffer.
  446. //
  447. //
  448. // Calculate needed buffer size . . .
  449. //
  450. if ( NdsRequestStr != NULL ) {
  451. va_start( Arguments, NdsRequestStr );
  452. bufferSize = CalculateBuf( NdsRequestStr, Arguments );
  453. va_end( Arguments );
  454. if ( bufferSize == 0 )
  455. {
  456. Status = STATUS_INVALID_PARAMETER;
  457. goto ExitWithCleanup;
  458. }
  459. }
  460. bufferSize += sizeof( NWR_NDS_REQUEST_PACKET ) + 50;
  461. RawRequest = LocalAlloc( LMEM_ZEROINIT, bufferSize );
  462. if ( !RawRequest ) {
  463. return STATUS_INSUFFICIENT_RESOURCES;
  464. }
  465. //
  466. // Build the request in our local buffer. The first DWORD
  467. // is the verb and the rest is the formatted request.
  468. //
  469. RawRequest->Parameters.RawRequest.NdsVerb = NdsVerb;
  470. NdsRequestBuf = &RawRequest->Parameters.RawRequest.Request[0];
  471. if ( NdsRequestStr != NULL ) {
  472. va_start( Arguments, NdsRequestStr );
  473. NdsRequestLen = FormatBuf( NdsRequestBuf,
  474. bufferSize - sizeof( NWR_NDS_REQUEST_PACKET ),
  475. NdsRequestStr,
  476. Arguments );
  477. if ( !NdsRequestLen ) {
  478. Status = STATUS_INVALID_PARAMETER;
  479. goto ExitWithCleanup;
  480. }
  481. va_end( Arguments );
  482. } else {
  483. NdsRequestLen = 0;
  484. }
  485. RawRequest->Parameters.RawRequest.RequestLength = NdsRequestLen;
  486. //
  487. // Pass this buffer to kernel mode via FSCTL.
  488. //
  489. try {
  490. Status = NtFsControlFile( hNdsServer,
  491. NULL,
  492. NULL,
  493. NULL,
  494. &IoStatusBlock,
  495. FSCTL_NWR_NDS_RAW_FRAGEX,
  496. (PVOID) RawRequest,
  497. NdsRequestLen + sizeof( NWR_NDS_REQUEST_PACKET ),
  498. (PVOID) pReplyBuffer,
  499. pReplyBufferLen );
  500. if ( NT_SUCCESS( Status ) ) {
  501. *pdwReplyLen = RawRequest->Parameters.RawRequest.ReplyLength;
  502. }
  503. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  504. Status = GetExceptionCode();
  505. }
  506. ExitWithCleanup:
  507. if ( RawRequest ) {
  508. LocalFree( RawRequest );
  509. }
  510. return Status;
  511. }