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.

1643 lines
38 KiB

  1. /*************************************************************************
  2. *
  3. * NDS.C
  4. *
  5. * NT NetWare NDS routines
  6. *
  7. * Copyright (c) 1995 Microsoft Corporation
  8. *
  9. *************************************************************************/
  10. #include <common.h>
  11. DWORD GUserObjectID;
  12. HANDLE GhRdrForUser;
  13. HANDLE GhRdr;
  14. WCHAR * NDSTREE_w = NULL;
  15. UNICODE_STRING NDSTREE_u;
  16. /********************************************************************
  17. ExpandRelativeName
  18. Routine Description:
  19. If the name is a relative NDS name append the proper context
  20. to the end. A relative name has periods on the end. Each
  21. period represents one level up the NDS tree.
  22. Arguments:
  23. Return Value:
  24. *******************************************************************/
  25. void
  26. ExpandRelativeName( LPSTR RelativeName, LPSTR AbsoluteName, unsigned int Len,
  27. LPSTR Context )
  28. {
  29. PBYTE ptr;
  30. unsigned int i;
  31. unsigned int count = 0;
  32. strncpy( AbsoluteName, RelativeName, Len );
  33. if ( ( AbsoluteName[0] == '.' ) &&
  34. ( AbsoluteName[ strlen( AbsoluteName ) - 1 ] != '.' ) )
  35. return;
  36. if ( ( strlen( AbsoluteName ) + strlen( Context ) ) > Len )
  37. {
  38. DisplayMessage( IDR_NOT_ENOUGH_MEMORY );
  39. return;
  40. }
  41. if ( AbsoluteName[0] == '\0' )
  42. {
  43. return;
  44. }
  45. ptr = &AbsoluteName[ strlen( AbsoluteName ) - 1 ];
  46. // Count the number of periods and back up over them.
  47. if ( *ptr != '.' )
  48. {
  49. //
  50. // No periods at the end
  51. // Assume this is a relative name and append the context
  52. //
  53. strcat( AbsoluteName, "." );
  54. strcat( AbsoluteName + strlen( AbsoluteName ), Context );
  55. return;
  56. }
  57. while ( *ptr == '.' )
  58. {
  59. ptr--;
  60. count++;
  61. }
  62. ptr++;
  63. *ptr = '\0';
  64. // ptr now points to where the copy of the rest of the context should start
  65. // skip the first "count" entries in the context
  66. ptr = Context;
  67. for ( i = 0; i < count; i++ )
  68. {
  69. ptr = strchr( ptr, '.' );
  70. if ( ptr == NULL )
  71. {
  72. return;
  73. }
  74. ptr++;
  75. }
  76. ptr--;
  77. // Now append
  78. strcat( AbsoluteName, ptr );
  79. }
  80. /********************************************************************
  81. NDSGetNameContext
  82. Routine Description:
  83. Get the current context
  84. Arguments:
  85. none
  86. Return Value:
  87. none
  88. *******************************************************************/
  89. NTSTATUS
  90. NDSGetNameContext( LPSTR Context, BOOLEAN flag )
  91. {
  92. //
  93. // For NdsResolveName.
  94. //
  95. UNICODE_STRING ReferredServer;
  96. WCHAR ServerStr[MAX_NAME_LEN];
  97. HANDLE hReferredServer;
  98. DWORD dwHandleType;
  99. NTSTATUS Status;
  100. OEM_STRING oemStr;
  101. UNICODE_STRING defaultcontext;
  102. DWORD ThisObjectID;
  103. BYTE Buffer[2048];
  104. WCHAR NdsStr[1024];
  105. PBYTE ptr;
  106. defaultcontext.Length = 0;
  107. defaultcontext.MaximumLength = sizeof( NdsStr );
  108. defaultcontext.Buffer = NdsStr;
  109. Status = NwNdsGetTreeContext( GhRdr, &NDSTREE_u, &defaultcontext );
  110. if ( !NT_SUCCESS( Status ) ) {
  111. return Status;
  112. }
  113. ReferredServer.Buffer = ServerStr;
  114. ReferredServer.Length = 0;
  115. ReferredServer.MaximumLength = sizeof( ServerStr );
  116. Status = NwNdsResolveName ( GhRdr,
  117. &defaultcontext,
  118. &ThisObjectID,
  119. &ReferredServer,
  120. NULL,
  121. 0 );
  122. if ( !NT_SUCCESS( Status ) ) {
  123. return Status;
  124. }
  125. if ( ReferredServer.Length > 0 ) {
  126. //
  127. // We've been referred to another server, so we
  128. // should change the global handle.
  129. //
  130. Status = NwNdsOpenGenericHandle( &ReferredServer,
  131. &dwHandleType,
  132. &hReferredServer );
  133. if ( !NT_SUCCESS( Status ) ) {
  134. DisplayMessage(IDR_NDS_USERNAME_FAILED);
  135. return Status;
  136. }
  137. if( GhRdr != GhRdrForUser ) {
  138. CloseHandle( GhRdr );
  139. }
  140. GhRdr = hReferredServer;
  141. }
  142. Status = NwNdsReadObjectInfo( GhRdr, ThisObjectID, Buffer, 2048 );
  143. if ( !NT_SUCCESS( Status ) ) {
  144. return Status;
  145. }
  146. ptr = Buffer + sizeof( NDS_RESPONSE_GET_OBJECT_INFO );
  147. ptr += ROUNDUP4(*(DWORD *)ptr);
  148. ptr += sizeof(DWORD);
  149. ptr += sizeof(DWORD);
  150. defaultcontext.Length = wcslen( (WCHAR *)ptr ) * 2;
  151. defaultcontext.MaximumLength = defaultcontext.Length;
  152. defaultcontext.Buffer = (WCHAR *)ptr;
  153. oemStr.Length = 0;
  154. oemStr.MaximumLength = NDS_NAME_CHARS;
  155. oemStr.Buffer = Context;
  156. RtlUnicodeStringToOemString( &oemStr, &defaultcontext, FALSE );
  157. return 0;
  158. }
  159. /********************************************************************
  160. NDSTypeless
  161. Routine Description:
  162. Change name to typelese
  163. Arguments:
  164. none
  165. Return Value:
  166. none
  167. *******************************************************************/
  168. unsigned int
  169. NDSTypeless( LPSTR OrigName , LPSTR TypelessName )
  170. {
  171. int i,j;
  172. PBYTE p;
  173. i = 0;
  174. j = 0;
  175. if ( !_strnicmp( "CN=", OrigName, 3 ) ||
  176. !_strnicmp( "OU=", OrigName, 3 ) )
  177. {
  178. i += 3;
  179. }
  180. else if ( !_strnicmp( "C=", OrigName, 2 ) ||
  181. !_strnicmp( "O=", OrigName, 2 ) )
  182. {
  183. i += 2;
  184. }
  185. for ( ; (( i < NDS_NAME_CHARS ) && ( OrigName[i] ) ); i++ )
  186. {
  187. if ( !_strnicmp( ".CN=", &OrigName[i], 4 ) ||
  188. !_strnicmp( ".OU=", &OrigName[i], 4 ) )
  189. {
  190. TypelessName[j++]= '.';
  191. i += 3;
  192. continue;
  193. }
  194. if ( !_strnicmp( ".C=", &OrigName[i], 3 ) ||
  195. !_strnicmp( ".O=", &OrigName[i], 3 ) )
  196. {
  197. TypelessName[j++]= '.';
  198. i += 2;
  199. continue;
  200. }
  201. /*
  202. * Strip out multiple blanks
  203. */
  204. if ( !_strnicmp( " ", &OrigName[i], 2 ) )
  205. {
  206. continue;
  207. }
  208. TypelessName[j++] = OrigName[i];
  209. }
  210. TypelessName[j] = '\0';
  211. return 0;
  212. }
  213. /********************************************************************
  214. NDSAbbreviateName
  215. Routine Description:
  216. Abbreviate name
  217. Arguments:
  218. none
  219. Return Value:
  220. none
  221. *******************************************************************/
  222. unsigned int
  223. NDSAbbreviateName( DWORD Flags, LPSTR OrigName , LPSTR AbbrevName )
  224. {
  225. BYTE Buffer[NDS_NAME_CHARS];
  226. BYTE CurrentContext[NDS_NAME_CHARS];
  227. PBYTE p;
  228. PBYTE c;
  229. NTSTATUS Status;
  230. if ( OrigName[0] == '.' )
  231. NDSTypeless( OrigName + 1, Buffer );
  232. else
  233. NDSTypeless( OrigName, Buffer );
  234. /*
  235. * We want a relative name
  236. */
  237. if ( Flags & FLAGS_LOCAL_CONTEXT )
  238. {
  239. p = &Buffer[strlen(Buffer)-strlen(REQUESTER_CONTEXT)];
  240. if ( !_strcmpi( REQUESTER_CONTEXT, p ) )
  241. {
  242. // The name is below us
  243. if ( ( *(p-1) == '.' ) && ( p > Buffer ) )
  244. p--;
  245. *p = '\0';
  246. strcpy( AbbrevName, Buffer );
  247. }
  248. else
  249. {
  250. //
  251. // Going from back to front for each section of context
  252. // in common with AbbrevName
  253. // truncate both
  254. // Going from back to front for each section of context
  255. // left over
  256. // concatonate a period to AbbrevName
  257. //
  258. // Example
  259. //
  260. // Name: w.x.y.z Context: a.b.z => w.x.y..
  261. //
  262. strcpy( CurrentContext, REQUESTER_CONTEXT );
  263. strcpy( AbbrevName, Buffer );
  264. if ( CurrentContext[0] && AbbrevName[0] )
  265. {
  266. c = &CurrentContext[ strlen( CurrentContext ) ] - 1;
  267. p = &AbbrevName[ strlen( AbbrevName ) ] - 1;
  268. //
  269. // Strip off the matching names from end to front
  270. //
  271. for ( ;; )
  272. {
  273. if ( ( c == CurrentContext ) && ( *p == '.' ) )
  274. {
  275. *c = '\0';
  276. *p = '\0';
  277. break;
  278. }
  279. if ( *c != *p )
  280. break;
  281. if ( ( *c == '.' ) && ( *p == '.' ) )
  282. {
  283. *c = '\0';
  284. *p = '\0';
  285. }
  286. if ( ( c == CurrentContext ) || ( p == AbbrevName ) )
  287. {
  288. break;
  289. }
  290. c--; p--;
  291. }
  292. //
  293. // Count the remaining sections of the context and
  294. // add that number of periods to the end of the buffer.
  295. // That is how far we need to back up before getting
  296. // to a matching branch of the tree.
  297. //
  298. if ( CurrentContext[0] ) {
  299. strcat( AbbrevName, "." );
  300. for ( c = CurrentContext; *c; c++ ) {
  301. if ( *c == '.' )
  302. strcat( AbbrevName, "." );
  303. }
  304. }
  305. }
  306. }
  307. }
  308. else
  309. strcpy( AbbrevName, Buffer );
  310. return 0;
  311. }
  312. /********************************************************************
  313. NDSInitUserProperty
  314. Routine Description:
  315. none
  316. Arguments:
  317. none
  318. Return Value:
  319. 0 = no error
  320. *******************************************************************/
  321. unsigned int
  322. NDSInitUserProperty( )
  323. {
  324. NTSTATUS Status;
  325. UNICODE_STRING ObjectName;
  326. PWCHAR lpT;
  327. UNICODE_STRING defaultcontext;
  328. //
  329. // For NdsResolveName.
  330. //
  331. UNICODE_STRING ReferredServer;
  332. WCHAR ServerStr[MAX_NAME_LEN];
  333. HANDLE hReferredServer;
  334. DWORD dwHandleType;
  335. //
  336. // Get a handle to the redirector.
  337. //
  338. Status = NwNdsOpenTreeHandle( &NDSTREE_u, &GhRdr );
  339. if ( !NT_SUCCESS( Status ) ) {
  340. DisplayMessage(IDR_TREE_OPEN_FAILED);
  341. return 1;
  342. }
  343. //
  344. // Resolve the name that we have to an object id.
  345. //
  346. RtlInitUnicodeString( &ObjectName, TYPED_USER_NAME_w );
  347. ReferredServer.Buffer = ServerStr;
  348. ReferredServer.Length = 0;
  349. ReferredServer.MaximumLength = sizeof( ServerStr );
  350. Status = NwNdsResolveName ( GhRdr,
  351. &ObjectName,
  352. &GUserObjectID,
  353. &ReferredServer,
  354. NULL,
  355. 0 );
  356. if ( !NT_SUCCESS( Status ) ) {
  357. DisplayMessage(IDR_NDS_USERNAME_FAILED);
  358. return 1;
  359. }
  360. if ( ReferredServer.Length > 0 ) {
  361. //
  362. // We've been referred to another server, so we
  363. // should change the global handle.
  364. //
  365. Status = NwNdsOpenGenericHandle( &ReferredServer,
  366. &dwHandleType,
  367. &hReferredServer );
  368. if ( !NT_SUCCESS( Status ) ) {
  369. DisplayMessage(IDR_NDS_USERNAME_FAILED);
  370. return 1;
  371. }
  372. CloseHandle( GhRdr );
  373. GhRdr = hReferredServer;
  374. }
  375. //
  376. // Save off this handle for the user so that we can use it to
  377. // get information about the user.
  378. //
  379. GhRdrForUser = GhRdr;
  380. //
  381. // Set the current context to what we think it should be
  382. // (At the user's location.)
  383. //
  384. lpT = wcschr( TYPED_USER_NAME_w, L'.' );
  385. while (lpT) // handle usernames with embedded/escaped dots
  386. {
  387. if (*(lpT-1) == L'\\')
  388. {
  389. lpT = wcschr (lpT+1, L'.');
  390. }
  391. else
  392. break;
  393. }
  394. if ( lpT )
  395. {
  396. RtlInitUnicodeString( &defaultcontext, lpT+1 );
  397. }
  398. else
  399. {
  400. RtlInitUnicodeString( &defaultcontext, L"" );
  401. }
  402. Status = NwNdsSetTreeContext( GhRdr, &NDSTREE_u, &defaultcontext );
  403. if ( !NT_SUCCESS( Status ) ) {
  404. DisplayMessage(IDR_NDS_CONTEXT_INVALID);
  405. return 1;
  406. }
  407. return 0;
  408. }
  409. /********************************************************************
  410. NDSCanonicalizeName
  411. Routine Description:
  412. return a canonicalized version of a name
  413. Arguments:
  414. Name - original name
  415. CanonName - Canonicalized name
  416. Len - length of CanonName
  417. fCurrentContext - TRUE => use current contex, FALSE use
  418. requester context
  419. Return Value:
  420. status error
  421. *******************************************************************/
  422. unsigned int
  423. NDSCanonicalizeName( PBYTE Name, PBYTE CanonName, int Len, int fCurrentContext )
  424. {
  425. NTSTATUS Status;
  426. int ccode = -1;
  427. DWORD ThisObjectID;
  428. OEM_STRING oemStr;
  429. UNICODE_STRING ObjectName;
  430. BYTE Buffer[2048];
  431. BYTE FullName[NDS_NAME_CHARS];
  432. PBYTE ptr;
  433. UNICODE_STRING ReferredServer;
  434. WCHAR ServerStr[MAX_NAME_LEN];
  435. DWORD dwHandleType;
  436. HANDLE hReferredServer;
  437. unsigned char CurrentContext[NDS_NAME_CHARS];
  438. //
  439. // Cope with relative names
  440. //
  441. if ( fCurrentContext )
  442. {
  443. Status = NDSGetNameContext( CurrentContext, TRUE );
  444. if ( !NT_SUCCESS( Status ) )
  445. return Status;
  446. ExpandRelativeName( Name, FullName, NDS_NAME_CHARS, CurrentContext );
  447. }
  448. else
  449. ExpandRelativeName( Name, FullName, NDS_NAME_CHARS, REQUESTER_CONTEXT );
  450. //
  451. // Fill it in in case we have an error
  452. //
  453. strncpy( CanonName, FullName, Len);
  454. //
  455. // Resolve the name that we have to an object id.
  456. //
  457. // Unfortuneately, the name resolver doesn't understand periods at the
  458. // front or end (absolute or relative names)
  459. //
  460. if ( FullName[0] == '.' )
  461. {
  462. oemStr.Length = (USHORT)strlen( FullName + 1 );
  463. oemStr.MaximumLength = oemStr.Length;
  464. oemStr.Buffer = FullName + 1;
  465. }
  466. else
  467. {
  468. oemStr.Length = (USHORT)strlen( FullName );
  469. oemStr.MaximumLength = oemStr.Length;
  470. oemStr.Buffer = FullName;
  471. }
  472. ObjectName.Length = 0;
  473. ObjectName.MaximumLength = sizeof(Buffer);
  474. ObjectName.Buffer = (WCHAR *)Buffer;
  475. RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
  476. ReferredServer.Buffer = ServerStr;
  477. ReferredServer.Length = 0;
  478. ReferredServer.MaximumLength = sizeof( ServerStr );
  479. Status = NwNdsResolveName ( GhRdr,
  480. &ObjectName,
  481. &ThisObjectID,
  482. &ReferredServer,
  483. NULL,
  484. 0 );
  485. if ( !NT_SUCCESS( Status ) ) {
  486. return Status;
  487. }
  488. if ( ReferredServer.Length > 0 ) {
  489. //
  490. // We've been referred to another server, so we
  491. // should change the global handle.
  492. //
  493. Status = NwNdsOpenGenericHandle( &ReferredServer,
  494. &dwHandleType,
  495. &hReferredServer );
  496. if ( !NT_SUCCESS( Status ) ) {
  497. return Status;
  498. }
  499. if( GhRdr != GhRdrForUser ) {
  500. CloseHandle( GhRdr );
  501. }
  502. GhRdr = hReferredServer;
  503. }
  504. Status = NwNdsReadObjectInfo( GhRdr, ThisObjectID, Buffer, 2048 );
  505. if ( !NT_SUCCESS( Status ) ) {
  506. return Status;
  507. }
  508. ptr = Buffer + sizeof( NDS_RESPONSE_GET_OBJECT_INFO );
  509. ptr += ROUNDUP4(*(DWORD *)ptr);
  510. ptr += sizeof(DWORD);
  511. ptr += sizeof(DWORD);
  512. RtlInitUnicodeString( &ObjectName, (PWCHAR)ptr );
  513. oemStr.Length = 0;
  514. oemStr.MaximumLength = (USHORT) Len;
  515. oemStr.Buffer = CanonName;
  516. RtlUnicodeStringToOemString( &oemStr, &ObjectName, FALSE );
  517. return 0;
  518. }
  519. /********************************************************************
  520. NDSGetUserProperty
  521. Routine Description:
  522. Return the NDS property for the object
  523. Arguments:
  524. Property - property name
  525. Data - data buffer
  526. Size - size of data buffer
  527. Return Value:
  528. 0 no error
  529. *******************************************************************/
  530. unsigned int
  531. NDSGetUserProperty( PBYTE Property,
  532. PBYTE Data,
  533. unsigned int Size,
  534. SYNTAX * pSyntaxID,
  535. unsigned int * pActualSize )
  536. {
  537. NTSTATUS Status = STATUS_SUCCESS;
  538. int ccode = -1;
  539. OEM_STRING oemStr;
  540. UNICODE_STRING PropertyName;
  541. WCHAR NdsStr[1024];
  542. DWORD iterhandle = INITIAL_ITERATION;
  543. PBYTE szBuffer;
  544. DWORD dwBufferSize = 2048;
  545. PNDS_RESPONSE_READ_ATTRIBUTE pReadAttribute;
  546. PNDS_ATTRIBUTE pAttribute;
  547. PBYTE pAttribValue;
  548. BOOL fContinue = TRUE;
  549. //
  550. // Read the User property
  551. //
  552. szBuffer = (PBYTE)malloc(dwBufferSize);
  553. if ( !szBuffer ) {
  554. DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
  555. Status = STATUS_NO_MEMORY;
  556. return Status;
  557. }
  558. memset( szBuffer, 0, dwBufferSize );
  559. oemStr.Length = (USHORT) strlen( Property );
  560. oemStr.MaximumLength = oemStr.Length;
  561. oemStr.Buffer = Property;
  562. PropertyName.Length = 0;
  563. PropertyName.MaximumLength = sizeof(NdsStr);
  564. PropertyName.Buffer = NdsStr;
  565. RtlOemStringToUnicodeString( &PropertyName, &oemStr, FALSE );
  566. while ( fContinue )
  567. {
  568. Status = NwNdsReadAttribute ( GhRdrForUser,
  569. GUserObjectID,
  570. &iterhandle,
  571. &PropertyName,
  572. szBuffer,
  573. dwBufferSize );
  574. if ( NT_SUCCESS(Status) && iterhandle != INITIAL_ITERATION )
  575. {
  576. dwBufferSize *= 2;
  577. free( szBuffer );
  578. szBuffer = (PBYTE)malloc(dwBufferSize);
  579. if ( !szBuffer ) {
  580. DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
  581. Status = STATUS_NO_MEMORY;
  582. return Status;
  583. }
  584. memset( szBuffer, 0, dwBufferSize );
  585. iterhandle = INITIAL_ITERATION;
  586. }
  587. else
  588. {
  589. fContinue = FALSE;
  590. }
  591. }
  592. if ( !NT_SUCCESS(Status) )
  593. {
  594. if ( szBuffer )
  595. free( szBuffer );
  596. return Status;
  597. }
  598. if ( NT_SUCCESS(Status) )
  599. {
  600. int i;
  601. pReadAttribute = (PNDS_RESPONSE_READ_ATTRIBUTE)szBuffer;
  602. pAttribute = (PNDS_ATTRIBUTE)(szBuffer
  603. + sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
  604. if ( pSyntaxID )
  605. {
  606. *pSyntaxID = pAttribute->SyntaxID;
  607. }
  608. pAttribValue = (PBYTE)(pAttribute->AttribName) +
  609. ROUNDUP4(pAttribute->AttribNameLength) +
  610. sizeof(DWORD);
  611. if ( pActualSize )
  612. {
  613. *pActualSize = *(DWORD *)pAttribValue;
  614. }
  615. memcpy( Data, pAttribValue + sizeof(DWORD),
  616. min(*(DWORD *)pAttribValue, Size) );
  617. }
  618. return Status;
  619. }
  620. /********************************************************************
  621. NDSGetVar
  622. Routine Description:
  623. Return value of user property
  624. Get the syntax type of the property
  625. Retrieve the data
  626. Do any data conversion
  627. Arguments:
  628. Name - of NDS property IN
  629. Value - value buffer OUT
  630. Size - size of value buffer IN
  631. Return Value:
  632. none
  633. *******************************************************************/
  634. void
  635. NDSGetVar ( PBYTE Name, PBYTE Value, unsigned int Size)
  636. {
  637. unsigned int err;
  638. SYNTAX Syntax;
  639. BYTE Buffer[ATTRBUFSIZE];
  640. DWORD ActualSize;
  641. Value[0] = 0;
  642. err = NDSGetUserProperty( Name, Buffer, ATTRBUFSIZE, &Syntax, &ActualSize );
  643. if ( err )
  644. {
  645. return;
  646. }
  647. switch ( Syntax )
  648. {
  649. case NDSI_BOOLEAN:
  650. if ( *(PBYTE)Buffer )
  651. {
  652. strcpy( Value, "Y" );
  653. }
  654. else
  655. {
  656. strcpy( Value, "N" );
  657. }
  658. break;
  659. case NDSI_DIST_NAME:
  660. case NDSI_CE_STRING:
  661. case NDSI_CI_STRING:
  662. case NDSI_OCTET_STRING:
  663. case NDSI_PR_STRING:
  664. case NDSI_NU_STRING:
  665. case NDSI_TEL_NUMBER:
  666. case NDSI_CLASS_NAME:
  667. ConvertUnicodeToAscii( Buffer );
  668. if ( Syntax == NDSI_DIST_NAME )
  669. NDSAbbreviateName(FLAGS_LOCAL_CONTEXT, Buffer, Buffer);
  670. strncpy( Value, Buffer, Size );
  671. break;
  672. case NDSI_CI_LIST:
  673. ConvertUnicodeToAscii( Buffer+8 );
  674. strncpy( Value, Buffer+8, Size );
  675. break;
  676. break;
  677. case NDSI_INTEGER:
  678. case NDSI_COUNTER:
  679. case NDSI_TIME:
  680. case NDSI_INTERVAL:
  681. case NDSI_TIMESTAMP:
  682. sprintf( Value, "%d", *(int *)Buffer );
  683. break;
  684. case NDSI_PO_ADDRESS:
  685. {
  686. // 6 null terminated lines
  687. int line,len;
  688. PBYTE ptr = Buffer + 4;
  689. // Stop if not 6 lines
  690. if ( *(int *)Buffer != 6 )
  691. break;
  692. for (line = 0; line <= 5; line++) {
  693. len = ROUNDUP4(*(int *)ptr);
  694. ptr += 4;
  695. if ( !len )
  696. break;
  697. ConvertUnicodeToAscii( ptr );
  698. strcat( Value, ptr );
  699. strcat( Value, "\n" );
  700. ptr += len;
  701. }
  702. }
  703. break;
  704. case NDSI_FAX_NUMBER:
  705. if ( *(int *)Buffer == 0 )
  706. return;
  707. ConvertUnicodeToAscii( Buffer+4 );
  708. strncpy( Value, Buffer+4, Size );
  709. break;
  710. case NDSI_EMAIL_ADDRESS:
  711. if ( *(int *)(Buffer+4) == 0 )
  712. return;
  713. ConvertUnicodeToAscii( Buffer+8 );
  714. strncpy( Value, Buffer+8, Size );
  715. break;
  716. case NDSI_PATH:
  717. {
  718. int len;
  719. len = *(int *)(Buffer+4);
  720. if ( len == 0 )
  721. break;
  722. len = ROUNDUP4( len );
  723. ConvertUnicodeToAscii( Buffer+8 );
  724. strcpy( Value, Buffer+8 );
  725. NDSAbbreviateName(FLAGS_LOCAL_CONTEXT, Value, Value);
  726. strcat( Value, ":" );
  727. if ( *(int *)(Buffer + 8 + len) == 0 )
  728. break;
  729. ConvertUnicodeToAscii( Buffer+8+len+4 );
  730. strcat( Value, Buffer+8+len+4 );
  731. break;
  732. }
  733. case NDSI_NET_ADDRESS:
  734. case NDSI_OCTET_LIST:
  735. case NDSI_OBJECT_ACL:
  736. case NDSI_STREAM:
  737. case NDSI_UNKNOWN:
  738. case NDSI_REPLICA_POINTER:
  739. case NDSI_BACK_LINK:
  740. case NDSI_TYPED_NAME:
  741. case NDSI_HOLD:
  742. case NDSI_TAX_COUNT:
  743. default:
  744. Value[0] = '\0';
  745. Value[1] = '\0';
  746. break;
  747. }
  748. }
  749. /********************************************************************
  750. NDSChangeContext
  751. Routine Description:
  752. Change the current context
  753. Arguments:
  754. Context - context string IN
  755. Return Value:
  756. error number
  757. *******************************************************************/
  758. unsigned int
  759. NDSChangeContext( PBYTE Context )
  760. {
  761. NTSTATUS Status;
  762. OEM_STRING oemStr;
  763. UNICODE_STRING defaultcontext;
  764. WCHAR NdsStr[1024];
  765. oemStr.Length = (USHORT)strlen( Context );
  766. oemStr.MaximumLength = oemStr.Length;
  767. oemStr.Buffer = Context;
  768. defaultcontext.Length = 0;
  769. defaultcontext.MaximumLength = sizeof(NdsStr);
  770. defaultcontext.Buffer = NdsStr;
  771. RtlOemStringToUnicodeString( &defaultcontext, &oemStr, FALSE );
  772. Status = NwNdsSetTreeContext( GhRdr, &NDSTREE_u, &defaultcontext );
  773. return Status;
  774. }
  775. /********************************************************************
  776. NDSGetContext
  777. Routine Description:
  778. Retrieve the current context
  779. Arguments:
  780. Buffer - data buffer for context string OUT
  781. len - length of data buffer IN
  782. Return Value:
  783. error number
  784. *******************************************************************/
  785. unsigned int
  786. NDSGetContext( PBYTE Buffer,
  787. unsigned int len )
  788. {
  789. NTSTATUS Status;
  790. Status = NDSGetNameContext( Buffer, TRUE );
  791. if ( !NT_SUCCESS( Status ) )
  792. return Status;
  793. NDSAbbreviateName(FLAGS_NO_CONTEXT, Buffer, Buffer);
  794. return 0;
  795. }
  796. /********************************************************************
  797. NDSfopenStream
  798. Routine Description:
  799. Open a file handle to an NDS stream property
  800. Arguments:
  801. Object - name of object IN
  802. Property - name of property IN
  803. pStream - pointer to file handle OUT
  804. pFileSize - pointer to file size OUT
  805. Return Value:
  806. error
  807. *******************************************************************/
  808. unsigned int
  809. NDSfopenStream ( PBYTE Object,
  810. PBYTE Property,
  811. PHANDLE pStream,
  812. unsigned int * pFileSize )
  813. {
  814. //
  815. // Status variables.
  816. //
  817. NTSTATUS Status;
  818. int ccode = -1;
  819. //
  820. // For NwNdsOpenTreeHandle.
  821. //
  822. HANDLE hRdr;
  823. OEM_STRING oemStr;
  824. UNICODE_STRING ObjectName;
  825. WCHAR NdsStr[1024];
  826. //
  827. // For NwNdsResolveName.
  828. //
  829. DWORD dwOid;
  830. UNICODE_STRING ReferredServer;
  831. WCHAR ServerStr[MAX_NAME_LEN];
  832. DWORD dwHandleType;
  833. HANDLE hReferredServer;
  834. //
  835. // Get a handle to the redirector.
  836. //
  837. Status = NwNdsOpenTreeHandle( &NDSTREE_u, &hRdr );
  838. if ( !NT_SUCCESS( Status ) ) {
  839. DisplayMessage(IDR_TREE_OPEN_FAILED);
  840. return ccode;
  841. }
  842. //
  843. // Resolve the name that we have to an object id.
  844. //
  845. if ( !Object )
  846. {
  847. return 1;
  848. }
  849. oemStr.Length = (USHORT)strlen( Object );
  850. oemStr.MaximumLength = oemStr.Length;
  851. oemStr.Buffer = Object;
  852. ObjectName.Length = 0;
  853. ObjectName.MaximumLength = sizeof(NdsStr);
  854. ObjectName.Buffer = NdsStr;
  855. RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
  856. ReferredServer.Buffer = ServerStr;
  857. ReferredServer.Length = 0;
  858. ReferredServer.MaximumLength = sizeof( ServerStr );
  859. Status = NwNdsResolveName ( hRdr,
  860. &ObjectName,
  861. &dwOid,
  862. &ReferredServer,
  863. NULL,
  864. 0 );
  865. if ( !NT_SUCCESS( Status ) ) {
  866. return 0xffffffff;
  867. }
  868. if ( ReferredServer.Length > 0 ) {
  869. //
  870. // We've been referred to another server, so we
  871. // must jump to that server before continuing.
  872. //
  873. Status = NwNdsOpenGenericHandle( &ReferredServer,
  874. &dwHandleType,
  875. &hReferredServer );
  876. if ( !NT_SUCCESS( Status ) ) {
  877. return 0xffffffff;
  878. }
  879. CloseHandle( hRdr );
  880. hRdr = hReferredServer;
  881. }
  882. //
  883. // Open the file stream.
  884. //
  885. oemStr.Length = (USHORT)strlen( Property );
  886. oemStr.MaximumLength = oemStr.Length;
  887. oemStr.Buffer = Property;
  888. ObjectName.Length = 0;
  889. ObjectName.MaximumLength = sizeof(NdsStr);
  890. ObjectName.Buffer = NdsStr;
  891. RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
  892. //
  893. // Try to open a file stream for read access.
  894. //
  895. Status = NwNdsOpenStream( hRdr,
  896. dwOid,
  897. &ObjectName,
  898. 1, // Read access.
  899. pFileSize );
  900. if ( !NT_SUCCESS( Status ) ) {
  901. return 0xffffffff;
  902. }
  903. *pStream = hRdr;
  904. return 0;
  905. }
  906. /*
  907. * IsMemberOfNDSGroup
  908. * ------------------
  909. *
  910. * Returns true if currently logged in user object is member of group with given name
  911. *
  912. */
  913. unsigned int
  914. IsMemberOfNDSGroup(
  915. PBYTE nwGroup
  916. )
  917. {
  918. NTSTATUS Status = STATUS_SUCCESS;
  919. UINT nwRet;
  920. BYTE szCanonTargetGroupName[NDS_NAME_CHARS+1];
  921. UINT syntaxid;
  922. UINT actualsize;
  923. PBYTE szBuffer;
  924. LPSTR pProp;
  925. UINT i;
  926. DWORD iterhandle = INITIAL_ITERATION;
  927. DWORD dwBufferSize = ATTRBUFSIZE;
  928. UINT fFoundGroup = FALSE;
  929. PNDS_RESPONSE_READ_ATTRIBUTE pReadAttribute;
  930. PNDS_ATTRIBUTE pAttribute;
  931. PBYTE pAttribValue;
  932. UNICODE_STRING PropertyName;
  933. UINT numvalues = 0;
  934. BOOL fContinue = TRUE;
  935. szBuffer = (PBYTE)malloc(dwBufferSize);
  936. if ( !szBuffer ) {
  937. DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
  938. return FALSE;
  939. }
  940. memset( szBuffer, 0, dwBufferSize );
  941. // Canonicalize name according to current context
  942. strcpy( szCanonTargetGroupName, nwGroup );
  943. nwRet = NDSCanonicalizeName( szCanonTargetGroupName,
  944. szCanonTargetGroupName,
  945. NDS_NAME_CHARS,
  946. TRUE );
  947. if (nwRet) {
  948. if ( nwGroup[0] != '.' ) {
  949. // Try an absolute name
  950. strcpy( szCanonTargetGroupName, "." );
  951. strcat( szCanonTargetGroupName, nwGroup );
  952. nwRet = NDSCanonicalizeName( szCanonTargetGroupName,
  953. szCanonTargetGroupName,
  954. NDS_NAME_CHARS,
  955. TRUE );
  956. }
  957. if ( nwRet )
  958. goto CleanRet;
  959. }
  960. // Should check class name of object
  961. RtlInitUnicodeString( &PropertyName, L"Group Membership" );
  962. while ( fContinue )
  963. {
  964. Status = NwNdsReadAttribute ( GhRdrForUser,
  965. GUserObjectID,
  966. &iterhandle,
  967. &PropertyName,
  968. szBuffer,
  969. dwBufferSize );
  970. if ( NT_SUCCESS(Status) && iterhandle != INITIAL_ITERATION )
  971. {
  972. dwBufferSize *= 2;
  973. free( szBuffer );
  974. szBuffer = (PBYTE)malloc(dwBufferSize);
  975. if ( !szBuffer ) {
  976. DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
  977. return FALSE;
  978. }
  979. memset( szBuffer, 0, dwBufferSize );
  980. iterhandle = INITIAL_ITERATION;
  981. }
  982. else
  983. {
  984. fContinue = FALSE;
  985. }
  986. }
  987. if ( !NT_SUCCESS(Status) )
  988. {
  989. goto CleanRet;
  990. }
  991. pReadAttribute = (PNDS_RESPONSE_READ_ATTRIBUTE)szBuffer;
  992. pAttribute = (PNDS_ATTRIBUTE)(szBuffer
  993. + sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
  994. pAttribute->SyntaxID;
  995. pAttribValue = (PBYTE)(pAttribute->AttribName) +
  996. ROUNDUP4(pAttribute->AttribNameLength) +
  997. sizeof(DWORD);
  998. numvalues = *(PUINT)((PBYTE)(pAttribute->AttribName) +
  999. ROUNDUP4(pAttribute->AttribNameLength));
  1000. if ( *(DWORD *)pAttribValue == 0 )
  1001. {
  1002. goto CleanRet;
  1003. }
  1004. for ( i = 0; i < numvalues; i++ ) {
  1005. ConvertUnicodeToAscii( pAttribValue+sizeof(DWORD) );
  1006. if (!_stricmp(pAttribValue+sizeof(DWORD),szCanonTargetGroupName)) {
  1007. fFoundGroup = TRUE;
  1008. break;
  1009. }
  1010. pAttribValue += ROUNDUP4(*(PUINT)pAttribValue) + sizeof(DWORD);
  1011. }
  1012. CleanRet:
  1013. if (szBuffer ) {
  1014. free (szBuffer);
  1015. }
  1016. return fFoundGroup;
  1017. }
  1018. /********************************************************************
  1019. NDSGetProperty
  1020. Routine Description:
  1021. Return the NDS property for the object
  1022. Arguments:
  1023. Object - name of object IN
  1024. Property - property name IN
  1025. Data - data buffer OUT
  1026. Size - size of data buffer IN
  1027. pActualSize - real data size OUT
  1028. Return Value:
  1029. error
  1030. *******************************************************************/
  1031. unsigned int
  1032. NDSGetProperty ( PBYTE Object,
  1033. PBYTE Property,
  1034. PBYTE Data,
  1035. unsigned int Size,
  1036. unsigned int * pActualSize )
  1037. {
  1038. //
  1039. // Status variables.
  1040. //
  1041. NTSTATUS Status = STATUS_SUCCESS;
  1042. int ccode = -1;
  1043. //
  1044. // For NwNdsOpenTreeHandle.
  1045. //
  1046. HANDLE hRdr;
  1047. OEM_STRING oemStr;
  1048. UNICODE_STRING ObjectName;
  1049. WCHAR NdsStr[1024];
  1050. //
  1051. // For NwNdsResolveName.
  1052. //
  1053. DWORD dwOid;
  1054. UNICODE_STRING ReferredServer;
  1055. WCHAR ServerStr[MAX_NAME_LEN];
  1056. DWORD dwHandleType;
  1057. HANDLE hReferredServer;
  1058. //
  1059. // For NwNdsReadAttribute
  1060. //
  1061. PBYTE szBuffer;
  1062. DWORD dwBufferSize = 2048;
  1063. DWORD iterhandle = INITIAL_ITERATION;
  1064. PNDS_RESPONSE_READ_ATTRIBUTE pReadAttribute;
  1065. PNDS_ATTRIBUTE pAttribute;
  1066. PBYTE pAttribValue;
  1067. BOOL fContinue = TRUE;
  1068. //
  1069. // Allocate a buffer for the NDS request.
  1070. //
  1071. szBuffer = (PBYTE)malloc(dwBufferSize);
  1072. if ( !szBuffer ) {
  1073. DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
  1074. Status = STATUS_NO_MEMORY;
  1075. return Status;
  1076. }
  1077. memset( szBuffer, 0, dwBufferSize );
  1078. //
  1079. // Get a handle to the redirector.
  1080. //
  1081. Status = NwNdsOpenTreeHandle( &NDSTREE_u, &hRdr );
  1082. if ( !NT_SUCCESS( Status ) ) {
  1083. DisplayMessage(IDR_TREE_OPEN_FAILED);
  1084. return ccode;
  1085. }
  1086. //
  1087. // Resolve the name that we have to an object id.
  1088. //
  1089. if ( !Object )
  1090. {
  1091. return 1;
  1092. }
  1093. oemStr.Length = (USHORT)strlen( Object );
  1094. oemStr.MaximumLength = oemStr.Length;
  1095. oemStr.Buffer = Object;
  1096. ObjectName.Length = 0;
  1097. ObjectName.MaximumLength = sizeof(NdsStr);
  1098. ObjectName.Buffer = NdsStr;
  1099. RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
  1100. ReferredServer.Buffer = ServerStr;
  1101. ReferredServer.Length = 0;
  1102. ReferredServer.MaximumLength = sizeof( ServerStr );
  1103. Status = NwNdsResolveName ( hRdr,
  1104. &ObjectName,
  1105. &dwOid,
  1106. &ReferredServer,
  1107. NULL,
  1108. 0 );
  1109. if ( !NT_SUCCESS( Status ) ) {
  1110. return 0xffffffff;
  1111. }
  1112. if ( ReferredServer.Length > 0 ) {
  1113. //
  1114. // We've been referred to another server, so we
  1115. // must jump to that server before continuing.
  1116. //
  1117. Status = NwNdsOpenGenericHandle( &ReferredServer,
  1118. &dwHandleType,
  1119. &hReferredServer );
  1120. if ( !NT_SUCCESS( Status ) ) {
  1121. return 0xffffffff;
  1122. }
  1123. CloseHandle( hRdr );
  1124. hRdr = hReferredServer;
  1125. }
  1126. //
  1127. // Get the attribute
  1128. //
  1129. oemStr.Length = (USHORT)strlen( Property );
  1130. oemStr.MaximumLength = oemStr.Length;
  1131. oemStr.Buffer = Property;
  1132. ObjectName.Length = 0;
  1133. ObjectName.MaximumLength = sizeof(NdsStr);
  1134. ObjectName.Buffer = NdsStr;
  1135. RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
  1136. while ( fContinue )
  1137. {
  1138. Status = NwNdsReadAttribute ( hRdr,
  1139. dwOid,
  1140. &iterhandle,
  1141. &ObjectName,
  1142. szBuffer,
  1143. dwBufferSize );
  1144. if ( NT_SUCCESS(Status) && iterhandle != INITIAL_ITERATION )
  1145. {
  1146. dwBufferSize *= 2;
  1147. free( szBuffer );
  1148. szBuffer = (PBYTE)malloc(dwBufferSize);
  1149. if ( !szBuffer ) {
  1150. DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
  1151. Status = STATUS_NO_MEMORY;
  1152. return Status;
  1153. }
  1154. memset( szBuffer, 0, dwBufferSize );
  1155. iterhandle = INITIAL_ITERATION;
  1156. }
  1157. else
  1158. {
  1159. fContinue = FALSE;
  1160. }
  1161. }
  1162. if ( !NT_SUCCESS(Status) )
  1163. {
  1164. NtClose( hRdr );
  1165. free( szBuffer );
  1166. return Status;
  1167. }
  1168. if ( NT_SUCCESS(Status) )
  1169. {
  1170. int i;
  1171. pReadAttribute = (PNDS_RESPONSE_READ_ATTRIBUTE)szBuffer;
  1172. pAttribute = (PNDS_ATTRIBUTE)(szBuffer
  1173. + sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
  1174. pAttribValue = (PBYTE)(pAttribute->AttribName) +
  1175. ROUNDUP4(pAttribute->AttribNameLength) +
  1176. sizeof(DWORD);
  1177. if ( pActualSize )
  1178. {
  1179. *pActualSize = *(DWORD *)pAttribValue;
  1180. }
  1181. memcpy( Data, pAttribValue + sizeof(DWORD),
  1182. min(*(DWORD *)pAttribValue, Size) );
  1183. }
  1184. NtClose( hRdr );
  1185. return Status;
  1186. }
  1187. /********************************************************************
  1188. NDSCleanup
  1189. Routine Description:
  1190. Does any NDS cleanup
  1191. Arguments:
  1192. none
  1193. Return Value:
  1194. none
  1195. *******************************************************************/
  1196. void
  1197. NDSCleanup ( void )
  1198. {
  1199. NtClose( GhRdr );
  1200. if( GhRdr != GhRdrForUser ) {
  1201. NtClose( GhRdrForUser );
  1202. }
  1203. }
  1204. /********************************************************************
  1205. NDSGetClassName
  1206. Routine Description:
  1207. return a class name for an object
  1208. Arguments:
  1209. szObjectName
  1210. ClassName
  1211. Return Value:
  1212. none
  1213. *******************************************************************/
  1214. unsigned int
  1215. NDSGetClassName( LPSTR szObjectName, LPSTR ClassName )
  1216. {
  1217. NTSTATUS Status;
  1218. int ccode = -1;
  1219. DWORD ThisObjectID;
  1220. OEM_STRING oemStr;
  1221. UNICODE_STRING ObjectName;
  1222. BYTE Buffer[2048];
  1223. BYTE FullName[NDS_NAME_CHARS];
  1224. PBYTE ptr;
  1225. UNICODE_STRING ReferredServer;
  1226. WCHAR ServerStr[MAX_NAME_LEN];
  1227. DWORD dwHandleType;
  1228. HANDLE hReferredServer;
  1229. DWORD Length;
  1230. //
  1231. // Resolve the name that we have to an object id.
  1232. //
  1233. oemStr.Length = (USHORT)strlen( szObjectName );
  1234. oemStr.MaximumLength = oemStr.Length;
  1235. oemStr.Buffer = szObjectName;
  1236. ObjectName.Length = 0;
  1237. ObjectName.MaximumLength = sizeof(Buffer);
  1238. ObjectName.Buffer = (WCHAR *)Buffer;
  1239. RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
  1240. ReferredServer.Buffer = ServerStr;
  1241. ReferredServer.Length = 0;
  1242. ReferredServer.MaximumLength = sizeof( ServerStr );
  1243. Status = NwNdsResolveName ( GhRdr,
  1244. &ObjectName,
  1245. &ThisObjectID,
  1246. &ReferredServer,
  1247. NULL,
  1248. 0 );
  1249. if ( !NT_SUCCESS( Status ) ) {
  1250. return Status;
  1251. }
  1252. if ( ReferredServer.Length > 0 ) {
  1253. //
  1254. // We've been referred to another server, so we
  1255. // should change the global handle.
  1256. //
  1257. Status = NwNdsOpenGenericHandle( &ReferredServer,
  1258. &dwHandleType,
  1259. &hReferredServer );
  1260. if ( !NT_SUCCESS( Status ) ) {
  1261. return Status;
  1262. }
  1263. if( GhRdr != GhRdrForUser ) {
  1264. CloseHandle( GhRdr );
  1265. }
  1266. GhRdr = hReferredServer;
  1267. }
  1268. Status = NwNdsReadObjectInfo( GhRdr, ThisObjectID, Buffer, 2048 );
  1269. if ( !NT_SUCCESS( Status ) ) {
  1270. return Status;
  1271. }
  1272. ptr = Buffer + sizeof( NDS_RESPONSE_GET_OBJECT_INFO ) + sizeof( DWORD );
  1273. RtlInitUnicodeString( &ObjectName, (PWCHAR)ptr );
  1274. oemStr.Length = 0;
  1275. oemStr.MaximumLength = NDS_NAME_CHARS;
  1276. oemStr.Buffer = ClassName;
  1277. RtlUnicodeStringToOemString( &oemStr, &ObjectName, FALSE );
  1278. return 0;
  1279. }