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.

957 lines
20 KiB

  1. #include "nwcompat.hxx"
  2. #pragma hdrstop
  3. //----------------------------------------------------------------------------
  4. //
  5. // Function: NWApiGetBinderyHandle
  6. //
  7. // Synopsis:
  8. //
  9. //----------------------------------------------------------------------------
  10. HRESULT
  11. NWApiGetBinderyHandle(
  12. NWCONN_HANDLE *phConnReturned,
  13. BSTR bstrBinderyName,
  14. CCredentials &Credentials
  15. )
  16. {
  17. CHAR szBinderyName[OBJ_NAME_SIZE + 1];
  18. NWLOCAL_SCOPE ScopeFlag = 0;
  19. NWCONN_HANDLE hConn = NULL;
  20. NWCCODE ccode = SUCCESSFUL;
  21. HRESULT hr = S_OK;
  22. PNWC_CONTEXT pNWCContext = NULL;
  23. LPWSTR pszUserName = NULL, pszPassword = NULL;
  24. BOOL fLoggedIn = FALSE;
  25. //
  26. // Try the cache for the passed in credentials.
  27. //
  28. ENTER_BIND_CRITSECT() ;
  29. if (pNWCContext = BindCacheLookup(bstrBinderyName, Credentials)) {
  30. *phConnReturned = pNWCContext->hConn;
  31. LEAVE_BIND_CRITSECT() ;
  32. return S_OK;
  33. }
  34. //
  35. // Entry not found in the cache, need to allocate a new one.
  36. //
  37. hr = BindCacheAllocEntry(&pNWCContext);
  38. if (FAILED(hr)) {
  39. LEAVE_BIND_CRITSECT() ;
  40. RRETURN(hr);
  41. }
  42. UnicodeToAnsiString(
  43. bstrBinderyName,
  44. szBinderyName,
  45. 0
  46. );
  47. hr = Credentials.GetUserName(&pszUserName);
  48. BAIL_ON_FAILURE(hr);
  49. hr = Credentials.GetPassword(&pszPassword);
  50. BAIL_ON_FAILURE(hr);
  51. if (pszUserName)
  52. {
  53. hr = NWApiCheckUserLoggedInToServer(bstrBinderyName, pszUserName);
  54. BAIL_ON_FAILURE(hr);
  55. if (hr == S_FALSE)
  56. {
  57. // Log in the user
  58. NETRESOURCE netResource;
  59. DWORD dwStatus;
  60. netResource.dwType = RESOURCETYPE_ANY;
  61. netResource.lpLocalName = NULL;
  62. netResource.lpRemoteName = (PWSTR) bstrBinderyName;
  63. netResource.lpProvider = NULL;
  64. dwStatus = WNetAddConnection2(
  65. &netResource,
  66. pszPassword ? pszPassword : L"",
  67. pszUserName,
  68. 0 // don't make a persistent connection
  69. );
  70. hr = HRESULT_FROM_WIN32(dwStatus);
  71. BAIL_ON_FAILURE(hr);
  72. fLoggedIn = TRUE;
  73. }
  74. }
  75. ccode = NWCCOpenConnByName(
  76. 0,
  77. szBinderyName,
  78. NWCC_NAME_FORMAT_BIND,
  79. NWCC_OPEN_UNLICENSED,
  80. NWCC_TRAN_TYPE_WILD,
  81. &hConn
  82. );
  83. hr = HRESULT_FROM_NWCCODE(ccode);
  84. BAIL_ON_FAILURE(hr);
  85. pNWCContext->hConn = hConn;
  86. hr = BindCacheAdd(bstrBinderyName, Credentials, fLoggedIn, pNWCContext) ;
  87. BAIL_ON_FAILURE(hr);
  88. *phConnReturned = hConn;
  89. FreeADsStr(pszUserName);
  90. FreeADsStr(pszPassword);
  91. LEAVE_BIND_CRITSECT();
  92. RRETURN(hr);
  93. error:
  94. *phConnReturned = NULL;
  95. if (hConn) {
  96. NWCCCloseConn(hConn);
  97. }
  98. if (fLoggedIn) {
  99. // log out
  100. WNetCancelConnection2((LPWSTR)szBinderyName, 0, FALSE);
  101. }
  102. if (pNWCContext) {
  103. BindCacheFreeEntry(pNWCContext);
  104. }
  105. FreeADsStr(pszUserName);
  106. FreeADsStr(pszPassword);
  107. LEAVE_BIND_CRITSECT();
  108. RRETURN(hr);
  109. }
  110. //----------------------------------------------------------------------------
  111. //
  112. // Function: NWApiReleaseBinderyHandle
  113. //
  114. // Synopsis:
  115. //
  116. //----------------------------------------------------------------------------
  117. HRESULT
  118. NWApiReleaseBinderyHandle(
  119. NWCONN_HANDLE hConn
  120. )
  121. {
  122. HRESULT hr = S_OK;
  123. NWCCODE ccode = SUCCESSFUL;
  124. PNWC_CONTEXT pNWCContext = NULL;
  125. DWORD dwStatus;
  126. // note that if lookup succeeds, it add-refs the context, so we have
  127. // to deref twice below: once for the ref we just added, and once
  128. // for our caller's ref that they're trying to release
  129. pNWCContext = BindCacheLookupByConn(hConn);
  130. if (!pNWCContext)
  131. RRETURN(E_FAIL);
  132. if (BindCacheDeref(pNWCContext) && (BindCacheDeref(pNWCContext) == 0)) {
  133. // ref count has dropped to zero and it's gone from cache
  134. ccode = NWCCCloseConn(hConn);
  135. hr = HRESULT_FROM_NWCCODE(ccode);
  136. BAIL_ON_FAILURE(hr);
  137. if (pNWCContext->fLoggedIn) {
  138. // logout
  139. dwStatus = WNetCancelConnection2(
  140. pNWCContext->pszBinderyName,
  141. 0,
  142. FALSE);
  143. hr = HRESULT_FROM_WIN32(dwStatus);
  144. BAIL_ON_FAILURE(hr);
  145. }
  146. BindCacheFreeEntry(pNWCContext);
  147. }
  148. RRETURN(hr);
  149. error:
  150. // N.B.: If we're here, we must have bailed from inside of
  151. // the BindCacheDeref block, and so pNWCContext must have
  152. // been removed from the cache. Thus, it's safe to free
  153. // it (and not to do so would cause a leak).
  154. BindCacheFreeEntry(pNWCContext);
  155. RRETURN(hr);
  156. }
  157. //----------------------------------------------------------------------------
  158. //
  159. // Function: NWApiIsUserLoggedInToServer
  160. //
  161. // Synopsis: Returns S_OK if pszUserName is logged in to bstrBinderyName,
  162. // S_FALSE if she isn't
  163. //
  164. //----------------------------------------------------------------------------
  165. HRESULT
  166. NWApiCheckUserLoggedInToServer(
  167. BSTR bstrBinderyName,
  168. LPWSTR pszUserName
  169. )
  170. {
  171. DWORD err;
  172. HRESULT hr;
  173. WCHAR pszUser[NW_USER_SIZE+1];
  174. DWORD dwUserLength = NW_USER_SIZE+1;
  175. err = WNetGetUser(bstrBinderyName, pszUser, &dwUserLength);
  176. switch(err)
  177. {
  178. case NO_ERROR:
  179. if (_wcsicmp(pszUser, pszUserName) == 0)
  180. hr = S_OK;
  181. else
  182. hr = S_FALSE;
  183. break;
  184. case ERROR_NOT_CONNECTED:
  185. hr = S_FALSE;
  186. break;
  187. default:
  188. hr = HRESULT_FROM_WIN32(err);
  189. }
  190. return hr;
  191. }
  192. //----------------------------------------------------------------------------
  193. //
  194. // Function: NWApiWriteProperty
  195. //
  196. // Synopsis: This function modifies values of a bindery property. For now, it
  197. // only accept one buffer segment. However, one segment is enough
  198. // for most practical purpose. If the bindery property does not
  199. // exist, the function will attempt to create the property.
  200. //
  201. //----------------------------------------------------------------------------
  202. HRESULT
  203. NWApiWriteProperty(
  204. NWCONN_HANDLE hConn,
  205. BSTR bstrObjectName,
  206. NWOBJ_TYPE wObjType,
  207. LPSTR lpszPropertyName,
  208. LPBYTE SegmentData
  209. )
  210. {
  211. CHAR szObjectName[OBJ_NAME_SIZE + 1];
  212. CHAR szPropertyName[OBJ_NAME_SIZE + 1];
  213. HRESULT hr = S_OK;
  214. NWCCODE ccode;
  215. //
  216. // Convert BSTR into an ANSI representation required by NW APIs. "0" is
  217. // passed to UnicodeToAnsiString when the length of the string is unknown.
  218. //
  219. UnicodeToAnsiString(
  220. bstrObjectName,
  221. szObjectName,
  222. 0
  223. );
  224. strcpy(szPropertyName, lpszPropertyName);
  225. ccode = NWWritePropertyValue(
  226. hConn,
  227. szObjectName,
  228. wObjType,
  229. szPropertyName,
  230. 1, // "1" for one segment.
  231. SegmentData,
  232. 0 // "0" for no more segment.
  233. );
  234. //
  235. // Create the property if it doesn't exist and attempt to write again.
  236. //
  237. if (ccode == NO_SUCH_PROPERTY) {
  238. hr = NWApiCreateProperty(
  239. hConn,
  240. bstrObjectName,
  241. wObjType,
  242. lpszPropertyName,
  243. BF_ITEM
  244. );
  245. BAIL_ON_FAILURE(hr);
  246. ccode = NWWritePropertyValue(
  247. hConn,
  248. szObjectName,
  249. wObjType,
  250. szPropertyName,
  251. 1, // "1" for one segment.
  252. SegmentData,
  253. 0 // "0" for no more segment.
  254. );
  255. }
  256. hr = HRESULT_FROM_NWCCODE(ccode);
  257. error:
  258. RRETURN(hr);
  259. }
  260. //----------------------------------------------------------------------------
  261. //
  262. // Function: NWApiObjectEnum
  263. //
  264. // Synopsis:
  265. //
  266. //----------------------------------------------------------------------------
  267. HRESULT
  268. NWApiObjectEnum(
  269. NWCONN_HANDLE hConn,
  270. NWOBJ_TYPE dwObjType,
  271. LPWSTR *lppszObjectName,
  272. DWORD *pdwResumeObjectID
  273. )
  274. {
  275. HRESULT hr = S_OK;
  276. LPWSTR lpszTemp = NULL;
  277. NWCCODE ccode = SUCCESSFUL;
  278. NWOBJ_TYPE pdwObjType = 0xFFFF;
  279. NWFLAGS pucHasProperties;
  280. NWFLAGS pucObjectFlags;
  281. NWFLAGS pucObjSecurity;
  282. CHAR szObjectName[OBJ_NAME_SIZE + 1];
  283. nstr8 searchObjectName[48] = "*";
  284. //
  285. // This call will fail and return 0xffff if the user is not authenticated
  286. // on the server to which the hConn handle is attached to.
  287. //
  288. ccode = NWScanObject(
  289. hConn,
  290. searchObjectName,
  291. dwObjType,
  292. pdwResumeObjectID,
  293. szObjectName,
  294. &pdwObjType,
  295. &pucHasProperties,
  296. &pucObjectFlags,
  297. &pucObjSecurity
  298. );
  299. hr = HRESULT_FROM_NWCCODE(ccode);
  300. BAIL_ON_FAILURE(hr);
  301. lpszTemp = AllocateUnicodeString(szObjectName);
  302. if (!lpszTemp) {
  303. RRETURN(S_FALSE);
  304. }
  305. *lppszObjectName = AllocADsStr(lpszTemp);
  306. if (!(*lppszObjectName)) {
  307. RRETURN(S_FALSE);
  308. }
  309. if(lpszTemp){
  310. FreeUnicodeString(lpszTemp);
  311. }
  312. RRETURN(hr);
  313. error:
  314. *lppszObjectName = NULL;
  315. pdwResumeObjectID = NULL;
  316. RRETURN(hr);
  317. }
  318. //----------------------------------------------------------------------------
  319. //
  320. // Function: NWApiValidateObject
  321. //
  322. // Synopsis:
  323. //
  324. //----------------------------------------------------------------------------
  325. HRESULT
  326. NWApiValidateObject(
  327. NWCONN_HANDLE hConn,
  328. NWOBJ_TYPE dwObjType,
  329. LPWSTR lpszObjectName,
  330. DWORD *pdwResumeObjectID
  331. )
  332. {
  333. HRESULT hr = S_OK;
  334. NWCCODE ccode = SUCCESSFUL;
  335. CHAR szAnsiObjectName[OBJ_NAME_SIZE + 1];
  336. CHAR szObjectName[OBJ_NAME_SIZE + 1];
  337. NWOBJ_TYPE pdwObjType = 0xFFFF;
  338. NWFLAGS pucHasProperties;
  339. NWFLAGS pucObjectFlags;
  340. NWFLAGS pucObjSecurity;
  341. //
  342. // Convert BSTR into an ANSI representation required by NW APIs. "0" is
  343. // passed to UnicodeToAnsiString when the length of the string is unknown.
  344. //
  345. UnicodeToAnsiString(
  346. lpszObjectName,
  347. szAnsiObjectName,
  348. 0
  349. );
  350. //
  351. // This call will fail and return 0xffff if the user is not authenticated
  352. // on the server to which the hConn handle is attached to.
  353. //
  354. ccode = NWScanObject(
  355. hConn,
  356. szAnsiObjectName,
  357. dwObjType,
  358. pdwResumeObjectID,
  359. szObjectName,
  360. &pdwObjType,
  361. &pucHasProperties,
  362. &pucObjectFlags,
  363. &pucObjSecurity
  364. );
  365. hr = HRESULT_FROM_NWCCODE(ccode);
  366. RRETURN(hr);
  367. }
  368. //----------------------------------------------------------------------------
  369. //
  370. // Function: NWApiGetAnyBinderyHandle
  371. //
  372. // Synopsis:
  373. //
  374. //----------------------------------------------------------------------------
  375. HRESULT
  376. NWApiGetAnyBinderyHandle(
  377. NWCONN_HANDLE *phConn
  378. )
  379. {
  380. HRESULT hr = S_OK;
  381. NWCCODE ccode = 0;
  382. nchar aServerName[OBJ_NAME_SIZE+1];
  383. nuint32 connRef = 0;
  384. ccode = NWCCGetPrimConnRef(
  385. &connRef
  386. );
  387. hr = HRESULT_FROM_NWCCODE(ccode);
  388. BAIL_ON_FAILURE(hr);
  389. ccode = NWCCOpenConnByRef(
  390. connRef,
  391. NWCC_OPEN_UNLICENSED,
  392. NWCC_RESERVED,
  393. phConn
  394. );
  395. hr = HRESULT_FROM_NWCCODE(ccode);
  396. error:
  397. RRETURN(hr);
  398. }
  399. //----------------------------------------------------------------------------
  400. //
  401. // Function: NWApiGetObjectName
  402. //
  403. // Synopsis:
  404. //
  405. //----------------------------------------------------------------------------
  406. HRESULT
  407. NWApiGetObjectName(
  408. NWCONN_HANDLE hConn,
  409. DWORD dwObjectID,
  410. LPWSTR *lppszObjectName
  411. )
  412. {
  413. CHAR szObjectName[OBJ_NAME_SIZE + 1];
  414. HRESULT hr = S_OK;
  415. LPWSTR lpszTemp = NULL;
  416. NWCCODE ccode = SUCCESSFUL;
  417. NWOBJ_TYPE dwObjType;
  418. ccode = NWGetObjectName(
  419. hConn,
  420. dwObjectID,
  421. szObjectName,
  422. &dwObjType
  423. );
  424. hr = HRESULT_FROM_NWCCODE(ccode);
  425. BAIL_ON_FAILURE(hr);
  426. lpszTemp = AllocateUnicodeString(szObjectName);
  427. if (!lpszTemp) {
  428. RRETURN(S_FALSE);
  429. }
  430. *lppszObjectName = AllocADsStr(lpszTemp);
  431. if (!(*lppszObjectName)) {
  432. RRETURN(S_FALSE);
  433. }
  434. FreeUnicodeString(lpszTemp);
  435. RRETURN(hr);
  436. error:
  437. *lppszObjectName = NULL;
  438. RRETURN(hr);
  439. }
  440. //----------------------------------------------------------------------------
  441. //
  442. // Function: HRESULT_FROM_NWCCODE
  443. //
  444. // Synopsis:
  445. //
  446. //----------------------------------------------------------------------------
  447. HRESULT
  448. HRESULT_FROM_NWCCODE(
  449. NWCCODE ccode
  450. )
  451. {
  452. HRESULT hr = S_OK;
  453. if (ccode == NO_SUCH_PROPERTY)
  454. {
  455. hr = E_ADS_PROPERTY_NOT_FOUND;
  456. }
  457. else if (ccode != SUCCESSFUL) {
  458. hr = HRESULT_FROM_WIN32(ERROR_EXTENDED_ERROR);
  459. }
  460. RRETURN(hr);
  461. }
  462. //----------------------------------------------------------------------------
  463. //
  464. // Function: NWApiOpenPrinter
  465. //
  466. // Synopsis:
  467. //
  468. //----------------------------------------------------------------------------
  469. HRESULT
  470. NWApiOpenPrinter(
  471. LPWSTR lpszUncPrinterName,
  472. HANDLE *phPrinter,
  473. DWORD dwAccess
  474. )
  475. {
  476. BOOL fStatus = TRUE;
  477. HANDLE hPrinter;
  478. HRESULT hr = S_OK;
  479. PRINTER_DEFAULTS PrinterDefault = {0, 0, dwAccess};
  480. //
  481. // Set desired access right.
  482. //
  483. PrinterDefault.DesiredAccess = dwAccess;
  484. //
  485. // Get a handle to the speccified printer using Win32 API.
  486. //
  487. fStatus = OpenPrinter(
  488. lpszUncPrinterName,
  489. &hPrinter,
  490. &PrinterDefault
  491. );
  492. //
  493. // Convert error code into HRESULT.
  494. //
  495. if (fStatus == FALSE) {
  496. hr = HRESULT_FROM_WIN32(GetLastError());
  497. }
  498. //
  499. // Return.
  500. //
  501. else {
  502. *phPrinter = hPrinter;
  503. }
  504. RRETURN(hr);
  505. }
  506. //----------------------------------------------------------------------------
  507. //
  508. // Function: NWApiClosePrinter
  509. //
  510. // Synopsis:
  511. //
  512. //----------------------------------------------------------------------------
  513. HRESULT
  514. NWApiClosePrinter(
  515. HANDLE hPrinter
  516. )
  517. {
  518. BOOL fStatus = TRUE;
  519. HRESULT hr = S_OK;
  520. //
  521. // Close a printer using Win32 API.
  522. //
  523. fStatus = ClosePrinter(hPrinter);
  524. //
  525. // Convert error code into HRESULT.
  526. //
  527. if (fStatus == FALSE) {
  528. hr = HRESULT_FROM_WIN32(GetLastError());
  529. }
  530. //
  531. // Return.
  532. //
  533. RRETURN(hr);
  534. }
  535. /* BUGBUG
  536. //----------------------------------------------------------------------------
  537. //
  538. // Function: NWApiEnumJobs
  539. //
  540. // Synopsis:
  541. //
  542. //----------------------------------------------------------------------------
  543. HRESULT
  544. NWApiEnumJobs(
  545. HANDLE hPrinter,
  546. DWORD dwFirstJob,
  547. DWORD dwNoJobs,
  548. DWORD dwLevel,
  549. LPBYTE *lplpbJobs,
  550. DWORD *pcbBuf,
  551. LPDWORD lpdwReturned
  552. )
  553. {
  554. BOOL fStatus = TRUE;
  555. HRESULT hr = S_OK;
  556. fStatus = WinNTEnumJobs(
  557. hPrinter,
  558. dwFirstJob,
  559. dwNoJobs,
  560. dwLevel,
  561. lplpbJobs,
  562. pcbBuf,
  563. lpdwReturned
  564. );
  565. if (fStatus == FALSE) {
  566. hr = HRESULT_FROM_WIN32(GetLastError());
  567. }
  568. RRETURN(hr);
  569. }
  570. //----------------------------------------------------------------------------
  571. //
  572. // Function: NWApiGetPrinter
  573. //
  574. // Synopsis:
  575. //
  576. //----------------------------------------------------------------------------
  577. HRESULT
  578. NWApiGetPrinter(
  579. HANDLE hPrinter,
  580. DWORD dwLevel,
  581. LPBYTE *lplpbPrinters
  582. )
  583. {
  584. BOOL fStatus = TRUE;
  585. HRESULT hr = S_OK;
  586. fStatus = WinNTGetPrinter(
  587. hPrinter,
  588. dwLevel,
  589. lplpbPrinters
  590. );
  591. if (fStatus == FALSE) {
  592. hr = HRESULT_FROM_WIN32(GetLastError());
  593. }
  594. RRETURN(hr);
  595. }
  596. */
  597. //----------------------------------------------------------------------------
  598. //
  599. // Function: NWApiSetPrinter
  600. //
  601. // Synopsis:
  602. //
  603. //----------------------------------------------------------------------------
  604. HRESULT
  605. NWApiSetPrinter(
  606. HANDLE hPrinter,
  607. DWORD dwLevel,
  608. LPBYTE lpbPrinters,
  609. DWORD dwAccess
  610. )
  611. {
  612. BOOL fStatus = FALSE;
  613. HRESULT hr = S_OK;
  614. fStatus = SetPrinter(
  615. hPrinter,
  616. dwLevel,
  617. lpbPrinters,
  618. dwAccess
  619. );
  620. if (!fStatus) {
  621. goto error;
  622. }
  623. RRETURN(S_OK);
  624. error:
  625. hr = HRESULT_FROM_WIN32(GetLastError());
  626. RRETURN(hr);
  627. }
  628. //----------------------------------------------------------------------------
  629. //
  630. // Function: NWApiGetJob
  631. //
  632. // Synopsis:
  633. //
  634. //----------------------------------------------------------------------------
  635. HRESULT
  636. NWApiGetJob(
  637. HANDLE hPrinter,
  638. DWORD dwJobId,
  639. DWORD dwLevel,
  640. LPBYTE *lplpbJobs
  641. )
  642. {
  643. BOOL fStatus = FALSE;
  644. DWORD dwError = 0;
  645. DWORD dwNeeded = 0;
  646. DWORD dwPassed = 1024;
  647. LPBYTE pMem = NULL;
  648. //
  649. // Allocate memory for return buffer.
  650. //
  651. pMem = (LPBYTE)AllocADsMem(dwPassed);
  652. if (!pMem) {
  653. RRETURN(E_OUTOFMEMORY);
  654. }
  655. //
  656. // Get Job's information.
  657. //
  658. fStatus = GetJob(
  659. hPrinter,
  660. dwJobId,
  661. dwLevel,
  662. pMem,
  663. dwPassed,
  664. &dwNeeded
  665. );
  666. //
  667. // Get job's information again with a bigger buffer if a bigger buffer is
  668. // needed for the result.
  669. //
  670. if (!fStatus) {
  671. if ((dwError = GetLastError()) != ERROR_INSUFFICIENT_BUFFER) {
  672. RRETURN(HRESULT_FROM_WIN32(dwError));
  673. }
  674. if (pMem){
  675. FreeADsMem(pMem);
  676. }
  677. pMem = (LPBYTE)AllocADsMem(
  678. dwNeeded
  679. );
  680. if (!pMem) {
  681. RRETURN(E_OUTOFMEMORY);
  682. }
  683. dwPassed = dwNeeded;
  684. fStatus = GetJob(
  685. hPrinter,
  686. dwJobId,
  687. dwLevel,
  688. pMem,
  689. dwPassed,
  690. &dwNeeded
  691. );
  692. if (!fStatus) {
  693. RRETURN(HRESULT_FROM_WIN32(GetLastError()));
  694. }
  695. }
  696. //
  697. // Return.
  698. //
  699. *lplpbJobs = pMem;
  700. RRETURN(S_OK);
  701. }
  702. //----------------------------------------------------------------------------
  703. //
  704. // Function: NWApiSetJob
  705. //
  706. // Synopsis:
  707. //
  708. //----------------------------------------------------------------------------
  709. HRESULT
  710. NWApiSetJob(
  711. HANDLE hPrinter,
  712. DWORD dwJobId,
  713. DWORD dwLevel,
  714. LPBYTE lpbJobs,
  715. DWORD dwCommand
  716. )
  717. {
  718. BOOL fStatus = FALSE;
  719. HRESULT hr = S_OK;
  720. fStatus = SetJob(
  721. hPrinter,
  722. dwJobId,
  723. dwLevel,
  724. lpbJobs,
  725. dwCommand
  726. );
  727. if (!fStatus) {
  728. goto error;
  729. }
  730. RRETURN(S_OK);
  731. error:
  732. hr = HRESULT_FROM_WIN32(GetLastError());
  733. RRETURN(hr);
  734. }
  735. //----------------------------------------------------------------------------
  736. //
  737. // Function: NWApiCreateProperty
  738. //
  739. // Synopsis: This function creates a bindery property. Access is logged read,
  740. // supervisor write.
  741. //
  742. //----------------------------------------------------------------------------
  743. HRESULT
  744. NWApiCreateProperty(
  745. NWCONN_HANDLE hConn,
  746. LPWSTR lpszObjectName,
  747. NWOBJ_TYPE wObjType,
  748. LPSTR lpszPropertyName,
  749. NWFLAGS ucObjectFlags
  750. )
  751. {
  752. CHAR szAnsiObjectName[OBJ_NAME_SIZE + 1];
  753. CHAR szPropertyName[OBJ_NAME_SIZE + 1];
  754. HRESULT hr = S_OK;
  755. NWCCODE ccode = SUCCESSFUL;
  756. //
  757. // Convert BSTR into an ANSI representation required by NW APIs. "0" is
  758. // passed to UnicodeToAnsiString when the length of the string is unknown.
  759. //
  760. UnicodeToAnsiString(
  761. lpszObjectName,
  762. szAnsiObjectName,
  763. 0
  764. );
  765. strcpy(szPropertyName, lpszPropertyName);
  766. //
  767. // Create property.
  768. //
  769. ccode = NWCreateProperty(
  770. hConn,
  771. szAnsiObjectName,
  772. wObjType,
  773. szPropertyName,
  774. ucObjectFlags,
  775. BS_LOGGED_READ | BS_SUPER_WRITE
  776. );
  777. //
  778. // Return.
  779. //
  780. hr = HRESULT_FROM_NWCCODE(ccode);
  781. RRETURN(hr);
  782. }