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.

1023 lines
31 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ApiWksta.c
  5. Abstract:
  6. This module contains individual API handlers for the NetWksta
  7. APIs.
  8. SUPPORTED : NetWkstaGetInfo, NetWkstaSetInfo.
  9. UNSUPPORTED : NetWkstaSetUid.
  10. SEE ALSO : NetWkstaUserLogon, NetWkstaUserLogoff - in ApiLogon.c.
  11. Author:
  12. Shanku Niyogi (w-shanku) 25-Feb-1991
  13. Revision History:
  14. --*/
  15. #include "XactSrvP.h"
  16. //
  17. // Declaration of descriptor strings.
  18. //
  19. STATIC const LPDESC Desc16_wksta_info_0 = REM16_wksta_info_0;
  20. STATIC const LPDESC Desc16_wksta_info_1 = REM16_wksta_info_1;
  21. STATIC const LPDESC Desc16_wksta_info_10 = REM16_wksta_info_10;
  22. //
  23. // The size of the heuristics is actually 55 chars but we add one
  24. // for padding.
  25. //
  26. #define SIZE_HEURISTICS 56
  27. NTSTATUS
  28. XsNetWkstaGetInfo (
  29. API_HANDLER_PARAMETERS
  30. )
  31. /*++
  32. Routine Description:
  33. This routine sets up a call to NetWkstaGetInfo. Because of the differences
  34. between 16- and 32-bit structures, this routine does not use the normal
  35. conversion process.
  36. Arguments:
  37. API_HANDLER_PARAMETERS - information about the API call. See
  38. XsTypes.h for details.
  39. Return Value:
  40. NTSTATUS - STATUS_SUCCESS or reason for failure.
  41. --*/
  42. {
  43. NET_API_STATUS status;
  44. PXS_NET_WKSTA_GET_INFO parameters = Parameters;
  45. LPWKSTA_INFO_100 wksta_100 = NULL; // Native parameters
  46. LPWKSTA_INFO_101 wksta_101 = NULL;
  47. LPWKSTA_INFO_502 wksta_502 = NULL;
  48. LPBYTE stringLocation = NULL; // Conversion variables
  49. DWORD bytesRequired = 0;
  50. BOOL varWrite;
  51. LPWKSTA_16_INFO_1 entry1;
  52. LPWKSTA_16_INFO_10 entry10;
  53. TCHAR heuristics[SIZE_HEURISTICS];
  54. DWORD i;
  55. USHORT level;
  56. WCHAR lanroot[PATHLEN+1];
  57. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  58. IF_DEBUG(WKSTA) {
  59. NetpKdPrint(( "XsNetWkstaGetInfo: header at %lx, "
  60. "params at %lx, level %ld\n",
  61. Header, parameters, SmbGetUshort( &parameters->Level ) ));
  62. }
  63. try {
  64. //
  65. // Check for errors.
  66. //
  67. level = SmbGetUshort( &parameters->Level );
  68. if ( (level != 0) && (level != 1) && (level != 10) ) {
  69. Header->Status = ERROR_INVALID_LEVEL;
  70. goto cleanup;
  71. }
  72. //
  73. // we return the system directory as the lanroot
  74. //
  75. *lanroot = 0;
  76. GetSystemDirectory(lanroot, sizeof(lanroot)/sizeof(*lanroot));
  77. //
  78. // Gather the requested data by making local GetInfo calls.
  79. //
  80. switch ( level ) {
  81. case 10:
  82. status = NetWkstaGetInfo(
  83. NULL,
  84. (DWORD)100,
  85. (LPBYTE *)&wksta_100
  86. );
  87. if ( !XsApiSuccess ( status )) {
  88. IF_DEBUG(API_ERRORS) {
  89. NetpKdPrint(( "XsWkstaGetInfo: WkstaGetInfo (level 100) "
  90. "failed: %X\n", status));
  91. }
  92. Header->Status = (WORD) status;
  93. goto cleanup;
  94. }
  95. break;
  96. case 0:
  97. case 1:
  98. status = NetWkstaGetInfo(
  99. NULL,
  100. (DWORD)101,
  101. (LPBYTE *)&wksta_101
  102. );
  103. if ( !XsApiSuccess( status )) {
  104. IF_DEBUG(API_ERRORS) {
  105. NetpKdPrint(( "XsWkstaGetInfo: WkstaGetInfo (level 101) "
  106. "failed: %X\n", status));
  107. }
  108. Header->Status = (WORD) status;
  109. goto cleanup;
  110. }
  111. status = NetWkstaGetInfo(
  112. NULL,
  113. (DWORD)502,
  114. (LPBYTE *)&wksta_502
  115. );
  116. if ( !XsApiSuccess( status )) {
  117. IF_DEBUG(API_ERRORS) {
  118. NetpKdPrint(( "XsWkstaGetInfo: WkstaGetInfo (level 502) "
  119. "failed: %X\n", status));
  120. }
  121. Header->Status = (WORD) status;
  122. goto cleanup;
  123. }
  124. break;
  125. }
  126. //
  127. // Calculate the amount of space required to hold the fixed and
  128. // variable data. Since this is the only place where we get one
  129. // case for each valid level, we will also get the source structure
  130. // descriptor here.
  131. //
  132. switch ( level ) {
  133. case 0:
  134. StructureDesc = Desc16_wksta_info_0;
  135. bytesRequired = sizeof( WKSTA_16_INFO_0 )
  136. + NetpUnicodeToDBCSLen( lanroot )
  137. + NetpUnicodeToDBCSLen( wksta_101->wki101_computername )
  138. + NetpUnicodeToDBCSLen( DEF16_wk_username )
  139. + NetpUnicodeToDBCSLen( wksta_101->wki101_langroup )
  140. + NetpUnicodeToDBCSLen( DEF16_wk_logon_server )
  141. + SIZE_HEURISTICS
  142. + 6; // for terminating nulls
  143. break;
  144. case 1:
  145. StructureDesc = Desc16_wksta_info_1;
  146. bytesRequired = sizeof( WKSTA_16_INFO_1 )
  147. + NetpUnicodeToDBCSLen( lanroot )
  148. + NetpUnicodeToDBCSLen( wksta_101->wki101_computername )
  149. + NetpUnicodeToDBCSLen( DEF16_wk_username )
  150. + NetpUnicodeToDBCSLen( wksta_101->wki101_langroup )
  151. + NetpUnicodeToDBCSLen( DEF16_wk_logon_server )
  152. + SIZE_HEURISTICS
  153. + NetpUnicodeToDBCSLen( DEF16_wk_logon_domain )
  154. + NetpUnicodeToDBCSLen( DEF16_wk_oth_domains )
  155. + 8; // for terminating nulls
  156. break;
  157. case 10:
  158. StructureDesc = Desc16_wksta_info_10;
  159. bytesRequired = sizeof( WKSTA_16_INFO_10 )
  160. + NetpUnicodeToDBCSLen( DEF16_wk_username )
  161. + NetpUnicodeToDBCSLen( DEF16_wk_logon_domain )
  162. + NetpUnicodeToDBCSLen( wksta_100->wki100_computername )
  163. + NetpUnicodeToDBCSLen( wksta_100->wki100_langroup )
  164. + NetpUnicodeToDBCSLen( DEF16_wk_oth_domains )
  165. + 5; // for terminating nulls
  166. break;
  167. }
  168. //
  169. // If there isn't enough room in the buffer for this, don't write any
  170. // variable data.
  171. //
  172. varWrite = ( (DWORD)SmbGetUshort( &parameters->BufLen )
  173. >= bytesRequired ) ? TRUE : FALSE;
  174. stringLocation = (LPBYTE)( XsSmbGetPointer( &parameters->Buffer )
  175. + RapStructureSize( StructureDesc, Response, FALSE ));
  176. //
  177. // Return NERR_BufTooSmall if fixed structure will not fit.
  178. //
  179. if ( !XsCheckBufferSize(
  180. SmbGetUshort( &parameters->BufLen ),
  181. StructureDesc,
  182. FALSE // not in native format
  183. )) {
  184. IF_DEBUG(ERRORS) {
  185. NetpKdPrint(( "XsNetWkstaGetInfo: Buffer too small.\n" ));
  186. }
  187. Header->Status = NERR_BufTooSmall;
  188. SmbPutUshort( &parameters->TotalAvail, (WORD)bytesRequired );
  189. goto cleanup;
  190. }
  191. //
  192. // Based on the level, fill the appropriate information directly into
  193. // 16-bit buffer.
  194. //
  195. entry1 = (LPWKSTA_16_INFO_1) XsSmbGetPointer( &parameters->Buffer );
  196. entry10 = (LPWKSTA_16_INFO_10) entry1;
  197. switch ( level ) {
  198. case 1:
  199. if ( varWrite ) {
  200. XsAddVarString(
  201. stringLocation,
  202. DEF16_wk_logon_domain,
  203. &entry1->wki1_logon_domain,
  204. entry1
  205. );
  206. XsAddVarString(
  207. stringLocation,
  208. DEF16_wk_oth_domains,
  209. &entry1->wki1_oth_domains,
  210. entry1
  211. );
  212. }
  213. SmbPutUshort( &entry1->wki1_numdgrambuf,
  214. DEF16_wk_numdgrambuf );
  215. //
  216. // Fill the rest of the level 1 structure just like a
  217. // level 0 structure.
  218. //
  219. case 0:
  220. //
  221. // Zero the reserved words.
  222. //
  223. SmbPutUshort( &entry1->wki1_reserved_1, (WORD) 0 );
  224. SmbPutUlong( &entry1->wki1_reserved_2, (DWORD) 0 );
  225. SmbPutUlong( &entry1->wki1_reserved_3, (DWORD) 0 );
  226. SmbPutUshort( &entry1->wki1_reserved_4, (WORD) 0 );
  227. SmbPutUshort( &entry1->wki1_reserved_5, (WORD) 0 );
  228. SmbPutUshort( &entry1->wki1_reserved_6, (WORD) 0 );
  229. //
  230. // Fill in the fields which have analogues in NT.
  231. //
  232. if ( varWrite ) {
  233. XsAddVarString(
  234. stringLocation,
  235. lanroot,
  236. &entry1->wki1_root,
  237. entry1
  238. );
  239. XsAddVarString(
  240. stringLocation,
  241. wksta_101->wki101_computername,
  242. &entry1->wki1_computername,
  243. entry1
  244. );
  245. XsAddVarString(
  246. stringLocation,
  247. wksta_101->wki101_langroup,
  248. &entry1->wki1_langroup,
  249. entry1
  250. );
  251. }
  252. entry1->wki1_ver_major = (BYTE) wksta_101->wki101_ver_major;
  253. entry1->wki1_ver_minor = (BYTE) wksta_101->wki101_ver_minor;
  254. SmbPutUshort( &entry1->wki1_charwait,
  255. XsDwordToWord( wksta_502->wki502_char_wait ) );
  256. SmbPutUlong( &entry1->wki1_chartime,
  257. (DWORD) wksta_502->wki502_collection_time );
  258. SmbPutUshort( &entry1->wki1_charcount,
  259. XsDwordToWord( wksta_502->
  260. wki502_maximum_collection_count ) );
  261. SmbPutUshort( &entry1->wki1_keepconn,
  262. XsDwordToWord( wksta_502->wki502_keep_conn ) );
  263. SmbPutUshort( &entry1->wki1_maxthreads,
  264. XsDwordToWord( wksta_502->wki502_max_threads ) );
  265. SmbPutUshort( &entry1->wki1_maxcmds,
  266. XsDwordToWord( wksta_502->wki502_max_cmds ) );
  267. SmbPutUshort( &entry1->wki1_sesstimeout,
  268. XsDwordToWord( wksta_502->wki502_sess_timeout ) );
  269. //
  270. // Construct the heuristics string.
  271. //
  272. // Request opportunistic locking of files.
  273. heuristics[0] = MAKE_TCHAR(XsBoolToDigit(
  274. wksta_502->wki502_use_opportunistic_locking ));
  275. // Optimize performance for command files.
  276. heuristics[1] = MAKE_TCHAR('1');
  277. // Unlock and WriteUnlock asynchronously.
  278. heuristics[2] = MAKE_TCHAR('1'); // default
  279. // Close and WriteClose asynchronously.
  280. heuristics[3] = MAKE_TCHAR('1'); // default
  281. // Buffer named pipes and communication devices.
  282. heuristics[4] = MAKE_TCHAR(XsBoolToDigit(
  283. wksta_502->wki502_buf_named_pipes ));
  284. // LockRead and WriteUnlock.
  285. heuristics[5] = MAKE_TCHAR(XsBoolToDigit(
  286. wksta_502->wki502_use_lock_read_unlock ));
  287. // Use Open and Read.
  288. heuristics[6] = MAKE_TCHAR('0');
  289. // Read-ahead to sector boundary.
  290. heuristics[7] = MAKE_TCHAR('1');
  291. // Use the "chain send" NetBIOS NCB.
  292. heuristics[8] = MAKE_TCHAR('2');
  293. // Buffer small read/write requests.
  294. heuristics[9] = MAKE_TCHAR('1');
  295. // Use buffer mode.
  296. heuristics[10] = MAKE_TCHAR('3');
  297. // Use raw data transfer read/write server message block protocols.
  298. heuristics[11] = MAKE_TCHAR('1');
  299. // Use large RAW read-ahead buffer.
  300. heuristics[12] = MAKE_TCHAR('1');
  301. // Use large RAW write-behind buffer.
  302. heuristics[13] = MAKE_TCHAR('1');
  303. // Use read multiplex SMB protocols.
  304. heuristics[14] = MAKE_TCHAR('0');
  305. // Use write multiplex SMB protocols.
  306. heuristics[15] = MAKE_TCHAR('0');
  307. // Use big buffer for large core reads.
  308. heuristics[16] = MAKE_TCHAR('1');
  309. // Set the read-ahead size.
  310. heuristics[17] = MAKE_TCHAR('0');
  311. // Set the write-behind size.
  312. heuristics[18] = MAKE_TCHAR('0');
  313. // Force 512-byte maximum transfers to and from core servers.
  314. heuristics[19] = MAKE_TCHAR(XsBoolToDigit(
  315. wksta_502->wki502_use_512_byte_max_transfer ));
  316. // Flush pipes and devices on DosBufReset or DosClose.
  317. heuristics[20] = MAKE_TCHAR('0');
  318. // Use encryption if the server supports it.
  319. heuristics[21] = MAKE_TCHAR(XsBoolToDigit(
  320. wksta_502->wki502_use_encryption ));
  321. // Control log entries for multiple occurences of an error.
  322. heuristics[22] = MAKE_TCHAR('1');
  323. // Buffer all files opened with "deny write" rights.
  324. heuristics[23] = MAKE_TCHAR(XsBoolToDigit(
  325. wksta_502->wki502_buf_files_deny_write ));
  326. // Buffer all files opened with R attribute.
  327. heuristics[24] = MAKE_TCHAR(XsBoolToDigit(
  328. wksta_502->wki502_buf_read_only_files ));
  329. // Read ahead when opening a file for execution.
  330. heuristics[25] = MAKE_TCHAR('0');
  331. // Handle Ctrl-C.
  332. heuristics[26] = MAKE_TCHAR('2');
  333. // Force correct open mode when creating files on a core server.
  334. heuristics[27] = MAKE_TCHAR(XsBoolToDigit(
  335. wksta_502->wki502_force_core_create_mode ));
  336. // Use NetBIOS NoAck mode.
  337. heuristics[28] = MAKE_TCHAR('0');
  338. // Send data along with SMB write-block-RAW requests.
  339. heuristics[29] = MAKE_TCHAR('1');
  340. // Send a popup when the workstation logs an error.
  341. heuristics[30] = MAKE_TCHAR('1');
  342. // Close the print job, causing the remote spooler to print if no
  343. // activity occurs on the printer for the time specified.
  344. heuristics[31] = MAKE_TCHAR('0');
  345. // Controls BufReset and SMBFlush behavior for the MS-DOS
  346. // compatibility box.
  347. heuristics[32] = MAKE_TCHAR('2');
  348. // Controls the time-out value for performing logon validation from a
  349. // domain controller.
  350. heuristics[33] = MAKE_TCHAR('0');
  351. for ( i = 34; i <= 54; i++ ) {
  352. heuristics[i] = MAKE_TCHAR('0');
  353. }
  354. heuristics[SIZE_HEURISTICS-1] = MAKE_TCHAR('\0');
  355. if ( varWrite ) {
  356. XsAddVarString(
  357. stringLocation,
  358. heuristics,
  359. &entry1->wki1_wrkheuristics,
  360. entry1
  361. );
  362. }
  363. //
  364. // Put default values in the fields that are meaningless in NT.
  365. //
  366. if ( varWrite ) {
  367. XsAddVarString(
  368. stringLocation,
  369. DEF16_wk_logon_server,
  370. &entry1->wki1_logon_server,
  371. entry1
  372. );
  373. XsAddVarString(
  374. stringLocation,
  375. DEF16_wk_username,
  376. &entry1->wki1_username,
  377. entry1
  378. );
  379. }
  380. SmbPutUshort( &entry1->wki1_keepsearch,
  381. (WORD) DEF16_wk_keepsearch );
  382. SmbPutUshort( &entry1->wki1_numworkbuf,
  383. (WORD) DEF16_wk_numworkbuf );
  384. SmbPutUshort( &entry1->wki1_sizworkbuf,
  385. (WORD) DEF16_wk_sizeworkbuf );
  386. SmbPutUshort( &entry1->wki1_maxwrkcache,
  387. (WORD) DEF16_wk_maxwrkcache );
  388. SmbPutUshort( &entry1->wki1_sizerror,
  389. (WORD) DEF16_wk_sizerror );
  390. SmbPutUshort( &entry1->wki1_numalerts,
  391. (WORD) DEF16_wk_numalerts );
  392. SmbPutUshort( &entry1->wki1_numservices,
  393. (WORD) DEF16_wk_numservices );
  394. SmbPutUshort( &entry1->wki1_errlogsz,
  395. (WORD) DEF16_wk_errlogsz );
  396. SmbPutUshort( &entry1->wki1_printbuftime,
  397. (WORD) DEF16_wk_printbuftime );
  398. SmbPutUshort( &entry1->wki1_numcharbuf,
  399. (WORD) DEF16_wk_numcharbuf );
  400. SmbPutUshort( &entry1->wki1_sizcharbuf,
  401. (WORD) DEF16_wk_sizcharbuf );
  402. SmbPutUshort( &entry1->wki1_mailslots,
  403. (WORD) DEF16_wk_mailslots );
  404. break;
  405. case 10:
  406. //
  407. // Fill in the fields which have analogues in NT.
  408. //
  409. if ( varWrite ) {
  410. XsAddVarString(
  411. stringLocation,
  412. wksta_100->wki100_computername,
  413. &entry10->wki10_computername,
  414. entry10
  415. );
  416. XsAddVarString(
  417. stringLocation,
  418. wksta_100->wki100_langroup,
  419. &entry10->wki10_langroup,
  420. entry10
  421. );
  422. }
  423. entry10->wki10_ver_major = XsDwordToByte( wksta_100->wki100_ver_major );
  424. entry10->wki10_ver_minor = XsDwordToByte( wksta_100->wki100_ver_minor );
  425. //
  426. // Put default values in the fields that are meaningless in NT.
  427. //
  428. if ( varWrite ) {
  429. XsAddVarString(
  430. stringLocation,
  431. DEF16_wk_username,
  432. &entry10->wki10_username,
  433. entry10
  434. );
  435. XsAddVarString(
  436. stringLocation,
  437. DEF16_wk_logon_domain,
  438. &entry10->wki10_logon_domain,
  439. entry10
  440. );
  441. XsAddVarString(
  442. stringLocation,
  443. DEF16_wk_oth_domains,
  444. &entry10->wki10_oth_domains,
  445. entry10
  446. );
  447. }
  448. break;
  449. }
  450. SmbPutUshort( &parameters->TotalAvail, (WORD)bytesRequired );
  451. if ( varWrite == 0 ) {
  452. Header->Status = ERROR_MORE_DATA;
  453. } else {
  454. Header->Status = NERR_Success;
  455. Header->Converter = 0;
  456. }
  457. cleanup:
  458. ;
  459. } except( EXCEPTION_EXECUTE_HANDLER ) {
  460. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  461. }
  462. if ( wksta_100 != NULL ) {
  463. NetApiBufferFree( wksta_100 );
  464. }
  465. if ( wksta_101 != NULL ) {
  466. NetApiBufferFree( wksta_101 );
  467. }
  468. if ( wksta_502 != NULL ) {
  469. NetApiBufferFree( wksta_502 );
  470. }
  471. //
  472. // Determine return buffer size.
  473. //
  474. XsSetDataCount(
  475. &parameters->BufLen,
  476. StructureDesc,
  477. Header->Converter,
  478. 1,
  479. Header->Status
  480. );
  481. return STATUS_SUCCESS;
  482. } // XsNetWkstaGetInfo
  483. NTSTATUS
  484. XsNetWkstaSetInfo (
  485. API_HANDLER_PARAMETERS
  486. )
  487. /*++
  488. Routine Description:
  489. This routine handles a call to NetWkstaSetInfo.
  490. Arguments:
  491. API_HANDLER_PARAMETERS - information about the API call. See
  492. XsTypes.h for details.
  493. Return Value:
  494. NTSTATUS - STATUS_SUCCESS or reason for failure.
  495. --*/
  496. {
  497. NET_API_STATUS status;
  498. PXS_NET_WKSTA_SET_INFO parameters = Parameters;
  499. DWORD data;
  500. BOOL flag;
  501. DWORD nativeParmNum;
  502. LPVOID buffer = NULL; // Conversion variables
  503. DWORD bufferSize;
  504. LPWKSTA_16_INFO_1 entry1;
  505. LPWKSTA_16_INFO_10 entry10;
  506. BOOL error;
  507. DWORD parmNum;
  508. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  509. try {
  510. //
  511. // Check for errors. We will filter out wrong levels now.
  512. //
  513. parmNum = SmbGetUshort( &parameters->ParmNum );
  514. switch ( SmbGetUshort( &parameters->Level )) {
  515. case 0:
  516. StructureDesc = Desc16_wksta_info_0;
  517. if ( parmNum == WKSTA_OTH_DOMAINS_PARMNUM ) {
  518. Header->Status = ERROR_INVALID_LEVEL;
  519. goto cleanup;
  520. }
  521. break;
  522. case 1:
  523. StructureDesc = Desc16_wksta_info_1;
  524. break;
  525. case 10:
  526. StructureDesc = Desc16_wksta_info_10;
  527. if ( parmNum == WKSTA_CHARWAIT_PARMNUM
  528. || parmNum == WKSTA_CHARTIME_PARMNUM
  529. || parmNum == WKSTA_CHARCOUNT_PARMNUM
  530. || parmNum == WKSTA_ERRLOGSZ_PARMNUM
  531. || parmNum == WKSTA_PRINTBUFTIME_PARMNUM
  532. || parmNum == WKSTA_WRKHEURISTICS_PARMNUM ) {
  533. Header->Status = ERROR_INVALID_LEVEL;
  534. goto cleanup;
  535. }
  536. break;
  537. default:
  538. Header->Status = ERROR_INVALID_LEVEL;
  539. goto cleanup;
  540. break;
  541. }
  542. //
  543. // Check input buffer size if parmnum is PARMNUM_ALL.
  544. //
  545. if ( parmNum == PARMNUM_ALL ) {
  546. if ( !XsCheckBufferSize(
  547. SmbGetUshort( &parameters->BufLen ),
  548. StructureDesc,
  549. FALSE // not in native format
  550. )) {
  551. Header->Status = NERR_BufTooSmall;
  552. goto cleanup;
  553. }
  554. }
  555. buffer = (LPVOID)XsSmbGetPointer( &parameters->Buffer );
  556. bufferSize = (DWORD)SmbGetUshort( &parameters->BufLen );
  557. entry1 = (LPWKSTA_16_INFO_1)buffer;
  558. entry10 = (LPWKSTA_16_INFO_10)buffer;
  559. //
  560. // Processing of this API depends on the value of the ParmNum
  561. // parameter. Because of all the discrepancies between NT and downlevel
  562. // info structures, we will handle each instance by hand.
  563. //
  564. error = TRUE;
  565. //
  566. // charwait - source data is in a WORD - convert to DWORD
  567. //
  568. if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_CHARWAIT_PARMNUM ) {
  569. if ( bufferSize < sizeof(WORD) ) {
  570. Header->Status = NERR_BufTooSmall;
  571. goto cleanup;
  572. }
  573. data = ( parmNum == PARMNUM_ALL )
  574. ? (DWORD)SmbGetUshort( &entry1->wki1_charwait )
  575. : (DWORD)SmbGetUshort( (LPWORD)buffer );
  576. status = NetWkstaSetInfo(
  577. NULL,
  578. PARMNUM_BASE_INFOLEVEL + WKSTA_CHARWAIT_PARMNUM,
  579. (LPBYTE)&data,
  580. NULL
  581. );
  582. if ( status != NERR_Success ) {
  583. IF_DEBUG(ERRORS) {
  584. NetpKdPrint(( "XsNetWkstaSetInfo : SetInfo of charwait failed"
  585. "%X\n", status ));
  586. }
  587. Header->Status = (WORD)status;
  588. goto cleanup;
  589. }
  590. error = FALSE;
  591. }
  592. //
  593. // chartime - source data is in a DWORD - convert to DWORD
  594. //
  595. if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_CHARTIME_PARMNUM ) {
  596. if ( bufferSize < sizeof(DWORD) ) {
  597. Header->Status = NERR_BufTooSmall;
  598. goto cleanup;
  599. }
  600. data = ( parmNum == PARMNUM_ALL )
  601. ? SmbGetUlong( &entry1->wki1_chartime )
  602. : SmbGetUlong( (LPDWORD)buffer );
  603. status = NetWkstaSetInfo(
  604. NULL,
  605. PARMNUM_BASE_INFOLEVEL + WKSTA_CHARTIME_PARMNUM,
  606. (LPBYTE)&data,
  607. NULL
  608. );
  609. if ( status != NERR_Success ) {
  610. IF_DEBUG(ERRORS) {
  611. NetpKdPrint(( "XsNetWkstaSetInfo : SetInfo of chartime failed"
  612. "%X\n", status ));
  613. }
  614. Header->Status = (WORD)status;
  615. goto cleanup;
  616. }
  617. error = FALSE;
  618. }
  619. //
  620. // charcount - source data is in a WORD - convert to DWORD
  621. //
  622. if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_CHARCOUNT_PARMNUM ) {
  623. if ( bufferSize < sizeof(WORD) ) {
  624. Header->Status = NERR_BufTooSmall;
  625. goto cleanup;
  626. }
  627. data = ( parmNum == PARMNUM_ALL )
  628. ? (DWORD)SmbGetUshort( &entry1->wki1_charcount )
  629. : (DWORD)SmbGetUshort( (LPWORD)buffer );
  630. status = NetWkstaSetInfo(
  631. NULL,
  632. PARMNUM_BASE_INFOLEVEL + WKSTA_CHARCOUNT_PARMNUM,
  633. (LPBYTE)&data,
  634. NULL
  635. );
  636. if ( status != NERR_Success ) {
  637. IF_DEBUG(ERRORS) {
  638. NetpKdPrint(( "XsNetWkstaSetInfo : SetInfo of charcount failed"
  639. "%X\n", status ));
  640. }
  641. Header->Status = (WORD)status;
  642. goto cleanup;
  643. }
  644. error = FALSE;
  645. }
  646. //
  647. // errlogsz, printbuftime - source data is in a WORD.
  648. //
  649. // We can't set this, but downlevel can, so indicate success,
  650. // as long as something was sent.
  651. //
  652. if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_ERRLOGSZ_PARMNUM
  653. || parmNum == WKSTA_PRINTBUFTIME_PARMNUM ) {
  654. if ( bufferSize < sizeof(WORD) ) {
  655. Header->Status = NERR_BufTooSmall;
  656. goto cleanup;
  657. }
  658. error = FALSE;
  659. }
  660. //
  661. // othdomains - source data is a string.
  662. //
  663. // We can't set this, but downlevel can, so indicate success,
  664. // as long as something was sent.
  665. //
  666. if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_OTH_DOMAINS_PARMNUM ) {
  667. if ( bufferSize == 0 ) {
  668. Header->Status = NERR_BufTooSmall;
  669. goto cleanup;
  670. }
  671. error = FALSE;
  672. }
  673. //
  674. // wrkheuristics - source data is in a string.
  675. //
  676. // There are some elements of this that we can set. We go through a loop,
  677. // setting these.
  678. //
  679. if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_WRKHEURISTICS_PARMNUM ) {
  680. LPBYTE heuristics;
  681. DWORD i;
  682. if ( bufferSize < 54 ) {
  683. Header->Status = NERR_BufTooSmall;
  684. goto cleanup;
  685. }
  686. heuristics = ( parmNum == PARMNUM_ALL )
  687. ? (LPBYTE)XsSmbGetPointer( &entry1->wki1_wrkheuristics )
  688. : (LPBYTE)buffer;
  689. //
  690. // Nothing to be changed
  691. //
  692. if ( heuristics == NULL ) {
  693. goto cleanup;
  694. }
  695. //
  696. // Make sure we have the right size of string.
  697. //
  698. if ( strlen( heuristics ) != 54 ) {
  699. Header->Status = ERROR_INVALID_PARAMETER;
  700. goto cleanup;
  701. }
  702. for ( i = 0; i < 54; i++ ) {
  703. //
  704. // Make sure heuristics string is valid.
  705. //
  706. if ( !isdigit( heuristics[i] )) {
  707. Header->Status = ERROR_INVALID_PARAMETER;
  708. goto cleanup;
  709. }
  710. //
  711. // Check if we can set this field.
  712. //
  713. switch ( i ) {
  714. case 0:
  715. nativeParmNum = WKSTA_USEOPPORTUNISTICLOCKING_PARMNUM;
  716. break;
  717. case 4:
  718. nativeParmNum = WKSTA_BUFFERNAMEDPIPES_PARMNUM;
  719. break;
  720. case 5:
  721. nativeParmNum = WKSTA_USELOCKANDREADANDUNLOCK_PARMNUM;
  722. break;
  723. case 19:
  724. nativeParmNum = WKSTA_USE512BYTESMAXTRANSFER_PARMNUM;
  725. break;
  726. case 21:
  727. nativeParmNum = WKSTA_USEENCRYPTION_PARMNUM;
  728. break;
  729. case 23:
  730. nativeParmNum = WKSTA_BUFFILESWITHDENYWRITE_PARMNUM;
  731. break;
  732. case 24:
  733. nativeParmNum = WKSTA_BUFFERREADONLYFILES_PARMNUM;
  734. break;
  735. case 27:
  736. nativeParmNum = WKSTA_FORCECORECREATEMODE_PARMNUM;
  737. break;
  738. default:
  739. nativeParmNum = 0;
  740. break;
  741. }
  742. //
  743. // If we can set the field, set it.
  744. //
  745. if ( nativeParmNum != 0 ) {
  746. if ( heuristics[i] != '0' && heuristics[i] != '1' ) {
  747. Header->Status = ERROR_INVALID_PARAMETER;
  748. goto cleanup;
  749. }
  750. flag = XsDigitToBool( heuristics[i] );
  751. status = NetWkstaSetInfo(
  752. NULL,
  753. PARMNUM_BASE_INFOLEVEL + nativeParmNum,
  754. (LPBYTE)&flag,
  755. NULL
  756. );
  757. if ( status != NERR_Success ) {
  758. IF_DEBUG(ERRORS) {
  759. NetpKdPrint(( "XsNetWkstaSetInfo : SetInfo of a "
  760. "heuristic failed: %X\n", status ));
  761. }
  762. Header->Status = (WORD)status;
  763. goto cleanup;
  764. }
  765. }
  766. }
  767. error = FALSE;
  768. }
  769. //
  770. // Tried all possible parmnums. If error is still set, we have an
  771. // invalid parmnum on our hands.
  772. //
  773. if ( error ) {
  774. Header->Status = ERROR_INVALID_PARAMETER;
  775. }
  776. //
  777. // No return information for this API.
  778. //
  779. cleanup:
  780. ;
  781. } except( EXCEPTION_EXECUTE_HANDLER ) {
  782. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  783. }
  784. return STATUS_SUCCESS;
  785. } // XsNetWkstaSetInfo
  786. NTSTATUS
  787. XsNetWkstaSetUID (
  788. API_HANDLER_PARAMETERS
  789. )
  790. /*++
  791. Routine Description:
  792. This temporary routine just returns STATUS_NOT_IMPLEMENTED.
  793. Arguments:
  794. API_HANDLER_PARAMETERS - information about the API call. See
  795. XsTypes.h for details.
  796. Return Value:
  797. NTSTATUS - STATUS_SUCCESS or reason for failure.
  798. --*/
  799. {
  800. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  801. Header->Status = (WORD)NERR_InvalidAPI;
  802. return STATUS_SUCCESS;
  803. } // XsNetWkstaSetUID