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.

403 lines
13 KiB

  1. /*++
  2. Copyright (c) 1991-92 Microsoft Corporation
  3. Module Name:
  4. SetField.c
  5. Abstract:
  6. This module consists of the routine RxpSetField and its helpers
  7. (RxpIsFieldSettable and RxpFieldSize).
  8. Author:
  9. John Rogers (JohnRo) 29-May-1991
  10. Environment:
  11. Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
  12. Requires ANSI C extensions: slash-slash comments, long external names.
  13. Revision History:
  14. 29-May-1991 JohnRo
  15. Created.
  16. 06-Jun-1991 JohnRo
  17. Fixed bug handling buffer size (it shouldn't be sent).
  18. Fixed off-by-one error in string size handling in RxpFieldSize.
  19. Added debug output.
  20. 12-Jul-1991 JohnRo
  21. Added more parameters to RxpSetField(), to support RxPrintJobSetInfo().
  22. Still more debug output.
  23. 17-Jul-1991 JohnRo
  24. Extracted RxpDebug.h from Rxp.h.
  25. 01-Oct-1991 JohnRo
  26. More work toward UNICODE.
  27. 21-Nov-1991 JohnRo
  28. Removed NT dependencies to reduce recompiles.
  29. 31-Mar-1992 JohnRo
  30. Prevent too large size requests.
  31. --*/
  32. // These must be included first:
  33. #include <windef.h> // IN, DWORD, etc.
  34. #include <lmcons.h> // PARMNUM_ALL, NET_API_STATUS, etc.
  35. // These may be included in any order:
  36. #include <lmerr.h> // NERR_Success, etc.
  37. #include <netdebug.h> // NetpAssert().
  38. #include <netlib.h> // NetpMemoryAllocate(), NetpMemoryFree().
  39. #include <remtypes.h> // REM_UNSUPPORTED_FIELD.
  40. #include <rxp.h> // My prototype, MAX_TRANSACT_ equates.
  41. #include <rxpdebug.h> // IF_DEBUG().
  42. #include <smbgtpt.h> // SmbGetUshort().
  43. #include <string.h> // strcpy().
  44. #include <tstring.h> // STRLEN(), NetpCopy string functions.
  45. // Size (in bytes) of SMB return parameters (status & converter):
  46. #define RETURN_AREA_SIZE (sizeof(WORD) + sizeof(WORD))
  47. DBGSTATIC DWORD
  48. RxpFieldSize(
  49. IN LPBYTE Field,
  50. IN LPDESC FieldDesc
  51. )
  52. {
  53. NetpAssert(Field != NULL);
  54. NetpAssert(FieldDesc != NULL);
  55. if (*FieldDesc == REM_ASCIZ || *FieldDesc == REM_ASCIZ_TRUNCATABLE) {
  56. // Compute string len (assuming conversion to correct code page).
  57. #if defined(UNICODE) // RxpFieldSize()
  58. return ( NetpUnicodeToDBCSLen((LPTSTR)Field) + 1 );
  59. #else
  60. return (STRLEN( (LPTSTR) Field ) + sizeof(char) );
  61. #endif // defined(UNICODE)
  62. } else {
  63. LPDESC TempDescPtr = FieldDesc;
  64. return ( RapGetFieldSize(
  65. FieldDesc,
  66. & TempDescPtr, // updated
  67. Both ) ); // transmission mode
  68. }
  69. /* NOTREACHED */
  70. } // RxpFieldSize
  71. DBGSTATIC NET_API_STATUS
  72. RxpIsFieldSettable(
  73. IN LPDESC DataDesc,
  74. IN DWORD FieldIndex
  75. )
  76. {
  77. LPDESC FieldDesc;
  78. NET_API_STATUS Status;
  79. // Analyze descriptor to find data type for this FieldIndex.
  80. FieldDesc = RapParmNumDescriptor(
  81. DataDesc,
  82. FieldIndex,
  83. Both, // Transmission mode.
  84. TRUE); // native mode
  85. if (FieldDesc == NULL) {
  86. return (ERROR_NOT_ENOUGH_MEMORY);
  87. }
  88. // Check for errors detected by RapParmNumDescriptor().
  89. if (*FieldDesc == REM_UNSUPPORTED_FIELD) {
  90. IF_DEBUG(SETFIELD) {
  91. NetpKdPrint(( "RxpIsFieldSettable: invalid parameter "
  92. "(ParmNumDesc).\n" ));
  93. }
  94. Status = ERROR_INVALID_PARAMETER;
  95. } else {
  96. Status = NERR_Success;
  97. }
  98. NetpMemoryFree(FieldDesc);
  99. return (Status);
  100. } // RxpIsFieldSettable
  101. NET_API_STATUS
  102. RxpSetField (
  103. IN DWORD ApiNumber,
  104. IN LPTSTR UncServerName,
  105. IN LPDESC ObjectDesc OPTIONAL,
  106. IN LPVOID ObjectToSet OPTIONAL,
  107. IN LPDESC ParmDesc,
  108. IN LPDESC DataDesc16,
  109. IN LPDESC DataDesc32,
  110. IN LPDESC DataDescSmb,
  111. IN LPVOID NativeInfoBuffer,
  112. IN DWORD ParmNumToSend,
  113. IN DWORD FieldIndex,
  114. IN DWORD Level
  115. )
  116. {
  117. LPBYTE CurrentBufferPointer;
  118. DWORD CurrentSize;
  119. DWORD ExtraParmSize;
  120. LPDESC FieldDesc;
  121. DWORD FieldSize16;
  122. LPBYTE SendDataBuffer;
  123. DWORD SendDataBufferSize;
  124. DWORD SendParmBufferSize;
  125. NET_API_STATUS Status;
  126. LPBYTE StringEnd;
  127. LPBYTE TransactSmbBuffer;
  128. DWORD TransactSmbBufferSize;
  129. //
  130. // MOD 06/11/91 RLF
  131. //
  132. DWORD ReturnedDataLength = 0;
  133. //
  134. // MOD 06/11/91 RLF
  135. //
  136. // Double-check caller.
  137. NetpAssert(DataDesc16 != NULL);
  138. NetpAssert(DataDesc32 != NULL);
  139. NetpAssert(DataDescSmb != NULL);
  140. if (RapValueWouldBeTruncated(Level)) {
  141. // Can't use 16-bit protocol if level won't even fit in 16 bits!
  142. return (ERROR_INVALID_LEVEL);
  143. }
  144. NetpAssert(ParmNumToSend != PARMNUM_ALL);
  145. NetpAssert(FieldIndex != PARMNUM_ALL);
  146. if (RapValueWouldBeTruncated(ParmNumToSend)) {
  147. IF_DEBUG(SETFIELD) {
  148. NetpKdPrint(( "RxpSetField: invalid parameter (trunc).\n" ));
  149. }
  150. return (ERROR_INVALID_PARAMETER);
  151. }
  152. //
  153. // Analyze descriptors to make sure this parm num is settable.
  154. //
  155. Status = RxpIsFieldSettable( DataDesc16, FieldIndex );
  156. if (Status != NERR_Success) {
  157. return (Status);
  158. }
  159. Status = RxpIsFieldSettable( DataDesc32, FieldIndex );
  160. if (Status != NERR_Success) {
  161. return (Status);
  162. }
  163. NetpKdPrint(( "RxpSetField: ParmNumToSend=" FORMAT_DWORD ", Level="
  164. FORMAT_DWORD ", FieldIndex=" FORMAT_DWORD ".\n",
  165. ParmNumToSend, Level, FieldIndex ));
  166. //
  167. // Analyze SMB version of descriptor to find data type for this ParmNum.
  168. // Use it to build send data buffer
  169. //
  170. FieldDesc = RapParmNumDescriptor(
  171. DataDescSmb,
  172. FieldIndex,
  173. Both, // Transmission mode.
  174. TRUE); // native version
  175. if (FieldDesc == NULL) {
  176. return (ERROR_NOT_ENOUGH_MEMORY);
  177. }
  178. // Check for errors detected by RapParmNumDescriptor().
  179. if (*FieldDesc == REM_UNSUPPORTED_FIELD) {
  180. NetpMemoryFree( FieldDesc );
  181. IF_DEBUG(SETFIELD) {
  182. NetpKdPrint(( "RxpSetField: invalid parameter (parmNumDesc).\n" ));
  183. }
  184. return (ERROR_INVALID_PARAMETER);
  185. }
  186. // How much memory will we need for send data buffer?
  187. FieldSize16 = RxpFieldSize( NativeInfoBuffer, FieldDesc );
  188. NetpAssert( FieldSize16 >= 1 );
  189. SendDataBufferSize = FieldSize16;
  190. if( SendDataBufferSize > MAX_TRANSACT_SEND_DATA_SIZE )
  191. {
  192. NetpBreakPoint();
  193. return (ERROR_BUFFER_OVERFLOW);
  194. }
  195. // Allocate send data buffer.
  196. SendDataBuffer = NetpMemoryAllocate( SendDataBufferSize );
  197. if (SendDataBuffer == NULL) {
  198. NetpMemoryFree( FieldDesc );
  199. return (ERROR_NOT_ENOUGH_MEMORY);
  200. }
  201. NetpKdPrint(( "RxpSetField: allocated " FORMAT_DWORD " bytes at "
  202. FORMAT_LPVOID ".\n", SendDataBufferSize, SendDataBuffer ));
  203. // Convert this field (and copy it to the send data buffer while we're
  204. // at it).
  205. if ( (*FieldDesc != REM_ASCIZ) && (*FieldDesc != REM_ASCIZ_TRUNCATABLE) ) {
  206. DWORD BytesNeeded = 0;
  207. LPBYTE BogusStringEnd = SendDataBuffer + SendDataBufferSize;
  208. NetpKdPrint(( "RxpSetField: converting...\n" ));
  209. Status = RapConvertSingleEntry (
  210. NativeInfoBuffer, // input data
  211. FieldDesc, // input descriptor
  212. FALSE, // no meaningless input pointers
  213. SendDataBuffer, // output buffer start
  214. SendDataBuffer, // output data
  215. FieldDesc, // output descriptor
  216. TRUE, // set offsets
  217. & BogusStringEnd, // string area end (updated)
  218. & BytesNeeded, // bytes required (updated)
  219. Both, // transmission mode
  220. NativeToRap); // conversion mode
  221. NetpAssert( Status == NERR_Success );
  222. NetpAssert( BytesNeeded == FieldSize16 );
  223. } else {
  224. // Can't use RapConvertSingleEntry for setinfo strings, because
  225. // they're not sent with a pointer (or offset). So, we just copy data.
  226. #if defined(UNICODE) // RxpSetField()
  227. NetpAssert(
  228. SendDataBufferSize >= NetpUnicodeToDBCSLen((LPTSTR)NativeInfoBuffer)+1);
  229. #else
  230. NetpAssert(
  231. SendDataBufferSize >= (STRLEN(NativeInfoBuffer)+sizeof(char)) );
  232. #endif // defined(UNICODE)
  233. NetpKdPrint(( "RxpSetField: copying string...\n" ));
  234. #if defined(UNICODE) // RxpSetField()
  235. NetpCopyWStrToStrDBCS(
  236. (LPSTR) SendDataBuffer, // dest
  237. (LPTSTR)NativeInfoBuffer ); // src
  238. #else
  239. NetpCopyTStrToStr(
  240. (LPSTR) SendDataBuffer, // dest
  241. NativeInfoBuffer); // src
  242. #endif // defined(UNICODE)
  243. }
  244. NetpMemoryFree( FieldDesc );
  245. //
  246. // OK, now let's work on the transact SMB buffer, which we'll use as the
  247. // send parm buffer and return parm buffer.
  248. //
  249. // Figure-out how many bytes of parameters we'll need.
  250. ExtraParmSize =
  251. sizeof(WORD) // level,
  252. + sizeof(WORD); // parmnum.
  253. if (ObjectDesc != NULL) {
  254. NetpAssert( ObjectToSet != NULL );
  255. NetpAssert( DESCLEN(ObjectDesc) == 1 );
  256. if (*ObjectDesc == REM_ASCIZ) {
  257. // Add size of ASCII version of object to set.
  258. ExtraParmSize += STRLEN(ObjectToSet) + sizeof(char);
  259. } else if (*ObjectDesc == REM_WORD_PTR) {
  260. ExtraParmSize += sizeof(WORD);
  261. } else {
  262. NetpAssert(FALSE);
  263. }
  264. } else {
  265. NetpAssert(ObjectToSet == NULL);
  266. }
  267. // Allocate SMB transaction request buffer.
  268. NetpAssert(ExtraParmSize >= 1);
  269. SendParmBufferSize = RxpComputeRequestBufferSize(
  270. ParmDesc,
  271. DataDescSmb,
  272. ExtraParmSize);
  273. NetpAssert( SendParmBufferSize <= MAX_TRANSACT_SEND_PARM_SIZE );
  274. if (SendParmBufferSize > RETURN_AREA_SIZE) {
  275. TransactSmbBufferSize = SendParmBufferSize;
  276. } else {
  277. TransactSmbBufferSize = RETURN_AREA_SIZE;
  278. }
  279. NetpAssert( TransactSmbBufferSize <= MAX_TRANSACT_SEND_PARM_SIZE );
  280. TransactSmbBuffer = NetpMemoryAllocate( TransactSmbBufferSize );
  281. if (TransactSmbBuffer == NULL) {
  282. return (ERROR_NOT_ENOUGH_MEMORY);
  283. }
  284. // Start filling-in parm buffer and set pointers and counters.
  285. Status = RxpStartBuildingTransaction(
  286. TransactSmbBuffer, // SMB buffer (will be built)
  287. SendParmBufferSize,
  288. ApiNumber,
  289. ParmDesc,
  290. DataDescSmb,
  291. (LPVOID *) & CurrentBufferPointer, // first avail byte to use (set)
  292. & CurrentSize, // bytes used so far (set)
  293. (LPVOID *) & StringEnd, // ptr to string area end (set)
  294. NULL); // don't need ptr to parm desc copy
  295. NetpAssert(Status == NERR_Success);
  296. // Fill in parameters.
  297. if (ObjectToSet != NULL) {
  298. if (*ObjectDesc == REM_ASCIZ) {
  299. // Copy string to output area, converting as necessary.
  300. RxpAddTStr(
  301. (LPTSTR) ObjectToSet, // input
  302. & CurrentBufferPointer, // updated
  303. & StringEnd, // updated
  304. & CurrentSize); // updated
  305. } else if (*ObjectDesc == REM_WORD_PTR) {
  306. RxpAddWord(
  307. * (LPWORD) ObjectToSet,
  308. & CurrentBufferPointer, // updated
  309. & CurrentSize); // updated
  310. } else {
  311. NetpAssert(FALSE);
  312. }
  313. }
  314. RxpAddWord(
  315. (WORD) Level,
  316. & CurrentBufferPointer, // updated
  317. & CurrentSize); // updated
  318. RxpAddWord(
  319. (WORD) ParmNumToSend,
  320. & CurrentBufferPointer, // updated
  321. & CurrentSize); // updated
  322. Status = RxpTransactSmb(
  323. UncServerName,
  324. NULL, // Transport name
  325. TransactSmbBuffer,
  326. SendParmBufferSize,
  327. SendDataBuffer,
  328. SendDataBufferSize,
  329. TransactSmbBuffer, // will be set with status and converter word.
  330. RETURN_AREA_SIZE,
  331. NULL, // no return data
  332. //
  333. // MOD 06/11/91 RLF
  334. //
  335. // 0, // 0 bytes of return data
  336. &ReturnedDataLength,
  337. //
  338. // MOD 06/11/91 RLF
  339. //
  340. FALSE); // not a null session API.
  341. // Don't process RxpTransactSmb status just yet...
  342. NetpMemoryFree(SendDataBuffer);
  343. if (Status != NERR_Success) {
  344. NetpMemoryFree(TransactSmbBuffer);
  345. return (Status); // status of transact, e.g. net not started.
  346. }
  347. Status = SmbGetUshort( (LPWORD) TransactSmbBuffer );
  348. NetpMemoryFree(TransactSmbBuffer);
  349. return (Status); // status of actual remote API.
  350. } // RxpSetField