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.

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