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.

2437 lines
56 KiB

  1. #include "NWCOMPAT.hxx"
  2. #pragma hdrstop
  3. //----------------------------------------------------------------------------
  4. //
  5. // Function: NWApiGetProperty
  6. //
  7. // Synopsis:
  8. //
  9. //----------------------------------------------------------------------------
  10. HRESULT
  11. NWApiGetProperty(
  12. BSTR bstrObjectName,
  13. LPSTR lpszPropertyName,
  14. NWOBJ_TYPE dwOT_ID,
  15. NWCONN_HANDLE hConn,
  16. LPP_RPLY_SGMT_LST lppReplySegment,
  17. LPDWORD pdwNumSegment
  18. )
  19. {
  20. CHAR szObjectName[(OBJ_NAME_SIZE + 1)*2];
  21. NWFLAGS pucMoreFlag = 0;
  22. NWFLAGS pucPropFlag = 0;
  23. unsigned char ucSegment = 1;
  24. LP_RPLY_SGMT_LST lpHeadReplySegment = NULL;
  25. LP_RPLY_SGMT_LST lpTempReplySegment = NULL;
  26. LP_RPLY_SGMT_LST lpTemp = NULL;
  27. HRESULT hr = S_OK;
  28. NWCCODE usRet = 0;
  29. //
  30. // lppReplySegment is assumed to be NULL.
  31. //
  32. ADsAssert((*lppReplySegment) == NULL);
  33. //
  34. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  35. // passed to UnicodeToAnsiString when the length of the string is unknown.
  36. //
  37. if (wcslen(bstrObjectName) > OBJ_NAME_SIZE) {
  38. hr = E_INVALIDARG;
  39. BAIL_ON_FAILURE(hr);
  40. }
  41. UnicodeToAnsiString(
  42. bstrObjectName,
  43. szObjectName,
  44. 0
  45. );
  46. //
  47. // Initialize first node of the list and set up temp traversal pointer.
  48. //
  49. INIT_RPLY_SGMT(lpTempReplySegment);
  50. lpHeadReplySegment = lpTempReplySegment;
  51. //
  52. // Read & dump property values into linked-list.
  53. //
  54. do {
  55. usRet = NWCReadPropertyValue(
  56. hConn,
  57. szObjectName,
  58. dwOT_ID,
  59. lpszPropertyName,
  60. ucSegment,
  61. lpTempReplySegment->Segment,
  62. &pucMoreFlag,
  63. &pucPropFlag
  64. );
  65. hr = HRESULT_FROM_NWCCODE(usRet);
  66. BAIL_ON_FAILURE(hr);
  67. if (pucMoreFlag) {
  68. INIT_RPLY_SGMT(lpTempReplySegment->lpNext);
  69. lpTempReplySegment = lpTempReplySegment->lpNext;
  70. ucSegment++;
  71. }
  72. } while(pucMoreFlag);
  73. //
  74. // Return the resulting linked-list.
  75. //
  76. *lppReplySegment = lpHeadReplySegment;
  77. *pdwNumSegment = ucSegment;
  78. error:
  79. if (FAILED(hr) && lpHeadReplySegment) {
  80. DELETE_LIST(lpHeadReplySegment);
  81. }
  82. RRETURN(hr);
  83. }
  84. //----------------------------------------------------------------------------
  85. //
  86. // Function: NWApiGetFileServerVersionInfo
  87. //
  88. // Synopsis:
  89. //
  90. //----------------------------------------------------------------------------
  91. HRESULT
  92. NWApiGetFileServerVersionInfo(
  93. NWCONN_HANDLE hConn,
  94. VERSION_INFO *pVersionInfo
  95. )
  96. {
  97. NWCCODE usRet = SUCCESSFUL;
  98. HRESULT hr = S_OK;
  99. usRet = NWCGetFileServerVersionInfo(
  100. hConn,
  101. pVersionInfo
  102. );
  103. hr = HRESULT_FROM_NWCCODE(usRet);
  104. RRETURN(hr);
  105. }
  106. //----------------------------------------------------------------------------
  107. //
  108. // Function: NWApiIsObjectInSet
  109. //
  110. // Synopsis:
  111. //
  112. //----------------------------------------------------------------------------
  113. HRESULT
  114. NWApiIsObjectInSet(
  115. NWCONN_HANDLE hConn,
  116. LPWSTR lpszObjectName,
  117. NWOBJ_TYPE wObjType,
  118. LPSTR lpszPropertyName,
  119. LPSTR lpszMemberName,
  120. NWOBJ_TYPE wMemberType
  121. )
  122. {
  123. CHAR szAnsiObjectName[(OBJ_NAME_SIZE + 1)*2];
  124. HRESULT hr = S_OK;
  125. NWCCODE usRet = SUCCESSFUL;
  126. //
  127. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  128. // passed to UnicodeToAnsiString when the length of the string is unknown.
  129. //
  130. if (wcslen(lpszObjectName) > OBJ_NAME_SIZE) {
  131. RRETURN(E_INVALIDARG);
  132. }
  133. UnicodeToAnsiString(
  134. lpszObjectName,
  135. szAnsiObjectName,
  136. 0
  137. );
  138. //
  139. // Call NWCIsObjectInSet.
  140. //
  141. usRet = NWCIsObjectInSet(
  142. hConn,
  143. szAnsiObjectName,
  144. wObjType,
  145. lpszPropertyName,
  146. lpszMemberName,
  147. wMemberType
  148. );
  149. hr = HRESULT_FROM_NWCCODE(usRet);
  150. RRETURN(hr);
  151. }
  152. //----------------------------------------------------------------------------
  153. //
  154. // Function: NWApiGetObjectID
  155. //
  156. // Synopsis:
  157. //
  158. //----------------------------------------------------------------------------
  159. HRESULT
  160. NWApiGetObjectID(
  161. NWCONN_HANDLE hConn,
  162. LPWSTR lpszObjectName,
  163. NWOBJ_TYPE wObjType,
  164. NWOBJ_ID *pObjectID
  165. )
  166. {
  167. CHAR szAnsiObjectName[(OBJ_NAME_SIZE + 1)*2];
  168. HRESULT hr = S_OK;
  169. NWCCODE usRet = SUCCESSFUL;
  170. //
  171. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  172. // passed to UnicodeToAnsiString when the length of the string is unknown.
  173. //
  174. if (wcslen(lpszObjectName) > OBJ_NAME_SIZE) {
  175. RRETURN(E_INVALIDARG);
  176. }
  177. UnicodeToAnsiString(
  178. lpszObjectName,
  179. szAnsiObjectName,
  180. 0
  181. );
  182. //
  183. // Get Object's ID.
  184. //
  185. usRet = NWCGetObjectID(
  186. hConn,
  187. szAnsiObjectName,
  188. wObjType,
  189. pObjectID
  190. );
  191. hr = HRESULT_FROM_NWCCODE(usRet);
  192. RRETURN(hr);
  193. }
  194. //----------------------------------------------------------------------------
  195. //
  196. // Function: NWApiGroupGetMembers
  197. //
  198. // Synopsis:
  199. //
  200. //----------------------------------------------------------------------------
  201. HRESULT
  202. NWApiGroupGetMembers(
  203. NWCONN_HANDLE hConn,
  204. LPWSTR szGroupName,
  205. LPBYTE *lppBuffer
  206. )
  207. {
  208. DWORD dwNumSegment = 0;
  209. HRESULT hr = S_OK;
  210. DWORD i;
  211. LP_RPLY_SGMT_LST lpTemp = NULL;
  212. LP_RPLY_SGMT_LST lpReplySegment = NULL;
  213. //
  214. // Assert
  215. //
  216. ADsAssert(*lppBuffer == NULL);
  217. //
  218. // Get GROUP_MEMBERS.
  219. //
  220. hr = NWApiGetProperty(
  221. szGroupName,
  222. NW_PROP_GROUP_MEMBERS,
  223. OT_USER_GROUP,
  224. hConn,
  225. &lpReplySegment,
  226. &dwNumSegment
  227. );
  228. BAIL_ON_FAILURE(hr);
  229. //
  230. // Pack returned linked list into buffer.
  231. //
  232. *lppBuffer = (LPBYTE) AllocADsMem(
  233. dwNumSegment * REPLY_VALUE_SIZE
  234. );
  235. if (!(*lppBuffer)) {
  236. RRETURN(E_OUTOFMEMORY);
  237. }
  238. lpTemp = lpReplySegment;
  239. for (i = 0; i < dwNumSegment; i++) {
  240. memcpy(
  241. *lppBuffer + i * REPLY_VALUE_SIZE,
  242. lpTemp->Segment,
  243. REPLY_VALUE_SIZE
  244. );
  245. lpTemp = lpTemp->lpNext;
  246. }
  247. error:
  248. //
  249. // Clean up.
  250. //
  251. lpTemp = NULL;
  252. if (lpReplySegment) {
  253. DELETE_LIST(lpReplySegment);
  254. }
  255. RRETURN(hr);
  256. }
  257. //----------------------------------------------------------------------------
  258. //
  259. // Function: NWApiAddGroupMember
  260. //
  261. // Synopsis:
  262. //
  263. //----------------------------------------------------------------------------
  264. HRESULT
  265. NWApiAddGroupMember(
  266. NWCONN_HANDLE hConn,
  267. LPWSTR pszGroupName,
  268. LPWSTR pszMemberName
  269. )
  270. {
  271. CHAR szGroupName[(OBJ_NAME_SIZE + 1)*2];
  272. CHAR szMemberName[(OBJ_NAME_SIZE + 1)*2];
  273. HRESULT hr = S_OK;
  274. NWCCODE usRet = SUCCESSFUL;
  275. //
  276. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  277. // passed to UnicodeToAnsiString when the length of the string is unknown.
  278. //
  279. if (wcslen(pszGroupName) > OBJ_NAME_SIZE) {
  280. hr = E_INVALIDARG;
  281. BAIL_ON_FAILURE(hr);
  282. }
  283. if (wcslen(pszMemberName) > OBJ_NAME_SIZE) {
  284. hr = E_INVALIDARG;
  285. BAIL_ON_FAILURE(hr);
  286. }
  287. UnicodeToAnsiString(
  288. pszGroupName,
  289. szGroupName,
  290. 0
  291. );
  292. UnicodeToAnsiString(
  293. pszMemberName,
  294. szMemberName,
  295. 0
  296. );
  297. //
  298. // Modify GROUP_MEMBERS property of the group to include the new member.
  299. //
  300. usRet = NWCAddObjectToSet(
  301. hConn,
  302. szGroupName,
  303. OT_USER_GROUP,
  304. "GROUP_MEMBERS",
  305. szMemberName,
  306. OT_USER
  307. );
  308. hr = HRESULT_FROM_NWCCODE(usRet);
  309. BAIL_ON_FAILURE(hr);
  310. //
  311. // Modify GROUPS_I'M_IN property of the new member to reflect its included
  312. // in the new group.
  313. //
  314. usRet = NWCAddObjectToSet(
  315. hConn,
  316. szMemberName,
  317. OT_USER,
  318. "GROUPS_I'M_IN",
  319. szGroupName,
  320. OT_USER_GROUP
  321. );
  322. hr = HRESULT_FROM_NWCCODE(usRet);
  323. BAIL_ON_FAILURE(hr);
  324. //
  325. // Modify SECURITY_EQUALS property of the new member to equate its security
  326. // to that of the new group it just joined.
  327. //
  328. usRet = NWCAddObjectToSet(
  329. hConn,
  330. szMemberName,
  331. OT_USER,
  332. "SECURITY_EQUALS",
  333. szGroupName,
  334. OT_USER_GROUP
  335. );
  336. hr = HRESULT_FROM_NWCCODE(usRet);
  337. BAIL_ON_FAILURE(hr);
  338. error:
  339. RRETURN(hr);
  340. }
  341. //----------------------------------------------------------------------------
  342. //
  343. // Function: NWApiRemoveGroupMember
  344. //
  345. // Synopsis:
  346. //
  347. //----------------------------------------------------------------------------
  348. HRESULT
  349. NWApiRemoveGroupMember(
  350. NWCONN_HANDLE hConn,
  351. LPWSTR pszGroupName,
  352. LPWSTR pszMemberName
  353. )
  354. {
  355. CHAR szGroupName[(OBJ_NAME_SIZE + 1)*2];
  356. CHAR szMemberName[(OBJ_NAME_SIZE + 1)*2];
  357. HRESULT hr = S_OK;
  358. NWCCODE usRet = SUCCESSFUL;
  359. //
  360. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  361. // passed to UnicodeToAnsiString when the length of the string is unknown.
  362. //
  363. if (wcslen(pszGroupName) > OBJ_NAME_SIZE) {
  364. hr = E_INVALIDARG;
  365. BAIL_ON_FAILURE(hr);
  366. }
  367. if (wcslen(pszMemberName) > OBJ_NAME_SIZE) {
  368. hr = E_INVALIDARG;
  369. BAIL_ON_FAILURE(hr);
  370. }
  371. UnicodeToAnsiString(
  372. pszGroupName,
  373. szGroupName,
  374. 0
  375. );
  376. UnicodeToAnsiString(
  377. pszMemberName,
  378. szMemberName,
  379. 0
  380. );
  381. //
  382. // Modify SECURITY_EQUALS property of the removed member to break its
  383. // security tie with the group it joined.
  384. //
  385. usRet = NWCDeleteObjectFromSet(
  386. hConn,
  387. szMemberName,
  388. OT_USER,
  389. "SECURITY_EQUALS",
  390. szGroupName,
  391. OT_USER_GROUP
  392. );
  393. hr = HRESULT_FROM_NWCCODE(usRet);
  394. BAIL_ON_FAILURE(hr);
  395. //
  396. // Modify GROUPS_I'M_IN property of the new member to reflect it is not
  397. // included in the group anymore.
  398. //
  399. usRet = NWCDeleteObjectFromSet(
  400. hConn,
  401. szMemberName,
  402. OT_USER,
  403. "GROUPS_I'M_IN",
  404. szGroupName,
  405. OT_USER_GROUP
  406. );
  407. hr = HRESULT_FROM_NWCCODE(usRet);
  408. BAIL_ON_FAILURE(hr);
  409. //
  410. // Modify GROUP_MEMBERS property of the group to remove the member.
  411. //
  412. usRet = NWCDeleteObjectFromSet(
  413. hConn,
  414. szGroupName,
  415. OT_USER_GROUP,
  416. "GROUP_MEMBERS",
  417. szMemberName,
  418. OT_USER
  419. );
  420. hr = HRESULT_FROM_NWCCODE(usRet);
  421. BAIL_ON_FAILURE(hr);
  422. error:
  423. RRETURN(hr);
  424. }
  425. //----------------------------------------------------------------------------
  426. //
  427. // Function: NWApiGetLOGIN_CONTROL
  428. //
  429. // Synopsis:
  430. //
  431. //----------------------------------------------------------------------------
  432. HRESULT
  433. NWApiGetLOGIN_CONTROL(
  434. NWCONN_HANDLE hConn,
  435. LPWSTR lpszUserName,
  436. LPLC_STRUCTURE lpLoginCtrlStruct
  437. )
  438. {
  439. DWORD dwNumSegment = 0;
  440. HRESULT hr = S_OK;
  441. LP_RPLY_SGMT_LST lpReplySegment = NULL;
  442. LP_RPLY_SGMT_LST lpTemp = NULL;
  443. hr = NWApiGetProperty(
  444. lpszUserName,
  445. NW_PROP_LOGIN_CONTROL,
  446. OT_USER,
  447. hConn,
  448. &lpReplySegment,
  449. &dwNumSegment
  450. );
  451. BAIL_ON_FAILURE(hr);
  452. *lpLoginCtrlStruct = *((LPLC_STRUCTURE) lpReplySegment->Segment);
  453. error:
  454. if (lpReplySegment) {
  455. DELETE_LIST(lpReplySegment);
  456. }
  457. RRETURN(hr);
  458. }
  459. //----------------------------------------------------------------------------
  460. //
  461. // Function: NWApiSetDefaultAcctExpDate
  462. //
  463. // Synopsis: This function looks at the local time and returns a default value
  464. // for an account expiration date in a variant date.
  465. //
  466. //----------------------------------------------------------------------------
  467. HRESULT
  468. NWApiSetDefaultAcctExpDate(
  469. DOUBLE * pdTime,
  470. SYSTEMTIME SysTime
  471. )
  472. {
  473. DOUBLE vTime;
  474. HRESULT hr = S_OK;
  475. //
  476. // According to SysCon, the default account expiration date is the first day
  477. // of the following month.
  478. //
  479. if (SysTime.wMonth == 12) {
  480. SysTime.wMonth = 1;
  481. }
  482. else {
  483. SysTime.wMonth++;
  484. }
  485. SysTime.wDay = 1;
  486. //
  487. // Subtract 1980 from wYear for NWApiMakeVariantTime.
  488. //
  489. SysTime.wYear -= 1980;
  490. hr = NWApiMakeVariantTime(
  491. &vTime,
  492. SysTime.wDay,
  493. SysTime.wMonth,
  494. SysTime.wYear,
  495. 0,0,0
  496. );
  497. BAIL_ON_FAILURE(hr);
  498. *pdTime = vTime;
  499. error:
  500. RRETURN(hr);
  501. }
  502. //----------------------------------------------------------------------------
  503. //
  504. // Function: NWApiUserAsSupervisor
  505. //
  506. // Synopsis: This functions turns the user into one of the supervisors if TRUE
  507. // is passed. User's supervisor privilege is removed otherwise.
  508. //
  509. //----------------------------------------------------------------------------
  510. HRESULT
  511. NWApiUserAsSupervisor(
  512. NWCONN_HANDLE hConn,
  513. LPWSTR lpszUserName,
  514. BOOL fSupervisor
  515. )
  516. {
  517. CHAR szUserName[(OBJ_NAME_SIZE + 1)*2];
  518. HRESULT hr = S_OK;
  519. NWCCODE usRet = SUCCESSFUL;
  520. //
  521. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  522. // passed to UnicodeToAnsiString when the length of the string is unknown.
  523. //
  524. if (wcslen(lpszUserName) > OBJ_NAME_SIZE) {
  525. RRETURN(E_INVALIDARG);
  526. }
  527. UnicodeToAnsiString(
  528. lpszUserName,
  529. szUserName,
  530. 0
  531. );
  532. //
  533. // Make it a supervisor.
  534. //
  535. if (fSupervisor == TRUE) {
  536. usRet = NWCAddObjectToSet(
  537. hConn,
  538. szUserName,
  539. OT_USER,
  540. "SECURITY_EQUALS",
  541. "SUPERVISOR",
  542. OT_USER
  543. );
  544. }
  545. //
  546. // Remove supervisor privilege.
  547. //
  548. else {
  549. usRet = NWCDeleteObjectFromSet(
  550. hConn,
  551. szUserName,
  552. OT_USER,
  553. "SECURITY_EQUALS",
  554. "SUPERVISOR",
  555. OT_USER
  556. );
  557. }
  558. hr = HRESULT_FROM_NWCCODE(usRet);
  559. RRETURN(hr);
  560. }
  561. //----------------------------------------------------------------------------
  562. //
  563. // Function: NWApiGetVolumeNumber
  564. //
  565. // Synopsis:
  566. //
  567. //----------------------------------------------------------------------------
  568. HRESULT
  569. NWApiGetVolumeNumber(
  570. NWCONN_HANDLE hConn,
  571. LPWSTR lpszVolumeName,
  572. NWVOL_NUM *pVolumeNumber
  573. )
  574. {
  575. CHAR szVolumeName[(OBJ_NAME_SIZE + 1)*2];
  576. HRESULT hr = S_OK;
  577. NWCCODE usRet = SUCCESSFUL;
  578. //
  579. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  580. // passed to UnicodeToAnsiString when the length of the string is unknown.
  581. //
  582. if (wcslen(lpszVolumeName) > OBJ_NAME_SIZE) {
  583. RRETURN(E_INVALIDARG);
  584. }
  585. UnicodeToAnsiString(
  586. lpszVolumeName,
  587. szVolumeName,
  588. 0
  589. );
  590. //
  591. // Get Volume's number.
  592. //
  593. usRet = NWCGetVolumeNumber(
  594. hConn,
  595. szVolumeName,
  596. pVolumeNumber
  597. );
  598. hr = HRESULT_FROM_NWCCODE(usRet);
  599. //
  600. // Return.
  601. //
  602. RRETURN(hr);
  603. }
  604. //----------------------------------------------------------------------------
  605. //
  606. // Function: NWApiGetVolumeName
  607. //
  608. // Synopsis:
  609. //
  610. //----------------------------------------------------------------------------
  611. HRESULT
  612. NWApiGetVolumeName(
  613. NWCONN_HANDLE hConn,
  614. NWVOL_NUM bVolNum,
  615. LPWSTR *lppszVolName
  616. )
  617. {
  618. CHAR szVolumeName[OBJ_NAME_SIZE + 1];
  619. HRESULT hr = S_OK;
  620. LPWSTR lpszTemp = NULL;
  621. NWCCODE usRet = SUCCESSFUL;
  622. //
  623. // Get Volume's name.
  624. //
  625. usRet = NWCGetVolumeName(
  626. hConn,
  627. bVolNum,
  628. szVolumeName
  629. );
  630. hr = HRESULT_FROM_NWCCODE(usRet);
  631. BAIL_ON_FAILURE(hr);
  632. //
  633. // Convert result into Unicode.
  634. //
  635. lpszTemp = AllocateUnicodeString(szVolumeName);
  636. if (!lpszTemp) {
  637. RRETURN(E_OUTOFMEMORY);
  638. }
  639. *lppszVolName = AllocADsStr(lpszTemp);
  640. if (!(*lppszVolName)) {
  641. RRETURN(E_OUTOFMEMORY);
  642. }
  643. FreeUnicodeString(lpszTemp);
  644. //
  645. // Return.
  646. //
  647. RRETURN(hr);
  648. error:
  649. *lppszVolName = NULL;
  650. RRETURN(hr);
  651. }
  652. //----------------------------------------------------------------------------
  653. //
  654. // Function: NWApiEnumJobs
  655. //
  656. // Synopsis:
  657. //
  658. //----------------------------------------------------------------------------
  659. HRESULT
  660. NWApiEnumJobs(
  661. HANDLE hPrinter,
  662. DWORD dwFirstJob,
  663. DWORD dwNoJobs,
  664. DWORD dwLevel,
  665. LPBYTE *lplpbJobs,
  666. DWORD *pcbBuf,
  667. LPDWORD lpdwReturned
  668. )
  669. {
  670. BOOL fStatus = TRUE;
  671. HRESULT hr = S_OK;
  672. fStatus = WinNTEnumJobs(
  673. hPrinter,
  674. dwFirstJob,
  675. dwNoJobs,
  676. dwLevel,
  677. lplpbJobs,
  678. pcbBuf,
  679. lpdwReturned
  680. );
  681. if (fStatus == FALSE) {
  682. hr = HRESULT_FROM_WIN32(GetLastError());
  683. }
  684. RRETURN(hr);
  685. }
  686. //----------------------------------------------------------------------------
  687. //
  688. // Function: NWApiGetPrinter
  689. //
  690. // Synopsis:
  691. //
  692. //----------------------------------------------------------------------------
  693. HRESULT
  694. NWApiGetPrinter(
  695. HANDLE hPrinter,
  696. DWORD dwLevel,
  697. LPBYTE *lplpbPrinters
  698. )
  699. {
  700. BOOL fStatus = TRUE;
  701. HRESULT hr = S_OK;
  702. fStatus = WinNTGetPrinter(
  703. hPrinter,
  704. dwLevel,
  705. lplpbPrinters
  706. );
  707. if (fStatus == FALSE) {
  708. hr = HRESULT_FROM_WIN32(GetLastError());
  709. }
  710. RRETURN(hr);
  711. }
  712. //----------------------------------------------------------------------------
  713. //
  714. // Function: NWApiUncFromADsPath
  715. //
  716. // Synopsis:
  717. //
  718. //----------------------------------------------------------------------------
  719. HRESULT
  720. NWApiUncFromADsPath(
  721. LPWSTR lpszADsPath,
  722. LPWSTR lpszUncName
  723. )
  724. {
  725. HRESULT hr;
  726. POBJECTINFO pObjectInfo = NULL;
  727. hr = BuildObjectInfo(lpszADsPath,
  728. &pObjectInfo );
  729. BAIL_ON_FAILURE(hr);
  730. wsprintf(
  731. lpszUncName,
  732. L"\\\\%s\\%s",
  733. pObjectInfo->ComponentArray[0],
  734. pObjectInfo->ComponentArray[1]
  735. );
  736. error:
  737. if(pObjectInfo){
  738. FreeObjectInfo(pObjectInfo);
  739. }
  740. RRETURN(hr);
  741. }
  742. //----------------------------------------------------------------------------
  743. //
  744. // Function: NWApiMakeUserInfo
  745. //
  746. // Synopsis: This function is very provider specific.
  747. //
  748. //----------------------------------------------------------------------------
  749. HRESULT
  750. NWApiMakeUserInfo(
  751. LPWSTR lpszBinderyName,
  752. LPWSTR lpszUserName,
  753. LPWSTR lpszPassword,
  754. PNW_USER_INFO pNwUserInfo
  755. )
  756. {
  757. HRESULT hr = S_OK;
  758. NW_USER_INFO NwUserInfo = {NULL, NULL, NULL, NULL};
  759. hr = NWApiGetBinderyHandle(
  760. &NwUserInfo.hConn,
  761. lpszBinderyName
  762. );
  763. BAIL_ON_FAILURE(hr);
  764. hr = ADsAllocString(lpszBinderyName, &NwUserInfo.lpszBinderyName);
  765. BAIL_ON_FAILURE(hr);
  766. hr = ADsAllocString(lpszUserName, &NwUserInfo.lpszUserName);
  767. BAIL_ON_FAILURE(hr);
  768. if (lpszPassword) {
  769. hr = ADsAllocString(lpszPassword, &NwUserInfo.lpszPassword);
  770. BAIL_ON_FAILURE(hr);
  771. }
  772. //
  773. // Return.
  774. //
  775. *pNwUserInfo = NwUserInfo;
  776. RRETURN(hr);
  777. error:
  778. if (NwUserInfo.lpszBinderyName)
  779. ADsFreeString(NwUserInfo.lpszBinderyName);
  780. if (NwUserInfo.lpszUserName)
  781. ADsFreeString(NwUserInfo.lpszUserName);
  782. if (NwUserInfo.lpszPassword) {
  783. SecureZeroMemory(NwUserInfo.lpszPassword, wcslen(NwUserInfo.lpszPassword) * sizeof(WCHAR));
  784. ADsFreeString(NwUserInfo.lpszPassword);
  785. }
  786. RRETURN(hr);
  787. }
  788. //----------------------------------------------------------------------------
  789. //
  790. // Function: NWApiFreeUserInfo
  791. //
  792. // Synopsis: This function is very provider specific.
  793. //
  794. //----------------------------------------------------------------------------
  795. HRESULT
  796. NWApiFreeUserInfo(
  797. PNW_USER_INFO pNwUserInfo
  798. )
  799. {
  800. HRESULT hr = S_OK;
  801. if (pNwUserInfo->lpszBinderyName) {
  802. ADsFreeString(pNwUserInfo->lpszBinderyName);
  803. pNwUserInfo->lpszBinderyName = NULL ;
  804. }
  805. if (pNwUserInfo->lpszUserName) {
  806. ADsFreeString(pNwUserInfo->lpszUserName);
  807. pNwUserInfo->lpszUserName = NULL;
  808. }
  809. if (pNwUserInfo->lpszPassword) {
  810. SecureZeroMemory(pNwUserInfo->lpszPassword, wcslen(pNwUserInfo->lpszPassword) * sizeof(WCHAR));
  811. ADsFreeString(pNwUserInfo->lpszPassword);
  812. pNwUserInfo->lpszPassword = NULL;
  813. }
  814. if (pNwUserInfo->hConn) {
  815. hr = NWApiReleaseBinderyHandle(
  816. pNwUserInfo->hConn
  817. );
  818. BAIL_ON_FAILURE(hr);
  819. }
  820. error:
  821. RRETURN(hr);
  822. }
  823. //----------------------------------------------------------------------------
  824. //
  825. // Function: NWApiCreateUser
  826. //
  827. // Synopsis:
  828. //
  829. //----------------------------------------------------------------------------
  830. HRESULT
  831. NWApiCreateUser(
  832. PNW_USER_INFO pNwUserInfo
  833. )
  834. {
  835. HRESULT hr = S_OK;
  836. HRESULT hrTemp = S_OK;
  837. NTSTATUS Status = STATUS_SUCCESS;
  838. NWCCODE usRet = SUCCESSFUL;
  839. NWCONN_HANDLE hConn = NULL;
  840. NWOBJ_ID UserObjectID;
  841. UCHAR ChallengeKey[8];
  842. UCHAR NewKeyedPassword[17];
  843. UCHAR ValidationKey[8];
  844. WCHAR szTemp[MAX_PATH];
  845. //
  846. // "Create Bindery Object" - user object. This user object is going to be
  847. // static, with access equals to logged read, supervisor write.
  848. //
  849. hr = NWApiCreateBinderyObject(
  850. pNwUserInfo->hConn,
  851. pNwUserInfo->lpszUserName,
  852. OT_USER,
  853. BF_STATIC,
  854. BS_LOGGED_READ | BS_SUPER_WRITE
  855. );
  856. BAIL_ON_FAILURE(hr);
  857. //
  858. // Add user password.
  859. //
  860. hr = NWApiSetUserPassword(
  861. pNwUserInfo,
  862. &UserObjectID,
  863. NULL // no old passwd - this is a SET
  864. );
  865. BAIL_ON_FAILURE(hr);
  866. //
  867. // Create necessary bindery property to facilitate the addition of this user
  868. // to the group EVERYONE.
  869. //
  870. hr = NWApiCreateProperty(
  871. pNwUserInfo->hConn,
  872. pNwUserInfo->lpszUserName,
  873. OT_USER,
  874. "GROUPS_I'M_IN",
  875. BF_SET
  876. );
  877. BAIL_ON_FAILURE(hr);
  878. hr = NWApiCreateProperty(
  879. pNwUserInfo->hConn,
  880. pNwUserInfo->lpszUserName,
  881. OT_USER,
  882. "SECURITY_EQUALS",
  883. BF_SET
  884. );
  885. BAIL_ON_FAILURE(hr);
  886. //
  887. // Add this user to the group EVERYONE.
  888. // (okay if this fails, EVERYONE might not exist)
  889. //
  890. wcscpy(szTemp, L"EVERYONE");
  891. hrTemp = NWApiAddGroupMember(
  892. pNwUserInfo->hConn,
  893. szTemp,
  894. pNwUserInfo->lpszUserName
  895. );
  896. //
  897. // Create mail directory and login files.
  898. // (okay if this fails)
  899. //
  900. hrTemp = NWApiCreateMailDirectory(
  901. pNwUserInfo,
  902. UserObjectID
  903. );
  904. //
  905. // Create LOGIN_CONTROL & ACCOUNT_BALANCE property for the user. Values
  906. // from USER_DEFAULTS are used as default.
  907. //
  908. hr = NWApiSetLoginCtrlAndAcctBalance(
  909. pNwUserInfo
  910. );
  911. BAIL_ON_FAILURE(hr);
  912. error:
  913. RRETURN(hr);
  914. }
  915. //----------------------------------------------------------------------------
  916. //
  917. // Function: NWApiDeleteUser
  918. //
  919. // Synopsis:
  920. //
  921. //----------------------------------------------------------------------------
  922. HRESULT
  923. NWApiDeleteUser(
  924. POBJECTINFO pObjectInfo
  925. )
  926. {
  927. BOOL err = TRUE;
  928. DWORD dwErr = 0;
  929. HRESULT hr = S_OK;
  930. NWCONN_HANDLE hConn = NULL;
  931. NWOBJ_ID ObjectID;
  932. WCHAR szPath[MAX_PATH];
  933. //
  934. // Open a handle to the bindery.
  935. //
  936. hr = NWApiGetBinderyHandle(
  937. &hConn,
  938. pObjectInfo->ComponentArray[0]
  939. );
  940. BAIL_ON_FAILURE(hr);
  941. //
  942. // Get the user's ObjectID which is needed to compose the path name of LOGIN
  943. // and LOGIN.OS2.
  944. //
  945. hr = NWApiGetObjectID(
  946. hConn,
  947. pObjectInfo->ComponentArray[1],
  948. OT_USER,
  949. &ObjectID
  950. );
  951. BAIL_ON_FAILURE(hr);
  952. //
  953. // Delete SYS:MAIL\<JOBID>\LOGIN. If the file is not found, that's OK, as
  954. // long as it is not there.
  955. //
  956. wsprintf(
  957. szPath,
  958. L"\\\\%s\\SYS\\MAIL\\%X\\LOGIN",
  959. pObjectInfo->ComponentArray[0],
  960. dwSWAP(ObjectID)
  961. );
  962. err = DeleteFile(szPath);
  963. //
  964. // Remove any error checking for the cleanup of
  965. // files. If they do exist, and we do clean them up
  966. // great. But otherwise Win95 chokes on us.
  967. //
  968. //
  969. // Delete SYS:MAIL\<JOBID>\LOGIN.OS2. If the file is not found, that's OK,
  970. // as long as it is not there.
  971. //
  972. wsprintf(
  973. szPath,
  974. L"\\\\%s\\SYS\\MAIL\\%X\\LOGIN.OS2",
  975. pObjectInfo->ComponentArray[0],
  976. dwSWAP(ObjectID)
  977. );
  978. err = DeleteFile(szPath);
  979. //
  980. // Remove any error checking for the cleanup of
  981. // files. If they do exist, and we do clean them up
  982. // great. But otherwise Win95 chokes on us.
  983. //
  984. //
  985. // Delete SYS:MAIL\<JOBID>.
  986. //
  987. wsprintf(
  988. szPath,
  989. L"\\\\%s\\SYS\\MAIL\\%X",
  990. pObjectInfo->ComponentArray[0],
  991. dwSWAP(ObjectID)
  992. );
  993. err = RemoveDirectory(szPath);
  994. //
  995. // Remove any error checking for the cleanup of
  996. // files. If they do exist, and we do clean them up
  997. // great. But otherwise Win95 chokes on us.
  998. //
  999. //
  1000. // Delete the user object.
  1001. //
  1002. hr = NWApiDeleteBinderyObject(
  1003. hConn,
  1004. pObjectInfo->ComponentArray[1],
  1005. OT_USER
  1006. );
  1007. BAIL_ON_FAILURE(hr);
  1008. error:
  1009. NWApiReleaseBinderyHandle(hConn);
  1010. RRETURN(hr);
  1011. }
  1012. //----------------------------------------------------------------------------
  1013. //
  1014. // Function: NWApiCreateBinderyObject
  1015. //
  1016. // Synopsis: This function create the specified object in the specified NetWare
  1017. // bindery. It returns S_OK if the object alread exist.
  1018. //
  1019. //----------------------------------------------------------------------------
  1020. HRESULT
  1021. NWApiCreateBinderyObject(
  1022. NWCONN_HANDLE hConn,
  1023. LPWSTR lpszObjectName,
  1024. NWOBJ_TYPE wObjType,
  1025. NWFLAGS ucObjectFlags,
  1026. NWFLAGS usObjSecurity
  1027. )
  1028. {
  1029. CHAR szAnsiObjectName[(OBJ_NAME_SIZE + 1)*2];
  1030. HRESULT hr = S_OK;
  1031. NWCCODE usRet = SUCCESSFUL;
  1032. //
  1033. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  1034. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1035. //
  1036. if (wcslen(lpszObjectName) > OBJ_NAME_SIZE) {
  1037. RRETURN(E_INVALIDARG);
  1038. }
  1039. UnicodeToAnsiString(
  1040. lpszObjectName,
  1041. szAnsiObjectName,
  1042. 0
  1043. );
  1044. //
  1045. // Create a Static object with LOGGED_READ & SUPERVISOR_WRITE.
  1046. //
  1047. usRet = NWCCreateObject(
  1048. hConn,
  1049. szAnsiObjectName,
  1050. wObjType,
  1051. BF_STATIC,
  1052. BS_LOGGED_READ | BS_SUPER_WRITE
  1053. );
  1054. //
  1055. // If an error occured, check if it is OBJECT_ALREADY_EXISTS. If it is,
  1056. // treat it as no error.
  1057. //
  1058. if (usRet) {
  1059. if (usRet == OBJECT_ALREADY_EXISTS) {
  1060. usRet = SUCCESSFUL;
  1061. }
  1062. }
  1063. //
  1064. // Return.
  1065. //
  1066. hr = HRESULT_FROM_NWCCODE(usRet);
  1067. RRETURN(hr);
  1068. }
  1069. //----------------------------------------------------------------------------
  1070. //
  1071. // Function: NWApiDeleteBinderyObject
  1072. //
  1073. // Synopsis:
  1074. //
  1075. //----------------------------------------------------------------------------
  1076. HRESULT
  1077. NWApiDeleteBinderyObject(
  1078. NWCONN_HANDLE hConn,
  1079. LPWSTR lpszObjectName,
  1080. NWOBJ_TYPE wObjType
  1081. )
  1082. {
  1083. CHAR szAnsiObjectName[(OBJ_NAME_SIZE + 1)*2];
  1084. HRESULT hr = S_OK;
  1085. NWCCODE usRet = SUCCESSFUL;
  1086. //
  1087. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  1088. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1089. //
  1090. if (wcslen(lpszObjectName) > OBJ_NAME_SIZE) {
  1091. RRETURN(E_INVALIDARG);
  1092. }
  1093. UnicodeToAnsiString(
  1094. lpszObjectName,
  1095. szAnsiObjectName,
  1096. 0
  1097. );
  1098. //
  1099. // Delete the object from the bindery.
  1100. //
  1101. usRet = NWCDeleteObject(
  1102. hConn,
  1103. szAnsiObjectName,
  1104. wObjType
  1105. );
  1106. //
  1107. // Return.
  1108. //
  1109. hr = HRESULT_FROM_NWCCODE(usRet);
  1110. RRETURN(hr);
  1111. }
  1112. #define NW_MAX_PASSWORD_LEN 256
  1113. //----------------------------------------------------------------------------
  1114. //
  1115. // Function: NWApiSetUserPassword
  1116. //
  1117. // Synopsis:
  1118. //
  1119. //----------------------------------------------------------------------------
  1120. HRESULT
  1121. NWApiSetUserPassword(
  1122. PNW_USER_INFO pNwUserInfo,
  1123. DWORD *pdwUserObjID,
  1124. LPWSTR pszOldPassword
  1125. )
  1126. {
  1127. CHAR szAnsiUserName[(OBJ_NAME_SIZE + 1)*2];
  1128. CHAR szAnsiPassword[(NW_MAX_PASSWORD_LEN + 1)*2];
  1129. CHAR szAnsiOldPassword[(NW_MAX_PASSWORD_LEN + 1)*2];
  1130. CHAR Buffer[128];
  1131. DWORD err = 0;
  1132. HRESULT hr = S_OK;
  1133. LC_STRUCTURE LoginCtrl;
  1134. NTSTATUS NtStatus;
  1135. UCHAR ChallengeKey[8];
  1136. UCHAR ucMoreFlag;
  1137. UCHAR ucPropFlag;
  1138. WCHAR szOldPasswordCopy[NW_MAX_PASSWORD_LEN + 1];
  1139. if ( !pNwUserInfo ||
  1140. !(pNwUserInfo->lpszUserName) ||
  1141. !(pNwUserInfo->lpszPassword) ) {
  1142. hr = E_INVALIDARG ;
  1143. BAIL_ON_FAILURE(hr);
  1144. }
  1145. if ( (wcslen(pNwUserInfo->lpszUserName) > OBJ_NAME_SIZE) ||
  1146. (wcslen(pNwUserInfo->lpszPassword) > NW_MAX_PASSWORD_LEN) ||
  1147. ( pszOldPassword && (wcslen(pszOldPassword) > NW_MAX_PASSWORD_LEN)) ) {
  1148. hr = E_INVALIDARG;
  1149. BAIL_ON_FAILURE(hr);
  1150. }
  1151. //
  1152. // Convert UNICODE into ANSI representation required by NW APIs. "0" is
  1153. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1154. //
  1155. err = UnicodeToAnsiString(
  1156. pNwUserInfo->lpszUserName,
  1157. szAnsiUserName,
  1158. 0
  1159. );
  1160. if (!err) {
  1161. hr = E_FAIL;
  1162. BAIL_ON_FAILURE(hr);
  1163. }
  1164. _wcsupr(pNwUserInfo->lpszPassword) ;
  1165. err = UnicodeToAnsiString(
  1166. pNwUserInfo->lpszPassword,
  1167. szAnsiPassword,
  1168. 0
  1169. );
  1170. if (!err) {
  1171. hr = E_FAIL;
  1172. BAIL_ON_FAILURE(hr);
  1173. }
  1174. if (pszOldPassword) {
  1175. wcscpy(szOldPasswordCopy, pszOldPassword);
  1176. _wcsupr(szOldPasswordCopy) ;
  1177. err = UnicodeToAnsiString(
  1178. szOldPasswordCopy,
  1179. szAnsiOldPassword,
  1180. 0
  1181. );
  1182. if (!err) {
  1183. hr = E_FAIL;
  1184. BAIL_ON_FAILURE(hr);
  1185. }
  1186. }
  1187. else {
  1188. szAnsiOldPassword[0] = 0 ;
  1189. }
  1190. //
  1191. // Get challenge key.
  1192. //
  1193. err = NWApiMapNtStatusToDosError(
  1194. NWPGetChallengeKey(
  1195. pNwUserInfo->hConn,
  1196. ChallengeKey
  1197. ));
  1198. if (!err) {
  1199. //
  1200. // For NetWare 4.x servers, this has to be done after the
  1201. // NWPGetChallengeKey so that the object id returned can be used to
  1202. // encrypt the password. 4.x bindery emulation might return different
  1203. // object ids for some users depending on whether the NWPGetChallengeKey
  1204. // is called beforehand.
  1205. //
  1206. err = NWApiMapNtStatusToDosError(
  1207. NWPGetObjectID(
  1208. pNwUserInfo->hConn,
  1209. szAnsiUserName,
  1210. OT_USER,
  1211. pdwUserObjID
  1212. ));
  1213. }
  1214. if (!err) {
  1215. //
  1216. // The old password and object ID make up the 17-byte Vold. This is used
  1217. // later to form the 17-byte Vc for changing password on the server.
  1218. //
  1219. UCHAR ValidationKey[8];
  1220. UCHAR NewKeyedPassword[17];
  1221. EncryptChangePassword(
  1222. (PUCHAR) szAnsiOldPassword,
  1223. (PUCHAR) szAnsiPassword,
  1224. *pdwUserObjID,
  1225. ChallengeKey,
  1226. ValidationKey,
  1227. NewKeyedPassword
  1228. );
  1229. err = NWApiMapNtStatusToDosError(
  1230. NWPChangeObjectPasswordEncrypted(
  1231. pNwUserInfo->hConn,
  1232. szAnsiUserName,
  1233. OT_USER,
  1234. ValidationKey,
  1235. NewKeyedPassword
  1236. ));
  1237. }
  1238. //
  1239. // Return.
  1240. //
  1241. hr = HRESULT_FROM_WIN32(err);
  1242. error:
  1243. SecureZeroMemory(szAnsiPassword, sizeof(szAnsiPassword));
  1244. SecureZeroMemory(szAnsiOldPassword, sizeof(szAnsiOldPassword));
  1245. SecureZeroMemory(szOldPasswordCopy, sizeof(szOldPasswordCopy));
  1246. RRETURN(hr);
  1247. }
  1248. //----------------------------------------------------------------------------
  1249. //
  1250. // Function: NWApiCreateMailDirectory
  1251. //
  1252. // Synopsis:
  1253. //
  1254. //----------------------------------------------------------------------------
  1255. HRESULT
  1256. NWApiCreateMailDirectory(
  1257. PNW_USER_INFO pNwUserInfo,
  1258. NWOBJ_ID UserObjID
  1259. )
  1260. {
  1261. BYTE szPath[(MAX_PATH + 1) * sizeof(WCHAR)];
  1262. CHAR szUserObjID[255];
  1263. DWORD err = 0;
  1264. HRESULT hr = S_OK;
  1265. //
  1266. // Make path.
  1267. //
  1268. _ltoa(
  1269. dwSWAP(UserObjID),
  1270. szUserObjID,
  1271. 16
  1272. );
  1273. strcpy((char *) szPath, "SYS:\\MAIL\\");
  1274. strcat((char *) szPath, szUserObjID);
  1275. //
  1276. // Create a directory with Maximum rights mask.
  1277. //
  1278. err = NWApiMapNtStatusToDosError(
  1279. NWPCreateDirectory(
  1280. pNwUserInfo->hConn,
  1281. 0,
  1282. (char *) szPath,
  1283. 0xFF // From SysCon --- Max. access rights for directory
  1284. )); // = Full Access
  1285. if ( !err ) {
  1286. //
  1287. // Add a trustee with all rights except PARENTAL right.
  1288. //
  1289. err = NWApiMapNtStatusToDosError(
  1290. NWPAddTrustee(
  1291. pNwUserInfo->hConn,
  1292. 0,
  1293. (char *) szPath,
  1294. UserObjID,
  1295. 0xDF // From SysCon --- Trustee has all rights
  1296. )); // EXCEPT parental rights (right to create/
  1297. // delete subdirs, make others trustees)
  1298. //
  1299. // Create a Login file.
  1300. //
  1301. if ( !err ) {
  1302. HANDLE hFile;
  1303. wsprintfW(
  1304. (LPWSTR) szPath,
  1305. L"\\\\%ws\\SYS\\MAIL\\%X\\LOGIN",
  1306. pNwUserInfo->lpszBinderyName,
  1307. dwSWAP(UserObjID)
  1308. );
  1309. hFile = CreateFile(
  1310. (LPWSTR) szPath,
  1311. GENERIC_WRITE,
  1312. 0,
  1313. NULL,
  1314. OPEN_ALWAYS,
  1315. FILE_ATTRIBUTE_NORMAL,
  1316. 0
  1317. );
  1318. if ( hFile == INVALID_HANDLE_VALUE ) {
  1319. err = GetLastError();
  1320. }
  1321. if ( !err )
  1322. CloseHandle( hFile );
  1323. if (!err) {
  1324. //
  1325. // Create a Login.os2 file.
  1326. //
  1327. wsprintfW(
  1328. (LPWSTR) szPath,
  1329. L"\\\\%ws\\SYS\\MAIL\\%X\\LOGIN.OS2",
  1330. pNwUserInfo->lpszBinderyName,
  1331. dwSWAP(UserObjID)
  1332. );
  1333. hFile = CreateFile(
  1334. (LPWSTR) szPath,
  1335. GENERIC_WRITE,
  1336. 0,
  1337. NULL,
  1338. OPEN_ALWAYS,
  1339. FILE_ATTRIBUTE_NORMAL,
  1340. 0
  1341. );
  1342. if ( hFile == INVALID_HANDLE_VALUE ) {
  1343. err = GetLastError();
  1344. }
  1345. if ( !err )
  1346. CloseHandle( hFile );
  1347. }
  1348. }
  1349. }
  1350. // err == 255 == "FAILURE"
  1351. // might be used to indicate directory already exists,
  1352. // but also used to signal generic failure
  1353. hr = HRESULT_FROM_WIN32(err);
  1354. RRETURN(hr);
  1355. }
  1356. //----------------------------------------------------------------------------
  1357. //
  1358. // Function: NWApiSetLoginCtrlAndAcctBalance
  1359. //
  1360. // Synopsis:
  1361. //
  1362. //----------------------------------------------------------------------------
  1363. HRESULT
  1364. NWApiSetLoginCtrlAndAcctBalance(
  1365. PNW_USER_INFO pNwUserInfo
  1366. )
  1367. {
  1368. ACCT_BALANCE AccountBalance;
  1369. DWORD dwNumSegment;
  1370. HRESULT hr = S_OK;
  1371. int i = 0;
  1372. LC_STRUCTURE LoginCtrl;
  1373. LP_RPLY_SGMT_LST lpReplySegment = NULL;
  1374. LP_RPLY_SGMT_LST lpTemp = NULL;
  1375. USER_DEFAULT UserDefault;
  1376. WCHAR szTemp[MAX_PATH];
  1377. //
  1378. // Get Supervisor's USER_DEFAULTS.
  1379. //
  1380. wcscpy(szTemp, NW_PROP_SUPERVISORW);
  1381. hr = NWApiGetProperty(
  1382. szTemp,
  1383. NW_PROP_USER_DEFAULTS,
  1384. OT_USER,
  1385. pNwUserInfo->hConn,
  1386. &lpReplySegment,
  1387. &dwNumSegment
  1388. );
  1389. if (SUCCEEDED(hr)) {
  1390. UserDefault = *((LPUSER_DEFAULT) lpReplySegment->Segment);
  1391. //
  1392. // Put default values into LoginCtrl.
  1393. //
  1394. LoginCtrl.byAccountExpires[0] = UserDefault.byAccountExpiresYear;
  1395. LoginCtrl.byAccountExpires[1] = UserDefault.byAccountExpiresMonth;
  1396. LoginCtrl.byAccountExpires[2] = UserDefault.byAccountExpiresDay;
  1397. LoginCtrl.byAccountDisabled = 0;
  1398. LoginCtrl.byPasswordExpires[0] = 85;
  1399. LoginCtrl.byPasswordExpires[1] = 01;
  1400. LoginCtrl.byPasswordExpires[2] = 01;
  1401. LoginCtrl.byGraceLogins = UserDefault.byGraceLoginReset;
  1402. LoginCtrl.wPasswordInterval = UserDefault.wPasswordInterval;
  1403. LoginCtrl.byGraceLoginReset = UserDefault.byGraceLoginReset;
  1404. LoginCtrl.byMinPasswordLength = UserDefault.byMinPasswordLength;
  1405. LoginCtrl.wMaxConnections = UserDefault.wMaxConnections;
  1406. LoginCtrl.byRestrictions = UserDefault.byRestrictions;
  1407. LoginCtrl.byUnused = 0;
  1408. LoginCtrl.lMaxDiskBlocks = UserDefault.lMaxDiskBlocks;
  1409. LoginCtrl.wBadLogins = 0;
  1410. LoginCtrl.lNextResetTime = 0;
  1411. for (i = 0; i < 42; i++) {
  1412. LoginCtrl.byLoginTimes[i] = UserDefault.byLoginTimes[i];
  1413. }
  1414. for (i = 0; i < 6; i++) {
  1415. LoginCtrl.byLastLogin[i] = 0;
  1416. }
  1417. for (i = 0; i < 12; i++) {
  1418. LoginCtrl.byBadLoginAddr[i] = 0;
  1419. }
  1420. LoginCtrl.byGraceLogins = LoginCtrl.byGraceLoginReset;
  1421. //
  1422. // Put default values into AccountBalance.
  1423. //
  1424. AccountBalance.lBalance = UserDefault.lBalance;
  1425. AccountBalance.lCreditLimit = UserDefault.lCreditLimit;
  1426. //
  1427. // Write LOGIN_CONTROL property.
  1428. //
  1429. hr = NWApiWriteProperty(
  1430. pNwUserInfo->hConn,
  1431. pNwUserInfo->lpszUserName,
  1432. OT_USER,
  1433. NW_PROP_LOGIN_CONTROL,
  1434. (LPBYTE) &LoginCtrl
  1435. );
  1436. BAIL_ON_FAILURE(hr);
  1437. //
  1438. // Write ACCOUNT_BALANCE property.
  1439. //
  1440. hr = NWApiWriteProperty(
  1441. pNwUserInfo->hConn,
  1442. pNwUserInfo->lpszUserName,
  1443. OT_USER,
  1444. NW_PROP_ACCOUNT_BALANCE,
  1445. (LPBYTE) &AccountBalance
  1446. );
  1447. BAIL_ON_FAILURE(hr);
  1448. }
  1449. //
  1450. // SUPERVISOR may not exist, or may not have USER_DEFAULTS.
  1451. // This is okay.
  1452. //
  1453. hr = S_OK;
  1454. error:
  1455. if (lpReplySegment) {
  1456. DELETE_LIST(lpReplySegment);
  1457. }
  1458. RRETURN(hr);
  1459. }
  1460. //----------------------------------------------------------------------------
  1461. //
  1462. // Function: NWApiCreateGroup
  1463. //
  1464. // Synopsis:
  1465. //
  1466. //----------------------------------------------------------------------------
  1467. HRESULT
  1468. NWApiCreateGroup(
  1469. POBJECTINFO pObjectInfo
  1470. )
  1471. {
  1472. HRESULT hr = S_OK;
  1473. NWCONN_HANDLE hConn = NULL;
  1474. //
  1475. // Open a handle to the bindery.
  1476. //
  1477. hr = NWApiGetBinderyHandle(
  1478. &hConn,
  1479. pObjectInfo->ComponentArray[0]
  1480. );
  1481. BAIL_ON_FAILURE(hr);
  1482. //
  1483. // Create a group bindery object.
  1484. //
  1485. hr = NWApiCreateBinderyObject(
  1486. hConn,
  1487. pObjectInfo->ComponentArray[1],
  1488. OT_USER_GROUP,
  1489. BF_STATIC,
  1490. BS_LOGGED_READ | BS_SUPER_WRITE
  1491. );
  1492. BAIL_ON_FAILURE(hr);
  1493. //
  1494. // Create GROUP_MEMBERS property.
  1495. //
  1496. hr = NWApiCreateProperty(
  1497. hConn,
  1498. pObjectInfo->ComponentArray[1],
  1499. OT_USER_GROUP,
  1500. NW_PROP_GROUP_MEMBERS,
  1501. BF_SET
  1502. );
  1503. BAIL_ON_FAILURE(hr);
  1504. error:
  1505. NWApiReleaseBinderyHandle(hConn);
  1506. RRETURN(hr);
  1507. }
  1508. //----------------------------------------------------------------------------
  1509. //
  1510. // Function: NWApiDeleteGroup
  1511. //
  1512. // Synopsis:
  1513. //
  1514. //----------------------------------------------------------------------------
  1515. HRESULT
  1516. NWApiDeleteGroup(
  1517. POBJECTINFO pObjectInfo
  1518. )
  1519. {
  1520. HRESULT hr = S_OK;
  1521. NWCONN_HANDLE hConn = NULL;
  1522. //
  1523. // Open a handle to the bindery.
  1524. //
  1525. hr = NWApiGetBinderyHandle(
  1526. &hConn,
  1527. pObjectInfo->ComponentArray[0]
  1528. );
  1529. BAIL_ON_FAILURE(hr);
  1530. //
  1531. // Delete the group object.
  1532. //
  1533. hr = NWApiDeleteBinderyObject(
  1534. hConn,
  1535. pObjectInfo->ComponentArray[1],
  1536. OT_USER_GROUP
  1537. );
  1538. BAIL_ON_FAILURE(hr);
  1539. error:
  1540. NWApiReleaseBinderyHandle(hConn);
  1541. RRETURN(hr);
  1542. }
  1543. //----------------------------------------------------------------------------
  1544. //
  1545. // Function: NWApiCreatePrinter
  1546. //
  1547. // Synopsis:
  1548. //
  1549. //----------------------------------------------------------------------------
  1550. HRESULT
  1551. NWApiCreatePrinter(
  1552. POBJECTINFO pObjectInfo
  1553. )
  1554. {
  1555. CHAR szQueueName[(OBJ_NAME_SIZE + 1)*2];
  1556. HRESULT hr = S_OK;
  1557. NWCCODE usRet = SUCCESSFUL;
  1558. NWCONN_HANDLE hConn = NULL;
  1559. WCHAR szTemp[MAX_PATH];
  1560. //
  1561. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  1562. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1563. //
  1564. if (wcslen(pObjectInfo->ComponentArray[1]) > OBJ_NAME_SIZE) {
  1565. RRETURN(E_INVALIDARG);
  1566. }
  1567. UnicodeToAnsiString(
  1568. pObjectInfo->ComponentArray[1],
  1569. szQueueName,
  1570. 0
  1571. );
  1572. //
  1573. // Open a handle to the bindery.
  1574. //
  1575. hr = NWApiGetBinderyHandle(
  1576. &hConn,
  1577. pObjectInfo->ComponentArray[0]
  1578. );
  1579. BAIL_ON_FAILURE(hr);
  1580. //
  1581. // Create a print queue object.
  1582. //
  1583. hr = NWApiCreatePrintQueue(
  1584. hConn,
  1585. pObjectInfo->ComponentArray[1]
  1586. );
  1587. BAIL_ON_FAILURE(hr);
  1588. //
  1589. // Change property security.
  1590. //
  1591. usRet = NWCChangePropertySecurity(
  1592. hConn,
  1593. szQueueName,
  1594. OT_PRINT_QUEUE,
  1595. NW_PROP_Q_OPERATORS,
  1596. BS_LOGGED_READ | BS_SUPER_WRITE
  1597. );
  1598. hr = HRESULT_FROM_NWCCODE(usRet);
  1599. BAIL_ON_FAILURE(hr);
  1600. //
  1601. // Add SUPERVISOR to Q_OPERATORS.
  1602. // (okay if this fails, maybe SUPERVISOR doesn't exist)
  1603. //
  1604. usRet = NWCAddObjectToSet(
  1605. hConn,
  1606. szQueueName,
  1607. OT_PRINT_QUEUE,
  1608. NW_PROP_Q_OPERATORS,
  1609. NW_PROP_SUPERVISOR,
  1610. OT_USER
  1611. );
  1612. //
  1613. // Add EVERYONE to Q_USERS.
  1614. // (okay if this fails, maybe EVERYONE doesn't exist)
  1615. //
  1616. usRet = NWCAddObjectToSet(
  1617. hConn,
  1618. szQueueName,
  1619. OT_PRINT_QUEUE,
  1620. NW_PROP_Q_USERS,
  1621. NW_PROP_EVERYONE,
  1622. OT_USER_GROUP
  1623. );
  1624. //
  1625. // Return.
  1626. //
  1627. error:
  1628. NWApiReleaseBinderyHandle(hConn);
  1629. RRETURN(hr);
  1630. }
  1631. //----------------------------------------------------------------------------
  1632. //
  1633. // Function: NWApiDeleteGroup
  1634. //
  1635. // Synopsis:
  1636. //
  1637. //----------------------------------------------------------------------------
  1638. HRESULT
  1639. NWApiDeletePrinter(
  1640. POBJECTINFO pObjectInfo
  1641. )
  1642. {
  1643. HRESULT hr = S_OK;
  1644. NWCONN_HANDLE hConn = NULL;
  1645. NWOBJ_ID dwQueueID = 0;
  1646. //
  1647. // Open a handle to the bindery.
  1648. //
  1649. hr = NWApiGetBinderyHandle(
  1650. &hConn,
  1651. pObjectInfo->ComponentArray[0]
  1652. );
  1653. BAIL_ON_FAILURE(hr);
  1654. //
  1655. // Get Queue ID.
  1656. //
  1657. hr = NWApiDestroyPrintQueue(
  1658. hConn,
  1659. pObjectInfo->ComponentArray[1]
  1660. );
  1661. BAIL_ON_FAILURE(hr);
  1662. error:
  1663. NWApiReleaseBinderyHandle(hConn);
  1664. RRETURN(hr);
  1665. }
  1666. //----------------------------------------------------------------------------
  1667. //
  1668. // Function: NWApiCreatePrintQueue
  1669. //
  1670. // Synopsis:
  1671. //
  1672. //----------------------------------------------------------------------------
  1673. HRESULT
  1674. NWApiCreatePrintQueue(
  1675. NWCONN_HANDLE hConn,
  1676. LPWSTR lpszQueueName
  1677. )
  1678. {
  1679. CHAR szQueueName[(OBJ_NAME_SIZE + 1)*2];
  1680. DWORD dwQueueID = 0;
  1681. HRESULT hr = S_OK;
  1682. NWCCODE usRet = SUCCESSFUL;
  1683. //
  1684. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  1685. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1686. //
  1687. if (wcslen(lpszQueueName) > OBJ_NAME_SIZE) {
  1688. RRETURN(E_INVALIDARG);
  1689. }
  1690. UnicodeToAnsiString(
  1691. lpszQueueName,
  1692. szQueueName,
  1693. 0
  1694. );
  1695. //
  1696. // Create a print queue object.
  1697. //
  1698. usRet = NWCCreateQueue(
  1699. hConn,
  1700. NULL,
  1701. szQueueName,
  1702. OT_PRINT_QUEUE,
  1703. NW_PRINTER_PATH,
  1704. &dwQueueID
  1705. );
  1706. hr = HRESULT_FROM_NWCCODE(usRet);
  1707. //
  1708. // Return.
  1709. //
  1710. RRETURN(hr);
  1711. }
  1712. //----------------------------------------------------------------------------
  1713. //
  1714. // Function: NWApiDestroyPrintQueue
  1715. //
  1716. // Synopsis:
  1717. //
  1718. //----------------------------------------------------------------------------
  1719. HRESULT
  1720. NWApiDestroyPrintQueue(
  1721. NWCONN_HANDLE hConn,
  1722. LPWSTR lpszQueueName
  1723. )
  1724. {
  1725. DWORD dwQueueID = 0;
  1726. HRESULT hr = S_OK;
  1727. NWCCODE usRet = SUCCESSFUL;
  1728. //
  1729. // Get Queue ID.
  1730. //
  1731. hr = NWApiGetObjectID(
  1732. hConn,
  1733. lpszQueueName,
  1734. OT_PRINT_QUEUE,
  1735. &dwQueueID
  1736. );
  1737. BAIL_ON_FAILURE(hr);
  1738. //
  1739. // Destroy print queue.
  1740. //
  1741. usRet = NWCDestroyQueue(
  1742. hConn,
  1743. dwSWAP(dwQueueID)
  1744. );
  1745. hr = HRESULT_FROM_NWCCODE(usRet);
  1746. //
  1747. // Return.
  1748. //
  1749. error:
  1750. RRETURN(hr);
  1751. }
  1752. //----------------------------------------------------------------------------
  1753. //
  1754. // Function: NWApiMapNtStatusToDosError
  1755. //
  1756. // Synopsis: This function maps the ntstatus that was returned from the NetWare
  1757. // redirector to window errors. Similar to RtlNtStatusToDosError
  1758. // except that the special handling is done to ntstatus with netware
  1759. // facility codes.
  1760. //
  1761. // Argument: NtStatus - The ntstatus returned from NetWare rdr
  1762. //
  1763. // Return Value: WinError
  1764. //
  1765. //----------------------------------------------------------------------------
  1766. DWORD
  1767. NWApiMapNtStatusToDosError(
  1768. IN NTSTATUS NtStatus
  1769. )
  1770. {
  1771. if ( (HIWORD( NtStatus) & FACILITY_NWRDR ) == FACILITY_NWRDR )
  1772. {
  1773. if ( NtStatus == NWRDR_PASSWORD_HAS_EXPIRED )
  1774. return ERROR_PASSWORD_EXPIRED;
  1775. else
  1776. return NETWARE_GENERAL_ERROR;
  1777. }
  1778. else if ( HIWORD( NtStatus) == 0xC001 )
  1779. {
  1780. return LOWORD( NtStatus ) + NETWARE_ERROR_BASE;
  1781. }
  1782. return RtlNtStatusToDosError( NtStatus );
  1783. }
  1784. //----------------------------------------------------------------------------
  1785. //
  1786. // Function: NWApiConvertToAddressFormat
  1787. //
  1788. // Synopsis: Convert an IPX address obtain from NWApiGetProperty into the
  1789. // format specified in spec.
  1790. //
  1791. //----------------------------------------------------------------------------
  1792. HRESULT
  1793. NWApiConvertToAddressFormat(
  1794. LP_RPLY_SGMT_LST lpReplySegment,
  1795. LPWSTR *lppszAddresses
  1796. )
  1797. {
  1798. int i = 0;
  1799. LPBYTE lpBuffer = NULL;
  1800. LPWSTR lpszTemp = NULL;
  1801. WORD wSegment[NET_ADDRESS_WORD_SIZE];
  1802. //
  1803. // Put values from szReply into the wSegment array
  1804. //
  1805. lpBuffer = (LPBYTE) lpReplySegment->Segment;
  1806. for (i = 0; i < NET_ADDRESS_WORD_SIZE; i++) {
  1807. wSegment[i] = NWApiReverseWORD(*((LPWORD)lpBuffer + i));
  1808. }
  1809. //
  1810. // Put address together in the format described in spec.
  1811. //
  1812. lpszTemp = (LPWSTR) AllocADsMem((NET_ADDRESS_NUM_CHAR+1)*sizeof(WCHAR));
  1813. if (!lpszTemp) {
  1814. RRETURN(E_OUTOFMEMORY);
  1815. }
  1816. wsprintf(
  1817. lpszTemp,
  1818. L"%s:%04X%04X.%04X%04X%04X.%04X",
  1819. bstrAddressTypeString,
  1820. wSegment[0],
  1821. wSegment[1],
  1822. wSegment[2],
  1823. wSegment[3],
  1824. wSegment[4],
  1825. wSegment[5]
  1826. );
  1827. //
  1828. // Return.
  1829. //
  1830. *lppszAddresses = lpszTemp;
  1831. RRETURN(S_OK);
  1832. }
  1833. //----------------------------------------------------------------------------
  1834. //
  1835. // Function: NWApiMakeVariantTime
  1836. //
  1837. // Synopsis: This function creates a double precision variant time.
  1838. //
  1839. //----------------------------------------------------------------------------
  1840. HRESULT
  1841. NWApiMakeVariantTime(
  1842. DOUBLE * pdTime,
  1843. WORD wDay, // Day = 1..31
  1844. WORD wMonth, // Month = 1..12
  1845. WORD wYear, // Year = (19XX or 20XX) - 1980, ie. 2019 -> 39
  1846. WORD wSecond, // Second = 0..30, Second divided by 2
  1847. WORD wMinute, // Minute = 0..59
  1848. WORD wHour // Hour = 0..23
  1849. )
  1850. {
  1851. BOOL fBool = TRUE;
  1852. DOUBLE vTime = 0;
  1853. WORD wDOSDate = 0;
  1854. WORD wDOSTime = 0;
  1855. //
  1856. // Fix up parameters.
  1857. // If wDay and wMonth are 0, turn them into one.
  1858. //
  1859. if (wDay == 0) {
  1860. wDay++;
  1861. }
  1862. if (wMonth == 0) {
  1863. wMonth++;
  1864. }
  1865. //
  1866. // Shift data to correct bit as required by the DOS date & time format.
  1867. //
  1868. wMonth = wMonth << 5;
  1869. wYear = wYear << 9;
  1870. wMinute = wMinute << 5;
  1871. wHour = wHour << 11;
  1872. //
  1873. // Put them in DOS format.
  1874. //
  1875. wDOSDate = wYear | wMonth | wDay;
  1876. wDOSTime = wHour | wMinute | wSecond;
  1877. //
  1878. // Convert into VariantTime.
  1879. //
  1880. fBool = DosDateTimeToVariantTime(
  1881. wDOSDate,
  1882. wDOSTime,
  1883. &vTime
  1884. );
  1885. //
  1886. // Return.
  1887. //
  1888. if (fBool == TRUE) {
  1889. *pdTime = vTime;
  1890. RRETURN(S_OK);
  1891. }
  1892. else {
  1893. RRETURN(E_FAIL);
  1894. }
  1895. }
  1896. //----------------------------------------------------------------------------
  1897. //
  1898. // Function: NWApiBreakVariantTime
  1899. //
  1900. // Synopsis: This function interprets a double precision variant time and
  1901. // returns the day, month and year individually.
  1902. //
  1903. //----------------------------------------------------------------------------
  1904. HRESULT
  1905. NWApiBreakVariantTime(
  1906. DOUBLE daDate,
  1907. PWORD pwDay,
  1908. PWORD pwMonth,
  1909. PWORD pwYear
  1910. )
  1911. {
  1912. BOOL fBool;
  1913. DOUBLE vTime;
  1914. WORD wDOSDate = 0;
  1915. WORD wDOSTime = 0;
  1916. WORD wDay = 0;
  1917. WORD wMonth = 0;
  1918. WORD wYear = 0;
  1919. //
  1920. // Convert variant time into DOS format.
  1921. //
  1922. fBool = VariantTimeToDosDateTime(
  1923. daDate,
  1924. &wDOSDate,
  1925. &wDOSTime
  1926. );
  1927. if (fBool == FALSE) {
  1928. goto error;
  1929. }
  1930. //
  1931. // Year: bits 9-15, add 80 to wYear because 80 was subtracted from it to
  1932. // call VariantTimeToDosDateTime.
  1933. //
  1934. wYear = wDOSDate >> 9;
  1935. wYear += 80;
  1936. //
  1937. // Month: bits 5-8.
  1938. //
  1939. wMonth = (wDOSDate >> 5) - (wYear << 4);
  1940. //
  1941. // Day: bits 0-4.
  1942. //
  1943. wDay = wDOSDate - (wMonth << 5) - (wYear << 9);
  1944. //
  1945. // Return.
  1946. //
  1947. *pwDay = wDay;
  1948. *pwMonth = wMonth;
  1949. *pwYear = wYear;
  1950. RRETURN(S_OK);
  1951. error:
  1952. RRETURN(E_FAIL);
  1953. }
  1954. //----------------------------------------------------------------------------
  1955. //
  1956. // Function: NWApiReverseWORD
  1957. //
  1958. // Synopsis: This function reverse a WORD.
  1959. //
  1960. //----------------------------------------------------------------------------
  1961. WORD
  1962. NWApiReverseWORD(
  1963. WORD wWORD
  1964. )
  1965. {
  1966. LPBYTE lpbTemp = (LPBYTE) &wWORD;
  1967. BYTE bTemp;
  1968. bTemp = *lpbTemp;
  1969. *lpbTemp = *(lpbTemp + 1);
  1970. *(lpbTemp + 1) = bTemp;
  1971. return(*((LPWORD) lpbTemp));
  1972. }
  1973. //----------------------------------------------------------------------------
  1974. //
  1975. // Function: NWApiUserGetGroups
  1976. //
  1977. // Synopsis:
  1978. //
  1979. //----------------------------------------------------------------------------
  1980. HRESULT
  1981. NWApiUserGetGroups(
  1982. NWCONN_HANDLE hConn,
  1983. LPWSTR szUserName,
  1984. LPBYTE *lppBuffer
  1985. )
  1986. {
  1987. DWORD dwNumSegment = 0;
  1988. HRESULT hr = S_OK;
  1989. DWORD i;
  1990. LP_RPLY_SGMT_LST lpTemp = NULL;
  1991. LP_RPLY_SGMT_LST lpReplySegment = NULL;
  1992. //
  1993. // Assert
  1994. //
  1995. ADsAssert(*lppBuffer == NULL);
  1996. //
  1997. // Get GROUP_MEMBERS.
  1998. //
  1999. hr = NWApiGetProperty(
  2000. szUserName,
  2001. NW_PROP_USER_GROUPS,
  2002. OT_USER,
  2003. hConn,
  2004. &lpReplySegment,
  2005. &dwNumSegment
  2006. );
  2007. BAIL_ON_FAILURE(hr);
  2008. //
  2009. // Pack returned linked list into buffer.
  2010. //
  2011. *lppBuffer = (LPBYTE) AllocADsMem(
  2012. dwNumSegment * REPLY_VALUE_SIZE
  2013. );
  2014. if (!(*lppBuffer)) {
  2015. RRETURN(E_OUTOFMEMORY);
  2016. }
  2017. lpTemp = lpReplySegment;
  2018. for (i = 0; i < dwNumSegment; i++) {
  2019. memcpy(
  2020. *lppBuffer + i * REPLY_VALUE_SIZE,
  2021. lpTemp->Segment,
  2022. REPLY_VALUE_SIZE
  2023. );
  2024. lpTemp = lpTemp->lpNext;
  2025. }
  2026. error:
  2027. //
  2028. // Clean up.
  2029. //
  2030. lpTemp = NULL;
  2031. if (lpReplySegment) {
  2032. DELETE_LIST(lpReplySegment);
  2033. }
  2034. RRETURN(hr);
  2035. }