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.

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