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.

2425 lines
53 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. ADsFreeString(NwUserInfo.lpszPassword);
  784. RRETURN(hr);
  785. }
  786. //----------------------------------------------------------------------------
  787. //
  788. // Function: NWApiFreeUserInfo
  789. //
  790. // Synopsis: This function is very provider specific.
  791. //
  792. //----------------------------------------------------------------------------
  793. HRESULT
  794. NWApiFreeUserInfo(
  795. PNW_USER_INFO pNwUserInfo
  796. )
  797. {
  798. HRESULT hr = S_OK;
  799. if (pNwUserInfo->lpszBinderyName) {
  800. ADsFreeString(pNwUserInfo->lpszBinderyName);
  801. pNwUserInfo->lpszBinderyName = NULL ;
  802. }
  803. if (pNwUserInfo->lpszUserName) {
  804. ADsFreeString(pNwUserInfo->lpszUserName);
  805. pNwUserInfo->lpszUserName = NULL;
  806. }
  807. if (pNwUserInfo->lpszPassword) {
  808. ADsFreeString(pNwUserInfo->lpszPassword);
  809. pNwUserInfo->lpszPassword = NULL;
  810. }
  811. if (pNwUserInfo->hConn) {
  812. hr = NWApiReleaseBinderyHandle(
  813. pNwUserInfo->hConn
  814. );
  815. BAIL_ON_FAILURE(hr);
  816. }
  817. error:
  818. RRETURN(hr);
  819. }
  820. //----------------------------------------------------------------------------
  821. //
  822. // Function: NWApiCreateUser
  823. //
  824. // Synopsis:
  825. //
  826. //----------------------------------------------------------------------------
  827. HRESULT
  828. NWApiCreateUser(
  829. PNW_USER_INFO pNwUserInfo
  830. )
  831. {
  832. HRESULT hr = S_OK;
  833. HRESULT hrTemp = S_OK;
  834. NTSTATUS Status = STATUS_SUCCESS;
  835. NWCCODE usRet = SUCCESSFUL;
  836. NWCONN_HANDLE hConn = NULL;
  837. NWOBJ_ID UserObjectID;
  838. UCHAR ChallengeKey[8];
  839. UCHAR NewKeyedPassword[17];
  840. UCHAR ValidationKey[8];
  841. WCHAR szTemp[MAX_PATH];
  842. //
  843. // "Create Bindery Object" - user object. This user object is going to be
  844. // static, with access equals to logged read, supervisor write.
  845. //
  846. hr = NWApiCreateBinderyObject(
  847. pNwUserInfo->hConn,
  848. pNwUserInfo->lpszUserName,
  849. OT_USER,
  850. BF_STATIC,
  851. BS_LOGGED_READ | BS_SUPER_WRITE
  852. );
  853. BAIL_ON_FAILURE(hr);
  854. //
  855. // Add user password.
  856. //
  857. hr = NWApiSetUserPassword(
  858. pNwUserInfo,
  859. &UserObjectID,
  860. NULL // no old passwd - this is a SET
  861. );
  862. BAIL_ON_FAILURE(hr);
  863. //
  864. // Create necessary bindery property to facilitate the addition of this user
  865. // to the group EVERYONE.
  866. //
  867. hr = NWApiCreateProperty(
  868. pNwUserInfo->hConn,
  869. pNwUserInfo->lpszUserName,
  870. OT_USER,
  871. "GROUPS_I'M_IN",
  872. BF_SET
  873. );
  874. BAIL_ON_FAILURE(hr);
  875. hr = NWApiCreateProperty(
  876. pNwUserInfo->hConn,
  877. pNwUserInfo->lpszUserName,
  878. OT_USER,
  879. "SECURITY_EQUALS",
  880. BF_SET
  881. );
  882. BAIL_ON_FAILURE(hr);
  883. //
  884. // Add this user to the group EVERYONE.
  885. // (okay if this fails, EVERYONE might not exist)
  886. //
  887. wcscpy(szTemp, L"EVERYONE");
  888. hrTemp = NWApiAddGroupMember(
  889. pNwUserInfo->hConn,
  890. szTemp,
  891. pNwUserInfo->lpszUserName
  892. );
  893. //
  894. // Create mail directory and login files.
  895. // (okay if this fails)
  896. //
  897. hrTemp = NWApiCreateMailDirectory(
  898. pNwUserInfo,
  899. UserObjectID
  900. );
  901. //
  902. // Create LOGIN_CONTROL & ACCOUNT_BALANCE property for the user. Values
  903. // from USER_DEFAULTS are used as default.
  904. //
  905. hr = NWApiSetLoginCtrlAndAcctBalance(
  906. pNwUserInfo
  907. );
  908. BAIL_ON_FAILURE(hr);
  909. error:
  910. RRETURN(hr);
  911. }
  912. //----------------------------------------------------------------------------
  913. //
  914. // Function: NWApiDeleteUser
  915. //
  916. // Synopsis:
  917. //
  918. //----------------------------------------------------------------------------
  919. HRESULT
  920. NWApiDeleteUser(
  921. POBJECTINFO pObjectInfo
  922. )
  923. {
  924. BOOL err = TRUE;
  925. DWORD dwErr = 0;
  926. HRESULT hr = S_OK;
  927. NWCONN_HANDLE hConn = NULL;
  928. NWOBJ_ID ObjectID;
  929. WCHAR szPath[MAX_PATH];
  930. //
  931. // Open a handle to the bindery.
  932. //
  933. hr = NWApiGetBinderyHandle(
  934. &hConn,
  935. pObjectInfo->ComponentArray[0]
  936. );
  937. BAIL_ON_FAILURE(hr);
  938. //
  939. // Get the user's ObjectID which is needed to compose the path name of LOGIN
  940. // and LOGIN.OS2.
  941. //
  942. hr = NWApiGetObjectID(
  943. hConn,
  944. pObjectInfo->ComponentArray[1],
  945. OT_USER,
  946. &ObjectID
  947. );
  948. BAIL_ON_FAILURE(hr);
  949. //
  950. // Delete SYS:MAIL\<JOBID>\LOGIN. If the file is not found, that's OK, as
  951. // long as it is not there.
  952. //
  953. wsprintf(
  954. szPath,
  955. L"\\\\%s\\SYS\\MAIL\\%X\\LOGIN",
  956. pObjectInfo->ComponentArray[0],
  957. dwSWAP(ObjectID)
  958. );
  959. err = DeleteFile(szPath);
  960. //
  961. // Remove any error checking for the cleanup of
  962. // files. If they do exist, and we do clean them up
  963. // great. But otherwise Win95 chokes on us.
  964. //
  965. //
  966. // Delete SYS:MAIL\<JOBID>\LOGIN.OS2. If the file is not found, that's OK,
  967. // as long as it is not there.
  968. //
  969. wsprintf(
  970. szPath,
  971. L"\\\\%s\\SYS\\MAIL\\%X\\LOGIN.OS2",
  972. pObjectInfo->ComponentArray[0],
  973. dwSWAP(ObjectID)
  974. );
  975. err = DeleteFile(szPath);
  976. //
  977. // Remove any error checking for the cleanup of
  978. // files. If they do exist, and we do clean them up
  979. // great. But otherwise Win95 chokes on us.
  980. //
  981. //
  982. // Delete SYS:MAIL\<JOBID>.
  983. //
  984. wsprintf(
  985. szPath,
  986. L"\\\\%s\\SYS\\MAIL\\%X",
  987. pObjectInfo->ComponentArray[0],
  988. dwSWAP(ObjectID)
  989. );
  990. err = RemoveDirectory(szPath);
  991. //
  992. // Remove any error checking for the cleanup of
  993. // files. If they do exist, and we do clean them up
  994. // great. But otherwise Win95 chokes on us.
  995. //
  996. //
  997. // Delete the user object.
  998. //
  999. hr = NWApiDeleteBinderyObject(
  1000. hConn,
  1001. pObjectInfo->ComponentArray[1],
  1002. OT_USER
  1003. );
  1004. BAIL_ON_FAILURE(hr);
  1005. error:
  1006. NWApiReleaseBinderyHandle(hConn);
  1007. RRETURN(hr);
  1008. }
  1009. //----------------------------------------------------------------------------
  1010. //
  1011. // Function: NWApiCreateBinderyObject
  1012. //
  1013. // Synopsis: This function create the specified object in the specified NetWare
  1014. // bindery. It returns S_OK if the object alread exist.
  1015. //
  1016. //----------------------------------------------------------------------------
  1017. HRESULT
  1018. NWApiCreateBinderyObject(
  1019. NWCONN_HANDLE hConn,
  1020. LPWSTR lpszObjectName,
  1021. NWOBJ_TYPE wObjType,
  1022. NWFLAGS ucObjectFlags,
  1023. NWFLAGS usObjSecurity
  1024. )
  1025. {
  1026. CHAR szAnsiObjectName[(OBJ_NAME_SIZE + 1)*2];
  1027. HRESULT hr = S_OK;
  1028. NWCCODE usRet = SUCCESSFUL;
  1029. //
  1030. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  1031. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1032. //
  1033. if (wcslen(lpszObjectName) > OBJ_NAME_SIZE) {
  1034. RRETURN(E_INVALIDARG);
  1035. }
  1036. UnicodeToAnsiString(
  1037. lpszObjectName,
  1038. szAnsiObjectName,
  1039. 0
  1040. );
  1041. //
  1042. // Create a Static object with LOGGED_READ & SUPERVISOR_WRITE.
  1043. //
  1044. usRet = NWCCreateObject(
  1045. hConn,
  1046. szAnsiObjectName,
  1047. wObjType,
  1048. BF_STATIC,
  1049. BS_LOGGED_READ | BS_SUPER_WRITE
  1050. );
  1051. //
  1052. // If an error occured, check if it is OBJECT_ALREADY_EXISTS. If it is,
  1053. // treat it as no error.
  1054. //
  1055. if (usRet) {
  1056. if (usRet == OBJECT_ALREADY_EXISTS) {
  1057. usRet = SUCCESSFUL;
  1058. }
  1059. }
  1060. //
  1061. // Return.
  1062. //
  1063. hr = HRESULT_FROM_NWCCODE(usRet);
  1064. RRETURN(hr);
  1065. }
  1066. //----------------------------------------------------------------------------
  1067. //
  1068. // Function: NWApiDeleteBinderyObject
  1069. //
  1070. // Synopsis:
  1071. //
  1072. //----------------------------------------------------------------------------
  1073. HRESULT
  1074. NWApiDeleteBinderyObject(
  1075. NWCONN_HANDLE hConn,
  1076. LPWSTR lpszObjectName,
  1077. NWOBJ_TYPE wObjType
  1078. )
  1079. {
  1080. CHAR szAnsiObjectName[(OBJ_NAME_SIZE + 1)*2];
  1081. HRESULT hr = S_OK;
  1082. NWCCODE usRet = SUCCESSFUL;
  1083. //
  1084. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  1085. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1086. //
  1087. if (wcslen(lpszObjectName) > OBJ_NAME_SIZE) {
  1088. RRETURN(E_INVALIDARG);
  1089. }
  1090. UnicodeToAnsiString(
  1091. lpszObjectName,
  1092. szAnsiObjectName,
  1093. 0
  1094. );
  1095. //
  1096. // Delete the object from the bindery.
  1097. //
  1098. usRet = NWCDeleteObject(
  1099. hConn,
  1100. szAnsiObjectName,
  1101. wObjType
  1102. );
  1103. //
  1104. // Return.
  1105. //
  1106. hr = HRESULT_FROM_NWCCODE(usRet);
  1107. RRETURN(hr);
  1108. }
  1109. #define NW_MAX_PASSWORD_LEN 256
  1110. //----------------------------------------------------------------------------
  1111. //
  1112. // Function: NWApiSetUserPassword
  1113. //
  1114. // Synopsis:
  1115. //
  1116. //----------------------------------------------------------------------------
  1117. HRESULT
  1118. NWApiSetUserPassword(
  1119. PNW_USER_INFO pNwUserInfo,
  1120. DWORD *pdwUserObjID,
  1121. LPWSTR pszOldPassword
  1122. )
  1123. {
  1124. CHAR szAnsiUserName[(OBJ_NAME_SIZE + 1)*2];
  1125. CHAR szAnsiPassword[(NW_MAX_PASSWORD_LEN + 1)*2];
  1126. CHAR szAnsiOldPassword[(NW_MAX_PASSWORD_LEN + 1)*2];
  1127. CHAR Buffer[128];
  1128. DWORD err = 0;
  1129. HRESULT hr = S_OK;
  1130. LC_STRUCTURE LoginCtrl;
  1131. NTSTATUS NtStatus;
  1132. UCHAR ChallengeKey[8];
  1133. UCHAR ucMoreFlag;
  1134. UCHAR ucPropFlag;
  1135. WCHAR szOldPasswordCopy[NW_MAX_PASSWORD_LEN + 1];
  1136. if ( !pNwUserInfo ||
  1137. !(pNwUserInfo->lpszUserName) ||
  1138. !(pNwUserInfo->lpszPassword) ) {
  1139. hr = E_INVALIDARG ;
  1140. BAIL_ON_FAILURE(hr);
  1141. }
  1142. if ( (wcslen(pNwUserInfo->lpszUserName) > OBJ_NAME_SIZE) ||
  1143. (wcslen(pNwUserInfo->lpszPassword) > NW_MAX_PASSWORD_LEN) ||
  1144. ( pszOldPassword && (wcslen(pszOldPassword) > NW_MAX_PASSWORD_LEN)) ) {
  1145. hr = E_INVALIDARG;
  1146. BAIL_ON_FAILURE(hr);
  1147. }
  1148. //
  1149. // Convert UNICODE into ANSI representation required by NW APIs. "0" is
  1150. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1151. //
  1152. err = UnicodeToAnsiString(
  1153. pNwUserInfo->lpszUserName,
  1154. szAnsiUserName,
  1155. 0
  1156. );
  1157. if (!err) {
  1158. hr = E_FAIL;
  1159. BAIL_ON_FAILURE(hr);
  1160. }
  1161. _wcsupr(pNwUserInfo->lpszPassword) ;
  1162. err = UnicodeToAnsiString(
  1163. pNwUserInfo->lpszPassword,
  1164. szAnsiPassword,
  1165. 0
  1166. );
  1167. if (!err) {
  1168. hr = E_FAIL;
  1169. BAIL_ON_FAILURE(hr);
  1170. }
  1171. if (pszOldPassword) {
  1172. wcscpy(szOldPasswordCopy, pszOldPassword);
  1173. _wcsupr(szOldPasswordCopy) ;
  1174. err = UnicodeToAnsiString(
  1175. szOldPasswordCopy,
  1176. szAnsiOldPassword,
  1177. 0
  1178. );
  1179. if (!err) {
  1180. hr = E_FAIL;
  1181. BAIL_ON_FAILURE(hr);
  1182. }
  1183. }
  1184. else {
  1185. szAnsiOldPassword[0] = 0 ;
  1186. }
  1187. //
  1188. // Get challenge key.
  1189. //
  1190. err = NWApiMapNtStatusToDosError(
  1191. NWPGetChallengeKey(
  1192. pNwUserInfo->hConn,
  1193. ChallengeKey
  1194. ));
  1195. if (!err) {
  1196. //
  1197. // For NetWare 4.x servers, this has to be done after the
  1198. // NWPGetChallengeKey so that the object id returned can be used to
  1199. // encrypt the password. 4.x bindery emulation might return different
  1200. // object ids for some users depending on whether the NWPGetChallengeKey
  1201. // is called beforehand.
  1202. //
  1203. err = NWApiMapNtStatusToDosError(
  1204. NWPGetObjectID(
  1205. pNwUserInfo->hConn,
  1206. szAnsiUserName,
  1207. OT_USER,
  1208. pdwUserObjID
  1209. ));
  1210. }
  1211. if (!err) {
  1212. //
  1213. // The old password and object ID make up the 17-byte Vold. This is used
  1214. // later to form the 17-byte Vc for changing password on the server.
  1215. //
  1216. UCHAR ValidationKey[8];
  1217. UCHAR NewKeyedPassword[17];
  1218. EncryptChangePassword(
  1219. (PUCHAR) szAnsiOldPassword,
  1220. (PUCHAR) szAnsiPassword,
  1221. *pdwUserObjID,
  1222. ChallengeKey,
  1223. ValidationKey,
  1224. NewKeyedPassword
  1225. );
  1226. err = NWApiMapNtStatusToDosError(
  1227. NWPChangeObjectPasswordEncrypted(
  1228. pNwUserInfo->hConn,
  1229. szAnsiUserName,
  1230. OT_USER,
  1231. ValidationKey,
  1232. NewKeyedPassword
  1233. ));
  1234. }
  1235. //
  1236. // Return.
  1237. //
  1238. hr = HRESULT_FROM_WIN32(err);
  1239. error:
  1240. RRETURN(hr);
  1241. }
  1242. //----------------------------------------------------------------------------
  1243. //
  1244. // Function: NWApiCreateMailDirectory
  1245. //
  1246. // Synopsis:
  1247. //
  1248. //----------------------------------------------------------------------------
  1249. HRESULT
  1250. NWApiCreateMailDirectory(
  1251. PNW_USER_INFO pNwUserInfo,
  1252. NWOBJ_ID UserObjID
  1253. )
  1254. {
  1255. BYTE szPath[(MAX_PATH + 1) * sizeof(WCHAR)];
  1256. CHAR szUserObjID[255];
  1257. DWORD err = 0;
  1258. HRESULT hr = S_OK;
  1259. //
  1260. // Make path.
  1261. //
  1262. _ltoa(
  1263. dwSWAP(UserObjID),
  1264. szUserObjID,
  1265. 16
  1266. );
  1267. strcpy((char *) szPath, "SYS:\\MAIL\\");
  1268. strcat((char *) szPath, szUserObjID);
  1269. //
  1270. // Create a directory with Maximum rights mask.
  1271. //
  1272. err = NWApiMapNtStatusToDosError(
  1273. NWPCreateDirectory(
  1274. pNwUserInfo->hConn,
  1275. 0,
  1276. (char *) szPath,
  1277. 0xFF // From SysCon --- Max. access rights for directory
  1278. )); // = Full Access
  1279. if ( !err ) {
  1280. //
  1281. // Add a trustee with all rights except PARENTAL right.
  1282. //
  1283. err = NWApiMapNtStatusToDosError(
  1284. NWPAddTrustee(
  1285. pNwUserInfo->hConn,
  1286. 0,
  1287. (char *) szPath,
  1288. UserObjID,
  1289. 0xDF // From SysCon --- Trustee has all rights
  1290. )); // EXCEPT parental rights (right to create/
  1291. // delete subdirs, make others trustees)
  1292. //
  1293. // Create a Login file.
  1294. //
  1295. if ( !err ) {
  1296. HANDLE hFile;
  1297. wsprintfW(
  1298. (LPWSTR) szPath,
  1299. L"\\\\%ws\\SYS\\MAIL\\%X\\LOGIN",
  1300. pNwUserInfo->lpszBinderyName,
  1301. dwSWAP(UserObjID)
  1302. );
  1303. hFile = CreateFile(
  1304. (LPWSTR) szPath,
  1305. GENERIC_WRITE,
  1306. 0,
  1307. NULL,
  1308. OPEN_ALWAYS,
  1309. FILE_ATTRIBUTE_NORMAL,
  1310. 0
  1311. );
  1312. if ( hFile == INVALID_HANDLE_VALUE ) {
  1313. err = GetLastError();
  1314. }
  1315. if ( !err )
  1316. CloseHandle( hFile );
  1317. //
  1318. // Create a Login.os2 file.
  1319. //
  1320. wsprintfW(
  1321. (LPWSTR) szPath,
  1322. L"\\\\%ws\\SYS\\MAIL\\%X\\LOGIN.OS2",
  1323. pNwUserInfo->lpszBinderyName,
  1324. dwSWAP(UserObjID)
  1325. );
  1326. hFile = CreateFile(
  1327. (LPWSTR) szPath,
  1328. GENERIC_WRITE,
  1329. 0,
  1330. NULL,
  1331. OPEN_ALWAYS,
  1332. FILE_ATTRIBUTE_NORMAL,
  1333. 0
  1334. );
  1335. if ( hFile == INVALID_HANDLE_VALUE ) {
  1336. err = GetLastError();
  1337. }
  1338. if ( !err )
  1339. CloseHandle( hFile );
  1340. }
  1341. }
  1342. // err == 255 == "FAILURE"
  1343. // might be used to indicate directory already exists,
  1344. // but also used to signal generic failure
  1345. hr = HRESULT_FROM_WIN32(err);
  1346. RRETURN(hr);
  1347. }
  1348. //----------------------------------------------------------------------------
  1349. //
  1350. // Function: NWApiSetLoginCtrlAndAcctBalance
  1351. //
  1352. // Synopsis:
  1353. //
  1354. //----------------------------------------------------------------------------
  1355. HRESULT
  1356. NWApiSetLoginCtrlAndAcctBalance(
  1357. PNW_USER_INFO pNwUserInfo
  1358. )
  1359. {
  1360. ACCT_BALANCE AccountBalance;
  1361. DWORD dwNumSegment;
  1362. HRESULT hr = S_OK;
  1363. int i = 0;
  1364. LC_STRUCTURE LoginCtrl;
  1365. LP_RPLY_SGMT_LST lpReplySegment = NULL;
  1366. LP_RPLY_SGMT_LST lpTemp = NULL;
  1367. USER_DEFAULT UserDefault;
  1368. WCHAR szTemp[MAX_PATH];
  1369. //
  1370. // Get Supervisor's USER_DEFAULTS.
  1371. //
  1372. wcscpy(szTemp, NW_PROP_SUPERVISORW);
  1373. hr = NWApiGetProperty(
  1374. szTemp,
  1375. NW_PROP_USER_DEFAULTS,
  1376. OT_USER,
  1377. pNwUserInfo->hConn,
  1378. &lpReplySegment,
  1379. &dwNumSegment
  1380. );
  1381. if (SUCCEEDED(hr)) {
  1382. UserDefault = *((LPUSER_DEFAULT) lpReplySegment->Segment);
  1383. //
  1384. // Put default values into LoginCtrl.
  1385. //
  1386. LoginCtrl.byAccountExpires[0] = UserDefault.byAccountExpiresYear;
  1387. LoginCtrl.byAccountExpires[1] = UserDefault.byAccountExpiresMonth;
  1388. LoginCtrl.byAccountExpires[2] = UserDefault.byAccountExpiresDay;
  1389. LoginCtrl.byAccountDisabled = 0;
  1390. LoginCtrl.byPasswordExpires[0] = 85;
  1391. LoginCtrl.byPasswordExpires[1] = 01;
  1392. LoginCtrl.byPasswordExpires[2] = 01;
  1393. LoginCtrl.byGraceLogins = UserDefault.byGraceLoginReset;
  1394. LoginCtrl.wPasswordInterval = UserDefault.wPasswordInterval;
  1395. LoginCtrl.byGraceLoginReset = UserDefault.byGraceLoginReset;
  1396. LoginCtrl.byMinPasswordLength = UserDefault.byMinPasswordLength;
  1397. LoginCtrl.wMaxConnections = UserDefault.wMaxConnections;
  1398. LoginCtrl.byRestrictions = UserDefault.byRestrictions;
  1399. LoginCtrl.byUnused = 0;
  1400. LoginCtrl.lMaxDiskBlocks = UserDefault.lMaxDiskBlocks;
  1401. LoginCtrl.wBadLogins = 0;
  1402. LoginCtrl.lNextResetTime = 0;
  1403. for (i = 0; i < 42; i++) {
  1404. LoginCtrl.byLoginTimes[i] = UserDefault.byLoginTimes[i];
  1405. }
  1406. for (i = 0; i < 6; i++) {
  1407. LoginCtrl.byLastLogin[i] = 0;
  1408. }
  1409. for (i = 0; i < 12; i++) {
  1410. LoginCtrl.byBadLoginAddr[i] = 0;
  1411. }
  1412. LoginCtrl.byGraceLogins = LoginCtrl.byGraceLoginReset;
  1413. //
  1414. // Put default values into AccountBalance.
  1415. //
  1416. AccountBalance.lBalance = UserDefault.lBalance;
  1417. AccountBalance.lCreditLimit = UserDefault.lCreditLimit;
  1418. //
  1419. // Write LOGIN_CONTROL property.
  1420. //
  1421. hr = NWApiWriteProperty(
  1422. pNwUserInfo->hConn,
  1423. pNwUserInfo->lpszUserName,
  1424. OT_USER,
  1425. NW_PROP_LOGIN_CONTROL,
  1426. (LPBYTE) &LoginCtrl
  1427. );
  1428. BAIL_ON_FAILURE(hr);
  1429. //
  1430. // Write ACCOUNT_BALANCE property.
  1431. //
  1432. hr = NWApiWriteProperty(
  1433. pNwUserInfo->hConn,
  1434. pNwUserInfo->lpszUserName,
  1435. OT_USER,
  1436. NW_PROP_ACCOUNT_BALANCE,
  1437. (LPBYTE) &AccountBalance
  1438. );
  1439. BAIL_ON_FAILURE(hr);
  1440. }
  1441. //
  1442. // SUPERVISOR may not exist, or may not have USER_DEFAULTS.
  1443. // This is okay.
  1444. //
  1445. hr = S_OK;
  1446. error:
  1447. if (lpReplySegment) {
  1448. DELETE_LIST(lpReplySegment);
  1449. }
  1450. RRETURN(hr);
  1451. }
  1452. //----------------------------------------------------------------------------
  1453. //
  1454. // Function: NWApiCreateGroup
  1455. //
  1456. // Synopsis:
  1457. //
  1458. //----------------------------------------------------------------------------
  1459. HRESULT
  1460. NWApiCreateGroup(
  1461. POBJECTINFO pObjectInfo
  1462. )
  1463. {
  1464. HRESULT hr = S_OK;
  1465. NWCONN_HANDLE hConn = NULL;
  1466. //
  1467. // Open a handle to the bindery.
  1468. //
  1469. hr = NWApiGetBinderyHandle(
  1470. &hConn,
  1471. pObjectInfo->ComponentArray[0]
  1472. );
  1473. BAIL_ON_FAILURE(hr);
  1474. //
  1475. // Create a group bindery object.
  1476. //
  1477. hr = NWApiCreateBinderyObject(
  1478. hConn,
  1479. pObjectInfo->ComponentArray[1],
  1480. OT_USER_GROUP,
  1481. BF_STATIC,
  1482. BS_LOGGED_READ | BS_SUPER_WRITE
  1483. );
  1484. BAIL_ON_FAILURE(hr);
  1485. //
  1486. // Create GROUP_MEMBERS property.
  1487. //
  1488. hr = NWApiCreateProperty(
  1489. hConn,
  1490. pObjectInfo->ComponentArray[1],
  1491. OT_USER_GROUP,
  1492. NW_PROP_GROUP_MEMBERS,
  1493. BF_SET
  1494. );
  1495. BAIL_ON_FAILURE(hr);
  1496. error:
  1497. NWApiReleaseBinderyHandle(hConn);
  1498. RRETURN(hr);
  1499. }
  1500. //----------------------------------------------------------------------------
  1501. //
  1502. // Function: NWApiDeleteGroup
  1503. //
  1504. // Synopsis:
  1505. //
  1506. //----------------------------------------------------------------------------
  1507. HRESULT
  1508. NWApiDeleteGroup(
  1509. POBJECTINFO pObjectInfo
  1510. )
  1511. {
  1512. HRESULT hr = S_OK;
  1513. NWCONN_HANDLE hConn = NULL;
  1514. //
  1515. // Open a handle to the bindery.
  1516. //
  1517. hr = NWApiGetBinderyHandle(
  1518. &hConn,
  1519. pObjectInfo->ComponentArray[0]
  1520. );
  1521. BAIL_ON_FAILURE(hr);
  1522. //
  1523. // Delete the group object.
  1524. //
  1525. hr = NWApiDeleteBinderyObject(
  1526. hConn,
  1527. pObjectInfo->ComponentArray[1],
  1528. OT_USER_GROUP
  1529. );
  1530. BAIL_ON_FAILURE(hr);
  1531. error:
  1532. NWApiReleaseBinderyHandle(hConn);
  1533. RRETURN(hr);
  1534. }
  1535. //----------------------------------------------------------------------------
  1536. //
  1537. // Function: NWApiCreatePrinter
  1538. //
  1539. // Synopsis:
  1540. //
  1541. //----------------------------------------------------------------------------
  1542. HRESULT
  1543. NWApiCreatePrinter(
  1544. POBJECTINFO pObjectInfo
  1545. )
  1546. {
  1547. CHAR szQueueName[(OBJ_NAME_SIZE + 1)*2];
  1548. HRESULT hr = S_OK;
  1549. NWCCODE usRet = SUCCESSFUL;
  1550. NWCONN_HANDLE hConn = NULL;
  1551. WCHAR szTemp[MAX_PATH];
  1552. //
  1553. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  1554. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1555. //
  1556. if (wcslen(pObjectInfo->ComponentArray[1]) > OBJ_NAME_SIZE) {
  1557. RRETURN(E_INVALIDARG);
  1558. }
  1559. UnicodeToAnsiString(
  1560. pObjectInfo->ComponentArray[1],
  1561. szQueueName,
  1562. 0
  1563. );
  1564. //
  1565. // Open a handle to the bindery.
  1566. //
  1567. hr = NWApiGetBinderyHandle(
  1568. &hConn,
  1569. pObjectInfo->ComponentArray[0]
  1570. );
  1571. BAIL_ON_FAILURE(hr);
  1572. //
  1573. // Create a print queue object.
  1574. //
  1575. hr = NWApiCreatePrintQueue(
  1576. hConn,
  1577. pObjectInfo->ComponentArray[1]
  1578. );
  1579. BAIL_ON_FAILURE(hr);
  1580. //
  1581. // Change property security.
  1582. //
  1583. usRet = NWCChangePropertySecurity(
  1584. hConn,
  1585. szQueueName,
  1586. OT_PRINT_QUEUE,
  1587. NW_PROP_Q_OPERATORS,
  1588. BS_LOGGED_READ | BS_SUPER_WRITE
  1589. );
  1590. hr = HRESULT_FROM_NWCCODE(usRet);
  1591. BAIL_ON_FAILURE(hr);
  1592. //
  1593. // Add SUPERVISOR to Q_OPERATORS.
  1594. // (okay if this fails, maybe SUPERVISOR doesn't exist)
  1595. //
  1596. usRet = NWCAddObjectToSet(
  1597. hConn,
  1598. szQueueName,
  1599. OT_PRINT_QUEUE,
  1600. NW_PROP_Q_OPERATORS,
  1601. NW_PROP_SUPERVISOR,
  1602. OT_USER
  1603. );
  1604. //
  1605. // Add EVERYONE to Q_USERS.
  1606. // (okay if this fails, maybe EVERYONE doesn't exist)
  1607. //
  1608. usRet = NWCAddObjectToSet(
  1609. hConn,
  1610. szQueueName,
  1611. OT_PRINT_QUEUE,
  1612. NW_PROP_Q_USERS,
  1613. NW_PROP_EVERYONE,
  1614. OT_USER_GROUP
  1615. );
  1616. //
  1617. // Return.
  1618. //
  1619. error:
  1620. NWApiReleaseBinderyHandle(hConn);
  1621. RRETURN(hr);
  1622. }
  1623. //----------------------------------------------------------------------------
  1624. //
  1625. // Function: NWApiDeleteGroup
  1626. //
  1627. // Synopsis:
  1628. //
  1629. //----------------------------------------------------------------------------
  1630. HRESULT
  1631. NWApiDeletePrinter(
  1632. POBJECTINFO pObjectInfo
  1633. )
  1634. {
  1635. HRESULT hr = S_OK;
  1636. NWCONN_HANDLE hConn = NULL;
  1637. NWOBJ_ID dwQueueID = 0;
  1638. //
  1639. // Open a handle to the bindery.
  1640. //
  1641. hr = NWApiGetBinderyHandle(
  1642. &hConn,
  1643. pObjectInfo->ComponentArray[0]
  1644. );
  1645. BAIL_ON_FAILURE(hr);
  1646. //
  1647. // Get Queue ID.
  1648. //
  1649. hr = NWApiDestroyPrintQueue(
  1650. hConn,
  1651. pObjectInfo->ComponentArray[1]
  1652. );
  1653. BAIL_ON_FAILURE(hr);
  1654. error:
  1655. NWApiReleaseBinderyHandle(hConn);
  1656. RRETURN(hr);
  1657. }
  1658. //----------------------------------------------------------------------------
  1659. //
  1660. // Function: NWApiCreatePrintQueue
  1661. //
  1662. // Synopsis:
  1663. //
  1664. //----------------------------------------------------------------------------
  1665. HRESULT
  1666. NWApiCreatePrintQueue(
  1667. NWCONN_HANDLE hConn,
  1668. LPWSTR lpszQueueName
  1669. )
  1670. {
  1671. CHAR szQueueName[(OBJ_NAME_SIZE + 1)*2];
  1672. DWORD dwQueueID = 0;
  1673. HRESULT hr = S_OK;
  1674. NWCCODE usRet = SUCCESSFUL;
  1675. //
  1676. // Convert BSTR into an ANSI representation required by NWC APIs. "0" is
  1677. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1678. //
  1679. if (wcslen(lpszQueueName) > OBJ_NAME_SIZE) {
  1680. RRETURN(E_INVALIDARG);
  1681. }
  1682. UnicodeToAnsiString(
  1683. lpszQueueName,
  1684. szQueueName,
  1685. 0
  1686. );
  1687. //
  1688. // Create a print queue object.
  1689. //
  1690. usRet = NWCCreateQueue(
  1691. hConn,
  1692. NULL,
  1693. szQueueName,
  1694. OT_PRINT_QUEUE,
  1695. NW_PRINTER_PATH,
  1696. &dwQueueID
  1697. );
  1698. hr = HRESULT_FROM_NWCCODE(usRet);
  1699. //
  1700. // Return.
  1701. //
  1702. RRETURN(hr);
  1703. }
  1704. //----------------------------------------------------------------------------
  1705. //
  1706. // Function: NWApiDestroyPrintQueue
  1707. //
  1708. // Synopsis:
  1709. //
  1710. //----------------------------------------------------------------------------
  1711. HRESULT
  1712. NWApiDestroyPrintQueue(
  1713. NWCONN_HANDLE hConn,
  1714. LPWSTR lpszQueueName
  1715. )
  1716. {
  1717. DWORD dwQueueID = 0;
  1718. HRESULT hr = S_OK;
  1719. NWCCODE usRet = SUCCESSFUL;
  1720. //
  1721. // Get Queue ID.
  1722. //
  1723. hr = NWApiGetObjectID(
  1724. hConn,
  1725. lpszQueueName,
  1726. OT_PRINT_QUEUE,
  1727. &dwQueueID
  1728. );
  1729. BAIL_ON_FAILURE(hr);
  1730. //
  1731. // Destroy print queue.
  1732. //
  1733. usRet = NWCDestroyQueue(
  1734. hConn,
  1735. dwSWAP(dwQueueID)
  1736. );
  1737. hr = HRESULT_FROM_NWCCODE(usRet);
  1738. //
  1739. // Return.
  1740. //
  1741. error:
  1742. RRETURN(hr);
  1743. }
  1744. //----------------------------------------------------------------------------
  1745. //
  1746. // Function: NWApiMapNtStatusToDosError
  1747. //
  1748. // Synopsis: This function maps the ntstatus that was returned from the NetWare
  1749. // redirector to window errors. Similar to RtlNtStatusToDosError
  1750. // except that the special handling is done to ntstatus with netware
  1751. // facility codes.
  1752. //
  1753. // Argument: NtStatus - The ntstatus returned from NetWare rdr
  1754. //
  1755. // Return Value: WinError
  1756. //
  1757. //----------------------------------------------------------------------------
  1758. DWORD
  1759. NWApiMapNtStatusToDosError(
  1760. IN NTSTATUS NtStatus
  1761. )
  1762. {
  1763. if ( (HIWORD( NtStatus) & FACILITY_NWRDR ) == FACILITY_NWRDR )
  1764. {
  1765. if ( NtStatus == NWRDR_PASSWORD_HAS_EXPIRED )
  1766. return ERROR_PASSWORD_EXPIRED;
  1767. else
  1768. return NETWARE_GENERAL_ERROR;
  1769. }
  1770. else if ( HIWORD( NtStatus) == 0xC001 )
  1771. {
  1772. return LOWORD( NtStatus ) + NETWARE_ERROR_BASE;
  1773. }
  1774. return RtlNtStatusToDosError( NtStatus );
  1775. }
  1776. //----------------------------------------------------------------------------
  1777. //
  1778. // Function: NWApiConvertToAddressFormat
  1779. //
  1780. // Synopsis: Convert an IPX address obtain from NWApiGetProperty into the
  1781. // format specified in spec.
  1782. //
  1783. //----------------------------------------------------------------------------
  1784. HRESULT
  1785. NWApiConvertToAddressFormat(
  1786. LP_RPLY_SGMT_LST lpReplySegment,
  1787. LPWSTR *lppszAddresses
  1788. )
  1789. {
  1790. int i = 0;
  1791. LPBYTE lpBuffer = NULL;
  1792. LPWSTR lpszTemp = NULL;
  1793. WORD wSegment[NET_ADDRESS_WORD_SIZE];
  1794. //
  1795. // Put values from szReply into the wSegment array
  1796. //
  1797. lpBuffer = (LPBYTE) lpReplySegment->Segment;
  1798. for (i = 0; i < NET_ADDRESS_WORD_SIZE; i++) {
  1799. wSegment[i] = NWApiReverseWORD(*((LPWORD)lpBuffer + i));
  1800. }
  1801. //
  1802. // Put address together in the format described in spec.
  1803. //
  1804. lpszTemp = (LPWSTR) AllocADsMem((NET_ADDRESS_NUM_CHAR+1)*sizeof(WCHAR));
  1805. if (!lpszTemp) {
  1806. RRETURN(E_OUTOFMEMORY);
  1807. }
  1808. wsprintf(
  1809. lpszTemp,
  1810. L"%s:%04X%04X.%04X%04X%04X.%04X",
  1811. bstrAddressTypeString,
  1812. wSegment[0],
  1813. wSegment[1],
  1814. wSegment[2],
  1815. wSegment[3],
  1816. wSegment[4],
  1817. wSegment[5]
  1818. );
  1819. //
  1820. // Return.
  1821. //
  1822. *lppszAddresses = lpszTemp;
  1823. RRETURN(S_OK);
  1824. }
  1825. //----------------------------------------------------------------------------
  1826. //
  1827. // Function: NWApiMakeVariantTime
  1828. //
  1829. // Synopsis: This function creates a double precision variant time.
  1830. //
  1831. //----------------------------------------------------------------------------
  1832. HRESULT
  1833. NWApiMakeVariantTime(
  1834. DOUBLE * pdTime,
  1835. WORD wDay, // Day = 1..31
  1836. WORD wMonth, // Month = 1..12
  1837. WORD wYear, // Year = (19XX or 20XX) - 1980, ie. 2019 -> 39
  1838. WORD wSecond, // Second = 0..30, Second divided by 2
  1839. WORD wMinute, // Minute = 0..59
  1840. WORD wHour // Hour = 0..23
  1841. )
  1842. {
  1843. BOOL fBool = TRUE;
  1844. DOUBLE vTime = 0;
  1845. WORD wDOSDate = 0;
  1846. WORD wDOSTime = 0;
  1847. //
  1848. // Fix up parameters.
  1849. // If wDay and wMonth are 0, turn them into one.
  1850. //
  1851. if (wDay == 0) {
  1852. wDay++;
  1853. }
  1854. if (wMonth == 0) {
  1855. wMonth++;
  1856. }
  1857. //
  1858. // Shift data to correct bit as required by the DOS date & time format.
  1859. //
  1860. wMonth = wMonth << 5;
  1861. wYear = wYear << 9;
  1862. wMinute = wMinute << 5;
  1863. wHour = wHour << 11;
  1864. //
  1865. // Put them in DOS format.
  1866. //
  1867. wDOSDate = wYear | wMonth | wDay;
  1868. wDOSTime = wHour | wMinute | wSecond;
  1869. //
  1870. // Convert into VariantTime.
  1871. //
  1872. fBool = DosDateTimeToVariantTime(
  1873. wDOSDate,
  1874. wDOSTime,
  1875. &vTime
  1876. );
  1877. //
  1878. // Return.
  1879. //
  1880. if (fBool == TRUE) {
  1881. *pdTime = vTime;
  1882. RRETURN(S_OK);
  1883. }
  1884. else {
  1885. RRETURN(E_FAIL);
  1886. }
  1887. }
  1888. //----------------------------------------------------------------------------
  1889. //
  1890. // Function: NWApiBreakVariantTime
  1891. //
  1892. // Synopsis: This function interprets a double precision variant time and
  1893. // returns the day, month and year individually.
  1894. //
  1895. //----------------------------------------------------------------------------
  1896. HRESULT
  1897. NWApiBreakVariantTime(
  1898. DOUBLE daDate,
  1899. PWORD pwDay,
  1900. PWORD pwMonth,
  1901. PWORD pwYear
  1902. )
  1903. {
  1904. BOOL fBool;
  1905. DOUBLE vTime;
  1906. WORD wDOSDate = 0;
  1907. WORD wDOSTime = 0;
  1908. WORD wDay = 0;
  1909. WORD wMonth = 0;
  1910. WORD wYear = 0;
  1911. //
  1912. // Convert variant time into DOS format.
  1913. //
  1914. fBool = VariantTimeToDosDateTime(
  1915. daDate,
  1916. &wDOSDate,
  1917. &wDOSTime
  1918. );
  1919. if (fBool == FALSE) {
  1920. goto error;
  1921. }
  1922. //
  1923. // Year: bits 9-15, add 80 to wYear because 80 was subtracted from it to
  1924. // call VariantTimeToDosDateTime.
  1925. //
  1926. wYear = wDOSDate >> 9;
  1927. wYear += 80;
  1928. //
  1929. // Month: bits 5-8.
  1930. //
  1931. wMonth = (wDOSDate >> 5) - (wYear << 4);
  1932. //
  1933. // Day: bits 0-4.
  1934. //
  1935. wDay = wDOSDate - (wMonth << 5) - (wYear << 9);
  1936. //
  1937. // Return.
  1938. //
  1939. *pwDay = wDay;
  1940. *pwMonth = wMonth;
  1941. *pwYear = wYear;
  1942. RRETURN(S_OK);
  1943. error:
  1944. RRETURN(E_FAIL);
  1945. }
  1946. //----------------------------------------------------------------------------
  1947. //
  1948. // Function: NWApiReverseWORD
  1949. //
  1950. // Synopsis: This function reverse a WORD.
  1951. //
  1952. //----------------------------------------------------------------------------
  1953. WORD
  1954. NWApiReverseWORD(
  1955. WORD wWORD
  1956. )
  1957. {
  1958. LPBYTE lpbTemp = (LPBYTE) &wWORD;
  1959. BYTE bTemp;
  1960. bTemp = *lpbTemp;
  1961. *lpbTemp = *(lpbTemp + 1);
  1962. *(lpbTemp + 1) = bTemp;
  1963. return(*((LPWORD) lpbTemp));
  1964. }
  1965. //----------------------------------------------------------------------------
  1966. //
  1967. // Function: NWApiUserGetGroups
  1968. //
  1969. // Synopsis:
  1970. //
  1971. //----------------------------------------------------------------------------
  1972. HRESULT
  1973. NWApiUserGetGroups(
  1974. NWCONN_HANDLE hConn,
  1975. LPWSTR szUserName,
  1976. LPBYTE *lppBuffer
  1977. )
  1978. {
  1979. DWORD dwNumSegment = 0;
  1980. HRESULT hr = S_OK;
  1981. DWORD i;
  1982. LP_RPLY_SGMT_LST lpTemp = NULL;
  1983. LP_RPLY_SGMT_LST lpReplySegment = NULL;
  1984. //
  1985. // Assert
  1986. //
  1987. ADsAssert(*lppBuffer == NULL);
  1988. //
  1989. // Get GROUP_MEMBERS.
  1990. //
  1991. hr = NWApiGetProperty(
  1992. szUserName,
  1993. NW_PROP_USER_GROUPS,
  1994. OT_USER,
  1995. hConn,
  1996. &lpReplySegment,
  1997. &dwNumSegment
  1998. );
  1999. BAIL_ON_FAILURE(hr);
  2000. //
  2001. // Pack returned linked list into buffer.
  2002. //
  2003. *lppBuffer = (LPBYTE) AllocADsMem(
  2004. dwNumSegment * REPLY_VALUE_SIZE
  2005. );
  2006. if (!(*lppBuffer)) {
  2007. RRETURN(E_OUTOFMEMORY);
  2008. }
  2009. lpTemp = lpReplySegment;
  2010. for (i = 0; i < dwNumSegment; i++) {
  2011. memcpy(
  2012. *lppBuffer + i * REPLY_VALUE_SIZE,
  2013. lpTemp->Segment,
  2014. REPLY_VALUE_SIZE
  2015. );
  2016. lpTemp = lpTemp->lpNext;
  2017. }
  2018. error:
  2019. //
  2020. // Clean up.
  2021. //
  2022. lpTemp = NULL;
  2023. if (lpReplySegment) {
  2024. DELETE_LIST(lpReplySegment);
  2025. }
  2026. RRETURN(hr);
  2027. }